xref: /titanic_51/usr/src/lib/libfakekernel/common/cond.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
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