diff -ruN -U 10 kozos06/Makefile kozos07/Makefile --- kozos06/Makefile Tue Oct 23 22:04:34 2007 +++ kozos07/Makefile Tue Oct 23 22:04:34 2007 @@ -1,11 +1,12 @@ -OBJS += thread.o syscall.o outlog.o main.o +OBJS += thread.o syscall.o outlog.o extintr.o +OBJS += main.o clock.o telnetd.o httpd.o TARGET ?= koz CC ?= gcc CFLAGS = #CFLAGS += -O CFLAGS += -g CFLAGS += -Wall CFLAGS += -static .SUFFIXES: .c .o diff -ruN -U 10 kozos06/clock.c kozos07/clock.c --- kozos06/clock.c Thu Jan 1 09:00:00 1970 +++ kozos07/clock.c Tue Oct 23 22:04:34 2007 @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +#include "kozos.h" + +int clock_id; + +int clock_main(int argc, char *argv[]) +{ + time_t t; + char *p; + + while (1) { + kz_timer(1000); + kz_recv(NULL, NULL); + + t = time(NULL); + p = kz_memalloc(128); + strcpy(p, ctime(&t)); + kz_send(outlog_id, 0, p); + } +} diff -ruN -U 10 kozos06/extintr.c kozos07/extintr.c --- kozos06/extintr.c Thu Jan 1 09:00:00 1970 +++ kozos07/extintr.c Tue Oct 23 22:04:34 2007 @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include + +#include "kozos.h" + +#define BUFFER_SIZE 2048 + +int extintr_id; + +typedef struct _intrbuf { + struct _intrbuf *next; + int fd; + int id; + enum { + INTR_TYPE_ACCEPT, + INTR_TYPE_READ, + } type; + struct sockaddr addr; +} intrbuf; + +static intrbuf *interrupts; +static fd_set readfds; +static int maxfd; + +static int setintrbuf(int fd, int id, struct sockaddr *addrp) +{ + intrbuf **ibpp; + intrbuf *ibp; + + for (ibpp = &interrupts; *ibpp; ibpp = &((*ibpp)->next)) { + if (((*ibpp)->fd == fd) && ((*ibpp)->id == id)) { + FD_CLR(fd, &readfds); + ibp = *ibpp; + *ibpp = (*ibpp)->next; + kz_memfree(ibp); + return -1; + } + } + + ibp = kz_memalloc(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)); + } + + *ibpp = ibp; + + FD_SET(fd, &readfds); + if (maxfd < fd) maxfd = fd; + + return 0; +} + +int extintr_main(int argc, char *argv[]) +{ + fd_set fds; + char *p, *buffer; + int fd, id, ret, size, s, len; + intrbuf *ibp; + + 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); + } + } + + 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; + } + } + } + } + } +} diff -ruN -U 10 kozos06/httpd.c kozos07/httpd.c --- kozos06/httpd.c Thu Jan 1 09:00:00 1970 +++ kozos07/httpd.c Tue Oct 23 22:04:34 2007 @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "kozos.h" + +#define PORT 30001 + +int httpd_id; + +static char mes[] = +"\n" +"\n" +"hello\n" +"\n" +"

KOZOS

\n" +"

This is HTTP server running on KOZO-OS.

\n" +"\n"; + +static int http_proc(int s, char *argv[]) +{ + char *p; + char buffer[1024]; + int len, size; + + kz_send(extintr_id, s, NULL); + + len = 0; + + do { + size = kz_recv(NULL, &p); + if (len + size >= sizeof(buffer)) { + break; + } + memcpy(buffer + len, p, size); + kz_memfree(p); + len += size; + buffer[len] = '\0'; + } while (strchr(buffer, '\n') == NULL); + + write(s, mes, sizeof(mes)); + + kz_send(extintr_id, s, NULL); + close(s); + + return 0; +} + +int httpd_main(int argc, char *argv[]) +{ + int sockt, s, ret; + char hostname[256]; + struct hostent *host; + struct sockaddr_in address; + int backlog = 5; + +#if 1 + gethostname(hostname, sizeof(hostname)); +#else + strcpy(hostname, "localhost"); +#endif + + host = gethostbyname(hostname); + if (host == NULL) { + fprintf(stderr, "gethostbyname() failed.\n"); + exit (-1); + } + + 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); + + sockt = socket(AF_INET, SOCK_STREAM, 0); + if (sockt < 0) { + fprintf(stderr, "socket() failed.\n"); + exit (-1); + } + + ret = bind(sockt, (struct sockaddr *)&address, sizeof(address)); + if (ret < 0) { + fprintf(stderr, "bind() failed.\n"); + exit (-1); + } + + ret = listen(sockt, backlog); + if (ret < 0) { + fprintf(stderr, "listen() failed.\n"); + exit (-1); + } + + kz_send(extintr_id, sockt, (char *)&address); + + while (1) { + s = kz_recv(NULL, NULL); + kz_run(http_proc, "httpproc", 7, s, NULL); + } + + close(sockt); + + return 0; +} diff -ruN -U 10 kozos06/kozos.h kozos07/kozos.h --- kozos06/kozos.h Tue Oct 23 22:04:34 2007 +++ kozos07/kozos.h Tue Oct 23 22:04:34 2007 @@ -9,21 +9,32 @@ int kz_run(kz_func func, char *name, int pri, int argc, char *argv[]); void kz_exit(); int kz_wait(); int kz_sleep(); int kz_wakeup(int id); int kz_getid(); int kz_chpri(int pri); int kz_send(int id, int size, char *p); int kz_recv(int *idp, char **pp); int kz_timer(int msec); +int kz_pending(); void *kz_memalloc(int size); int kz_memfree(void *p); /* library */ void kz_start(kz_func func, char *name, int pri, int argc, char *argv[]); /* general thread */ extern int outlog_id; +extern int extintr_id; int outlog_main(int argc, char *argv[]); +int extintr_main(int argc, char *argv[]); + +/* user thread */ +extern int clock_id; +extern int telnetd_id; +extern int httpd_id; +int clock_main(int argc, char *argv[]); +int telnetd_main(int argc, char *argv[]); +int httpd_main(int argc, char *argv[]); #endif diff -ruN -U 10 kozos06/syscall.c kozos07/syscall.c --- kozos06/syscall.c Tue Oct 23 22:04:34 2007 +++ kozos07/syscall.c Tue Oct 23 22:04:34 2007 @@ -90,20 +90,27 @@ } int kz_timer(int msec) { kz_syscall_param_t param; param.un.timer.msec = msec; kz_syscall(KZ_SYSCALL_TYPE_TIMER, ¶m); return param.un.timer.ret; } +int kz_pending() +{ + kz_syscall_param_t param; + kz_syscall(KZ_SYSCALL_TYPE_PENDING, ¶m); + return param.un.pending.ret; +} + void *kz_memalloc(int size) { kz_syscall_param_t param; param.un.memalloc.size = size; kz_syscall(KZ_SYSCALL_TYPE_MEMALLOC, ¶m); return param.un.memalloc.ret; } int kz_memfree(void *p) { diff -ruN -U 10 kozos06/syscall.h kozos07/syscall.h --- kozos06/syscall.h Tue Oct 23 22:04:34 2007 +++ kozos07/syscall.h Tue Oct 23 22:04:34 2007 @@ -7,20 +7,21 @@ KZ_SYSCALL_TYPE_RUN, KZ_SYSCALL_TYPE_EXIT, KZ_SYSCALL_TYPE_WAIT, KZ_SYSCALL_TYPE_SLEEP, KZ_SYSCALL_TYPE_WAKEUP, KZ_SYSCALL_TYPE_GETID, KZ_SYSCALL_TYPE_CHPRI, KZ_SYSCALL_TYPE_SEND, KZ_SYSCALL_TYPE_RECV, KZ_SYSCALL_TYPE_TIMER, + KZ_SYSCALL_TYPE_PENDING, KZ_SYSCALL_TYPE_MEMALLOC, KZ_SYSCALL_TYPE_MEMFREE, } kz_syscall_type_t; typedef struct { union { struct { kz_func func; char *name; int pri; @@ -56,20 +57,23 @@ } send; struct { int *idp; char **pp; int ret; } recv; struct { int msec; int ret; } timer; + struct { + int ret; + } pending; struct { int size; void *ret; } memalloc; struct { char *p; int ret; } memfree; } un; } kz_syscall_param_t; diff -ruN -U 10 kozos06/telnetd.c kozos07/telnetd.c --- kozos06/telnetd.c Thu Jan 1 09:00:00 1970 +++ kozos07/telnetd.c Tue Oct 23 22:04:34 2007 @@ -0,0 +1,122 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kozos.h" +#include "thread.h" + +#define PORT 20001 + +int telnetd_id; + +static int command_main(int s, char *argv[]) +{ + char *p; + char buffer[128]; + int len, size; + + kz_send(extintr_id, s, NULL); + + len = 0; + write(s, "> ", 2); + + while (1) { + size = kz_recv(NULL, &p); + memcpy(buffer + len, p, size); + kz_memfree(p); + len += size; + buffer[len] = '\0'; + + p = strchr(buffer, '\n'); + if (p == NULL) continue; + + if (!strncmp(buffer, "echo", 4)) { + write(s, buffer + 4, strlen(buffer + 4)); + } else if (!strncmp(buffer, "date", 4)) { + time_t t; + t = time(NULL); + strcpy(buffer, ctime(&t)); + write(s, buffer, strlen(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) break; + write(s, thp->name, strlen(thp->name)); + write(s, "\n", 1); + } + } else if (!strncmp(buffer, "exit", 4)) { + break; + } + + len = 0; + write(s, "OK\n> ", 5); + } + + kz_send(extintr_id, s, NULL); + close(s); + + return 0; +} + +int telnetd_main(int argc, char *argv[]) +{ + int sockt, s, ret; + char hostname[256]; + struct hostent *host; + struct sockaddr_in address; + int backlog = 5; + +#if 1 + gethostname(hostname, sizeof(hostname)); +#else + strcpy(hostname, "localhost"); +#endif + + host = gethostbyname(hostname); + if (host == NULL) { + fprintf(stderr, "gethostbyname() failed.\n"); + exit (-1); + } + + 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); + + sockt = socket(AF_INET, SOCK_STREAM, 0); + if (sockt < 0) { + fprintf(stderr, "socket() failed.\n"); + exit (-1); + } + + ret = bind(sockt, (struct sockaddr *)&address, sizeof(address)); + if (ret < 0) { + fprintf(stderr, "bind() failed.\n"); + exit (-1); + } + + ret = listen(sockt, backlog); + if (ret < 0) { + fprintf(stderr, "listen() failed.\n"); + exit (-1); + } + + kz_send(extintr_id, sockt, (char *)&address); + + while (1) { + s = kz_recv(NULL, NULL); + kz_run(command_main, "command", 7, s, NULL); + } + + close(sockt); + + return 0; +} diff -ruN -U 10 kozos06/thread.c kozos07/thread.c --- kozos06/thread.c Tue Oct 23 22:04:34 2007 +++ kozos07/thread.c Tue Oct 23 22:04:34 2007 @@ -271,20 +271,26 @@ sendmsg(timers->thp, 0, 0, NULL); tmp = timers; timers = timers->next; free(tmp); if (timers) { gettimeofday(&alarm_tm, NULL); ualarm(timers->msec * 1000, 0); } } +static int thread_pending() +{ + putcurrent(); + return current->messages ? 1 : 0; +} + static void *thread_memalloc(int size) { putcurrent(); return malloc(size); } static int thread_memfree(char *p) { free(p); putcurrent(); @@ -323,20 +329,23 @@ p->un.chpri.ret = thread_chpri(p->un.chpri.pri); break; case KZ_SYSCALL_TYPE_SEND: p->un.send.ret = thread_send(p->un.send.id, p->un.send.size, p->un.send.p); break; case KZ_SYSCALL_TYPE_RECV: p->un.recv.ret = thread_recv(p->un.recv.idp, p->un.recv.pp); break; case KZ_SYSCALL_TYPE_TIMER: p->un.timer.ret = thread_timer(p->un.timer.msec); + break; + case KZ_SYSCALL_TYPE_PENDING: + p->un.pending.ret = thread_pending(); break; case KZ_SYSCALL_TYPE_MEMALLOC: p->un.memalloc.ret = thread_memalloc(p->un.memalloc.size); break; case KZ_SYSCALL_TYPE_MEMFREE: p->un.memfree.ret = thread_memfree(p->un.memfree.p); break; default: break; } diff -ruN -U 10 kozos06/thread.h kozos07/thread.h --- kozos06/thread.h Tue Oct 23 22:04:34 2007 +++ kozos07/thread.h Tue Oct 23 22:04:34 2007 @@ -32,13 +32,14 @@ kz_syscall_param_t *param; } syscall; kz_membuf *messages; struct { jmp_buf env; } context; } kz_thread; +extern kz_thread threads[THREAD_NUM]; extern kz_thread *current; #endif