1 /* $NetBSD: thread-stub.c,v 1.24 2013/04/05 20:15:42 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.24 2013/04/05 20:15:42 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 /* mutexes */ 71 72 int __libc_mutex_catchall_stub(mutex_t *); 73 74 __weak_alias(__libc_mutex_init,__libc_mutex_init_stub) 75 __weak_alias(__libc_mutex_lock,__libc_mutex_catchall_stub) 76 __weak_alias(__libc_mutex_trylock,__libc_mutex_catchall_stub) 77 __weak_alias(__libc_mutex_unlock,__libc_mutex_catchall_stub) 78 __weak_alias(__libc_mutex_destroy,__libc_mutex_catchall_stub) 79 80 __strong_alias(__libc_mutex_lock_stub,__libc_mutex_catchall_stub) 81 __strong_alias(__libc_mutex_trylock_stub,__libc_mutex_catchall_stub) 82 __strong_alias(__libc_mutex_unlock_stub,__libc_mutex_catchall_stub) 83 __strong_alias(__libc_mutex_destroy_stub,__libc_mutex_catchall_stub) 84 85 int __libc_mutexattr_catchall_stub(mutexattr_t *); 86 87 __weak_alias(__libc_mutexattr_init,__libc_mutexattr_catchall_stub) 88 __weak_alias(__libc_mutexattr_destroy,__libc_mutexattr_catchall_stub) 89 __weak_alias(__libc_mutexattr_settype,__libc_mutexattr_settype_stub) 90 91 __strong_alias(__libc_mutexattr_init_stub,__libc_mutexattr_catchall_stub) 92 __strong_alias(__libc_mutexattr_destroy_stub,__libc_mutexattr_catchall_stub) 93 94 int 95 __libc_mutex_init_stub(mutex_t *m, const mutexattr_t *a) 96 { 97 /* LINTED deliberate lack of effect */ 98 (void)m; 99 /* LINTED deliberate lack of effect */ 100 (void)a; 101 102 CHECK_NOT_THREADED(); 103 104 return (0); 105 } 106 107 int 108 __libc_mutex_catchall_stub(mutex_t *m) 109 { 110 /* LINTED deliberate lack of effect */ 111 (void)m; 112 113 CHECK_NOT_THREADED(); 114 115 return (0); 116 } 117 118 int 119 __libc_mutexattr_settype_stub(mutexattr_t *ma, int type) 120 { 121 /* LINTED deliberate lack of effect */ 122 (void)ma; 123 /* LINTED deliberate lack of effect */ 124 (void)type; 125 126 return (0); 127 } 128 129 int 130 __libc_mutexattr_catchall_stub(mutexattr_t *ma) 131 { 132 /* LINTED deliberate lack of effect */ 133 (void)ma; 134 135 CHECK_NOT_THREADED(); 136 137 return (0); 138 } 139 140 /* condition variables */ 141 142 int __libc_cond_catchall_stub(cond_t *); 143 144 __weak_alias(__libc_cond_init,__libc_cond_init_stub) 145 __weak_alias(__libc_cond_signal,__libc_cond_catchall_stub) 146 __weak_alias(__libc_cond_broadcast,__libc_cond_catchall_stub) 147 __weak_alias(__libc_cond_wait,__libc_cond_wait_stub) 148 __weak_alias(__libc_cond_timedwait,__libc_cond_timedwait_stub) 149 __weak_alias(__libc_cond_destroy,__libc_cond_catchall_stub) 150 151 __strong_alias(__libc_cond_signal_stub,__libc_cond_catchall_stub) 152 __strong_alias(__libc_cond_broadcast_stub,__libc_cond_catchall_stub) 153 __strong_alias(__libc_cond_wait_stub,__libc_cond_catchall_stub) 154 __strong_alias(__libc_cond_destroy_stub,__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_catchall_stub(rwlock_t *); 212 213 __weak_alias(__libc_rwlock_init,__libc_rwlock_init_stub) 214 __weak_alias(__libc_rwlock_rdlock,__libc_rwlock_catchall_stub) 215 __weak_alias(__libc_rwlock_wrlock,__libc_rwlock_catchall_stub) 216 __weak_alias(__libc_rwlock_tryrdlock,__libc_rwlock_catchall_stub) 217 __weak_alias(__libc_rwlock_trywrlock,__libc_rwlock_catchall_stub) 218 __weak_alias(__libc_rwlock_unlock,__libc_rwlock_catchall_stub) 219 __weak_alias(__libc_rwlock_destroy,__libc_rwlock_catchall_stub) 220 221 __strong_alias(__libc_rwlock_rdlock_stub,__libc_rwlock_catchall_stub) 222 __strong_alias(__libc_rwlock_wrlock_stub,__libc_rwlock_catchall_stub) 223 __strong_alias(__libc_rwlock_tryrdlock_stub,__libc_rwlock_catchall_stub) 224 __strong_alias(__libc_rwlock_trywrlock_stub,__libc_rwlock_catchall_stub) 225 __strong_alias(__libc_rwlock_unlock_stub,__libc_rwlock_catchall_stub) 226 __strong_alias(__libc_rwlock_destroy_stub,__libc_rwlock_catchall_stub) 227 228 229 int 230 __libc_rwlock_init_stub(rwlock_t *l, const 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 __weak_alias(__libc_thr_keycreate,__libc_thr_keycreate_stub) 269 __weak_alias(__libc_thr_setspecific,__libc_thr_setspecific_stub) 270 __weak_alias(__libc_thr_getspecific,__libc_thr_getspecific_stub) 271 __weak_alias(__libc_thr_keydelete,__libc_thr_keydelete_stub) 272 273 int 274 __libc_thr_keycreate_stub(thread_key_t *k, void (*d)(void *)) 275 { 276 int i; 277 278 for (i = __libc_tsd_nextkey; i < TSD_KEYS_MAX; i++) { 279 if (__libc_tsd[i].tsd_inuse == 0) 280 goto out; 281 } 282 283 for (i = 0; i < __libc_tsd_nextkey; i++) { 284 if (__libc_tsd[i].tsd_inuse == 0) 285 goto out; 286 } 287 288 return (EAGAIN); 289 290 out: 291 /* 292 * XXX We don't actually do anything with the destructor. We 293 * XXX probably should. 294 */ 295 __libc_tsd[i].tsd_inuse = 1; 296 __libc_tsd_nextkey = (i + i) % TSD_KEYS_MAX; 297 __libc_tsd[i].tsd_dtor = d; 298 *k = i; 299 300 return (0); 301 } 302 303 int 304 __libc_thr_setspecific_stub(thread_key_t k, const void *v) 305 { 306 307 __libc_tsd[k].tsd_val = __UNCONST(v); 308 309 return (0); 310 } 311 312 void * 313 __libc_thr_getspecific_stub(thread_key_t k) 314 { 315 316 return (__libc_tsd[k].tsd_val); 317 } 318 319 int 320 __libc_thr_keydelete_stub(thread_key_t k) 321 { 322 323 /* 324 * XXX Do not recycle key; see big comment in libpthread. 325 */ 326 327 __libc_tsd[k].tsd_dtor = NULL; 328 329 return (0); 330 } 331 332 333 /* misc. */ 334 335 __weak_alias(__libc_thr_once,__libc_thr_once_stub) 336 __weak_alias(__libc_thr_sigsetmask,__libc_thr_sigsetmask_stub) 337 __weak_alias(__libc_thr_self,__libc_thr_self_stub) 338 __weak_alias(__libc_thr_yield,__libc_thr_yield_stub) 339 __weak_alias(__libc_thr_create,__libc_thr_create_stub) 340 __weak_alias(__libc_thr_exit,__libc_thr_exit_stub) 341 __weak_alias(__libc_thr_setcancelstate,__libc_thr_setcancelstate_stub) 342 __weak_alias(__libc_thr_equal,__libc_thr_equal_stub) 343 __weak_alias(__libc_thr_curcpu,__libc_thr_curcpu_stub) 344 345 346 int 347 __libc_thr_once_stub(once_t *o, void (*r)(void)) 348 { 349 350 /* XXX Knowledge of libpthread types. */ 351 352 if (o->pto_done == 0) { 353 (*r)(); 354 o->pto_done = 1; 355 } 356 357 return (0); 358 } 359 360 int 361 __libc_thr_sigsetmask_stub(int h, const sigset_t *s, sigset_t *o) 362 { 363 364 CHECK_NOT_THREADED(); 365 366 return sigprocmask(h, s, o); 367 } 368 369 thr_t 370 __libc_thr_self_stub(void) 371 { 372 373 return ((thr_t) -1); 374 } 375 376 int 377 __libc_thr_yield_stub(void) 378 { 379 380 /* Nothing to do. */ 381 return (0); 382 } 383 384 int 385 __libc_thr_create_stub(thr_t *tp, const thrattr_t *ta, 386 void *(*f)(void *), void *a) 387 { 388 /* LINTED deliberate lack of effect */ 389 (void)tp; 390 /* LINTED deliberate lack of effect */ 391 (void)ta; 392 /* LINTED deliberate lack of effect */ 393 (void)f; 394 /* LINTED deliberate lack of effect */ 395 (void)a; 396 397 DIE(); 398 399 return (EOPNOTSUPP); 400 } 401 402 void 403 __libc_thr_exit_stub(void *v) 404 { 405 /* LINTED deliberate lack of effect */ 406 (void)v; 407 exit(0); 408 } 409 410 int 411 __libc_thr_setcancelstate_stub(int new, int *old) 412 { 413 /* LINTED deliberate lack of effect */ 414 (void)new; 415 416 /* LINTED deliberate lack of effect */ 417 (void)old; 418 419 CHECK_NOT_THREADED(); 420 421 return (0); 422 } 423 424 int 425 __libc_thr_equal_stub(pthread_t t1, pthread_t t2) 426 { 427 428 /* assert that t1=t2=pthread_self() */ 429 return (t1 == t2); 430 } 431 432 unsigned int 433 __libc_thr_curcpu_stub(void) 434 { 435 436 return (0); 437 } 438 439 #endif /* _REENTRANT */ 440