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