Binary files kozos12/koz.core and kozos13/koz.core differ diff -ruN kozos12/thread.c kozos13/thread.c --- kozos12/thread.c Sun Nov 11 20:53:01 2007 +++ kozos13/thread.c Sun Nov 11 20:59:30 2007 @@ -3,7 +3,6 @@ #include #include #include -#include #include #include @@ -13,7 +12,6 @@ #include "stublib.h" #define SIG_NUM 32 -#define STACK_SIZE 0x8000 typedef struct _kz_timebuf { struct _kz_timebuf *next; @@ -23,13 +21,14 @@ kz_thread threads[THREAD_NUM]; kz_thread *readyque[PRI_NUM]; -static jmp_buf intr_env; +static ucontext_t intr_env; static kz_timebuf *timers; static kz_thread *sigcalls[SIG_NUM]; static int debug_sockt = 0; static sigset_t block; kz_thread *current; +static int current_signo; static void getcurrent() { @@ -48,21 +47,23 @@ return 0; } -static void thread_init(kz_thread *thp, int argc, char *argv[]) +static void thread_end() { - thp->func(argc, argv); + kz_exit(); } -static void thread_end() +static void thread_init(kz_thread *thp, int argc, char *argv[]) { - kz_exit(); + sigprocmask(SIG_UNBLOCK, &block, NULL); + + thp->func(argc, argv); + thread_end(); } static int thread_run(kz_func func, char *name, int pri, int argc, char *argv[]) { int i; - char *sp; kz_thread *thp; for (i = 0; i < THREAD_NUM; i++) { @@ -78,37 +79,18 @@ thp->id = thp; thp->func = func; thp->pri = pri; - thp->stack = malloc(STACK_SIZE); - - memset(thp->stack, 0, STACK_SIZE); + thp->stack = malloc(SIGSTKSZ); - sp = thp->stack + STACK_SIZE - 32; + memset(thp->stack, 0, SIGSTKSZ); - /* メイン関数終了時の戻り先 */ - ((int *)sp)[1] = (int)thread_end; + getcontext(&thp->context.uap); - /* スタック上に引数(argc,argv)を準備する */ - ((int *)sp)[2] = (int)thp; - ((int *)sp)[3] = argc; - ((int *)sp)[4] = (int)argv; + thp->context.uap.uc_stack.ss_sp = thp->stack; + thp->context.uap.uc_stack.ss_size = SIGSTKSZ; + thp->context.uap.uc_stack.ss_flags = 0; + thp->context.uap.uc_link = NULL; - /* - * 以下の設定については setjmp()/longjmp() - * (/usr/src/lib/libc/i386/gen)を参照. - */ -#if 1 - thp->context.env[0]._jb[0] = (int)thread_init; /* EIP */ - thp->context.env[0]._jb[1] = intr_env[0]._jb[1]; /* EBX */ - thp->context.env[0]._jb[2] = (int)sp; /* ESP */ - thp->context.env[0]._jb[3] = intr_env[0]._jb[3]; /* EBP */ - thp->context.env[0]._jb[4] = intr_env[0]._jb[4]; /* ESI */ - thp->context.env[0]._jb[5] = intr_env[0]._jb[5]; /* EDI */ - /* thp->context.env[0]._jb[6] = ??? */ -#else - memcpy(thp->context.env, intr_env, sizeof(intr_env)); - thp->context.env[0]._jb[0] = (int)thread_init; /* EIP */ - thp->context.env[0]._jb[2] = (int)sp; /* ESP */ -#endif + makecontext(&thp->context.uap, (void (*)())thread_init, 3, thp, argc, argv); /* 起動時の初回のスレッド作成では current 未定なのでNULLチェックする */ if (current) { @@ -428,23 +410,14 @@ } extintr_proc(signo); dispatch(); - longjmp(current->context.env, 1); + setcontext(¤t->context.uap); } static void thread_intr(int signo, siginfo_t *info, ucontext_t *uap) { memcpy(¤t->context.uap, uap, sizeof(ucontext_t)); - - /* - * setjmp()/longjmp() はシグナルマスクを保存し復元するが, - * _setjmp()/_longjmp() はシグナルマスクを保存しない. - * (レジスタセットとスタックしか保存および復元しない) - */ - if (setjmp(current->context.env) == 0) { - longjmp(intr_env, signo); - } - - setcontext(¤t->context.uap); + current_signo = signo; + setcontext(&intr_env); } static void thread_start(kz_func func, char *name, int pri, int argc, char *argv[]) @@ -460,7 +433,17 @@ memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = (void (*)(int, siginfo_t *, void *))thread_intr; sa.sa_flags |= SA_SIGINFO; +#if 0 sa.sa_mask = block; +#else + /* + * シグナル処理中のシグナル発生を受け付ける. + * これを有効にするとKOZOSの処理中に再入する可能性が発生するため問題有り + * なのだが,スタブ中での read() ブロック中に SIGALRM が発生した場合の + * 暫定対処とする. + */ + sigemptyset(&sa.sa_mask); +#endif sigaction(SIGSYS , &sa, NULL); sigaction(SIGHUP , &sa, NULL); @@ -477,13 +460,22 @@ current = NULL; current = (kz_thread *)thread_run(func, name, pri, argc, argv); - longjmp(current->context.env, 1); + swapcontext(&intr_env, ¤t->context.uap); + { + /* なぜか getcontext() しなおさないと正常動作しない...謎 */ + static int f; + do { + f = 0; + getcontext(&intr_env); + } while (f); + f = 1; + } + + thread_intrvec(current_signo); } void kz_start(kz_func func, char *name, int pri, int argc, char *argv[]) { - int signo; - /* * setjmp()/longjmp()はシグナルマスクを保存/復旧するので, * intr_env の setjmp() 前にシグナルマスクを設定することでシグナル処理中の @@ -502,15 +494,7 @@ sigaddset(&block, SIGILL); sigprocmask(SIG_BLOCK, &block, NULL); - /* - * setjmp()は最低位の関数から呼ぶ必要があるので,本体は thread_start() に - * 置いて setjmp() 呼び出し直後に本体を呼び出す. - * (setjmp()した関数から return 後に longjmp() を呼び出してはいけない) - */ - if ((signo = setjmp(intr_env)) == 0) { - thread_start(func, name, pri, argc, argv); - } - thread_intrvec(signo); + thread_start(func, name, pri, argc, argv); /* ここには返ってこない */ abort(); diff -ruN kozos12/thread.h kozos13/thread.h --- kozos12/thread.h Sun Nov 11 20:53:01 2007 +++ kozos13/thread.h Sun Nov 11 19:48:44 2007 @@ -3,7 +3,6 @@ #include #include -#include #include #include "kozos.h" @@ -36,7 +35,6 @@ kz_membuf *messages; struct { - jmp_buf env; ucontext_t uap; } context; } kz_thread;