lat_rpc.c
来自「pebble」· C语言 代码 · 共 537 行
C
537 行
/*
* Copyright 1999, 2000, 2001, 2002 Lucent Technologies Inc.
* All Rights Reserved.
* Information Sciences Research Center, Bell Labs.
*
* LUCENT TECHNOLOGIES DOES NOT CLAIM MERCHANTABILITY OF THIS SOFTWARE
* OR THE SUITABILITY OF THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The
* software is provided "as is" without expressed or implied warranty
* of any kind.
*
* These notices must be retained in any copies of any part of this
* software.
*
*/
#include "pebble.h"
#include "unistd.h"
#include "types.h"
#include "time.h"
#include "synch.h"
#include "perfcount.h"
#define N 10000
#define NP 10
#define NDOMAIN 8
static Barrier *bp;
static int my_asid;
static int worker_asid[NDOMAIN];
Time overhead_cycles, overhead_usec;
static int same_smaiii_id; /* portal to same domain with template "smaiii" */
static int same_smaiwi_id; /* portal to same domain with template "smaiwi" */
static int same_qmaiii_id; /* portal to same domain with template "qmaiii" */
static int same_qmaiwi_id; /* portal to same domain with template "qmaiwi" */
static int same_spaiii_id; /* portal to same domain with template "spaiii" */
static int same_spaiwi_id; /* portal to same domain with template "spaiwi" */
static int same_qpaiii_id; /* portal to same domain with template "qpaiii" */
static int same_qpaiwi_id; /* portal to same domain with template "qpaiwi" */
static int next_smaiii_id; /* portal to next domain with template "smaiii" */
static int next_smaiwi_id; /* portal to next domain with template "smaiwi" */
static int next_qmaiii_id; /* portal to next domain with template "qmaiii" */
static int next_qmaiwi_id; /* portal to next domain with template "qmaiwi" */
static int next_spaiii_id; /* portal to next domain with template "spaiii" */
static int next_spaiwi_id; /* portal to next domain with template "spaiwi" */
static int next_qpaiii_id; /* portal to next domain with template "qpaiii" */
static int next_qpaiwi_id; /* portal to next domain with template "qpaiwi" */
int
f(int asid)
{
return (int)hrtime();
}
int
f_smaiii(int asid, int p1, int p2, int p3)
{
if (p1 <= 0)
return my_asid;
else
return call_portal(next_smaiii_id, p1 - 1, p2, p3);
}
int
f_spaiii(int asid, int p1, int p2, int p3)
{
if (p1 <= 0)
return my_asid;
else
return call_portal(next_spaiii_id, p1 - 1, p2, p3);
}
int
f_qmaiii(int asid, int p1, int p2, int p3)
{
if (p1 <= 0)
return my_asid;
else
return call_portal(next_qmaiii_id, p1 - 1, p2, p3);
}
int
f_qpaiii(int asid, int p1, int p2, int p3)
{
if (p1 <= 0)
return my_asid;
else
return call_portal(next_qpaiii_id, p1 - 1, p2, p3);
}
int
f_smaiwi(int asid, int p1, int *buf, int p3)
{
if (p3)
buf[0]++;
if (p1 <= 0)
return my_asid;
else
return call_portal(next_smaiwi_id, p1-1, buf, p3);
}
int
f_spaiwi(int asid, int p1, int *buf, int p3)
{
if (p3)
buf[0]++;
if (p1 <= 0)
return my_asid;
else
return call_portal(next_spaiwi_id, p1-1, buf, p3);
}
int
f_qmaiwi(int asid, int p1, int *buf, int p3)
{
if (p3)
buf[0]++;
if (p1 <= 0)
return my_asid;
else
return call_portal(next_qmaiwi_id, p1-1, buf, p3);
}
int
f_qpaiwi(int asid, int p1, int *buf, int p3)
{
if (p3)
buf[0]++;
if (p1 <= 0)
return my_asid;
else
return call_portal(next_qpaiwi_id, p1-1, buf, p3);
}
void
init_portals(int i)
{
char name[NAMELEN];
sprintf(name, "smaiii%d", i);
if ((same_smaiii_id = portal_create(-1, "smaiii", 0, f_smaiii, 0)) < 0)
panic("portal_create:");
if (portal_name(same_smaiii_id, name, 1) < 0)
panic("portal_name:");
printf("worker %d created portal %s id=%d\n", i, name, same_smaiii_id);
sprintf(name, "smaiwi%d", i);
if ((same_smaiwi_id = portal_create(-1, "smaiwi", 0, f_smaiwi, 0)) < 0)
panic("portal_create:");
if (portal_name(same_smaiwi_id, name, 1) < 0)
panic("portal_name:");
printf("worker %d created portal %s id=%d\n", i, name, same_smaiwi_id);
sprintf(name, "spaiii%d", i);
if ((same_spaiii_id = portal_create(-1, "spaiii", 0, f_spaiii, 0)) < 0)
panic("portal_create:");
if (portal_name(same_spaiii_id, name, 1) < 0)
panic("portal_name:");
printf("worker %d created portal %s id=%d\n", i, name, same_spaiii_id);
sprintf(name, "spaiwi%d", i);
if ((same_spaiwi_id = portal_create(-1, "spaiwi", 0, f_spaiwi, 0)) < 0)
panic("portal_create:");
if (portal_name(same_spaiwi_id, name, 1) < 0)
panic("portal_name:");
printf("worker %d created portal %s id=%d\n", i, name, same_spaiwi_id);
sprintf(name, "qmaiii%d", i);
if ((same_qmaiii_id = portal_create(-1, "qmaiii", 0, f_qmaiii, 0)) < 0)
panic("portal_create:");
if (portal_name(same_qmaiii_id, name, 1) < 0)
panic("portal_name:");
printf("worker %d created portal %s id=%d\n", i, name, same_qmaiii_id);
sprintf(name, "qmaiwi%d", i);
if ((same_qmaiwi_id = portal_create(-1, "qmaiwi", 0, f_qmaiwi, 0)) < 0)
panic("portal_create:");
if (portal_name(same_qmaiwi_id, name, 1) < 0)
panic("portal_name:");
printf("worker %d created portal %s id=%d\n", i, name, same_qmaiwi_id);
sprintf(name, "qpaiii%d", i);
if ((same_qpaiii_id = portal_create(-1, "qpaiii", 0, f_qpaiii, 0)) < 0)
panic("portal_create:");
if (portal_name(same_qpaiii_id, name, 1) < 0)
panic("portal_name:");
printf("worker %d created portal %s id=%d\n", i, name, same_qpaiii_id);
sprintf(name, "qpaiwi%d", i);
if ((same_qpaiwi_id = portal_create(-1, "qpaiwi", 0, f_qpaiwi, 0)) < 0)
panic("portal_create:");
if (portal_name(same_qpaiwi_id, name, 1) < 0)
panic("portal_name:");
printf("worker %d created portal %s id=%d\n", i, name, same_qpaiwi_id);
}
void
open_portals(int i, int n)
{
char name[NAMELEN];
if (i >= n-1)
return;
sprintf(name, "smaiii%d", i+1);
if ((next_smaiii_id = portal_open(name, 1)) < 0)
panic("portal_open:");
sprintf(name, "smaiwi%d", i+1);
if ((next_smaiwi_id = portal_open(name, 1)) < 0)
panic("portal_open:");
printf("worker %d: next_smaiii_id=%d next_smaiwi_id=%d\n",
i, next_smaiii_id, next_smaiwi_id);
sprintf(name, "spaiii%d", i+1);
if ((next_spaiii_id = portal_open(name, 1)) < 0)
panic("portal_open:");
sprintf(name, "spaiwi%d", i+1);
if ((next_spaiwi_id = portal_open(name, 1)) < 0)
panic("portal_open:");
printf("worker %d: next_spaiii_id=%d next_spaiwi_id=%d\n",
i, next_spaiii_id, next_spaiwi_id);
sprintf(name, "qmaiii%d", i+1);
if ((next_qmaiii_id = portal_open(name, 1)) < 0)
panic("portal_open:");
sprintf(name, "qmaiwi%d", i+1);
if ((next_qmaiwi_id = portal_open(name, 1)) < 0)
panic("portal_open:");
printf("worker %d: next_qmaiii_id=%d next_qmaiwi_id=%d\n",
i, next_qmaiii_id, next_qmaiwi_id);
sprintf(name, "qpaiii%d", i+1);
if ((next_qpaiii_id = portal_open(name, 1)) < 0)
panic("portal_open:");
sprintf(name, "qpaiwi%d", i+1);
if ((next_qpaiwi_id = portal_open(name, 1)) < 0)
panic("portal_open:");
printf("worker %d: next_qpaiii_id=%d next_qpaiwi_id=%d\n",
i, next_qpaiii_id, next_qpaiwi_id);
}
void
worker(int i, int n)
{
my_asid = get_asid();
printf("worker %d of %d initializing. asid=%d\n", i, n, my_asid);
init_portals(i);
if (barrier_wait(bp, i, n) < 0)
panic("barrier_wait:");
open_portals(i, n);
if (barrier_wait(bp, i, n) < 0)
panic("barrier_wait:");
/* workers wait here to allow parent to terminate first */
if (barrier_wait(bp, i, n) < 0)
panic("barrier_wait:");
}
void
measure_creation(const char *template, int (*f)())
{
int i;
int id[NP];
Time start, elapsed;
printf("==========\n");
printf("measure portal creation time with template: %s\n", template);
/* create and delete portals to reduce memory management time */
for (i = 0; i < NP; i++) {
if ((id[i] = portal_create(-1, template, 0, f, 0)) < 0)
panic("portal_create failed:");
}
for (i = 0; i < NP; i++) {
if (portal_delete(id[i], 1, 0) < 0)
panic("portal delete failed:");
}
start = hrtime();
for (i = 0; i < NP; i++) {
if ((id[i] = portal_create(-1, template, 0, f, 0)) < 0)
panic("portal_create failed:");
}
elapsed = 2*(hrtime() - start);
printf("%d cycles per portal\n", (int)(elapsed/NP));
for (i = 0; i < NP; i++) {
if (portal_delete(id[i], 1, 0) < 0)
panic("portal delete failed:");
}
}
void
measure(int same_id, int next_id, int *buf, int p3, char *name)
{
int i, j, id, p1, code, perf_ix;
Time start, start_usec, elapsed, elapsed_usec;
uint perf_count;
for (j = 0; j < NDOMAIN; j++) {
if (j == 0) {
id = same_id;
p1 = 0;
} else {
id = next_id;
p1 = j - 1;
}
/* measure portal traversal through j domains */
if (buf != NULL)
buf[0] = 0;
if ((code = call_portal(id, p1, buf, p3)) != worker_asid[j]) {
printf("calling %s failed for %d domains. returned %d. should be %d\n",
name, j, code, worker_asid[j]);
task_exit(1);
}
if (buf != NULL && p3 != 0 && buf[0] != (p1+1)) {
printf("calling %s failed for %d domains\n",
name, j);
printf("v[0]=%d; should be %d\n", buf[0], p1+1);
task_exit(1);
}
for (perf_ix = 0; perf_vec[perf_ix].name != NULL; perf_ix++) {
printf("============\n");
set_perf_ctrl(perf_vec[perf_ix].ctrl);
start = hrtime();
start_usec = uptime();
for (i = 0; i < N; i++)
call_portal(id, p1, buf, p3);
perf_count = get_perf_count();
elapsed = 2*(hrtime() - start) - overhead_cycles;
elapsed_usec = uptime() - start_usec - overhead_usec;
printf("%d domain portals with template %s through %d domains\n",
N, name, j);
printf("elapsed time %d cycles; each portal traversal path %d cycles\n",
(int)elapsed, (int)((elapsed + N/2)/N));
printf("elapsed time %d usec.; each portal traversal path %d usec.\n",
(int)elapsed_usec, (int)((elapsed_usec + N/2)/N));
printf("%s: %d\n", perf_vec[perf_ix].name, perf_count);
}
}
}
int
main(void)
{
int i, id_s, id_q;
uvlong start, elapsed;
uvlong start_usec, elapsed_usec;
uvlong hrtime_cycles, hrtime_usec;
int *v;
printf("lat_rpc benchmark starting\n");
bp = (Barrier *)shm_create(sizeof(Barrier));
if (bp == (Barrier *)-1)
panic("shm_create");
if (barrier_init(bp) < 0)
panic("barrier_init:");
for (i = 1; i < NDOMAIN; i++) {
if ((worker_asid[i] = domain_fork(NULL)) < 0)
panic("domain_fork:");
if (worker_asid[i] == 0) {
/* we are in the child domain */
worker(i, NDOMAIN);
task_exit(0);
}
}
worker_asid[0] = my_asid = get_asid();
printf("parent initializing. asid=%d\n", my_asid);
init_portals(0);
if ((v = (int *)malloc(getpagesize())) == NULL)
panic("malloc:");
if (barrier_wait(bp, 0, NDOMAIN) < 0)
panic("barrier_wait:");
open_portals(0, NDOMAIN);
if (barrier_wait(bp, 0, NDOMAIN) < 0)
panic("barrier_wait:");
if ((id_s = portal_create(-1, "smaiii", 0, f, 0)) < 0)
panic("portal_create:");
if ((id_q = portal_create(-1, "qpaiii", 0, f, 0)) < 0)
panic("portal_create:");
/* measure loop overhead */
start = hrtime();
start_usec = uptime();
for (i = 0; i < N; i++)
;
overhead_cycles = 2*(hrtime() - start);
overhead_usec = uptime() - start_usec;
printf("============\n");
printf("overhead of %d iterations\n", N);
printf("elapsed time %d cycles; each iteration %d cycles\n",
(int)overhead_cycles, (int)((overhead_cycles + N/2)/N));
printf("elapsed time %d usec.; each iteration %d usec.\n",
(int)overhead_usec, (int)((overhead_usec + N/2)/N));
/* measure hrtime overhead */
start = hrtime();
start_usec = uptime();
for (i = 0; i < N; i++)
hrtime();
hrtime_cycles = 2*(hrtime() - start);
hrtime_usec = uptime() - start_usec;
printf("============\n");
printf("overhead of %d hrtime\n", N);
printf("elapsed time %d cycles; each iteration %d cycles\n",
(int)hrtime_cycles, (int)((hrtime_cycles + N/2)/N));
printf("elapsed time %d usec.; each iteration %d usec.\n",
(int)hrtime_usec, (int)((hrtime_usec + N/2)/N));
/* measure short circuit portal time */
start = hrtime();
start_usec = uptime();
for (i = 0; i < N; i++)
get_asid();
elapsed = 2*(hrtime() - start) - overhead_cycles;
elapsed_usec = uptime() - start_usec - overhead_usec;
printf("============\n");
printf("%d short circuit portals\n", N);
printf("elapsed time %d cycles; each portal traversal %d cycles\n",
(int)elapsed, (int)((elapsed + N/2)/N));
printf("elapsed time %d usec.; each portal traversal %d usec.\n",
(int)elapsed_usec, (int)((elapsed_usec + N/2)/N));
/* measure one-way IPC time */
/* ignore timer overflow since call_portal() returns an integer */
elapsed = 0;
for (i = 0; i < N; i++) {
start = hrtime();
elapsed += (uint)call_portal(id_s) - (uint)start;
}
elapsed = 2 * elapsed - hrtime_cycles;
printf("============\n");
printf("%d one-way IPC with shared stack & minimal save\n", N);
printf("elapsed time %d cycles; each one-way shared-stack IPC %d cycles\n",
(int)elapsed, (int)((elapsed + N/2)/N));
elapsed = 0;
for (i = 0; i < N; i++) {
start = hrtime();
elapsed += (uint)call_portal(id_q) - (uint)start;
}
elapsed = 2 * elapsed - hrtime_cycles;
printf("============\n");
printf("%d one-way IPC with stacks queue & partial save\n", N);
printf("elapsed time %d cycles; each one-way stack_queued IPC %d cycles\n",
(int)elapsed, (int)((elapsed + N/2)/N));
/* measure portal creation; create larger portals first to improve */
/* memory reclamation in portal mananger */
measure_creation("smciii", f_smaiii);
measure_creation("qpciwi", f_qpaiwi);
measure_creation("qpciii", f_qpaiii);
measure_creation("smciwi", f_smaiwi);
measure(same_smaiii_id, next_smaiii_id, NULL, 0, "smaiii");
measure(same_smaiwi_id, next_smaiwi_id, v, 0,
"smaiwi (do not touch window)");
measure(same_smaiwi_id, next_smaiwi_id, v, 1,
"smaiwi (touch window in each domain)");
measure(same_spaiii_id, next_spaiii_id, NULL, 0, "spaiii");
measure(same_spaiwi_id, next_spaiwi_id, v, 0,
"spaiwi (do not touch window)");
measure(same_spaiwi_id, next_spaiwi_id, v, 1,
"spaiwi (touch window in each domain)");
#if 0
measure(same_qmaiii_id, next_qmaiii_id, NULL, 0, "qmaiii");
measure(same_qmaiwi_id, next_qmaiwi_id, v, 0,
"qmaiwi (do not touch window)");
measure(same_qmaiwi_id, next_qmaiwi_id, v, 1,
"qmaiwi (touch window in each domain)");
#endif
measure(same_qpaiii_id, next_qpaiii_id, NULL, 0, "qpaiii");
measure(same_qpaiwi_id, next_qpaiwi_id, v, 0,
"qpaiwi (do not touch window)");
measure(same_qpaiwi_id, next_qpaiwi_id, v, 1,
"qpaiwi (touch window in each domain)");
printf("LAT_RPC ENDED\n");
task_exit(0);
return(1);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?