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(core_intrinsics)]
13#![feature(int_roundings)]
14#![feature(thread_local)]
15#![feature(auto_traits)]
16#![feature(negative_impls)]
17#![allow(unexpected_cfgs)]
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 meta;
35pub mod object;
36pub mod pager;
37pub mod security;
38pub mod simple_mutex;
39pub mod slot;
40pub mod syscall;
41pub mod thread;
42pub mod trace;
43pub mod upcall;
44
45#[cfg(all(not(target_os = "twizzler"), not(feature = "kernel")))]
46static _NO: () = panic!("cannot compile for non-twizzler OS");
47
48#[inline]
49unsafe fn internal_abort() -> ! {
50    core::intrinsics::abort();
51}
52
53pub fn print_err(err: &str) {
54    syscall::sys_kernel_console_write(
55        KernelConsoleSource::Console,
56        err.as_bytes(),
57        syscall::KernelConsoleWriteFlags::empty(),
58    );
59}
60
61#[allow(dead_code)]
62/// during runtime init, we need to call functions that might fail, but if they do so, we should
63/// just abort. the standard unwrap() function for option will call panic, but we can't use that, as
64/// the runtime init stuff runs before the panic runtime is ready.
65fn internal_unwrap<T>(t: Option<T>, msg: &str) -> T {
66    if let Some(t) = t {
67        t
68    } else {
69        print_err(msg);
70        unsafe {
71            internal_abort();
72        }
73    }
74}
75
76#[allow(dead_code)]
77/// during runtime init, we need to call functions that might fail, but if they do so, we should
78/// just abort. the standard unwrap() function for result will call panic, but we can't use that, as
79/// the runtime init stuff runs before the panic runtime is ready.
80fn internal_unwrap_result<T, E>(t: Result<T, E>, msg: &str) -> T {
81    if let Ok(t) = t {
82        t
83    } else {
84        print_err(msg);
85        unsafe {
86            internal_abort();
87        }
88    }
89}
90
91#[cfg(test)]
92extern crate test;
93
94#[cfg(test)]
95mod tester {
96    use core::sync::atomic::AtomicU64;
97
98    use crate::{
99        simple_mutex::Mutex,
100        syscall::{
101            sys_thread_sync, ThreadSync, ThreadSyncFlags, ThreadSyncOp, ThreadSyncReference,
102            ThreadSyncSleep, ThreadSyncWake,
103        },
104    };
105
106    #[bench]
107    fn test_bench(bench: &mut test::Bencher) {
108        bench.iter(|| {
109            for i in 0..10000 {
110                core::hint::black_box(i);
111            }
112        });
113    }
114
115    #[bench]
116    fn bench_yield(bench: &mut test::Bencher) {
117        bench.iter(|| {
118            crate::syscall::sys_thread_yield();
119        });
120    }
121
122    #[bench]
123    fn bench_simple_syscall(bench: &mut test::Bencher) {
124        bench.iter(|| {
125            crate::syscall::sys_thread_self_id();
126        });
127    }
128
129    #[bench]
130    fn bench_thread_sync_sleep_ready(bench: &mut test::Bencher) {
131        let word = AtomicU64::new(0);
132        bench.iter(|| {
133            let r = sys_thread_sync(
134                &mut [ThreadSync::new_sleep(ThreadSyncSleep::new(
135                    ThreadSyncReference::Virtual(&word),
136                    1,
137                    ThreadSyncOp::Equal,
138                    ThreadSyncFlags::empty(),
139                ))],
140                None,
141            );
142            let _ = core::hint::black_box(r);
143        });
144    }
145
146    #[bench]
147    fn bench_thread_sync_wake(bench: &mut test::Bencher) {
148        let word = AtomicU64::new(0);
149        bench.iter(|| {
150            let r = sys_thread_sync(
151                &mut [ThreadSync::new_wake(ThreadSyncWake::new(
152                    ThreadSyncReference::Virtual(&word),
153                    1,
154                ))],
155                None,
156            );
157            let _ = core::hint::black_box(r);
158        });
159    }
160
161    #[bench]
162    fn bench1000_smutex_lock_unlock(bench: &mut test::Bencher) {
163        let lock = Mutex::new(3);
164        bench.iter(|| {
165            for _ in 0..1000 {
166                let mut g = lock.lock();
167                *g += 1;
168                let g = core::hint::black_box(g);
169                drop(g);
170            }
171        });
172    }
173}