1b819cea2SGordon Ross /* 2b819cea2SGordon Ross * This file and its contents are supplied under the terms of the 3b819cea2SGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0. 4b819cea2SGordon Ross * You may only use this file in accordance with the terms of version 5b819cea2SGordon Ross * 1.0 of the CDDL. 6b819cea2SGordon Ross * 7b819cea2SGordon Ross * A full copy of the text of the CDDL should have accompanied this 8b819cea2SGordon Ross * source. A copy of the CDDL is also available via the Internet at 9b819cea2SGordon Ross * http://www.illumos.org/license/CDDL. 10b819cea2SGordon Ross */ 11b819cea2SGordon Ross 12b819cea2SGordon Ross /* 13b819cea2SGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 14*f06dce2cSAndrew Stormont * Copyright 2017 RackTop Systems. 15b819cea2SGordon Ross */ 16b819cea2SGordon Ross 17b819cea2SGordon Ross /* 18b819cea2SGordon Ross * condvar(9f) 19b819cea2SGordon Ross */ 20b819cea2SGordon Ross 21b819cea2SGordon Ross /* This is the API we're emulating */ 22b819cea2SGordon Ross #include <sys/condvar.h> 23b819cea2SGordon Ross 24b819cea2SGordon Ross #include <sys/errno.h> 25b819cea2SGordon Ross #include <sys/debug.h> 26b819cea2SGordon Ross #include <sys/thread.h> 27*f06dce2cSAndrew Stormont #include <sys/systm.h> 28b819cea2SGordon Ross 29b819cea2SGordon Ross /* avoiding synch.h */ 30b819cea2SGordon Ross int _lwp_cond_wait(lwp_cond_t *, lwp_mutex_t *); 31b819cea2SGordon Ross int _lwp_cond_timedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *); 32b819cea2SGordon Ross int _lwp_cond_reltimedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *); 33b819cea2SGordon Ross int _lwp_cond_signal(lwp_cond_t *); 34b819cea2SGordon Ross int _lwp_cond_broadcast(lwp_cond_t *); 35b819cea2SGordon Ross 36b819cea2SGordon Ross 37b819cea2SGordon Ross extern clock_t ddi_get_lbolt(void); 38b819cea2SGordon Ross 39b819cea2SGordon Ross static int cv__wait(kcondvar_t *, kmutex_t *, int); 40*f06dce2cSAndrew Stormont static clock_t cv__twait(kcondvar_t *, kmutex_t *, clock_t, int, int); 41b819cea2SGordon Ross 42b819cea2SGordon Ross static const lwp_cond_t default_cv = 43b819cea2SGordon Ross {{{0, 0, 0, 0}, USYNC_THREAD, _COND_MAGIC}, 0}; 44b819cea2SGordon Ross 45b819cea2SGordon Ross 46b819cea2SGordon Ross /* ARGSUSED */ 47b819cea2SGordon Ross void 48b819cea2SGordon Ross cv_init(kcondvar_t *cv, char *name, kcv_type_t typ, void *arg) 49b819cea2SGordon Ross { 50b819cea2SGordon Ross *cv = default_cv; 51b819cea2SGordon Ross } 52b819cea2SGordon Ross 53b819cea2SGordon Ross /* ARGSUSED */ 54b819cea2SGordon Ross void 55b819cea2SGordon Ross cv_destroy(kcondvar_t *cv) 56b819cea2SGordon Ross { 57b819cea2SGordon Ross } 58b819cea2SGordon Ross 59b819cea2SGordon Ross void 60b819cea2SGordon Ross cv_signal(kcondvar_t *cv) 61b819cea2SGordon Ross { 62b819cea2SGordon Ross (void) _lwp_cond_signal(cv); 63b819cea2SGordon Ross } 64b819cea2SGordon Ross 65b819cea2SGordon Ross void 66b819cea2SGordon Ross cv_broadcast(kcondvar_t *cv) 67b819cea2SGordon Ross { 68b819cea2SGordon Ross (void) _lwp_cond_broadcast(cv); 69b819cea2SGordon Ross } 70b819cea2SGordon Ross 71b819cea2SGordon Ross void 72b819cea2SGordon Ross cv_wait(kcondvar_t *cv, kmutex_t *mp) 73b819cea2SGordon Ross { 74b819cea2SGordon Ross (void) cv__wait(cv, mp, 0); 75b819cea2SGordon Ross } 76b819cea2SGordon Ross 77b819cea2SGordon Ross int 78b819cea2SGordon Ross cv_wait_sig(kcondvar_t *cv, kmutex_t *mp) 79b819cea2SGordon Ross { 80b819cea2SGordon Ross return (cv__wait(cv, mp, 1)); 81b819cea2SGordon Ross } 82b819cea2SGordon Ross 83b819cea2SGordon Ross int 84b819cea2SGordon Ross cv__wait(kcondvar_t *cv, kmutex_t *mp, int sigok) 85b819cea2SGordon Ross { 86b819cea2SGordon Ross int err; 87b819cea2SGordon Ross 88b819cea2SGordon Ross top: 89b819cea2SGordon Ross ASSERT(mp->m_owner == _curthread()); 90b819cea2SGordon Ross mp->m_owner = _KTHREAD_INVALID; 91b819cea2SGordon Ross err = _lwp_cond_wait(cv, &mp->m_lock); 92b819cea2SGordon Ross mp->m_owner = _curthread(); 93b819cea2SGordon Ross 94b819cea2SGordon Ross if (err == 0) 95b819cea2SGordon Ross return (1); 96b819cea2SGordon Ross if (err == EINTR) { 97b819cea2SGordon Ross if (sigok) 98b819cea2SGordon Ross return (0); 99b819cea2SGordon Ross goto top; 100b819cea2SGordon Ross } 101b819cea2SGordon Ross return (-1); 102b819cea2SGordon Ross } 103b819cea2SGordon Ross 104b819cea2SGordon Ross clock_t 105b819cea2SGordon Ross cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 106b819cea2SGordon Ross { 107b819cea2SGordon Ross clock_t delta; 108b819cea2SGordon Ross 109b819cea2SGordon Ross delta = abstime - ddi_get_lbolt(); 110*f06dce2cSAndrew Stormont return (cv__twait(cv, mp, delta, 0, 0)); 111b819cea2SGordon Ross } 112b819cea2SGordon Ross 113b819cea2SGordon Ross clock_t 114b819cea2SGordon Ross cv_timedwait_sig(kcondvar_t *cv, kmutex_t *mp, clock_t abstime) 115b819cea2SGordon Ross { 116b819cea2SGordon Ross clock_t delta; 117b819cea2SGordon Ross 118b819cea2SGordon Ross delta = abstime - ddi_get_lbolt(); 119*f06dce2cSAndrew Stormont return (cv__twait(cv, mp, delta, 1, 0)); 120*f06dce2cSAndrew Stormont } 121*f06dce2cSAndrew Stormont 122*f06dce2cSAndrew Stormont /*ARGSUSED*/ 123*f06dce2cSAndrew Stormont clock_t 124*f06dce2cSAndrew Stormont cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res, 125*f06dce2cSAndrew Stormont int flag) 126*f06dce2cSAndrew Stormont { 127*f06dce2cSAndrew Stormont clock_t delta; 128*f06dce2cSAndrew Stormont 129*f06dce2cSAndrew Stormont delta = tim; 130*f06dce2cSAndrew Stormont if (flag & CALLOUT_FLAG_ABSOLUTE) 131*f06dce2cSAndrew Stormont delta -= gethrtime(); 132*f06dce2cSAndrew Stormont return (cv__twait(cv, mp, delta, 0, 1)); 133b819cea2SGordon Ross } 134b819cea2SGordon Ross 135b819cea2SGordon Ross clock_t 136b819cea2SGordon Ross cv_reltimedwait(kcondvar_t *cv, kmutex_t *mp, clock_t delta, time_res_t res) 137b819cea2SGordon Ross { 138b819cea2SGordon Ross _NOTE(ARGUNUSED(res)) 139b819cea2SGordon Ross 140*f06dce2cSAndrew Stormont return (cv__twait(cv, mp, delta, 0, 0)); 141b819cea2SGordon Ross } 142b819cea2SGordon Ross 143b819cea2SGordon Ross clock_t 144b819cea2SGordon Ross cv_reltimedwait_sig(kcondvar_t *cv, kmutex_t *mp, clock_t delta, 145b819cea2SGordon Ross time_res_t res) 146b819cea2SGordon Ross { 147b819cea2SGordon Ross _NOTE(ARGUNUSED(res)) 148b819cea2SGordon Ross 149*f06dce2cSAndrew Stormont return (cv__twait(cv, mp, delta, 1, 0)); 150b819cea2SGordon Ross } 151b819cea2SGordon Ross 152b819cea2SGordon Ross /* 153b819cea2SGordon Ross * Factored out implementation of all the cv_*timedwait* functions. 154b819cea2SGordon Ross * Note that the delta passed in is relative to the (simulated) 155b819cea2SGordon Ross * current time reported by ddi_get_lbolt(). Convert that to 156b819cea2SGordon Ross * timespec format and keep calling _lwp_cond_reltimedwait, 157b819cea2SGordon Ross * which (NB!) decrements that delta in-place! 158b819cea2SGordon Ross */ 159b819cea2SGordon Ross static clock_t 160*f06dce2cSAndrew Stormont cv__twait(kcondvar_t *cv, kmutex_t *mp, clock_t delta, int sigok, int hires) 161b819cea2SGordon Ross { 162b819cea2SGordon Ross timestruc_t ts; 163b819cea2SGordon Ross int err; 164b819cea2SGordon Ross 165b819cea2SGordon Ross if (delta <= 0) 166b819cea2SGordon Ross return (-1); 167b819cea2SGordon Ross 168*f06dce2cSAndrew Stormont if (hires) { 169*f06dce2cSAndrew Stormont ts.tv_sec = delta / NANOSEC; 170*f06dce2cSAndrew Stormont ts.tv_nsec = delta % NANOSEC; 171*f06dce2cSAndrew Stormont } else { 172*f06dce2cSAndrew Stormont ts.tv_sec = delta / hz; 173*f06dce2cSAndrew Stormont ts.tv_nsec = (delta % hz) * (NANOSEC / hz); 174*f06dce2cSAndrew Stormont } 175b819cea2SGordon Ross 176b819cea2SGordon Ross top: 177b819cea2SGordon Ross if (ts.tv_sec == 0 && ts.tv_nsec == 0) 178b819cea2SGordon Ross return (-1); 179b819cea2SGordon Ross 180b819cea2SGordon Ross ASSERT(mp->m_owner == _curthread()); 181b819cea2SGordon Ross mp->m_owner = _KTHREAD_INVALID; 182b819cea2SGordon Ross err = _lwp_cond_reltimedwait(cv, &mp->m_lock, &ts); 183b819cea2SGordon Ross mp->m_owner = _curthread(); 184b819cea2SGordon Ross 185b819cea2SGordon Ross switch (err) { 186b819cea2SGordon Ross case 0: 187b819cea2SGordon Ross return (1); 188b819cea2SGordon Ross case EINTR: 189b819cea2SGordon Ross if (sigok) 190b819cea2SGordon Ross return (0); 191b819cea2SGordon Ross goto top; 192b819cea2SGordon Ross default: 193b819cea2SGordon Ross ASSERT(0); 194b819cea2SGordon Ross /* FALLTHROUGH */ 195b819cea2SGordon Ross case ETIME: 196b819cea2SGordon Ross break; 197b819cea2SGordon Ross } 198b819cea2SGordon Ross 199b819cea2SGordon Ross return (-1); 200b819cea2SGordon Ross } 201