1 /* $NetBSD: thread-stub.c,v 1.9 2003/07/18 21:44:38 nathanw Exp $ */ 2 3 /*- 4 * Copyright (c) 2003 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Stubs for thread operations, for use when threads are not used by 41 * the application. See "reentrant.h" for details. 42 */ 43 44 #ifdef _REENTRANT 45 46 #define __LIBC_THREAD_STUBS 47 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)kill(getpid(), 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 /* mutexes */ 73 74 int __libc_mutex_init_stub(mutex_t *, const mutexattr_t *); 75 int __libc_mutex_catchall_stub(mutex_t *); 76 77 __weak_alias(__libc_mutex_init,__libc_mutex_init_stub) 78 __weak_alias(__libc_mutex_lock,__libc_mutex_catchall_stub) 79 __weak_alias(__libc_mutex_trylock,__libc_mutex_catchall_stub) 80 __weak_alias(__libc_mutex_unlock,__libc_mutex_catchall_stub) 81 __weak_alias(__libc_mutex_destroy,__libc_mutex_catchall_stub) 82 83 int __libc_mutexattr_catchall_stub(mutexattr_t *); 84 int __libc_mutexattr_settype_stub(mutexattr_t *, int); 85 86 __weak_alias(__libc_mutexattr_init,__libc_mutexattr_catchall_stub) 87 __weak_alias(__libc_mutexattr_destroy,__libc_mutexattr_catchall_stub) 88 __weak_alias(__libc_mutexattr_settype,__libc_mutexattr_settype_stub) 89 90 int 91 __libc_mutex_init_stub(mutex_t *m, const mutexattr_t *a) 92 { 93 /* LINTED deliberate lack of effect */ 94 (void)m; 95 /* LINTED deliberate lack of effect */ 96 (void)a; 97 98 CHECK_NOT_THREADED(); 99 100 return (0); 101 } 102 103 int 104 __libc_mutex_catchall_stub(mutex_t *m) 105 { 106 /* LINTED deliberate lack of effect */ 107 (void)m; 108 109 CHECK_NOT_THREADED(); 110 111 return (0); 112 } 113 114 int 115 __libc_mutexattr_settype_stub(mutexattr_t *ma, int type) 116 { 117 /* LINTED deliberate lack of effect */ 118 (void)ma; 119 /* LINTED deliberate lack of effect */ 120 (void)type; 121 122 return (0); 123 } 124 125 int 126 __libc_mutexattr_catchall_stub(mutexattr_t *ma) 127 { 128 /* LINTED deliberate lack of effect */ 129 (void)ma; 130 131 CHECK_NOT_THREADED(); 132 133 return (0); 134 } 135 136 /* condition variables */ 137 138 int __libc_cond_init_stub(cond_t *, const condattr_t *); 139 int __libc_cond_wait_stub(cond_t *, mutex_t *); 140 int __libc_cond_timedwait_stub(cond_t *, mutex_t *, 141 const struct timespec *); 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 int 152 __libc_cond_init_stub(cond_t *c, const condattr_t *a) 153 { 154 /* LINTED deliberate lack of effect */ 155 (void)c; 156 /* LINTED deliberate lack of effect */ 157 (void)a; 158 159 CHECK_NOT_THREADED(); 160 161 return (0); 162 } 163 164 int 165 __libc_cond_wait_stub(cond_t *c, mutex_t *m) 166 { 167 /* LINTED deliberate lack of effect */ 168 (void)c; 169 /* LINTED deliberate lack of effect */ 170 (void)m; 171 172 CHECK_NOT_THREADED(); 173 174 return (0); 175 } 176 177 int 178 __libc_cond_timedwait_stub(cond_t *c, mutex_t *m, const struct timespec *t) 179 { 180 /* LINTED deliberate lack of effect */ 181 (void)c; 182 /* LINTED deliberate lack of effect */ 183 (void)m; 184 /* LINTED deliberate lack of effect */ 185 (void)t; 186 187 CHECK_NOT_THREADED(); 188 189 return (0); 190 } 191 192 int 193 __libc_cond_catchall_stub(cond_t *c) 194 { 195 /* LINTED deliberate lack of effect */ 196 (void)c; 197 198 CHECK_NOT_THREADED(); 199 200 return (0); 201 } 202 203 204 /* read-write locks */ 205 206 int __libc_rwlock_init_stub(rwlock_t *, rwlockattr_t *); 207 int __libc_rwlock_catchall_stub(rwlock_t *); 208 209 __weak_alias(__libc_rwlock_init,__libc_rwlock_init_stub) 210 __weak_alias(__libc_rwlock_rdlock,__libc_rwlock_catchall_stub) 211 __weak_alias(__libc_rwlock_wrlock,__libc_rwlock_catchall_stub) 212 __weak_alias(__libc_rwlock_tryrdlock,__libc_rwlock_catchall_stub) 213 __weak_alias(__libc_rwlock_trywrlock,__libc_rwlock_catchall_stub) 214 __weak_alias(__libc_rwlock_unlock,__libc_rwlock_catchall_stub) 215 __weak_alias(__libc_rwlock_destroy,__libc_rwlock_catchall_stub) 216 217 int 218 __libc_rwlock_init_stub(rwlock_t *l, rwlockattr_t *a) 219 { 220 /* LINTED deliberate lack of effect */ 221 (void)l; 222 /* LINTED deliberate lack of effect */ 223 (void)a; 224 225 CHECK_NOT_THREADED(); 226 227 return (0); 228 } 229 230 int 231 __libc_rwlock_catchall_stub(rwlock_t *l) 232 { 233 /* LINTED deliberate lack of effect */ 234 (void)l; 235 236 CHECK_NOT_THREADED(); 237 238 return (0); 239 } 240 241 242 /* 243 * thread-specific data; we need to actually provide a simple TSD 244 * implementation, since some thread-safe libraries want to use it. 245 */ 246 247 #define TSD_KEYS_MAX 64 248 249 static struct { 250 void *tsd_val; 251 void (*tsd_dtor)(void *); 252 int tsd_inuse; 253 } __libc_tsd[TSD_KEYS_MAX]; 254 static int __libc_tsd_nextkey; 255 256 int __libc_thr_keycreate_stub(thread_key_t *, void (*)(void *)); 257 int __libc_thr_setspecific_stub(thread_key_t, const void *); 258 void *__libc_thr_getspecific_stub(thread_key_t); 259 int __libc_thr_keydelete_stub(thread_key_t); 260 261 __weak_alias(__libc_thr_keycreate,__libc_thr_keycreate_stub) 262 __weak_alias(__libc_thr_setspecific,__libc_thr_setspecific_stub) 263 __weak_alias(__libc_thr_getspecific,__libc_thr_getspecific_stub) 264 __weak_alias(__libc_thr_keydelete,__libc_thr_keydelete_stub) 265 266 int 267 __libc_thr_keycreate_stub(thread_key_t *k, void (*d)(void *)) 268 { 269 int i; 270 271 for (i = __libc_tsd_nextkey; i < TSD_KEYS_MAX; i++) { 272 if (__libc_tsd[i].tsd_inuse == 0) 273 goto out; 274 } 275 276 for (i = 0; i < __libc_tsd_nextkey; i++) { 277 if (__libc_tsd[i].tsd_inuse == 0) 278 goto out; 279 } 280 281 return (EAGAIN); 282 283 out: 284 /* 285 * XXX We don't actually do anything with the destructor. We 286 * XXX probably should. 287 */ 288 __libc_tsd[i].tsd_inuse = 1; 289 __libc_tsd_nextkey = (i + i) % TSD_KEYS_MAX; 290 __libc_tsd[i].tsd_dtor = d; 291 *k = i; 292 293 return (0); 294 } 295 296 int 297 __libc_thr_setspecific_stub(thread_key_t k, const void *v) 298 { 299 300 /* LINTED cast away const */ 301 __libc_tsd[k].tsd_val = (void *) v; 302 303 return (0); 304 } 305 306 void * 307 __libc_thr_getspecific_stub(thread_key_t k) 308 { 309 310 return (__libc_tsd[k].tsd_val); 311 } 312 313 int 314 __libc_thr_keydelete_stub(thread_key_t k) 315 { 316 317 /* 318 * XXX Do not recycle key; see big comment in libpthread. 319 */ 320 321 __libc_tsd[k].tsd_dtor = NULL; 322 323 return (0); 324 } 325 326 327 /* misc. */ 328 329 int __libc_thr_once_stub(once_t *, void (*)(void)); 330 int __libc_thr_sigsetmask_stub(int, const sigset_t *, sigset_t *); 331 thr_t __libc_thr_self_stub(void); 332 void __libc_thr_yield_stub(void); 333 int __libc_thr_create_stub(thr_t *, const thrattr_t *, 334 void *(*)(void *), void *); 335 void __libc_thr_exit_stub(void *); 336 int *__libc_thr_errno_stub(void); 337 int __libc_thr_setcancelstate_stub(int, int *); 338 339 __weak_alias(__libc_thr_once,__libc_thr_once_stub) 340 __weak_alias(__libc_thr_sigsetmask,__libc_thr_sigsetmask_stub) 341 __weak_alias(__libc_thr_self,__libc_thr_self_stub) 342 __weak_alias(__libc_thr_yield,__libc_thr_yield_stub) 343 __weak_alias(__libc_thr_create,__libc_thr_create_stub) 344 __weak_alias(__libc_thr_exit,__libc_thr_exit_stub) 345 __weak_alias(__libc_thr_errno,__libc_thr_errno_stub) 346 __weak_alias(__libc_thr_setcancelstate,__libc_thr_setcancelstate_stub) 347 348 349 int 350 __libc_thr_once_stub(once_t *o, void (*r)(void)) 351 { 352 353 /* XXX Knowledge of libpthread types. */ 354 355 if (o->pto_done == 0) { 356 (*r)(); 357 o->pto_done = 1; 358 } 359 360 return (0); 361 } 362 363 int 364 __libc_thr_sigsetmask_stub(int h, const sigset_t *s, sigset_t *o) 365 { 366 /* LINTED deliberate lack of effect */ 367 (void)h; 368 /* LINTED deliberate lack of effect */ 369 (void)s; 370 /* LINTED deliberate lack of effect */ 371 (void)o; 372 373 CHECK_NOT_THREADED(); 374 375 /* XXX just use sigmask(2)? abort? */ 376 377 return (0); 378 } 379 380 thr_t 381 __libc_thr_self_stub(void) 382 { 383 384 return ((thr_t) -1); 385 } 386 387 void 388 __libc_thr_yield_stub(void) 389 { 390 391 /* Nothing to do. */ 392 } 393 394 int 395 __libc_thr_create_stub(thr_t *tp, const thrattr_t *ta, 396 void *(*f)(void *), void *a) 397 { 398 /* LINTED deliberate lack of effect */ 399 (void)tp; 400 /* LINTED deliberate lack of effect */ 401 (void)ta; 402 /* LINTED deliberate lack of effect */ 403 (void)f; 404 /* LINTED deliberate lack of effect */ 405 (void)a; 406 407 DIE(); 408 409 return (EOPNOTSUPP); 410 } 411 412 void 413 __libc_thr_exit_stub(void *v) 414 { 415 /* LINTED deliberate lack of effect */ 416 (void)v; 417 418 exit(0); 419 } 420 421 int 422 __libc_thr_setcancelstate_stub(int new, int *old) 423 { 424 /* LINTED deliberate lack of effect */ 425 (void)new; 426 427 /* LINTED deliberate lack of effect */ 428 (void)old; 429 430 CHECK_NOT_THREADED(); 431 432 return (0); 433 } 434 435 int * 436 __libc_thr_errno_stub(void) 437 { 438 439 DIE(); 440 441 return (NULL); 442 } 443 444 #endif /* _REENTRANT */ 445