Home | History | Annotate | Line # | Download | only in thread-stub
thread-stub.c revision 1.21
      1 /*	$NetBSD: thread-stub.c,v 1.21 2009/01/30 23:21:03 ad 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.21 2009/01/30 23:21:03 ad 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 /* libpthread init */
     71 
     72 void	__libc_thr_init(void);
     73 void	__libc_thr_init_stub(void);
     74 
     75 __weak_alias(__libc_thr_init,__libc_thr_init_stub)
     76 
     77 void
     78 __libc_thr_init_stub(void)
     79 {
     80 
     81 	/* nothing, may be overridden by libpthread */
     82 }
     83 
     84 /* mutexes */
     85 
     86 int	__libc_mutex_init_stub(mutex_t *, const mutexattr_t *);
     87 int	__libc_mutex_catchall_stub(mutex_t *);
     88 
     89 __weak_alias(__libc_mutex_init,__libc_mutex_init_stub)
     90 __weak_alias(__libc_mutex_lock,__libc_mutex_catchall_stub)
     91 __weak_alias(__libc_mutex_trylock,__libc_mutex_catchall_stub)
     92 __weak_alias(__libc_mutex_unlock,__libc_mutex_catchall_stub)
     93 __weak_alias(__libc_mutex_destroy,__libc_mutex_catchall_stub)
     94 
     95 int	__libc_mutexattr_catchall_stub(mutexattr_t *);
     96 int	__libc_mutexattr_settype_stub(mutexattr_t *, int);
     97 
     98 __weak_alias(__libc_mutexattr_init,__libc_mutexattr_catchall_stub)
     99 __weak_alias(__libc_mutexattr_destroy,__libc_mutexattr_catchall_stub)
    100 __weak_alias(__libc_mutexattr_settype,__libc_mutexattr_settype_stub)
    101 
    102 int
    103 __libc_mutex_init_stub(mutex_t *m, const mutexattr_t *a)
    104 {
    105 	/* LINTED deliberate lack of effect */
    106 	(void)m;
    107 	/* LINTED deliberate lack of effect */
    108 	(void)a;
    109 
    110 	CHECK_NOT_THREADED();
    111 
    112 	return (0);
    113 }
    114 
    115 int
    116 __libc_mutex_catchall_stub(mutex_t *m)
    117 {
    118 	/* LINTED deliberate lack of effect */
    119 	(void)m;
    120 
    121 	CHECK_NOT_THREADED();
    122 
    123 	return (0);
    124 }
    125 
    126 int
    127 __libc_mutexattr_settype_stub(mutexattr_t *ma, int type)
    128 {
    129 	/* LINTED deliberate lack of effect */
    130 	(void)ma;
    131 	/* LINTED deliberate lack of effect */
    132 	(void)type;
    133 
    134 	return (0);
    135 }
    136 
    137 int
    138 __libc_mutexattr_catchall_stub(mutexattr_t *ma)
    139 {
    140 	/* LINTED deliberate lack of effect */
    141 	(void)ma;
    142 
    143 	CHECK_NOT_THREADED();
    144 
    145 	return (0);
    146 }
    147 
    148 /* condition variables */
    149 
    150 int	__libc_cond_init_stub(cond_t *, const condattr_t *);
    151 int	__libc_cond_wait_stub(cond_t *, mutex_t *);
    152 int	__libc_cond_timedwait_stub(cond_t *, mutex_t *,
    153 				   const struct timespec *);
    154 int	__libc_cond_catchall_stub(cond_t *);
    155 
    156 __weak_alias(__libc_cond_init,__libc_cond_init_stub)
    157 __weak_alias(__libc_cond_signal,__libc_cond_catchall_stub)
    158 __weak_alias(__libc_cond_broadcast,__libc_cond_catchall_stub)
    159 __weak_alias(__libc_cond_wait,__libc_cond_wait_stub)
    160 __weak_alias(__libc_cond_timedwait,__libc_cond_timedwait_stub)
    161 __weak_alias(__libc_cond_destroy,__libc_cond_catchall_stub)
    162 
    163 int
    164 __libc_cond_init_stub(cond_t *c, const condattr_t *a)
    165 {
    166 	/* LINTED deliberate lack of effect */
    167 	(void)c;
    168 	/* LINTED deliberate lack of effect */
    169 	(void)a;
    170 
    171 	CHECK_NOT_THREADED();
    172 
    173 	return (0);
    174 }
    175 
    176 int
    177 __libc_cond_wait_stub(cond_t *c, mutex_t *m)
    178 {
    179 	/* LINTED deliberate lack of effect */
    180 	(void)c;
    181 	/* LINTED deliberate lack of effect */
    182 	(void)m;
    183 
    184 	CHECK_NOT_THREADED();
    185 
    186 	return (0);
    187 }
    188 
    189 int
    190 __libc_cond_timedwait_stub(cond_t *c, mutex_t *m, const struct timespec *t)
    191 {
    192 	/* LINTED deliberate lack of effect */
    193 	(void)c;
    194 	/* LINTED deliberate lack of effect */
    195 	(void)m;
    196 	/* LINTED deliberate lack of effect */
    197 	(void)t;
    198 
    199 	CHECK_NOT_THREADED();
    200 
    201 	return (0);
    202 }
    203 
    204 int
    205 __libc_cond_catchall_stub(cond_t *c)
    206 {
    207 	/* LINTED deliberate lack of effect */
    208 	(void)c;
    209 
    210 	CHECK_NOT_THREADED();
    211 
    212 	return (0);
    213 }
    214 
    215 
    216 /* read-write locks */
    217 
    218 int	__libc_rwlock_init_stub(rwlock_t *, rwlockattr_t *);
    219 int	__libc_rwlock_catchall_stub(rwlock_t *);
    220 
    221 __weak_alias(__libc_rwlock_init,__libc_rwlock_init_stub)
    222 __weak_alias(__libc_rwlock_rdlock,__libc_rwlock_catchall_stub)
    223 __weak_alias(__libc_rwlock_wrlock,__libc_rwlock_catchall_stub)
    224 __weak_alias(__libc_rwlock_tryrdlock,__libc_rwlock_catchall_stub)
    225 __weak_alias(__libc_rwlock_trywrlock,__libc_rwlock_catchall_stub)
    226 __weak_alias(__libc_rwlock_unlock,__libc_rwlock_catchall_stub)
    227 __weak_alias(__libc_rwlock_destroy,__libc_rwlock_catchall_stub)
    228 
    229 int
    230 __libc_rwlock_init_stub(rwlock_t *l, 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 int	__libc_thr_keycreate_stub(thread_key_t *, void (*)(void *));
    269 int	__libc_thr_setspecific_stub(thread_key_t, const void *);
    270 void	*__libc_thr_getspecific_stub(thread_key_t);
    271 int	__libc_thr_keydelete_stub(thread_key_t);
    272 
    273 __weak_alias(__libc_thr_keycreate,__libc_thr_keycreate_stub)
    274 __weak_alias(__libc_thr_setspecific,__libc_thr_setspecific_stub)
    275 __weak_alias(__libc_thr_getspecific,__libc_thr_getspecific_stub)
    276 __weak_alias(__libc_thr_keydelete,__libc_thr_keydelete_stub)
    277 
    278 int
    279 __libc_thr_keycreate_stub(thread_key_t *k, void (*d)(void *))
    280 {
    281 	int i;
    282 
    283 	for (i = __libc_tsd_nextkey; i < TSD_KEYS_MAX; i++) {
    284 		if (__libc_tsd[i].tsd_inuse == 0)
    285 			goto out;
    286 	}
    287 
    288 	for (i = 0; i < __libc_tsd_nextkey; i++) {
    289 		if (__libc_tsd[i].tsd_inuse == 0)
    290 			goto out;
    291 	}
    292 
    293 	return (EAGAIN);
    294 
    295  out:
    296 	/*
    297 	 * XXX We don't actually do anything with the destructor.  We
    298 	 * XXX probably should.
    299 	 */
    300 	__libc_tsd[i].tsd_inuse = 1;
    301 	__libc_tsd_nextkey = (i + i) % TSD_KEYS_MAX;
    302 	__libc_tsd[i].tsd_dtor = d;
    303 	*k = i;
    304 
    305 	return (0);
    306 }
    307 
    308 int
    309 __libc_thr_setspecific_stub(thread_key_t k, const void *v)
    310 {
    311 
    312 	__libc_tsd[k].tsd_val = __UNCONST(v);
    313 
    314 	return (0);
    315 }
    316 
    317 void *
    318 __libc_thr_getspecific_stub(thread_key_t k)
    319 {
    320 
    321 	return (__libc_tsd[k].tsd_val);
    322 }
    323 
    324 int
    325 __libc_thr_keydelete_stub(thread_key_t k)
    326 {
    327 
    328 	/*
    329 	 * XXX Do not recycle key; see big comment in libpthread.
    330 	 */
    331 
    332 	__libc_tsd[k].tsd_dtor = NULL;
    333 
    334 	return (0);
    335 }
    336 
    337 
    338 /* misc. */
    339 
    340 int	__libc_thr_once_stub(once_t *, void (*)(void));
    341 int	__libc_thr_sigsetmask_stub(int, const sigset_t *, sigset_t *);
    342 thr_t	__libc_thr_self_stub(void);
    343 int	__libc_thr_yield_stub(void);
    344 int	__libc_thr_create_stub(thr_t *, const thrattr_t *,
    345 	    void *(*)(void *), void *);
    346 void	__libc_thr_exit_stub(void *);
    347 int	*__libc_thr_errno_stub(void);
    348 int	__libc_thr_setcancelstate_stub(int, int *);
    349 int	__libc_thr_equal_stub(pthread_t, pthread_t);
    350 unsigned int __libc_thr_curcpu_stub(void);
    351 
    352 __weak_alias(__libc_thr_once,__libc_thr_once_stub)
    353 __weak_alias(__libc_thr_sigsetmask,__libc_thr_sigsetmask_stub)
    354 __weak_alias(__libc_thr_self,__libc_thr_self_stub)
    355 __weak_alias(__libc_thr_yield,__libc_thr_yield_stub)
    356 __weak_alias(__libc_thr_create,__libc_thr_create_stub)
    357 __weak_alias(__libc_thr_exit,__libc_thr_exit_stub)
    358 __weak_alias(__libc_thr_errno,__libc_thr_errno_stub)
    359 __weak_alias(__libc_thr_setcancelstate,__libc_thr_setcancelstate_stub)
    360 __weak_alias(__libc_thr_equal,__libc_thr_equal_stub)
    361 __weak_alias(__libc_thr_curcpu,__libc_thr_curcpu_stub)
    362 
    363 
    364 int
    365 __libc_thr_once_stub(once_t *o, void (*r)(void))
    366 {
    367 
    368 	/* XXX Knowledge of libpthread types. */
    369 
    370 	if (o->pto_done == 0) {
    371 		(*r)();
    372 		o->pto_done = 1;
    373 	}
    374 
    375 	return (0);
    376 }
    377 
    378 int
    379 __libc_thr_sigsetmask_stub(int h, const sigset_t *s, sigset_t *o)
    380 {
    381 
    382 	CHECK_NOT_THREADED();
    383 
    384 	return sigprocmask(h, s, o);
    385 }
    386 
    387 thr_t
    388 __libc_thr_self_stub(void)
    389 {
    390 
    391 	return ((thr_t) -1);
    392 }
    393 
    394 int
    395 __libc_thr_yield_stub(void)
    396 {
    397 
    398 	/* Nothing to do. */
    399 	return (0);
    400 }
    401 
    402 int
    403 __libc_thr_create_stub(thr_t *tp, const thrattr_t *ta,
    404     void *(*f)(void *), void *a)
    405 {
    406 	/* LINTED deliberate lack of effect */
    407 	(void)tp;
    408 	/* LINTED deliberate lack of effect */
    409 	(void)ta;
    410 	/* LINTED deliberate lack of effect */
    411 	(void)f;
    412 	/* LINTED deliberate lack of effect */
    413 	(void)a;
    414 
    415 	DIE();
    416 
    417 	return (EOPNOTSUPP);
    418 }
    419 
    420 void
    421 __libc_thr_exit_stub(void *v)
    422 {
    423 	/* LINTED deliberate lack of effect */
    424 	(void)v;
    425 	exit(0);
    426 }
    427 
    428 int
    429 __libc_thr_setcancelstate_stub(int new, int *old)
    430 {
    431 	/* LINTED deliberate lack of effect */
    432 	(void)new;
    433 
    434 	/* LINTED deliberate lack of effect */
    435 	(void)old;
    436 
    437 	CHECK_NOT_THREADED();
    438 
    439 	return (0);
    440 }
    441 
    442 int
    443 __libc_thr_equal_stub(pthread_t t1, pthread_t t2)
    444 {
    445 
    446 	/* assert that t1=t2=pthread_self() */
    447 	return (t1 == t2);
    448 }
    449 
    450 int *
    451 __libc_thr_errno_stub(void)
    452 {
    453 
    454 	DIE();
    455 
    456 	return (NULL);
    457 }
    458 
    459 unsigned int
    460 __libc_thr_curcpu_stub(void)
    461 {
    462 
    463 	return (0);
    464 }
    465 
    466 #endif /* _REENTRANT */
    467