semaphore.h 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /**
  2. * @file semaphore.h
  3. * @author fslngjin (lonjin@RinGoTek.cn)
  4. * @brief 信号量
  5. * @version 0.1
  6. * @date 2022-04-12
  7. *
  8. * @copyright Copyright (c) 2022
  9. *
  10. */
  11. #pragma once
  12. #include <process/atomic.h>
  13. #include <process/process.h>
  14. #include <sched/sched.h>
  15. /**
  16. * @brief 信号量的等待队列
  17. *
  18. */
  19. typedef struct
  20. {
  21. struct List wait_list;
  22. struct process_control_block *pcb;
  23. } wait_queue_node_t;
  24. /**
  25. * @brief 初始化信号量的等待队列
  26. *
  27. * @param wait_queue 等待队列
  28. * @param pcb pcb
  29. */
  30. void wait_queue_init(wait_queue_node_t *wait_queue, struct process_control_block *pcb)
  31. {
  32. list_init(&wait_queue->wait_list);
  33. wait_queue->pcb = pcb;
  34. }
  35. /**
  36. * @brief 信号量的结构体
  37. *
  38. */
  39. typedef struct
  40. {
  41. atomic_t counter;
  42. wait_queue_node_t wait_queue;
  43. } semaphore_t;
  44. /**
  45. * @brief 初始化信号量
  46. *
  47. * @param sema 信号量对象
  48. * @param count 信号量的初始值
  49. */
  50. void semaphore_init(semaphore_t *sema, ul count)
  51. {
  52. atomic_set(&sema->counter, count);
  53. wait_queue_init(&sema->wait_queue, NULL);
  54. }
  55. /**
  56. * @brief 信号量down
  57. *
  58. * @param sema
  59. */
  60. void semaphore_down(semaphore_t *sema)
  61. {
  62. if (atomic_read(&sema->counter) > 0) // 信号量大于0,资源充足
  63. atomic_dec(&sema->counter);
  64. else // 资源不足,进程休眠
  65. {
  66. // 将当前进程加入信号量的等待队列
  67. wait_queue_node_t wait;
  68. wait_queue_init(&wait, current_pcb);
  69. current_pcb->state = PROC_UNINTERRUPTIBLE;
  70. list_append(&sema->wait_queue.wait_list, &wait.wait_list);
  71. // 执行调度
  72. sched_cfs();
  73. }
  74. }
  75. void semaphore_up(semaphore_t *sema)
  76. {
  77. if (list_empty(&sema->wait_queue.wait_list)) // 没有进程在等待资源
  78. {
  79. atomic_inc(&sema->counter);
  80. }
  81. else // 有进程在等待资源,唤醒进程
  82. {
  83. wait_queue_node_t *wq = container_of(list_next(&sema->wait_queue.wait_list), wait_queue_node_t, wait_list);
  84. list_del(&wq->wait_list);
  85. wq->pcb->state = PROC_RUNNING;
  86. sched_cfs_enqueue(wq->pcb);
  87. }
  88. }