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/features | |
parent | eca4dfd49216f6158df69143994a18a0b3edd4fe (diff) |
Added poll syscall
Diffstat (limited to 'kernel/features')
-rw-r--r-- | kernel/features/fs.c | 16 | ||||
-rw-r--r-- | kernel/features/proc.c | 57 | ||||
-rw-r--r-- | kernel/features/syscall.c | 26 |
3 files changed, 83 insertions, 16 deletions
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(); |