1*61046927SAndroid Build Coastguard Worker /**************************************************************************
2*61046927SAndroid Build Coastguard Worker *
3*61046927SAndroid Build Coastguard Worker * Copyright 1999-2006 Brian Paul
4*61046927SAndroid Build Coastguard Worker * Copyright 2008 VMware, Inc.
5*61046927SAndroid Build Coastguard Worker * All Rights Reserved.
6*61046927SAndroid Build Coastguard Worker *
7*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
8*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
9*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
10*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
12*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
13*61046927SAndroid Build Coastguard Worker *
14*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included
15*61046927SAndroid Build Coastguard Worker * in all copies or substantial portions of the Software.
16*61046927SAndroid Build Coastguard Worker *
17*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18*61046927SAndroid Build Coastguard Worker * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21*61046927SAndroid Build Coastguard Worker * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22*61046927SAndroid Build Coastguard Worker * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23*61046927SAndroid Build Coastguard Worker * OTHER DEALINGS IN THE SOFTWARE.
24*61046927SAndroid Build Coastguard Worker *
25*61046927SAndroid Build Coastguard Worker **************************************************************************/
26*61046927SAndroid Build Coastguard Worker
27*61046927SAndroid Build Coastguard Worker #ifndef U_THREAD_H_
28*61046927SAndroid Build Coastguard Worker #define U_THREAD_H_
29*61046927SAndroid Build Coastguard Worker
30*61046927SAndroid Build Coastguard Worker #include <errno.h>
31*61046927SAndroid Build Coastguard Worker #include <stdint.h>
32*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
33*61046927SAndroid Build Coastguard Worker #include <string.h>
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Worker #include "c11/threads.h"
36*61046927SAndroid Build Coastguard Worker #include "detect_os.h"
37*61046927SAndroid Build Coastguard Worker
38*61046927SAndroid Build Coastguard Worker /* Some highly performance-sensitive thread-local variables like the current GL
39*61046927SAndroid Build Coastguard Worker * context are declared with the initial-exec model on Linux. glibc allocates a
40*61046927SAndroid Build Coastguard Worker * fixed number of extra slots for initial-exec TLS variables at startup, and
41*61046927SAndroid Build Coastguard Worker * Mesa relies on (even if it's dlopen()ed after init) being able to fit into
42*61046927SAndroid Build Coastguard Worker * those. This model saves the call to look up the address of the TLS variable.
43*61046927SAndroid Build Coastguard Worker *
44*61046927SAndroid Build Coastguard Worker * However, if we don't have this TLS model available on the platform, then we
45*61046927SAndroid Build Coastguard Worker * still want to use normal TLS (which involves a function call, but not the
46*61046927SAndroid Build Coastguard Worker * expensive pthread_getspecific() or its equivalent).
47*61046927SAndroid Build Coastguard Worker */
48*61046927SAndroid Build Coastguard Worker #if DETECT_OS_APPLE
49*61046927SAndroid Build Coastguard Worker /* Apple Clang emits wrappers when using thread_local that break module linkage,
50*61046927SAndroid Build Coastguard Worker * but not with __thread
51*61046927SAndroid Build Coastguard Worker */
52*61046927SAndroid Build Coastguard Worker #define __THREAD_INITIAL_EXEC __thread
53*61046927SAndroid Build Coastguard Worker #elif defined(__GLIBC__)
54*61046927SAndroid Build Coastguard Worker #define __THREAD_INITIAL_EXEC thread_local __attribute__((tls_model("initial-exec")))
55*61046927SAndroid Build Coastguard Worker #define REALLY_INITIAL_EXEC
56*61046927SAndroid Build Coastguard Worker #else
57*61046927SAndroid Build Coastguard Worker #define __THREAD_INITIAL_EXEC thread_local
58*61046927SAndroid Build Coastguard Worker #endif
59*61046927SAndroid Build Coastguard Worker
60*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
61*61046927SAndroid Build Coastguard Worker extern "C" {
62*61046927SAndroid Build Coastguard Worker #endif
63*61046927SAndroid Build Coastguard Worker
64*61046927SAndroid Build Coastguard Worker int
65*61046927SAndroid Build Coastguard Worker util_get_current_cpu(void);
66*61046927SAndroid Build Coastguard Worker
67*61046927SAndroid Build Coastguard Worker int u_thread_create(thrd_t *thrd, int (*routine)(void *), void *param);
68*61046927SAndroid Build Coastguard Worker
69*61046927SAndroid Build Coastguard Worker void u_thread_setname( const char *name );
70*61046927SAndroid Build Coastguard Worker
71*61046927SAndroid Build Coastguard Worker /**
72*61046927SAndroid Build Coastguard Worker * Set thread affinity.
73*61046927SAndroid Build Coastguard Worker *
74*61046927SAndroid Build Coastguard Worker * \param thread Thread
75*61046927SAndroid Build Coastguard Worker * \param mask Set this affinity mask
76*61046927SAndroid Build Coastguard Worker * \param old_mask Previous affinity mask returned if not NULL
77*61046927SAndroid Build Coastguard Worker * \param num_mask_bits Number of bits in both masks
78*61046927SAndroid Build Coastguard Worker * \return true on success
79*61046927SAndroid Build Coastguard Worker */
80*61046927SAndroid Build Coastguard Worker bool
81*61046927SAndroid Build Coastguard Worker util_set_thread_affinity(thrd_t thread,
82*61046927SAndroid Build Coastguard Worker const uint32_t *mask,
83*61046927SAndroid Build Coastguard Worker uint32_t *old_mask,
84*61046927SAndroid Build Coastguard Worker unsigned num_mask_bits);
85*61046927SAndroid Build Coastguard Worker
86*61046927SAndroid Build Coastguard Worker static inline bool
util_set_current_thread_affinity(const uint32_t * mask,uint32_t * old_mask,unsigned num_mask_bits)87*61046927SAndroid Build Coastguard Worker util_set_current_thread_affinity(const uint32_t *mask,
88*61046927SAndroid Build Coastguard Worker uint32_t *old_mask,
89*61046927SAndroid Build Coastguard Worker unsigned num_mask_bits)
90*61046927SAndroid Build Coastguard Worker {
91*61046927SAndroid Build Coastguard Worker return util_set_thread_affinity(thrd_current(), mask, old_mask,
92*61046927SAndroid Build Coastguard Worker num_mask_bits);
93*61046927SAndroid Build Coastguard Worker }
94*61046927SAndroid Build Coastguard Worker
95*61046927SAndroid Build Coastguard Worker /*
96*61046927SAndroid Build Coastguard Worker * Thread statistics.
97*61046927SAndroid Build Coastguard Worker */
98*61046927SAndroid Build Coastguard Worker
99*61046927SAndroid Build Coastguard Worker /* Return the time of a thread's CPU time clock. */
100*61046927SAndroid Build Coastguard Worker int64_t
101*61046927SAndroid Build Coastguard Worker util_thread_get_time_nano(thrd_t thread);
102*61046927SAndroid Build Coastguard Worker
103*61046927SAndroid Build Coastguard Worker /* Return the time of the current thread's CPU time clock. */
104*61046927SAndroid Build Coastguard Worker static inline int64_t
util_current_thread_get_time_nano(void)105*61046927SAndroid Build Coastguard Worker util_current_thread_get_time_nano(void)
106*61046927SAndroid Build Coastguard Worker {
107*61046927SAndroid Build Coastguard Worker return util_thread_get_time_nano(thrd_current());
108*61046927SAndroid Build Coastguard Worker }
109*61046927SAndroid Build Coastguard Worker
u_thread_is_self(thrd_t thread)110*61046927SAndroid Build Coastguard Worker static inline bool u_thread_is_self(thrd_t thread)
111*61046927SAndroid Build Coastguard Worker {
112*61046927SAndroid Build Coastguard Worker return thrd_equal(thrd_current(), thread);
113*61046927SAndroid Build Coastguard Worker }
114*61046927SAndroid Build Coastguard Worker
115*61046927SAndroid Build Coastguard Worker /*
116*61046927SAndroid Build Coastguard Worker * util_barrier
117*61046927SAndroid Build Coastguard Worker */
118*61046927SAndroid Build Coastguard Worker
119*61046927SAndroid Build Coastguard Worker #if defined(HAVE_PTHREAD) && !defined(__APPLE__) && !defined(__HAIKU__)
120*61046927SAndroid Build Coastguard Worker
121*61046927SAndroid Build Coastguard Worker typedef pthread_barrier_t util_barrier;
122*61046927SAndroid Build Coastguard Worker
123*61046927SAndroid Build Coastguard Worker #else /* If the OS doesn't have its own, implement barriers using a mutex and a condvar */
124*61046927SAndroid Build Coastguard Worker
125*61046927SAndroid Build Coastguard Worker typedef struct {
126*61046927SAndroid Build Coastguard Worker unsigned count;
127*61046927SAndroid Build Coastguard Worker unsigned waiters;
128*61046927SAndroid Build Coastguard Worker uint64_t sequence;
129*61046927SAndroid Build Coastguard Worker mtx_t mutex;
130*61046927SAndroid Build Coastguard Worker cnd_t condvar;
131*61046927SAndroid Build Coastguard Worker } util_barrier;
132*61046927SAndroid Build Coastguard Worker
133*61046927SAndroid Build Coastguard Worker #endif
134*61046927SAndroid Build Coastguard Worker
135*61046927SAndroid Build Coastguard Worker void util_barrier_init(util_barrier *barrier, unsigned count);
136*61046927SAndroid Build Coastguard Worker
137*61046927SAndroid Build Coastguard Worker void util_barrier_destroy(util_barrier *barrier);
138*61046927SAndroid Build Coastguard Worker
139*61046927SAndroid Build Coastguard Worker bool util_barrier_wait(util_barrier *barrier);
140*61046927SAndroid Build Coastguard Worker
141*61046927SAndroid Build Coastguard Worker /*
142*61046927SAndroid Build Coastguard Worker * Semaphores
143*61046927SAndroid Build Coastguard Worker */
144*61046927SAndroid Build Coastguard Worker
145*61046927SAndroid Build Coastguard Worker typedef struct
146*61046927SAndroid Build Coastguard Worker {
147*61046927SAndroid Build Coastguard Worker mtx_t mutex;
148*61046927SAndroid Build Coastguard Worker cnd_t cond;
149*61046927SAndroid Build Coastguard Worker int counter;
150*61046927SAndroid Build Coastguard Worker } util_semaphore;
151*61046927SAndroid Build Coastguard Worker
152*61046927SAndroid Build Coastguard Worker
153*61046927SAndroid Build Coastguard Worker static inline void
util_semaphore_init(util_semaphore * sema,int init_val)154*61046927SAndroid Build Coastguard Worker util_semaphore_init(util_semaphore *sema, int init_val)
155*61046927SAndroid Build Coastguard Worker {
156*61046927SAndroid Build Coastguard Worker (void) mtx_init(&sema->mutex, mtx_plain);
157*61046927SAndroid Build Coastguard Worker cnd_init(&sema->cond);
158*61046927SAndroid Build Coastguard Worker sema->counter = init_val;
159*61046927SAndroid Build Coastguard Worker }
160*61046927SAndroid Build Coastguard Worker
161*61046927SAndroid Build Coastguard Worker static inline void
util_semaphore_destroy(util_semaphore * sema)162*61046927SAndroid Build Coastguard Worker util_semaphore_destroy(util_semaphore *sema)
163*61046927SAndroid Build Coastguard Worker {
164*61046927SAndroid Build Coastguard Worker mtx_destroy(&sema->mutex);
165*61046927SAndroid Build Coastguard Worker cnd_destroy(&sema->cond);
166*61046927SAndroid Build Coastguard Worker }
167*61046927SAndroid Build Coastguard Worker
168*61046927SAndroid Build Coastguard Worker /** Signal/increment semaphore counter */
169*61046927SAndroid Build Coastguard Worker static inline void
util_semaphore_signal(util_semaphore * sema)170*61046927SAndroid Build Coastguard Worker util_semaphore_signal(util_semaphore *sema)
171*61046927SAndroid Build Coastguard Worker {
172*61046927SAndroid Build Coastguard Worker mtx_lock(&sema->mutex);
173*61046927SAndroid Build Coastguard Worker sema->counter++;
174*61046927SAndroid Build Coastguard Worker cnd_signal(&sema->cond);
175*61046927SAndroid Build Coastguard Worker mtx_unlock(&sema->mutex);
176*61046927SAndroid Build Coastguard Worker }
177*61046927SAndroid Build Coastguard Worker
178*61046927SAndroid Build Coastguard Worker /** Wait for semaphore counter to be greater than zero */
179*61046927SAndroid Build Coastguard Worker static inline void
util_semaphore_wait(util_semaphore * sema)180*61046927SAndroid Build Coastguard Worker util_semaphore_wait(util_semaphore *sema)
181*61046927SAndroid Build Coastguard Worker {
182*61046927SAndroid Build Coastguard Worker mtx_lock(&sema->mutex);
183*61046927SAndroid Build Coastguard Worker while (sema->counter <= 0) {
184*61046927SAndroid Build Coastguard Worker cnd_wait(&sema->cond, &sema->mutex);
185*61046927SAndroid Build Coastguard Worker }
186*61046927SAndroid Build Coastguard Worker sema->counter--;
187*61046927SAndroid Build Coastguard Worker mtx_unlock(&sema->mutex);
188*61046927SAndroid Build Coastguard Worker }
189*61046927SAndroid Build Coastguard Worker
190*61046927SAndroid Build Coastguard Worker #ifdef __cplusplus
191*61046927SAndroid Build Coastguard Worker }
192*61046927SAndroid Build Coastguard Worker #endif
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker #endif /* U_THREAD_H_ */
195