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