1 /**************************************************************************
3 * Copyright 1999-2006 Brian Paul
4 * Copyright 2008 VMware, Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
31 * Thread, mutex, condition variable, barrier, semaphore and
32 * thread-specific data functions.
40 #include "pipe/p_compiler.h"
41 #include "util/u_debug.h" /* for assert */
43 #include "c11/threads.h"
52 typedef thrd_t pipe_thread
;
54 #define PIPE_THREAD_ROUTINE( name, param ) \
55 int name( void *param )
57 static INLINE pipe_thread
pipe_thread_create( PIPE_THREAD_ROUTINE((*routine
), ), void *param
)
61 sigset_t saved_set
, new_set
;
65 pthread_sigmask(SIG_SETMASK
, &new_set
, &saved_set
);
66 ret
= thrd_create( &thread
, routine
, param
);
67 pthread_sigmask(SIG_SETMASK
, &saved_set
, NULL
);
70 ret
= thrd_create( &thread
, routine
, param
);
78 static INLINE
int pipe_thread_wait( pipe_thread thread
)
80 return thrd_join( thread
, NULL
);
83 static INLINE
int pipe_thread_destroy( pipe_thread thread
)
85 return thrd_detach( thread
);
88 static INLINE
void pipe_thread_setname( const char *name
)
90 #if defined(HAVE_PTHREAD)
91 # if defined(__GNU_LIBRARY__) && defined(__GLIBC__) && defined(__GLIBC_MINOR__) && \
92 (__GLIBC__ >= 3 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 12))
93 pthread_setname_np(pthread_self(), name
);
102 typedef mtx_t pipe_mutex
;
104 #define pipe_static_mutex(mutex) \
105 static pipe_mutex mutex = _MTX_INITIALIZER_NP
107 #define pipe_mutex_init(mutex) \
108 (void) mtx_init(&(mutex), mtx_plain)
110 #define pipe_mutex_destroy(mutex) \
111 mtx_destroy(&(mutex))
113 #define pipe_mutex_lock(mutex) \
114 (void) mtx_lock(&(mutex))
116 #define pipe_mutex_unlock(mutex) \
117 (void) mtx_unlock(&(mutex))
122 typedef cnd_t pipe_condvar
;
124 #define pipe_condvar_init(cond) \
127 #define pipe_condvar_destroy(cond) \
130 #define pipe_condvar_wait(cond, mutex) \
131 cnd_wait(&(cond), &(mutex))
133 #define pipe_condvar_signal(cond) \
136 #define pipe_condvar_broadcast(cond) \
137 cnd_broadcast(&(cond))
144 #if (defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_HURD)) && !defined(PIPE_OS_ANDROID)
146 typedef pthread_barrier_t pipe_barrier
;
148 static INLINE
void pipe_barrier_init(pipe_barrier
*barrier
, unsigned count
)
150 pthread_barrier_init(barrier
, NULL
, count
);
153 static INLINE
void pipe_barrier_destroy(pipe_barrier
*barrier
)
155 pthread_barrier_destroy(barrier
);
158 static INLINE
void pipe_barrier_wait(pipe_barrier
*barrier
)
160 pthread_barrier_wait(barrier
);
164 #else /* If the OS doesn't have its own, implement barriers using a mutex and a condvar */
171 pipe_condvar condvar
;
174 static INLINE
void pipe_barrier_init(pipe_barrier
*barrier
, unsigned count
)
176 barrier
->count
= count
;
177 barrier
->waiters
= 0;
178 barrier
->sequence
= 0;
179 pipe_mutex_init(barrier
->mutex
);
180 pipe_condvar_init(barrier
->condvar
);
183 static INLINE
void pipe_barrier_destroy(pipe_barrier
*barrier
)
185 assert(barrier
->waiters
== 0);
186 pipe_mutex_destroy(barrier
->mutex
);
187 pipe_condvar_destroy(barrier
->condvar
);
190 static INLINE
void pipe_barrier_wait(pipe_barrier
*barrier
)
192 pipe_mutex_lock(barrier
->mutex
);
194 assert(barrier
->waiters
< barrier
->count
);
197 if (barrier
->waiters
< barrier
->count
) {
198 uint64_t sequence
= barrier
->sequence
;
201 pipe_condvar_wait(barrier
->condvar
, barrier
->mutex
);
202 } while (sequence
== barrier
->sequence
);
204 barrier
->waiters
= 0;
206 pipe_condvar_broadcast(barrier
->condvar
);
209 pipe_mutex_unlock(barrier
->mutex
);
229 pipe_semaphore_init(pipe_semaphore
*sema
, int init_val
)
231 pipe_mutex_init(sema
->mutex
);
232 pipe_condvar_init(sema
->cond
);
233 sema
->counter
= init_val
;
237 pipe_semaphore_destroy(pipe_semaphore
*sema
)
239 pipe_mutex_destroy(sema
->mutex
);
240 pipe_condvar_destroy(sema
->cond
);
243 /** Signal/increment semaphore counter */
245 pipe_semaphore_signal(pipe_semaphore
*sema
)
247 pipe_mutex_lock(sema
->mutex
);
249 pipe_condvar_signal(sema
->cond
);
250 pipe_mutex_unlock(sema
->mutex
);
253 /** Wait for semaphore counter to be greater than zero */
255 pipe_semaphore_wait(pipe_semaphore
*sema
)
257 pipe_mutex_lock(sema
->mutex
);
258 while (sema
->counter
<= 0) {
259 pipe_condvar_wait(sema
->cond
, sema
->mutex
);
262 pipe_mutex_unlock(sema
->mutex
);
268 * Thread-specific data.
277 #define PIPE_TSD_INIT_MAGIC 0xff8adc98
281 pipe_tsd_init(pipe_tsd
*tsd
)
283 if (tss_create(&tsd
->key
, NULL
/*free*/) != 0) {
286 tsd
->initMagic
= PIPE_TSD_INIT_MAGIC
;
290 pipe_tsd_get(pipe_tsd
*tsd
)
292 if (tsd
->initMagic
!= (int) PIPE_TSD_INIT_MAGIC
) {
295 return tss_get(tsd
->key
);
299 pipe_tsd_set(pipe_tsd
*tsd
, void *value
)
301 if (tsd
->initMagic
!= (int) PIPE_TSD_INIT_MAGIC
) {
304 if (tss_set(tsd
->key
, value
) != 0) {
311 #endif /* OS_THREAD_H_ */