xref: /netbsd-src/lib/libc/thread-stub/thread-stub.c (revision a4ddc2c8fb9af816efe3b1c375a5530aef0e89e9)
1 /*	$NetBSD: thread-stub.c,v 1.23 2013/03/21 16:49:11 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 2003, 2009 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 #if defined(LIBC_SCCS) && !defined(lint)
34 __RCSID("$NetBSD: thread-stub.c,v 1.23 2013/03/21 16:49:11 christos Exp $");
35 #endif /* LIBC_SCCS and not lint */
36 
37 /*
38  * Stubs for thread operations, for use when threads are not used by
39  * the application.  See "reentrant.h" for details.
40  */
41 
42 #ifdef _REENTRANT
43 
44 #define	__LIBC_THREAD_STUBS
45 
46 #include "namespace.h"
47 #include "reentrant.h"
48 
49 #include <errno.h>
50 #include <signal.h>
51 #include <stdlib.h>
52 #include <unistd.h>
53 
54 extern int __isthreaded;
55 
56 #define	DIE()	(void)raise(SIGABRT)
57 
58 #define	CHECK_NOT_THREADED_ALWAYS()	\
59 do {					\
60 	if (__isthreaded)		\
61 		DIE();			\
62 } while (/*CONSTCOND*/0)
63 
64 #if 1
65 #define	CHECK_NOT_THREADED()	CHECK_NOT_THREADED_ALWAYS()
66 #else
67 #define	CHECK_NOT_THREADED()	/* nothing */
68 #endif
69 
70 /* libpthread init */
71 
72 __weak_alias(__libc_thr_init,__libc_thr_init_stub)
73 
74 void
75 __libc_thr_init_stub(void)
76 {
77 
78 	/* nothing, may be overridden by libpthread */
79 }
80 
81 /* mutexes */
82 
83 int __libc_mutex_catchall_stub(mutex_t *);
84 
85 __weak_alias(__libc_mutex_init,__libc_mutex_init_stub)
86 __weak_alias(__libc_mutex_lock,__libc_mutex_catchall_stub)
87 __weak_alias(__libc_mutex_trylock,__libc_mutex_catchall_stub)
88 __weak_alias(__libc_mutex_unlock,__libc_mutex_catchall_stub)
89 __weak_alias(__libc_mutex_destroy,__libc_mutex_catchall_stub)
90 
91 __strong_alias(__libc_mutex_lock_stub,__libc_mutex_catchall_stub)
92 __strong_alias(__libc_mutex_trylock_stub,__libc_mutex_catchall_stub)
93 __strong_alias(__libc_mutex_unlock_stub,__libc_mutex_catchall_stub)
94 __strong_alias(__libc_mutex_destroy_stub,__libc_mutex_catchall_stub)
95 
96 int __libc_mutexattr_catchall_stub(mutexattr_t *);
97 
98 __weak_alias(__libc_mutexattr_init,__libc_mutexattr_catchall_stub)
99 __weak_alias(__libc_mutexattr_destroy,__libc_mutexattr_catchall_stub)
100 __weak_alias(__libc_mutexattr_settype,__libc_mutexattr_settype_stub)
101 
102 __strong_alias(__libc_mutexattr_init_stub,__libc_mutexattr_catchall_stub)
103 __strong_alias(__libc_mutexattr_destroy_stub,__libc_mutexattr_catchall_stub)
104 
105 int
106 __libc_mutex_init_stub(mutex_t *m, const mutexattr_t *a)
107 {
108 	/* LINTED deliberate lack of effect */
109 	(void)m;
110 	/* LINTED deliberate lack of effect */
111 	(void)a;
112 
113 	CHECK_NOT_THREADED();
114 
115 	return (0);
116 }
117 
118 int
119 __libc_mutex_catchall_stub(mutex_t *m)
120 {
121 	/* LINTED deliberate lack of effect */
122 	(void)m;
123 
124 	CHECK_NOT_THREADED();
125 
126 	return (0);
127 }
128 
129 int
130 __libc_mutexattr_settype_stub(mutexattr_t *ma, int type)
131 {
132 	/* LINTED deliberate lack of effect */
133 	(void)ma;
134 	/* LINTED deliberate lack of effect */
135 	(void)type;
136 
137 	return (0);
138 }
139 
140 int
141 __libc_mutexattr_catchall_stub(mutexattr_t *ma)
142 {
143 	/* LINTED deliberate lack of effect */
144 	(void)ma;
145 
146 	CHECK_NOT_THREADED();
147 
148 	return (0);
149 }
150 
151 /* condition variables */
152 
153 int __libc_cond_catchall_stub(cond_t *);
154 
155 __weak_alias(__libc_cond_init,__libc_cond_init_stub)
156 __weak_alias(__libc_cond_signal,__libc_cond_catchall_stub)
157 __weak_alias(__libc_cond_broadcast,__libc_cond_catchall_stub)
158 __weak_alias(__libc_cond_wait,__libc_cond_wait_stub)
159 __weak_alias(__libc_cond_timedwait,__libc_cond_timedwait_stub)
160 __weak_alias(__libc_cond_destroy,__libc_cond_catchall_stub)
161 
162 __strong_alias(__libc_cond_signal_stub,__libc_cond_catchall_stub)
163 __strong_alias(__libc_cond_broadcast_stub,__libc_cond_catchall_stub)
164 __strong_alias(__libc_cond_wait_stub,__libc_cond_catchall_stub)
165 __strong_alias(__libc_cond_destroy_stub,__libc_cond_catchall_stub)
166 
167 int
168 __libc_cond_init_stub(cond_t *c, const condattr_t *a)
169 {
170 	/* LINTED deliberate lack of effect */
171 	(void)c;
172 	/* LINTED deliberate lack of effect */
173 	(void)a;
174 
175 	CHECK_NOT_THREADED();
176 
177 	return (0);
178 }
179 
180 int
181 __libc_cond_wait_stub(cond_t *c, mutex_t *m)
182 {
183 	/* LINTED deliberate lack of effect */
184 	(void)c;
185 	/* LINTED deliberate lack of effect */
186 	(void)m;
187 
188 	CHECK_NOT_THREADED();
189 
190 	return (0);
191 }
192 
193 int
194 __libc_cond_timedwait_stub(cond_t *c, mutex_t *m, const struct timespec *t)
195 {
196 	/* LINTED deliberate lack of effect */
197 	(void)c;
198 	/* LINTED deliberate lack of effect */
199 	(void)m;
200 	/* LINTED deliberate lack of effect */
201 	(void)t;
202 
203 	CHECK_NOT_THREADED();
204 
205 	return (0);
206 }
207 
208 int
209 __libc_cond_catchall_stub(cond_t *c)
210 {
211 	/* LINTED deliberate lack of effect */
212 	(void)c;
213 
214 	CHECK_NOT_THREADED();
215 
216 	return (0);
217 }
218 
219 
220 /* read-write locks */
221 
222 int __libc_rwlock_catchall_stub(rwlock_t *);
223 
224 __weak_alias(__libc_rwlock_init,__libc_rwlock_init_stub)
225 __weak_alias(__libc_rwlock_rdlock,__libc_rwlock_catchall_stub)
226 __weak_alias(__libc_rwlock_wrlock,__libc_rwlock_catchall_stub)
227 __weak_alias(__libc_rwlock_tryrdlock,__libc_rwlock_catchall_stub)
228 __weak_alias(__libc_rwlock_trywrlock,__libc_rwlock_catchall_stub)
229 __weak_alias(__libc_rwlock_unlock,__libc_rwlock_catchall_stub)
230 __weak_alias(__libc_rwlock_destroy,__libc_rwlock_catchall_stub)
231 
232 __strong_alias(__libc_rwlock_rdlock_stub,__libc_rwlock_catchall_stub)
233 __strong_alias(__libc_rwlock_wrlock_stub,__libc_rwlock_catchall_stub)
234 __strong_alias(__libc_rwlock_tryrdlock_stub,__libc_rwlock_catchall_stub)
235 __strong_alias(__libc_rwlock_trywrlock_stub,__libc_rwlock_catchall_stub)
236 __strong_alias(__libc_rwlock_unlock_stub,__libc_rwlock_catchall_stub)
237 __strong_alias(__libc_rwlock_destroy_stub,__libc_rwlock_catchall_stub)
238 
239 
240 int
241 __libc_rwlock_init_stub(rwlock_t *l, const rwlockattr_t *a)
242 {
243 	/* LINTED deliberate lack of effect */
244 	(void)l;
245 	/* LINTED deliberate lack of effect */
246 	(void)a;
247 
248 	CHECK_NOT_THREADED();
249 
250 	return (0);
251 }
252 
253 int
254 __libc_rwlock_catchall_stub(rwlock_t *l)
255 {
256 	/* LINTED deliberate lack of effect */
257 	(void)l;
258 
259 	CHECK_NOT_THREADED();
260 
261 	return (0);
262 }
263 
264 
265 /*
266  * thread-specific data; we need to actually provide a simple TSD
267  * implementation, since some thread-safe libraries want to use it.
268  */
269 
270 #define	TSD_KEYS_MAX	64
271 
272 static struct {
273 	void *tsd_val;
274 	void (*tsd_dtor)(void *);
275 	int tsd_inuse;
276 } __libc_tsd[TSD_KEYS_MAX];
277 static int __libc_tsd_nextkey;
278 
279 __weak_alias(__libc_thr_keycreate,__libc_thr_keycreate_stub)
280 __weak_alias(__libc_thr_setspecific,__libc_thr_setspecific_stub)
281 __weak_alias(__libc_thr_getspecific,__libc_thr_getspecific_stub)
282 __weak_alias(__libc_thr_keydelete,__libc_thr_keydelete_stub)
283 
284 int
285 __libc_thr_keycreate_stub(thread_key_t *k, void (*d)(void *))
286 {
287 	int i;
288 
289 	for (i = __libc_tsd_nextkey; i < TSD_KEYS_MAX; i++) {
290 		if (__libc_tsd[i].tsd_inuse == 0)
291 			goto out;
292 	}
293 
294 	for (i = 0; i < __libc_tsd_nextkey; i++) {
295 		if (__libc_tsd[i].tsd_inuse == 0)
296 			goto out;
297 	}
298 
299 	return (EAGAIN);
300 
301  out:
302 	/*
303 	 * XXX We don't actually do anything with the destructor.  We
304 	 * XXX probably should.
305 	 */
306 	__libc_tsd[i].tsd_inuse = 1;
307 	__libc_tsd_nextkey = (i + i) % TSD_KEYS_MAX;
308 	__libc_tsd[i].tsd_dtor = d;
309 	*k = i;
310 
311 	return (0);
312 }
313 
314 int
315 __libc_thr_setspecific_stub(thread_key_t k, const void *v)
316 {
317 
318 	__libc_tsd[k].tsd_val = __UNCONST(v);
319 
320 	return (0);
321 }
322 
323 void *
324 __libc_thr_getspecific_stub(thread_key_t k)
325 {
326 
327 	return (__libc_tsd[k].tsd_val);
328 }
329 
330 int
331 __libc_thr_keydelete_stub(thread_key_t k)
332 {
333 
334 	/*
335 	 * XXX Do not recycle key; see big comment in libpthread.
336 	 */
337 
338 	__libc_tsd[k].tsd_dtor = NULL;
339 
340 	return (0);
341 }
342 
343 
344 /* misc. */
345 
346 __weak_alias(__libc_thr_once,__libc_thr_once_stub)
347 __weak_alias(__libc_thr_sigsetmask,__libc_thr_sigsetmask_stub)
348 __weak_alias(__libc_thr_self,__libc_thr_self_stub)
349 __weak_alias(__libc_thr_yield,__libc_thr_yield_stub)
350 __weak_alias(__libc_thr_create,__libc_thr_create_stub)
351 __weak_alias(__libc_thr_exit,__libc_thr_exit_stub)
352 __weak_alias(__libc_thr_errno,__libc_thr_errno_stub)
353 __weak_alias(__libc_thr_setcancelstate,__libc_thr_setcancelstate_stub)
354 __weak_alias(__libc_thr_equal,__libc_thr_equal_stub)
355 __weak_alias(__libc_thr_curcpu,__libc_thr_curcpu_stub)
356 
357 
358 int
359 __libc_thr_once_stub(once_t *o, void (*r)(void))
360 {
361 
362 	/* XXX Knowledge of libpthread types. */
363 
364 	if (o->pto_done == 0) {
365 		(*r)();
366 		o->pto_done = 1;
367 	}
368 
369 	return (0);
370 }
371 
372 int
373 __libc_thr_sigsetmask_stub(int h, const sigset_t *s, sigset_t *o)
374 {
375 
376 	CHECK_NOT_THREADED();
377 
378 	return sigprocmask(h, s, o);
379 }
380 
381 thr_t
382 __libc_thr_self_stub(void)
383 {
384 
385 	return ((thr_t) -1);
386 }
387 
388 int
389 __libc_thr_yield_stub(void)
390 {
391 
392 	/* Nothing to do. */
393 	return (0);
394 }
395 
396 int
397 __libc_thr_create_stub(thr_t *tp, const thrattr_t *ta,
398     void *(*f)(void *), void *a)
399 {
400 	/* LINTED deliberate lack of effect */
401 	(void)tp;
402 	/* LINTED deliberate lack of effect */
403 	(void)ta;
404 	/* LINTED deliberate lack of effect */
405 	(void)f;
406 	/* LINTED deliberate lack of effect */
407 	(void)a;
408 
409 	DIE();
410 
411 	return (EOPNOTSUPP);
412 }
413 
414 void
415 __libc_thr_exit_stub(void *v)
416 {
417 	/* LINTED deliberate lack of effect */
418 	(void)v;
419 	exit(0);
420 }
421 
422 int
423 __libc_thr_setcancelstate_stub(int new, int *old)
424 {
425 	/* LINTED deliberate lack of effect */
426 	(void)new;
427 
428 	/* LINTED deliberate lack of effect */
429 	(void)old;
430 
431 	CHECK_NOT_THREADED();
432 
433 	return (0);
434 }
435 
436 int
437 __libc_thr_equal_stub(pthread_t t1, pthread_t t2)
438 {
439 
440 	/* assert that t1=t2=pthread_self() */
441 	return (t1 == t2);
442 }
443 
444 int *
445 __libc_thr_errno_stub(void)
446 {
447 
448 	DIE();
449 
450 	return (NULL);
451 }
452 
453 unsigned int
454 __libc_thr_curcpu_stub(void)
455 {
456 
457 	return (0);
458 }
459 
460 #endif /* _REENTRANT */
461