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