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
cv_init(kcondvar_t * cv,char * name,kcv_type_t typ,void * arg)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
cv_destroy(kcondvar_t * cv)54*b819cea2SGordon Ross cv_destroy(kcondvar_t *cv)
55*b819cea2SGordon Ross {
56*b819cea2SGordon Ross }
57*b819cea2SGordon Ross
58*b819cea2SGordon Ross void
cv_signal(kcondvar_t * cv)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
cv_broadcast(kcondvar_t * cv)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
cv_wait(kcondvar_t * cv,kmutex_t * mp)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
cv_wait_sig(kcondvar_t * cv,kmutex_t * mp)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
cv__wait(kcondvar_t * cv,kmutex_t * mp,int sigok)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
cv_timedwait(kcondvar_t * cv,kmutex_t * mp,clock_t abstime)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
cv_timedwait_sig(kcondvar_t * cv,kmutex_t * mp,clock_t abstime)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
cv_reltimedwait(kcondvar_t * cv,kmutex_t * mp,clock_t delta,time_res_t res)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
cv_reltimedwait_sig(kcondvar_t * cv,kmutex_t * mp,clock_t delta,time_res_t res)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
cv__twait(kcondvar_t * cv,kmutex_t * mp,clock_t delta,int sigok)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