1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3 * This file and its contents are supplied under the terms of the
4 * Common Development and Distribution License ("CDDL"), version 1.0.
5 * You may only use this file in accordance with the terms of version
6 * 1.0 of the CDDL.
7 *
8 * A full copy of the text of the CDDL should have accompanied this
9 * source. A copy of the CDDL is also available via the Internet at
10 * https://opensource.org/license/CDDL-1.0.
11 */
12 /*
13 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
14 * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
15 * Copyright (c) 2016 Actifio, Inc. All rights reserved.
16 * Copyright (c) 2025, Klara, Inc.
17 */
18
19 #include <assert.h>
20 #include <pthread.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <sys/timer.h>
24 #include <sys/condvar.h>
25
26 /*
27 * =========================================================================
28 * condition variables
29 * =========================================================================
30 */
31
32 void
cv_init(kcondvar_t * cv,char * name,int type,void * arg)33 cv_init(kcondvar_t *cv, char *name, int type, void *arg)
34 {
35 (void) name, (void) type, (void) arg;
36 VERIFY0(pthread_cond_init(cv, NULL));
37 }
38
39 void
cv_destroy(kcondvar_t * cv)40 cv_destroy(kcondvar_t *cv)
41 {
42 VERIFY0(pthread_cond_destroy(cv));
43 }
44
45 void
cv_wait(kcondvar_t * cv,kmutex_t * mp)46 cv_wait(kcondvar_t *cv, kmutex_t *mp)
47 {
48 memset(&mp->m_owner, 0, sizeof (pthread_t));
49 VERIFY0(pthread_cond_wait(cv, &mp->m_lock));
50 mp->m_owner = pthread_self();
51 }
52
53 int
cv_wait_sig(kcondvar_t * cv,kmutex_t * mp)54 cv_wait_sig(kcondvar_t *cv, kmutex_t *mp)
55 {
56 cv_wait(cv, mp);
57 return (1);
58 }
59
60 int
cv_timedwait(kcondvar_t * cv,kmutex_t * mp,clock_t abstime)61 cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
62 {
63 int error;
64 struct timeval tv;
65 struct timespec ts;
66 clock_t delta;
67
68 delta = abstime - ddi_get_lbolt();
69 if (delta <= 0)
70 return (-1);
71
72 VERIFY0(gettimeofday(&tv, NULL));
73
74 ts.tv_sec = tv.tv_sec + delta / hz;
75 ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC + (delta % hz) * (NANOSEC / hz);
76 if (ts.tv_nsec >= NANOSEC) {
77 ts.tv_sec++;
78 ts.tv_nsec -= NANOSEC;
79 }
80
81 memset(&mp->m_owner, 0, sizeof (pthread_t));
82 error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
83 mp->m_owner = pthread_self();
84
85 if (error == ETIMEDOUT)
86 return (-1);
87
88 VERIFY0(error);
89
90 return (1);
91 }
92
93 int
cv_timedwait_hires(kcondvar_t * cv,kmutex_t * mp,hrtime_t tim,hrtime_t res,int flag)94 cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
95 int flag)
96 {
97 (void) res;
98 int error;
99 struct timeval tv;
100 struct timespec ts;
101 hrtime_t delta;
102
103 ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
104
105 delta = tim;
106 if (flag & CALLOUT_FLAG_ABSOLUTE)
107 delta -= gethrtime();
108
109 if (delta <= 0)
110 return (-1);
111
112 VERIFY0(gettimeofday(&tv, NULL));
113
114 ts.tv_sec = tv.tv_sec + delta / NANOSEC;
115 ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC + (delta % NANOSEC);
116 if (ts.tv_nsec >= NANOSEC) {
117 ts.tv_sec++;
118 ts.tv_nsec -= NANOSEC;
119 }
120
121 memset(&mp->m_owner, 0, sizeof (pthread_t));
122 error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
123 mp->m_owner = pthread_self();
124
125 if (error == ETIMEDOUT)
126 return (-1);
127
128 VERIFY0(error);
129
130 return (1);
131 }
132
133 void
cv_signal(kcondvar_t * cv)134 cv_signal(kcondvar_t *cv)
135 {
136 VERIFY0(pthread_cond_signal(cv));
137 }
138
139 void
cv_broadcast(kcondvar_t * cv)140 cv_broadcast(kcondvar_t *cv)
141 {
142 VERIFY0(pthread_cond_broadcast(cv));
143 }
144