|
|
@@ -0,0 +1,86 @@
|
|
|
+#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 操作,原子操作
|
|
|
+}
|