diff -ruN -U 10 kozos03/kozos.h kozos04/kozos.h --- kozos03/kozos.h Sun Oct 21 22:32:45 2007 +++ kozos04/kozos.h Sun Oct 21 22:32:45 2007 @@ -8,15 +8,16 @@ /* syscall */ int kz_run(kz_func func, char *name, int pri, int argc, char *argv[]); void kz_exit(); int kz_wait(); int kz_sleep(); int kz_wakeup(int id); int kz_getid(); int kz_chpri(int pri); int kz_send(int id, int size, char *p); int kz_recv(int *idp, char **pp); +int kz_timer(int msec); /* library */ void kz_start(kz_func func, char *name, int pri, int argc, char *argv[]); #endif diff -ruN -U 10 kozos03/syscall.c kozos04/syscall.c --- kozos03/syscall.c Sun Oct 21 22:32:45 2007 +++ kozos04/syscall.c Sun Oct 21 22:32:45 2007 @@ -81,10 +81,18 @@ } int kz_recv(int *idp, char **pp) { kz_syscall_param_t param; param.un.recv.idp = idp; param.un.recv.pp = pp; kz_syscall(KZ_SYSCALL_TYPE_RECV, ¶m); return param.un.recv.ret; } + +int kz_timer(int msec) +{ + kz_syscall_param_t param; + param.un.timer.msec = msec; + kz_syscall(KZ_SYSCALL_TYPE_TIMER, ¶m); + return param.un.timer.ret; +} diff -ruN -U 10 kozos03/syscall.h kozos04/syscall.h --- kozos03/syscall.h Sun Oct 21 22:32:45 2007 +++ kozos04/syscall.h Sun Oct 21 22:32:45 2007 @@ -6,20 +6,21 @@ typedef enum { KZ_SYSCALL_TYPE_RUN, KZ_SYSCALL_TYPE_EXIT, KZ_SYSCALL_TYPE_WAIT, KZ_SYSCALL_TYPE_SLEEP, KZ_SYSCALL_TYPE_WAKEUP, KZ_SYSCALL_TYPE_GETID, KZ_SYSCALL_TYPE_CHPRI, KZ_SYSCALL_TYPE_SEND, KZ_SYSCALL_TYPE_RECV, + KZ_SYSCALL_TYPE_TIMER, } kz_syscall_type_t; typedef struct { union { struct { kz_func func; char *name; int pri; int argc; char **argv; @@ -49,16 +50,20 @@ int id; int size; char *p; int ret; } send; struct { int *idp; char **pp; int ret; } recv; + struct { + int msec; + int ret; + } timer; } un; } kz_syscall_param_t; void kz_syscall(kz_syscall_type_t type, kz_syscall_param_t *param); #endif diff -ruN -U 10 kozos03/thread.c kozos04/thread.c --- kozos03/thread.c Sun Oct 21 22:32:45 2007 +++ kozos04/thread.c Sun Oct 21 22:32:45 2007 @@ -5,23 +5,30 @@ #include #include #include "kozos.h" #include "syscall.h" #include "thread.h" #define SIG_NUM 32 #define STACK_SIZE 0x8000 +typedef struct _kz_timebuf { + struct _kz_timebuf *next; + int msec; + kz_thread *thp; +} kz_timebuf; + kz_thread threads[THREAD_NUM]; kz_thread *readyque[PRI_NUM]; static jmp_buf intr_env; +static kz_timebuf *timers; kz_thread *current; static void getcurrent() { readyque[current->pri] = current->next; current->next = NULL; } static int putcurrent() @@ -205,20 +212,61 @@ if (current->messages == NULL) { /* メッセージが無いのでブロックする */ return -1; } recvmsg(); putcurrent(); return current->syscall.param->un.recv.ret; } +static int thread_timer(int msec) +{ + kz_timebuf **tmpp; + kz_timebuf *tmp; + + tmp = malloc(sizeof(*tmp)); + tmp->next = NULL; + tmp->thp = current; + + for (tmpp = &timers; *tmpp; tmpp = &((*tmpp)->next)) { + if (msec < (*tmpp)->msec) { + (*tmpp)->msec -= msec; + break; + } + msec -= (*tmpp)->msec; + } + + if (msec == 0) msec++; + tmp->msec = msec; + tmp->next = *tmpp; + *tmpp = tmp; + + ualarm(timers->msec * 1000, 0); + + putcurrent(); + return 0; +} + +void alarm_handler() +{ + kz_timebuf *tmp; + + sendmsg(timers->thp, 0, 0, NULL); + tmp = timers; + timers = timers->next; + free(tmp); + if (timers) { + ualarm(timers->msec * 1000, 0); + } +} + static void syscall_proc() { /* システムコールの実行中にcurrentが書き換わるのでポインタを保存しておく */ kz_syscall_param_t *p = current->syscall.param; getcurrent(); switch (current->syscall.type) { case KZ_SYSCALL_TYPE_RUN: p->un.run.ret = thread_run(p->un.run.func, p->un.run.name, p->un.run.pri, @@ -242,20 +290,23 @@ break; case KZ_SYSCALL_TYPE_CHPRI: p->un.chpri.ret = thread_chpri(p->un.chpri.pri); break; case KZ_SYSCALL_TYPE_SEND: p->un.send.ret = thread_send(p->un.send.id, p->un.send.size, p->un.send.p); break; case KZ_SYSCALL_TYPE_RECV: p->un.recv.ret = thread_recv(p->un.recv.idp, p->un.recv.pp); break; + case KZ_SYSCALL_TYPE_TIMER: + p->un.timer.ret = thread_timer(p->un.timer.msec); + break; default: break; } return; } static void dispatch() { int i; for (i = 0; i < PRI_NUM; i++) { @@ -267,20 +318,23 @@ } current = readyque[i]; } static void thread_intrvec(int signo) { switch (signo) { case SIGSYS: /* システムコール */ syscall_proc(); break; + case SIGALRM: /* タイマ割込み発生 */ + alarm_handler(); + break; case SIGBUS: /* ダウン要因発生 */ case SIGSEGV: case SIGTRAP: case SIGILL: { fprintf(stderr, "error %s\n", current->name); /* ダウン要因発生により継続不可能なので,スリープ状態にする*/ getcurrent(); } break; @@ -301,21 +355,24 @@ if (setjmp(current->context.env) == 0) { longjmp(intr_env, signo); } } static void thread_start(kz_func func, char *name, int pri, int argc, char *argv[]) { memset(threads, 0, sizeof(threads)); memset(readyque, 0, sizeof(readyque)); + timers = NULL; + signal(SIGSYS, thread_intr); + signal(SIGALRM, thread_intr); /* * current 未定のためにシステムコール発行はできないので, * 直接関数を呼び出してスレッド作成する. */ current = NULL; current = (kz_thread *)thread_run(func, name, pri, argc, argv); longjmp(current->context.env, 1); }