app1.c

来自「pebble」· C语言 代码 · 共 2,046 行 · 第 1/4 页

C
2,046
字号
	if ((fd = fd_open("fs2")) < 0)
		panic("fd_open(fs2):");

	printf("before window passing test: TLB miss count=%d general exceptions count=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());
	printf("calling fs write2\n");
	start = hrtime();
	for (i = 0; i < N; i++)
		call_portal(WRITE2PORT(fd), np, sz);
	elapsed = 2*(hrtime() - start) - loop_overhead;
	printf(
	"elapsed cycles of %d portal crossing with window open/close w/out TLB update: %d\n",
		i, (int)elapsed);
	printf("each portal crossing: %d cycles\n",
		(int)(elapsed+N/2)/N);
	printf("after window passing test: TLB miss count=%d general exceptions count=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());

	printf("calling fs read2\n");
	np[0] = 0;
	start = hrtime();
	for (i = 0; i < N; i++)
		call_portal(READ2PORT(fd), np, sz);
	elapsed = 2*(hrtime() - start) - loop_overhead;
	printf(
	"elapsed cycles of %d portal crossing with window open/close and TLB update: %d\n",
		i, (int)elapsed);
	printf("each portal crossing: %d cycles\n",
		(int)(elapsed+N/2)/N);
	printf(
"after window access test: TLB miss count=%d general exceptions count=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());
	printf("portal window test ended successfully\n\n");
}


void
test_page_transfer(void)
{
	int i, code, sz, npages, *p1, *p2, *p3, *pp;
	void *q;
	int give_id, peek_id, take_id, swap_id;
	int share_id, set_id, unmap_id, count_id;
	char msg[NAMELEN];
	Time start, elapsed;

	/* check window give/take/swap */
	printf("testing window give/take/swap\n");
	p1 = alloc_page();
	p2 = alloc_page();
	p3 = alloc_page();
	sz = getpagesize();
	printf("p1=%p p2=%p p3=%p pagesize=%d\n", p1, p2, p3, sz);
	set_mem(p1, sz);
	set_mem(p2, sz);
	set_mem(p3, sz);
	clean_cache(p1, sz);
	clean_cache(p2, sz);
	clean_cache(p3, sz);
	check_mem(p1, (int)p1, sz);
	check_mem(p2, (int)p2, sz);
	check_mem(p3, (int)p3, sz);

	if ((give_id = portal_open("fs_give", 1)) < 0)
		panic("portal_open(fs_give):");
	if ((peek_id = portal_open("fs_peek", 1)) < 0)
		panic("portal_open(fs_peek):");
	if ((take_id = portal_open("fs_take", 1)) < 0)
		panic("portal_open(fs_take):");
	if ((swap_id = portal_open("fs_swap", 1)) < 0)
		panic("portal_open(fs_swap):");
	if ((share_id = portal_open("fs_share", 1)) < 0)
		panic("portal_open(fs_share):");
	if ((set_id = portal_open("fs_set", 1)) < 0)
		panic("portal_open(fs_set):");
	if ((unmap_id = portal_open("fs_unmap", 1)) < 0)
		panic("portal_open(fs_unmap):");
	if ((count_id = portal_open("fs_count", 1)) < 0)
		panic("portal_open(fs_count):");

	/* testing fs_give */
	if (call_portal(give_id, NULL, 0) >= 0)
		panic("fs_give(NULL) expected to fail but did not");
	get_error(msg);
	printf("expected error message from fs_give(NULL): %s\n", msg);

	if (call_portal(give_id, &shared_flag, 0) >= 0)
		panic("fs_give(<data address>) expected to fail but did not");
	get_error(msg);
	printf("expected error message from fs_give(<data address>): %s\n",
		msg);

	if (vm_count_page(&shared_flag) >= 0)
		 panic("vm_count_page(<data addr>) did not fail\n");
	get_error(msg);
	printf("expected error message from vm_count_page(<data addr>): %s\n",
		msg);

	if ((code = vm_count_page(p1)) < 0)
		panic("vm_count_page(p1) failed:");
	if (code != 1) {
		printf("fs_count(%p) returned %d; expected 1\n", p1, code);
		task_exit(1);
	}

	if (call_portal(give_id, p1, 0) < 0)
		panic("fs_give:");

	/* this doamin can not access page p1 any longer */
	if (vm_count_page(p1) >= 0)
		panic("vm_count_page(%p) expected to fail but did not\n", p1);
	get_error(msg);
	printf("expected error msg from vm_count_page(p1) after fs_give: %s\n",
		msg);

	/* fs domain can access page p1 */
	if ((code = call_portal(count_id, p1)) < 0)
		panic("fs_count(p1) failed:");
	if (code != 1) {
		printf("fs_count(%p) returned %d; expected 1\n", p1, code);
		task_exit(1);
	}

	if (call_portal(give_id, p1, 0) >= 0)
		panic("2nd fs_give expected to fail but did not");
	get_error(msg);
	printf("expected error message from 2nd give: %s\n", msg);

	/* verify that page is available now in the fs domain */
	printf("checking page contents after transfer to fs domain\n");
	for (i = 0; i < sz; i += sizeof(int)) {
		code = call_portal(peek_id, (int)p1 + i);
		if (code != ~((int)p1+i)) {
			printf("fs_peek failed: addr=%p value=%d expected=%d\n",
				(int *)((int)p1 + i), code, ~((int)p1 + i));
			task_exit(1);
		}
	}
	printf("page contents is correct when accessed from fs domain\n");

	/* get the page back */
	pp = (int *)call_portal(take_id, 0);
	if (pp == (int *)-1)
		panic("fs_take:");
	if (pp != p1) {
		printf("fs_take returned %p; expected %p\n", pp, p1);
		task_exit(1);
	}

	/* verify that fs domain can not access the page any longer */
	if ((code = call_portal(count_id, p1)) >= 0)
		panic("fs_count(%p) expected to fail but did not\n", p1);
	get_error(msg);
	printf("expected error msg from fs_count(p1) after fs_take: %s\n",
		msg);

	/* verify that calling domain can access the page */
	if ((code = vm_count_page(pp)) < 0)
		panic("vm_count_page(pp) failed:");
	if (code != 1) {
		printf("fs_count(%p) returned %d; expected 1\n", pp, code);
		task_exit(1);
	}
	printf("vm_count_page(p1) after fs_take: %d\n", code);

	printf("checking returned page contents\n");
	check_mem(pp, (int)p1, sz);

	pp = (int *)call_portal(take_id, 0);
	if (pp != (int *)-1) {
		printf("2nd fs_take did not fail as expected");
		task_exit(1);
	}
	get_error(msg);
	printf("expected error message from 2nd fs_take: %s\n", msg);

	/* give page p1; then swap it with page p2 */
	printf("checking page swap\n");
	if (call_portal(give_id, p1, 0) < 0)
		panic("fs_give:");

	if (call_portal(swap_id, NULL, 0) >= 0) {
		printf("fs_swap(NULL) did not fail as expected\n");
		task_exit(1);
	}
	get_error(msg);
	printf("expected error message from fs_swap(NULL): %s\n", msg);

	if (call_portal(swap_id, &shared_flag, 0) >= 0) {
		printf("fs_swap(<data area>) did not fail as expected\n");
		task_exit(1);
	}
	get_error(msg);
	printf("expected error message from fs_swap(<data area>): %s\n", msg);

	if (call_portal(swap_id, p1, 0) >= 0) {
		printf("fs_swap(p1) did not fail as expected\n");
		task_exit(1);
	}
	get_error(msg);
	printf("expected error message from fs_swap(p1): %s\n", msg);

	if (call_portal(swap_id, p2, 0) < 0)
		panic("fs_swap(p2):");

	pp = (int *)call_portal(take_id, 0);
	if (pp == (int *)-1)
		panic("fs_take:");
	if (pp != p1) {
		printf("fs_take returned %p; expected %p\n", pp, p1);
		task_exit(1);
	}

	printf("checking contents of swapped pages\n");
	check_mem(p1, (int)p2, sz);
	check_mem(p2, (int)p1, sz);

	/* test page share */
	if (call_portal(share_id, p3) < 0)
		panic("fs_share(p3):");

	/* verify that page is available now in the fs domain */
	printf("checking page contents after sharing with fs domain\n");
	for (i = 0; i < sz; i += sizeof(int)) {
		code = call_portal(peek_id, (int)p3 + i);
		if (code != ~((int)p3+i)) {
			printf("fs_peek failed: addr=%p value=%d expected=%d\n",
				(int *)((int)p3 + i), code, ~((int)p3 + i));
			task_exit(1);
		}
	}
	printf("correct shared page contents when accessed from fs domain\n");

	if (call_portal(set_id, p3, ~0) < 0)
		panic("fs_set(p3, 0):");

	if (*p3 != ~0) {
		printf("fs_set failed: addr=%p value=%d expected=%d\n",
			p3, *p3, ~0);
		task_exit(1);
	}
	printf("fs_set succeeded\n");

	if (call_portal(unmap_id, p3) < 0)
		panic("fs_unmap(p3):");

	if (call_portal(unmap_id, p3) >= 0) {
		printf("2nd fs_unmap(%p) did not fail as expected\n", p3);
		task_exit(1);
	}
	get_error(msg);
	printf("expected error message from 2nd fs_unmap(p3): %s\n", msg);

	if (vm_unmap_page(p3) >= 0) {
		printf("vm_unmap_page(%p) did not fail as expected\n", p3);
		task_exit(1);
	}
	get_error(msg);
	printf("expected error message from vm_unmap_page(p3): %s\n", msg);

	/* test vm_unmap_page() when page is shared twice with fs domain */
	if (call_portal(share_id, p3) < 0)
		panic("1st fs_share(p3):");
	
	if (call_portal(share_id, p3) < 0)
		panic("2nd fs_share(p3):");
	
	if ((code = vm_count_page(p3)) < 0)
		panic("vm_count_page(p3) failed:");
	if (code != 1) {
		printf("vm_count_page(%p) returns %d; expected 1\n", p3, code);
		task_exit(1);
	}

	if ((code = call_portal(count_id, p3)) < 0)
		panic("fs_count(p3) failed:");
	if (code != 2) {
		printf("fs_count(%p) returns %d; expected 2\n", p3, code);
		task_exit(1);
	}
	printf("fs_count(p3) after two sharing with fs is %d\n", code);

	if (vm_unmap_page(p3) < 0)
		panic("vm_unmap_page(p3):");
	printf("vm_unmap_page(p3) successful\n");

	if (vm_count_page(p3) >= 0) {
		printf("vm_count_page(%p) did not fail as expected\n", p3);
		task_exit(1);
	}

	/* can unmap only once, since page is shared twice with fs domain */
	if (call_portal(unmap_id, p3) < 0)
		panic("1st fs_unmap(p3):");

	if ((code = call_portal(count_id, p3)) < 0)
		panic("fs_count(p3) failed:");
	if (code != 1) {
		printf("fs_count(%p) returns %d; expected 1\n", p3, code);
		task_exit(1);
	}

	if (call_portal(unmap_id, p3) >= 0) {
		printf("2nd fs_unmap(%p) did not fail as expected\n", p3);
		task_exit(1);
	}
	get_error(msg);
	printf("expected error message from 2nd fs_unmap(p3): %s\n", msg);

	printf("page count/give/take/swap/share/set/unmap is successful\n\n");

	npages = MEM/sz;
	for (i = 0; i < npages; i++) {
		if ((v[i] = (void *)malloc(sz)) == NULL)
			panic("malloc:");
		/* to force loading TLB entry */
		memset((char *)v[i], 0, sz);
	}

	/* time page give with prior access */
	start = hrtime();
	for (i = 0; i < npages; i++)
		if (call_portal(give_id, v[i], i) < 0)
			panic("fs_give:");

	elapsed = 2*(hrtime() - start) - (loop_overhead * npages) / N;
	printf("elapsed cycles of %d page give (with TLB erase) is %d\n",
		i, (int)elapsed);
	printf("each page give (with TLB erase): %d cycles\n",
		(int)(elapsed+npages/2)/npages);

	/* force loading TLB entry in fs domain */
	for (i = 0; i < npages; i++)
		call_portal(peek_id, v[i]);

	start = hrtime();
	for (i = 0; i < npages; i++)
		if (call_portal(swap_id, p1, i) < 0)
			panic("fs_swap:");

	elapsed = 2*(hrtime() - start) - (npages * loop_overhead) / N;
	printf("elapsed cycles of %d page swaps (with TLB erase) is %d\n",
		i, (int)elapsed);
	printf("each page swap (with TLB erase): %d cycles\n",
		(int)(elapsed+npages/2)/npages);

	/* force loading TLB entry in fs domain */
	for (i = 0; i < npages; i++)
		call_portal(peek_id, v[i]);

	/* time page take with prior access */
	start = hrtime();
	for (i = 0; i < npages; i++) {
		q = (void *)call_portal(take_id, i);
		if (v[i] != q) {
			printf("fs take failed. returned %p expected %p\n",
				q, v[i]);
			task_exit(1);
		}
	}

	elapsed = 2*(hrtime() - start) - (npages * loop_overhead) / N;
	printf("elapsed cycles of %d page take (with TLB erase) is %d\n",
		i, (int)elapsed);
	printf("each page take (with TLB erase): %d cycles\n",
		(int)(elapsed+npages/2)/npages);

	/* time page give w/out prior access */
	start = hrtime();
	for (i = 0; i < npages; i++)
		if (call_portal(give_id, v[i], i) < 0)
			panic("fs_give:");

	elapsed = 2*(hrtime() - start) - (npages * loop_overhead) / N;
	printf("elapsed cycles of %d page give (w/out TLB erase) is %d\n",
		i, (int)elapsed);
	printf("each page give (w/out TLB erase): %d cycles\n",
		(int)(elapsed+npages/2)/npages);

	/* time page take w/out prior access */
	start = hrtime();
	for (i = 0; i < npages; i++) {
		q = (void *)call_portal(take_id, i);
		if (v[i] != q) {
			printf("fs take failed. returned %p expected %p\n",
				q, v[i]);
			task_exit(1);
		}
	}

	elapsed = 2*(hrtime() - start) - (npages * loop_overhead) / N;
	printf("elapsed cycles of %d page take (w/out TLB erase) is %d\n",
		i, (int)elapsed);
	printf("each page take (w/out TLB erase): %d cycles\n",
		(int)(elapsed+npages/2)/npages);

	printf("\n");
}

void
cond_barrier_init(Cond_Barrier *cb)
{
	cond_init(&cb->cond);
	cb->count = cb->version = 0;
	mutex_init(&cb->lock, MUTEX_ERRORCHECK);
}

void
cond_barrier(Cond_Barrier *cb, int i, int n)
{
	vlong old_version;

	mutex_lock_safe(&cb->lock, "lock barrier");
	cb->count++;
	if (cb->count < n) {
		old_version = cb->version;
		do {
			if (cond_wait(&cb->cond, &cb->lock) < 0)
				panic("cond_barrier: cond_wait failed:");
		} while (cb->version == old_version);
	} else	{
		cb->count = 0;
		cb->version++;
		if (cond_broadcast(&cb->cond) < 0)
			panic("cond_barrier: cond_broadcast failed:");
	}
	mutex_unlock_safe(&cb->lock, "unlock barrier");
}


void
chan_init(Chan *c)
{
	mutex_init(&c->lock, MUTEX_ERRORCHECK);
	cond_init(&c->cond);
	c->head = c->tail = NULL;
}


/* put a value in a channel which can obtained later by */
/* cond_get() or cond_tget() */
void
cond_put(Chan *c, int val)
{
	Elem *e;

	if ((e = (Elem *)malloc(sizeof(Elem))) == NULL)
		panic("cond_put: malloc failed:");

	e->val = val;
	e->next = NULL;
	mutex_lock_safe(&c->lock, "cond_put: lock channel");
	if (c->tail != NULL)
		c->tail->next = e;
	else
		c->head = e;
	c->tail = e;

	if (cond_signal(&c->cond) < 0)
		panic("cond_put: cond_signal failed:");
	mutex_unlock_safe(&c->lock, "cond_put: unlock channel");
}


/* get a value from a channel without timeout (blocking) */
int
cond_get(Chan *c)
{
	Elem *e;
	int val;

	mutex_lock_safe(&c->lock, "cond_get: lock channel");
	while ((e = c->head) == NULL) {
		if (cond_wait(&c->cond, &c->lock) < 0)
			panic("cond_get: cond_wait %p failed:", &c->cond);
	}
	c->head = e->next;
	if (e->next == NULL)
		c->tail = NULL;
	mutex_unlock_safe(&c->lock, "cond_get: unlock channel");

	val = e->val;
	free(e);

	return val;
}


/* get a value from a channel with timeout */
int
cond_tget(Chan *c, Time t)
{
	Elem *e = NULL;
	int val;

	mutex_lock_safe(&c->lock, "cond_tget: lock channel");
	if ((e = c->head) == NULL) {
		if (cond_twait(&c->cond, &c->lock, t) >= 0)
			e = c->head;
	}
	if (e != NULL) {
		c->head = e->next;
		if (e->next == NULL)
			c->tail = NULL;
	}
	mutex_unlock_safe(&c->lock, "cond_tget: unlock channel");

	if (e != NULL) {
		val = e->val;
		free(e);
		return val;
	} else

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?