1 /* $OpenBSD: thread_private.h,v 1.24 2008/06/14 15:43:43 otto Exp $ */ 2 3 /* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman <marc@snafu.org> */ 4 5 #ifndef _THREAD_PRIVATE_H_ 6 #define _THREAD_PRIVATE_H_ 7 8 /* 9 * This file defines the thread library interface to libc. Thread 10 * libraries must implement the functions described here for proper 11 * inter-operation with libc. libc contains weak versions of the 12 * described functions for operation in a non-threaded environment. 13 */ 14 15 /* 16 * This variable is 0 until a second thread is created. 17 */ 18 extern int __isthreaded; 19 20 /* 21 * Weak symbols are used in libc so that the thread library can 22 * efficiently wrap libc functions. 23 * 24 * Use WEAK_NAME(n) to get a libc-private name for n (_weak_n), 25 * WEAK_ALIAS(n) to generate the weak symbol n pointing to _weak_n, 26 * WEAK_PROTOTYPE(n) to generate a prototype for _weak_n (based on n). 27 */ 28 #define WEAK_NAME(name) __CONCAT(_weak_,name) 29 #define WEAK_ALIAS(name) __weak_alias(name, WEAK_NAME(name)) 30 #ifdef __GNUC__ 31 #define WEAK_PROTOTYPE(name) __typeof__(name) WEAK_NAME(name) 32 #else 33 #define WEAK_PROTOTYPE(name) /* typeof() only in gcc */ 34 #endif 35 36 /* 37 * helper macro to make unique names in the thread namespace 38 */ 39 #define __THREAD_NAME(name) __CONCAT(_thread_tagname_,name) 40 41 /* 42 * helper functions that exist as (weak) null functions in libc and 43 * (strong) functions in the thread library. These functions: 44 * 45 * _thread_tag_lock: 46 * lock the mutex associated with the given tag. If the given 47 * tag is NULL a tag is first allocated. 48 * 49 * _thread_tag_unlock: 50 * unlock the mutex associated with the given tag. If the given 51 * tag is NULL a tag is first allocated. 52 * 53 * _thread_tag_storage: 54 * return a pointer to per thread instance of data associated 55 * with the given tag. If the given tag is NULL a tag is first 56 * allocated. 57 * 58 * _thread_mutex_lock: 59 * lock the given mutex. If the given mutex is NULL, 60 * rely on rthreads/pthreads implementation to initialize 61 * the mutex before locking. 62 * 63 * _thread_mutex_unlock: 64 * unlock the given mutex. 65 * 66 * _thread_mutex_destroy: 67 * destroy the given mutex. 68 */ 69 void _thread_tag_lock(void **); 70 void _thread_tag_unlock(void **); 71 void *_thread_tag_storage(void **, void *, size_t, void *); 72 void _thread_mutex_lock(void **); 73 void _thread_mutex_unlock(void **); 74 void _thread_mutex_destroy(void **); 75 76 /* 77 * Macros used in libc to access thread mutex, keys, and per thread storage. 78 * _THREAD_PRIVATE_KEY and _THREAD_PRIVATE_MUTEX are different macros for 79 * historical reasons. They do the same thing, define a static variable 80 * keyed by 'name' that identifies a mutex and a key to identify per thread 81 * data. 82 */ 83 #define _THREAD_PRIVATE_KEY(name) \ 84 static void *__THREAD_NAME(name) 85 #define _THREAD_PRIVATE_MUTEX(name) \ 86 static void *__THREAD_NAME(name) 87 #define _THREAD_PRIVATE_MUTEX_LOCK(name) \ 88 _thread_tag_lock(&(__THREAD_NAME(name))) 89 #define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \ 90 _thread_tag_unlock(&(__THREAD_NAME(name))) 91 #define _THREAD_PRIVATE(keyname, storage, error) \ 92 _thread_tag_storage(&(__THREAD_NAME(keyname)), &(storage), \ 93 sizeof (storage), error) 94 95 /* 96 * Macros used in libc to access mutexes. 97 */ 98 #define _MUTEX_LOCK(mutex) \ 99 do { \ 100 if (__isthreaded) \ 101 _thread_mutex_lock(mutex); \ 102 } while (0) 103 #define _MUTEX_UNLOCK(mutex) \ 104 do { \ 105 if (__isthreaded) \ 106 _thread_mutex_unlock(mutex); \ 107 } while (0) 108 #define _MUTEX_DESTROY(mutex) \ 109 do { \ 110 if (__isthreaded) \ 111 _thread_mutex_destroy(mutex); \ 112 } while (0) 113 114 /* 115 * Resolver code is special cased in that it uses global keys. 116 */ 117 extern void *__THREAD_NAME(_res); 118 extern void *__THREAD_NAME(_res_ext); 119 extern void *__THREAD_NAME(serv_mutex); 120 121 /* 122 * malloc lock/unlock prototypes and definitions 123 */ 124 void _thread_malloc_lock(void); 125 void _thread_malloc_unlock(void); 126 127 #define _MALLOC_LOCK() do { \ 128 if (__isthreaded) \ 129 _thread_malloc_lock(); \ 130 } while (0) 131 #define _MALLOC_UNLOCK() do { \ 132 if (__isthreaded) \ 133 _thread_malloc_unlock();\ 134 } while (0) 135 136 void _thread_atexit_lock(void); 137 void _thread_atexit_unlock(void); 138 139 #define _ATEXIT_LOCK() do { \ 140 if (__isthreaded) \ 141 _thread_atexit_lock(); \ 142 } while (0) 143 #define _ATEXIT_UNLOCK() do { \ 144 if (__isthreaded) \ 145 _thread_atexit_unlock();\ 146 } while (0) 147 148 void _thread_arc4_lock(void); 149 void _thread_arc4_unlock(void); 150 151 #define _ARC4_LOCK() do { \ 152 if (__isthreaded) \ 153 _thread_arc4_lock(); \ 154 } while (0) 155 #define _ARC4_UNLOCK() do { \ 156 if (__isthreaded) \ 157 _thread_arc4_unlock();\ 158 } while (0) 159 160 #endif /* _THREAD_PRIVATE_H_ */ 161