diff -ruN -U 10 kozos01/kozos.h kozos03/kozos.h --- kozos01/kozos.h Sun Oct 21 22:32:45 2007 +++ kozos03/kozos.h Sun Oct 21 22:32:45 2007 @@ -4,15 +4,19 @@ #include "configure.h" typedef int (*kz_func)(int argc, char *argv[]); /* 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); /* library */ void kz_start(kz_func func, char *name, int pri, int argc, char *argv[]); #endif diff -ruN -U 10 kozos01/syscall.c kozos03/syscall.c --- kozos01/syscall.c Sun Oct 21 22:32:45 2007 +++ kozos03/syscall.c Sun Oct 21 22:32:45 2007 @@ -47,10 +47,44 @@ return param.un.sleep.ret; } int kz_wakeup(int id) { kz_syscall_param_t param; param.un.wakeup.id = id; kz_syscall(KZ_SYSCALL_TYPE_WAKEUP, ¶m); return param.un.wakeup.ret; } + +int kz_getid() +{ + kz_syscall_param_t param; + kz_syscall(KZ_SYSCALL_TYPE_GETID, ¶m); + return param.un.getid.ret; +} + +int kz_chpri(int pri) +{ + kz_syscall_param_t param; + param.un.chpri.pri = pri; + kz_syscall(KZ_SYSCALL_TYPE_CHPRI, ¶m); + return param.un.chpri.ret; +} + +int kz_send(int id, int size, char *p) +{ + kz_syscall_param_t param; + param.un.send.id = id; + param.un.send.size = size; + param.un.send.p = p; + kz_syscall(KZ_SYSCALL_TYPE_SEND, ¶m); + return param.un.send.ret; +} + +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; +} diff -ruN -U 10 kozos01/syscall.h kozos03/syscall.h --- kozos01/syscall.h Sun Oct 21 22:32:45 2007 +++ kozos03/syscall.h Sun Oct 21 22:32:45 2007 @@ -2,20 +2,24 @@ #define _KOZOS_SYSCALL_H_INCLUDED_ #include "kozos.h" 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_t; typedef struct { union { struct { kz_func func; char *name; int pri; int argc; char **argv; @@ -27,16 +31,34 @@ struct { int ret; } wait; struct { int ret; } sleep; struct { int id; int ret; } wakeup; + struct { + int ret; + } getid; + struct { + int pri; + int ret; + } chpri; + struct { + int id; + int size; + char *p; + int ret; + } send; + struct { + int *idp; + char **pp; + int ret; + } recv; } un; } kz_syscall_param_t; void kz_syscall(kz_syscall_type_t type, kz_syscall_param_t *param); #endif diff -ruN -U 10 kozos01/thread.c kozos03/thread.c --- kozos01/thread.c Sun Oct 21 22:32:45 2007 +++ kozos03/thread.c Sun Oct 21 22:32:45 2007 @@ -129,20 +129,96 @@ } static int thread_wakeup(int id) { putcurrent(); current = (kz_thread *)id; putcurrent(); return 0; } +static int thread_getid() +{ + putcurrent(); + return (int)current->id; +} + +static int thread_chpri(int pri) +{ + int old = current->pri; + if (pri >= 0) + current->pri = pri; + putcurrent(); + return old; +} + +static void recvmsg() +{ + kz_membuf *mp; + + mp = current->messages; + current->messages = mp->next; + mp->next = NULL; + + current->syscall.param->un.recv.ret = mp->size; + if (current->syscall.param->un.recv.idp) + *(current->syscall.param->un.recv.idp) = mp->id; + if (current->syscall.param->un.recv.pp) + *(current->syscall.param->un.recv.pp) = mp->p; + free(mp); +} + +static void sendmsg(kz_thread *thp, int id, int size, char *p) +{ + kz_membuf *mp; + kz_membuf **mpp; + + current = thp; + + mp = (kz_membuf *)malloc(sizeof(*mp)); + if (mp == NULL) { + fprintf(stderr, "cannot allocate memory.\n"); + exit(1); + } + mp->next = NULL; + mp->size = size; + mp->id = id; + mp->p = p; + for (mpp = ¤t->messages; *mpp; mpp = &((*mpp)->next)) + ; + *mpp = mp; + + if (putcurrent() == 0) { + /* 受信する側がブロック中の場合には受信処理を行う */ + recvmsg(); + } +} + +static int thread_send(int id, int size, char *p) +{ + putcurrent(); + sendmsg((kz_thread *)id, (int)current, size, p); + return size; +} + +static int thread_recv(int *idp, char **pp) +{ + if (current->messages == NULL) { + /* メッセージが無いのでブロックする */ + return -1; + } + + recvmsg(); + putcurrent(); + return current->syscall.param->un.recv.ret; +} + 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, @@ -153,20 +229,32 @@ thread_exit(); break; case KZ_SYSCALL_TYPE_WAIT: p->un.wait.ret = thread_wait(); break; case KZ_SYSCALL_TYPE_SLEEP: p->un.sleep.ret = thread_sleep(); break; case KZ_SYSCALL_TYPE_WAKEUP: p->un.wakeup.ret = thread_wakeup(p->un.wakeup.id); + break; + case KZ_SYSCALL_TYPE_GETID: + p->un.getid.ret = thread_getid(); + 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; default: break; } return; } static void dispatch() { int i; diff -ruN -U 10 kozos01/thread.h kozos03/thread.h --- kozos01/thread.h Sun Oct 21 22:32:45 2007 +++ kozos03/thread.h Sun Oct 21 22:32:45 2007 @@ -5,31 +5,40 @@ #include #include #include "kozos.h" #include "syscall.h" #define THREAD_NUM 16 #define PRI_NUM 32 #define THREAD_NAME_SIZE 16 +typedef struct _kz_membuf { + struct _kz_membuf *next; + int id; + int size; + char *p; +} kz_membuf; + typedef struct _kz_thread { struct _kz_thread *next; char name[THREAD_NAME_SIZE + 1]; struct _kz_thread *id; kz_func func; int pri; char *stack; struct { kz_syscall_type_t type; kz_syscall_param_t *param; } syscall; + + kz_membuf *messages; struct { jmp_buf env; } context; } kz_thread; extern kz_thread *current; #endif