sync.c 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #include "sync.h"
  2. // 初始化信号量
  3. void semaphore_init(struct semaphore *sem, uint8_t value)
  4. {
  5. sem->value = value;
  6. list_init(&sem->waiters);
  7. }
  8. // 初始化锁
  9. void lock_init(struct lock *lock)
  10. {
  11. lock->holder = NULL;
  12. lock->holder_repeat_count = 0;
  13. semaphore_init(&lock->sem, 1); // acquire 1
  14. }
  15. // 信号量 down 操作 P
  16. void semaphore_down(struct semaphore *sem)
  17. {
  18. enum intr_status old_status = intr_disable(); // 关中断,保证原子操作
  19. while (sem->value == 0)
  20. { // value 为 0, 表示已经被别人持有
  21. ASSERT(!elem_find(&sem->waiters, &running_thread()->general_tag));
  22. // 当前线程不应该出现在信号量的 waiters 中
  23. if (elem_find(&sem->waiters, &running_thread()->general_tag))
  24. {
  25. PANIC("semaphore_down: blocked thread in waiters list\n");
  26. }
  27. // 若信号量的值为 0,则当前线程把自己加入等待队列,然后阻塞自己
  28. list_append(&sem->waiters, &running_thread()->general_tag);
  29. thread_block(TASK_BLOCKED); // 阻塞自己,直到被其它线程唤醒
  30. }
  31. // value 为 1 或被唤醒后,会执行下面的代码,也就是获得了锁
  32. sem->value--;
  33. ASSERT(sem->value == 0);
  34. intr_set_status(old_status); // enable interrupt
  35. }
  36. // 信号量 up 操作 V
  37. void semaphore_up(struct semaphore *sem)
  38. {
  39. enum intr_status old_status = intr_disable(); // 关中断,保证原子操作
  40. ASSERT(sem->value == 0);
  41. if (!list_empty(&sem->waiters))
  42. {
  43. struct list_elem *elem = list_pop(&sem->waiters);
  44. struct task_struct *thread_blocked = elem2entry(struct task_struct, general_tag, elem);
  45. thread_unblock(thread_blocked);
  46. }
  47. sem->value++;
  48. ASSERT(sem->value == 1);
  49. intr_set_status(old_status); // 恢复之前的中断
  50. }
  51. // 获取锁
  52. void lock_acquire(struct lock *plock)
  53. {
  54. // 排除曾经自己已经持有锁但还未将其释放的情况
  55. if (plock->holder != running_thread())
  56. {
  57. semaphore_down(&plock->sem); // 对信号量执行 P 操作,原子操作
  58. plock->holder = running_thread();
  59. ASSERT(plock->holder_repeat_count == 0);
  60. plock->holder_repeat_count = 1;
  61. }
  62. else
  63. {
  64. plock->holder_repeat_count++; // 重入次数加 1
  65. }
  66. }
  67. // 释放锁
  68. void lock_release(struct lock *plock)
  69. {
  70. ASSERT(plock->holder == running_thread());
  71. if (plock->holder_repeat_count > 1)
  72. {
  73. plock->holder_repeat_count--;
  74. return;
  75. }
  76. ASSERT(plock->holder_repeat_count == 1);
  77. plock->holder = NULL;
  78. plock->holder_repeat_count = 0;
  79. semaphore_up(&plock->sem); // 对信号量执行 V 操作,原子操作
  80. }