1 /* $OpenBSD: thread_private.h,v 1.25 2011/10/16 06:29:56 guenther 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 * Ditto for hand-written syscall stubs: 38 * 39 * Use STUB_NAME(n) to get the strong name of the stub: _thread_sys_n 40 * STUB_ALIAS(n) to generate the weak symbol n pointing to _thread_sys_n, 41 * STUB_PROTOTYPE(n) to generate a prototype for _thread_sys_n (based on n). 42 */ 43 #define STUB_NAME(name) __CONCAT(_thread_sys_,name) 44 #define STUB_ALIAS(name) __weak_alias(name, STUB_NAME(name)) 45 #ifdef __GNUC__ 46 #define STUB_PROTOTYPE(name) __typeof__(name) STUB_NAME(name) 47 #else 48 #define STUB_PROTOTYPE(name) /* typeof() only in gcc */ 49 #endif 50 51 /* 52 * helper macro to make unique names in the thread namespace 53 */ 54 #define __THREAD_NAME(name) __CONCAT(_thread_tagname_,name) 55 56 /* 57 * helper functions that exist as (weak) null functions in libc and 58 * (strong) functions in the thread library. These functions: 59 * 60 * _thread_tag_lock: 61 * lock the mutex associated with the given tag. If the given 62 * tag is NULL a tag is first allocated. 63 * 64 * _thread_tag_unlock: 65 * unlock the mutex associated with the given tag. If the given 66 * tag is NULL a tag is first allocated. 67 * 68 * _thread_tag_storage: 69 * return a pointer to per thread instance of data associated 70 * with the given tag. If the given tag is NULL a tag is first 71 * allocated. 72 * 73 * _thread_mutex_lock: 74 * lock the given mutex. If the given mutex is NULL, 75 * rely on rthreads/pthreads implementation to initialize 76 * the mutex before locking. 77 * 78 * _thread_mutex_unlock: 79 * unlock the given mutex. 80 * 81 * _thread_mutex_destroy: 82 * destroy the given mutex. 83 */ 84 void _thread_tag_lock(void **); 85 void _thread_tag_unlock(void **); 86 void *_thread_tag_storage(void **, void *, size_t, void *); 87 void _thread_mutex_lock(void **); 88 void _thread_mutex_unlock(void **); 89 void _thread_mutex_destroy(void **); 90 91 /* 92 * Macros used in libc to access thread mutex, keys, and per thread storage. 93 * _THREAD_PRIVATE_KEY and _THREAD_PRIVATE_MUTEX are different macros for 94 * historical reasons. They do the same thing, define a static variable 95 * keyed by 'name' that identifies a mutex and a key to identify per thread 96 * data. 97 */ 98 #define _THREAD_PRIVATE_KEY(name) \ 99 static void *__THREAD_NAME(name) 100 #define _THREAD_PRIVATE_MUTEX(name) \ 101 static void *__THREAD_NAME(name) 102 #define _THREAD_PRIVATE_MUTEX_LOCK(name) \ 103 _thread_tag_lock(&(__THREAD_NAME(name))) 104 #define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \ 105 _thread_tag_unlock(&(__THREAD_NAME(name))) 106 #define _THREAD_PRIVATE(keyname, storage, error) \ 107 _thread_tag_storage(&(__THREAD_NAME(keyname)), &(storage), \ 108 sizeof (storage), error) 109 110 /* 111 * Macros used in libc to access mutexes. 112 */ 113 #define _MUTEX_LOCK(mutex) \ 114 do { \ 115 if (__isthreaded) \ 116 _thread_mutex_lock(mutex); \ 117 } while (0) 118 #define _MUTEX_UNLOCK(mutex) \ 119 do { \ 120 if (__isthreaded) \ 121 _thread_mutex_unlock(mutex); \ 122 } while (0) 123 #define _MUTEX_DESTROY(mutex) \ 124 do { \ 125 if (__isthreaded) \ 126 _thread_mutex_destroy(mutex); \ 127 } while (0) 128 129 /* 130 * Resolver code is special cased in that it uses global keys. 131 */ 132 extern void *__THREAD_NAME(_res); 133 extern void *__THREAD_NAME(_res_ext); 134 extern void *__THREAD_NAME(serv_mutex); 135 136 /* 137 * malloc lock/unlock prototypes and definitions 138 */ 139 void _thread_malloc_lock(void); 140 void _thread_malloc_unlock(void); 141 142 #define _MALLOC_LOCK() do { \ 143 if (__isthreaded) \ 144 _thread_malloc_lock(); \ 145 } while (0) 146 #define _MALLOC_UNLOCK() do { \ 147 if (__isthreaded) \ 148 _thread_malloc_unlock();\ 149 } while (0) 150 151 void _thread_atexit_lock(void); 152 void _thread_atexit_unlock(void); 153 154 #define _ATEXIT_LOCK() do { \ 155 if (__isthreaded) \ 156 _thread_atexit_lock(); \ 157 } while (0) 158 #define _ATEXIT_UNLOCK() do { \ 159 if (__isthreaded) \ 160 _thread_atexit_unlock();\ 161 } while (0) 162 163 void _thread_arc4_lock(void); 164 void _thread_arc4_unlock(void); 165 166 #define _ARC4_LOCK() do { \ 167 if (__isthreaded) \ 168 _thread_arc4_lock(); \ 169 } while (0) 170 #define _ARC4_UNLOCK() do { \ 171 if (__isthreaded) \ 172 _thread_arc4_unlock();\ 173 } while (0) 174 175 #endif /* _THREAD_PRIVATE_H_ */ 176