xref: /freebsd/lib/libc/gen/_pthread_stubs.c (revision f0adf7f5cdd241db2f2c817683191a6ef64a4e95)
1 /*
2  * Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 #include <signal.h>
31 #include <pthread.h>
32 
33 #include "libc_private.h"
34 
35 /*
36  * Weak symbols: All libc internal usage of these functions should
37  * use the weak symbol versions (_pthread_XXX).  If libpthread is
38  * linked, it will override these functions with (non-weak) routines.
39  * The _pthread_XXX functions are provided solely for internal libc
40  * usage to avoid unwanted cancellation points and to differentiate
41  * between application locks and libc locks (threads holding the
42  * latter can't be allowed to exit/terminate).
43  */
44 
45 /* Define a null pthread structure just to satisfy _pthread_self. */
46 struct pthread {
47 };
48 
49 static struct pthread	main_thread;
50 
51 static int		stub_main(void);
52 static void 		*stub_null(void);
53 static struct pthread	*stub_self(void);
54 static int		stub_zero(void);
55 
56 #define	PJT_DUAL_ENTRY(entry)	\
57 	(pthread_func_t)entry, (pthread_func_t)entry
58 
59 pthread_func_entry_t __thr_jtable[PJT_MAX] = {
60 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_COND_BROADCAST */
61 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_COND_DESTROY */
62 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_COND_INIT */
63 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_COND_SIGNAL */
64 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_COND_WAIT */
65 	{PJT_DUAL_ENTRY(stub_null)},	/* PJT_GETSPECIFIC */
66 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_KEY_CREATE */
67 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_KEY_DELETE */
68 	{PJT_DUAL_ENTRY(stub_main)},	/* PJT_MAIN_NP */
69 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_MUTEX_DESTROY */
70 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_MUTEX_INIT */
71 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_MUTEX_LOCK */
72 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_MUTEX_TRYLOCK */
73 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_MUTEX_UNLOCK */
74 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_MUTEXATTR_DESTROY */
75 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_MUTEXATTR_INIT */
76 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_MUTEXATTR_SETTYPE */
77 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_ONCE */
78 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_RWLOCK_DESTROY */
79 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_RWLOCK_INIT */
80 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_RWLOCK_RDLOCK */
81 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_RWLOCK_TRYRDLOCK */
82 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_RWLOCK_TRYWRLOCK */
83 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_RWLOCK_UNLOCK */
84 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_RWLOCK_WRLOCK */
85 	{PJT_DUAL_ENTRY(stub_self)},	/* PJT_SELF */
86 	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_SETSPECIFIC */
87 	{PJT_DUAL_ENTRY(stub_zero)}	/* PJT_SIGMASK */
88 };
89 
90 /*
91  * Weak aliases for exported (pthread_*) and internal (_pthread_*) routines.
92  */
93 #define	WEAK_REF(sym, alias)	__weak_reference(sym, alias)
94 
95 #define	FUNC_TYPE(name)		__CONCAT(name, _func_t)
96 #define	FUNC_INT(name)		__CONCAT(name, _int)
97 #define	FUNC_EXP(name)		__CONCAT(name, _exp)
98 
99 #define	STUB_FUNC(name, idx, ret)				\
100 	static ret FUNC_EXP(name)(void) __unused;		\
101 	static ret FUNC_INT(name)(void) __unused;		\
102 	WEAK_REF(FUNC_EXP(name), name);				\
103 	WEAK_REF(FUNC_INT(name), __CONCAT(_, name));		\
104 	typedef ret (*FUNC_TYPE(name))(void);			\
105 	static ret FUNC_EXP(name)(void)				\
106 	{							\
107 		FUNC_TYPE(name) func;				\
108 		func = (FUNC_TYPE(name))__thr_jtable[idx][0];	\
109 		return (func());				\
110 	}							\
111 	static ret FUNC_INT(name)(void)				\
112 	{							\
113 		FUNC_TYPE(name) func;				\
114 		func = (FUNC_TYPE(name))__thr_jtable[idx][1];	\
115 		return (func());				\
116 	}
117 
118 #define	STUB_FUNC1(name, idx, ret, p0_type)			\
119 	static ret FUNC_EXP(name)(p0_type) __unused;		\
120 	static ret FUNC_INT(name)(p0_type) __unused;		\
121 	WEAK_REF(FUNC_EXP(name), name);				\
122 	WEAK_REF(FUNC_INT(name), __CONCAT(_, name));		\
123 	typedef ret (*FUNC_TYPE(name))(p0_type);		\
124 	static ret FUNC_EXP(name)(p0_type p0)			\
125 	{							\
126 		FUNC_TYPE(name) func;				\
127 		func = (FUNC_TYPE(name))__thr_jtable[idx][0];	\
128 		return (func(p0));				\
129 	}							\
130 	static ret FUNC_INT(name)(p0_type p0)			\
131 	{							\
132 		FUNC_TYPE(name) func;				\
133 		func = (FUNC_TYPE(name))__thr_jtable[idx][1];	\
134 		return (func(p0));				\
135 	}
136 
137 #define	STUB_FUNC2(name, idx, ret, p0_type, p1_type)		\
138 	static ret FUNC_EXP(name)(p0_type, p1_type) __unused;	\
139 	static ret FUNC_INT(name)(p0_type, p1_type) __unused;	\
140 	WEAK_REF(FUNC_EXP(name), name);				\
141 	WEAK_REF(FUNC_INT(name), __CONCAT(_, name));		\
142 	typedef ret (*FUNC_TYPE(name))(p0_type, p1_type);	\
143 	static ret FUNC_EXP(name)(p0_type p0, p1_type p1)	\
144 	{							\
145 		FUNC_TYPE(name) func;				\
146 		func = (FUNC_TYPE(name))__thr_jtable[idx][0];	\
147 		return (func(p0, p1));				\
148 	}							\
149 	static ret FUNC_INT(name)(p0_type p0, p1_type p1)	\
150 	{							\
151 		FUNC_TYPE(name) func;				\
152 		func = (FUNC_TYPE(name))__thr_jtable[idx][1];	\
153 		return (func(p0, p1));				\
154 	}
155 
156 #define	STUB_FUNC3(name, idx, ret, p0_type, p1_type, p2_type)	\
157 	static ret FUNC_EXP(name)(p0_type, p1_type, p2_type) __unused; \
158 	static ret FUNC_INT(name)(p0_type, p1_type, p2_type) __unused; \
159 	WEAK_REF(FUNC_EXP(name), name);				\
160 	WEAK_REF(FUNC_INT(name), __CONCAT(_, name));		\
161 	typedef ret (*FUNC_TYPE(name))(p0_type, p1_type, p2_type); \
162 	static ret FUNC_EXP(name)(p0_type p0, p1_type p1, p2_type p2) \
163 	{							\
164 		FUNC_TYPE(name) func;				\
165 		func = (FUNC_TYPE(name))__thr_jtable[idx][0];	\
166 		return (func(p0, p1, p2));			\
167 	}							\
168 	static ret FUNC_INT(name)(p0_type p0, p1_type p1, p2_type p2) \
169 	{							\
170 		FUNC_TYPE(name) func;				\
171 		func = (FUNC_TYPE(name))__thr_jtable[idx][1];	\
172 		return (func(p0, p1, p2));			\
173 	}
174 
175 STUB_FUNC1(pthread_cond_broadcast, PJT_COND_BROADCAST, int, void *)
176 STUB_FUNC1(pthread_cond_destroy, PJT_COND_DESTROY, int, void *)
177 STUB_FUNC2(pthread_cond_init,	PJT_COND_INIT, int, void *, void *)
178 STUB_FUNC1(pthread_cond_signal,	PJT_COND_SIGNAL, int, void *)
179 STUB_FUNC1(pthread_cond_wait,	PJT_COND_WAIT, int, void *)
180 STUB_FUNC1(pthread_getspecific,	PJT_GETSPECIFIC, void *, pthread_key_t)
181 STUB_FUNC2(pthread_key_create,	PJT_KEY_CREATE, int, void *, void *)
182 STUB_FUNC1(pthread_key_delete,	PJT_KEY_DELETE, int, pthread_key_t)
183 STUB_FUNC(pthread_main_np,	PJT_MAIN_NP, int)
184 STUB_FUNC1(pthread_mutex_destroy, PJT_MUTEX_DESTROY, int, void *)
185 STUB_FUNC2(pthread_mutex_init,	PJT_MUTEX_INIT, int, void *, void *)
186 STUB_FUNC1(pthread_mutex_lock,	PJT_MUTEX_LOCK, int, void *)
187 STUB_FUNC1(pthread_mutex_trylock, PJT_MUTEX_TRYLOCK, int, void *)
188 STUB_FUNC1(pthread_mutex_unlock, PJT_MUTEX_UNLOCK, int, void *)
189 STUB_FUNC1(pthread_mutexattr_destroy, PJT_MUTEXATTR_DESTROY, int, void *)
190 STUB_FUNC1(pthread_mutexattr_init, PJT_MUTEXATTR_INIT, int, void *)
191 STUB_FUNC1(pthread_mutexattr_settype, PJT_MUTEXATTR_SETTYPE, int, void *)
192 STUB_FUNC2(pthread_once, 	PJT_ONCE, int, void *, void *)
193 STUB_FUNC1(pthread_rwlock_destroy, PJT_RWLOCK_DESTROY, int, void *)
194 STUB_FUNC2(pthread_rwlock_init,	PJT_RWLOCK_INIT, int, void *, void *)
195 STUB_FUNC1(pthread_rwlock_rdlock, PJT_RWLOCK_RDLOCK, int, void *)
196 STUB_FUNC1(pthread_rwlock_tryrdlock, PJT_RWLOCK_TRYRDLOCK, int, void *)
197 STUB_FUNC1(pthread_rwlock_trywrlock, PJT_RWLOCK_TRYWRLOCK, int, void *)
198 STUB_FUNC1(pthread_rwlock_unlock, PJT_RWLOCK_UNLOCK, int, void *)
199 STUB_FUNC1(pthread_rwlock_wrlock, PJT_RWLOCK_WRLOCK, int, void *)
200 STUB_FUNC(pthread_self,		PJT_SELF, pthread_t)
201 STUB_FUNC2(pthread_setspecific, PJT_SETSPECIFIC, int, pthread_key_t, void *)
202 STUB_FUNC3(pthread_sigmask, PJT_SIGMASK, int, int, void *, void *)
203 
204 static int
205 stub_zero(void)
206 {
207 	return (0);
208 }
209 
210 static void *
211 stub_null(void)
212 {
213 	return (NULL);
214 }
215 
216 static struct pthread *
217 stub_self(void)
218 {
219 	return (&main_thread);
220 }
221 
222 static int
223 stub_main(void)
224 {
225 	return (-1);
226 }
227