Home | History | Annotate | Download | only in private
      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 (at) 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_ */
    163