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