diff -ruN kozos30/extintr.c kozos32/extintr.c --- kozos30/extintr.c Mon Dec 17 22:28:21 2007 +++ kozos32/extintr.c Fri Jan 4 02:19:46 2008 @@ -121,14 +121,50 @@ return 0; } -int extintr_main(int argc, char *argv[]) +static int cnt_fd = -1; + +void extintr_handler(int signo) { fd_set fds; - char *p, *buffer; - int fd, id, ret, cnt_fd = -1, size, s; + char *buffer; + int ret, size, s; socklen_t len; struct timeval tm = {0, 0}; intrbuf *ibp; + + fds = readfds; + ret = select(maxfd + 1, &fds, NULL, NULL, &tm); + if (ret > 0) { + for (ibp = interrupts; ibp; ibp = ibp->next) { + if (FD_ISSET(ibp->fd, &fds)) { + switch (ibp->type) { + case INTR_TYPE_ACCEPT: + len = ibp->addr.sa_len; + s = accept(ibp->fd, &ibp->addr, &len); + if (s > 0) + kz_send(ibp->id, s, NULL); + break; + case INTR_TYPE_READ: + buffer = kz_kmalloc(BUFFER_SIZE); + size = read(ibp->fd, buffer, BUFFER_SIZE); + if (size >= 0) + kz_send(ibp->id, size, buffer); + break; + } + } + } + } + /* + * GDBスタブ利用の場合はスタブ側で read() されてしまい上の select() で + * 検知できないので,子プロセスへの割り込み再開通知を毎回行う. + */ + write(cnt_fd, "refresh", 8); +} + +int extintr_main(int argc, char *argv[]) +{ + char *p; + int fd, id; int fildes[2]; pid_t chld_pid = 0; @@ -136,39 +172,11 @@ maxfd = 0; pid = getpid(); - kz_setsig(SIGHUP); + kz_sethandler(SIGHUP, extintr_handler); while (1) { fd = kz_recv(&id, &p); - if (id == 0) { /* from kozos */ - fds = readfds; - ret = select(maxfd + 1, &fds, NULL, NULL, &tm); - if (ret > 0) { - for (ibp = interrupts; ibp; ibp = ibp->next) { - if (FD_ISSET(ibp->fd, &fds)) { - switch (ibp->type) { - case INTR_TYPE_ACCEPT: - len = ibp->addr.sa_len; - s = accept(ibp->fd, &ibp->addr, &len); - if (s > 0) - kz_send(ibp->id, s, NULL); - break; - case INTR_TYPE_READ: - buffer = kz_kmalloc(BUFFER_SIZE); - size = read(ibp->fd, buffer, BUFFER_SIZE); - if (size >= 0) - kz_send(ibp->id, size, buffer); - break; - } - } - } - } - /* - * GDBスタブ利用の場合はスタブ側で read() されてしまい上の select() で - * 検知できないので,子プロセスへの割り込み再開通知を毎回行う. - */ - write(cnt_fd, "refresh", 8); - } else if (fd) { /* from thread */ + if (fd) { /* from thread */ setintrbuf(fd, id, (struct sockaddr *)p); /* * ソケットを子プロセスに引き継ぐ必要があるので,子プロセスを diff -ruN kozos30/kozos.h kozos32/kozos.h --- kozos30/kozos.h Mon Dec 17 22:28:21 2007 +++ kozos32/kozos.h Fri Jan 4 02:19:46 2008 @@ -31,6 +31,8 @@ void kz_sysdown(); void kz_trap(); void kz_break(); +void kz_block(); +void kz_unblock(); /* general thread */ extern int outlog_id; diff -ruN kozos30/thread.c kozos32/thread.c --- kozos30/thread.c Mon Dec 17 22:28:21 2007 +++ kozos32/thread.c Fri Jan 4 02:19:46 2008 @@ -31,12 +31,23 @@ static kz_handler handlers[SIG_NUM]; static int debug_sockt = 0; sigset_t block; +static sigset_t block_sys; +static sigset_t block_old; +static int block_count = 0; static stack_t intrstack; kz_thread *current; -static void getcurrent() +static int getcurrent() { + if (current == NULL) { + return -1; + } + if (!(current->flags & KZ_THREAD_FLAG_RUNNING)) { + /* すでに無い場合は無視 */ + return 1; + } + readyque[current->pri].head = current->next; if (readyque[current->pri].head == NULL) { readyque[current->pri].tail = NULL; @@ -44,13 +55,18 @@ } current->flags &= ~KZ_THREAD_FLAG_RUNNING; current->next = NULL; + + return 0; } static int putcurrent() { + if (current == NULL) { + return -1; + } if (current->flags & KZ_THREAD_FLAG_RUNNING) { /* すでに有る場合は無視 */ - return -1; + return 1; } if (readyque[current->pri].tail) { @@ -325,8 +341,25 @@ static void extintr_proc(int signo) { - if (handlers[signo]) + /* + * システムコールのパラメータ格納にコンテキストが必要なので, + * 割り込み処理用のコンテキストを確保する. + * (割り込みがネストしたときのために,スタック上に確保する) + */ + kz_thread intrcontext; + kz_thread *current_save; + + if (handlers[signo]) { + memset(&intrcontext, 0, sizeof(intrcontext)); + current_save = current; + current = &intrcontext; + + sigprocmask(SIG_UNBLOCK, &block_sys, NULL); handlers[signo](signo); + sigprocmask(SIG_BLOCK, &block_sys, NULL); + + current = current_save; + } if (sigcalls[signo]) sendmsg(sigcalls[signo], 0, 0, NULL); } @@ -365,14 +398,12 @@ return 0; } -static void syscall_proc() +static void syscall_proc(kz_syscall_type_t type, kz_syscall_param_t *p) { - /* システムコールの実行中にcurrentが書き換わるのでポインタを保存しておく */ - kz_syscall_param_t *p = current->syscall.param; - getcurrent(); - switch (current->syscall.type) { + /* システムコールの実行中にcurrentが書き換わるので注意 */ + switch (type) { case KZ_SYSCALL_TYPE_RUN: p->un.run.ret = thread_run(p->un.run.func, p->un.run.name, p->un.run.pri, p->un.run.argc, p->un.run.argv); @@ -468,11 +499,11 @@ current = readyque[n].head; } -static void thread_intrvec(int signo) +static void thread_intrvec(int signo, kz_thread *thp) { switch (signo) { case SIGSYS: /* システムコール */ - syscall_proc(); + syscall_proc(thp->syscall.type, thp->syscall.param); break; case SIGHUP: /* 外部割込み */ break; @@ -484,7 +515,7 @@ case SIGTRAP: case SIGILL: if (debug_sockt) { - stub_proc(current, signo); + stub_proc(thp, signo); } else { fprintf(stderr, "error thread \"%s\"\n", current->name); /* ダウン要因発生により継続不可能なので,スリープ状態にする*/ @@ -498,6 +529,11 @@ break; } extintr_proc(signo); + + if (current == NULL) { + return; + } + schedule(); /* @@ -518,11 +554,16 @@ static void thread_intr(int signo, siginfo_t *info, ucontext_t *uap) { unsigned int esp = uap->uc_mcontext.mc_esp; - if ((esp < (unsigned int)intrstack.ss_sp) || - (esp >= (unsigned int)intrstack.ss_sp + intrstack.ss_size)) { + kz_thread *thp = current; + + if ((esp >= (unsigned int)intrstack.ss_sp) && + (esp < (unsigned int)intrstack.ss_sp + intrstack.ss_size)) { + current = NULL; + } else { memcpy(¤t->context.uap, uap, sizeof(ucontext_t)); } - thread_intrvec(signo); + thread_intrvec(signo, thp); + current = thp; } static void thread_start(kz_func func, char *name, int pri, int argc, char *argv[]) @@ -578,6 +619,9 @@ sigaddset(&block, SIGTRAP); sigaddset(&block, SIGILL); + sigemptyset(&block_sys); + sigaddset(&block_sys, SIGSYS); + thread_start(func, name, pri, argc, argv); /* ここには返ってこない */ @@ -598,4 +642,22 @@ { void breakpoint(); breakpoint(); +} + +void kz_block() +{ + if (block_count == 0) { + sigprocmask(SIG_BLOCK, &block, &block_old); + } + block_count++; +} + +void kz_unblock() +{ + if (block_count > 0) { + block_count--; + if (block_count == 0) { + sigprocmask(SIG_SETMASK, &block_old, NULL); + } + } }