diff -ruN kozos07/Makefile kozos08/Makefile --- kozos07/Makefile Sat Nov 3 08:21:04 2007 +++ kozos08/Makefile Sat Nov 3 08:21:05 2007 @@ -1,4 +1,4 @@ -OBJS += thread.o syscall.o outlog.o extintr.o +OBJS += thread.o syscall.o outlog.o extintr.o idle.o OBJS += main.o clock.o telnetd.o httpd.o TARGET ?= koz CC ?= gcc diff -ruN kozos07/extintr.c kozos08/extintr.c --- kozos07/extintr.c Sat Nov 3 08:21:04 2007 +++ kozos08/extintr.c Sat Nov 3 08:21:05 2007 @@ -1,8 +1,11 @@ #include #include #include +#include #include #include +#include +#include #include "kozos.h" @@ -24,6 +27,61 @@ static intrbuf *interrupts; static fd_set readfds; static int maxfd; +static pid_t pid; + +static int intr_controller(int cnt_fd) +{ + int fd, ret, size; + fd_set fds; + char buf[32]; + char *p; + + /* + * 子プロセスなので,この中で kz_ システムコールを利用してはいけない. + */ + + FD_SET(cnt_fd, &readfds); + if (maxfd < cnt_fd) maxfd = cnt_fd; + + while (1) { + fds = readfds; + ret = select(maxfd + 1, &fds, NULL, NULL, NULL); + if (ret > 0) { + if (FD_ISSET(cnt_fd, &fds)) { + size = read(cnt_fd, buf, sizeof(buf)); + if (size > 0) { + for (p = buf; p < buf + size; p += strlen(p) + 1) { + if (!strcmp(p, "exit")) + goto end; + fd = atoi(p); + FD_SET(fd, &readfds); + } + } + } else { + kill(pid, SIGHUP); + for (fd = 0; fd <= maxfd; fd++) { + if ((fd != cnt_fd) && FD_ISSET(fd, &fds)) { + FD_CLR(fd, &readfds); + } + } + } +#if 0 + /* + * 繰り返しシグナルが発生することの防止. + * 本来なら割込み処理側からメッセージを送ってもらって, + * ソケットごとに割込みの有効化/無効化を行う必要があるだろう. + * (シグナル送信したら無効化し,割込み処理が行われたら + * メッセージを送ってもらって割込みを有効化する) + */ + usleep(1000); +#endif + } + } + +end: + close(cnt_fd); + exit(0); +} static int setintrbuf(int fd, int id, struct sockaddr *addrp) { @@ -64,42 +122,72 @@ { fd_set fds; char *p, *buffer; - int fd, id, ret, size, s, len; + int fd, id, ret, cnt_fd = -1, size, s, len; + struct timeval tm = {0, 0}; intrbuf *ibp; + int fildes[2]; + char buf[32]; + pid_t chld_pid = 0; FD_ZERO(&readfds); maxfd = 0; - while (1) { - while (kz_pending()) { - fd = kz_recv(&id, &p); - if (fd) { /* from thread */ - setintrbuf(fd, id, (struct sockaddr *)p); - } - } + pid = getpid(); + kz_setsig(SIGHUP); - fds = readfds; - ret = select(maxfd + 1, &fds, NULL, NULL, NULL); - - 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_memalloc(BUFFER_SIZE); - size = read(ibp->fd, buffer, BUFFER_SIZE); - if (size > 0) - kz_send(ibp->id, size, buffer); - break; + 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_memalloc(BUFFER_SIZE); + size = read(ibp->fd, buffer, BUFFER_SIZE); + if (size >= 0) + kz_send(ibp->id, size, buffer); + break; + } + /* + * GDBスタブ利用の場合はスタブ側で read() されてしまい + * 上の select() で検知できないので,子プロセスへの + * 割り込み再開通知を別の方法で毎回行う必要があるだろう. + */ + sprintf(buf, "%d", ibp->fd); + write(cnt_fd, buf, strlen(buf) + 1); } } } + } else if (fd) { /* from thread */ + setintrbuf(fd, id, (struct sockaddr *)p); + /* + * ソケットを子プロセスに引き継ぐ必要があるので,子プロセスを + * 毎回作りなおす. + */ + if (chld_pid) { + write(cnt_fd, "exit", 5); + wait(NULL); + close(cnt_fd); + } + pipe(fildes); + if ((chld_pid = fork()) == 0) { /* 子プロセス */ +#if 0 + signal(SIGALRM, SIG_IGN); +#endif + close(fildes[1]); + intr_controller(fildes[0]); + } + close(fildes[0]); + cnt_fd = fildes[1]; } } } diff -ruN kozos07/httpd.c kozos08/httpd.c --- kozos07/httpd.c Sat Nov 3 08:21:04 2007 +++ kozos08/httpd.c Sat Nov 3 08:21:05 2007 @@ -45,7 +45,7 @@ write(s, mes, sizeof(mes)); kz_send(extintr_id, s, NULL); - close(s); + shutdown(s, SHUT_RDWR); return 0; } diff -ruN kozos07/idle.c kozos08/idle.c --- kozos07/idle.c Thu Jan 1 09:00:00 1970 +++ kozos08/idle.c Sat Nov 3 08:21:05 2007 @@ -0,0 +1,14 @@ +#include +#include +#include + +#include "kozos.h" + +int idle_id; + +int idle_main(int argc, char *argv[]) +{ + while (1) { + select(0, NULL, NULL, NULL, NULL); + } +} diff -ruN kozos07/kozos.h kozos08/kozos.h --- kozos07/kozos.h Sat Nov 3 08:21:04 2007 +++ kozos08/kozos.h Sat Nov 3 08:21:05 2007 @@ -17,6 +17,7 @@ int kz_recv(int *idp, char **pp); int kz_timer(int msec); int kz_pending(); +int kz_setsig(int signo); void *kz_memalloc(int size); int kz_memfree(void *p); @@ -26,8 +27,10 @@ /* general thread */ extern int outlog_id; extern int extintr_id; +extern int idle_id; int outlog_main(int argc, char *argv[]); int extintr_main(int argc, char *argv[]); +int idle_main(int argc, char *argv[]); /* user thread */ extern int clock_id; diff -ruN kozos07/main.c kozos08/main.c --- kozos07/main.c Sat Nov 3 08:21:04 2007 +++ kozos08/main.c Sat Nov 3 08:21:05 2007 @@ -5,8 +5,9 @@ int mainfunc(int argc, char *argv[]) { - extintr_id = kz_run(extintr_main, "extintr", 31, 0, NULL); - outlog_id = kz_run(outlog_main, "outlog", 1, 0, NULL); + extintr_id = kz_run(extintr_main, "extintr", 1, 0, NULL); + outlog_id = kz_run(outlog_main, "outlog", 2, 0, NULL); + idle_id = kz_run(idle_main, "idle", 31, 0, NULL); clock_id = kz_run(clock_main, "clock", 7, 0, NULL); telnetd_id = kz_run(telnetd_main, "telnetd", 8, 0, NULL); httpd_id = kz_run(httpd_main, "httpd", 9, 0, NULL); diff -ruN kozos07/syscall.c kozos08/syscall.c --- kozos07/syscall.c Sat Nov 3 08:21:04 2007 +++ kozos08/syscall.c Sat Nov 3 08:21:05 2007 @@ -104,6 +104,14 @@ return param.un.pending.ret; } +int kz_setsig(int signo) +{ + kz_syscall_param_t param; + param.un.setsig.signo = signo; + kz_syscall(KZ_SYSCALL_TYPE_SETSIG, ¶m); + return param.un.setsig.ret; +} + void *kz_memalloc(int size) { kz_syscall_param_t param; diff -ruN kozos07/syscall.h kozos08/syscall.h --- kozos07/syscall.h Sat Nov 3 08:21:04 2007 +++ kozos08/syscall.h Sat Nov 3 08:21:05 2007 @@ -15,6 +15,7 @@ KZ_SYSCALL_TYPE_RECV, KZ_SYSCALL_TYPE_TIMER, KZ_SYSCALL_TYPE_PENDING, + KZ_SYSCALL_TYPE_SETSIG, KZ_SYSCALL_TYPE_MEMALLOC, KZ_SYSCALL_TYPE_MEMFREE, } kz_syscall_type_t; @@ -67,6 +68,10 @@ struct { int ret; } pending; + struct { + int signo; + int ret; + } setsig; struct { int size; void *ret; diff -ruN kozos07/telnetd.c kozos08/telnetd.c --- kozos07/telnetd.c Sat Nov 3 08:21:04 2007 +++ kozos08/telnetd.c Sat Nov 3 08:21:05 2007 @@ -27,6 +27,10 @@ while (1) { size = kz_recv(NULL, &p); + if ((size == 0) + || memchr(p, 0x04, size) /* Ctrl-D対応 */ + || memchr(p, 0xff, size) /* Ctrl-C対応 */ + ) break; memcpy(buffer + len, p, size); kz_memfree(p); len += size; @@ -60,7 +64,7 @@ } kz_send(extintr_id, s, NULL); - close(s); + shutdown(s, SHUT_RDWR); return 0; } diff -ruN kozos07/thread.c kozos08/thread.c --- kozos07/thread.c Sat Nov 3 08:21:04 2007 +++ kozos08/thread.c Sat Nov 3 08:21:05 2007 @@ -23,6 +23,7 @@ kz_thread *readyque[PRI_NUM]; static jmp_buf intr_env; static kz_timebuf *timers; +static kz_thread *sigcalls[SIG_NUM]; kz_thread *current; @@ -284,6 +285,19 @@ return current->messages ? 1 : 0; } +static int thread_setsig(int signo) +{ + sigcalls[signo] = current; + putcurrent(); + return 0; +} + +static void extintr_proc(int signo) +{ + if (sigcalls[signo]) + sendmsg(sigcalls[signo], 0, 0, NULL); +} + static void *thread_memalloc(int size) { putcurrent(); @@ -340,6 +354,9 @@ case KZ_SYSCALL_TYPE_PENDING: p->un.pending.ret = thread_pending(); break; + case KZ_SYSCALL_TYPE_SETSIG: + p->un.setsig.ret = thread_setsig(p->un.setsig.signo); + break; case KZ_SYSCALL_TYPE_MEMALLOC: p->un.memalloc.ret = thread_memalloc(p->un.memalloc.size); break; @@ -371,6 +388,8 @@ case SIGSYS: /* システムコール */ syscall_proc(); break; + case SIGHUP: /* 外部割込み */ + break; case SIGALRM: /* タイマ割込み発生 */ alarm_handler(); break; @@ -387,6 +406,7 @@ default: break; } + extintr_proc(signo); dispatch(); longjmp(current->context.env, 1); } @@ -407,10 +427,12 @@ { memset(threads, 0, sizeof(threads)); memset(readyque, 0, sizeof(readyque)); + memset(sigcalls, 0, sizeof(sigcalls)); timers = NULL; signal(SIGSYS, thread_intr); + signal(SIGHUP, thread_intr); signal(SIGALRM, thread_intr); /*