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