app1.c

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

C
2,046
字号
		return -1;
}
		
	
void
mutex_worker(int i)
{
	int j, k, val;
	int last_val = -1;
	void *t;
	static int put_count = 0;

	mutex_init(&ring[i], MUTEX_ERRORCHECK);
	barrier_wait(&b, i, NTHREAD);

	for (j = 0; j < N; j++) {
		mutex_lock_safe(&ring[i], "ring-left");
		if (NTHREAD > 1)
			mutex_lock_safe(&ring[(i+1)%NTHREAD], "ring-right");
		mutex_lock_safe(&master_lock, "master_lock");
		yield();
		mutex_unlock_safe(&master_lock, "master_lock");
		if (NTHREAD > 1)
			mutex_unlock_safe(&ring[(i+1)%NTHREAD], "ring-right");
		mutex_unlock_safe(&ring[i], "ring-left");
	}

	if (i == 0)
		printf("testing condition variables\n");

	/* test cond_wait() and cond_signal() */
	for (j = 0; j < K; j++) {
		val = cond_get(&chan[i]);
		cond_put(&chan[(i+1)%NTHREAD], val+1);
		fadd(&put_count, 1);
	}

	if (i == NTHREAD-1) {
		if (val == (K*NTHREAD-1) && val == put_count-1)
			printf("successful 1st conditional variables test\n"); 
		else
			panic("thread=%d last token value=%d expected=%d put_count=%d",
				i, val, K*NTHREAD-1, put_count-1);
	}

	/* test cond_wait(), cond_twait(), cond_broadcast() and cond_signal() */
	for (j = 0; j < K; j++) {
		/* test cond_twait() and cond_signal() */
		val = cond_tget(&chan[i], hrtime() + (sec2ticks()/100));
		/* test cond_wait() and cond_broadcast() */
		cond_barrier(&cb, i, NTHREAD);
		if (val >= 0) {
			cond_put(&chan[(i+1)%NTHREAD], val+1);
			last_val = val;
			fadd(&put_count, 1);
		}
	}

	if (i == (put_count-1)%NTHREAD) {
		if (last_val == (put_count-1))
			printf("successful 2nd conditional variables test\n");
		else
			panic("thread=%d last token value=%d expected=%d",
				i, last_val, put_count-1);
	}

	/* test cond_signal_thread */
	if (i == 0)
		printf("testing cond_signal_thread\n");

	mutex_lock_safe(&l, "condition lock");
	thread_id[nc++] = get_thread();
	if (nc < NTHREAD) {
		if (cond_wait(&c, &l) < 0)
			panic("cond_wait:");
	} else	{
		/* shuffle the threads table in order to wake threads in a */
		/* random order */
		for (j = 0; j < NTHREAD-1; j++) {
			/* note: NTHREAD > 1 if we execute the loop body */
			/* this is why NTHREAD-1 > 0 here */
			k = (long)random() % (NTHREAD-1);
			t = thread_id[k];
			thread_id[k] = thread_id[j];
			thread_id[j] = t;
		}

		/* signal threads */
		for (j = 0; j < NTHREAD-1; j++) {
			if (cond_signal_thread(&c, thread_id[j]) < 0)
				panic("cond_signal_thread(%p, %p) failed:",
					&c, thread_id[j]);
		}
	}
	mutex_unlock_safe(&l, "condition lock");

	if (i == 0) {
		printf("test cond_signal_thread ended successfully\n");
		printf("starting cyclic buffer test\n");
		barrier_wait(&b, i, NTHREAD);

		if (cq_dequeue(&cq, cq_buf, 0) != NULL)
			panic("cq_dequeue of an empty queue did not fail");

		for (j = 1; j < NTHREAD; j++) {
			if (cq_enqueue(&cq, cq_buf, (void *)j) < 0)
				panic("cq_enqueue master iter %d failed:", j);
		}

		barrier_wait(&b, i, NTHREAD);

		for (j = 1; j < NTHREAD; j++) {
			usleep(SEC2USEC/10);
			if (cq_enqueue(&cq, cq_buf, (void *)j) < 0)
				panic("cq_enqueue master iter %d failed:", j);
		}

		barrier_wait(&b, i, NTHREAD);
		printf("cyclic buffer test ended successfully\n");
	} else {
		barrier_wait(&b, i, NTHREAD);

		if (cq_dequeue(&cq, cq_buf, 1) == NULL)
			panic("cq_dequeue of thread %d failed:", i);

		barrier_wait(&b, i, NTHREAD);

		if (cq_dequeue(&cq, cq_buf, 1) == NULL)
			panic("cq_dequeue of thread %d failed:", i);

		barrier_wait(&b, i, NTHREAD);
	}

	if (i == 0)
		printf("master thread waiting for mutex children completion\n");
	barrier_wait(&b, i, NTHREAD);
}


void
test_mutex(void)
{
	int i, code;
	Time start, elapsed;
	Lock lock;
	char msg[NAMELEN];

	printf("testing mutex_lock and mutex_unlock\n");
	mutex_init(&lock, 0);
	start = hrtime();
	for (i = 0; i < N10; i++) {
		if (mutex_lock(&lock) < 0)
			panic("mutex_lock:");
		if (mutex_unlock(&lock) < 0)
			panic("mutex_unlock:");
	}
	elapsed = 2*(hrtime() - start) - (N10*loop_overhead)/N;
	printf("elapsed cycles of %d mutex_lock/mutex_unlock pairs is %d\n", i,
		(int)elapsed);
	printf("each mutex_lock/unlock pair: %d cycles\n",
		(int)(elapsed+N10/2)/N10);

	printf("testing mutex_lock and mutex_unlock with error checking\n");
	mutex_init(&lock, MUTEX_ERRORCHECK);
	start = hrtime();
	for (i = 0; i < N10; i++) {
		if (mutex_lock(&lock) < 0)
			panic("mutex_lock:");
		if (mutex_unlock(&lock) < 0)
			panic("mutex_unlock:");
	}
	elapsed = 2*(hrtime() - start) - (N10*loop_overhead)/N;
	printf("elapsed cycles of %d mutex_lock/mutex_unlock pairs is %d\n", i,
		(int)elapsed);
	printf("each mutex_lock/unlock with error checking pair: %d cycles\n\n",
		(int)(elapsed+N10/2)/N10);

	mutex_init(&master_lock, MUTEX_ERRORCHECK);
	mutex_init(&l, MUTEX_ERRORCHECK);
	cond_init(&c);
	if (barrier_init(&b) < 0)
		panic("barrier_init:");
	for (i = 0; i < NTHREAD; i++)
		chan_init(&chan[i]);
	cond_put(&chan[0], 0);
	cond_barrier_init(&cb);

	if (cq_init(&cq, cq_buf, NTHREAD) < 0)
		panic("cq_init failed:");

	mutex_lock(&l);
	if (cond_signal_thread(&c, (void *)0xdeadbeef) >= 0)
		panic("cond_signal_thread(%p, 0xdeadbeef) did not fail as expected", &c);
	mutex_unlock(&l);
	get_error(msg);
	printf("expected error message from cond_signal_thread(%p, 0): %s\n",
		&c, msg);

	for (i = 1; i < NTHREAD; i++) {
		code = fork();
		if (code == 0) {
			printf("mutex thread %d (%p) started\n",
				i, get_thread());
			mutex_worker(i);

			/* child threads wait forever here */
			barrier_wait(&b, i, NTHREAD);
			/* end of child thread */
		}

		/* parent thread */
		if (code < 0)
			panic("fork:");
	}

	/* parent thread */
	printf("parent thread %p starting concurrent mutex test\n",
		get_thread());
	mutex_worker(0);
	printf("mutex, condition variables & cyclic buffer tests ended successfully\n\n");

	/* parent continues, child threads wait forever */
}


static int count[NSIG+1];

void
handler(int signo)
{
	if (signo <= 0 || signo > NSIG)
		panic("invalid signal number in signal handler: %d", signo);
	count[signo]++;
}

void
signal_all(void)
{
	int signo, i;

	for (signo = 1; signo <= NSIG; signo++)
		for (i = signo; i <= NSIG; i++) {
			if (kill(get_asid(), i) < 0)
				panic("kill(%d, %d) failed:", get_asid(), i);
			/* allow the signals handler thread to run */
			yield();
		}
}

void
send_signals(Time delay)
{
	int code;
	int s;

	if (delay == 0) {
		signal_all();
	} else	{
		s = sem_create(0);
		if (s < 0)
			panic("send_signals: sem_create() failed:");

		code = fork();
		if (code < 0)
			panic("send_signals: fork() failed:");
		if (code == 0) {
			/* the child */
			usleep(delay);
			signal_all();
			/* wait forever */
			sem_wait(s);
		}
	}
}

void
verify(int x[], int pos1, int val1, int pos2, int val2, int n)
{
	int i;

	for (i = 0; i < n; i++) {
		if (i == pos1) {
			if (x[i] != val1)
				panic("verify failed: x[%d]=%d; expected %d",
					i, x[i], val1);
		} else if (i == pos2) {
			if (x[i] != val2)
				panic("verify failed: x[%d]=%d; expected %d",
					i, x[i], val2);
		} else {
			/* all other elements must be zero */
			if (x[i] != 0)
				panic("verify failed: x[%d]=%d; expected 0",
					i, x[i]);
		}
	}
}


void
test_signal(void)
{
	sigset_t set, block;
	Time start, elapsed;
	char msg[NAMELEN];

	printf("starting signals test\n");
	if (sigpending(&set) < 0)
		panic("sigpending failed:");
	if (set != 0)
		panic("pending signals mask not zero: %08x", set);

	printf("send signals when all are ignored\n");
	memset(count, 0, sizeof(count));
	/* send signals intially; expect all to fail since domain is not */
	/* initialized */
	if (kill(get_asid(), SIG1) >= 0)
		panic("kill(%d, %d) did not fail as expected",
			get_asid(), SIG1);
	get_error(msg);
	printf("expected error message=%s\n", msg);

	if (sigpending(&set) < 0)
		panic("sigpending failed:");
	if (set != 0)
		panic("pending signals mask not zero: %08x", set);

	verify(count, 0, 0, 0, 0, NSIG+1);
	printf("ignored signals completed correctly\n");

	/* define two signal handlers */
	printf("send signals when two are defined\n");
	if ((int)signal(SIG1, handler) == -1)
		panic("signal(%d, handler) failed:", SIG1);
	if ((int)signal(SIG2, handler) == -1)
		panic("signal(%d, handler) failed:", SIG2);
	memset(count, 0, sizeof(count));
	send_signals(0);
	usleep(SEC2USEC/10);

	if (sigpending(&set) < 0)
		panic("sigpending failed:");
	if (set != 0)
		panic("pending signals mask not zero: %08x", set);

	verify(count, SIG1, SIG1, SIG2, SIG2, NSIG+1);
	printf("deliver two signals completed correctly\n");

	/* block two signals and see what happens */
	sigemptyset(&block);
	sigaddset(&block, SIG1);
	sigaddset(&block, SIG2);
	if (sigprocmask(SIG_BLOCK, &block, NULL) < 0)
		panic("sigprocmask failed:");

	memset(count, 0, sizeof(count));
	send_signals(0);
	usleep(SEC2USEC/10);

	if (sigpending(&set) < 0)
		panic("sigpending failed:");
	if (set != block)
		panic("invalid mask of pending signals: %08x expected=%08x",
			set, block); 
	printf("pending signals when blocked=%08x\n", set);
	verify(count, 0, 0, 0, 0, NSIG+1);

	/* enable signals */
	if (sigprocmask(SIG_UNBLOCK, &block, NULL) < 0)
		panic("sigprocmask failed:");
	usleep(SEC2USEC/10);

	if (sigpending(&set) < 0)
		panic("sigpending failed:");
	if (set != 0)
		panic("pending signals mask not zero: %08x", set);

	verify(count, SIG1, 1, SIG2, 1, NSIG+1);
	printf("deliver two signals after blocking completed correctly\n");

	/* redefine the signals and retest */
	printf("redefine the signals\n");
	if ((int)signal(SIG1, SIG_DFL) == -1)
		panic("signal(%d, SIG_DFL) failed:", SIG1);
	if ((int)signal(SIG2, SIG_IGN) == -1)
		panic("signal(%d, SIG_IGN) failed:", SIG2);
	if ((int)signal(SIG3, handler) == -1)
		panic("signal(%d, handler) failed:", SIG3);
	if ((int)signal(SIG4, handler) == -1)
		panic("signal(%d, handler) failed:", SIG4);
	memset(count, 0, sizeof(count));
	send_signals(0);
	usleep(SEC2USEC/10);

	if (sigpending(&set) < 0)
		panic("sigpending failed:");
	if (set != 0)
		panic("pending signals mask not zero: %08x", set);

	verify(count, SIG3, SIG3, SIG4, SIG4, NSIG+1);
	printf("deliver two new signals completed correctly\n");

	/* check sigsuspend */
	printf("testing sigsuspend\n");

	/* block two signals and see what happens */
	sigemptyset(&block);
	sigaddset(&block, SIG3);
	sigaddset(&block, SIG4);
	if (sigprocmask(SIG_BLOCK, &block, NULL) < 0)
		panic("sigprocmask failed:");

	memset(count, 0, sizeof(count));
	send_signals(0);
	usleep(SEC2USEC/10);

	if (sigpending(&set) < 0)
		panic("sigpending failed:");
	if (set != block)
		panic("invalid mask of pending signals: %08x expected=%08x",
			set, block); 

	/* enable signals */
	printf("suspend main thread until signals are delivered\n");
	sigemptyset(&block);
	if (sigsuspend(&block) < 0)
		panic("sigsuspend failed:");
	/* note: only one of the signals is delivered, since the mask */
	/* is reset immediately */
	if (count[SIG3] == 0 && count[SIG4] == 0)
		panic("signals not called by sigsuspend");

	/* deliver all pending signals */
	sigemptyset(&block);
	if (sigprocmask(SIG_SETMASK, &block, NULL) < 0)
		panic("sigprocmask failed:");
	usleep(SEC2USEC/10);
	printf("sigsuspend works correctly\n");

	/* try again, now with delayed signals */
	/* block two signals */
	sigemptyset(&block);
	sigaddset(&block, SIG3);
	sigaddset(&block, SIG4);
	if (sigprocmask(SIG_BLOCK, &block, NULL) < 0)
		panic("sigprocmask failed:");

	printf("testing sigsuspend with delayed signals\n");
	memset(count, 0, sizeof(count));
	start = uptime();
	send_signals(SEC2USEC);

	printf("suspend main thread until signals are delivered\n");
	sigemptyset(&block);
	if (sigsuspend(&block) < 0)
		panic("sigsuspend failed:");
	elapsed = uptime() - start;
	/* note: only one of the signals is delivered, since the mask */
	/* is reset immediately */
	if (count[SIG3] == 0 && count[SIG4] == 0)
		panic("signals not called by sigsuspend");
	if (elapsed < SEC2USEC || elapsed > (11*SEC2USEC)/10)
		panic("sigsuspend is too fast or too slow. elapsed=%d (usec.)",
			(int)elapsed);
	printf("sigsuspend elapsed time=%d (usec.) as expected\n",
		(int)elapsed);
	
	printf("sigsuspend test ended correctly\n");
	printf("signals test ended successfully\n\n");
}

void
test_shm(void)
{
	int try_id, peek_id, window_peek_id;
	int sz;
	int val = 0;
	int *addr, *p;
	int s1, s2, code;

	printf("starting shared memory segment test\n");
	if ((peek_id = portal_open("fs_peek", 1)) < 0)
		panic("portal_open(fs_peek):");
	if ((window_peek_id = portal_open("fs_window_peek", 1)) < 0)
		panic("portal_open(fs_window_peek):");
	if ((try_id = portal_open("fs_try", 1)) < 0)
		panic("portal_open(fs_try):");
	if ((addr = (int *)shm_open("shared")) == (int *)-1)
		panic("shm_open(\"shared\"):");
	if ((sz = shm_size(addr)) < 0)
		panic("shm_size:");
	printf("shared memory region start addr=%p size=%d\n", addr, sz);
	set_mem(addr, sz);
	printf("before clean_cache of %d bytes\n", sz);
	clean_cache(addr, sz);
	check_mem(addr, (int)addr, sz);
	printf("check memory using fs_peek\n");
	for (p = addr; p < (int *)((ulong)addr + sz); p++) {
		if ((val = call_portal(peek_id, p)) == ~((int)p))
			continue;
		printf(
	"invalid shared memory contents: addr=%p value=%08x should be=%08x\n",
			p, val, ~((int)p));
		task_exit(1);
	}
	printf("check memory using fs_window_peek\n");
	for (p = addr; p < (int *)((ulong)addr + sz); p++) {
		if ((val = call_portal(window_peek_id, p)) == ~((int)p))
			continue;
		printf(
	"invalid shared memory contents: addr=%p value=%08x should be=%08x\n",
			p, val, ~((int)p));

⌨️ 快捷键说明

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