1 /* $OpenBSD: thread_private.h,v 1.15 2003/01/28 04:58:00 marc Exp $ */ 2 3 #ifndef _THREAD_PRIVATE_H_ 4 #define _THREAD_PRIVATE_H_ 5 6 #include <pthread.h> 7 8 /* 9 * This variable is initially 0 when there is exactly one thread. 10 * It should never decrease. 11 */ 12 extern int __isthreaded; 13 14 /* 15 * Weak symbols are used in libc so that the thread library can 16 * efficiently wrap libc functions. 17 * 18 * Use WEAK_NAME(n) to get a libc-private name for n (_weak_n), 19 * WEAK_ALIAS(n) to generate the weak symbol n pointing to _weak_n, 20 * WEAK_PROTOTYPE(n) to generate a prototype for _weak_n (based on n). 21 */ 22 #define WEAK_NAME(name) __CONCAT(_weak_,name) 23 #define WEAK_ALIAS(name) __weak_alias(name, WEAK_NAME(name)) 24 #ifdef __GNUC__ 25 #define WEAK_PROTOTYPE(name) __typeof__(name) WEAK_NAME(name) 26 #else 27 #define WEAK_PROTOTYPE(name) /* typeof() only in gcc */ 28 #endif 29 30 /* 31 * These macros help in making persistent storage thread-specific. 32 * Libc makes extensive use of private static data structures 33 * that hold state across function invocation, and these macros 34 * are no-ops when running single-threaded. 35 * 36 * Linking against the user-thread library causes these macros to 37 * allocate storage on a per-thread basis. 38 */ 39 40 #define __THREAD_MUTEX_NAME(name) __CONCAT(_libc_storage_mutex_,name) 41 #define __THREAD_KEY_NAME(name) __CONCAT(_libc_storage_key_,name) 42 43 struct _thread_private_key_struct { 44 pthread_once_t once; 45 void (*cleanfn)(void *); 46 pthread_key_t key; 47 }; 48 49 void _libc_private_storage_lock(pthread_mutex_t *); 50 void _libc_private_storage_unlock(pthread_mutex_t *); 51 void * _libc_private_storage(volatile struct _thread_private_key_struct *, 52 void *, size_t, void *); 53 54 /* Declare a module mutex. */ 55 #define _THREAD_PRIVATE_MUTEX(name) \ 56 static pthread_mutex_t __THREAD_MUTEX_NAME(name) = \ 57 PTHREAD_MUTEX_INITIALIZER 58 59 /* Lock a module mutex against use by any other threads. */ 60 #define _THREAD_PRIVATE_MUTEX_LOCK(name) \ 61 _libc_private_storage_lock(&__THREAD_MUTEX_NAME(name)) 62 63 /* Unlock a module mutex. */ 64 #define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \ 65 _libc_private_storage_unlock(&__THREAD_MUTEX_NAME(name)) 66 67 /* Declare a thread-private storage key. */ 68 #define _THREAD_PRIVATE_KEY(name) \ 69 static volatile struct _thread_private_key_struct \ 70 __THREAD_KEY_NAME(name) = { \ 71 PTHREAD_ONCE_INIT, \ 72 0 \ 73 } 74 75 /* 76 * In threaded mode, return a pointer to thread-private memory of 77 * the same size as, and (initially) with the same contents as 'storage'. If 78 * an error occurs, the 'error' parameter is returned. 79 * In single-threaded mode, no storage is allocated. Instead, a pointer 80 * to storage is always returned. 81 * The 'cleanfn' function of the key structure is called to free the storage. 82 * If 'cleanfn' is NULL, then free() is used. This hook can be useful for 83 * getting rid of memory leaks. 84 */ 85 #define _THREAD_PRIVATE(keyname, storage, error) \ 86 _libc_private_storage(&__THREAD_KEY_NAME(keyname), \ 87 &(storage), sizeof (storage), error) 88 89 /* 90 * Keys used to access the per thread instances of resolver global data. 91 * These are not static as they are referenced in several places. 92 */ 93 extern volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res); 94 #ifdef INET6 95 extern volatile struct _thread_private_key_struct __THREAD_KEY_NAME(_res_ext); 96 #endif 97 98 /* 99 * File descriptor locking definitions. 100 */ 101 #define FD_READ 0x1 102 #define FD_WRITE 0x2 103 #define FD_RDWR (FD_READ | FD_WRITE) 104 105 #define _FD_LOCK(_fd,_type,_ts) \ 106 _thread_fd_lock(_fd, _type, _ts, __FILE__, __LINE__) 107 #define _FD_UNLOCK(_fd,_type) \ 108 _thread_fd_unlock(_fd, _type, __FILE__, __LINE__) 109 110 int _thread_fd_lock(int, int, struct timespec *, const char *, int); 111 void _thread_fd_unlock(int, int, const char *, int); 112 113 /* 114 * malloc lock/unlock definitions 115 */ 116 # define _MALLOC_LOCK() do { \ 117 if (__isthreaded) \ 118 _thread_malloc_lock(); \ 119 } while (0) 120 # define _MALLOC_UNLOCK() do { \ 121 if (__isthreaded) \ 122 _thread_malloc_unlock();\ 123 } while (0) 124 # define _MALLOC_LOCK_INIT()do { \ 125 if (__isthreaded) \ 126 _thread_malloc_init();\ 127 } while (0) 128 129 130 void _thread_malloc_init(void); 131 void _thread_malloc_lock(void); 132 void _thread_malloc_unlock(void); 133 134 #endif /* _THREAD_PRIVATE_H_ */ 135