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