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 40extern "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 */ 52typedef 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 65void __wake_up_interruptible(wait_queue_head_t *wait); 66void __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 240static 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