• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
31 #ifndef _LINUXKPI_LINUX_WAIT_H_
32 #define	_LINUXKPI_LINUX_WAIT_H_
33 
34 #include <linux/spinlock.h>
35 #include "los_event.h"
36 #include "los_sys.h"
37 
38 #ifdef __cplusplus
39 #if __cplusplus
40 extern "C" {
41 #endif /* __cplusplus */
42 #endif /* __cplusplus */
43 
44 /**
45  * Notice about wait_queue_head_t:
46  * 1.The stEvent is used for task-synchronization and has the same function as wait_event_head in Linux.
47  *   In LiteOS, when wait_event is called, if the condition is not true, the task will be blocked and
48  *   mounted on stEvent.stEventList. In Linux, the blocked task will be mounted on wait_queue_head.task_list.
49  * 2.The lock and poll_queue are only used for poll operation: poll_queue is used to link poll_wait_node,
50  *   and lock is used to protect this poll_queue.
51  */
52 typedef struct wait_queue_head {
53     EVENT_CB_S     stEvent;
54     spinlock_t     lock;
55     LOS_DL_LIST    poll_queue;
56 } wait_queue_head_t;
57 
58 #define osWaitForever     0xFFFFFFFF
59 #define INVALID_ADDR      0xFFFFFFFF
60 #define DECLARE_WAIT_QUEUE_HEAD(wq) \
61         wait_queue_head_t wq = { { 0, { (struct LOS_DL_LIST *)0xFFFFFFFF, (struct LOS_DL_LIST *)0xFFFFFFFF } },	\
62         SPIN_LOCK_INITIALIZER("wait_queue_spinlock"),			\
63         { &wq.poll_queue, &wq.poll_queue } }
64 
65 void __wake_up_interruptible(wait_queue_head_t *wait);
66 void __init_waitqueue_head(wait_queue_head_t *wait);
67 
68 /**
69  * @ingroup  wait
70  * @brief Initialize the waitqueue head.
71  *
72  * @par Description:
73  * This API is used to initialize the waitqueue head.
74  *
75  * @attention
76  * <ul>
77  * <li>Please make sure the input parameter wait is valid, otherwise, the system would be crash.</li>
78  * </ul>
79  *
80  * @param  wait [IN]  struct of the process that registered on the wait queue .
81  *
82  * @retval None.
83  * @par Dependency:
84  * <ul><li>Wait.h: the header file that contains the API declaration.</li></ul>
85  * @see none
86  */
87 #define init_waitqueue_head(wait) __init_waitqueue_head(wait)
88 
89 /**
90  * @ingroup  wait
91  * @brief wakeup the process that registered on the wait queue.
92  *
93  * @par Description:
94  * This API is used to wakeup the process that registered on the wait queue.
95  *
96  * @attention
97  * <ul>
98  * <li>Please make sure the input parameter wait is valid, otherwise, the system would be crash.</li>
99  * </ul>
100  *
101  * @param  wait [IN]  struct of the process that registered on the wait queue .
102  *
103  * @retval None.
104  * @par Dependency:
105  * <ul><li>Wait.h: the header file that contains the API declaration.</li></ul>
106  * @see none
107  */
108 #define wake_up_interruptible(wait) __wake_up_interruptible(wait)
109 #define wake_up_interruptible_poll(wait, key) __wake_up_interruptible_poll(wait, key)
110 
111 /**
112  * @ingroup  wait
113  * @brief wakeup the process that registered on the wait queue.
114  *
115  * @par Description:
116  * This API is used to wakeup the process that registered on the wait queue.
117  *
118  * @attention
119  * <ul>
120  * <li>Please look up the function __wake_up_interruptible(wait).</li>
121  * </ul>
122  *
123  * @param None.
124  *
125  * @retval None.
126  * @par Dependency:
127  * <ul><li>Wait.h: the header file that contains the API declaration.</li></ul>
128  * @see wake_up_interruptible
129  */
130 #define wake_up        wake_up_interruptible
131 
132 /**
133  * @ingroup wait
134  * @brief sleep until a condition gets true.
135  *
136  * @par Description:
137  * This API is used to sleep  a process until the condition evaluates to true.
138  * The condition is checked each time when the waitqueue wait is woken up.
139  *
140  * @attention
141  * <ul>
142  * <li>none.</li>
143  * </ul>
144  *
145  * @param  wait [IN] the waitqueue to wait on.
146  * @param  condition [IN] a condition evaluates to true or false.
147 
148  * @retval #0 always return 0
149 
150  * @par Dependency:
151  * <ul><li>linux\wait.h: the header file that contains the API declaration.</li></ul>
152  * @see
153  */
154 #define wait_event(wait, condition) ({                                                                     \
155     INT32 ret = 0;                                                                                         \
156                                                                                                            \
157     if ((wait).stEvent.stEventList.pstPrev == (struct LOS_DL_LIST *)INVALID_ADDR) {                        \
158         (VOID)LOS_EventInit(&(wait).stEvent);                                                              \
159     }                                                                                                      \
160     while (!(condition)) {                                                                                 \
161         (VOID)LOS_EventRead(&(wait).stEvent, 0x1U, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, LOS_WAIT_FOREVER); \
162     }                                                                                                      \
163     ret;                                                                                                   \
164 })
165 
166 #define wait_event_interruptible      wait_event
167 
168 /**
169  * @ingroup wait
170  * @brief sleep until a condition gets true or a timeout elapses.
171  *
172  * @par Description:
173  * This API is used to sleep  a process until the condition evaluates to true or a timeout elapses.
174  * The condition is checked each time when the waitqueue wait is woken up.
175  *
176  * @attention
177  * <ul>
178  * <li>none.</li>
179  * </ul>
180  *
181  * @param  wait [IN] the waitqueue to wait on.
182  * @param  condition [IN] a condition evaluates to true or false.
183  * @param  timeout [IN] the max sleep time (unit : Tick). it is jiffies in linux.
184  *
185  * @retval #0 return 0 if the condition evaluated to false after the timeout elapsed
186  * @retval #1 return 1 if the condition evaluated to true after the timeout elapsed
187  * @retval #2 return 2 if the condition evaluated to true and the timeout is osWaitForever
188  *
189  * @par Dependency:
190  * <ul><li>linux\wait.h: the header file that contains the API declaration.</li></ul>
191  * @see
192  */
193 #define wait_event_interruptible_timeout(wait, condition, timeout)  ({                              \
194     INT32 tmpTimeout;                                                                               \
195     UINT32 ret = 2;                                                                                 \
196     UINT64 ticksnow;                                                                                \
197                                                                                                     \
198     if ((wait).stEvent.stEventList.pstPrev == (struct LOS_DL_LIST *)INVALID_ADDR) {                 \
199         (VOID)LOS_EventInit(&(wait).stEvent);                                                       \
200     }                                                                                               \
201     while (!(condition)) {                                                                          \
202         ticksnow = LOS_TickCountGet();                                                              \
203         ret = LOS_EventRead(&(wait).stEvent, 0x1U, LOS_WAITMODE_AND | LOS_WAITMODE_CLR, (timeout)); \
204         if ((timeout) == osWaitForever) {                                                           \
205             if (condition) {                                                                        \
206                 ret = 2;                                                                            \
207                 break;                                                                              \
208             } else {                                                                                \
209                 continue;                                                                           \
210             }                                                                                       \
211         }                                                                                           \
212         tmpTimeout = (INT32)((timeout) - (UINT32)(LOS_TickCountGet() - ticksnow));                  \
213         if (tmpTimeout <= 0) {                                                                      \
214             ret = (condition) ? 1 : 0;                                                              \
215             break;                                                                                  \
216         } else {                                                                                    \
217             if (ret == LOS_ERRNO_EVENT_READ_TIMEOUT) {                                              \
218                 if (condition) {                                                                    \
219                     ret = 1;                                                                        \
220                     break;                                                                          \
221                 } else {                                                                            \
222                     ret = 0;                                                                        \
223                     break;                                                                          \
224                 }                                                                                   \
225             } else {                                                                                \
226                 if (condition) {                                                                    \
227                     ret = 2;                                                                        \
228                     break;                                                                          \
229                 }                                                                                   \
230             }                                                                                       \
231         }                                                                                           \
232     }                                                                                               \
233     ret;                                                                                            \
234 })
235 
236 #define add_wait_queue(wait, newWait) do {} while (0)
237 #define remove_wait_queue(wait, oldWait) do {} while (0)
238 #define DECLARE_WAITQUEUE(wait, current) do {} while (0)
239 
linux_waitqueue_active(wait_queue_head_t * q)240 static inline int linux_waitqueue_active(wait_queue_head_t *q)
241 {
242     return !LOS_ListEmpty(&(q->stEvent.stEventList));
243 }
244 
245 #define	waitqueue_active(wqh)		linux_waitqueue_active(wqh)
246 
247 #ifdef __cplusplus
248 #if __cplusplus
249 }
250 #endif /* __cplusplus */
251 #endif /* __cplusplus */
252 
253 #endif /* _LINUXKPI_LINUX_WAIT_H_ */
254