diff --git a/src/lib.rs b/src/lib.rs index 5bdb6ac..68affee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -115,6 +115,7 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) -> ! { unsafe { arch::interrupt::enable(); } +// thread::test::local_key(); // thread::test::unpack(); // sync::test::philosopher_using_mutex(); // sync::test::philosopher_using_monitor(); diff --git a/src/thread.rs b/src/thread.rs index e53881c..3a19637 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -53,6 +53,7 @@ pub fn spawn(f: F) -> JoinHandle { let f = unsafe { Box::from_raw(f as *mut F) }; let ret = Box::new(f()); + unsafe { LocalKey::::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 JoinHandle { } } -pub struct LocalKey { +pub struct LocalKey { init: fn() -> T, } -impl LocalKey { +impl LocalKey { pub fn with(&'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::().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>` at kernel stack bottom + /// Get `BTreeMap>` at the current kernel stack bottom /// The stack must be aligned with 0x8000 - fn get_map_key(&self) -> (&mut BTreeMap>, usize) { + unsafe fn get_map() -> &'static mut BTreeMap> { 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 LocalKey { 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> = thread::LocalKey::new(); + static FOO: thread::LocalKey> = 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();