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