操作系统 Lab 5


Lab 5

功能实现

sys_enable_deadlock_detect

  1. 修改 ProcessControlBlockInner 结构体, 为 mutexsemaphore 分别实现死锁检测算法所需的数据结构.
  2. ProcessControlBlockInner 结构体实现 fn deadlock_detect() 进行死锁检测.
  3. sys_thread_create() 创建新线程时, 更新 allocationneed.
  4. sys_mutex_create()sys_semaphore_create() 创建资源后, 更新 available 的大小, 扩展 allocationneed.
  5. sys_mutex_lock()sys_semaphore_down() 申请资源时, 将 need 增加, 并进行死锁检测, 通过后减少 need, 减少 available 并增加 allocation 以使用资源.
  6. sys_mutex_unlock()sys_semaphore_up() 归还资源, 将 available 增加, allocation 减少以释放资源.

实验用时

  1. 阅读文档及代码框架: 2h.
  2. 功能实现与报告: 2.5h.

问答题

  1. 在我们的多线程实现中, 当主线程 (即 0 号线程) 退出时, 视为整个进程退出, 此时需要结束该进程管理的所有线程并回收其资源. 需要回收的资源有哪些? 其他线程的 TaskControlBlock 可能在哪些位置被引用, 分别是否需要回收, 为什么?

    答: (1) 回收所有子线程的 TaskUserRes, 包括用户栈, Trap 上下文以及进程 pid, 回收子进程列表以及用户空间数据. (2) 其他线程的 TaskControlBlock 可能在调度队列或等待某些同步原语时被引用, 无需回收, 会在主线程回收时一起回收.

  1. 对比以下两种 Mutex.unlock 的实现, 二者有什么区别? 这些区别可能会导致什么问题?

    impl Mutex for Mutex1 {
        fn unlock(&self) {
            let mut mutex_inner = self.inner.exclusive_access();
            assert!(mutex_inner.locked);
            mutex_inner.locked = false;
            if let Some(waking_task) = mutex_inner.wait_queue.pop_front() {
                add_task(waking_task);
            }
        }
    }
    
    impl Mutex for Mutex2 {
        fn unlock(&self) {
            let mut mutex_inner = self.inner.exclusive_access();
            assert!(mutex_inner.locked);
            if let Some(waking_task) = mutex_inner.wait_queue.pop_front() {
                add_task(waking_task);
            } else {
                mutex_inner.locked = false;
            }
        }
    }

    答: 二者的区别在于对锁的状态修改. 第一种实现的逻辑是错误的.

    第一种释放锁时, 可能会被其他线程抢占, 任务不一定持有锁; 第二种将任务加入队列时, 同时实现了锁的继承.


文章作者: Chengsx
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Chengsx !
  目录