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 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