1 /* $OpenBSD: completion.h,v 1.3 2019/12/30 09:30:31 mpi Exp $ */ 2 /* 3 * Copyright (c) 2015, 2018 Mark Kettenis 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #ifndef _LINUX_COMPLETION_H 19 #define _LINUX_COMPLETION_H 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/mutex.h> 24 #include <linux/wait.h> 25 26 struct completion { 27 u_int done; 28 wait_queue_head_t wait; 29 }; 30 31 static inline void 32 init_completion(struct completion *x) 33 { 34 x->done = 0; 35 mtx_init(&x->wait.lock, IPL_TTY); 36 } 37 38 static inline u_long 39 wait_for_completion_timeout(struct completion *x, u_long timo) 40 { 41 int ret; 42 43 KASSERT(!cold); 44 45 mtx_enter(&x->wait.lock); 46 while (x->done == 0) { 47 ret = msleep(x, &x->wait.lock, 0, "wfct", timo); 48 if (ret) { 49 mtx_leave(&x->wait.lock); 50 return (ret == EWOULDBLOCK) ? 0 : -ret; 51 } 52 } 53 x->done--; 54 mtx_leave(&x->wait.lock); 55 56 return 1; 57 } 58 59 static inline u_long 60 wait_for_completion_interruptible(struct completion *x) 61 { 62 int ret; 63 64 KASSERT(!cold); 65 66 mtx_enter(&x->wait.lock); 67 while (x->done == 0) { 68 ret = msleep_nsec(x, &x->wait.lock, PCATCH, "wfci", INFSLP); 69 if (ret) { 70 mtx_leave(&x->wait.lock); 71 return (ret == EWOULDBLOCK) ? 0 : -ret; 72 } 73 } 74 x->done--; 75 mtx_leave(&x->wait.lock); 76 77 return 0; 78 } 79 80 static inline u_long 81 wait_for_completion_interruptible_timeout(struct completion *x, u_long timo) 82 { 83 int ret; 84 85 KASSERT(!cold); 86 87 mtx_enter(&x->wait.lock); 88 while (x->done == 0) { 89 ret = msleep(x, &x->wait.lock, PCATCH, "wfcit", timo); 90 if (ret) { 91 mtx_leave(&x->wait.lock); 92 return (ret == EWOULDBLOCK) ? 0 : -ret; 93 } 94 } 95 x->done--; 96 mtx_leave(&x->wait.lock); 97 98 return 1; 99 } 100 101 static inline void 102 complete_all(struct completion *x) 103 { 104 mtx_enter(&x->wait.lock); 105 x->done = UINT_MAX; 106 mtx_leave(&x->wait.lock); 107 wakeup(x); 108 } 109 110 static inline bool 111 try_wait_for_completion(struct completion *x) 112 { 113 mtx_enter(&x->wait.lock); 114 if (x->done == 0) { 115 mtx_leave(&x->wait.lock); 116 return false; 117 } 118 x->done--; 119 mtx_leave(&x->wait.lock); 120 return true; 121 } 122 123 #endif 124