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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
pub mod latch;
pub mod scope;
mod system;

mod job;
mod scheduler;
mod unwind;

pub mod prelude {
    pub use super::latch::{CountLatch, Latch, LatchProbe, LockLatch, SpinLatch};
    pub use super::system::PanicHandler;
}

use self::ins::{ctx, CTX};
use self::scope::Scope;
use self::system::{PanicHandler, SchedulerSystem};

/// Setup the sched system.
pub(crate) unsafe fn setup(
    num: u32,
    stack_size: Option<usize>,
    panic_handler: Option<Box<PanicHandler>>,
) {
    debug_assert!(CTX.is_null(), "duplicated setup of sched system.");

    CTX = Box::into_raw(Box::new(if num > 0 {
        SchedulerSystem::new(num, stack_size, panic_handler)
    } else {
        SchedulerSystem::headless()
    }));
}

/// Discard the sched system.
pub(crate) unsafe fn discard() {
    if CTX.is_null() {
        return;
    }

    drop(Box::from_raw(CTX as *mut SchedulerSystem));
    CTX = std::ptr::null();
}

pub(crate) unsafe fn terminate() {
    ctx().terminate();
}

/// Checks if the sched system is enabled.
#[inline]
pub fn valid() -> bool {
    unsafe { !CTX.is_null() }
}

// /// Blocks current thread until latch is set. Try to keep busy by popping and stealing jobs
// /// as necessary.
// #[inline]
// pub fn wait_until<T>(latch: &T)
// where
//     T: LatchWaitProbe,
// {
//     ctx().wait_until(latch);
// }

/// Spawn an asynchronous job in the global `Scheduler.`
pub fn spawn<F>(func: F)
where
    F: FnOnce() + Send + 'static,
{
    ctx().spawn(func);
}

/// Create a "fork-join" scope `s` and invokes the closure with a
/// reference to `s`. This closure can then spawn asynchronous tasks
/// into `s`. Those tasks may run asynchronously with respect to the
/// closure; they may themselves spawn additional tasks into `s`. When
/// the closure returns, it will block until all tasks that have been
/// spawned into `s` complete.
pub fn scope<'s, F, R>(func: F) -> R
where
    F: for<'r> FnOnce(&'r Scope<'s>) -> R + 's + Send,
    R: Send,
{
    ctx().scope(func)
}

mod ins {
    use super::system::SchedulerSystem;

    pub static mut CTX: *const SchedulerSystem = std::ptr::null();

    pub fn ctx() -> &'static SchedulerSystem {
        unsafe {
            debug_assert!(
                !CTX.is_null(),
                "scheduler system has not been initialized properly."
            );

            &*CTX
        }
    }
}