summaryrefslogtreecommitdiffstats
path: root/proc/scheduler.c
diff options
context:
space:
mode:
authorJon Santmyer <jon@jonsantmyer.com>2026-10-09 16:50:13 -0400
committerJon Santmyer <jon@jonsantmyer.com>2026-10-09 16:50:13 -0400
commit5ab3b18865eb813d433a6c0687dfa1f62a1b6055 (patch)
tree8272e561d7d7a83780fc05e16722f29f58b18a28 /proc/scheduler.c
parentcc23ea5a4b38807e79aceb23e6f43e965926618f (diff)
downloadjove-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.c117
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"::