diff options
Diffstat (limited to 'kernel/features/proc.c')
-rw-r--r-- | kernel/features/proc.c | 182 |
1 files changed, 146 insertions, 36 deletions
diff --git a/kernel/features/proc.c b/kernel/features/proc.c index d76312c..bec48fa 100644 --- a/kernel/features/proc.c +++ b/kernel/features/proc.c @@ -3,12 +3,12 @@ #include <assert.h> #include <boot.h> #include <cpu.h> -#include <interrupts.h> -#include <list.h> +#include <fs.h> #include <load.h> #include <mem.h> #include <print.h> #include <proc.h> +#include <stack.h> #include <str.h> #include <timer.h> @@ -16,6 +16,7 @@ u32 current_pid = 0; u32 quantum = 0; struct proc *priority_proc; struct list *proc_list; +struct node *idle_proc; struct node *current; // TODO: Use less memcpy and only copy relevant registers @@ -44,8 +45,7 @@ void scheduler(struct regs *regs) } else if (((struct proc *)proc_list->head->data)->state == PROC_RUNNING) { current = proc_list->head; } else { - print("TODO: All processes are sleeping!\n"); // TODO! - /* loop(); */ + current = idle_proc; } memcpy(regs, &((struct proc *)current->data)->regs, sizeof(struct regs)); @@ -63,6 +63,12 @@ void scheduler(struct regs *regs) /* printf("{%d}", ((struct proc *)current->data)->pid); */ } +void kernel_idle() +{ + while (1) + ; +} + void proc_print(void) { struct node *node = proc_list->head; @@ -82,33 +88,6 @@ struct proc *proc_current(void) return current && current->data ? current->data : NULL; } -void proc_send(struct proc *src, struct proc *dest, u32 type, void *data) -{ - // TODO: Use unique key instead of pid for IPC - if (!src || !dest) - return; - struct proc_message *msg = malloc(sizeof(*msg)); - msg->src = src; - msg->dest = dest; - msg->msg = malloc(sizeof(struct message)); - msg->msg->src = (int)src->pid; - msg->msg->type = (int)type; - msg->msg->data = data; - list_add(dest->messages, msg); - priority_proc = dest; -} - -struct proc_message *proc_receive(struct proc *proc) -{ - if (proc->messages && proc->messages->head) { - struct proc_message *msg = proc->messages->head->data; - list_remove(proc->messages, proc->messages->head); - return msg; - } else { - return NULL; - } -} - struct proc *proc_from_pid(u32 pid) { struct node *iterator = proc_list->head; @@ -120,13 +99,18 @@ struct proc *proc_from_pid(u32 pid) return NULL; } +void proc_clear_quantum() +{ + quantum = 0; +} + void proc_exit(struct proc *proc, int status) { assert(proc); int res = 0; struct node *iterator = proc_list->head; - while (iterator != NULL) { + while (iterator) { if (iterator->data == proc) { res = 1; list_remove(proc_list, iterator); @@ -141,20 +125,38 @@ void proc_exit(struct proc *proc, int status) if (res) printf("Process %s exited with status %d\n", proc->name, status); - quantum = 0; // TODO: Add quantum to each process struct? + proc_clear_quantum(); // TODO: Add quantum to each process struct? + sti(); + hlt(); } void proc_yield(struct regs *r) { - quantum = 0; + proc_clear_quantum(); scheduler(r); } +void proc_enable_waiting(u32 dev_id) +{ + 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; + } + iterator = iterator->next; + } +} + struct proc *proc_make(void) { struct proc *proc = malloc(sizeof(*proc)); proc->pid = current_pid++; - proc->messages = list_new(); + proc->messages = stack_new(); proc->state = PROC_RUNNING; if (current) @@ -163,6 +165,94 @@ struct proc *proc_make(void) return proc; } +s32 procfs_write(const char *path, void *buf, u32 offset, u32 count, struct device *dev) +{ + while (*path == '/') + path++; + + int pid = 0; + while (path[0] >= '0' && path[0] <= '9') { + pid = pid * 10 + (path[0] - '0'); + path++; + } + + if (!pid && !memcmp(path, "self/", 5)) { + pid = proc_current()->pid; + path += 4; + } + + if (pid) { + struct proc *p = proc_from_pid(pid); + if (!p || path[0] != '/') + return -1; + + path++; + if (!memcmp(path, "msg", 4)) { + stack_push_bot(p->messages, buf); + return count; + } + } + + printf("%s - off: %d, cnt: %d, buf: %x, dev %x\n", path, offset, count, buf, dev); + return -1; +} + +s32 procfs_read(const char *path, void *buf, u32 offset, u32 count, struct device *dev) +{ + (void)dev; + + while (*path == '/') + path++; + + int pid = 0; + while (path[0] >= '0' && path[0] <= '9') { + pid = pid * 10 + (path[0] - '0'); + path++; + } + + if (!pid && !memcmp(path, "self/", 5)) { + pid = proc_current()->pid; + path += 4; + } + + if (pid) { + struct proc *p = proc_from_pid(pid); + if (!p || path[0] != '/') + return -1; + + path++; + if (!memcmp(path, "pid", 4)) { + //memcpy(buf, ((u8 *)p->pid) + offset, count); + *(u32 *)buf = p->pid; + return count; + } else if (!memcmp(path, "name", 5)) { + memcpy(buf, p->name + offset, count); + return count; + } else if (!memcmp(path, "status", 7)) { + const char *status = p->state == PROC_RUNNING ? "running" : "sleeping"; + memcpy(buf, status + offset, count); + return count; + } else if (!memcmp(path, "msg", 4)) { + if (stack_empty(p->messages)) { + return 0; + } else { + u8 *msg = stack_pop(p->messages); + memcpy(buf, msg + offset, count); + return count; + } + } + } + + return -1; +} + +u8 procfs_ready(const char *path, struct device *dev) +{ + (void)path; + (void)dev; + return 1; +} + extern void proc_jump_userspace(void); u32 _esp, _eip; @@ -175,7 +265,27 @@ void proc_init(void) scheduler_enable(); proc_list = list_new(); - kernel_proc = proc_make(); + // Procfs + struct vfs *vfs = malloc(sizeof(*vfs)); + vfs->type = VFS_PROCFS; + vfs->read = procfs_read; + vfs->write = procfs_write; + vfs->ready = procfs_ready; + vfs->data = NULL; + struct device *dev = malloc(sizeof(*dev)); + dev->name = "proc"; + dev->type = DEV_CHAR; + dev->vfs = vfs; + device_add(dev); + vfs_mount(dev, "/proc/"); + + // Idle proc + struct proc *kernel_proc = proc_make(); + void (*func)() = kernel_idle; + proc_load(kernel_proc, *(void **)&func); + strcpy(kernel_proc->name, "idle"); + kernel_proc->state = PROC_SLEEPING; + idle_proc = list_add(proc_list, kernel_proc); struct node *new = list_add(proc_list, proc_make()); bin_load((char *)"/bin/init", new->data); |