From c33df28307a282d4782ac084e15ba8183f43e842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Rativel?= Date: Thu, 20 Apr 2023 14:43:15 +0200 Subject: [PATCH] Merging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RĂ©mi Rativel --- src/kernel/thread_manager.rs | 43 +++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index cb73fcc..b7ae47d 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -1,67 +1,67 @@ //! # Thread manager -//! +//! //! This module describes the data structure and the methods used for thread scheduling //! in the BurritOS operating system. A struct named `ThreadManager` holds the list of //! all existing threads and synchronization objects, such as `Locks`, `Semaphores` and //! `Conditions`. -//! +//! //! ## Purpose -//! +//! //! `ThreadManager` holds the state of the system processes using the following subcomponents: -//! +//! //! ### Two lists of threads -//! +//! //! - **ready_list**: The list of threads ready to be executed //! - **g_alive**: The list of currently executing threads -//! +//! //! The difference between the two above lists lies in the state of the threads in question. //! Ready threads have just been enqueued. They are not being executed yet. The second list is //! needed because many threads may be executing at a given time. However, only a single thread //! can be handled by the machine at a time. The system thus needs to keep in memory the alive //! threads in case the currently running thread finishes or gets rescheduled. -//! +//! //! ### A list of synchronization objects -//! +//! //! Locks, Semaphores and Conditions allow resource sharing among running threads. Since resources //! can only be accessed by a single thread at a time, we need data structures to signal other //! threads that a resource may be busy or unavailable; say for example that thread **A** wants to //! write to a file while **B** is currently reading said file. Thread **A** mutating the state of //! the file could cause issues for **B**. Therefore **B** needs to lock the file in question to //! avoid such issues. Thread **A** will have to wait for **B** to finish reading the file. -//! +//! //! These synchronization objects are held in an instance of the ObjAddr structure held by //! ThreadManager. Their state is mutated depending on the actions of the currently running thread -//! through methods such as `ThreadManager::sem_p`. -//! +//! through methods such as `ThreadManager::sem_p`. +//! //! ## Usage -//! +//! //! `ThreadManager` is thought as a subcomponent of the `System` struct. Instanciating //! `System` will automatically instanciate a `ThreadManager` -//! +//! //! Manually loading a Thread into ThreadManager to execute a program with BurritOS could look like //! this: -//! +//! //! ``` //! fn load_thread_manually(args: ...) { //! let mut system = System::new(args.debug); -//! +//! //! let thread_exec = Thread::new(args.executable.as_str()); //! let thread_exec = Rc::new(RefCell::new(thread_exec)); //! system.get_thread_manager().get_g_alive().push(Rc::clone(&thread_exec)); -//! +//! //! let owner1 = Process { num_thread: 0 }; //! let owner1 = Rc::new(RefCell::new(owner1)); //! system.get_thread_manager().start_thread(Rc::clone(&thread_exec), owner1, loader.elf_header.entrypoint, ptr, -1); -//! +//! //! let to_run = system.get_thread_manager().find_next_to_run().unwrap(); //! system.get_thread_manager().switch_to(&mut machine, Rc::clone(&to_run)); -//! +//! //! machine.run(&mut system); //! } //! ``` -//! +//! //! ## Imports -//! +//! //! The `List` and `ObjAddr` submodules used in this module are defined in the utility //! module. The source code of ObjAddr has been decoupled from thread_manager in an effort //! to keep this module concise. @@ -448,12 +448,14 @@ mod test { let lock = Lock::new(); let lock_id = thread_manager.get_obj_addrs().add_lock(lock); let thread = Rc::new(RefCell::new(Thread::new("test_lock"))); + let thread_test = thread.clone(); thread_manager.ready_to_run(Rc::clone(&thread)); thread_manager.set_g_current_thread(Some(thread)); thread_manager.lock_acquire(lock_id, &mut machine).expect("lock acquire return an error: "); { let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); + assert_eq!(lock.owner,Some(thread_test)); assert!(!lock.free); assert!(lock.waiting_queue.is_empty()); } @@ -461,6 +463,7 @@ mod test { thread_manager.lock_release(lock_id, &mut machine).expect("lock release return an error: "); { let lock = thread_manager.get_obj_addrs().search_lock(lock_id).unwrap(); + assert_eq!(lock.owner, None); assert!(!lock.free); assert!(lock.waiting_queue.is_empty()); }