summaryrefslogtreecommitdiffstats
path: root/proc/scheduler.c
blob: 875bcc4c5dbcf7f45165f298cfe0842aa91a2581 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "scheduler.h"
#include "api/error.h"
#include "hal/smp.h"
#include "sys/objdir.h"
#include "proc/init.h"
#include "proc/process.h"

static struct pcb_header *s_ready_queue;

static inline int
s_scheduler_yield_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);

    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();
    pcb_t *current_pcb = obj_deref(processor_getpcb(proc));
    pcb_t *target_pcb = (pcb_t*)((struct pcb_header*)current_pcb)->sched_next;

    if(target_pid != 0) {
        pcb_t *target_pcb = pcb_frompid(target_pid);
    }
    if(target_pcb == 0) {
        return -EBADPROC;
    }

    return s_scheduler_yield_pcb(proc, current_pcb, target_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);

    __asm__("movq %0, %%rsp; \
             xorq %%rbp, %%rbp; \
             jmp %1"::
             "m"(pcb_header->ksp), "r"(process_main));
}