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