1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or https://opensource.org/licenses/CDDL-1.0.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2012, 2018 by Delphix. All rights reserved.
25 * Copyright (c) 2016 Actifio, Inc. All rights reserved.
26 * Copyright (c) 2025, Klara, Inc.
27 */
28
29 #include <assert.h>
30 #include <pthread.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <sys/timer.h>
34 #include <sys/condvar.h>
35
36 /*
37 * =========================================================================
38 * condition variables
39 * =========================================================================
40 */
41
42 void
cv_init(kcondvar_t * cv,char * name,int type,void * arg)43 cv_init(kcondvar_t *cv, char *name, int type, void *arg)
44 {
45 (void) name, (void) type, (void) arg;
46 VERIFY0(pthread_cond_init(cv, NULL));
47 }
48
49 void
cv_destroy(kcondvar_t * cv)50 cv_destroy(kcondvar_t *cv)
51 {
52 VERIFY0(pthread_cond_destroy(cv));
53 }
54
55 void
cv_wait(kcondvar_t * cv,kmutex_t * mp)56 cv_wait(kcondvar_t *cv, kmutex_t *mp)
57 {
58 memset(&mp->m_owner, 0, sizeof (pthread_t));
59 VERIFY0(pthread_cond_wait(cv, &mp->m_lock));
60 mp->m_owner = pthread_self();
61 }
62
63 int
cv_wait_sig(kcondvar_t * cv,kmutex_t * mp)64 cv_wait_sig(kcondvar_t *cv, kmutex_t *mp)
65 {
66 cv_wait(cv, mp);
67 return (1);
68 }
69
70 int
cv_timedwait(kcondvar_t * cv,kmutex_t * mp,clock_t abstime)71 cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
72 {
73 int error;
74 struct timeval tv;
75 struct timespec ts;
76 clock_t delta;
77
78 delta = abstime - ddi_get_lbolt();
79 if (delta <= 0)
80 return (-1);
81
82 VERIFY0(gettimeofday(&tv, NULL));
83
84 ts.tv_sec = tv.tv_sec + delta / hz;
85 ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC + (delta % hz) * (NANOSEC / hz);
86 if (ts.tv_nsec >= NANOSEC) {
87 ts.tv_sec++;
88 ts.tv_nsec -= NANOSEC;
89 }
90
91 memset(&mp->m_owner, 0, sizeof (pthread_t));
92 error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
93 mp->m_owner = pthread_self();
94
95 if (error == ETIMEDOUT)
96 return (-1);
97
98 VERIFY0(error);
99
100 return (1);
101 }
102
103 int
cv_timedwait_hires(kcondvar_t * cv,kmutex_t * mp,hrtime_t tim,hrtime_t res,int flag)104 cv_timedwait_hires(kcondvar_t *cv, kmutex_t *mp, hrtime_t tim, hrtime_t res,
105 int flag)
106 {
107 (void) res;
108 int error;
109 struct timeval tv;
110 struct timespec ts;
111 hrtime_t delta;
112
113 ASSERT(flag == 0 || flag == CALLOUT_FLAG_ABSOLUTE);
114
115 delta = tim;
116 if (flag & CALLOUT_FLAG_ABSOLUTE)
117 delta -= gethrtime();
118
119 if (delta <= 0)
120 return (-1);
121
122 VERIFY0(gettimeofday(&tv, NULL));
123
124 ts.tv_sec = tv.tv_sec + delta / NANOSEC;
125 ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC + (delta % NANOSEC);
126 if (ts.tv_nsec >= NANOSEC) {
127 ts.tv_sec++;
128 ts.tv_nsec -= NANOSEC;
129 }
130
131 memset(&mp->m_owner, 0, sizeof (pthread_t));
132 error = pthread_cond_timedwait(cv, &mp->m_lock, &ts);
133 mp->m_owner = pthread_self();
134
135 if (error == ETIMEDOUT)
136 return (-1);
137
138 VERIFY0(error);
139
140 return (1);
141 }
142
143 void
cv_signal(kcondvar_t * cv)144 cv_signal(kcondvar_t *cv)
145 {
146 VERIFY0(pthread_cond_signal(cv));
147 }
148
149 void
cv_broadcast(kcondvar_t * cv)150 cv_broadcast(kcondvar_t *cv)
151 {
152 VERIFY0(pthread_cond_broadcast(cv));
153 }
154