The Android Open Source Project | a27d2ba | 2008-10-21 07:00:00 -0700 | [diff] [blame^] | 1 | /* $OpenBSD: thread_private.h,v 1.18 2006/02/22 07:16:31 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 | #include <pthread.h> |
| 9 | |
| 10 | /* |
| 11 | * This file defines the thread library interface to libc. Thread |
| 12 | * libraries must implement the functions described here for proper |
| 13 | * inter-operation with libc. libc contains weak versions of the |
| 14 | * described functions for operation in a non-threaded environment. |
| 15 | */ |
| 16 | |
| 17 | /* |
| 18 | * This variable is 0 until a second thread is created. |
| 19 | */ |
| 20 | extern int __isthreaded; |
| 21 | |
| 22 | /* |
| 23 | * Weak symbols are used in libc so that the thread library can |
| 24 | * efficiently wrap libc functions. |
| 25 | * |
| 26 | * Use WEAK_NAME(n) to get a libc-private name for n (_weak_n), |
| 27 | * WEAK_ALIAS(n) to generate the weak symbol n pointing to _weak_n, |
| 28 | * WEAK_PROTOTYPE(n) to generate a prototype for _weak_n (based on n). |
| 29 | */ |
| 30 | #define WEAK_NAME(name) __CONCAT(_weak_,name) |
| 31 | #define WEAK_ALIAS(name) __weak_alias(name, WEAK_NAME(name)) |
| 32 | #ifdef __GNUC__ |
| 33 | #define WEAK_PROTOTYPE(name) __typeof__(name) WEAK_NAME(name) |
| 34 | #else |
| 35 | #define WEAK_PROTOTYPE(name) /* typeof() only in gcc */ |
| 36 | #endif |
| 37 | |
| 38 | /* |
| 39 | * helper macro to make unique names in the thread namespace |
| 40 | */ |
| 41 | #define __THREAD_NAME(name) __CONCAT(_thread_tagname_,name) |
| 42 | |
| 43 | struct __thread_private_tag_t { |
| 44 | pthread_mutex_t _private_lock; |
| 45 | pthread_key_t _private_key; |
| 46 | }; |
| 47 | |
| 48 | #define _THREAD_PRIVATE_MUTEX(name) \ |
| 49 | static struct __thread_private_tag_t __THREAD_NAME(name) = { PTHREAD_MUTEX_INITIALIZER, -1 } |
| 50 | #define _THREAD_PRIVATE_MUTEX_LOCK(name) \ |
| 51 | pthread_mutex_lock( &__THREAD_NAME(name)._private_lock ) |
| 52 | #define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \ |
| 53 | pthread_mutex_unlock( &__THREAD_NAME(name)._private_lock ) |
| 54 | |
| 55 | #define _THREAD_PRIVATE_KEY(name) \ |
| 56 | static struct __thread_private_tag_t __THREAD_NAME(name) = { PTHREAD_MUTEX_INITIALIZER, -1 } |
| 57 | |
| 58 | extern void* __bionic_thread_private_storage( struct __thread_private_tag_t* ptag, void* storage, size_t objsize, void* error ); |
| 59 | |
| 60 | #define _THREAD_PRIVATE(name, storage, error) \ |
| 61 | __bionic_thread_private_storage( &__THREAD_NAME(name), &(storage),sizeof(storage), error) |
| 62 | |
| 63 | #if 0 |
| 64 | /* |
| 65 | * helper functions that exist as (weak) null functions in libc and |
| 66 | * (strong) functions in the thread library. These functions: |
| 67 | * |
| 68 | * _thread_tag_lock: |
| 69 | * lock the mutex associated with the given tag. If the given |
| 70 | * tag is NULL a tag is first allocated. |
| 71 | * |
| 72 | * _thread_tag_unlock: |
| 73 | * unlock the mutex associated with the given tag. If the given |
| 74 | * tag is NULL a tag is first allocated. |
| 75 | * |
| 76 | * _thread_tag_storage: |
| 77 | * return a pointer to per thread instance of data associated |
| 78 | * with the given tag. If the given tag is NULL a tag is first |
| 79 | * allocated. |
| 80 | */ |
| 81 | void _thread_tag_lock(void **); |
| 82 | void _thread_tag_unlock(void **); |
| 83 | void *_thread_tag_storage(void **, void *, size_t, void *); |
| 84 | |
| 85 | /* |
| 86 | * Macros used in libc to access thread mutex, keys, and per thread storage. |
| 87 | * _THREAD_PRIVATE_KEY and _THREAD_PRIVATE_MUTEX are different macros for |
| 88 | * historical reasons. They do the same thing, define a static variable |
| 89 | * keyed by 'name' that identifies a mutex and a key to identify per thread |
| 90 | * data. |
| 91 | */ |
| 92 | #define _THREAD_PRIVATE_KEY(name) \ |
| 93 | static void *__THREAD_NAME(name) |
| 94 | #define _THREAD_PRIVATE_MUTEX(name) \ |
| 95 | static void *__THREAD_NAME(name) |
| 96 | #define _THREAD_PRIVATE_MUTEX_LOCK(name) \ |
| 97 | _thread_tag_lock(&(__THREAD_NAME(name))) |
| 98 | #define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \ |
| 99 | _thread_tag_unlock(&(__THREAD_NAME(name))) |
| 100 | #define _THREAD_PRIVATE(keyname, storage, error) \ |
| 101 | _thread_tag_storage(&(__THREAD_NAME(keyname)), &(storage), \ |
| 102 | sizeof (storage), error) |
| 103 | /* |
| 104 | * Resolver code is special cased in that it uses global keys. |
| 105 | */ |
| 106 | extern void *__THREAD_NAME(_res); |
| 107 | extern void *__THREAD_NAME(_res_ext); |
| 108 | extern void *__THREAD_NAME(serv_mutex); |
| 109 | #endif |
| 110 | |
| 111 | /* |
| 112 | * File descriptor locking definitions. |
| 113 | */ |
| 114 | #define FD_READ 0x1 |
| 115 | #define FD_WRITE 0x2 |
| 116 | #define FD_RDWR (FD_READ | FD_WRITE) |
| 117 | |
| 118 | struct timespec; |
| 119 | int _thread_fd_lock(int, int, struct timespec *); |
| 120 | void _thread_fd_unlock(int, int); |
| 121 | |
| 122 | /* |
| 123 | * Macros are used in libc code for historical (debug) reasons. |
| 124 | * Define them here. |
| 125 | */ |
| 126 | #define _FD_LOCK(_fd,_type,_ts) _thread_fd_lock(_fd, _type, _ts) |
| 127 | #define _FD_UNLOCK(_fd,_type) _thread_fd_unlock(_fd, _type) |
| 128 | |
| 129 | |
| 130 | /* |
| 131 | * malloc lock/unlock prototypes and definitions |
| 132 | */ |
| 133 | void _thread_malloc_init(void); |
| 134 | void _thread_malloc_lock(void); |
| 135 | void _thread_malloc_unlock(void); |
| 136 | |
| 137 | #define _MALLOC_LOCK() do { \ |
| 138 | if (__isthreaded) \ |
| 139 | _thread_malloc_lock(); \ |
| 140 | } while (0) |
| 141 | #define _MALLOC_UNLOCK() do { \ |
| 142 | if (__isthreaded) \ |
| 143 | _thread_malloc_unlock();\ |
| 144 | } while (0) |
| 145 | #define _MALLOC_LOCK_INIT() do { \ |
| 146 | if (__isthreaded) \ |
| 147 | _thread_malloc_init();\ |
| 148 | } while (0) |
| 149 | |
| 150 | void _thread_atexit_lock(void); |
| 151 | void _thread_atexit_unlock(void); |
| 152 | |
| 153 | #define _ATEXIT_LOCK() do { \ |
| 154 | if (__isthreaded) \ |
| 155 | _thread_atexit_lock(); \ |
| 156 | } while (0) |
| 157 | #define _ATEXIT_UNLOCK() do { \ |
| 158 | if (__isthreaded) \ |
| 159 | _thread_atexit_unlock();\ |
| 160 | } while (0) |
| 161 | |
| 162 | #endif /* _THREAD_PRIVATE_H_ */ |