| The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [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_ */ |