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; +} + +static void send_use(int num) +{ + char *p; + p = kz_kmalloc(2); + p[0] = 'u'; + p[1] = '0' + num; + kz_send(extintr_id, 2, p); +} + +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; +} - *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 i, size, id; 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(); + + 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); return 0; }