diff options
| author | Jon Santmyer <jon@jonsantmyer.com> | 2026-10-09 16:50:13 -0400 |
|---|---|---|
| committer | Jon Santmyer <jon@jonsantmyer.com> | 2026-10-09 16:50:13 -0400 |
| commit | 5ab3b18865eb813d433a6c0687dfa1f62a1b6055 (patch) | |
| tree | 8272e561d7d7a83780fc05e16722f29f58b18a28 /proc/scheduler.c | |
| parent | cc23ea5a4b38807e79aceb23e6f43e965926618f (diff) | |
| download | jove-kernel-5ab3b18865eb813d433a6c0687dfa1f62a1b6055.tar.gz jove-kernel-5ab3b18865eb813d433a6c0687dfa1f62a1b6055.tar.bz2 jove-kernel-5ab3b18865eb813d433a6c0687dfa1f62a1b6055.zip | |
add ipc send/recv mechanism for kernel objects.
Diffstat (limited to 'proc/scheduler.c')
| -rw-r--r-- | proc/scheduler.c | 117 |
1 files changed, 109 insertions, 8 deletions
diff --git a/proc/scheduler.c b/proc/scheduler.c index 875bcc4..29f45b5 100644 --- a/proc/scheduler.c +++ b/proc/scheduler.c @@ -5,24 +5,27 @@ #include "proc/init.h" #include "proc/process.h" +//TODO: Better scheduling algorithm than round robin. +static struct pcb_header *s_running_list; + static struct pcb_header *s_ready_queue; +static struct pcb_header *s_mail_queue; + +static uintmax_t s_this_tick; -static inline int -s_scheduler_yield_pcb(processor_t *proc, pcb_t *current_pcb, pcb_t *target_pcb) +static inline void +s_scheduler_swap_pcb(processor_t *proc, pcb_t *current_pcb, pcb_t *target_pcb) { jove_owned_obj_t *target_rootdir = obj_take(pcb_getrootdir(target_pcb)); jove_owned_obj_t *target_pcb_obj = pcb_getself(target_rootdir); + obj_release(target_rootdir); processor_setpcb(proc, target_pcb_obj); - obj_release(target_rootdir); _scheduler_switch_pcb_arch(target_pcb); scheduler_switch(pcb_getksp_ref(current_pcb), pcb_getksp(target_pcb)); - - return 0; } - int scheduler_yield(pid_t target_pid) { processor_t *proc = processor_current(); @@ -35,19 +38,117 @@ int scheduler_yield(pid_t target_pid) if(target_pcb == 0) { return -EBADPROC; } + + scheduler_savestate(); + s_scheduler_swap_pcb(proc, current_pcb, target_pcb); + scheduler_restorestate(); + return 0; +} - return s_scheduler_yield_pcb(proc, current_pcb, target_pcb); +void +s_enqueue_pcb(struct pcb_header *pcb, struct pcb_header *list) +{ + if(pcb->sched_prev) pcb->sched_prev->sched_next = pcb->sched_next; + if(pcb->sched_prev) pcb->sched_next->sched_prev = pcb->sched_prev; + + list->sched_prev = pcb; + pcb->sched_next = list; + pcb->sched_prev = NULL; +} + +void +scheduler_block_for_mail(struct pcb_header *pcb, uintmax_t timeout, pid_t yield_target) +{ + pcb->state = PCB_STATE_BLOCKED_MAIL; + + s_enqueue_pcb(pcb, s_mail_queue); + s_mail_queue = pcb; + + pcb->block_until = s_this_tick + timeout; + scheduler_yield(yield_target); +} + +void +s_schedule_ready_queue(void) +{ + for(struct pcb_header *pcb = s_ready_queue; pcb; pcb = s_ready_queue) { + s_ready_queue = pcb->sched_next; + + //Add this process to the ready list after the last ready process. + pcb->state = PCB_STATE_READY; + s_enqueue_pcb(pcb, s_running_list); + s_running_list = pcb; + } +} + +void +s_schedule_mail_queue(void) +{ + struct pcb_header *pcb = s_mail_queue; + while(pcb) { + struct pcb_header *next_pcb = pcb->sched_next; + + if(pcb->send.obj) { + struct pcb_header *send_target = (struct pcb_header*)pcb_frompid(pcb->send.pid); + if(send_target->recv.pid == 0 || send_target->recv.pid == pcb->pid) { + objdir_swapobj(send_target->recv.obj, pcb->send.obj); + send_target->recv.pid = pcb->pid; + + s_enqueue_pcb(pcb, s_running_list); + s_running_list = pcb; + goto loop_end; + } + } + if(pcb->recv.obj) { + s_enqueue_pcb(pcb, s_running_list); + s_running_list = pcb; + goto loop_end; + } + + if(s_this_tick >= pcb->block_until) { + s_enqueue_pcb(pcb, s_running_list); + s_running_list = pcb; + } +loop_end: + pcb = next_pcb; + } +} + +void +scheduler_tick() +{ + size_t last_tick = s_this_tick++; + + s_schedule_ready_queue(); + s_schedule_mail_queue(); + + processor_t *proc = processor_current(); + struct pcb_header *current_pcb = obj_deref(processor_getpcb(proc)); + struct pcb_header *next_pcb = s_running_list; + struct pcb_header *tail = next_pcb; + + while(tail->sched_next) { + tail = tail->sched_next; + if(tail == next_pcb) break; + } + + tail->sched_next = next_pcb; + next_pcb->sched_prev = tail; + s_running_list = next_pcb->sched_next; + + s_scheduler_swap_pcb(proc, (pcb_t*)current_pcb, (pcb_t*)next_pcb); } void scheduler_init(jove_owned_obj_t *pcb_obj, void *process_main) { struct pcb_header *pcb_header = obj_deref(pcb_obj); pcb_header->state = PCB_STATE_RUNNING; - pcb_header->sched_next = pcb_header; processor_t *proc = processor_current(); processor_setpcb(proc, pcb_obj); + s_running_list = pcb_header; + __asm__("movq %0, %%rsp; \ xorq %%rbp, %%rbp; \ jmp %1":: |
