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