diff -ruN kozos33/clock.c kozos34/clock.c --- kozos33/clock.c Sun Jan 4 09:36:43 2009 +++ kozos34/clock.c Sun Jan 18 23:48:35 2009 @@ -7,13 +7,32 @@ int clock_id; +static void send_use(int num) +{ + char *p; + p = kz_kmalloc(2); + p[0] = 't'; + p[1] = '0' + num; + kz_send(extintr_id, 2, p); +} + +static void send_enable() +{ + char *p; + p = kz_kmalloc(9); + strcpy(p, "s1;;;0;;;"); + kz_send(extintr_id, 9, p); +} + int clock_main(int argc, char *argv[]) { time_t t; char *p; + send_use(0); + while (1) { - kz_timer(1000); + send_enable(); kz_recv(NULL, NULL); t = time(NULL); diff -ruN kozos33/diff.txt kozos34/diff.txt --- kozos33/diff.txt Mon Jan 12 21:23:08 2009 +++ kozos34/diff.txt Mon Jan 19 00:41:20 2009 @@ -1,44 +1,15 @@ -diff -ruN kozos32/Makefile kozos33/Makefile ---- kozos32/Makefile Fri Jan 4 02:19:46 2008 -+++ kozos33/Makefile Mon Jan 5 22:27:58 2009 -@@ -1,6 +1,6 @@ - OBJS += thread.o syscall.o memory.o outlog.o extintr.o idle.o - OBJS += stubd.o stublib.o i386-stub.o --OBJS += main.o clock.o telnetd.o httpd.o -+OBJS += main.o clock.o command.o - TARGET ?= koz - CC ?= gcc - CFLAGS = -diff -ruN kozos32/command.c kozos33/command.c ---- kozos32/command.c Thu Jan 1 09:00:00 1970 -+++ kozos33/command.c Thu Jan 8 19:53:31 2009 -@@ -0,0 +1,130 @@ -+#include -+#include -+#include -+#include -+ -+#include "kozos.h" -+#include "thread.h" -+ -+int command_id; -+int command_dummy; -+ -+static int dummy_func(int n) -+{ -+ int i, sum; -+ sum = 0; -+ for (i = 1; i < n; i++) { -+ sum += i; -+ } -+ return sum; -+} -+ +diff -ruN kozos33/clock.c kozos34/clock.c +--- kozos33/clock.c Sun Jan 4 09:36:43 2009 ++++ kozos34/clock.c Sun Jan 18 23:48:35 2009 +@@ -7,13 +7,32 @@ + + int clock_id; + +static void send_use(int num) +{ + char *p; + p = kz_kmalloc(2); -+ p[0] = 'u'; ++ p[0] = 't'; + p[1] = '0' + num; + kz_send(extintr_id, 2, p); +} @@ -46,739 +17,21 @@ +static void send_enable() +{ + char *p; -+ p = kz_kmalloc(1); -+ p[0] = 'e'; -+ kz_send(extintr_id, 1, p); -+} -+ -+#if 0 -+static void send_disable() -+{ -+ char *p; -+ p = kz_kmalloc(1); -+ p[0] = 'd'; -+ kz_send(extintr_id, 1, p); -+} -+#endif -+ -+static void send_write(char *str) -+{ -+ char *p; -+ int len; -+ len = strlen(str); -+ p = kz_kmalloc(len + 1); -+ p[0] = 'w'; -+ memcpy(&p[1], str, len); -+ kz_send(extintr_id, len + 1, p); -+} -+ -+static int command_proc() -+{ -+ char *p; -+ char buffer[128]; -+ int len, size; -+ -+ len = 0; -+ send_write("> "); -+ send_enable(); -+ -+ while (1) { -+ size = kz_recv(NULL, &p); -+ send_enable(); -+ if ((size == 0) -+ || memchr(p, 0x04, size) /* Ctrl-D対応 */ -+ || memchr(p, 0xff, size) /* Ctrl-C対応 */ -+ ) break; -+ memcpy(buffer + len, p, size); -+ kz_kmfree(p); -+ len += size; -+ buffer[len] = '\0'; -+ -+ p = strchr(buffer, '\n'); -+ if (p == NULL) continue; -+ -+ if (!strncmp(buffer, "echo", 4)) { -+ send_write(buffer + 4); -+ } else if (!strncmp(buffer, "call", 4)) { -+ dummy_func(10); -+ } else if (!strncmp(buffer, "down", 4)) { -+ int *nullp = NULL; -+ *nullp = 1; -+ } else if (!strncmp(buffer, "trap", 4)) { -+ kz_trap(); -+ } else if (!strncmp(buffer, "break", 5)) { -+ kz_break(); -+ } else if (!strncmp(buffer, "date", 4)) { -+ time_t t; -+ t = time(NULL); -+ strcpy(buffer, ctime(&t)); -+ send_write(buffer); -+ } else if (!strncmp(buffer, "threads", 7)) { -+ kz_thread *thp; -+ int i; -+ for (i = 0; i < THREAD_NUM; i++) { -+ thp = &threads[i]; -+ if (!thp->id) continue; -+ send_write(thp->name); -+ send_write("\n"); -+ } -+ } else if (!strncmp(buffer, "exit", 4)) { -+ break; -+ } -+ -+ len = 0; -+ send_write("OK\n> "); -+ } -+ -+ return 0; -+} -+ -+int command_main(int argc, char *argv[]) -+{ -+ send_use(0); -+ -+ while (1) { -+ command_proc(); -+ } -+ -+ return 0; -+} -diff -ruN kozos32/extintr.c kozos33/extintr.c ---- kozos32/extintr.c Fri Jan 4 02:19:46 2008 -+++ kozos33/extintr.c Thu Jan 8 20:10:24 2009 -@@ -3,204 +3,466 @@ - #include - #include - #include --#include - #include --#include -+#include -+#include -+#include - - #include "kozos.h" - #include "thread.h" - - #define BUFFER_SIZE 1024 -+#define INTERRUPT_NUM 4 -+#define PORT 12345 - - int extintr_id; - --typedef struct _intrbuf { -- struct _intrbuf *next; -- int fd; -- int id; -- enum { -- INTR_TYPE_ACCEPT, -- INTR_TYPE_READ, -- } type; -+static int control_fd; /* 親プロセスからの制御用 */ -+ -+struct intrbuf { -+ int accept_socket; -+ int rw_socket; -+ int read_fd; /* 親プロセスからの転送用 */ -+ int write_fd; /* 親プロセスへの転送用 */ -+ int cnt_fd; /* 親プロセスからの制御用 */ - struct sockaddr addr; --} intrbuf; -+ unsigned int flags; -+#define INTRBUF_FLAG_ENABLE (1<<0) -+} intrbuf[INTERRUPT_NUM]; - --static intrbuf *interrupts; --static fd_set readfds; --static int maxfd; - static pid_t pid; - --static int intr_controller(int cnt_fd) -+static void set_readfds(int fd, int *maxfd, fd_set *fds) - { -- int fd, ret, size; -+ if (fd >= 0) { -+ FD_SET(fd, fds); -+ if (*maxfd < fd) *maxfd = fd; -+ } -+} -+ -+static void reset_readfds(int fd, int *maxfd, fd_set *fds) -+{ -+ if (fd >= 0) { -+ FD_CLR(fd, fds); -+ if ((*maxfd == fd) && (fd > 0)) *maxfd = fd - 1; -+ } -+} -+ -+static int socket_init_addr() -+{ -+ char hostname[256]; -+ struct hostent *host; -+ struct sockaddr_in address; -+ int i, port; -+ struct intrbuf *ibp; -+ -+#if 1 -+ gethostname(hostname, sizeof(hostname)); -+#else -+ strcpy(hostname, "localhost"); -+#endif -+ -+ host = gethostbyname(hostname); -+ if (host == NULL) { -+ fprintf(stderr, "gethostbyname() failed.\n"); -+ exit (-1); -+ } -+ -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ ibp = &intrbuf[i]; -+ port = PORT + i; -+ -+ memset(&address, 0, sizeof(address)); -+ address.sin_family = AF_INET; -+ address.sin_len = sizeof(address); -+ address.sin_port = htons(port); -+ memcpy(&(address.sin_addr), host->h_addr, host->h_length); -+ -+ memcpy(&ibp->addr, &address, sizeof(ibp->addr)); -+ } -+ -+ return 0; -+} -+ -+static int socket_init() -+{ -+ int i, s, ret, backlog = 5; -+ struct intrbuf *ibp; -+ -+ socket_init_addr(); -+ -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ ibp = &intrbuf[i]; -+ -+ s = socket(ibp->addr.sa_family, SOCK_STREAM, 0); -+ if (s < 0) { -+ fprintf(stderr, "socket() failed.\n"); -+ exit (-1); -+ } -+ -+ ret = bind(s, &ibp->addr, ibp->addr.sa_len); -+ if (ret < 0) { -+ fprintf(stderr, "bind() failed.\n"); -+ exit (-1); -+ } -+ -+ ret = listen(s, backlog); -+ if (ret < 0) { -+ fprintf(stderr, "listen() failed.\n"); -+ exit (-1); -+ } -+ -+ ibp->accept_socket = s; -+ } -+ -+ return 0; -+} -+ -+static int intrbuf_init() -+{ -+ int i; -+ struct intrbuf *ibp; -+ -+ control_fd = -1; -+ -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ ibp = &intrbuf[i]; -+ memset(ibp, 0, sizeof(*ibp)); -+ ibp->accept_socket = -1; -+ ibp->rw_socket = -1; -+ ibp->read_fd = -1; -+ ibp->write_fd = -1; -+ ibp->cnt_fd = -1; -+ } -+ -+ return 0; -+} -+ -+static int intr_controller() -+{ -+ int i, s, ret, size; -+ int maxfd; -+ fd_set readfds; - fd_set fds; -- char buf[32]; -- char *p; -- fd_set readfds_save; -+ char buf[128]; -+ struct intrbuf *ibp; -+ socklen_t len; -+ -+ socket_init(); -+ -+ maxfd = -1; -+ FD_ZERO(&readfds); -+ -+ set_readfds(control_fd, &maxfd, &readfds); -+ -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ ibp = &intrbuf[i]; -+ set_readfds(ibp->accept_socket, &maxfd, &readfds); -+ set_readfds(ibp->read_fd, &maxfd, &readfds); -+ set_readfds(ibp->cnt_fd, &maxfd, &readfds); -+ } - - /* - * 子プロセスなので,この中で kz_ システムコールを利用してはいけない. - */ - -- FD_SET(cnt_fd, &readfds); -- if (maxfd < cnt_fd) maxfd = cnt_fd; -- readfds_save = readfds; -- - 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")) -+ -+ if (ret < 0) { -+ /* none */ -+ } else if (ret == 0) { -+ /* none */ -+ } else { -+ if ((control_fd >= 0) && FD_ISSET(control_fd, &fds)) { -+ size = read(control_fd, buf, sizeof(buf)); -+ if (size <= 0) { -+ goto end; -+ } else { -+ for (i = 0; i < size; i++) { -+ switch (buf[i]) { -+ case 'e': - goto end; -- if (!strcmp(p, "refresh")) -- readfds = readfds_save; -+ default: -+ break; -+ } -+ } -+ } -+ } -+ -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ ibp = &intrbuf[i]; -+ -+ if ((ibp->accept_socket >= 0) && FD_ISSET(ibp->accept_socket, &fds)) { -+ len = ibp->addr.sa_len; -+ s = accept(ibp->accept_socket, &ibp->addr, &len); -+ if (s >= 0) { -+ if (ibp->rw_socket >= 0) { -+ close(s); -+ } else { -+ ibp->rw_socket = s; -+ if (ibp->flags & INTRBUF_FLAG_ENABLE) -+ set_readfds(ibp->rw_socket, &maxfd, &readfds); -+ } -+ } -+ } -+ -+ if ((ibp->rw_socket >= 0) && FD_ISSET(ibp->rw_socket, &fds)) { -+ ibp->flags &= ~INTRBUF_FLAG_ENABLE; -+ reset_readfds(ibp->rw_socket, &maxfd, &readfds); -+ size = read(ibp->rw_socket, buf, sizeof(buf)); -+ if (size <= 0) { -+ shutdown(ibp->rw_socket, SHUT_RDWR); -+ ibp->rw_socket = -1; -+ } else { -+ write(ibp->write_fd, buf, size); -+ kill(pid, SIGHUP); -+ } -+ } -+ -+ if ((ibp->read_fd >= 0) && FD_ISSET(ibp->read_fd, &fds)) { -+ size = read(ibp->read_fd, buf, sizeof(buf)); -+ if (size > 0) { -+ write(ibp->rw_socket, buf, size); -+ } -+ } -+ -+ if ((ibp->cnt_fd >= 0) && FD_ISSET(ibp->cnt_fd, &fds)) { -+ size = read(ibp->cnt_fd, buf, sizeof(buf)); -+ if (size > 0) { -+ for (i = 0; i < size; i++) { -+ switch (buf[i]) { -+ case 'e': -+ ibp->flags |= INTRBUF_FLAG_ENABLE; -+ if (ibp->rw_socket >= 0) -+ set_readfds(ibp->rw_socket, &maxfd, &readfds); -+ break; -+ -+ case 'd': -+ ibp->flags &= ~INTRBUF_FLAG_ENABLE; -+ if (ibp->rw_socket >= 0) -+ reset_readfds(ibp->rw_socket, &maxfd, &readfds); -+ break; -+ default: -+ break; -+ } -+ } - } - } -- } 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); -+ return 0; - } - --static int setintrbuf(int fd, int id, struct sockaddr *addrp) -+/* -+ * ここから下は親プロセスの処理 -+ */ -+ -+static int control_intr_fd; /* 子プロセスへの制御用 */ -+ -+struct intrreg { -+ int read_fd; /* 子プロセスからの転送用 */ -+ int write_fd; /* 子プロセスへの転送用 */ -+ int cnt_fd; /* 子プロセスへの制御用 */ -+ int id; -+} intrreg[INTERRUPT_NUM]; -+ -+static struct intrreg *intrreg_search(int id) - { -- intrbuf **ibpp; -- intrbuf *ibp; -+ int i; -+ struct intrreg *irp; - -- for (ibpp = &interrupts; *ibpp; ibpp = &((*ibpp)->next)) { -- if (((*ibpp)->fd == fd) && ((*ibpp)->id == id)) { -- FD_CLR(fd, &readfds); -- ibp = *ibpp; -- *ibpp = (*ibpp)->next; -- kz_kmfree(ibp); -- return -1; -+ if (id) { -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ irp = &intrreg[i]; -+ if (irp->id == id) return irp; - } - } - -- ibp = kz_kmalloc(sizeof(*ibp)); -- ibp->next = NULL; -- ibp->fd = fd; -- ibp->id = id; -- if (addrp) { -- ibp->type = INTR_TYPE_ACCEPT; -- memcpy(&ibp->addr, addrp, addrp->sa_len); -- } else { -- ibp->type = INTR_TYPE_READ; -- memset(&ibp->addr, 0, sizeof(ibp->addr)); -- } -+ return NULL; ++ p = kz_kmalloc(9); ++ strcpy(p, "s1;;;0;;;"); ++ kz_send(extintr_id, 9, p); +} - -- *ibpp = ibp; -+static int intrreg_init() -+{ -+ int i; -+ struct intrreg *irp; - -- FD_SET(fd, &readfds); -- if (maxfd < fd) maxfd = fd; -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ irp = &intrreg[i]; -+ irp->read_fd = -1; -+ irp->write_fd = -1; -+ irp->cnt_fd = -1; -+ irp->id = 0; -+ } - - return 0; - } - --static int cnt_fd = -1; -- --void extintr_handler(int signo) -+static void extintr_handler(int maxfd, fd_set *readfds) - { - fd_set fds; - char *buffer; -- int ret, size, s; -- socklen_t len; -+ int ret, size, i; - struct timeval tm = {0, 0}; -- intrbuf *ibp; -+ struct intrreg *irp; -+ -+ fds = *readfds; - -- 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; -- } -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ irp = &intrreg[i]; -+ if ((irp->read_fd >= 0) && FD_ISSET(irp->read_fd, &fds)) { -+ -+ /* -+ * 現状ではスレッドからハンドラが呼ばれているのでシステムコールを -+ * 呼んでも問題は無いが,割り込みハンドラにした場合には -+ * システムコールを呼ぶと問題あるかも... -+ */ -+ buffer = kz_kmalloc(BUFFER_SIZE); + -+ size = read(irp->read_fd, buffer, BUFFER_SIZE); -+ if ((size >= 0) && irp->id) -+ kz_send(irp->id, size, buffer); -+ else -+ kz_kmfree(buffer); - } - } - } -- /* -- * GDBスタブ利用の場合はスタブ側で read() されてしまい上の select() で -- * 検知できないので,子プロセスへの割り込み再開通知を毎回行う. -- */ -- write(cnt_fd, "refresh", 8); -+ -+ return; - } - --int extintr_main(int argc, char *argv[]) -+static int extintr_mainloop() + int clock_main(int argc, char *argv[]) { -+ int i, size, id; + time_t t; char *p; -- int fd, id; -- int fildes[2]; -- pid_t chld_pid = 0; -+ char c; -+ struct intrreg *irp; -+ int maxfd; -+ fd_set readfds; - -+ maxfd = -1; - FD_ZERO(&readfds); -- maxfd = 0; - -- pid = getpid(); -- kz_sethandler(SIGHUP, extintr_handler); -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ irp = &intrreg[i]; -+ set_readfds(irp->read_fd, &maxfd, &readfds); -+ } - while (1) { -- fd = kz_recv(&id, &p); -- 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) { /* 子プロセス */ -- /* -- * 子プロセスはシグナル設定を引き継ぐらしいので,シグナル無効にする. -- * (man sigaction に以下の記述あり) -- * After a fork(2) or vfork(2) all signals, the signal mask, the signal -- * stack, and the restart/interrupt flags are inherited by the child. -- */ -- sigprocmask(SIG_BLOCK, &block, NULL); -- close(fildes[1]); -- intr_controller(fildes[0]); -+ size = kz_recv(&id, &p); -+ -+ if (!id) { -+ /* 子プロセスからの割り込み通知 */ -+ extintr_handler(maxfd, &readfds); -+ } else { -+ switch (p[0]) { -+ case 'u': /* コンソールの利用 */ -+ irp = &intrreg[p[1] - '0']; -+ irp->id = id; -+ break; -+ -+ case 'e': /* 割り込み有効化 */ -+ case 'd': /* 割り込み無効化 */ -+ irp = intrreg_search(id); -+ c = p[0]; -+ write(irp->cnt_fd, &c, 1); -+ break; -+ -+ case 'w': /* 出力 */ -+ write(irp->write_fd, &p[1], size - 1); -+ break; -+ -+ default: -+ break; - } -- close(fildes[0]); -- cnt_fd = fildes[1]; -+ -+ kz_kmfree(p); -+ } -+ } -+ -+ return 0; -+} -+ -+int extintr_main(int argc, char *argv[]) -+{ -+ int i; -+ int cnt_fildes[2]; -+ int intr_r_fildes[INTERRUPT_NUM][2]; -+ int intr_w_fildes[INTERRUPT_NUM][2]; -+ int intr_cnt_fildes[INTERRUPT_NUM][2]; -+ struct intrbuf *ibp; -+ struct intrreg *irp; -+ -+ pid = getpid(); -+ -+ pipe(cnt_fildes); -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ pipe(intr_r_fildes[i]); -+ pipe(intr_w_fildes[i]); -+ pipe(intr_cnt_fildes[i]); -+ } -+ -+ if (fork() == 0) { /* 子プロセス */ -+ /* -+ * 子プロセスはシグナル設定を引き継ぐらしいので,シグナル無効にする. -+ * (man sigaction に以下の記述あり) -+ * After a fork(2) or vfork(2) all signals, the signal mask, the signal -+ * stack, and the restart/interrupt flags are inherited by the child. -+ */ -+ sigprocmask(SIG_BLOCK, &block, NULL); -+ -+ intrbuf_init(); -+ -+ close(cnt_fildes[1]); /* 書き込み端 */ -+ control_fd = cnt_fildes[0]; /* 読み込み端 */ -+ -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ ibp = &intrbuf[i]; -+ -+ close(intr_r_fildes[i][0]); /* 読み込み端 */ -+ ibp->write_fd = intr_r_fildes[i][1]; /* 書き込み端 */ -+ -+ close(intr_w_fildes[i][1]); /* 書き込み端 */ -+ ibp->read_fd = intr_w_fildes[i][0]; /* 読み込み端 */ -+ -+ close(intr_cnt_fildes[i][1]); /* 書き込み端 */ -+ ibp->cnt_fd = intr_cnt_fildes[i][0]; /* 読み込み端 */ - } -+ -+ intr_controller(); -+ -+ exit(0); -+ } -+ -+ /* 親プロセス */ -+ -+ intrreg_init(); -+ -+ close(cnt_fildes[0]); /* 読み込み端 */ -+ control_intr_fd = cnt_fildes[1]; /* 書き込み端 */ -+ -+ kz_setsig(SIGHUP); -+ -+ for (i = 0; i < INTERRUPT_NUM; i++) { -+ irp = &intrreg[i]; -+ -+ close(intr_r_fildes[i][1]); /* 書き込み端 */ -+ irp->read_fd = intr_r_fildes[i][0]; /* 読み込み端 */ -+ -+ close(intr_w_fildes[i][0]); /* 読み込み端 */ -+ irp->write_fd = intr_w_fildes[i][1]; /* 書き込み端 */ -+ -+ close(intr_cnt_fildes[i][0]); /* 読み込み端 */ -+ irp->cnt_fd = intr_cnt_fildes[i][1]; /* 書き込み端 */ - } -+ -+ extintr_mainloop(); ++ send_use(0); + -+ return 0; - } -diff -ruN kozos32/kozos.h kozos33/kozos.h ---- kozos32/kozos.h Fri Jan 4 02:19:46 2008 -+++ kozos33/kozos.h Mon Jan 5 22:28:41 2009 -@@ -46,10 +46,8 @@ - - /* user thread */ - extern int clock_id; --extern int telnetd_id; --extern int httpd_id; -+extern int command_id; - int clock_main(int argc, char *argv[]); --int telnetd_main(int argc, char *argv[]); --int httpd_main(int argc, char *argv[]); -+int command_main(int argc, char *argv[]); - - #endif -diff -ruN kozos32/main.c kozos33/main.c ---- kozos32/main.c Fri Jan 4 02:19:46 2008 -+++ kozos33/main.c Thu Jan 8 00:38:18 2009 -@@ -6,12 +6,13 @@ - int mainfunc(int argc, char *argv[]) - { - extintr_id = kz_run(extintr_main, "extintr", 1, 0, NULL); -+#if 0 - stubd_id = kz_run(stubd_main, "stubd", 2, 0, NULL); -+#endif - outlog_id = kz_run(outlog_main, "outlog", 3, 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); -+ command_id = kz_run(command_main, "command", 8, 0, NULL); + while (1) { +- kz_timer(1000); ++ send_enable(); + kz_recv(NULL, NULL); - return 0; - } + t = time(NULL); diff -ruN kozos33/extintr.c kozos34/extintr.c --- kozos33/extintr.c Thu Jan 8 20:10:24 2009 +++ kozos34/extintr.c Sun Jan 18 23:55:47 2009 @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -12,6 +13,7 @@ #include "thread.h" #define BUFFER_SIZE 1024 +#define TIMER_NUM 4 #define INTERRUPT_NUM 4 #define PORT 12345 @@ -19,6 +21,16 @@ static int control_fd; /* 親プロセスからの制御用 */ +struct timerbuf { + struct timeval tm; + int write_fd; /* 親プロセスへの転送用 */ + int cnt_fd; /* 親プロセスからの制御用 */ + unsigned int flags; +#define TIMERBUF_FLAG_ENABLE (1<<0) +#define TIMERBUF_FLAG_MASKED (1<<1) +#define TIMERBUF_FLAG_EXPIRED (1<<2) +} timerbuf[TIMER_NUM]; + struct intrbuf { int accept_socket; int rw_socket; @@ -32,6 +44,87 @@ static pid_t pid; +static int timecmp(struct timeval *tm1, struct timeval *tm2) +{ + if (tm1->tv_sec > tm2->tv_sec ) return 1; + if (tm1->tv_sec < tm2->tv_sec ) return -1; + if (tm1->tv_usec > tm2->tv_usec) return 1; + if (tm1->tv_usec < tm2->tv_usec) return -1; + return 0; +} + +static int timeadd(struct timeval *add, struct timeval *tm1, struct timeval *tm2) +{ + add->tv_sec = tm1->tv_sec + tm2->tv_sec; + add->tv_usec = tm1->tv_usec + tm2->tv_usec; + while (add->tv_usec >= 1000000) { + add->tv_sec++; + add->tv_usec -= 1000000; + } + return 0; +} + +static int timesub(struct timeval *sub, struct timeval *tm1, struct timeval *tm2) +{ + int s = 0; + if (tm1->tv_usec < tm2->tv_usec) s = 1; + sub->tv_sec = -s + tm1->tv_sec - tm2->tv_sec; + sub->tv_usec = s * 1000000 + tm1->tv_usec - tm2->tv_usec; + return 0; +} + +static int check_timer(struct timeval *now) +{ + int i; + struct timerbuf *tbp; + for (i = 0; i < TIMER_NUM; i++) { + tbp = &timerbuf[i]; + if (!(tbp->flags & TIMERBUF_FLAG_ENABLE)) + continue; + if (tbp->flags & TIMERBUF_FLAG_EXPIRED) + continue; + if (timecmp(now, &tbp->tm) >= 0) { + tbp->flags |= TIMERBUF_FLAG_EXPIRED; + } + } + return 0; +} + +static int expire_timer() +{ + int i; + struct timerbuf *tbp; + for (i = 0; i < TIMER_NUM; i++) { + tbp = &timerbuf[i]; + if (!(tbp->flags & TIMERBUF_FLAG_ENABLE)) + continue; + if ((tbp->flags & TIMERBUF_FLAG_EXPIRED) && + !(tbp->flags & TIMERBUF_FLAG_MASKED)) { + write(tbp->write_fd, "e", 1); + kill(pid, SIGHUP); + tbp->flags &= ~(TIMERBUF_FLAG_ENABLE | TIMERBUF_FLAG_EXPIRED); + } + } + return 0; +} + +static struct timerbuf *search_recent_timer() +{ + int i; + struct timerbuf *tbp; + struct timerbuf *recent_timer = NULL; + for (i = 0; i < TIMER_NUM; i++) { + tbp = &timerbuf[i]; + if (!(tbp->flags & TIMERBUF_FLAG_ENABLE)) + continue; + if (tbp->flags & TIMERBUF_FLAG_EXPIRED) + continue; + if (!recent_timer || (timecmp(&recent_timer->tm, &tbp->tm) > 0)) + recent_timer = tbp; + } + return recent_timer; +} + static void set_readfds(int fd, int *maxfd, fd_set *fds) { if (fd >= 0) { @@ -118,13 +211,26 @@ return 0; } +static int timerbuf_init() +{ + int i; + struct timerbuf *tbp; + + for (i = 0; i < TIMER_NUM; i++) { + tbp = &timerbuf[i]; + memset(tbp, 0, sizeof(*tbp)); + tbp->write_fd = -1; + tbp->cnt_fd = -1; + } + + return 0; +} + static int intrbuf_init() { int i; struct intrbuf *ibp; - control_fd = -1; - for (i = 0; i < INTERRUPT_NUM; i++) { ibp = &intrbuf[i]; memset(ibp, 0, sizeof(*ibp)); @@ -138,6 +244,14 @@ return 0; } +static int controller_init() +{ + control_fd = -1; + timerbuf_init(); + intrbuf_init(); + return 0; +} + static int intr_controller() { int i, s, ret, size; @@ -145,8 +259,12 @@ fd_set readfds; fd_set fds; char buf[128]; + struct timerbuf *tbp; struct intrbuf *ibp; socklen_t len; + struct timeval now, tm; + struct timeval *tp; + struct timerbuf *recent_timer; socket_init(); @@ -155,6 +273,11 @@ set_readfds(control_fd, &maxfd, &readfds); + for (i = 0; i < TIMER_NUM; i++) { + tbp = &timerbuf[i]; + set_readfds(tbp->cnt_fd, &maxfd, &readfds); + } + for (i = 0; i < INTERRUPT_NUM; i++) { ibp = &intrbuf[i]; set_readfds(ibp->accept_socket, &maxfd, &readfds); @@ -167,13 +290,26 @@ */ while (1) { + gettimeofday(&now, NULL); + + check_timer(&now); + expire_timer(); + + recent_timer = search_recent_timer(); + if (!recent_timer) { + tp = NULL; + } else { + timesub(&tm, &recent_timer->tm, &now); + tp = &tm; + } + fds = readfds; - ret = select(maxfd + 1, &fds, NULL, NULL, NULL); + ret = select(maxfd + 1, &fds, NULL, NULL, tp); if (ret < 0) { /* none */ } else if (ret == 0) { - /* none */ + continue; } else { if ((control_fd >= 0) && FD_ISSET(control_fd, &fds)) { size = read(control_fd, buf, sizeof(buf)); @@ -191,6 +327,34 @@ } } + for (i = 0; i < TIMER_NUM; i++) { + tbp = &timerbuf[i]; + + if ((tbp->cnt_fd >= 0) && FD_ISSET(tbp->cnt_fd, &fds)) { + size = read(tbp->cnt_fd, buf, sizeof(buf)); + if (size > 0) { + for (i = 0; i < size; i++) { + switch (buf[i]) { + case 's': + tbp->flags |= INTRBUF_FLAG_ENABLE; + tbp->tm.tv_sec = strtol(&buf[1], NULL, 0); + tbp->tm.tv_usec = strtol(&buf[5], NULL, 0); + timeadd(&tbp->tm, &now, &tbp->tm); + i += 8; + break; + + case 'm': + tbp->flags |= TIMERBUF_FLAG_MASKED; + break; + + default: + break; + } + } + } + } + } + for (i = 0; i < INTERRUPT_NUM; i++) { ibp = &intrbuf[i]; @@ -264,6 +428,12 @@ static int control_intr_fd; /* 子プロセスへの制御用 */ +struct timerreg { + int read_fd; /* 子プロセスからの転送用 */ + int cnt_fd; /* 子プロセスへの制御用 */ + int id; +} timerreg[TIMER_NUM]; + struct intrreg { int read_fd; /* 子プロセスからの転送用 */ int write_fd; /* 子プロセスへの転送用 */ @@ -271,6 +441,21 @@ int id; } intrreg[INTERRUPT_NUM]; +static struct timerreg *timerreg_search(int id) +{ + int i; + struct timerreg *trp; + + if (id) { + for (i = 0; i < TIMER_NUM; i++) { + trp = &timerreg[i]; + if (trp->id == id) return trp; + } + } + + return NULL; +} + static struct intrreg *intrreg_search(int id) { int i; @@ -286,6 +471,21 @@ return NULL; } +static int timerreg_init() +{ + int i; + struct timerreg *trp; + + for (i = 0; i < TIMER_NUM; i++) { + trp = &timerreg[i]; + memset(trp, 0, sizeof(*trp)); + trp->read_fd = -1; + trp->cnt_fd = -1; + } + + return 0; +} + static int intrreg_init() { int i; @@ -293,6 +493,7 @@ for (i = 0; i < INTERRUPT_NUM; i++) { irp = &intrreg[i]; + memset(irp, 0, sizeof(*irp)); irp->read_fd = -1; irp->write_fd = -1; irp->cnt_fd = -1; @@ -302,18 +503,35 @@ return 0; } +static int extintr_init() +{ + timerreg_init(); + intrreg_init(); + return 0; +} + static void extintr_handler(int maxfd, fd_set *readfds) { fd_set fds; char *buffer; int ret, size, i; + char c; struct timeval tm = {0, 0}; + struct timerreg *trp; struct intrreg *irp; fds = *readfds; ret = select(maxfd + 1, &fds, NULL, NULL, &tm); if (ret > 0) { + for (i = 0; i < TIMER_NUM; i++) { + trp = &timerreg[i]; + if ((trp->read_fd >= 0) && FD_ISSET(trp->read_fd, &fds)) { + size = read(trp->read_fd, &c, 1); + if ((size >= 0) && trp->id) + kz_send(trp->id, 0, NULL); + } + } for (i = 0; i < INTERRUPT_NUM; i++) { irp = &intrreg[i]; if ((irp->read_fd >= 0) && FD_ISSET(irp->read_fd, &fds)) { @@ -341,7 +559,7 @@ { int i, size, id; char *p; - char c; + struct timerreg *trp; struct intrreg *irp; int maxfd; fd_set readfds; @@ -349,6 +567,10 @@ maxfd = -1; FD_ZERO(&readfds); + for (i = 0; i < TIMER_NUM; i++) { + trp = &timerreg[i]; + set_readfds(trp->read_fd, &maxfd, &readfds); + } for (i = 0; i < INTERRUPT_NUM; i++) { irp = &intrreg[i]; set_readfds(irp->read_fd, &maxfd, &readfds); @@ -362,19 +584,34 @@ extintr_handler(maxfd, &readfds); } else { switch (p[0]) { + case 't': /* タイマの利用 */ + trp = &timerreg[p[1] - '0']; + trp->id = id; + break; + + case 's': /* タイマ起動 */ + trp = timerreg_search(id); + write(trp->cnt_fd, &p[0], 9); + break; + + case 'm': /* タイマ割り込みのマスク */ + trp = timerreg_search(id); + write(trp->cnt_fd, &p[0], 1); + break; + case 'u': /* コンソールの利用 */ irp = &intrreg[p[1] - '0']; irp->id = id; break; - case 'e': /* 割り込み有効化 */ - case 'd': /* 割り込み無効化 */ + case 'e': /* コンソール割り込み有効化 */ + case 'd': /* コンソール割り込み無効化 */ irp = intrreg_search(id); - c = p[0]; - write(irp->cnt_fd, &c, 1); + write(irp->cnt_fd, &p[0], 1); break; case 'w': /* 出力 */ + irp = intrreg_search(id); write(irp->write_fd, &p[1], size - 1); break; @@ -393,15 +630,23 @@ { int i; int cnt_fildes[2]; + int timer_r_fildes[TIMER_NUM][2]; + int timer_cnt_fildes[TIMER_NUM][2]; int intr_r_fildes[INTERRUPT_NUM][2]; int intr_w_fildes[INTERRUPT_NUM][2]; int intr_cnt_fildes[INTERRUPT_NUM][2]; + struct timerbuf *tbp; + struct timerreg *trp; struct intrbuf *ibp; struct intrreg *irp; pid = getpid(); pipe(cnt_fildes); + for (i = 0; i < TIMER_NUM; i++) { + pipe(timer_r_fildes[i]); + pipe(timer_cnt_fildes[i]); + } for (i = 0; i < INTERRUPT_NUM; i++) { pipe(intr_r_fildes[i]); pipe(intr_w_fildes[i]); @@ -417,11 +662,21 @@ */ sigprocmask(SIG_BLOCK, &block, NULL); - intrbuf_init(); + controller_init(); close(cnt_fildes[1]); /* 書き込み端 */ control_fd = cnt_fildes[0]; /* 読み込み端 */ + for (i = 0; i < TIMER_NUM; i++) { + tbp = &timerbuf[i]; + + close(timer_r_fildes[i][0]); /* 読み込み端 */ + tbp->write_fd = timer_r_fildes[i][1]; /* 書き込み端 */ + + close(timer_cnt_fildes[i][1]); /* 書き込み端 */ + tbp->cnt_fd = timer_cnt_fildes[i][0]; /* 読み込み端 */ + } + for (i = 0; i < INTERRUPT_NUM; i++) { ibp = &intrbuf[i]; @@ -442,12 +697,22 @@ /* 親プロセス */ - intrreg_init(); + extintr_init(); close(cnt_fildes[0]); /* 読み込み端 */ control_intr_fd = cnt_fildes[1]; /* 書き込み端 */ kz_setsig(SIGHUP); + + for (i = 0; i < TIMER_NUM; i++) { + trp = &timerreg[i]; + + close(timer_r_fildes[i][1]); /* 書き込み端 */ + trp->read_fd = timer_r_fildes[i][0]; /* 読み込み端 */ + + close(timer_cnt_fildes[i][0]); /* 読み込み端 */ + trp->cnt_fd = timer_cnt_fildes[i][1]; /* 書き込み端 */ + } for (i = 0; i < INTERRUPT_NUM; i++) { irp = &intrreg[i];