aboutsummaryrefslogtreecommitdiff
path: root/kernel/features/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/features/proc.c')
-rw-r--r--kernel/features/proc.c182
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);