xref: /netbsd-src/lib/libc/thread-stub/thread-stub.c (revision 62f324d0121177eaf2e0384f92fd9ca2a751c795)
1 /*	$NetBSD: thread-stub.c,v 1.24 2013/04/05 20:15:42 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.24 2013/04/05 20:15:42 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 /* mutexes */
71 
72 int __libc_mutex_catchall_stub(mutex_t *);
73 
74 __weak_alias(__libc_mutex_init,__libc_mutex_init_stub)
75 __weak_alias(__libc_mutex_lock,__libc_mutex_catchall_stub)
76 __weak_alias(__libc_mutex_trylock,__libc_mutex_catchall_stub)
77 __weak_alias(__libc_mutex_unlock,__libc_mutex_catchall_stub)
78 __weak_alias(__libc_mutex_destroy,__libc_mutex_catchall_stub)
79 
80 __strong_alias(__libc_mutex_lock_stub,__libc_mutex_catchall_stub)
81 __strong_alias(__libc_mutex_trylock_stub,__libc_mutex_catchall_stub)
82 __strong_alias(__libc_mutex_unlock_stub,__libc_mutex_catchall_stub)
83 __strong_alias(__libc_mutex_destroy_stub,__libc_mutex_catchall_stub)
84 
85 int __libc_mutexattr_catchall_stub(mutexattr_t *);
86 
87 __weak_alias(__libc_mutexattr_init,__libc_mutexattr_catchall_stub)
88 __weak_alias(__libc_mutexattr_destroy,__libc_mutexattr_catchall_stub)
89 __weak_alias(__libc_mutexattr_settype,__libc_mutexattr_settype_stub)
90 
91 __strong_alias(__libc_mutexattr_init_stub,__libc_mutexattr_catchall_stub)
92 __strong_alias(__libc_mutexattr_destroy_stub,__libc_mutexattr_catchall_stub)
93 
94 int
95 __libc_mutex_init_stub(mutex_t *m, const mutexattr_t *a)
96 {
97 	/* LINTED deliberate lack of effect */
98 	(void)m;
99 	/* LINTED deliberate lack of effect */
100 	(void)a;
101 
102 	CHECK_NOT_THREADED();
103 
104 	return (0);
105 }
106 
107 int
108 __libc_mutex_catchall_stub(mutex_t *m)
109 {
110 	/* LINTED deliberate lack of effect */
111 	(void)m;
112 
113 	CHECK_NOT_THREADED();
114 
115 	return (0);
116 }
117 
118 int
119 __libc_mutexattr_settype_stub(mutexattr_t *ma, int type)
120 {
121 	/* LINTED deliberate lack of effect */
122 	(void)ma;
123 	/* LINTED deliberate lack of effect */
124 	(void)type;
125 
126 	return (0);
127 }
128 
129 int
130 __libc_mutexattr_catchall_stub(mutexattr_t *ma)
131 {
132 	/* LINTED deliberate lack of effect */
133 	(void)ma;
134 
135 	CHECK_NOT_THREADED();
136 
137 	return (0);
138 }
139 
140 /* condition variables */
141 
142 int __libc_cond_catchall_stub(cond_t *);
143 
144 __weak_alias(__libc_cond_init,__libc_cond_init_stub)
145 __weak_alias(__libc_cond_signal,__libc_cond_catchall_stub)
146 __weak_alias(__libc_cond_broadcast,__libc_cond_catchall_stub)
147 __weak_alias(__libc_cond_wait,__libc_cond_wait_stub)
148 __weak_alias(__libc_cond_timedwait,__libc_cond_timedwait_stub)
149 __weak_alias(__libc_cond_destroy,__libc_cond_catchall_stub)
150 
151 __strong_alias(__libc_cond_signal_stub,__libc_cond_catchall_stub)
152 __strong_alias(__libc_cond_broadcast_stub,__libc_cond_catchall_stub)
153 __strong_alias(__libc_cond_wait_stub,__libc_cond_catchall_stub)
154 __strong_alias(__libc_cond_destroy_stub,__libc_cond_catchall_stub)
155 
156 int
157 __libc_cond_init_stub(cond_t *c, const condattr_t *a)
158 {
159 	/* LINTED deliberate lack of effect */
160 	(void)c;
161 	/* LINTED deliberate lack of effect */
162 	(void)a;
163 
164 	CHECK_NOT_THREADED();
165 
166 	return (0);
167 }
168 
169 int
170 __libc_cond_wait_stub(cond_t *c, mutex_t *m)
171 {
172 	/* LINTED deliberate lack of effect */
173 	(void)c;
174 	/* LINTED deliberate lack of effect */
175 	(void)m;
176 
177 	CHECK_NOT_THREADED();
178 
179 	return (0);
180 }
181 
182 int
183 __libc_cond_timedwait_stub(cond_t *c, mutex_t *m, const struct timespec *t)
184 {
185 	/* LINTED deliberate lack of effect */
186 	(void)c;
187 	/* LINTED deliberate lack of effect */
188 	(void)m;
189 	/* LINTED deliberate lack of effect */
190 	(void)t;
191 
192 	CHECK_NOT_THREADED();
193 
194 	return (0);
195 }
196 
197 int
198 __libc_cond_catchall_stub(cond_t *c)
199 {
200 	/* LINTED deliberate lack of effect */
201 	(void)c;
202 
203 	CHECK_NOT_THREADED();
204 
205 	return (0);
206 }
207 
208 
209 /* read-write locks */
210 
211 int __libc_rwlock_catchall_stub(rwlock_t *);
212 
213 __weak_alias(__libc_rwlock_init,__libc_rwlock_init_stub)
214 __weak_alias(__libc_rwlock_rdlock,__libc_rwlock_catchall_stub)
215 __weak_alias(__libc_rwlock_wrlock,__libc_rwlock_catchall_stub)
216 __weak_alias(__libc_rwlock_tryrdlock,__libc_rwlock_catchall_stub)
217 __weak_alias(__libc_rwlock_trywrlock,__libc_rwlock_catchall_stub)
218 __weak_alias(__libc_rwlock_unlock,__libc_rwlock_catchall_stub)
219 __weak_alias(__libc_rwlock_destroy,__libc_rwlock_catchall_stub)
220 
221 __strong_alias(__libc_rwlock_rdlock_stub,__libc_rwlock_catchall_stub)
222 __strong_alias(__libc_rwlock_wrlock_stub,__libc_rwlock_catchall_stub)
223 __strong_alias(__libc_rwlock_tryrdlock_stub,__libc_rwlock_catchall_stub)
224 __strong_alias(__libc_rwlock_trywrlock_stub,__libc_rwlock_catchall_stub)
225 __strong_alias(__libc_rwlock_unlock_stub,__libc_rwlock_catchall_stub)
226 __strong_alias(__libc_rwlock_destroy_stub,__libc_rwlock_catchall_stub)
227 
228 
229 int
230 __libc_rwlock_init_stub(rwlock_t *l, const rwlockattr_t *a)
231 {
232 	/* LINTED deliberate lack of effect */
233 	(void)l;
234 	/* LINTED deliberate lack of effect */
235 	(void)a;
236 
237 	CHECK_NOT_THREADED();
238 
239 	return (0);
240 }
241 
242 int
243 __libc_rwlock_catchall_stub(rwlock_t *l)
244 {
245 	/* LINTED deliberate lack of effect */
246 	(void)l;
247 
248 	CHECK_NOT_THREADED();
249 
250 	return (0);
251 }
252 
253 
254 /*
255  * thread-specific data; we need to actually provide a simple TSD
256  * implementation, since some thread-safe libraries want to use it.
257  */
258 
259 #define	TSD_KEYS_MAX	64
260 
261 static struct {
262 	void *tsd_val;
263 	void (*tsd_dtor)(void *);
264 	int tsd_inuse;
265 } __libc_tsd[TSD_KEYS_MAX];
266 static int __libc_tsd_nextkey;
267 
268 __weak_alias(__libc_thr_keycreate,__libc_thr_keycreate_stub)
269 __weak_alias(__libc_thr_setspecific,__libc_thr_setspecific_stub)
270 __weak_alias(__libc_thr_getspecific,__libc_thr_getspecific_stub)
271 __weak_alias(__libc_thr_keydelete,__libc_thr_keydelete_stub)
272 
273 int
274 __libc_thr_keycreate_stub(thread_key_t *k, void (*d)(void *))
275 {
276 	int i;
277 
278 	for (i = __libc_tsd_nextkey; i < TSD_KEYS_MAX; i++) {
279 		if (__libc_tsd[i].tsd_inuse == 0)
280 			goto out;
281 	}
282 
283 	for (i = 0; i < __libc_tsd_nextkey; i++) {
284 		if (__libc_tsd[i].tsd_inuse == 0)
285 			goto out;
286 	}
287 
288 	return (EAGAIN);
289 
290  out:
291 	/*
292 	 * XXX We don't actually do anything with the destructor.  We
293 	 * XXX probably should.
294 	 */
295 	__libc_tsd[i].tsd_inuse = 1;
296 	__libc_tsd_nextkey = (i + i) % TSD_KEYS_MAX;
297 	__libc_tsd[i].tsd_dtor = d;
298 	*k = i;
299 
300 	return (0);
301 }
302 
303 int
304 __libc_thr_setspecific_stub(thread_key_t k, const void *v)
305 {
306 
307 	__libc_tsd[k].tsd_val = __UNCONST(v);
308 
309 	return (0);
310 }
311 
312 void *
313 __libc_thr_getspecific_stub(thread_key_t k)
314 {
315 
316 	return (__libc_tsd[k].tsd_val);
317 }
318 
319 int
320 __libc_thr_keydelete_stub(thread_key_t k)
321 {
322 
323 	/*
324 	 * XXX Do not recycle key; see big comment in libpthread.
325 	 */
326 
327 	__libc_tsd[k].tsd_dtor = NULL;
328 
329 	return (0);
330 }
331 
332 
333 /* misc. */
334 
335 __weak_alias(__libc_thr_once,__libc_thr_once_stub)
336 __weak_alias(__libc_thr_sigsetmask,__libc_thr_sigsetmask_stub)
337 __weak_alias(__libc_thr_self,__libc_thr_self_stub)
338 __weak_alias(__libc_thr_yield,__libc_thr_yield_stub)
339 __weak_alias(__libc_thr_create,__libc_thr_create_stub)
340 __weak_alias(__libc_thr_exit,__libc_thr_exit_stub)
341 __weak_alias(__libc_thr_setcancelstate,__libc_thr_setcancelstate_stub)
342 __weak_alias(__libc_thr_equal,__libc_thr_equal_stub)
343 __weak_alias(__libc_thr_curcpu,__libc_thr_curcpu_stub)
344 
345 
346 int
347 __libc_thr_once_stub(once_t *o, void (*r)(void))
348 {
349 
350 	/* XXX Knowledge of libpthread types. */
351 
352 	if (o->pto_done == 0) {
353 		(*r)();
354 		o->pto_done = 1;
355 	}
356 
357 	return (0);
358 }
359 
360 int
361 __libc_thr_sigsetmask_stub(int h, const sigset_t *s, sigset_t *o)
362 {
363 
364 	CHECK_NOT_THREADED();
365 
366 	return sigprocmask(h, s, o);
367 }
368 
369 thr_t
370 __libc_thr_self_stub(void)
371 {
372 
373 	return ((thr_t) -1);
374 }
375 
376 int
377 __libc_thr_yield_stub(void)
378 {
379 
380 	/* Nothing to do. */
381 	return (0);
382 }
383 
384 int
385 __libc_thr_create_stub(thr_t *tp, const thrattr_t *ta,
386     void *(*f)(void *), void *a)
387 {
388 	/* LINTED deliberate lack of effect */
389 	(void)tp;
390 	/* LINTED deliberate lack of effect */
391 	(void)ta;
392 	/* LINTED deliberate lack of effect */
393 	(void)f;
394 	/* LINTED deliberate lack of effect */
395 	(void)a;
396 
397 	DIE();
398 
399 	return (EOPNOTSUPP);
400 }
401 
402 void
403 __libc_thr_exit_stub(void *v)
404 {
405 	/* LINTED deliberate lack of effect */
406 	(void)v;
407 	exit(0);
408 }
409 
410 int
411 __libc_thr_setcancelstate_stub(int new, int *old)
412 {
413 	/* LINTED deliberate lack of effect */
414 	(void)new;
415 
416 	/* LINTED deliberate lack of effect */
417 	(void)old;
418 
419 	CHECK_NOT_THREADED();
420 
421 	return (0);
422 }
423 
424 int
425 __libc_thr_equal_stub(pthread_t t1, pthread_t t2)
426 {
427 
428 	/* assert that t1=t2=pthread_self() */
429 	return (t1 == t2);
430 }
431 
432 unsigned int
433 __libc_thr_curcpu_stub(void)
434 {
435 
436 	return (0);
437 }
438 
439 #endif /* _REENTRANT */
440