kernel/scheduler.rad 1.7 KiB raw
1
//! User-space CPU windows and bounded worker execution.
2
export mod abi;
3
export mod sys;
4
export mod mmio;
5
6
/// Scheduler or worker startup values.
7
record Env: Copy {
8
    /// Shared resource bundle for the scheduler.
9
    argsPointer: *abi::BootInfo,
10
    /// Zero for a worker, or the resource header size for the scheduler.
11
    argsSize: u64,
12
    /// Installed event capability.
13
    eventsHandle: u64,
14
    /// Shared event-ring address.
15
    eventsPointer: u64,
16
}
17
18
/// Run a worker or distribute four successive CPU windows from the boot bundle.
19
@default unsafe fn main(env: *Env) -> ! {
20
    if env.argsSize == 0 {
21
        sys::exit(7);
22
    }
23
    assert env.argsSize == @sizeOf(abi::BootInfo) as u64;
24
    let info = env.argsPointer;
25
    let self = abi::Handle(info.handles[0]);
26
    let started = mmio::read64(info.clock, 0);
27
    assert sys::queryDomain(self).state == 1;
28
    for turn in 0..4 {
29
        let current = sys::currentContext();
30
        let budget = abi::Handle(current.budget);
31
        let window = try! sys::queryBudget(budget);
32
        let later = try! sys::budgetSplit(budget, window.start + info.timebase);
33
        let worker = try! sys::domainCreate(self, info.schedulerImage);
34
        let stack = try! sys::pageAllocate(self, 16);
35
        let extent = sys::queryPage(stack);
36
        let transferred = try! sys::capabilityTransfer(stack, worker, abi::RIGHTS_MASK as u64);
37
        try! sys::domainActivate(worker, extent.base + extent.count * 4096, (&*env) as *unsafe opaque, 0);
38
        try! sys::yield(worker);
39
        assert sys::currentContext().budget == *later;
40
    }
41
    assert mmio::read64(info.clock, 0) > started;
42
    if info.shutdown <> abi::Handle(0) {
43
        mmio::write32(info.shutdown, 0, 0x5555);
44
        panic "shutdown returned";
45
    }
46
    sys::exit(0);
47
}