Home | History | Annotate | Line # | Download | only in thread-stub
thread-stub.c revision 1.13
      1 /*	$NetBSD: thread-stub.c,v 1.13 2005/06/12 05:21:28 lukem 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.13 2005/06/12 05:21:28 lukem 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 /* mutexes */
     78 
     79 int	__libc_mutex_init_stub(mutex_t *, const mutexattr_t *);
     80 int	__libc_mutex_catchall_stub(mutex_t *);
     81 
     82 __weak_alias(__libc_mutex_init,__libc_mutex_init_stub)
     83 __weak_alias(__libc_mutex_lock,__libc_mutex_catchall_stub)
     84 __weak_alias(__libc_mutex_trylock,__libc_mutex_catchall_stub)
     85 __weak_alias(__libc_mutex_unlock,__libc_mutex_catchall_stub)
     86 __weak_alias(__libc_mutex_destroy,__libc_mutex_catchall_stub)
     87 
     88 int	__libc_mutexattr_catchall_stub(mutexattr_t *);
     89 int	__libc_mutexattr_settype_stub(mutexattr_t *, int);
     90 
     91 __weak_alias(__libc_mutexattr_init,__libc_mutexattr_catchall_stub)
     92 __weak_alias(__libc_mutexattr_destroy,__libc_mutexattr_catchall_stub)
     93 __weak_alias(__libc_mutexattr_settype,__libc_mutexattr_settype_stub)
     94 
     95 int
     96 __libc_mutex_init_stub(mutex_t *m, const mutexattr_t *a)
     97 {
     98 	/* LINTED deliberate lack of effect */
     99 	(void)m;
    100 	/* LINTED deliberate lack of effect */
    101 	(void)a;
    102 
    103 	CHECK_NOT_THREADED();
    104 
    105 	return (0);
    106 }
    107 
    108 int
    109 __libc_mutex_catchall_stub(mutex_t *m)
    110 {
    111 	/* LINTED deliberate lack of effect */
    112 	(void)m;
    113 
    114 	CHECK_NOT_THREADED();
    115 
    116 	return (0);
    117 }
    118 
    119 int
    120 __libc_mutexattr_settype_stub(mutexattr_t *ma, int type)
    121 {
    122 	/* LINTED deliberate lack of effect */
    123 	(void)ma;
    124 	/* LINTED deliberate lack of effect */
    125 	(void)type;
    126 
    127 	return (0);
    128 }
    129 
    130 int
    131 __libc_mutexattr_catchall_stub(mutexattr_t *ma)
    132 {
    133 	/* LINTED deliberate lack of effect */
    134 	(void)ma;
    135 
    136 	CHECK_NOT_THREADED();
    137 
    138 	return (0);
    139 }
    140 
    141 /* condition variables */
    142 
    143 int	__libc_cond_init_stub(cond_t *, const condattr_t *);
    144 int	__libc_cond_wait_stub(cond_t *, mutex_t *);
    145 int	__libc_cond_timedwait_stub(cond_t *, mutex_t *,
    146 				   const struct timespec *);
    147 int	__libc_cond_catchall_stub(cond_t *);
    148 
    149 __weak_alias(__libc_cond_init,__libc_cond_init_stub)
    150 __weak_alias(__libc_cond_signal,__libc_cond_catchall_stub)
    151 __weak_alias(__libc_cond_broadcast,__libc_cond_catchall_stub)
    152 __weak_alias(__libc_cond_wait,__libc_cond_wait_stub)
    153 __weak_alias(__libc_cond_timedwait,__libc_cond_timedwait_stub)
    154 __weak_alias(__libc_cond_destroy,__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_init_stub(rwlock_t *, rwlockattr_t *);
    212 int	__libc_rwlock_catchall_stub(rwlock_t *);
    213 
    214 __weak_alias(__libc_rwlock_init,__libc_rwlock_init_stub)
    215 __weak_alias(__libc_rwlock_rdlock,__libc_rwlock_catchall_stub)
    216 __weak_alias(__libc_rwlock_wrlock,__libc_rwlock_catchall_stub)
    217 __weak_alias(__libc_rwlock_tryrdlock,__libc_rwlock_catchall_stub)
    218 __weak_alias(__libc_rwlock_trywrlock,__libc_rwlock_catchall_stub)
    219 __weak_alias(__libc_rwlock_unlock,__libc_rwlock_catchall_stub)
    220 __weak_alias(__libc_rwlock_destroy,__libc_rwlock_catchall_stub)
    221 
    222 int
    223 __libc_rwlock_init_stub(rwlock_t *l, rwlockattr_t *a)
    224 {
    225 	/* LINTED deliberate lack of effect */
    226 	(void)l;
    227 	/* LINTED deliberate lack of effect */
    228 	(void)a;
    229 
    230 	CHECK_NOT_THREADED();
    231 
    232 	return (0);
    233 }
    234 
    235 int
    236 __libc_rwlock_catchall_stub(rwlock_t *l)
    237 {
    238 	/* LINTED deliberate lack of effect */
    239 	(void)l;
    240 
    241 	CHECK_NOT_THREADED();
    242 
    243 	return (0);
    244 }
    245 
    246 
    247 /*
    248  * thread-specific data; we need to actually provide a simple TSD
    249  * implementation, since some thread-safe libraries want to use it.
    250  */
    251 
    252 #define	TSD_KEYS_MAX	64
    253 
    254 static struct {
    255 	void *tsd_val;
    256 	void (*tsd_dtor)(void *);
    257 	int tsd_inuse;
    258 } __libc_tsd[TSD_KEYS_MAX];
    259 static int __libc_tsd_nextkey;
    260 
    261 int	__libc_thr_keycreate_stub(thread_key_t *, void (*)(void *));
    262 int	__libc_thr_setspecific_stub(thread_key_t, const void *);
    263 void	*__libc_thr_getspecific_stub(thread_key_t);
    264 int	__libc_thr_keydelete_stub(thread_key_t);
    265 
    266 __weak_alias(__libc_thr_keycreate,__libc_thr_keycreate_stub)
    267 __weak_alias(__libc_thr_setspecific,__libc_thr_setspecific_stub)
    268 __weak_alias(__libc_thr_getspecific,__libc_thr_getspecific_stub)
    269 __weak_alias(__libc_thr_keydelete,__libc_thr_keydelete_stub)
    270 
    271 int
    272 __libc_thr_keycreate_stub(thread_key_t *k, void (*d)(void *))
    273 {
    274 	int i;
    275 
    276 	for (i = __libc_tsd_nextkey; i < TSD_KEYS_MAX; i++) {
    277 		if (__libc_tsd[i].tsd_inuse == 0)
    278 			goto out;
    279 	}
    280 
    281 	for (i = 0; i < __libc_tsd_nextkey; i++) {
    282 		if (__libc_tsd[i].tsd_inuse == 0)
    283 			goto out;
    284 	}
    285 
    286 	return (EAGAIN);
    287 
    288  out:
    289 	/*
    290 	 * XXX We don't actually do anything with the destructor.  We
    291 	 * XXX probably should.
    292 	 */
    293 	__libc_tsd[i].tsd_inuse = 1;
    294 	__libc_tsd_nextkey = (i + i) % TSD_KEYS_MAX;
    295 	__libc_tsd[i].tsd_dtor = d;
    296 	*k = i;
    297 
    298 	return (0);
    299 }
    300 
    301 int
    302 __libc_thr_setspecific_stub(thread_key_t k, const void *v)
    303 {
    304 
    305 	/* LINTED cast away const */
    306 	__libc_tsd[k].tsd_val = (void *) v;
    307 
    308 	return (0);
    309 }
    310 
    311 void *
    312 __libc_thr_getspecific_stub(thread_key_t k)
    313 {
    314 
    315 	return (__libc_tsd[k].tsd_val);
    316 }
    317 
    318 int
    319 __libc_thr_keydelete_stub(thread_key_t k)
    320 {
    321 
    322 	/*
    323 	 * XXX Do not recycle key; see big comment in libpthread.
    324 	 */
    325 
    326 	__libc_tsd[k].tsd_dtor = NULL;
    327 
    328 	return (0);
    329 }
    330 
    331 
    332 /* misc. */
    333 
    334 int	__libc_thr_once_stub(once_t *, void (*)(void));
    335 int	__libc_thr_sigsetmask_stub(int, const sigset_t *, sigset_t *);
    336 thr_t	__libc_thr_self_stub(void);
    337 int	__libc_thr_yield_stub(void);
    338 int	__libc_thr_create_stub(thr_t *, const thrattr_t *,
    339 	    void *(*)(void *), void *);
    340 void	__libc_thr_exit_stub(void *);
    341 int	*__libc_thr_errno_stub(void);
    342 int	__libc_thr_setcancelstate_stub(int, int *);
    343 
    344 __weak_alias(__libc_thr_once,__libc_thr_once_stub)
    345 __weak_alias(__libc_thr_sigsetmask,__libc_thr_sigsetmask_stub)
    346 __weak_alias(__libc_thr_self,__libc_thr_self_stub)
    347 __weak_alias(__libc_thr_yield,__libc_thr_yield_stub)
    348 __weak_alias(__libc_thr_create,__libc_thr_create_stub)
    349 __weak_alias(__libc_thr_exit,__libc_thr_exit_stub)
    350 __weak_alias(__libc_thr_errno,__libc_thr_errno_stub)
    351 __weak_alias(__libc_thr_setcancelstate,__libc_thr_setcancelstate_stub)
    352 
    353 
    354 int
    355 __libc_thr_once_stub(once_t *o, void (*r)(void))
    356 {
    357 
    358 	/* XXX Knowledge of libpthread types. */
    359 
    360 	if (o->pto_done == 0) {
    361 		(*r)();
    362 		o->pto_done = 1;
    363 	}
    364 
    365 	return (0);
    366 }
    367 
    368 int
    369 __libc_thr_sigsetmask_stub(int h, const sigset_t *s, sigset_t *o)
    370 {
    371 
    372 	CHECK_NOT_THREADED();
    373 
    374 	return sigprocmask(h, s, o);
    375 }
    376 
    377 thr_t
    378 __libc_thr_self_stub(void)
    379 {
    380 
    381 	return ((thr_t) -1);
    382 }
    383 
    384 int
    385 __libc_thr_yield_stub(void)
    386 {
    387 
    388 	/* Nothing to do. */
    389 	return (0);
    390 }
    391 
    392 int
    393 __libc_thr_create_stub(thr_t *tp, const thrattr_t *ta,
    394     void *(*f)(void *), void *a)
    395 {
    396 	/* LINTED deliberate lack of effect */
    397 	(void)tp;
    398 	/* LINTED deliberate lack of effect */
    399 	(void)ta;
    400 	/* LINTED deliberate lack of effect */
    401 	(void)f;
    402 	/* LINTED deliberate lack of effect */
    403 	(void)a;
    404 
    405 	DIE();
    406 
    407 	return (EOPNOTSUPP);
    408 }
    409 
    410 void
    411 __libc_thr_exit_stub(void *v)
    412 {
    413 	/* LINTED deliberate lack of effect */
    414 	(void)v;
    415 	exit(0);
    416 }
    417 
    418 int
    419 __libc_thr_setcancelstate_stub(int new, int *old)
    420 {
    421 	/* LINTED deliberate lack of effect */
    422 	(void)new;
    423 
    424 	/* LINTED deliberate lack of effect */
    425 	(void)old;
    426 
    427 	CHECK_NOT_THREADED();
    428 
    429 	return (0);
    430 }
    431 
    432 int *
    433 __libc_thr_errno_stub(void)
    434 {
    435 
    436 	DIE();
    437 
    438 	return (NULL);
    439 }
    440 
    441 #endif /* _REENTRANT */
    442