Merge branch 'thread_scheduler' into 'thread_join'
Merge Thread scheduler to thread_join See merge request simpleos/burritos!16
This commit is contained in:
commit
e0eb027aea
@ -367,29 +367,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(¤t_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)
|
||||||
}
|
}
|
||||||
@ -494,35 +496,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();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Start.s
|
/* Start.s
|
||||||
* Assembly language assist for user programs running on top of Nachos.
|
* Assembly language assist for user programs running on top of BurritOS.
|
||||||
*
|
*
|
||||||
* Since we don't want to pull in the entire C library, we define
|
* Since we don't want to pull in the entire C library, we define
|
||||||
* what we need for a user program here, namely Start and the system
|
* what we need for a user program here, namely Start and the system
|
||||||
|
Loading…
Reference in New Issue
Block a user