1 /* $NetBSD: thread-stub.c,v 1.14 2005/11/29 03:12:00 christos 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 #include <sys/cdefs.h> 40 #if defined(LIBC_SCCS) && !defined(lint) 41 __RCSID("$NetBSD: thread-stub.c,v 1.14 2005/11/29 03:12:00 christos Exp $"); 42 #endif /* LIBC_SCCS and not lint */ 43 44 /* 45 * Stubs for thread operations, for use when threads are not used by 46 * the application. See "reentrant.h" for details. 47 */ 48 49 #ifdef _REENTRANT 50 51 #define __LIBC_THREAD_STUBS 52 53 #include "namespace.h" 54 #include "reentrant.h" 55 56 #include <errno.h> 57 #include <signal.h> 58 #include <stdlib.h> 59 #include <unistd.h> 60 61 extern int __isthreaded; 62 63 #define DIE() (void)kill(getpid(), SIGABRT) 64 65 #define CHECK_NOT_THREADED_ALWAYS() \ 66 do { \ 67 if (__isthreaded) \ 68 DIE(); \ 69 } while (/*CONSTCOND*/0) 70 71 #if 1 72 #define CHECK_NOT_THREADED() CHECK_NOT_THREADED_ALWAYS() 73 #else 74 #define CHECK_NOT_THREADED() /* nothing */ 75 #endif 76 77 /* mutexes */ 78 79 int __libc_mutex_init_stub(mutex_t *, const mutexattr_t *); 80 int __libc_mutex_catchall_stub(mutex_t *); 81 82 __weak_alias(__libc_mutex_init,__libc_mutex_init_stub) 83 __weak_alias(__libc_mutex_lock,__libc_mutex_catchall_stub) 84 __weak_alias(__libc_mutex_trylock,__libc_mutex_catchall_stub) 85 __weak_alias(__libc_mutex_unlock,__libc_mutex_catchall_stub) 86 __weak_alias(__libc_mutex_destroy,__libc_mutex_catchall_stub) 87 88 int __libc_mutexattr_catchall_stub(mutexattr_t *); 89 int __libc_mutexattr_settype_stub(mutexattr_t *, int); 90 91 __weak_alias(__libc_mutexattr_init,__libc_mutexattr_catchall_stub) 92 __weak_alias(__libc_mutexattr_destroy,__libc_mutexattr_catchall_stub) 93 __weak_alias(__libc_mutexattr_settype,__libc_mutexattr_settype_stub) 94 95 int 96 __libc_mutex_init_stub(mutex_t *m, const mutexattr_t *a) 97 { 98 /* LINTED deliberate lack of effect */ 99 (void)m; 100 /* LINTED deliberate lack of effect */ 101 (void)a; 102 103 CHECK_NOT_THREADED(); 104 105 return (0); 106 } 107 108 int 109 __libc_mutex_catchall_stub(mutex_t *m) 110 { 111 /* LINTED deliberate lack of effect */ 112 (void)m; 113 114 CHECK_NOT_THREADED(); 115 116 return (0); 117 } 118 119 int 120 __libc_mutexattr_settype_stub(mutexattr_t *ma, int type) 121 { 122 /* LINTED deliberate lack of effect */ 123 (void)ma; 124 /* LINTED deliberate lack of effect */ 125 (void)type; 126 127 return (0); 128 } 129 130 int 131 __libc_mutexattr_catchall_stub(mutexattr_t *ma) 132 { 133 /* LINTED deliberate lack of effect */ 134 (void)ma; 135 136 CHECK_NOT_THREADED(); 137 138 return (0); 139 } 140 141 /* condition variables */ 142 143 int __libc_cond_init_stub(cond_t *, const condattr_t *); 144 int __libc_cond_wait_stub(cond_t *, mutex_t *); 145 int __libc_cond_timedwait_stub(cond_t *, mutex_t *, 146 const struct timespec *); 147 int __libc_cond_catchall_stub(cond_t *); 148 149 __weak_alias(__libc_cond_init,__libc_cond_init_stub) 150 __weak_alias(__libc_cond_signal,__libc_cond_catchall_stub) 151 __weak_alias(__libc_cond_broadcast,__libc_cond_catchall_stub) 152 __weak_alias(__libc_cond_wait,__libc_cond_wait_stub) 153 __weak_alias(__libc_cond_timedwait,__libc_cond_timedwait_stub) 154 __weak_alias(__libc_cond_destroy,__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_init_stub(rwlock_t *, rwlockattr_t *); 212 int __libc_rwlock_catchall_stub(rwlock_t *); 213 214 __weak_alias(__libc_rwlock_init,__libc_rwlock_init_stub) 215 __weak_alias(__libc_rwlock_rdlock,__libc_rwlock_catchall_stub) 216 __weak_alias(__libc_rwlock_wrlock,__libc_rwlock_catchall_stub) 217 __weak_alias(__libc_rwlock_tryrdlock,__libc_rwlock_catchall_stub) 218 __weak_alias(__libc_rwlock_trywrlock,__libc_rwlock_catchall_stub) 219 __weak_alias(__libc_rwlock_unlock,__libc_rwlock_catchall_stub) 220 __weak_alias(__libc_rwlock_destroy,__libc_rwlock_catchall_stub) 221 222 int 223 __libc_rwlock_init_stub(rwlock_t *l, rwlockattr_t *a) 224 { 225 /* LINTED deliberate lack of effect */ 226 (void)l; 227 /* LINTED deliberate lack of effect */ 228 (void)a; 229 230 CHECK_NOT_THREADED(); 231 232 return (0); 233 } 234 235 int 236 __libc_rwlock_catchall_stub(rwlock_t *l) 237 { 238 /* LINTED deliberate lack of effect */ 239 (void)l; 240 241 CHECK_NOT_THREADED(); 242 243 return (0); 244 } 245 246 247 /* 248 * thread-specific data; we need to actually provide a simple TSD 249 * implementation, since some thread-safe libraries want to use it. 250 */ 251 252 #define TSD_KEYS_MAX 64 253 254 static struct { 255 void *tsd_val; 256 void (*tsd_dtor)(void *); 257 int tsd_inuse; 258 } __libc_tsd[TSD_KEYS_MAX]; 259 static int __libc_tsd_nextkey; 260 261 int __libc_thr_keycreate_stub(thread_key_t *, void (*)(void *)); 262 int __libc_thr_setspecific_stub(thread_key_t, const void *); 263 void *__libc_thr_getspecific_stub(thread_key_t); 264 int __libc_thr_keydelete_stub(thread_key_t); 265 266 __weak_alias(__libc_thr_keycreate,__libc_thr_keycreate_stub) 267 __weak_alias(__libc_thr_setspecific,__libc_thr_setspecific_stub) 268 __weak_alias(__libc_thr_getspecific,__libc_thr_getspecific_stub) 269 __weak_alias(__libc_thr_keydelete,__libc_thr_keydelete_stub) 270 271 int 272 __libc_thr_keycreate_stub(thread_key_t *k, void (*d)(void *)) 273 { 274 int i; 275 276 for (i = __libc_tsd_nextkey; i < TSD_KEYS_MAX; i++) { 277 if (__libc_tsd[i].tsd_inuse == 0) 278 goto out; 279 } 280 281 for (i = 0; i < __libc_tsd_nextkey; i++) { 282 if (__libc_tsd[i].tsd_inuse == 0) 283 goto out; 284 } 285 286 return (EAGAIN); 287 288 out: 289 /* 290 * XXX We don't actually do anything with the destructor. We 291 * XXX probably should. 292 */ 293 __libc_tsd[i].tsd_inuse = 1; 294 __libc_tsd_nextkey = (i + i) % TSD_KEYS_MAX; 295 __libc_tsd[i].tsd_dtor = d; 296 *k = i; 297 298 return (0); 299 } 300 301 int 302 __libc_thr_setspecific_stub(thread_key_t k, const void *v) 303 { 304 305 __libc_tsd[k].tsd_val = __UNCONST(v); 306 307 return (0); 308 } 309 310 void * 311 __libc_thr_getspecific_stub(thread_key_t k) 312 { 313 314 return (__libc_tsd[k].tsd_val); 315 } 316 317 int 318 __libc_thr_keydelete_stub(thread_key_t k) 319 { 320 321 /* 322 * XXX Do not recycle key; see big comment in libpthread. 323 */ 324 325 __libc_tsd[k].tsd_dtor = NULL; 326 327 return (0); 328 } 329 330 331 /* misc. */ 332 333 int __libc_thr_once_stub(once_t *, void (*)(void)); 334 int __libc_thr_sigsetmask_stub(int, const sigset_t *, sigset_t *); 335 thr_t __libc_thr_self_stub(void); 336 int __libc_thr_yield_stub(void); 337 int __libc_thr_create_stub(thr_t *, const thrattr_t *, 338 void *(*)(void *), void *); 339 void __libc_thr_exit_stub(void *); 340 int *__libc_thr_errno_stub(void); 341 int __libc_thr_setcancelstate_stub(int, int *); 342 343 __weak_alias(__libc_thr_once,__libc_thr_once_stub) 344 __weak_alias(__libc_thr_sigsetmask,__libc_thr_sigsetmask_stub) 345 __weak_alias(__libc_thr_self,__libc_thr_self_stub) 346 __weak_alias(__libc_thr_yield,__libc_thr_yield_stub) 347 __weak_alias(__libc_thr_create,__libc_thr_create_stub) 348 __weak_alias(__libc_thr_exit,__libc_thr_exit_stub) 349 __weak_alias(__libc_thr_errno,__libc_thr_errno_stub) 350 __weak_alias(__libc_thr_setcancelstate,__libc_thr_setcancelstate_stub) 351 352 353 int 354 __libc_thr_once_stub(once_t *o, void (*r)(void)) 355 { 356 357 /* XXX Knowledge of libpthread types. */ 358 359 if (o->pto_done == 0) { 360 (*r)(); 361 o->pto_done = 1; 362 } 363 364 return (0); 365 } 366 367 int 368 __libc_thr_sigsetmask_stub(int h, const sigset_t *s, sigset_t *o) 369 { 370 371 CHECK_NOT_THREADED(); 372 373 return sigprocmask(h, s, o); 374 } 375 376 thr_t 377 __libc_thr_self_stub(void) 378 { 379 380 return ((thr_t) -1); 381 } 382 383 int 384 __libc_thr_yield_stub(void) 385 { 386 387 /* Nothing to do. */ 388 return (0); 389 } 390 391 int 392 __libc_thr_create_stub(thr_t *tp, const thrattr_t *ta, 393 void *(*f)(void *), void *a) 394 { 395 /* LINTED deliberate lack of effect */ 396 (void)tp; 397 /* LINTED deliberate lack of effect */ 398 (void)ta; 399 /* LINTED deliberate lack of effect */ 400 (void)f; 401 /* LINTED deliberate lack of effect */ 402 (void)a; 403 404 DIE(); 405 406 return (EOPNOTSUPP); 407 } 408 409 void 410 __libc_thr_exit_stub(void *v) 411 { 412 /* LINTED deliberate lack of effect */ 413 (void)v; 414 exit(0); 415 } 416 417 int 418 __libc_thr_setcancelstate_stub(int new, int *old) 419 { 420 /* LINTED deliberate lack of effect */ 421 (void)new; 422 423 /* LINTED deliberate lack of effect */ 424 (void)old; 425 426 CHECK_NOT_THREADED(); 427 428 return (0); 429 } 430 431 int * 432 __libc_thr_errno_stub(void) 433 { 434 435 DIE(); 436 437 return (NULL); 438 } 439 440 #endif /* _REENTRANT */ 441