#include "sync.h" // 初始化信号量 void semaphore_init(struct semaphore *sem, uint8_t value) { sem->value = value; list_init(&sem->waiters); } // 初始化锁 void lock_init(struct lock *lock) { lock->holder = NULL; lock->holder_repeat_count = 0; semaphore_init(&lock->sem, 1); // acquire 1 } // 信号量 down 操作 P void semaphore_down(struct semaphore *sem) { enum intr_status old_status = intr_disable(); // 关中断,保证原子操作 while (sem->value == 0) { // value 为 0, 表示已经被别人持有 ASSERT(!elem_find(&sem->waiters, &running_thread()->general_tag)); // 当前线程不应该出现在信号量的 waiters 中 if (elem_find(&sem->waiters, &running_thread()->general_tag)) { PANIC("semaphore_down: blocked thread in waiters list\n"); } // 若信号量的值为 0,则当前线程把自己加入等待队列,然后阻塞自己 list_append(&sem->waiters, &running_thread()->general_tag); thread_block(TASK_BLOCKED); // 阻塞自己,直到被其它线程唤醒 } // value 为 1 或被唤醒后,会执行下面的代码,也就是获得了锁 sem->value--; ASSERT(sem->value == 0); intr_set_status(old_status); // enable interrupt } // 信号量 up 操作 V void semaphore_up(struct semaphore *sem) { enum intr_status old_status = intr_disable(); // 关中断,保证原子操作 ASSERT(sem->value == 0); if (!list_empty(&sem->waiters)) { struct list_elem *elem = list_pop(&sem->waiters); struct task_struct *thread_blocked = elem2entry(struct task_struct, general_tag, elem); thread_unblock(thread_blocked); } sem->value++; ASSERT(sem->value == 1); intr_set_status(old_status); // 恢复之前的中断 } // 获取锁 void lock_acquire(struct lock *plock) { // 排除曾经自己已经持有锁但还未将其释放的情况 if (plock->holder != running_thread()) { semaphore_down(&plock->sem); // 对信号量执行 P 操作,原子操作 plock->holder = running_thread(); ASSERT(plock->holder_repeat_count == 0); plock->holder_repeat_count = 1; } else { plock->holder_repeat_count++; // 重入次数加 1 } } // 释放锁 void lock_release(struct lock *plock) { ASSERT(plock->holder == running_thread()); if (plock->holder_repeat_count > 1) { plock->holder_repeat_count--; return; } ASSERT(plock->holder_repeat_count == 1); plock->holder = NULL; plock->holder_repeat_count = 0; semaphore_up(&plock->sem); // 对信号量执行 V 操作,原子操作 }