diff options
author | Marvin Borner | 2021-02-07 16:58:48 +0100 |
---|---|---|
committer | Marvin Borner | 2021-02-07 16:58:48 +0100 |
commit | 59894afa1bc0f4efc85917710adf2e93d7e17a5e (patch) | |
tree | eafaa21081430de4a0d09d8ac963ddc4e2f21a00 /kernel | |
parent | eca4dfd49216f6158df69143994a18a0b3edd4fe (diff) |
Added poll syscall
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/drivers/keyboard.c | 2 | ||||
-rw-r--r-- | kernel/drivers/mouse.c | 3 | ||||
-rw-r--r-- | kernel/features/fs.c | 16 | ||||
-rw-r--r-- | kernel/features/proc.c | 57 | ||||
-rw-r--r-- | kernel/features/syscall.c | 26 | ||||
-rw-r--r-- | kernel/inc/fs.h | 1 | ||||
-rw-r--r-- | kernel/inc/proc.h | 10 | ||||
-rw-r--r-- | kernel/main.c | 2 |
8 files changed, 96 insertions, 21 deletions
diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c index 0dd7219..1652625 100644 --- a/kernel/drivers/keyboard.c +++ b/kernel/drivers/keyboard.c @@ -44,7 +44,7 @@ void keyboard_handler() state = 0; merged = 0; - proc_enable_waiting(dev_id); + proc_enable_waiting(dev_id, PROC_WAIT_DEV); } void keyboard_acknowledge(void) diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c index 2e9ceae..b03ed50 100644 --- a/kernel/drivers/mouse.c +++ b/kernel/drivers/mouse.c @@ -6,6 +6,7 @@ #include <interrupts.h> #include <mem.h> #include <print.h> +#include <proc.h> #include <stack.h> #include <str.h> #include <sys.h> @@ -44,8 +45,8 @@ void mouse_handler() event->but2 = (mouse_byte[0] >> 1) & 1; event->but3 = (mouse_byte[0] >> 2) & 1; stack_push_bot(queue, event); - mouse_cycle = 0; + proc_enable_waiting(dev_id, PROC_WAIT_DEV); break; default: break; diff --git a/kernel/features/fs.c b/kernel/features/fs.c index ecb2b85..16a12f7 100644 --- a/kernel/features/fs.c +++ b/kernel/features/fs.c @@ -181,6 +181,21 @@ s32 vfs_stat(const char *path, struct stat *buf) return m->dev->vfs->stat(path, buf, m->dev); } +s32 vfs_poll(const char **files) +{ + if (!files) + return -1; + + for (const char **p = files; *p && **p; p++) + if (vfs_ready(*p)) + return p - files; + + for (const char **p = files; *p && **p; p++) + proc_wait_for(vfs_find_dev(*p)->id, PROC_WAIT_DEV, vfs_poll); + + return PROC_MAX_WAIT_IDS + 1; +} + u8 vfs_ready(const char *path) { while (*path == ' ') @@ -268,6 +283,7 @@ void device_install(void) struct vfs *vfs = malloc(sizeof(*vfs)); vfs->type = VFS_DEVFS; vfs->read = devfs_read; + vfs->perm = devfs_perm; vfs->ready = devfs_ready; struct device *dev = malloc(sizeof(*dev)); dev->name = "dev"; diff --git a/kernel/features/proc.c b/kernel/features/proc.c index 5dde2bd..1f402d8 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -147,22 +147,57 @@ void proc_yield(struct regs *r) scheduler(r); } -void proc_enable_waiting(u32 dev_id) +void proc_enable_waiting(u32 id, enum proc_wait_type type) { struct node *iterator = proc_list->head; while (iterator) { struct proc *p = iterator->data; struct proc_wait *w = &p->wait; - if (p && w && w->id == dev_id) { - struct regs *r = &p->regs; - r->eax = (u32)w->func((char *)r->ebx, (void *)r->ecx, r->edx, r->esi); - memset(&p->wait, 0, sizeof(p->wait)); - p->state = PROC_RUNNING; + + if (!p || !w || w->id_cnt == 0 || w->type != type) { + iterator = iterator->next; + continue; + } + + u8 dispatched = 0; + + for (u32 i = 0; i < PROC_MAX_WAIT_IDS; i++) { + if (w->ids[i] == id) { + struct regs *r = &p->regs; + if (w->func) + r->eax = (u32)w->func((char *)r->ebx, (void *)r->ecx, + r->edx, r->esi); + w->ids[i] = 0; + p->state = PROC_RUNNING; + dispatched = 1; + break; + } } + + if (dispatched) + memset(&p->wait, 0, sizeof(p->wait)); + iterator = iterator->next; } } +void proc_wait_for(u32 id, enum proc_wait_type type, s32 (*func)()) +{ + struct proc *p = proc_current(); + + if (p->wait.id_cnt > 0) { + p->wait.ids[p->wait.id_cnt++] = id; + assert(func == p->wait.func && type == p->wait.type); + } else { + p->wait.type = type; + p->wait.id_cnt = 1; + p->wait.ids[0] = id; + p->wait.func = func; + } + + p->state = PROC_SLEEPING; +} + struct proc *proc_make(void) { struct proc *proc = malloc(sizeof(*proc)); @@ -170,6 +205,8 @@ struct proc *proc_make(void) proc->super = 0; proc->messages = stack_new(); proc->state = PROC_RUNNING; + proc->wait.id_cnt = 0; + proc->wait.func = NULL; if (current) list_add(proc_list, proc); @@ -261,9 +298,12 @@ s32 procfs_read(const char *path, void *buf, u32 offset, u32 count, struct devic u8 procfs_perm(const char *path, enum vfs_perm perm, struct device *dev) { (void)path; - (void)perm; (void)dev; - return 1; + + if (perm == VFS_EXEC) + return 0; + else + return 1; } u8 procfs_ready(const char *path, struct device *dev) @@ -290,6 +330,7 @@ void proc_init(void) vfs->type = VFS_PROCFS; vfs->read = procfs_read; vfs->write = procfs_write; + vfs->perm = procfs_perm; vfs->ready = procfs_ready; vfs->data = NULL; struct device *dev = malloc(sizeof(*dev)); diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c index d980317..8140313 100644 --- a/kernel/features/syscall.c +++ b/kernel/features/syscall.c @@ -12,6 +12,14 @@ #include <sys.h> #include <timer.h> +void syscall_yield(struct regs *r) +{ + proc_yield(r); + sti(); + while (1) + hlt(); +} + void syscall_handler(struct regs *r) { enum sys num = r->eax; @@ -40,14 +48,8 @@ void syscall_handler(struct regs *r) if (vfs_ready((char *)r->ebx)) { r->eax = (u32)vfs_read((char *)r->ebx, (void *)r->ecx, r->edx, r->esi); } else { - struct proc *p = proc_current(); - p->state = PROC_SLEEPING; - p->wait.id = vfs_find_dev((char *)r->ebx)->id; - p->wait.func = vfs_read; - proc_yield(r); - sti(); - while (1) - hlt(); + proc_wait_for(vfs_find_dev((char *)r->ebx)->id, PROC_WAIT_DEV, vfs_read); + syscall_yield(r); } break; } @@ -55,6 +57,14 @@ void syscall_handler(struct regs *r) r->eax = (u32)vfs_write((char *)r->ebx, (void *)r->ecx, r->edx, r->esi); break; } + case SYS_POLL: { + s32 ret = vfs_poll((const char **)r->ebx); + if (ret == PROC_MAX_WAIT_IDS + 1) + syscall_yield(r); + else + r->eax = ret; + break; + } case SYS_EXEC: { char *path = (char *)r->ebx; struct proc *proc = proc_make(); diff --git a/kernel/inc/fs.h b/kernel/inc/fs.h index 1069597..1f46ba3 100644 --- a/kernel/inc/fs.h +++ b/kernel/inc/fs.h @@ -60,6 +60,7 @@ struct device *vfs_find_dev(const char *path); s32 vfs_read(const char *path, void *buf, u32 offset, u32 count); s32 vfs_write(const char *path, void *buf, u32 offset, u32 count); s32 vfs_stat(const char *path, struct stat *buf); +s32 vfs_poll(const char **files); u8 vfs_ready(const char *path); struct device *device_get_by_name(const char *name); diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h index 4a75638..0007744 100644 --- a/kernel/inc/proc.h +++ b/kernel/inc/proc.h @@ -17,10 +17,15 @@ #define GDT_USER_CODE_OFFSET 0x1b // User code segment offset in GDT (with ring3 mask) #define GDT_USER_DATA_OFFSET 0x23 // User data segment offset in GDT (with ring3 mask) +#define PROC_MAX_WAIT_IDS 16 + enum proc_state { PROC_RUNNING, PROC_SLEEPING }; +enum proc_wait_type { PROC_WAIT_DEV }; struct proc_wait { - u32 id; // dev_id + enum proc_wait_type type; + u32 ids[PROC_MAX_WAIT_IDS]; // dev_id + u32 id_cnt; s32 (*func)(); }; @@ -43,7 +48,8 @@ struct proc *proc_from_pid(u32 pid); void proc_exit(struct proc *proc, int status); void proc_yield(struct regs *r); void proc_clear_quantum(); -void proc_enable_waiting(u32 dev_id); +void proc_enable_waiting(u32 id, enum proc_wait_type type); +void proc_wait_for(u32 id, enum proc_wait_type type, s32 (*func)()); struct proc *proc_make(void); #endif diff --git a/kernel/main.c b/kernel/main.c index 7466f5d..8739a53 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -36,7 +36,7 @@ void kernel_main(struct vid_info *vid_info) timer_install(); keyboard_install(); mouse_install(); - net_install(); + /* net_install(); */ // Enable drivers sti(); |