1*aa772005SRobert Watson /*-
2*aa772005SRobert Watson * Copyright (c) 2009-2010 The FreeBSD Foundation
3*aa772005SRobert Watson * All rights reserved.
4*aa772005SRobert Watson *
5*aa772005SRobert Watson * This software was developed by Pawel Jakub Dawidek under sponsorship from
6*aa772005SRobert Watson * the FreeBSD Foundation.
7*aa772005SRobert Watson *
8*aa772005SRobert Watson * Redistribution and use in source and binary forms, with or without
9*aa772005SRobert Watson * modification, are permitted provided that the following conditions
10*aa772005SRobert Watson * are met:
11*aa772005SRobert Watson * 1. Redistributions of source code must retain the above copyright
12*aa772005SRobert Watson * notice, this list of conditions and the following disclaimer.
13*aa772005SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright
14*aa772005SRobert Watson * notice, this list of conditions and the following disclaimer in the
15*aa772005SRobert Watson * documentation and/or other materials provided with the distribution.
16*aa772005SRobert Watson *
17*aa772005SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18*aa772005SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*aa772005SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*aa772005SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21*aa772005SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*aa772005SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*aa772005SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*aa772005SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*aa772005SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*aa772005SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*aa772005SRobert Watson * SUCH DAMAGE.
28*aa772005SRobert Watson */
29*aa772005SRobert Watson
30*aa772005SRobert Watson #ifndef _SYNCH_H_
31*aa772005SRobert Watson #define _SYNCH_H_
32*aa772005SRobert Watson
33*aa772005SRobert Watson #include <errno.h>
34*aa772005SRobert Watson #include <pthread.h>
35*aa772005SRobert Watson #ifdef HAVE_PTHREAD_NP_H
36*aa772005SRobert Watson #include <pthread_np.h>
37*aa772005SRobert Watson #endif
38*aa772005SRobert Watson #include <stdbool.h>
39*aa772005SRobert Watson #include <time.h>
40*aa772005SRobert Watson
41*aa772005SRobert Watson #include "pjdlog.h"
42*aa772005SRobert Watson
43*aa772005SRobert Watson #ifndef PJDLOG_ASSERT
44*aa772005SRobert Watson #include <assert.h>
45*aa772005SRobert Watson #define PJDLOG_ASSERT(...) assert(__VA_ARGS__)
46*aa772005SRobert Watson #endif
47*aa772005SRobert Watson
48*aa772005SRobert Watson static __inline void
mtx_init(pthread_mutex_t * lock)49*aa772005SRobert Watson mtx_init(pthread_mutex_t *lock)
50*aa772005SRobert Watson {
51*aa772005SRobert Watson int error;
52*aa772005SRobert Watson
53*aa772005SRobert Watson error = pthread_mutex_init(lock, NULL);
54*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
55*aa772005SRobert Watson }
56*aa772005SRobert Watson static __inline void
mtx_destroy(pthread_mutex_t * lock)57*aa772005SRobert Watson mtx_destroy(pthread_mutex_t *lock)
58*aa772005SRobert Watson {
59*aa772005SRobert Watson int error;
60*aa772005SRobert Watson
61*aa772005SRobert Watson error = pthread_mutex_destroy(lock);
62*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
63*aa772005SRobert Watson }
64*aa772005SRobert Watson static __inline void
mtx_lock(pthread_mutex_t * lock)65*aa772005SRobert Watson mtx_lock(pthread_mutex_t *lock)
66*aa772005SRobert Watson {
67*aa772005SRobert Watson int error;
68*aa772005SRobert Watson
69*aa772005SRobert Watson error = pthread_mutex_lock(lock);
70*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
71*aa772005SRobert Watson }
72*aa772005SRobert Watson static __inline bool
mtx_trylock(pthread_mutex_t * lock)73*aa772005SRobert Watson mtx_trylock(pthread_mutex_t *lock)
74*aa772005SRobert Watson {
75*aa772005SRobert Watson int error;
76*aa772005SRobert Watson
77*aa772005SRobert Watson error = pthread_mutex_trylock(lock);
78*aa772005SRobert Watson PJDLOG_ASSERT(error == 0 || error == EBUSY);
79*aa772005SRobert Watson return (error == 0);
80*aa772005SRobert Watson }
81*aa772005SRobert Watson static __inline void
mtx_unlock(pthread_mutex_t * lock)82*aa772005SRobert Watson mtx_unlock(pthread_mutex_t *lock)
83*aa772005SRobert Watson {
84*aa772005SRobert Watson int error;
85*aa772005SRobert Watson
86*aa772005SRobert Watson error = pthread_mutex_unlock(lock);
87*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
88*aa772005SRobert Watson }
89*aa772005SRobert Watson static __inline bool
mtx_owned(pthread_mutex_t * lock)90*aa772005SRobert Watson mtx_owned(pthread_mutex_t *lock)
91*aa772005SRobert Watson {
92*aa772005SRobert Watson
93*aa772005SRobert Watson return (pthread_mutex_isowned_np(lock) != 0);
94*aa772005SRobert Watson }
95*aa772005SRobert Watson
96*aa772005SRobert Watson static __inline void
rw_init(pthread_rwlock_t * lock)97*aa772005SRobert Watson rw_init(pthread_rwlock_t *lock)
98*aa772005SRobert Watson {
99*aa772005SRobert Watson int error;
100*aa772005SRobert Watson
101*aa772005SRobert Watson error = pthread_rwlock_init(lock, NULL);
102*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
103*aa772005SRobert Watson }
104*aa772005SRobert Watson static __inline void
rw_destroy(pthread_rwlock_t * lock)105*aa772005SRobert Watson rw_destroy(pthread_rwlock_t *lock)
106*aa772005SRobert Watson {
107*aa772005SRobert Watson int error;
108*aa772005SRobert Watson
109*aa772005SRobert Watson error = pthread_rwlock_destroy(lock);
110*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
111*aa772005SRobert Watson }
112*aa772005SRobert Watson static __inline void
rw_rlock(pthread_rwlock_t * lock)113*aa772005SRobert Watson rw_rlock(pthread_rwlock_t *lock)
114*aa772005SRobert Watson {
115*aa772005SRobert Watson int error;
116*aa772005SRobert Watson
117*aa772005SRobert Watson error = pthread_rwlock_rdlock(lock);
118*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
119*aa772005SRobert Watson }
120*aa772005SRobert Watson static __inline void
rw_wlock(pthread_rwlock_t * lock)121*aa772005SRobert Watson rw_wlock(pthread_rwlock_t *lock)
122*aa772005SRobert Watson {
123*aa772005SRobert Watson int error;
124*aa772005SRobert Watson
125*aa772005SRobert Watson error = pthread_rwlock_wrlock(lock);
126*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
127*aa772005SRobert Watson }
128*aa772005SRobert Watson static __inline void
rw_unlock(pthread_rwlock_t * lock)129*aa772005SRobert Watson rw_unlock(pthread_rwlock_t *lock)
130*aa772005SRobert Watson {
131*aa772005SRobert Watson int error;
132*aa772005SRobert Watson
133*aa772005SRobert Watson error = pthread_rwlock_unlock(lock);
134*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
135*aa772005SRobert Watson }
136*aa772005SRobert Watson
137*aa772005SRobert Watson static __inline void
cv_init(pthread_cond_t * cv)138*aa772005SRobert Watson cv_init(pthread_cond_t *cv)
139*aa772005SRobert Watson {
140*aa772005SRobert Watson pthread_condattr_t attr;
141*aa772005SRobert Watson int error;
142*aa772005SRobert Watson
143*aa772005SRobert Watson error = pthread_condattr_init(&attr);
144*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
145*aa772005SRobert Watson #ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
146*aa772005SRobert Watson error = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
147*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
148*aa772005SRobert Watson #endif
149*aa772005SRobert Watson error = pthread_cond_init(cv, &attr);
150*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
151*aa772005SRobert Watson error = pthread_condattr_destroy(&attr);
152*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
153*aa772005SRobert Watson }
154*aa772005SRobert Watson static __inline void
cv_wait(pthread_cond_t * cv,pthread_mutex_t * lock)155*aa772005SRobert Watson cv_wait(pthread_cond_t *cv, pthread_mutex_t *lock)
156*aa772005SRobert Watson {
157*aa772005SRobert Watson int error;
158*aa772005SRobert Watson
159*aa772005SRobert Watson error = pthread_cond_wait(cv, lock);
160*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
161*aa772005SRobert Watson }
162*aa772005SRobert Watson static __inline bool
cv_timedwait(pthread_cond_t * cv,pthread_mutex_t * lock,int timeout)163*aa772005SRobert Watson cv_timedwait(pthread_cond_t *cv, pthread_mutex_t *lock, int timeout)
164*aa772005SRobert Watson {
165*aa772005SRobert Watson struct timespec ts;
166*aa772005SRobert Watson int error;
167*aa772005SRobert Watson
168*aa772005SRobert Watson if (timeout == 0) {
169*aa772005SRobert Watson cv_wait(cv, lock);
170*aa772005SRobert Watson return (false);
171*aa772005SRobert Watson }
172*aa772005SRobert Watson
173*aa772005SRobert Watson #ifdef HAVE_PTHREAD_CONDATTR_SETCLOCK
174*aa772005SRobert Watson error = clock_gettime(CLOCK_MONOTONIC, &ts);
175*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
176*aa772005SRobert Watson ts.tv_sec += timeout;
177*aa772005SRobert Watson error = pthread_cond_timedwait(cv, lock, &ts);
178*aa772005SRobert Watson #elif HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE_NP
179*aa772005SRobert Watson ts.tv_sec = timeout;
180*aa772005SRobert Watson ts.tv_nsec = 0;
181*aa772005SRobert Watson error = pthread_cond_timedwait_relative_np(cv, lock, &ts);
182*aa772005SRobert Watson #else
183*aa772005SRobert Watson #error Neither pthread_condattr_setclock nor pthread_cond_timedwait_relative_np is available.
184*aa772005SRobert Watson #endif
185*aa772005SRobert Watson PJDLOG_ASSERT(error == 0 || error == ETIMEDOUT);
186*aa772005SRobert Watson return (error == ETIMEDOUT);
187*aa772005SRobert Watson }
188*aa772005SRobert Watson static __inline void
cv_signal(pthread_cond_t * cv)189*aa772005SRobert Watson cv_signal(pthread_cond_t *cv)
190*aa772005SRobert Watson {
191*aa772005SRobert Watson int error;
192*aa772005SRobert Watson
193*aa772005SRobert Watson error = pthread_cond_signal(cv);
194*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
195*aa772005SRobert Watson }
196*aa772005SRobert Watson static __inline void
cv_broadcast(pthread_cond_t * cv)197*aa772005SRobert Watson cv_broadcast(pthread_cond_t *cv)
198*aa772005SRobert Watson {
199*aa772005SRobert Watson int error;
200*aa772005SRobert Watson
201*aa772005SRobert Watson error = pthread_cond_broadcast(cv);
202*aa772005SRobert Watson PJDLOG_ASSERT(error == 0);
203*aa772005SRobert Watson }
204*aa772005SRobert Watson #endif /* !_SYNCH_H_ */
205