Merge branch 'fix-double-free' into 'thread_scheduler'

Fix double free

See merge request simpleos/burritos!15
This commit is contained in:
Legot Quentin 2023-05-04 22:14:47 +00:00
commit 6eeaa57647

View File

@ -355,29 +355,31 @@ impl ThreadManager {
/// Wake up a waiter if necessary, or release it if no thread is waiting. /// Wake up a waiter if necessary, or release it if no thread is waiting.
pub fn lock_release(&mut self, id: i32, machine: &mut Machine) -> Result<MachineOk, MachineError> { pub fn lock_release(&mut self, id: i32, machine: &mut Machine) -> Result<MachineOk, MachineError> {
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
let current_thread = match self.get_g_current_thread() { let current_thread = match self.get_g_current_thread() {
Some(thread) => Rc::clone(thread), Some(thread) => Rc::clone(thread),
None => Err(String::from("lock_release error: current_thread should not be None."))? None => Err(String::from("lock_release error: current_thread should not be None."))?
}; };
let mut lock = match self.get_obj_addrs().search_lock(id).cloned() { let mut lock = match self.get_obj_addrs().search_lock(id) {
Some(lock) => lock, Some(lock) => lock,
None => Err(String::from("lock_release error: cannot find lock."))? None => Err(String::from("lock_release error: cannot find lock."))?
}; };
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
if let Some(lock_owner) = &lock.owner { if let Some(lock_owner) = &lock.owner {
if Rc::ptr_eq(&current_thread, lock_owner) { if current_thread.eq(lock_owner) { // is_held_by_current_thread
if let Some(thread) = lock.waiting_queue.pop() { match lock.waiting_queue.pop() {
if !lock.waiting_queue.is_empty() { Some(th) => {
let clone = Rc::clone(&thread); lock.owner = Some(Rc::clone(&th));
lock.owner = Some(thread); self.ready_to_run(Rc::clone(&th));
self.ready_to_run(clone); },
} else { None => {
lock.free = true; lock.free = true;
lock.owner = None; lock.owner = None;
}} }
}
} }
}; };
self.get_obj_addrs().update_lock(id, lock); // self.get_obj_addrs().update_lock(id, lock);
machine.interrupt.set_status(old_status); machine.interrupt.set_status(old_status);
Ok(MachineOk::Ok) Ok(MachineOk::Ok)
} }
@ -482,35 +484,36 @@ mod test {
let lock_id = thread_manager.get_obj_addrs().add_lock(lock); let lock_id = thread_manager.get_obj_addrs().add_lock(lock);
let thread_1 = Rc::new(RefCell::new(Thread::new("test_lock_1"))); let thread_1 = Rc::new(RefCell::new(Thread::new("test_lock_1")));
let thread_2 = Rc::new(RefCell::new(Thread::new("test_lock_2"))); let thread_2 = Rc::new(RefCell::new(Thread::new("test_lock_2")));
let thread_test_1 = thread_1.clone(); thread_manager.ready_to_run(thread_1.clone());
let thread_test_2 = thread_2.clone(); thread_manager.ready_to_run(thread_2.clone());
thread_manager.ready_to_run(Rc::clone(&thread_1)); thread_manager.set_g_current_thread(Some(thread_1.clone()));
thread_manager.ready_to_run(Rc::clone(&thread_2));
thread_manager.set_g_current_thread(Some(thread_1));
thread_manager.lock_acquire(lock_id, &mut machine).expect("lock acquire return an error at first iteration: "); thread_manager.lock_acquire(lock_id, &mut machine).expect("lock acquire return an error at first iteration: ");
{ {
let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap();
assert_eq!(lock.owner,Some(thread_test_1.clone())); assert_eq!(lock.owner,Some(thread_1.clone()));
assert!(!lock.free); assert!(!lock.free);
assert!(lock.waiting_queue.is_empty()); assert!(lock.waiting_queue.is_empty());
} }
thread_manager.set_g_current_thread(Some(thread_2)); thread_manager.set_g_current_thread(Some(thread_2.clone()));
thread_manager.lock_acquire(lock_id, &mut machine).expect("lock acquire return an error at second iteration: "); thread_manager.lock_acquire(lock_id, &mut machine).expect("lock acquire return an error at second iteration: ");
{ {
let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap();
assert_eq!(lock.owner,Some(thread_test_1)); assert_eq!(lock.owner,Some(thread_1.clone()));
assert!(!lock.free); assert!(!lock.free);
assert_eq!(lock.waiting_queue.iter().count(),1); assert_eq!(lock.waiting_queue.iter().count(),1);
} }
thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error at first iteration: "); thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error at first iteration: ");
{ {
let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap();
assert_eq!(lock.owner, Some(thread_test_2)); assert_eq!(lock.owner, Some(thread_2.clone()));
assert!(!lock.free); assert!(!lock.free);
assert!(lock.waiting_queue.is_empty()); assert!(lock.waiting_queue.is_empty());
} }
thread_manager.set_g_current_thread(Some(thread_2.clone()));
thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error at second iteration: "); thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error at second iteration: ");
{ {
let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap();