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