diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2025-12-11 16:34:51 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2025-12-11 16:34:51 +0800 |
| commit | 27fc7bda593c8bd2c24a334a368772b5f15d4e9e (patch) | |
| tree | cee97c7b0ba2701be3981b587902e03ba8b85e12 /src/kernel/proc | |
| parent | 497e4a1b2f6f9181518e9887991c0464bd8f6bcf (diff) | |
| download | lume-27fc7bda593c8bd2c24a334a368772b5f15d4e9e.tar.gz lume-27fc7bda593c8bd2c24a334a368772b5f15d4e9e.tar.xz | |
feat:Cooperative Multitasking
Diffstat (limited to 'src/kernel/proc')
| -rw-r--r-- | src/kernel/proc/proc.cc | 113 | ||||
| -rw-r--r-- | src/kernel/proc/swtch.S | 34 |
2 files changed, 147 insertions, 0 deletions
diff --git a/src/kernel/proc/proc.cc b/src/kernel/proc/proc.cc new file mode 100644 index 0000000..469b7eb --- /dev/null +++ b/src/kernel/proc/proc.cc @@ -0,0 +1,113 @@ +#include "kernel/proc.h" +#include "kernel/pmm.h" +#include "drivers/uart.h" + +#define NPROC 10 + +void str_copy(char *dst, const char *src) +{ + while (*src) + *dst++ = *src++; + *dst = 0; +} + +extern "C" void swtch(struct Context *old_ctx, struct Context *new_ctx); + +struct Proc procs[NPROC]; +struct Context main_context; + +namespace ProcManager +{ + void init() + { + for (int i = 0; i < NPROC; i++) + { + procs[i].state = UNUSED; + } + } + + void create_kernel_thread(void (*func)(), const char *name) + { + struct Proc *p = nullptr; + for(int i = 0; i < NPROC; i++) + { + if(procs[i].state == UNUSED) + { + p = &procs[i]; + p->pid = i + 1; + break; + } + } + + if (!p) + { + Drivers::uart_puts("Error: No free process slots!\n"); + return; + } + + p->kstack = PMM::alloc_page(); + if (!p->kstack) + { + Drivers::uart_puts("Error: Alloc kstack failed!\n"); + return; + } + + p->context.ra = (uint64)func; + + p->context.sp = (uint64)p->kstack + 4096; + + p->state = RUNNABLE; + str_copy(p->name, name); + + Drivers::uart_puts("[Proc] Created thread: "); + Drivers::uart_puts(name); + Drivers::uart_puts("\n"); + } + + void yield() + { + struct Proc *p = nullptr; + for(int i = 0; i < NPROC; i++) + { + if (procs[i].state == RUNNING) + { + p = &procs[i]; + break; + } + } + if(p) + { + p->state = RUNNABLE; + swtch(&p->context, &main_context); + } + } + + void scheduler() + { + struct Proc *p = nullptr; + Drivers::uart_puts("[Proc] Scheduler started.\n"); + + for (;;) + { + // int nothing_to_run = 1; + + intr_off(); + + for (p = procs; p < &procs[NPROC]; p++) + { + if (p->state == RUNNABLE) + { + // nothing_to_run = 0; + + p->state = RUNNING; + + intr_on(); + + swtch(&main_context, &p->context); + + intr_off(); + } + } + } + } +}
\ No newline at end of file diff --git a/src/kernel/proc/swtch.S b/src/kernel/proc/swtch.S new file mode 100644 index 0000000..f59de20 --- /dev/null +++ b/src/kernel/proc/swtch.S @@ -0,0 +1,34 @@ +.global swtch + +swtch: + sd ra, 0(a0) + sd sp, 8(a0) + sd s0, 16(a0) + sd s1, 24(a0) + sd s2, 32(a0) + sd s3, 40(a0) + sd s4, 48(a0) + sd s5, 56(a0) + sd s6, 64(a0) + sd s7, 72(a0) + sd s8, 80(a0) + sd s9, 88(a0) + sd s10, 96(a0) + sd s11, 104(a0) + + ld ra, 0(a1) + ld sp, 8(a1) + ld s0, 16(a1) + ld s1, 24(a1) + ld s2, 32(a1) + ld s3, 40(a1) + ld s4, 48(a1) + ld s5, 56(a1) + ld s6, 64(a1) + ld s7, 72(a1) + ld s8, 80(a1) + ld s9, 88(a1) + ld s10, 96(a1) + ld s11, 104(a1) + + ret |
