1 #pragma once
2 #include <common/glib.h>
3 #include <common/spinlock.h>
4 struct process_control_block;
5 
6 // todo: 按照linux里面的样子,修正等待队列。也就是修正好wait_queue_node和wait_queue_head的意思。
7 
8 /**
9  * @brief 信号量的等待队列
10  *
11  */
12 typedef struct
13 {
14     struct List wait_list;
15     struct process_control_block *pcb;
16 } wait_queue_node_t;
17 
18 /**
19  * @brief 初始化等待队列
20  *
21  * @param wait_queue 等待队列
22  * @param pcb pcb
23  */
24 void wait_queue_init(wait_queue_node_t *wait_queue, struct process_control_block *pcb);
25 
26 /**
27  * @brief 在等待队列上进行等待
28  *
29  * @param wait_queue_head 队列头指针
30  */
31 void wait_queue_sleep_on(wait_queue_node_t *wait_queue_head);
32 
33 /**
34  * @brief 在等待队列上进行等待,同时释放自旋锁
35  *
36  * @param wait_queue_head 队列头指针
37  */
38 void wait_queue_sleep_on_unlock(wait_queue_node_t *wait_queue_head, void *lock);
39 /**
40  * @brief 在等待队列上进行等待(允许中断)
41  *
42  * @param wait_queue_head 队列头指针
43  */
44 void wait_queue_sleep_on_interriptible(wait_queue_node_t *wait_queue_head);
45 
46 /**
47  * @brief 唤醒在等待队列的头部的进程
48  *
49  * @param wait_queue_head 队列头
50  * @param state 要唤醒的进程的状态
51  */
52 void wait_queue_wakeup(wait_queue_node_t *wait_queue_head, int64_t state);
53 
54 typedef struct
55 {
56     struct List wait_list;
57     spinlock_t lock; // 队列需要有一个自旋锁,虽然目前内部并没有使用,但是以后可能会用.[在completion内部使用]
58 } wait_queue_head_t;
59 
60 #define DECLARE_WAIT_ON_STACK(name, pcb) \
61     wait_queue_node_t name = {0};        \
62     wait_queue_init(&(name), pcb);
63 
64 #define DECLARE_WAIT_ON_STACK_SELF(name) \
65     wait_queue_node_t name = {0};        \
66     wait_queue_init(&(name), current_pcb);
67 
68 #define DECLARE_WAIT_ALLOC(name, pcb)                                                     \
69     wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
70     wait_queue_init(&(name), pcb);
71 
72 #define DECLARE_WAIT_ALLOC_SELF(name)                                                     \
73     wait_queue_node_t *wait = (wait_queue_node_t *)kzalloc(sizeof(wait_queue_node_t), 0); \
74     wait_queue_init(&(name), current_pcb);
75 
76 #define DECLARE_WAIT_QUEUE_HEAD(name)    \
77     struct wait_queue_head_t name = {0}; \
78     wait_queue_head_init(&name);
79 
80 /**
81  * @brief 初始化wait_queue队列头
82  *
83  * @param wait_queue
84  */
85 void wait_queue_head_init(wait_queue_head_t *wait_queue);
86 
87 /**
88  * @brief 在等待队列上进行等待, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
89  *
90  * @param q 队列头指针
91  * @param wait wait节点
92  */
93 void wait_queue_sleep_with_node(wait_queue_head_t *q, wait_queue_node_t *wait);
94 
95 /**
96  * @brief  在等待队列上进行等待,同时释放自旋锁, 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
97  *
98  * @param q  队列头指针
99  * @param wait wait节点
100  * @param lock
101  */
102 void wait_queue_sleep_with_node_unlock(wait_queue_head_t *q, wait_queue_node_t *wait, void *lock);
103 
104 /**
105  * @brief 在等待队列上进行等待(允许中断), 但是你需要确保wait已经被init, 同时wakeup只能使用wake_up_on_stack函数。
106  *
107  * @param wait_queue_head 队列头指针
108  * @param wait wait节点
109  */
110 void wait_queue_sleep_with_node_interriptible(wait_queue_head_t *q, wait_queue_node_t *wait);
111 
112 /**
113  * @brief 唤醒在等待队列的头部的进程, 但是不会free掉这个节点的空间(默认这个节点在栈上创建)
114  *
115  * @param wait_queue_head_t  q: 队列头
116  * @param state 要唤醒的进程的状态
117  */
118 void wait_queue_wakeup_on_stack(wait_queue_head_t *q, int64_t state);