twizzler_abi/
lib.rs

1//! This library provides a common interface for applications that want to talk to the Twizzler
2//! kernel, and defines that interface for both applications and the kernel to follow. It's made of
3//! several parts:
4//!   1. System Calls -- see [syscall] and [arch::syscall].
5//!   2. Other Application-Kernel ABI definitions (e.g. pager queue entries).
6//!
7//! # Should I use these APIs?
8//! All of these interfaces are potentially unstable and should not be used directly by most
9//! programs.
10
11#![no_std]
12#![feature(naked_functions)]
13#![feature(core_intrinsics)]
14#![feature(int_roundings)]
15#![feature(thread_local)]
16#![feature(auto_traits)]
17#![feature(negative_impls)]
18#![allow(internal_features)]
19#![feature(rustc_attrs)]
20#![feature(linkage)]
21#![feature(test)]
22#![feature(c_variadic)]
23
24use syscall::KernelConsoleSource;
25pub mod arch;
26
27#[allow(unused_extern_crates)]
28extern crate alloc as rustc_alloc;
29
30pub mod aux;
31pub mod device;
32pub mod klog;
33pub mod kso;
34pub mod marker;
35pub mod meta;
36pub mod object;
37pub mod pager;
38pub mod security;
39pub mod simple_mutex;
40pub mod slot;
41pub mod syscall;
42pub mod thread;
43pub mod trace;
44pub mod upcall;
45
46#[inline]
47unsafe fn internal_abort() -> ! {
48    core::intrinsics::abort();
49}
50
51pub fn print_err(err: &str) {
52    syscall::sys_kernel_console_write(
53        KernelConsoleSource::Console,
54        err.as_bytes(),
55        syscall::KernelConsoleWriteFlags::empty(),
56    );
57}
58
59#[allow(dead_code)]
60/// during runtime init, we need to call functions that might fail, but if they do so, we should
61/// just abort. the standard unwrap() function for option will call panic, but we can't use that, as
62/// the runtime init stuff runs before the panic runtime is ready.
63fn internal_unwrap<T>(t: Option<T>, msg: &str) -> T {
64    if let Some(t) = t {
65        t
66    } else {
67        print_err(msg);
68        unsafe {
69            internal_abort();
70        }
71    }
72}
73
74#[allow(dead_code)]
75/// during runtime init, we need to call functions that might fail, but if they do so, we should
76/// just abort. the standard unwrap() function for result will call panic, but we can't use that, as
77/// the runtime init stuff runs before the panic runtime is ready.
78fn internal_unwrap_result<T, E>(t: Result<T, E>, msg: &str) -> T {
79    if let Ok(t) = t {
80        t
81    } else {
82        print_err(msg);
83        unsafe {
84            internal_abort();
85        }
86    }
87}
88
89#[cfg(test)]
90extern crate test;
91
92#[cfg(test)]
93mod tester {
94    use core::sync::atomic::AtomicU64;
95
96    use crate::{
97        simple_mutex::Mutex,
98        syscall::{
99            sys_thread_sync, ThreadSync, ThreadSyncFlags, ThreadSyncOp, ThreadSyncReference,
100            ThreadSyncSleep, ThreadSyncWake,
101        },
102    };
103
104    #[bench]
105    fn test_bench(bench: &mut test::Bencher) {
106        bench.iter(|| {
107            for i in 0..10000 {
108                core::hint::black_box(i);
109            }
110        });
111    }
112
113    #[bench]
114    fn bench_yield(bench: &mut test::Bencher) {
115        bench.iter(|| {
116            crate::syscall::sys_thread_yield();
117        });
118    }
119
120    #[bench]
121    fn bench_simple_syscall(bench: &mut test::Bencher) {
122        bench.iter(|| {
123            crate::syscall::sys_thread_self_id();
124        });
125    }
126
127    #[bench]
128    fn bench_thread_sync_sleep_ready(bench: &mut test::Bencher) {
129        let word = AtomicU64::new(0);
130        bench.iter(|| {
131            let r = sys_thread_sync(
132                &mut [ThreadSync::new_sleep(ThreadSyncSleep::new(
133                    ThreadSyncReference::Virtual(&word),
134                    1,
135                    ThreadSyncOp::Equal,
136                    ThreadSyncFlags::empty(),
137                ))],
138                None,
139            );
140            let _ = core::hint::black_box(r);
141        });
142    }
143
144    #[bench]
145    fn bench_thread_sync_wake(bench: &mut test::Bencher) {
146        let word = AtomicU64::new(0);
147        bench.iter(|| {
148            let r = sys_thread_sync(
149                &mut [ThreadSync::new_wake(ThreadSyncWake::new(
150                    ThreadSyncReference::Virtual(&word),
151                    1,
152                ))],
153                None,
154            );
155            let _ = core::hint::black_box(r);
156        });
157    }
158
159    #[bench]
160    fn bench1000_smutex_lock_unlock(bench: &mut test::Bencher) {
161        let lock = Mutex::new(3);
162        bench.iter(|| {
163            for _ in 0..1000 {
164                let mut g = lock.lock();
165                *g += 1;
166                let g = core::hint::black_box(g);
167                drop(g);
168            }
169        });
170    }
171}