| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- #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 操作,原子操作
- }
|