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 + -
显示快捷键?