xref: /openbsd-src/lib/libc/include/thread_private.h (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /* $OpenBSD: thread_private.h,v 1.7 2001/08/12 12:03:01 heko 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  * If the symbol _NO_WEAK_ALIASES is defined, then symbols will be
23  */
24 
25 #ifdef _NO_WEAK_ALIASES
26 #ifdef _THREAD_SAFE
27 #define WEAK_NAME(name)			__CONCAT(_weak,name)
28 #else
29 #define WEAK_NAME(name)			name
30 #endif
31 #define WEAK_ALIAS(name)		/* unavailable */
32 #define WEAK_PROTOTYPE(name)		/* unnecessary */
33 #else /* !_NO_WEAK_ALIASES */
34 #define WEAK_NAME(name)			__CONCAT(_weak_,name)
35 #define WEAK_ALIAS(name)		__weak_alias(name, WEAK_NAME(name))
36 #ifdef __GNUC__
37 #define WEAK_PROTOTYPE(name)		__typeof__(name) WEAK_NAME(name)
38 #else
39 #define WEAK_PROTOTYPE(name)		/* typeof() only in gcc */
40 #endif
41 #endif /* !_NO_WEAK_ALIASES */
42 
43 /*
44  * These macros help in making persistent storage thread-specific.
45  * Libc makes extensive use of private static data structures
46  * that hold state across function invocation, and these macros
47  * are no-ops when running single-threaded.
48  *
49  * Linking against the user-thread library causes these macros to
50  * allocate storage on a per-thread basis.
51  */
52 
53 #define __THREAD_MUTEX_NAME(name)	__CONCAT(_libc_storage_mutex_,name)
54 #define __THREAD_KEY_NAME(name)		__CONCAT(_libc_storage_key_,name)
55 
56 struct _thread_private_key_struct {
57 	pthread_once_t		once;
58 	void			(*cleanfn)__P((void *));
59 	pthread_key_t		key;
60 };
61 
62 void	_libc_private_storage_lock(pthread_mutex_t *);
63 void	_libc_private_storage_unlock(pthread_mutex_t *);
64 void *	_libc_private_storage(volatile struct _thread_private_key_struct *,
65 	void *, size_t, void *);
66 
67 /* Declare a module mutex. */
68 #define _THREAD_PRIVATE_MUTEX(name)					\
69 	static pthread_mutex_t __THREAD_MUTEX_NAME(name) = 		\
70 		PTHREAD_MUTEX_INITIALIZER
71 
72 /* Lock a module mutex against use by any other threads. */
73 #define _THREAD_PRIVATE_MUTEX_LOCK(name) 				\
74 	_libc_private_storage_lock(&__THREAD_MUTEX_NAME(name))
75 
76 /* Unlock a module mutex. */
77 #define _THREAD_PRIVATE_MUTEX_UNLOCK(name) 				\
78 	_libc_private_storage_unlock(&__THREAD_MUTEX_NAME(name))
79 
80 /* Declare a thread-private storage key. */
81 #define _THREAD_PRIVATE_KEY(name)					\
82 	static volatile struct _thread_private_key_struct		\
83 	__THREAD_KEY_NAME(name) = {					\
84 		PTHREAD_ONCE_INIT, 					\
85 		0							\
86 	}
87 
88 /*
89  * In threaded mode, return a pointer to thread-private memory of
90  * the same size as, and (initially) with the same contents as 'storage'. If
91  * an error occurs, the 'error' parameter is returned.
92  * In single-threaded mode, no storage is allocated. Instead, a pointer
93  * to storage is always returned.
94  * The 'cleanfn' function of the key structure is called to free the storage.
95  * If 'cleanfn' is NULL, then free() is used. This hook can be useful for
96  * getting rid of memory leaks.
97  */
98 #define _THREAD_PRIVATE(keyname, storage, error) 			\
99 	_libc_private_storage(&__THREAD_KEY_NAME(keyname),		\
100 		&(storage), sizeof (storage), error)
101 
102 /*
103  * Macros for locking and unlocking FILEs. These test if the
104  * process is threaded to avoid locking when not required.
105  */
106 #ifdef	_FLOCK_DEBUG
107 #define FLOCKFILE(fp)		_flockfile_debug(fp, __FILE__, __LINE__)
108 #else
109 #define FLOCKFILE(fp)		flockfile(fp)
110 #endif
111 #define	FUNLOCKFILE(fp)		funlockfile(fp)
112 
113 /*
114  * File descriptor locking definitions.
115  */
116 #define FD_READ		    0x1
117 #define FD_WRITE	    0x2
118 #define FD_RDWR		    (FD_READ | FD_WRITE)
119 
120 #ifdef	_LOCK_DEBUG
121 #define _FD_LOCK(_fd,_type,_ts)		_thread_fd_lock_debug(_fd, _type, \
122 						_ts, __FILE__, __LINE__)
123 #define _FD_UNLOCK(_fd,_type)		_thread_fd_unlock_debug(_fd, _type, \
124 						__FILE__, __LINE__)
125 #else
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 #endif
129 
130 int	_thread_fd_lock(int, int, struct timespec *);
131 int	_thread_fd_lock_debug(int, int, struct timespec *, const char *, int);
132 void	_thread_fd_unlock(int, int);
133 void	_thread_fd_unlock_debug(int, int, const char *, int);
134 
135 #endif /* _THREAD_PRIVATE_H_ */
136