1 /* $NetBSD: thread-stub.c,v 1.19 2007/12/14 17:06:07 christos 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.19 2007/12/14 17:06:07 christos 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 int __libc_thr_equal_stub(pthread_t, pthread_t); 357 unsigned int __libc_thr_curcpu_stub(void); 358 359 __weak_alias(__libc_thr_once,__libc_thr_once_stub) 360 __weak_alias(__libc_thr_sigsetmask,__libc_thr_sigsetmask_stub) 361 __weak_alias(__libc_thr_self,__libc_thr_self_stub) 362 __weak_alias(__libc_thr_yield,__libc_thr_yield_stub) 363 __weak_alias(__libc_thr_create,__libc_thr_create_stub) 364 __weak_alias(__libc_thr_exit,__libc_thr_exit_stub) 365 __weak_alias(__libc_thr_errno,__libc_thr_errno_stub) 366 __weak_alias(__libc_thr_setcancelstate,__libc_thr_setcancelstate_stub) 367 __weak_alias(__libc_thr_equal,__libc_thr_equal_stub) 368 __weak_alias(__libc_thr_curcpu,__libc_thr_curcpu_stub) 369 370 371 int 372 __libc_thr_once_stub(once_t *o, void (*r)(void)) 373 { 374 375 /* XXX Knowledge of libpthread types. */ 376 377 if (o->pto_done == 0) { 378 (*r)(); 379 o->pto_done = 1; 380 } 381 382 return (0); 383 } 384 385 int 386 __libc_thr_sigsetmask_stub(int h, const sigset_t *s, sigset_t *o) 387 { 388 389 CHECK_NOT_THREADED(); 390 391 return sigprocmask(h, s, o); 392 } 393 394 thr_t 395 __libc_thr_self_stub(void) 396 { 397 398 return ((thr_t) -1); 399 } 400 401 int 402 __libc_thr_yield_stub(void) 403 { 404 405 /* Nothing to do. */ 406 return (0); 407 } 408 409 int 410 __libc_thr_create_stub(thr_t *tp, const thrattr_t *ta, 411 void *(*f)(void *), void *a) 412 { 413 /* LINTED deliberate lack of effect */ 414 (void)tp; 415 /* LINTED deliberate lack of effect */ 416 (void)ta; 417 /* LINTED deliberate lack of effect */ 418 (void)f; 419 /* LINTED deliberate lack of effect */ 420 (void)a; 421 422 DIE(); 423 424 return (EOPNOTSUPP); 425 } 426 427 void 428 __libc_thr_exit_stub(void *v) 429 { 430 /* LINTED deliberate lack of effect */ 431 (void)v; 432 exit(0); 433 } 434 435 int 436 __libc_thr_setcancelstate_stub(int new, int *old) 437 { 438 /* LINTED deliberate lack of effect */ 439 (void)new; 440 441 /* LINTED deliberate lack of effect */ 442 (void)old; 443 444 CHECK_NOT_THREADED(); 445 446 return (0); 447 } 448 449 int 450 __libc_thr_equal_stub(pthread_t t1, pthread_t t2) 451 { 452 453 /* assert that t1=t2=pthread_self() */ 454 return (t1 == t2); 455 } 456 457 int * 458 __libc_thr_errno_stub(void) 459 { 460 461 DIE(); 462 463 return (NULL); 464 } 465 466 unsigned int 467 __libc_thr_curcpu_stub(void) 468 { 469 470 return (0); 471 } 472 473 #endif /* _REENTRANT */ 474