obkrnl/proc/cell.rs
1use super::Thread;
2use crate::context::{BorrowedArc, current_thread};
3use core::cell::Cell;
4
5/// Encapsulates a field of [Thread] that can only be accessed by the CPU that currently executing
6/// the thread.
7///
8/// # Context safety
9/// [`Default`] implementation of this type does not require a CPU context as long as implementation
10/// on `T` does not.
11#[derive(Default)]
12pub struct PrivateCell<T>(T);
13
14impl<T> PrivateCell<T> {
15 fn validate(&self, owner: &Thread) {
16 // This check will optimized out for most of the time due to the implementation of
17 // current_thread() use "pure" + "nomem" on inline assembly.
18 let current = current_thread();
19
20 if !core::ptr::eq(BorrowedArc::as_ptr(¤t), owner) {
21 panic!("accessing a private cell from the other thread is not supported");
22 }
23 }
24}
25
26impl<T> PrivateCell<Cell<T>> {
27 /// See [set] for a safe wrapper.
28 ///
29 /// # Safety
30 /// `owner` must be an owner of this field.
31 ///
32 /// # Panics
33 /// If `owner` is not the current thread.
34 pub unsafe fn set(&self, owner: &Thread, v: T) {
35 self.validate(owner);
36 self.0.set(v);
37 }
38}
39
40impl<T: Copy> PrivateCell<Cell<T>> {
41 /// See [get] for a safe wrapper.
42 ///
43 /// # Safety
44 /// `owner` must be an owner of this field.
45 ///
46 /// # Panics
47 /// If `owner` is not the current thread.
48 pub unsafe fn get(&self, owner: &Thread) -> T {
49 self.validate(owner);
50 self.0.get()
51 }
52}
53
54unsafe impl<T: Send> Sync for PrivateCell<T> {}
55
56/// Safe wrapper of [PrivateCell::set()].
57macro_rules! set {
58 ($t:ident, $f:ident, $v:expr) => {
59 // SAFETY: $t is an owner of $f.
60 unsafe { $t.$f.set($t, $v) }
61 };
62}
63
64/// Safe wrapper of [PrivateCell::get()].
65macro_rules! get {
66 ($t:ident, $f:ident) => {
67 // SAFETY: $t is an owner of $f.
68 unsafe { $t.$f.get($t) }
69 };
70}
71
72pub(super) use get;
73pub(super) use set;