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 * $FreeBSD: src/lib/libc/gen/_pthread_stubs.c,v 1.5 2001/06/11 23:18:22 iedowse Exp $
27 */
28
29 #include <sys/cdefs.h>
30 #include "namespace.h"
31 /* following should not be included in namespace here */
32 #undef pthread_kill
33 #undef pthread_sigmask
34 #include <errno.h>
35 #include <stdlib.h>
36 #include <signal.h>
37 #include "un-namespace.h"
38 #include <pthread.h>
39
40 /*
41 * Weak symbols: All libc internal usage of these functions should
42 * use the weak symbol versions (_pthread_XXX). If libpthread is
43 * linked, it will override these functions with (non-weak) routines.
44 * The _pthread_XXX functions are provided solely for internal libc
45 * usage to avoid unwanted cancellation points and to differentiate
46 * between application locks and libc locks (threads holding the
47 * latter can't be allowed to exit/terminate).
48 */
49
50 #define WRlc(f, n) \
51 __weak_reference_asm(f, _ ## n);
52 #define WR(f, n) \
53 __weak_reference_asm(f, _ ## n); \
54 __weak_reference_asm(f, n)
55
56 /* XXX this needs something more clever, should not some of these return errors? */
57 WR(__atfork, pthread_atfork);
58 WR(stub_zero, pthread_attr_destroy);
59 WR(stub_zero, pthread_attr_get_np);
60 WR(stub_zero, pthread_attr_getaffinity_np);
61 WR(stub_zero, pthread_attr_getdetachstate);
62 WR(stub_zero, pthread_attr_getguardsize);
63 WR(stub_zero, pthread_attr_getinheritsched);
64 WR(stub_zero, pthread_attr_getschedparam);
65 WR(stub_zero, pthread_attr_getschedpolicy);
66 WR(stub_zero, pthread_attr_getscope);
67 WR(stub_zero, pthread_attr_getstack);
68 WR(stub_zero, pthread_attr_getstackaddr);
69 WR(stub_zero, pthread_attr_getstacksize);
70 WR(stub_zero, pthread_attr_init);
71 WR(stub_zero, pthread_attr_setaffinity_np);
72 WR(stub_zero, pthread_attr_setcreatesuspend_np);
73 WR(stub_zero, pthread_attr_setdetachstate);
74 WR(stub_zero, pthread_attr_setguardsize);
75 WR(stub_zero, pthread_attr_setinheritsched);
76 WR(stub_zero, pthread_attr_setschedparam);
77 WR(stub_zero, pthread_attr_setschedpolicy);
78 WR(stub_zero, pthread_attr_setscope);
79 WR(stub_zero, pthread_attr_setstack);
80 WR(stub_zero, pthread_attr_setstackaddr);
81 WR(stub_zero, pthread_attr_setstacksize);
82 WR(stub_zero, pthread_barrier_destroy);
83 WR(stub_zero, pthread_barrier_init);
84 WR(stub_zero, pthread_barrier_wait);
85 WR(stub_zero, pthread_barrierattr_destroy);
86 WR(stub_zero, pthread_barrierattr_getpshared);
87 WR(stub_zero, pthread_barrierattr_init);
88 WR(stub_zero, pthread_barrierattr_setpshared);
89 WRlc(stub_zero, pthread_cancel);
90 WR(stub_zero, pthread_cleanup_pop);
91 WR(stub_zero, pthread_cleanup_push);
92 WR(stub_zero, pthread_cond_broadcast);
93 WR(stub_zero, pthread_cond_destroy);
94 WR(stub_zero, pthread_cond_init);
95 WR(stub_zero, pthread_cond_signal);
96 WR(stub_zero, pthread_cond_timedwait);
97 WR(stub_zero, pthread_cond_wait);
98 WR(stub_zero, pthread_condattr_destroy);
99 WR(stub_zero, pthread_condattr_getclock);
100 WR(stub_zero, pthread_condattr_getpshared);
101 WR(stub_zero, pthread_condattr_init);
102 WR(stub_zero, pthread_condattr_setclock);
103 WR(stub_zero, pthread_condattr_setpshared);
104 WR(stub_zero, pthread_detach);
105 WR(stub_equal, pthread_equal);
106 WR(stub_exit, pthread_exit);
107 WR(stub_zero, pthread_getaffinity_np);
108 WR(stub_zero, pthread_getattr_np);
109 WR(stub_zero, pthread_getconcurrency);
110 WR(stub_zero, pthread_getcpuclockid);
111 WR(stub_zero, pthread_getprio);
112 WR(stub_zero, pthread_getschedparam);
113 WR(stub_null, pthread_getspecific);
114 WR(stub_zero, pthread_getthreadid_np);
115 WR(stub_empty, pthread_init_early);
116 WR(stub_isthreaded, pthread_is_threaded_np);
117 WR(stub_zero, pthread_join);
118 WR(stub_zero, pthread_key_create);
119 WR(stub_zero, pthread_key_delete);
120 WR(stub_zero, pthread_kill);
121 WR(stub_main, pthread_main_np);
122 WR(stub_zero, pthread_multi_np);
123 WR(stub_zero, pthread_mutex_destroy);
124 WR(stub_zero, pthread_mutex_getprioceiling);
125 WR(stub_zero, pthread_mutex_init);
126 WR(stub_zero, pthread_mutex_lock);
127 WR(stub_zero, pthread_mutex_setprioceiling);
128 WR(stub_zero, pthread_mutex_timedlock);
129 WR(stub_zero, pthread_mutex_trylock);
130 WR(stub_zero, pthread_mutex_unlock);
131 WR(stub_zero, pthread_mutexattr_destroy);
132 WR(stub_zero, pthread_mutexattr_getkind_np);
133 WR(stub_zero, pthread_mutexattr_getprioceiling);
134 WR(stub_zero, pthread_mutexattr_getprotocol);
135 WR(stub_zero, pthread_mutexattr_getpshared);
136 WR(stub_zero, pthread_mutexattr_gettype);
137 WR(stub_zero, pthread_mutexattr_init);
138 WR(stub_zero, pthread_mutexattr_setkind_np);
139 WR(stub_zero, pthread_mutexattr_setprioceiling);
140 WR(stub_zero, pthread_mutexattr_setprotocol);
141 WR(stub_zero, pthread_mutexattr_setpshared);
142 WR(stub_zero, pthread_mutexattr_settype);
143 WR(stub_once, pthread_once);
144 WR(stub_zero, pthread_resume_all_np);
145 WR(stub_zero, pthread_resume_np);
146 WR(stub_zero, pthread_rwlock_destroy);
147 WR(stub_zero, pthread_rwlock_init);
148 WR(stub_zero, pthread_rwlock_rdlock);
149 WR(stub_zero, pthread_rwlock_timedrdlock);
150 WR(stub_zero, pthread_rwlock_timedwrlock);
151 WR(stub_zero, pthread_rwlock_tryrdlock);
152 WR(stub_zero, pthread_rwlock_trywrlock);
153 WR(stub_zero, pthread_rwlock_unlock);
154 WR(stub_zero, pthread_rwlock_wrlock);
155 WR(stub_zero, pthread_rwlockattr_destroy);
156 WR(stub_zero, pthread_rwlockattr_getpshared);
157 WR(stub_zero, pthread_rwlockattr_init);
158 WR(stub_zero, pthread_rwlockattr_setpshared);
159 WR(stub_self, pthread_self);
160 WR(stub_pthread_get_name_np, pthread_get_name_np);
161 WR(stub_pthread_getname_np, pthread_getname_np);
162 WR(stub_zero, pthread_set_name_np);
163 WR(stub_zero, pthread_setname_np);
164 WR(stub_zero, pthread_setaffinity_np);
165 WR(stub_zero, pthread_setcancelstate);
166 WR(stub_zero, pthread_setcanceltype);
167 WR(stub_zero, pthread_setconcurrency);
168 WR(stub_zero, pthread_setprio);
169 WR(stub_zero, pthread_setschedparam);
170 WR(stub_zero, pthread_setspecific);
171 WR(stub_sigmask, pthread_sigmask);
172 WR(stub_zero, pthread_single_np);
173 WR(stub_zero, pthread_spin_destroy);
174 WR(stub_zero, pthread_spin_init);
175 WR(stub_zero, pthread_spin_lock);
176 WR(stub_zero, pthread_spin_trylock);
177 WR(stub_zero, pthread_spin_unlock);
178 WR(stub_zero, pthread_suspend_all_np);
179 WR(stub_zero, pthread_suspend_np);
180 WR(stub_zero, pthread_switch_add_np);
181 WR(stub_zero, pthread_switch_delete_np);
182 WR(stub_zero, pthread_testcancel);
183 WR(stub_zero, pthread_timedjoin_np);
184 WR(stub_zero, pthread_yield);
185 WR(stub_zero, pthread_yield_np);
186 WR(stub_zero, sem_close);
187 WR(stub_zero, sem_destroy);
188 WR(stub_zero, sem_getvalue);
189 WR(stub_zero, sem_init);
190 WR(stub_zero, sem_open);
191 WR(stub_zero, sem_post);
192 WR(stub_zero, sem_trywait);
193 WR(stub_zero, sem_timedwait);
194 WR(stub_zero, sem_unlink);
195 WR(stub_zero, sem_wait);
196
197
198 static int __used
stub_zero(void)199 stub_zero(void)
200 {
201 return (0);
202 }
203
204 static int __used
stub_once(pthread_once_t * o,void (* r)(void))205 stub_once(pthread_once_t *o, void (*r)(void))
206 {
207 if (o->__state != PTHREAD_DONE_INIT) {
208 (*r)();
209 o->__state = PTHREAD_DONE_INIT;
210 }
211
212 return (0);
213 }
214
215 static void * __used
stub_null(void)216 stub_null(void)
217 {
218 return (NULL);
219 }
220
221 static void * __used
stub_self(void)222 stub_self(void)
223 {
224 static struct {} main_thread;
225
226 return (&main_thread);
227 }
228
229 static int __used
stub_main(void)230 stub_main(void)
231 {
232 return (-1);
233 }
234
235 static int __used
stub_equal(pthread_t a,pthread_t b)236 stub_equal(pthread_t a, pthread_t b)
237 {
238 return (a == b);
239 }
240
241 static void __used
stub_empty(void)242 stub_empty(void)
243 {
244 }
245
246 static void __used
stub_exit(void)247 stub_exit(void)
248 {
249 exit(0);
250 }
251
252 static int __used
stub_sigmask(int how,const sigset_t * set,sigset_t * oset)253 stub_sigmask(int how, const sigset_t *set, sigset_t *oset)
254 {
255 if (_sigprocmask(how, set, oset))
256 return (errno);
257 return (0);
258 }
259
260 static void __used
stub_pthread_get_name_np(pthread_t a,char * name,size_t len)261 stub_pthread_get_name_np(pthread_t a, char *name, size_t len)
262 {
263 if (len)
264 name[0] = 0;
265 }
266
267 static int __used
stub_pthread_getname_np(pthread_t a,char * name,size_t len)268 stub_pthread_getname_np(pthread_t a, char *name, size_t len)
269 {
270 if (len)
271 name[0] = 0;
272 return (0);
273 }
274
275 /*
276 * If libpthread is loaded, make sure it is initialised before
277 * other libraries call pthread functions
278 */
279 void _pthread_init(void) __constructor(101);
280 void _pthread_init_early(void);
281 void
_pthread_init(void)282 _pthread_init(void)
283 {
284 _pthread_init_early();
285 }
286
287 extern void (*cb_prepare)(void);
288 extern void (*cb_parent)(void);
289 extern void (*cb_child)(void);
290 extern int __isthreaded;
291
292 static int __used
__atfork(void (* prepare)(void),void (* parent)(void),void (* child)(void))293 __atfork(void (*prepare)(void), void (*parent)(void),
294 void (*child)(void))
295 {
296 if (__isthreaded)
297 return (-1);
298 cb_prepare = prepare;
299 cb_parent = parent;
300 cb_child = child;
301 return (0);
302 }
303
304 static int __used
stub_isthreaded(void)305 stub_isthreaded(void)
306 {
307 return (__isthreaded != 0);
308 }
309