1 /* 2 * Copyright (c) 2014 Imre Vadász 3 * Copyright (c) 2014-2019 François Tigeot <ftigeot@wolfpond.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice unmodified, this list of conditions, and the following 11 * disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #ifndef _LINUX_WAIT_H_ 29 #define _LINUX_WAIT_H_ 30 31 #include <linux/list.h> 32 #include <linux/stddef.h> 33 #include <linux/spinlock.h> 34 #include <asm/current.h> 35 36 typedef struct { 37 } wait_queue_t; 38 39 typedef struct { 40 struct lock lock; 41 } wait_queue_head_t; 42 43 static inline void 44 init_waitqueue_head(wait_queue_head_t *eq) 45 { 46 lockinit(&eq->lock, "lwq", 0, LK_CANRECURSE); 47 } 48 49 #define wake_up(eq) wakeup_one(eq) 50 #define wake_up_all(eq) wakeup(eq) 51 #define wake_up_interruptible(eq) wakeup_one(eq) 52 #define wake_up_interruptible_all(eq) wakeup(eq) 53 54 /* 55 * wait_event_interruptible_timeout: 56 * - The process is put to sleep until the condition evaluates to true. 57 * - The condition is checked each time the waitqueue wq is woken up. 58 * - wake_up has to be called after changing any variable that could change 59 * the result of the wait condition. 60 * 61 * returns: 62 * - 0 if the timeout elapsed 63 * - the remaining jiffies if the condition evaluated to true before 64 * the timeout elapsed. 65 * - remaining jiffies are always at least 1 66 * - -ERESTARTSYS if interrupted by a signal (when PCATCH is set in flags) 67 */ 68 #define __wait_event_common(wq, condition, timeout_jiffies, flags) \ 69 ({ \ 70 int start_jiffies, elapsed_jiffies, remaining_jiffies, ret; \ 71 bool timeout_expired = false; \ 72 bool interrupted = false; \ 73 long retval; \ 74 \ 75 start_jiffies = ticks; \ 76 \ 77 lockmgr(&wq.lock, LK_EXCLUSIVE); \ 78 while (1) { \ 79 if (condition) \ 80 break; \ 81 \ 82 ret = lksleep(&wq, &wq.lock, flags, \ 83 "lwe", timeout_jiffies); \ 84 if (ret == EINTR || ret == ERESTART) { \ 85 interrupted = true; \ 86 break; \ 87 } \ 88 if (ret == EWOULDBLOCK) { \ 89 timeout_expired = true; \ 90 break; \ 91 } \ 92 } \ 93 lockmgr(&wq.lock, LK_RELEASE); \ 94 \ 95 elapsed_jiffies = ticks - start_jiffies; \ 96 remaining_jiffies = timeout_jiffies - elapsed_jiffies; \ 97 if (remaining_jiffies <= 0) \ 98 remaining_jiffies = 1; \ 99 \ 100 if (timeout_expired) \ 101 retval = 0; \ 102 else if (interrupted) \ 103 retval = -ERESTARTSYS; \ 104 else if (timeout_jiffies > 0) \ 105 retval = remaining_jiffies; \ 106 else \ 107 retval = 1; \ 108 \ 109 retval; \ 110 }) 111 112 #define wait_event(wq, condition) \ 113 __wait_event_common(wq, condition, 0, 0) 114 115 #define wait_event_timeout(wq, condition, timeout) \ 116 __wait_event_common(wq, condition, timeout, 0) 117 118 #define wait_event_interruptible(wq, condition) \ 119 ({ \ 120 long retval; \ 121 \ 122 retval = __wait_event_common(wq, condition, 0, PCATCH); \ 123 if (retval != -ERESTARTSYS) \ 124 retval = 0; \ 125 retval; \ 126 }) 127 128 #define wait_event_interruptible_timeout(wq, condition, timeout) \ 129 __wait_event_common(wq, condition, timeout, PCATCH) 130 131 static inline int 132 waitqueue_active(wait_queue_head_t *q) 133 { 134 return 0; /* XXX: not really implemented */ 135 } 136 137 #define DEFINE_WAIT(name) \ 138 wait_queue_t name = {} 139 140 static inline void 141 prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state) 142 { 143 } 144 145 static inline void 146 finish_wait(wait_queue_head_t *q, wait_queue_t *wait) 147 { 148 } 149 150 static inline void 151 add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) 152 { 153 } 154 155 #define DECLARE_WAIT_QUEUE_HEAD(name) \ 156 wait_queue_head_t name = { \ 157 .lock = LOCK_INITIALIZER("name", 0, LK_CANRECURSE) \ 158 } 159 160 #endif /* _LINUX_WAIT_H_ */ 161