xref: /openbsd-src/lib/libc/include/thread_private.h (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
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