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