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