Skip to main content

osiris/syscalls/
sched.rs

1//! This module provides task management related syscalls.
2
3use core::ffi::c_int;
4
5use proc_macros::syscall_handler;
6
7use crate::{sched, time, uapi::sched::RtAttrs};
8
9#[syscall_handler(num = 1)]
10fn sleep(until_hi: u32, until_lo: u32) -> c_int {
11    let until = ((until_hi as u64) << 32) | (until_lo as u64);
12    sched::with(|sched| {
13        if sched.sleep_until(None, until, time::tick()).is_err() {
14            bug!("no current thread set.");
15        }
16    });
17    0
18}
19
20#[syscall_handler(num = 2)]
21fn sleep_for(duration_hi: u32, duration_lo: u32) -> c_int {
22    let duration = ((duration_hi as u64) << 32) | (duration_lo as u64);
23    sched::with(|sched| {
24        let now = time::tick();
25        if sched
26            .sleep_until(None, now.saturating_add(duration), now)
27            .is_err()
28        {
29            bug!("no current thread set.");
30        }
31    });
32    0
33}
34
35fn valid_rt_attrs(attrs: RtAttrs) -> bool {
36    attrs.budget != 0
37        && attrs.period != 0
38        && attrs.deadline != 0
39        && attrs.budget as u64 <= attrs.deadline
40        && attrs.deadline <= attrs.period as u64
41}
42
43#[syscall_handler(num = 3)]
44fn spawn_thread(func_ptr: usize, ctx: usize, attrs: *const RtAttrs) -> c_int {
45    sched::with(|sched| {
46        let attrs = if attrs.is_null() {
47            None
48        } else {
49            let attrs = unsafe { *attrs };
50            if !valid_rt_attrs(attrs) {
51                return -1;
52            }
53            Some(attrs)
54        };
55
56        let attrs = sched::thread::Attributes {
57            entry: unsafe { core::mem::transmute(func_ptr) },
58            ctx: ctx as *mut core::ffi::c_void,
59            fin: None,
60            attrs,
61        };
62        match sched.create_thread(None, &attrs) {
63            Ok(uid) => {
64                if sched.enqueue(time::tick(), uid).is_err() {
65                    bug!("failed to enqueue thread.");
66                }
67                uid.as_usize() as c_int
68            }
69            Err(_) => -1,
70        }
71    })
72}
73
74#[syscall_handler(num = 4)]
75fn exit(_code: usize) -> c_int {
76    sched::with(|sched| {
77        if sched.kill_by_thread(None).is_err() {
78            bug!("failed to terminate thread.");
79        }
80    });
81    0
82}
83
84#[syscall_handler(num = 5)]
85fn kick_thread(_uid: usize) -> c_int {
86    // TODO: Implement a way to retrieve the thread UID from the usize uid.
87    0
88}
89
90#[syscall_handler(num = 6)]
91fn current_id() -> c_int {
92    sched::with(|sched| match sched.current_uid() {
93        Some(uid) => uid as c_int,
94        None => -1,
95    })
96}