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