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