1 /*-
2 * Copyright (c) 2010 Isilon Systems, Inc.
3 * Copyright (c) 2010 iX Systems, Inc.
4 * Copyright (c) 2010 Panasas, Inc.
5 * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
6 * Copyright (c) 2017 Mark Johnston <markj@FreeBSD.org>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice unmodified, this list of conditions, and the following
14 * disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $FreeBSD: releng/12.2/sys/compat/linuxkpi/common/include/linux/wait.h 364674 2020-08-24 13:19:16Z manu $
31 */
32
33 #ifndef _LINUX_WAIT_H_
34 #define _LINUX_WAIT_H_
35
36 #include <linux/spinlock.h>
37 #include "los_event.h"
38 #include "los_sys.h"
39
40 #ifdef __cplusplus
41 #if __cplusplus
42 extern "C" {
43 #endif /* __cplusplus */
44 #endif /* __cplusplus */
45
46 /**
47 * Notice about wait_queue_head_t:
48 * 1.The stEvent is used for task-synchronization and has the same function as wait_event_head in Linux.
49 * In LiteOS, when wait_event is called, if the condition is not true, the task will be blocked and
50 * mounted on stEvent.stEventList. In Linux, the blocked task will be mounted on wait_queue_head.task_list.
51 * 2.The lock and poll_queue are only used for poll operation: poll_queue is used to link poll_wait_node,
52 * and lock is used to protect this poll_queue.
53 */
54 typedef struct wait_queue_head {
55 EVENT_CB_S stEvent;
56 spinlock_t lock;
57 LOS_DL_LIST poll_queue;
58 } wait_queue_head_t;
59
60 #define osWaitForever 0xFFFFFFFF
61 #define INVALID_ADDR 0xFFFFFFFF
62 #define DECLARE_WAIT_QUEUE_HEAD(wq) \
63 wait_queue_head_t wq = { { 0, { (struct LOS_DL_LIST *)0xFFFFFFFF, (struct LOS_DL_LIST *)0xFFFFFFFF } }, \
64 SPIN_LOCK_INITIALIZER("wait_queue_spinlock"), \
65 { &wq.poll_queue, &wq.poll_queue } }
66
67 void __wake_up_interruptible(wait_queue_head_t *wait);
68 void __init_waitqueue_head(wait_queue_head_t *wait);
69
70 /**
71 * @ingroup wait
72 * @brief Initialize the waitqueue head.
73 *
74 * @par Description:
75 * This API is used to initialize the waitqueue head.
76 *
77 * @attention
78 * <ul>
79 * <li>Please make sure the input parameter wait is valid, otherwise, the system would be crash.</li>
80 * </ul>
81 *
82 * @param wait [IN] struct of the process that registered on the wait queue .
83 *
84 * @retval None.
85 * @par Dependency:
86 * <ul><li>Wait.h: the header file that contains the API declaration.</li></ul>
87 * @see none
88 */
89 #define init_waitqueue_head(wait) __init_waitqueue_head(wait)
90
91 /**
92 * @ingroup wait
93 * @brief wakeup the process that registered on the wait queue.
94 *
95 * @par Description:
96 * This API is used to wakeup the process that registered on the wait queue.
97 *
98 * @attention
99 * <ul>
100 * <li>Please make sure the input parameter wait is valid, otherwise, the system would be crash.</li>
101 * </ul>
102 *
103 * @param wait [IN] struct of the process that registered on the wait queue .
104 *
105 * @retval None.
106 * @par Dependency:
107 * <ul><li>Wait.h: the header file that contains the API declaration.</li></ul>
108 * @see none
109 */
110 #define wake_up_interruptible(wait) __wake_up_interruptible(wait)
111 #define wake_up_interruptible_poll(wait, key) __wake_up_interruptible_poll(wait, key)
112
113 /**
114 * @ingroup wait
115 * @brief wakeup the process that registered on the wait queue.
116 *
117 * @par Description:
118 * This API is used to wakeup the process that registered on the wait queue.
119 *
120 * @attention
121 * <ul>
122 * <li>Please look up the function __wake_up_interruptible(wait).</li>
123 * </ul>
124 *
125 * @param None.
126 *
127 * @retval None.
128 * @par Dependency:
129 * <ul><li>Wait.h: the header file that contains the API declaration.</li></ul>
130 * @see wake_up_interruptible
131 */
132 #define wake_up wake_up_interruptible
133
134 /**
135 * @ingroup wait
136 * @brief sleep until a condition gets true.
137 *
138 * @par Description:
139 * This API is used to sleep a process until the condition evaluates to true.
140 * The condition is checked each time when the waitqueue wait is woken up.
141 *
142 * @attention
143 * <ul>
144 * <li>none.</li>
145 * </ul>
146 *
147 * @param wait [IN] the waitqueue to wait on.
148 * @param condition [IN] a condition evaluates to true or false.
149
150 * @retval #0 always return 0
151
152 * @par Dependency:
153 * <ul><li>linux\wait.h: the header file that contains the API declaration.</li></ul>
154 * @see
155 */
156 #define wait_event(wait, condition) ({ \
157 INT32 ret = 0; \
158 \
159 if ((wait).stEvent.stEventList.pstPrev == (struct LOS_DL_LIST *)INVALID_ADDR) { \
160 (VOID)LOS_EventInit(&(wait).stEvent); \
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 #define wait_event_interruptible wait_event
169
170 /**
171 * @ingroup wait
172 * @brief sleep until a condition gets true or a timeout elapses.
173 *
174 * @par Description:
175 * This API is used to sleep a process until the condition evaluates to true or a timeout elapses.
176 * The condition is checked each time when the waitqueue wait is woken up.
177 *
178 * @attention
179 * <ul>
180 * <li>none.</li>
181 * </ul>
182 *
183 * @param wait [IN] the waitqueue to wait on.
184 * @param condition [IN] a condition evaluates to true or false.
185 * @param timeout [IN] the max sleep time (unit : Tick). it is jiffies in linux.
186 *
187 * @retval #0 return 0 if the condition evaluated to false after the timeout elapsed
188 * @retval #1 return 1 if the condition evaluated to true after the timeout elapsed
189 * @retval #2 return 2 if the condition evaluated to true and the timeout is osWaitForever
190 *
191 * @par Dependency:
192 * <ul><li>linux\wait.h: the header file that contains the API declaration.</li></ul>
193 * @see
194 */
195 #define wait_event_interruptible_timeout(wait, condition, timeout) ({ \
196 INT32 tmpTimeout; \
197 UINT32 ret = 2; \
198 UINT64 ticksnow; \
199 \
200 if ((wait).stEvent.stEventList.pstPrev == (struct LOS_DL_LIST *)INVALID_ADDR) { \
201 (VOID)LOS_EventInit(&(wait).stEvent); \
202 } \
203 while (!(condition)) { \
204 ticksnow = LOS_TickCountGet(); \
205 ret = LOS_EventRead(&(wait).stEvent, 0x1U, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, (timeout)); \
206 if ((timeout) == osWaitForever) { \
207 if (condition) { \
208 ret = 2; \
209 break; \
210 } else { \
211 continue; \
212 } \
213 } \
214 tmpTimeout = (INT32)((timeout) - (UINT32)(LOS_TickCountGet() - ticksnow)); \
215 if (tmpTimeout <= 0) { \
216 ret = (condition) ? 1 : 0; \
217 break; \
218 } else { \
219 if (ret == LOS_ERRNO_EVENT_READ_TIMEOUT) { \
220 if (condition) { \
221 ret = 1; \
222 break; \
223 } else { \
224 ret = 0; \
225 break; \
226 } \
227 } else { \
228 if (condition) { \
229 ret = 2; \
230 break; \
231 } \
232 } \
233 } \
234 } \
235 ret; \
236 })
237
238 #define add_wait_queue(wait, newWait) do {} while (0)
239 #define remove_wait_queue(wait, oldWait) do {} while (0)
240 #define DECLARE_WAITQUEUE(wait, current) do {} while (0)
241
linux_waitqueue_active(wait_queue_head_t * q)242 static inline int linux_waitqueue_active(wait_queue_head_t *q)
243 {
244 return !LOS_ListEmpty(&(q->stEvent.stEventList));
245 }
246
247 #define waitqueue_active(wqh) linux_waitqueue_active(wqh)
248
249 #ifdef __cplusplus
250 #if __cplusplus
251 }
252 #endif /* __cplusplus */
253 #endif /* __cplusplus */
254
255 #endif /* _LINUX_WAIT_H_ */
256