diff --git a/arch/amd64/syscall.c b/arch/amd64/syscall.c index db7d8ca..819ecab 100644 --- a/arch/amd64/syscall.c +++ b/arch/amd64/syscall.c @@ -25,6 +25,7 @@ void *syscall_table[256] = { [SYSCALL_NR_LSEEK] = sys_lseek, [SYSCALL_NR_IOCTL] = sys_ioctl, [SYSCALL_NR_ACCESS] = sys_access, + [SYSCALL_NR_SELECT] = sys_select, [SYSCALL_NR_GETCWD] = sys_getcwd, [SYSCALL_NR_CHDIR] = sys_chdir, [SYSCALL_NR_MKDIR] = sys_mkdir, diff --git a/etc/make/conf.mk b/etc/make/conf.mk index 40a6a57..4aeeff3 100644 --- a/etc/make/conf.mk +++ b/etc/make/conf.mk @@ -56,7 +56,8 @@ OBJS+=$(O)/sys/debug.o \ $(O)/sys/init.o \ $(O)/sys/font/logo.o \ $(O)/sys/font/psf.o \ - $(O)/sys/font/default8x16.o + $(O)/sys/font/default8x16.o \ + $(O)/sys/list.o DIRS+=$(O)/sys \ $(O)/sys/char \ $(O)/sys/block \ diff --git a/include/sys/list.h b/include/sys/list.h new file mode 100644 index 0000000..0a54d25 --- /dev/null +++ b/include/sys/list.h @@ -0,0 +1,28 @@ +#pragma once + +struct list_link { + struct list_link *prev, *next; +}; + +struct list { + struct list_link *begin, *end; +}; + +#define LIST_HEAD(name) \ + struct list name = { NULL, NULL } + +#define list_foreach(head, iter) \ + for (struct list_link *iter = (head)->begin; iter; iter = iter->next) + +#define list_link_value(link, type, member) ({ \ + const typeof (((type *) 0)->member) *__memb = (link); \ + (type *) ((char *) __memb - offsetof(type, member)); \ + }) + +#define list_link_init(link) ({ \ + (link)->prev = NULL; \ + (link)->next = NULL; \ + }) + +void list_append(struct list *list, struct list_link *ptr); +void list_remove(struct list *list, struct list_link *ptr); diff --git a/include/sys/spin.h b/include/sys/spin.h index f600a30..1ed917d 100644 --- a/include/sys/spin.h +++ b/include/sys/spin.h @@ -5,14 +5,7 @@ #include "arch/amd64/sys/spin.h" #endif -#if defined(AMD64_SMP) void spin_lock(spin_t *s); void spin_release(spin_t *s); void spin_lock_irqsave(spin_t *s, uintptr_t *irq); void spin_release_irqrestore(spin_t *s, uintptr_t *irq); -#else -#define spin_lock(s) -#define spin_release(s) -#define spin_lock_irqsave(s, i) -#define spin_release_irqrestore(s, i) -#endif diff --git a/include/sys/sys_file.h b/include/sys/sys_file.h index 180823f..4d0ebd9 100644 --- a/include/sys/sys_file.h +++ b/include/sys/sys_file.h @@ -1,4 +1,5 @@ #pragma once +#include "user/select.h" #include "sys/types.h" ssize_t sys_read(int fd, void *data, size_t lim); @@ -17,6 +18,7 @@ int sys_open(const char *filename, int flags, int mode); void sys_close(int fd); int sys_stat(const char *filename, struct stat *st); int sys_access(const char *path, int mode); +int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *excp, struct timeval *tv); int sys_chmod(const char *path, mode_t mode); int sys_chown(const char *path, uid_t uid, gid_t gid); off_t sys_lseek(int fd, off_t offset, int whence); diff --git a/include/sys/thread.h b/include/sys/thread.h index 3bc4ba5..1b99249 100644 --- a/include/sys/thread.h +++ b/include/sys/thread.h @@ -2,6 +2,7 @@ #if defined(ARCH_AMD64) #include "arch/amd64/asm/asm_thread.h" #endif +#include "sys/list.h" #include "fs/vfs.h" #include "sys/mm.h" @@ -59,11 +60,11 @@ struct thread { int exit_status; // Global thread list (for stuff like finding by PID) - struct thread *g_prev, *g_next; + struct list_link g_link; // Scheduler int cpu; - struct thread *prev, *next; + struct thread *sched_prev, *sched_next; }; pid_t thread_alloc_pid(int is_user); diff --git a/include/user/select.h b/include/user/select.h new file mode 100644 index 0000000..a238891 --- /dev/null +++ b/include/user/select.h @@ -0,0 +1,26 @@ +#pragma once + +struct timeval; + +// 64 bits +typedef long int __fd_mask; + +#define __NFDBITS (8 * (int) sizeof(__fd_mask)) +// TODO: Guess this should be the same as the maximum +// per-process filedes count +#define __FD_SETSIZE 64 + +typedef struct { + __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; +} fd_set; + +#define FD_SET(fd, fds) \ + (fds)->fds_bits[(fd) / __NFDBITS] |= (1ULL << ((fd) % __NFDBITS)) + +#define FD_ISSET(fd, fds) \ + (!!((fds)->fds_bits[(fd) / __NFDBITS] & (1ULL << ((fd) % __NFDBITS)))) + +#define FD_ZERO(fds) \ + for (int __i = 0; __i < (__FD_SETSIZE / __NFDBITS); ++__i) \ + (fds)->fds_bits[__i] = 0 + diff --git a/include/user/syscall.h b/include/user/syscall.h index 2babe9a..2cb57bf 100644 --- a/include/user/syscall.h +++ b/include/user/syscall.h @@ -8,6 +8,7 @@ #define SYSCALL_NR_LSEEK 8 #define SYSCALL_NR_IOCTL 16 #define SYSCALL_NR_ACCESS 21 +#define SYSCALL_NR_SELECT 23 #define SYSCALL_NR_GETCWD 79 #define SYSCALL_NR_CHDIR 80 #define SYSCALL_NR_MKDIR 83 diff --git a/sys/list.c b/sys/list.c new file mode 100644 index 0000000..3907951 --- /dev/null +++ b/sys/list.c @@ -0,0 +1,37 @@ +#include "sys/assert.h" +#include "sys/types.h" +#include "sys/list.h" + +void list_append(struct list *head, struct list_link *link) { + link->prev = head->end; + if (head->end) { + head->end->next = link; + } else { + head->begin = link; + } + link->next = NULL; + head->end = link; +} + +void list_remove(struct list *head, struct list_link *link) { + struct list_link *prev, *next; + prev = link->prev; + next = link->next; + + if (prev) { + prev->next = next; + } else { + _assert(link == head->begin); + head->begin = next; + } + + if (next) { + next->prev = prev; + } else { + _assert(link == head->end); + head->end = prev; + } + + link->prev = NULL; + link->next = NULL; +} diff --git a/sys/sched.c b/sys/sched.c index 9e46ad8..3e1f88a 100644 --- a/sys/sched.c +++ b/sys/sched.c @@ -48,15 +48,15 @@ void sched_queue_to(struct thread *thr, int cpu_no) { thr->cpu = cpu_no; if (queue_heads[cpu_no]) { - struct thread *queue_tail = queue_heads[cpu_no]->prev; + struct thread *queue_tail = queue_heads[cpu_no]->sched_prev; - queue_tail->next = thr; - thr->prev = queue_tail; - queue_heads[cpu_no]->prev = thr; - thr->next = queue_heads[cpu_no]; + queue_tail->sched_next = thr; + thr->sched_prev = queue_tail; + queue_heads[cpu_no]->sched_prev = thr; + thr->sched_next = queue_heads[cpu_no]; } else { - thr->next = thr; - thr->prev = thr; + thr->sched_next = thr; + thr->sched_prev = thr; queue_heads[cpu_no] = thr; } @@ -66,6 +66,7 @@ void sched_queue_to(struct thread *thr, int cpu_no) { } void sched_queue(struct thread *thr) { +#if defined(AMD64_SMP) size_t min_queue_size = (size_t) -1; int min_queue_index = 0; uintptr_t irq; @@ -78,8 +79,10 @@ void sched_queue(struct thread *thr) { } } spin_release_irqrestore(&sched_lock, &irq); - sched_queue_to(thr, min_queue_index); +#else + sched_queue_to(thr, 0); +#endif } void sched_unqueue(struct thread *thr, enum thread_state new_state) { @@ -97,8 +100,8 @@ void sched_unqueue(struct thread *thr, enum thread_state new_state) { thr->cpu = -1; int cpu_no = cpu->processor_id; - struct thread *prev = thr->prev; - struct thread *next = thr->next; + struct thread *sched_prev = thr->sched_prev; + struct thread *sched_next = thr->sched_next; _assert((new_state == THREAD_WAITING) || (new_state == THREAD_STOPPED) || @@ -112,9 +115,9 @@ void sched_unqueue(struct thread *thr, enum thread_state new_state) { thread_check_signal(thr, 0); spin_lock_irqsave(&sched_lock, &irq); - if (next == thr) { - thr->next = NULL; - thr->prev = NULL; + if (sched_next == thr) { + thr->sched_next = NULL; + thr->sched_prev = NULL; queue_heads[cpu_no] = NULL; @@ -126,21 +129,21 @@ void sched_unqueue(struct thread *thr, enum thread_state new_state) { } if (thr == queue_heads[cpu_no]) { - queue_heads[cpu_no] = next; + queue_heads[cpu_no] = sched_next; } - _assert(thr && next && prev); + _assert(thr && sched_next && sched_prev); - next->prev = prev; - prev->next = next; + sched_next->sched_prev = sched_prev; + sched_prev->sched_next = sched_next; - thr->prev = NULL; - thr->next = NULL; + thr->sched_prev = NULL; + thr->sched_next = NULL; spin_release_irqrestore(&sched_lock, &irq); if (thr == cpu->thread) { - cpu->thread = next; - context_switch_to(next, thr); + cpu->thread = sched_next; + context_switch_to(sched_next, thr); } } @@ -210,7 +213,7 @@ void sched_debug_cycle(uint64_t delta_ms) { struct thread *head = queue_heads[cpu]; if (head) { - struct thread *tail = head->prev; + struct thread *tail = head->sched_prev; do { if (head->name[0]) { @@ -226,7 +229,7 @@ void sched_debug_cycle(uint64_t delta_ms) { } else { debugs(DEBUG_DEFAULT, ", "); } - head = head->next; + head = head->sched_next; } while (1); debugs(DEBUG_DEFAULT, "\n"); @@ -272,8 +275,8 @@ void yield(void) { struct thread *from = cpu->thread; struct thread *to; - if (from && from->next) { - to = from->next; + if (from && from->sched_next) { + to = from->sched_next; } else if (queue_heads[cpu->processor_id]) { to = queue_heads[cpu->processor_id]; } else { diff --git a/sys/sys_file.c b/sys/sys_file.c index 3fbef44..d2ada17 100644 --- a/sys/sys_file.c +++ b/sys/sys_file.c @@ -233,3 +233,48 @@ ssize_t sys_readdir(int fd, struct dirent *ent) { return vfs_readdir(&thr->ioctx, thr->fds[fd], ent); } + + +int sys_select(int n, fd_set *inp, fd_set *outp, fd_set *excp, struct timeval *tv) { + struct thread *thr = get_cpu()->thread; + _assert(thr); + + // Not yet implemented + _assert(!outp); + _assert(!excp); + + if (!inp) { + return 0; + } + + fd_set _inp; + memcpy(&_inp, inp, sizeof(fd_set)); + FD_ZERO(inp); + + // Check fds + for (int i = 0; i < n; ++i) { + if (FD_ISSET(i, &_inp)) { + struct ofile *fd = thr->fds[i]; + + if (!fd) { + return -EBADF; + } + + _assert(fd->vnode); + if (fd->vnode->type != VN_CHR) { + kerror("Tried to select() on non-char device/file: %s\n", fd->vnode->name); + return -ENOSYS; + } + } + } + + uint64_t deadline = (uint64_t) -1; + if (tv) { + deadline = tv->tv_sec * 1000000000ULL + tv->tv_usec * 1000ULL + system_time; + } + int res; + + panic("NYI\n"); + + return 0; +} diff --git a/sys/thread.c b/sys/thread.c index a26ecef..d219878 100644 --- a/sys/thread.c +++ b/sys/thread.c @@ -36,7 +36,8 @@ struct sys_fork_frame { //// -static struct thread *threads_all_head = NULL; +//static struct thread *threads_all_head = NULL; +LIST_HEAD(threads_all_head); static pid_t last_kernel_pid = 0; static pid_t last_user_pid = 0; @@ -48,32 +49,32 @@ pid_t thread_alloc_pid(int is_user) { } } -static void thread_add(struct thread *thr) { - if (threads_all_head) { - threads_all_head->g_prev = thr; - } - thr->g_next = threads_all_head; - thr->g_prev = NULL; - threads_all_head = thr; -} - -static void thread_remove(struct thread *thr) { - struct thread *prev = thr->g_prev; - struct thread *next = thr->g_next; - - if (prev) { - prev->g_next = next; - } else { - threads_all_head = next; - } - - if (next) { - next->g_prev = prev; - } - - thr->g_next = NULL; - thr->g_prev = NULL; -} +//static void thread_add(struct thread *thr) { +// if (threads_all_head) { +// threads_all_head->g_prev = thr; +// } +// thr->g_next = threads_all_head; +// thr->g_prev = NULL; +// threads_all_head = thr; +//} +// +//static void thread_remove(struct thread *thr) { +// struct thread *prev = thr->g_prev; +// struct thread *next = thr->g_next; +// +// if (prev) { +// prev->g_next = next; +// } else { +// threads_all_head = next; +// } +// +// if (next) { +// next->g_prev = prev; +// } +// +// thr->g_next = NULL; +// thr->g_prev = NULL; +//} //// @@ -103,7 +104,10 @@ void thread_ioctx_fork(struct thread *dst, struct thread *src) { int thread_signal_pgid(pid_t pgid, int signum) { int ret = 0; - for (struct thread *thr = threads_all_head; thr; thr = thr->g_next) { + list_foreach(&threads_all_head, _thr) { + struct thread *thr = list_link_value(_thr, struct thread, g_link); + _assert(thr); + if (thr->state != THREAD_STOPPED && thr->pgid == pgid) { thread_signal(thr, signum); ++ret; @@ -114,11 +118,15 @@ int thread_signal_pgid(pid_t pgid, int signum) { } struct thread *thread_find(pid_t pid) { - for (struct thread *thr = threads_all_head; thr; thr = thr->g_next) { + list_foreach(&threads_all_head, _thr) { + struct thread *thr = list_link_value(_thr, struct thread, g_link); + _assert(thr); + if (thr->pid == pid) { return thr; } } + return NULL; } @@ -218,6 +226,8 @@ int thread_init(struct thread *thr, uintptr_t entry, void *arg, int user) { thr->name[0] = 0; thr->flags = user ? 0 : THREAD_KERNEL; + list_link_init(&thr->g_link); + uint64_t *stack = (uint64_t *) (thr->data.rsp0_base + thr->data.rsp0_size); if (user) { @@ -330,7 +340,7 @@ int thread_init(struct thread *thr, uintptr_t entry, void *arg, int user) { thr->pgid = -1; thr->pid = -1; - thread_add(thr); + list_append(&threads_all_head, &thr->g_link); return 0; } @@ -347,6 +357,8 @@ int sys_fork(struct sys_fork_frame *frame) { uintptr_t stack_pages = amd64_phys_alloc_contiguous(2); _assert(stack_pages != MM_NADDR); + list_link_init(&dst->g_link); + dst->data.rsp0_base = MM_VIRTUALIZE(stack_pages); dst->data.rsp0_size = MM_PAGE_SIZE * 2; dst->data.rsp0_top = dst->data.rsp0_base + dst->data.rsp0_size; @@ -430,7 +442,7 @@ int sys_fork(struct sys_fork_frame *frame) { dst->pgid = src->pgid; dst->sigq = 0; - thread_add(dst); + list_append(&threads_all_head, &dst->g_link); sched_queue(dst); return dst->pid; @@ -625,7 +637,7 @@ int sys_waitpid(pid_t pid, int *status) { } thread_unchild(chld); - thread_remove(chld); + list_remove(&threads_all_head, &chld->g_link); thread_free(chld); return 0;