aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMarvin Borner2021-02-07 16:58:48 +0100
committerMarvin Borner2021-02-07 16:58:48 +0100
commit59894afa1bc0f4efc85917710adf2e93d7e17a5e (patch)
treeeafaa21081430de4a0d09d8ac963ddc4e2f21a00 /kernel
parenteca4dfd49216f6158df69143994a18a0b3edd4fe (diff)
Added poll syscall
Diffstat (limited to 'kernel')
-rw-r--r--kernel/drivers/keyboard.c2
-rw-r--r--kernel/drivers/mouse.c3
-rw-r--r--kernel/features/fs.c16
-rw-r--r--kernel/features/proc.c57
-rw-r--r--kernel/features/syscall.c26
-rw-r--r--kernel/inc/fs.h1
-rw-r--r--kernel/inc/proc.h10
-rw-r--r--kernel/main.c2
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();