• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /**
16  * @defgroup wait Wait
17  * @ingroup linux
18  */
19 #ifndef _LINUX_WAIT_H
20 #define _LINUX_WAIT_H
21 
22 #include <linux/spinlock.h>
23 #include "los_event.h"
24 #include "los_typedef.h"
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif /* __cplusplus */
29 
30 /**
31  * Notice about wait_queue_head_t:
32  * 1.The stEvent is used for task-synchronization and has the same function as wait_event_head in Linux.
33  *   In LiteOS, when wait_event is called, if the condition is not true, the task will be blocked and
34  *   mounted on stEvent.stEventList. In Linux, the blocked task will be mounted on wait_queue_head.task_list.
35  * 2.The lock and poll_queue are only used for poll operation: poll_queue is used to link poll_wait_node,
36  *   and lock is used to protect this poll_queue.
37  */
38 typedef struct wait_queue_head {
39     EVENT_CB_S     stEvent;
40     spinlock_t     lock;
41     LOS_DL_LIST    poll_queue;
42 } wait_queue_head_t;
43 
44 #define osWaitForever     0xFFFFFFFFU     /* wait forever timeout value */
45 #define DECLARE_WAIT_QUEUE_HEAD(wq) wait_queue_head_t wq = { { 0, &wq.stEvent.stEventList, &wq.stEvent.stEventList },  \
46                                                              SPIN_LOCK_INITIALIZER("wait_queue_spinlock"), \
47                                                              { &wq.poll_queue, &wq.poll_queue } }
48 
49 void __init_waitqueue_head(wait_queue_head_t *wait);
50 
51 /**
52  * @ingroup  wait
53  * @brief Initialize the waitqueue head.
54  *
55  * @par Description:
56  * This API is used to initialize the waitqueue head.
57  *
58  * @attention
59  * <ul>
60  * <li>Please make sure the input parameter wait is valid, otherwise, the system would crash.</li>
61  * </ul>
62  *
63  * @param  wait [IN]  Pointer to the waiting queue.
64  *
65  * @retval None.
66  * @par Dependency:
67  * <ul><li>Wait.h: the header file that contains the API declaration.</li></ul>
68  * @see None.
69  */
70 #define init_waitqueue_head(wait) __init_waitqueue_head(wait)
71 
72 void __wake_up_interruptible(wait_queue_head_t *wait);
73 
74 /**
75  * @ingroup  wait
76  * @brief wakeup the process that registered on the wait queue.
77  *
78  * @par Description:
79  * This API is used to wakeup the process that registered on the wait queue.
80  *
81  * @attention
82  * <ul>
83  * <li>Please make sure the input parameter wait is valid, otherwise, the system would crash.</li>
84  * </ul>
85  *
86  * @param  wait [IN]  Pointer to the waiting queue.
87  *
88  * @retval None.
89  * @par Dependency:
90  * <ul><li>Wait.h: the header file that contains the API declaration.</li></ul>
91  * @see wake_up.
92  */
93 #define wake_up_interruptible(wait) __wake_up_interruptible(wait)
94 
95 void __wake_up_interruptible_poll(wait_queue_head_t *wait, unsigned int key);
96 
97 /**
98  * @ingroup  wait
99  * @brief wakeup the process that registered on the wait queue.
100  *
101  * @par Description:
102  * This API is used to wakeup the process that registered on the wait queue.
103  *
104  * @attention
105  * <ul>
106  * <li>Please make sure the input parameter wait is valid, otherwise, the system would crash.</li>
107  * <li>This function is used to wake up the queue head with multiple events waiting.</li>
108  * </ul>
109  *
110  * @param  wait [IN]  Pointer to the waiting queue.
111  * @param  key  [IN]  Mask for waiting events.
112  *
113  * @retval None.
114  * @par Dependency:
115  * <ul><li>Wait.h: the header file that contains the API declaration.</li></ul>
116  * @see wake_up_interruptible.
117  */
118 #define wake_up_interruptible_poll(wait, key) __wake_up_interruptible_poll(wait, key)
119 
120 /**
121  * @ingroup  wait
122  * @brief wakeup the process that registered on the wait queue.
123  *
124  * @par Description:
125  * This API is used to wake up the process that registered on the wait queue.
126  *
127  * @attention
128  * <ul>
129  * <li>Please make sure the input parameter wait is valid, otherwise, the system would crash.</li>
130  * </ul>
131  *
132  * @param  wait [IN]  Pointer to the waiting queue.
133  *
134  * @retval None.
135  * @par Dependency:
136  * <ul><li>Wait.h: the header file that contains the API declaration.</li></ul>
137  * @see wake_up_interruptible
138  */
139 #define wake_up(wait)        wake_up_interruptible(wait)
140 
141 /**
142  * @ingroup wait
143  * @brief sleep until a condition gets true.
144  *
145  * @attention
146  * <ul>
147  * <li>The OS does not support signal interrupts.</li>
148  * <li>This event does not support interrupting by a signal.</li>
149  * </ul>
150  * @param  wait         [IN] the waitqueue to wait on.
151  * @param  condition    [IN] a condition evaluates to true or false.
152  *
153  * @retval #0 always return 0
154  *
155  * @par Dependency:
156  * <ul><li>wait.h: the header file that contains the API declaration.</li></ul>
157  * @see wait_event.
158  */
159 #define wait_event_interruptible(wait, condition) ({                                                       \
160     int ret = 0;                                                                                           \
161                                                                                                            \
162     while (!(condition)) {                                                                                 \
163         (void)LOS_EventRead(&(wait).stEvent, 0x1U, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); \
164     }                                                                                                      \
165     ret;                                                                                                   \
166 })
167 
168 /**
169  * @ingroup wait
170  * @brief sleep until a condition gets true.
171  *
172  * @par Description:
173  * This API is used to sleep  a process until the condition evaluates to true.
174  * The condition is checked each time when the waitqueue wait is woken up.
175  *
176  * @attention
177  * None.
178  *
179  * @param  wait         [IN] the waitqueue to wait on.
180  * @param  condition    [IN] a condition evaluates to true or false.
181  *
182  * @retval None.
183  *
184  * @par Dependency:
185  * <ul><li>wait.h: the header file that contains the API declaration.</li></ul>
186  * @see wait_event_interruptible.
187  */
188 #define wait_event(wait, condition)  (VOID)wait_event_interruptible(wait, condition)
189 
190 /**
191  * @ingroup wait
192  * @brief sleep until a condition gets true or a timeout elapses.
193  *
194  * @par Description:
195  * This API is used to sleep  a process until the condition evaluates to true or a timeout elapses.
196  * The condition is checked each time when the waitqueue wait is woken up.
197  *
198  * @attention
199  * <ul>
200  * <li>This API does not fully adapt to Linux, and the returned values are different.</li>
201  * <li>The value range of parameter timeout is [0, 0xFFFFFFFF], and 0xFFFFFFFF means waiting forever.</li>
202  * <li>This event does not support interrupting by a signal.</li>
203  * </ul>
204  *
205  * @param  wait         [IN] the waitqueue to wait on.
206  * @param  condition    [IN] a condition evaluates to true or false.
207  * @param  timeout      [IN] the max sleep time (unit : Tick). it is jiffies in linux.
208  *
209  * @retval #0 return 0 if the condition evaluated to false after the timeout elapsed
210  * @retval #1 return 1 if the condition evaluated to true after the timeout elapsed
211  * @retval #2 return 2 if the condition evaluated to true and the timeout is osWaitForever
212  * @retval #others return the remaining ticks if the condition evaluated to true before the timeout elapsed
213  *
214  * @par Dependency:
215  * <ul><li>linux\wait.h: the header file that contains the API declaration.</li></ul>
216  * @see wait_event_interruptible.
217  */
218 #define wait_event_interruptible_timeout(wait, condition, timeout)  ({                               \
219     INT32 tmpTimeout;                                                                                \
220     UINT32 ret = (timeout);                                                                          \
221     UINT64 ticksnow;                                                                                 \
222                                                                                                      \
223     ticksnow = LOS_TickCountGet();                                                                   \
224     tmpTimeout = (timeout);                                                                          \
225     if ((condition) && ((timeout) == 0)) {                                                           \
226         ret = 1;                                                                                     \
227     }                                                                                                \
228     while (!(condition)) {                                                                           \
229         ret = LOS_EventRead(&(wait).stEvent, 0x1U, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, tmpTimeout); \
230         if ((timeout) == osWaitForever) {                                                            \
231             if (!(condition)) {                                                                      \
232                 continue;                                                                            \
233             }                                                                                        \
234             ret = 2;                                                                                 \
235             break;                                                                                   \
236         }                                                                                            \
237         tmpTimeout = (INT32)((timeout) - (UINT32)(LOS_TickCountGet() - ticksnow));                   \
238                                                                                                      \
239         /* If the timeout elapsed or read event times out, the wait ends. */                         \
240         if ((tmpTimeout <= 0) || ((tmpTimeout > 0) && (ret == LOS_ERRNO_EVENT_READ_TIMEOUT))) {      \
241             ret = (condition) ? 1 : 0;                                                               \
242             break;                                                                                   \
243         }                                                                                            \
244                                                                                                      \
245         if (condition) {                                                                             \
246             ret = (UINT32)tmpTimeout;                                                                \
247             break;                                                                                   \
248         }                                                                                            \
249     }                                                                                                \
250     ret;                                                                                             \
251 })
252 
253 #define add_wait_queue(wait, newWait) do {} while (0)
254 #define remove_wait_queue(wait, oldWait) do {} while (0)
255 #define DECLARE_WAITQUEUE(wait, current) do {} while (0)
256 
257 /**
258  * @ingroup wait
259  * @brief Check whether the waitqueue is active.
260  *
261  * @par Description:
262  * This API is used to check whether the waitqueue is active.
263  *
264  * @attention
265  * <ul>
266  * <li> The parameter passed in should be a legal pointer. </li>
267  * </ul>
268  *
269  * @param  q    [IN] The waitqueue to be checked.
270  *
271  * @retval #0 The queue is not active.
272  * @retval #1 The queue is active.
273  *
274  * @par Dependency:
275  * <ul><li>linux\wait.h: the header file that contains the API declaration.</li></ul>
276  * @see None.
277  */
waitqueue_active(wait_queue_head_t * q)278 static inline int waitqueue_active(wait_queue_head_t *q)
279 {
280     return !LOS_ListEmpty(&(q->stEvent.stEventList));
281 }
282 
283 #ifdef __cplusplus
284 }
285 #endif /* __cplusplus */
286 
287 #endif /* _LINUX_WAIT_H */
288