|
|
|
@ -53,6 +53,7 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T>
|
|
|
|
|
{
|
|
|
|
|
let f = unsafe { Box::from_raw(f as *mut F) };
|
|
|
|
|
let ret = Box::new(f());
|
|
|
|
|
unsafe { LocalKey::<usize>::get_map() }.clear();
|
|
|
|
|
let mut processor = PROCESSOR.try().unwrap().lock();
|
|
|
|
|
let pid = processor.current_pid();
|
|
|
|
|
processor.exit(pid, Box::into_raw(ret) as usize);
|
|
|
|
@ -121,28 +122,28 @@ impl<T> JoinHandle<T> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct LocalKey<T: 'static + Default> {
|
|
|
|
|
pub struct LocalKey<T: 'static> {
|
|
|
|
|
init: fn() -> T,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: 'static + Default> LocalKey<T> {
|
|
|
|
|
impl<T: 'static> LocalKey<T> {
|
|
|
|
|
pub fn with<F, R>(&'static self, f: F) -> R
|
|
|
|
|
where F: FnOnce(&T) -> R
|
|
|
|
|
{
|
|
|
|
|
let (map, key) = self.get_map_key();
|
|
|
|
|
let map = unsafe { Self::get_map() };
|
|
|
|
|
let key = self as *const _ as usize;
|
|
|
|
|
if !map.contains_key(&key) {
|
|
|
|
|
map.insert(key, Box::new((self.init)()));
|
|
|
|
|
}
|
|
|
|
|
let value = map.get(&key).unwrap().downcast_ref::<T>().expect("type error");
|
|
|
|
|
f(value)
|
|
|
|
|
}
|
|
|
|
|
pub const fn new() -> Self {
|
|
|
|
|
LocalKey { init: Self::_init }
|
|
|
|
|
pub const fn new(init: fn() -> T) -> Self {
|
|
|
|
|
LocalKey { init }
|
|
|
|
|
}
|
|
|
|
|
fn _init() -> T { T::default() }
|
|
|
|
|
/// A `BTreeMap<usize, Box<Any>>` at kernel stack bottom
|
|
|
|
|
/// Get `BTreeMap<usize, Box<Any>>` at the current kernel stack bottom
|
|
|
|
|
/// The stack must be aligned with 0x8000
|
|
|
|
|
fn get_map_key(&self) -> (&mut BTreeMap<usize, Box<Any>>, usize) {
|
|
|
|
|
unsafe fn get_map() -> &'static mut BTreeMap<usize, Box<Any>> {
|
|
|
|
|
const STACK_SIZE: usize = 0x8000;
|
|
|
|
|
let stack_var = 0usize;
|
|
|
|
|
let ptr = (&stack_var as *const _ as usize) / STACK_SIZE * STACK_SIZE;
|
|
|
|
@ -150,9 +151,7 @@ impl<T: 'static + Default> LocalKey<T> {
|
|
|
|
|
if map.is_none() {
|
|
|
|
|
*map = Some(BTreeMap::new());
|
|
|
|
|
}
|
|
|
|
|
let map = map.as_mut().unwrap();
|
|
|
|
|
let key = self as *const _ as usize;
|
|
|
|
|
(map, key)
|
|
|
|
|
map.as_mut().unwrap()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -180,17 +179,17 @@ pub mod test {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn local_key() {
|
|
|
|
|
static FOO: thread::LocalKey<RefCell<usize>> = thread::LocalKey::new();
|
|
|
|
|
static FOO: thread::LocalKey<RefCell<usize>> = thread::LocalKey::new(|| RefCell::new(1));
|
|
|
|
|
|
|
|
|
|
FOO.with(|f| {
|
|
|
|
|
assert_eq!(*f.borrow(), 0);
|
|
|
|
|
assert_eq!(*f.borrow(), 1);
|
|
|
|
|
*f.borrow_mut() = 2;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// each thread starts out with the initial value of 1
|
|
|
|
|
thread::spawn(move || {
|
|
|
|
|
FOO.with(|f| {
|
|
|
|
|
assert_eq!(*f.borrow(), 0);
|
|
|
|
|
assert_eq!(*f.borrow(), 1);
|
|
|
|
|
*f.borrow_mut() = 3;
|
|
|
|
|
});
|
|
|
|
|
}).join();
|
|
|
|
|