8809 libzpool should leverage work done in libfakekernel
[unleashed.git] / usr / src / lib / libfakekernel / common / cond.c
blob08d0265dd2098cbcb97d2a80837b365e3b41b569
1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
14 * Copyright 2017 RackTop Systems.
18 * condvar(9f)
21 /* This is the API we're emulating */
22 #include <sys/condvar.h>
24 #include <sys/errno.h>
25 #include <sys/debug.h>
26 #include <sys/thread.h>
27 #include <sys/systm.h>
29 /* avoiding synch.h */
30 int _lwp_cond_wait(lwp_cond_t *, lwp_mutex_t *);
31 int _lwp_cond_timedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *);
32 int _lwp_cond_reltimedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *);
33 int _lwp_cond_signal(lwp_cond_t *);
34 int _lwp_cond_broadcast(lwp_cond_t *);
37 extern clock_t ddi_get_lbolt(void);
39 static int cv__wait(kcondvar_t *, kmutex_t *, int);
40 static clock_t cv__twait(kcondvar_t *, kmutex_t *, clock_t, int, int);
42 static const lwp_cond_t default_cv =
43 {{{0, 0, 0, 0}, USYNC_THREAD, _COND_MAGIC}, 0};
46 /* ARGSUSED */
47 void
48 cv_init(kcondvar_t *cv, char *name, kcv_type_t typ, void *arg)
50 *cv = default_cv;
53 /* ARGSUSED */
54 void
55 cv_destroy(kcondvar_t *cv)
59 void
60 cv_signal(kcondvar_t *cv)
62 (void) _lwp_cond_signal(cv);
65 void
66 cv_broadcast(kcondvar_t *cv)
68 (void) _lwp_cond_broadcast(cv);
71 void
72 cv_wait(kcondvar_t *cv, kmutex_t *mp)
74 (void) cv__wait(cv, mp, 0);
77 int
78 cv_wait_sig(kcondvar_t *cv, kmutex_t *mp)
80 return (cv__wait(cv, mp, 1));
83 int
84 cv__wait(kcondvar_t *cv, kmutex_t *mp, int sigok)
86 int err;
88 top:
89 ASSERT(mp->m_owner == _curthread());
90 mp->m_owner = _KTHREAD_INVALID;
91 err = _lwp_cond_wait(cv, &mp->m_lock);
92 mp->m_owner = _curthread();
94 if (err == 0)
95 return (1);
96 if (err == EINTR) {
97 if (sigok)
98 return (0);
99 goto top;
101 return (-1);
104 clock_t
105 cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
107 clock_t delta;
109 delta = abstime - ddi_get_lbolt();
110 return (cv__twait(cv, mp, delta, 0, 0));
113 clock_t
114 cv_timedwait_sig(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
116 clock_t delta;
118 delta = abstime - ddi_get_lbolt();
119 return (cv__twait(cv, mp, delta, 1, 0));
122 /*ARGSUSED*/
123 clock_t
124 cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
125 int flag)
127 clock_t delta;
129 delta = tim;
130 if (flag & CALLOUT_FLAG_ABSOLUTE)
131 delta -= gethrtime();
132 return (cv__twait(cv, mp, delta, 0, 1));
135 clock_t
136 cv_reltimedwait(kcondvar_t *cv, kmutex_t *mp, clock_t delta, time_res_t res)
138 _NOTE(ARGUNUSED(res))
140 return (cv__twait(cv, mp, delta, 0, 0));
143 clock_t
144 cv_reltimedwait_sig(kcondvar_t *cv, kmutex_t *mp, clock_t delta,
145 time_res_t res)
147 _NOTE(ARGUNUSED(res))
149 return (cv__twait(cv, mp, delta, 1, 0));
153 * Factored out implementation of all the cv_*timedwait* functions.
154 * Note that the delta passed in is relative to the (simulated)
155 * current time reported by ddi_get_lbolt(). Convert that to
156 * timespec format and keep calling _lwp_cond_reltimedwait,
157 * which (NB!) decrements that delta in-place!
159 static clock_t
160 cv__twait(kcondvar_t *cv, kmutex_t *mp, clock_t delta, int sigok, int hires)
162 timestruc_t ts;
163 int err;
165 if (delta <= 0)
166 return (-1);
168 if (hires) {
169 ts.tv_sec = delta / NANOSEC;
170 ts.tv_nsec = delta % NANOSEC;
171 } else {
172 ts.tv_sec = delta / hz;
173 ts.tv_nsec = (delta % hz) * (NANOSEC / hz);
176 top:
177 if (ts.tv_sec == 0 && ts.tv_nsec == 0)
178 return (-1);
180 ASSERT(mp->m_owner == _curthread());
181 mp->m_owner = _KTHREAD_INVALID;
182 err = _lwp_cond_reltimedwait(cv, &mp->m_lock, &ts);
183 mp->m_owner = _curthread();
185 switch (err) {
186 case 0:
187 return (1);
188 case EINTR:
189 if (sigok)
190 return (0);
191 goto top;
192 default:
193 ASSERT(0);
194 /* FALLTHROUGH */
195 case ETIME:
196 break;
199 return (-1);