boc_sys/
lib.rs

1//! Low level FFI bindings to the [verona runtime](https://github.com/microsoft/verona-rt)
2//!
3//! This is an implementation detail of the [`boc`](https://docs.rs/boc/) crate.
4//!
5//! This is a research project, and is at an early stage of development. It is not
6//! ready for use outside of research.
7#![cfg_attr(not(test), no_std)]
8use core::fmt;
9
10use descriptor::Descriptor;
11
12pub mod descriptor;
13mod vsizeof;
14pub use vsizeof::vsizeof;
15
16#[repr(transparent)]
17#[derive(Clone, Copy)]
18/// A reference to a `verona::rt::Scheduler`.
19///
20/// The underlying Schedular is a singleton, but multiple `Schedular`
21/// structs can exist, which will all point to the same singleton.
22///
23/// Create with [`scheduler_get`]
24pub struct Scheduler(*mut ());
25
26/// Equivalent to `rt::Cown*` on the C++ side.
27///
28/// This is a reference cointed pointer, so embeders shouldn't
29/// implement Copy.
30#[derive(Clone, Copy)]
31#[repr(transparent)]
32pub struct CownPtr {
33    // TODO: Can we use not-null here?
34    addr: *mut (),
35}
36unsafe impl Send for CownPtr {}
37unsafe impl Sync for CownPtr {}
38
39impl fmt::Pointer for CownPtr {
40    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41        write!(f, "{:p}", self.addr)
42    }
43}
44
45impl CownPtr {
46    pub fn addr(self) -> *mut () {
47        self.addr
48    }
49}
50
51#[repr(C)]
52#[derive(Debug)]
53/// `Corresponds to rt::Cown`.
54///
55/// Rust code shouldn't inspect the contents of it, but use it for size/
56/// allignment/pointer arithmetic.
57pub struct OpaqueCown {
58    _marker: core::mem::MaybeUninit<[*const (); 3]>,
59}
60
61#[repr(transparent)]
62#[derive(Clone, Copy)]
63pub struct WorkPtr(*mut ());
64
65#[repr(C)]
66pub struct Slot {
67    pub cown: CownPtr,
68    _scheginfo: core::sync::atomic::AtomicUsize,
69}
70
71#[link(name = "boxcar_bindings")]
72extern "C" {
73
74    /// Returns the global `Scheduler`.
75    ///
76    /// ## Safety
77    ///
78    /// Safe
79    pub fn scheduler_get() -> Scheduler;
80
81    /// Initialize the schedular with the given number of threads.
82    ///
83    /// ## Safety
84    ///
85    /// - `n_threads` must not be zero.
86    /// - The scheduler must not be "initialized"
87    ///   - TODO: What exactly does this mean??
88    pub fn scheduler_init(schedular: Scheduler, n_threads: usize);
89
90    /// Run the schedular.
91    ///
92    /// This will "de-initialize" the scheduler, allowing you to "re-initialize"
93    /// it.
94    ///
95    /// ## Safety
96    ///
97    /// - Unclear. It's probably a bad idea to call it multiple times without
98    ///   re-initializing the schedular.
99    pub fn scheduler_run(schedular: Scheduler);
100
101    /// Extremely racy.
102    pub fn schedular_set_detect_leaks(detect_leaks: bool);
103    pub fn schedular_has_leaks() -> bool;
104
105    pub fn boxcars_acquire_object(cown: CownPtr);
106    pub fn boxcars_release_object(cown: CownPtr);
107
108    pub fn boxcars_allocate_cown(descriptor: &'static Descriptor) -> CownPtr;
109
110    pub fn enable_logging();
111    pub fn boxcars_dump_flight_recorder();
112
113    pub fn boxcars_sched_lambda(
114        f: extern "C" fn(WorkPtr),
115
116        cowns: *const CownPtr,
117        n_cowns: usize,
118
119        payload: *const (),
120        payload_size: usize,
121    );
122    pub fn boxcars_preinvoke(
123        work: WorkPtr,
124        slots: &mut *const Slot,
125        body: &mut *const (),
126        count: &mut usize,
127    );
128    pub fn boxcars_postinvoke(work: WorkPtr);
129
130    pub fn boxcar_log_cstr(ptr: *const core::ffi::c_char);
131    pub fn boxcar_log_usize(n: usize);
132    pub fn boxcar_log_ptr(p: *const ());
133    pub fn boxcar_log_endl();
134    // TODO: Should this be c_char?
135    pub fn boxcars_snmalloc_message(ptr: *const u8, len: usize);
136}
137
138#[test]
139fn cown_size_and_align() {
140    #[link(name = "boxcar_bindings")]
141    extern "C" {
142        fn boxcars_test_cown_info(size: &mut usize, align: &mut usize);
143    }
144    let mut size = 0;
145    let mut align = 0;
146    unsafe {
147        boxcars_test_cown_info(&mut size, &mut align);
148    }
149    assert_eq!(size, std::mem::size_of::<OpaqueCown>());
150    assert_eq!(align, std::mem::align_of::<OpaqueCown>())
151}
152
153#[test]
154fn slot_size_and_align() {
155    extern "C" {
156        fn boxcars_test_slot_info(size: &mut usize, align: &mut usize);
157    }
158
159    let (mut size, mut align) = (0, 0);
160    unsafe { boxcars_test_slot_info(&mut size, &mut align) };
161    assert_eq!(size, std::mem::size_of::<Slot>());
162    assert_eq!(align, std::mem::align_of::<Slot>());
163}