xref: /openbsd-src/sbin/unwind/libunbound/util/locks.h (revision ae8c6e27550649e7a558381bdb90c7b5a9042405)
1*ae8c6e27Sflorian /**
2*ae8c6e27Sflorian  * util/locks.h - unbound locking primitives
3*ae8c6e27Sflorian  *
4*ae8c6e27Sflorian  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5*ae8c6e27Sflorian  *
6*ae8c6e27Sflorian  * This software is open source.
7*ae8c6e27Sflorian  *
8*ae8c6e27Sflorian  * Redistribution and use in source and binary forms, with or without
9*ae8c6e27Sflorian  * modification, are permitted provided that the following conditions
10*ae8c6e27Sflorian  * are met:
11*ae8c6e27Sflorian  *
12*ae8c6e27Sflorian  * Redistributions of source code must retain the above copyright notice,
13*ae8c6e27Sflorian  * this list of conditions and the following disclaimer.
14*ae8c6e27Sflorian  *
15*ae8c6e27Sflorian  * Redistributions in binary form must reproduce the above copyright notice,
16*ae8c6e27Sflorian  * this list of conditions and the following disclaimer in the documentation
17*ae8c6e27Sflorian  * and/or other materials provided with the distribution.
18*ae8c6e27Sflorian  *
19*ae8c6e27Sflorian  * Neither the name of the NLNET LABS nor the names of its contributors may
20*ae8c6e27Sflorian  * be used to endorse or promote products derived from this software without
21*ae8c6e27Sflorian  * specific prior written permission.
22*ae8c6e27Sflorian  *
23*ae8c6e27Sflorian  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24*ae8c6e27Sflorian  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25*ae8c6e27Sflorian  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26*ae8c6e27Sflorian  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27*ae8c6e27Sflorian  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28*ae8c6e27Sflorian  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29*ae8c6e27Sflorian  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30*ae8c6e27Sflorian  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31*ae8c6e27Sflorian  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32*ae8c6e27Sflorian  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*ae8c6e27Sflorian  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*ae8c6e27Sflorian  */
35*ae8c6e27Sflorian 
36*ae8c6e27Sflorian #ifndef UTIL_LOCKS_H
37*ae8c6e27Sflorian #define UTIL_LOCKS_H
38*ae8c6e27Sflorian 
39*ae8c6e27Sflorian /**
40*ae8c6e27Sflorian  * \file
41*ae8c6e27Sflorian  * Locking primitives.
42*ae8c6e27Sflorian  * If pthreads is available, these are used.
43*ae8c6e27Sflorian  * If no locking exists, they do nothing.
44*ae8c6e27Sflorian  *
45*ae8c6e27Sflorian  * The idea is to have different sorts of locks for different tasks.
46*ae8c6e27Sflorian  * This allows the locking code to be ported more easily.
47*ae8c6e27Sflorian  *
48*ae8c6e27Sflorian  * Types of locks that are supported.
49*ae8c6e27Sflorian  *   o lock_rw: lock that has many readers and one writer (to a data entry).
50*ae8c6e27Sflorian  *   o lock_basic: simple mutex. Blocking, one person has access only.
51*ae8c6e27Sflorian  *     This lock is meant for non performance sensitive uses.
52*ae8c6e27Sflorian  *   o lock_quick: speed lock. For performance sensitive locking of critical
53*ae8c6e27Sflorian  *     sections. Could be implemented by a mutex or a spinlock.
54*ae8c6e27Sflorian  *
55*ae8c6e27Sflorian  * Also thread creation and deletion functions are defined here.
56*ae8c6e27Sflorian  */
57*ae8c6e27Sflorian 
58*ae8c6e27Sflorian /* if you define your own LOCKRET before including locks.h, you can get most
59*ae8c6e27Sflorian  * locking functions without the dependency on log_err. */
60*ae8c6e27Sflorian #ifndef LOCKRET
61*ae8c6e27Sflorian #include "util/log.h"
62*ae8c6e27Sflorian /**
63*ae8c6e27Sflorian  * The following macro is used to check the return value of the
64*ae8c6e27Sflorian  * pthread calls. They return 0 on success and an errno on error.
65*ae8c6e27Sflorian  * The errno is logged to the logfile with a descriptive comment.
66*ae8c6e27Sflorian  */
67*ae8c6e27Sflorian #define LOCKRET(func) do {\
68*ae8c6e27Sflorian 	int lockret_err;		\
69*ae8c6e27Sflorian 	if( (lockret_err=(func)) != 0)		\
70*ae8c6e27Sflorian 		log_err("%s at %d could not " #func ": %s", \
71*ae8c6e27Sflorian 		__FILE__, __LINE__, strerror(lockret_err));	\
72*ae8c6e27Sflorian  	} while(0)
73*ae8c6e27Sflorian #endif
74*ae8c6e27Sflorian 
75*ae8c6e27Sflorian /** DEBUG: use thread debug whenever possible */
76*ae8c6e27Sflorian #if defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_SPINLOCK_T) && defined(ENABLE_LOCK_CHECKS)
77*ae8c6e27Sflorian #  define USE_THREAD_DEBUG
78*ae8c6e27Sflorian #endif
79*ae8c6e27Sflorian 
80*ae8c6e27Sflorian #ifdef USE_THREAD_DEBUG
81*ae8c6e27Sflorian /******************* THREAD DEBUG ************************/
82*ae8c6e27Sflorian /* (some) checking; to detect races and deadlocks. */
83*ae8c6e27Sflorian #include "testcode/checklocks.h"
84*ae8c6e27Sflorian 
85*ae8c6e27Sflorian #else /* USE_THREAD_DEBUG */
86*ae8c6e27Sflorian #define lock_protect(lock, area, size) /* nop */
87*ae8c6e27Sflorian #define lock_unprotect(lock, area) /* nop */
88*ae8c6e27Sflorian #define lock_get_mem(lock) (0) /* nothing */
89*ae8c6e27Sflorian #define checklock_start() /* nop */
90*ae8c6e27Sflorian #define checklock_stop() /* nop */
91*ae8c6e27Sflorian 
92*ae8c6e27Sflorian #ifdef HAVE_PTHREAD
93*ae8c6e27Sflorian #include <pthread.h>
94*ae8c6e27Sflorian 
95*ae8c6e27Sflorian /******************* PTHREAD ************************/
96*ae8c6e27Sflorian 
97*ae8c6e27Sflorian /** use pthread mutex for basic lock */
98*ae8c6e27Sflorian typedef pthread_mutex_t lock_basic_type;
99*ae8c6e27Sflorian /** small front for pthread init func, NULL is default attrs. */
100*ae8c6e27Sflorian #define lock_basic_init(lock) LOCKRET(pthread_mutex_init(lock, NULL))
101*ae8c6e27Sflorian #define lock_basic_destroy(lock) LOCKRET(pthread_mutex_destroy(lock))
102*ae8c6e27Sflorian #define lock_basic_lock(lock) LOCKRET(pthread_mutex_lock(lock))
103*ae8c6e27Sflorian #define lock_basic_unlock(lock) LOCKRET(pthread_mutex_unlock(lock))
104*ae8c6e27Sflorian 
105*ae8c6e27Sflorian #ifndef HAVE_PTHREAD_RWLOCK_T
106*ae8c6e27Sflorian /** in case rwlocks are not supported, use a mutex. */
107*ae8c6e27Sflorian typedef pthread_mutex_t lock_rw_type;
108*ae8c6e27Sflorian #define lock_rw_init(lock) LOCKRET(pthread_mutex_init(lock, NULL))
109*ae8c6e27Sflorian #define lock_rw_destroy(lock) LOCKRET(pthread_mutex_destroy(lock))
110*ae8c6e27Sflorian #define lock_rw_rdlock(lock) LOCKRET(pthread_mutex_lock(lock))
111*ae8c6e27Sflorian #define lock_rw_wrlock(lock) LOCKRET(pthread_mutex_lock(lock))
112*ae8c6e27Sflorian #define lock_rw_unlock(lock) LOCKRET(pthread_mutex_unlock(lock))
113*ae8c6e27Sflorian #else /* HAVE_PTHREAD_RWLOCK_T */
114*ae8c6e27Sflorian /** we use the pthread rwlock */
115*ae8c6e27Sflorian typedef pthread_rwlock_t lock_rw_type;
116*ae8c6e27Sflorian /** small front for pthread init func, NULL is default attrs. */
117*ae8c6e27Sflorian #define lock_rw_init(lock) LOCKRET(pthread_rwlock_init(lock, NULL))
118*ae8c6e27Sflorian #define lock_rw_destroy(lock) LOCKRET(pthread_rwlock_destroy(lock))
119*ae8c6e27Sflorian #define lock_rw_rdlock(lock) LOCKRET(pthread_rwlock_rdlock(lock))
120*ae8c6e27Sflorian #define lock_rw_wrlock(lock) LOCKRET(pthread_rwlock_wrlock(lock))
121*ae8c6e27Sflorian #define lock_rw_unlock(lock) LOCKRET(pthread_rwlock_unlock(lock))
122*ae8c6e27Sflorian #endif /* HAVE_PTHREAD_RWLOCK_T */
123*ae8c6e27Sflorian 
124*ae8c6e27Sflorian #ifndef HAVE_PTHREAD_SPINLOCK_T
125*ae8c6e27Sflorian /** in case spinlocks are not supported, use a mutex. */
126*ae8c6e27Sflorian typedef pthread_mutex_t lock_quick_type;
127*ae8c6e27Sflorian /** small front for pthread init func, NULL is default attrs. */
128*ae8c6e27Sflorian #define lock_quick_init(lock) LOCKRET(pthread_mutex_init(lock, NULL))
129*ae8c6e27Sflorian #define lock_quick_destroy(lock) LOCKRET(pthread_mutex_destroy(lock))
130*ae8c6e27Sflorian #define lock_quick_lock(lock) LOCKRET(pthread_mutex_lock(lock))
131*ae8c6e27Sflorian #define lock_quick_unlock(lock) LOCKRET(pthread_mutex_unlock(lock))
132*ae8c6e27Sflorian 
133*ae8c6e27Sflorian #else /* HAVE_PTHREAD_SPINLOCK_T */
134*ae8c6e27Sflorian /** use pthread spinlock for the quick lock */
135*ae8c6e27Sflorian typedef pthread_spinlock_t lock_quick_type;
136*ae8c6e27Sflorian /**
137*ae8c6e27Sflorian  * allocate process private since this is available whether
138*ae8c6e27Sflorian  * Thread Process-Shared Synchronization is supported or not.
139*ae8c6e27Sflorian  * This means only threads inside this process may access the lock.
140*ae8c6e27Sflorian  * (not threads from another process that shares memory).
141*ae8c6e27Sflorian  * spinlocks are not supported on all pthread platforms.
142*ae8c6e27Sflorian  */
143*ae8c6e27Sflorian #define lock_quick_init(lock) LOCKRET(pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE))
144*ae8c6e27Sflorian #define lock_quick_destroy(lock) LOCKRET(pthread_spin_destroy(lock))
145*ae8c6e27Sflorian #define lock_quick_lock(lock) LOCKRET(pthread_spin_lock(lock))
146*ae8c6e27Sflorian #define lock_quick_unlock(lock) LOCKRET(pthread_spin_unlock(lock))
147*ae8c6e27Sflorian 
148*ae8c6e27Sflorian #endif /* HAVE SPINLOCK */
149*ae8c6e27Sflorian 
150*ae8c6e27Sflorian /** Thread creation */
151*ae8c6e27Sflorian typedef pthread_t ub_thread_type;
152*ae8c6e27Sflorian /** On alpine linux default thread stack size is 80 Kb. See
153*ae8c6e27Sflorian http://wiki.musl-libc.org/wiki/Functional_differences_from_glibc#Thread_stack_size
154*ae8c6e27Sflorian This is not enough and cause segfault. Other linux distros have 2 Mb at least.
155*ae8c6e27Sflorian Wrapper for set up thread stack size */
156*ae8c6e27Sflorian #define PTHREADSTACKSIZE 2*1024*1024
157*ae8c6e27Sflorian #define PTHREADCREATE(thr, stackrequired, func, arg) do {\
158*ae8c6e27Sflorian 	pthread_attr_t attr; \
159*ae8c6e27Sflorian 	size_t stacksize; \
160*ae8c6e27Sflorian 	LOCKRET(pthread_attr_init(&attr)); \
161*ae8c6e27Sflorian 	LOCKRET(pthread_attr_getstacksize(&attr, &stacksize)); \
162*ae8c6e27Sflorian 	if (stacksize < stackrequired) { \
163*ae8c6e27Sflorian 		LOCKRET(pthread_attr_setstacksize(&attr, stackrequired)); \
164*ae8c6e27Sflorian 		LOCKRET(pthread_create(thr, &attr, func, arg)); \
165*ae8c6e27Sflorian 		LOCKRET(pthread_attr_getstacksize(&attr, &stacksize)); \
166*ae8c6e27Sflorian 		verbose(VERB_ALGO, "Thread stack size set to %u", (unsigned)stacksize); \
167*ae8c6e27Sflorian 	} else {LOCKRET(pthread_create(thr, NULL, func, arg));} \
168*ae8c6e27Sflorian 	} while(0)
169*ae8c6e27Sflorian /** Use wrapper for set thread stack size on attributes. */
170*ae8c6e27Sflorian #define ub_thread_create(thr, func, arg) PTHREADCREATE(thr, PTHREADSTACKSIZE, func, arg)
171*ae8c6e27Sflorian /** get self id. */
172*ae8c6e27Sflorian #define ub_thread_self() pthread_self()
173*ae8c6e27Sflorian /** wait for another thread to terminate */
174*ae8c6e27Sflorian #define ub_thread_join(thread) LOCKRET(pthread_join(thread, NULL))
175*ae8c6e27Sflorian typedef pthread_key_t ub_thread_key_type;
176*ae8c6e27Sflorian #define ub_thread_key_create(key, f) LOCKRET(pthread_key_create(key, f))
177*ae8c6e27Sflorian #define ub_thread_key_set(key, v) LOCKRET(pthread_setspecific(key, v))
178*ae8c6e27Sflorian #define ub_thread_key_get(key) pthread_getspecific(key)
179*ae8c6e27Sflorian 
180*ae8c6e27Sflorian #else /* we do not HAVE_PTHREAD */
181*ae8c6e27Sflorian #ifdef HAVE_SOLARIS_THREADS
182*ae8c6e27Sflorian 
183*ae8c6e27Sflorian /******************* SOLARIS THREADS ************************/
184*ae8c6e27Sflorian #include <synch.h>
185*ae8c6e27Sflorian #include <thread.h>
186*ae8c6e27Sflorian 
187*ae8c6e27Sflorian typedef rwlock_t lock_rw_type;
188*ae8c6e27Sflorian #define lock_rw_init(lock) LOCKRET(rwlock_init(lock, USYNC_THREAD, NULL))
189*ae8c6e27Sflorian #define lock_rw_destroy(lock) LOCKRET(rwlock_destroy(lock))
190*ae8c6e27Sflorian #define lock_rw_rdlock(lock) LOCKRET(rw_rdlock(lock))
191*ae8c6e27Sflorian #define lock_rw_wrlock(lock) LOCKRET(rw_wrlock(lock))
192*ae8c6e27Sflorian #define lock_rw_unlock(lock) LOCKRET(rw_unlock(lock))
193*ae8c6e27Sflorian 
194*ae8c6e27Sflorian /** use basic mutex */
195*ae8c6e27Sflorian typedef mutex_t lock_basic_type;
196*ae8c6e27Sflorian #define lock_basic_init(lock) LOCKRET(mutex_init(lock, USYNC_THREAD, NULL))
197*ae8c6e27Sflorian #define lock_basic_destroy(lock) LOCKRET(mutex_destroy(lock))
198*ae8c6e27Sflorian #define lock_basic_lock(lock) LOCKRET(mutex_lock(lock))
199*ae8c6e27Sflorian #define lock_basic_unlock(lock) LOCKRET(mutex_unlock(lock))
200*ae8c6e27Sflorian 
201*ae8c6e27Sflorian /** No spinlocks in solaris threads API. Use a mutex. */
202*ae8c6e27Sflorian typedef mutex_t lock_quick_type;
203*ae8c6e27Sflorian #define lock_quick_init(lock) LOCKRET(mutex_init(lock, USYNC_THREAD, NULL))
204*ae8c6e27Sflorian #define lock_quick_destroy(lock) LOCKRET(mutex_destroy(lock))
205*ae8c6e27Sflorian #define lock_quick_lock(lock) LOCKRET(mutex_lock(lock))
206*ae8c6e27Sflorian #define lock_quick_unlock(lock) LOCKRET(mutex_unlock(lock))
207*ae8c6e27Sflorian 
208*ae8c6e27Sflorian /** Thread creation, create a default thread. */
209*ae8c6e27Sflorian typedef thread_t ub_thread_type;
210*ae8c6e27Sflorian #define ub_thread_create(thr, func, arg) LOCKRET(thr_create(NULL, NULL, func, arg, NULL, thr))
211*ae8c6e27Sflorian #define ub_thread_self() thr_self()
212*ae8c6e27Sflorian #define ub_thread_join(thread) LOCKRET(thr_join(thread, NULL, NULL))
213*ae8c6e27Sflorian typedef thread_key_t ub_thread_key_type;
214*ae8c6e27Sflorian #define ub_thread_key_create(key, f) LOCKRET(thr_keycreate(key, f))
215*ae8c6e27Sflorian #define ub_thread_key_set(key, v) LOCKRET(thr_setspecific(key, v))
216*ae8c6e27Sflorian void* ub_thread_key_get(ub_thread_key_type key);
217*ae8c6e27Sflorian 
218*ae8c6e27Sflorian 
219*ae8c6e27Sflorian #else /* we do not HAVE_SOLARIS_THREADS and no PTHREADS */
220*ae8c6e27Sflorian /******************* WINDOWS THREADS ************************/
221*ae8c6e27Sflorian #ifdef HAVE_WINDOWS_THREADS
222*ae8c6e27Sflorian #include <windows.h>
223*ae8c6e27Sflorian 
224*ae8c6e27Sflorian /* Use a mutex */
225*ae8c6e27Sflorian typedef LONG lock_rw_type;
226*ae8c6e27Sflorian #define lock_rw_init(lock) lock_basic_init(lock)
227*ae8c6e27Sflorian #define lock_rw_destroy(lock) lock_basic_destroy(lock)
228*ae8c6e27Sflorian #define lock_rw_rdlock(lock) lock_basic_lock(lock)
229*ae8c6e27Sflorian #define lock_rw_wrlock(lock) lock_basic_lock(lock)
230*ae8c6e27Sflorian #define lock_rw_unlock(lock) lock_basic_unlock(lock)
231*ae8c6e27Sflorian 
232*ae8c6e27Sflorian /** the basic lock is a mutex, implemented opaquely, for error handling. */
233*ae8c6e27Sflorian typedef LONG lock_basic_type;
234*ae8c6e27Sflorian void lock_basic_init(lock_basic_type* lock);
235*ae8c6e27Sflorian void lock_basic_destroy(lock_basic_type* lock);
236*ae8c6e27Sflorian void lock_basic_lock(lock_basic_type* lock);
237*ae8c6e27Sflorian void lock_basic_unlock(lock_basic_type* lock);
238*ae8c6e27Sflorian 
239*ae8c6e27Sflorian /** on windows no spinlock, use mutex too. */
240*ae8c6e27Sflorian typedef LONG lock_quick_type;
241*ae8c6e27Sflorian #define lock_quick_init(lock) lock_basic_init(lock)
242*ae8c6e27Sflorian #define lock_quick_destroy(lock) lock_basic_destroy(lock)
243*ae8c6e27Sflorian #define lock_quick_lock(lock) lock_basic_lock(lock)
244*ae8c6e27Sflorian #define lock_quick_unlock(lock) lock_basic_unlock(lock)
245*ae8c6e27Sflorian 
246*ae8c6e27Sflorian /** Thread creation, create a default thread. */
247*ae8c6e27Sflorian typedef HANDLE ub_thread_type;
248*ae8c6e27Sflorian void ub_thread_create(ub_thread_type* thr, void* (*func)(void*), void* arg);
249*ae8c6e27Sflorian ub_thread_type ub_thread_self(void);
250*ae8c6e27Sflorian void ub_thread_join(ub_thread_type thr);
251*ae8c6e27Sflorian typedef DWORD ub_thread_key_type;
252*ae8c6e27Sflorian void ub_thread_key_create(ub_thread_key_type* key, void* f);
253*ae8c6e27Sflorian void ub_thread_key_set(ub_thread_key_type key, void* v);
254*ae8c6e27Sflorian void* ub_thread_key_get(ub_thread_key_type key);
255*ae8c6e27Sflorian 
256*ae8c6e27Sflorian #else /* we do not HAVE_SOLARIS_THREADS, PTHREADS or WINDOWS_THREADS */
257*ae8c6e27Sflorian 
258*ae8c6e27Sflorian /******************* NO THREADS ************************/
259*ae8c6e27Sflorian #define THREADS_DISABLED 1
260*ae8c6e27Sflorian /** In case there is no thread support, define locks to do nothing */
261*ae8c6e27Sflorian typedef int lock_rw_type;
262*ae8c6e27Sflorian #define lock_rw_init(lock) /* nop */
263*ae8c6e27Sflorian #define lock_rw_destroy(lock) /* nop */
264*ae8c6e27Sflorian #define lock_rw_rdlock(lock) /* nop */
265*ae8c6e27Sflorian #define lock_rw_wrlock(lock) /* nop */
266*ae8c6e27Sflorian #define lock_rw_unlock(lock) /* nop */
267*ae8c6e27Sflorian 
268*ae8c6e27Sflorian /** define locks to do nothing */
269*ae8c6e27Sflorian typedef int lock_basic_type;
270*ae8c6e27Sflorian #define lock_basic_init(lock) /* nop */
271*ae8c6e27Sflorian #define lock_basic_destroy(lock) /* nop */
272*ae8c6e27Sflorian #define lock_basic_lock(lock) /* nop */
273*ae8c6e27Sflorian #define lock_basic_unlock(lock) /* nop */
274*ae8c6e27Sflorian 
275*ae8c6e27Sflorian /** define locks to do nothing */
276*ae8c6e27Sflorian typedef int lock_quick_type;
277*ae8c6e27Sflorian #define lock_quick_init(lock) /* nop */
278*ae8c6e27Sflorian #define lock_quick_destroy(lock) /* nop */
279*ae8c6e27Sflorian #define lock_quick_lock(lock) /* nop */
280*ae8c6e27Sflorian #define lock_quick_unlock(lock) /* nop */
281*ae8c6e27Sflorian 
282*ae8c6e27Sflorian /** Thread creation, threads do not exist */
283*ae8c6e27Sflorian typedef pid_t ub_thread_type;
284*ae8c6e27Sflorian /** ub_thread_create is simulated with fork (extremely heavy threads,
285*ae8c6e27Sflorian   * with no shared memory). */
286*ae8c6e27Sflorian #define ub_thread_create(thr, func, arg) \
287*ae8c6e27Sflorian 	ub_thr_fork_create(thr, func, arg)
288*ae8c6e27Sflorian #define ub_thread_self() getpid()
289*ae8c6e27Sflorian #define ub_thread_join(thread) ub_thr_fork_wait(thread)
290*ae8c6e27Sflorian void ub_thr_fork_wait(ub_thread_type thread);
291*ae8c6e27Sflorian void ub_thr_fork_create(ub_thread_type* thr, void* (*func)(void*), void* arg);
292*ae8c6e27Sflorian typedef void* ub_thread_key_type;
293*ae8c6e27Sflorian #define ub_thread_key_create(key, f) (*(key)) = NULL
294*ae8c6e27Sflorian #define ub_thread_key_set(key, v) (key) = (v)
295*ae8c6e27Sflorian #define ub_thread_key_get(key) (key)
296*ae8c6e27Sflorian 
297*ae8c6e27Sflorian #endif /* HAVE_WINDOWS_THREADS */
298*ae8c6e27Sflorian #endif /* HAVE_SOLARIS_THREADS */
299*ae8c6e27Sflorian #endif /* HAVE_PTHREAD */
300*ae8c6e27Sflorian #endif /* USE_THREAD_DEBUG */
301*ae8c6e27Sflorian 
302*ae8c6e27Sflorian /**
303*ae8c6e27Sflorian  * Block all signals for this thread.
304*ae8c6e27Sflorian  * fatal exit on error.
305*ae8c6e27Sflorian  */
306*ae8c6e27Sflorian void ub_thread_blocksigs(void);
307*ae8c6e27Sflorian 
308*ae8c6e27Sflorian /**
309*ae8c6e27Sflorian  * unblock one signal for this thread.
310*ae8c6e27Sflorian  */
311*ae8c6e27Sflorian void ub_thread_sig_unblock(int sig);
312*ae8c6e27Sflorian 
313*ae8c6e27Sflorian #endif /* UTIL_LOCKS_H */
314