app1.c

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

C
2,046
字号
/* 
 * 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 "unistd.h"		/* for write, sbrk, fork */
#include "types.h"
#include "pebble.h"
#include "time.h"
#include "synch.h"
#include "signal.h"
#include "log.h"
#include "lock_free.h"
#include "assert.h"


enum	{
	N = 10000,
	N10 = N*10,		/* number of mutex_lock/unlock pairs */
	MEM = (1024*1024),
	M = 20,			/* number of timeout events */
	K = 1000,		/* number of condition variable operations */
	NTHREAD = 7,		/* number of threads for mutex test */
	NP = 4,			/* group size of portals to create/delete */
	NLOG = 10,		/* number of events log entries to create */
	MAGIC_CODE = 0xdeadbeef,/* magic code for event log entries */
	CLONE_MAGIC = 0x12345678,/* magic constant in cloned portals */
	SIG1 = 1,
	SIG2 = 2,
	SIG3 = 10,
	SIG4 = NSIG,
};

typedef	struct	{
	Condition cond;
	Lock lock;
	int count;
	vlong version;
} Cond_Barrier;

typedef struct Elem Elem;
struct	Elem {
	int val;
	Elem *next;
};

typedef	struct Chan Chan;
struct Chan {
	Lock lock;
	Condition cond;
	Elem *head;
	Elem *tail;
};

static int shared_flag;
static int rpc1, rpc2;

static Time when[M], timeout_delay[M];
/* elapsed time of N iterations of an empty loop in machine cycles */
static Time loop_overhead;  
static int timeout_flag[M];
static Barrier b;
static Lock master_lock;
static Lock ring[NTHREAD];
static void *v[N];
static CQ cq;
static void *cq_buf[NTHREAD];

static Cond_Barrier cb;
static Chan chan[NTHREAD];

/* data structures for testing cond_signal_thread */
static Condition c;
static Lock l;
static volatile int nc = 0;
static void *thread_id[NTHREAD];

/* demonstrate modulu bug */
void
test_mod(ulong u)
{
	int k;

	k = u % (NTHREAD-1);
	printf("k=%d (ulong)\n", k);
	k = (long)u % (NTHREAD-1);
	printf("k=%d (long)\n", k);
}

void
test_csd()
{
	Lock lock, old_lock, new_lock;
	int word;

	printf("testing compare & swap\n");

	word = 0;
	if (csw(&word, 0, 1) < 0)
		panic("csw 0 failed");
	if (csw(&word, 1, 0) < 0)
		panic("csw 1 failed");

	lock.v = 0;
	if (csd((vlong *)&lock, 0, 1) < 0)
		panic("csd 0 failed");

	lock.v = 0;
	lock.s.flags = 1;
	old_lock = lock;
	new_lock = lock;
	new_lock.s.lock = 1;
	if (csd((vlong *)&lock, old_lock.v, new_lock.v) < 0)
		panic("csd 1 failed");

	old_lock = lock;
	new_lock = old_lock;
	new_lock.s.lock = 0;
	if (csd((vlong *)&lock, old_lock.v, new_lock.v) < 0)
		panic("csd 2 failed");

	printf("csd() test ended successfully\n\n");
}


/* tests idle_time(), usleep() and sec2ticks() */
/* implicit assumption: the idle loop does one iteration per clock tick */
void
test_idle(void)
{
	Time start, elapsed;
	Time s2ticks = sec2ticks();

	printf("testing idle_time():\n");

	printf("waiting for serial output buffer to flush\n");
	/* note: we wait exactly one second! */
	start = hrtime();
	usleep(SEC2USEC);
	elapsed = hrtime() - start;

	if (elapsed < s2ticks || elapsed > (5*s2ticks)/4)
		panic("usleep(1sec) duration %d ticks; expected %d ticks",
			(int)elapsed, (int)s2ticks);
	else
		printf("usleep(1sec) duration %d ticks; expected %d ticks\n",
			(int)elapsed, (int)s2ticks);

	start = idle_time();
	if (hrsleep(hrtime() + s2ticks) < 0)
		panic("hrsleep() failed:");
	elapsed = idle_time() - start;
	printf("idle ticks=%u %u during hrsleep for %d ticks\n",
		(int)(elapsed >> 32), (int)elapsed, (int)s2ticks);

	if (elapsed < (4*s2ticks)/5 || elapsed > s2ticks)
		printf("idle_time() test failed\n");
	else
		printf("idle_time() test passed successfully\n\n");
}

int
f(unsigned long task, int i)
{
	int x;

	printf("RPC f(%d) thread=%08lx executes in asid %d stack at %p\n",
		i, task, get_asid(), &x);
	return -i;
}

int
g(unsigned long task, int i)
{
	return -i;
}

void
test_mem(int *start, int *end)
{
	volatile int *p;

	for (p = start; p < end; p++)
		*p = (int)p;

	for (p = start; p < end; p++)
		if (*p != (int)p)
			printf("heap contents error at %p\n", p);
}


void
tout(void *val)
{
	assert((int)val >= 0 && (int)val < M);

	timeout_delay[(int)val] = hrtime() - when[(int)val];
	timeout_flag[(int)val] = 1;
}

void *
alloc_page()
{
	int psize, offset;
	void *brk, *page;

	psize = getpagesize();

	/* allocate enough memory to align on next page boundary */
	brk = sbrk(0);
	if (brk == (void *)-1)
		panic("sbrk(0):");
	offset = ((int)brk) & (psize - 1);
	if (offset != 0)
		sbrk(psize - offset);

	/* allocate a page of the heap */
	page = sbrk(psize);
	if (page == (void *)-1)
		panic("sbrk(pagesize()):");
	offset = ((int)page) & (psize - 1);
	if (offset != 0)
		panic("alloc_page() failed to allocate on page boundary");

	return page;
}

void
set_mem(int *start, int len)
{
	int i, *p;

	for (i = 0, p = start; i < len; i += sizeof(int), p++)
		*p = ~((int)p);
}

void
check_mem(int *start, int val, int len)
{
	int i, *p;

	for (i = 0, p = start; i < len; i += sizeof(int), p++) {
		if (*p == ~(val + i))
			continue;
		printf("check_mem failed: addr=%p value=%08x should be=%08x\n",
			p, *p, ~(val+i));
		task_exit(1);
	}
}


void
test_malloc(void)
{
	int sz;
	char *np;

	printf("sbrk(0)=%p getpagesize()=%d\n", sbrk(0), getpagesize());
	printf("before malloc test: TLB miss count=%d general exceptions count=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());
	for (sz = 8; sz <= MEM; sz *= 2) {
		if ((np = (char *)malloc(sz)) == NULL)
			panic("malloc:");
		printf("testing dynamic memory [%p,%p] size=%d\n",
			np, np+sz, sz);
		test_mem((int *)np, (int *)(np+sz));
		printf("virt=%p phys=%p - virt=%p phys=%p\n",
			np, virt2phys(np), np+sz-1, virt2phys(np+sz-1));
		free(np);
	}
	printf("after malloc test: TLB miss count=%d general exceptions count=%d\n",
		get_tlb_excpt_count(), get_gen_excpt_count());

	printf("malloc test ended successfully\n\n");
}


/* test event logging */
void
test_log(void)
{
	int i, j, head, last_head;
	int errors = 0;
	LogEntry entry;
	uchar found[NLOG];

	printf("starting events log test\n");

	/* generate event log entries */
	if ((last_head = get_log_head()) < 0)
		panic("get_log_head:");

	for (i = 0; i < NLOG; i++) {
		put_log(MAGIC_CODE, i);
		head = get_log_head();
		if (head == last_head)
			panic("put_log did not move the log head");
		last_head = head;
	}

	memset(found, 0, sizeof(found));

	/* scan the log from the oldest to the newest entry */
	j = get_log_head();
	for (i = 0; i < get_log_entries(); i++) {
		if (get_log(j, &entry) < 0)
			panic("get_log(%d) failed:", j);

		j = (j + 1) % get_log_entries();

		if (entry.v[LOG_ENTRY_P0] != MAGIC_CODE)
			continue;

		if (entry.v[LOG_ENTRY_P1] < 0 || entry.v[LOG_ENTRY_P1] >= NLOG)
			panic("invalid log entry index=%d",
				entry.v[LOG_ENTRY_P1]);

		found[entry.v[LOG_ENTRY_P1]]++;
	}

	/* check that we found all entries that we placed in the events log */
	for (i = 0; i < NLOG; i++) {
		if (found[i] == 0) {
			printf("event log entry #%d is missing from the log\n",
				i);
			errors++;
		} else if (found[i] > 1) {
			printf("event log entry #%d appears %d times in log\n",
				i, found[i]);
			errors++;
		}
	}

	if (errors)
		panic("events log test failed");
	else
		printf("events log test completed successfully\n\n");
}


/* test portal allocation and deletion */
void
test_portal_alloc(void)
{
	int i, j, id, id1, id_clone, id_clone1, code;
	Time start, elapsed;
	char msg[NAMELEN];

	printf("allocating %d portals and deleting without portal creation\n",
		NP);

	if ((id1 = portal_create(-1, "smtiii", 0, &f, 0)) < 0)
		panic("portal_alloc failed:");

	if ((id = portal_alloc(NP, 0)) < 0)
		panic("portal_alloc(%d, 0) failed:", NP);

	if (portal_clone(-1, id, NP, CLONE_MAGIC, 0) > 0)
		panic("portal_clone of uninitialized portals did not fail");
	get_error(msg);
	printf("expected error message for portal_clone: %s\n", msg);

	if (portal_delete(id1, 1, 0) < 0)
		panic("portal_delete(%d, 1, 0) failed:", id1);
	if (portal_delete(id, NP, 0) < 0)
		panic("portal_delete(%d, %d, 0) failed:", id, NP);

	for (j = 0; j < 2; j++) {
		printf(
		"iteration %d: allocating, creating and deleting %d portals\n",
			j, NP);

		if ((code = portal_create(-1, "smtiii", 0, &f, 0)) != id1)
			panic("portal_create(-1) returned %d; expected %d:", 
				code, id1);

		if ((code = portal_alloc(NP, 0)) != id)
			panic("portal_alloc(%d, 0) returned %d; expected %d:",
				NP, code, id);

		printf("single portal number=%d portals group starts at %d\n",
			id1, id);

		start = hrtime();
		for (i = 0; i < NP; i++) {
			code = portal_create(id+i, "smtcii", i, &g, 0);
			if (code != id+i)
				panic(
				"portal_alloc(%d) returned %d; expected %d\n",
					id+i, code, id+i); 
		}
		elapsed = 2 * (hrtime() - start);
		printf("created %d portals. starts at %d. elapsed=%d cycles\n",
			NP, id, (int)elapsed);

		start = hrtime();
		if ((id_clone = portal_clone(-1, id, NP, CLONE_MAGIC, 0)) < 0)
			panic("portal_clone failed:");
		elapsed = 2 * (hrtime() - start);
		printf("cloned %d portals. starts at %d. elapsed=%d cycles\n",
			NP, id_clone, (int)elapsed);

		if ((id_clone1 = portal_alloc(NP, 0)) < 0)
			panic("portal_alloc(%d, 0) failed:", NP);
		if ((code = portal_clone(id_clone1, id, NP, CLONE_MAGIC, 0))
		    != id_clone1)
			panic("portal_clone returns %d; expected %d:",
				code, id_clone1);

		for (i = 0; i < NP; i++) {
			code = portal_magic(id+i, 0);
			if (code != i)
				panic(
				"portal_magic(%d,0) returns %d; expected %d:",
				id+i, code, i);

			code = portal_magic(id_clone+i, 0);
			if (code != CLONE_MAGIC)
				panic(
				"portal_magic(%d,0) returns %d; expected %d:",
				id_clone+i, code, CLONE_MAGIC);
		}

		/* test regular and cloned portals */
		printf("testing portal calls\n");
		for (i = 0; i < NP; i++) {
			if ((code = call_portal(id+i)) != -i)
				panic("call_portal(%d) returns %d; expected %d",
					code, -i);
			if ((code = call_portal(id_clone+i)) != -CLONE_MAGIC)
				panic("call_portal(%d) returns %d; expected %d",
					code, -CLONE_MAGIC);
		}

		if (portal_delete(id1, 1, 0) < 0)
			panic("portal_delete(%d, 1, 0) failed:", id1);
		if (portal_delete(id, NP, 0) < 0)
			panic("portal_delete(%d, %d, 0) failed:", id, NP);
		if (portal_delete(id_clone, NP, 0) < 0)
			panic("portal_delete(%d, %d, 0) failed:",
				id_clone, NP);
		if (portal_delete(id_clone1, NP, 0) < 0)
			panic("portal_delete(%d, %d, 0) failed:",
				id_clone1, NP);
	}

	printf("portal allocation, cloning & deletion ended successfully\n\n");
}


void
test_portal_window(void)
{
	int i, sz, fd, code, window_peek_id;
	char msg[NAMELEN];
	char *np;
	Time start, elapsed;

	sz = getpagesize();
	if ((np = (char *)alloc_page()) == NULL)
		panic("malloc:");
	if ((fd = fd_open("fs1")) < 0)
		panic("fd_open(fs1):");

	printf("calling fs write(NULL,%d)\n", sz);
	code = call_portal(WRITE2PORT(fd), NULL, sz);
	if (code >= 0)
		panic("fs write did not fail!");
	get_error(msg);
	printf("code=%d error msg=%s\n", code, msg);

	printf("calling fs write(invalid,%d)\n", sz);
	code = call_portal(WRITE2PORT(fd), sbrk(0) + 2 * getpagesize(), sz);
	if (code >= 0)
		panic("fs write did not fail!");
	get_error(msg);
	printf("code=%d error msg=%s\n", code, msg);

	np[0] = 0;
	printf("calling fs write(%p,%d)\n", np, sz);
	call_portal(WRITE2PORT(fd), np, sz);
	printf("return from fs write\n");

	printf("calling fs read(%p,%d)\n", np, sz);
	call_portal(READ2PORT(fd), np, sz);
	printf("buf[0] after fs read %d\n", np[0]);

	printf("testing access to entire window contents in fs\n");
	if ((window_peek_id = portal_open("fs_window_peek", 1)) < 0)
		panic("portal_open of fs_window_peek:");

	set_mem((int *)np, sz);
	for (i = 0; i < sz; i += sizeof(int)) {
		code = call_portal(window_peek_id, np + i);
		if (code == ~((ulong)np + i))
			continue;
		printf("window peek failed for addr=%p value=%d expected=%d\n",
			np + i, code, ~((uint)np + i));
		task_exit(1);
	}
	printf("test of window access and contents ended successfully\n");

⌨️ 快捷键说明

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