1 /* $NetBSD: thread-stub.c,v 1.7 2003/01/20 01:58:54 thorpej 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 <unistd.h> 54 55 extern int __isthreaded; 56 57 #define DIE() (void)kill(getpid(), SIGABRT) 58 59 #define CHECK_NOT_THREADED_ALWAYS() \ 60 do { \ 61 if (__isthreaded) \ 62 DIE(); \ 63 } while (/*CONSTCOND*/0) 64 65 #if 1 66 #define CHECK_NOT_THREADED() CHECK_NOT_THREADED_ALWAYS() 67 #else 68 #define CHECK_NOT_THREADED() /* nothing */ 69 #endif 70 71 /* mutexes */ 72 73 int __libc_mutex_init_stub(mutex_t *, const mutexattr_t *); 74 int __libc_mutex_catchall_stub(mutex_t *); 75 76 __weak_alias(__libc_mutex_init,__libc_mutex_init_stub) 77 __weak_alias(__libc_mutex_lock,__libc_mutex_catchall_stub) 78 __weak_alias(__libc_mutex_trylock,__libc_mutex_catchall_stub) 79 __weak_alias(__libc_mutex_unlock,__libc_mutex_catchall_stub) 80 __weak_alias(__libc_mutex_destroy,__libc_mutex_catchall_stub) 81 82 int __libc_mutexattr_catchall_stub(mutexattr_t *); 83 int __libc_mutexattr_settype_stub(mutexattr_t *, int); 84 85 __weak_alias(__libc_mutexattr_init,__libc_mutexattr_catchall_stub) 86 __weak_alias(__libc_mutexattr_destroy,__libc_mutexattr_catchall_stub) 87 __weak_alias(__libc_mutexattr_settype,__libc_mutexattr_settype_stub) 88 89 int 90 __libc_mutex_init_stub(mutex_t *m, const mutexattr_t *a) 91 { 92 /* LINTED deliberate lack of effect */ 93 (void)m; 94 /* LINTED deliberate lack of effect */ 95 (void)a; 96 97 CHECK_NOT_THREADED(); 98 99 return (0); 100 } 101 102 int 103 __libc_mutex_catchall_stub(mutex_t *m) 104 { 105 /* LINTED deliberate lack of effect */ 106 (void)m; 107 108 CHECK_NOT_THREADED(); 109 110 return (0); 111 } 112 113 int 114 __libc_mutexattr_settype_stub(mutexattr_t *ma, int type) 115 { 116 /* LINTED deliberate lack of effect */ 117 (void)ma; 118 /* LINTED deliberate lack of effect */ 119 (void)type; 120 121 return (0); 122 } 123 124 int 125 __libc_mutexattr_catchall_stub(mutexattr_t *ma) 126 { 127 /* LINTED deliberate lack of effect */ 128 (void)ma; 129 130 CHECK_NOT_THREADED(); 131 132 return (0); 133 } 134 135 /* condition variables */ 136 137 int __libc_cond_init_stub(cond_t *, const condattr_t *); 138 int __libc_cond_wait_stub(cond_t *, mutex_t *); 139 int __libc_cond_timedwait_stub(cond_t *, mutex_t *, 140 const struct timespec *); 141 int __libc_cond_catchall_stub(cond_t *); 142 143 __weak_alias(__libc_cond_init,__libc_cond_init_stub) 144 __weak_alias(__libc_cond_signal,__libc_cond_catchall_stub) 145 __weak_alias(__libc_cond_broadcast,__libc_cond_catchall_stub) 146 __weak_alias(__libc_cond_wait,__libc_cond_wait_stub) 147 __weak_alias(__libc_cond_timedwait,__libc_cond_timedwait_stub) 148 __weak_alias(__libc_cond_destroy,__libc_cond_catchall_stub) 149 150 int 151 __libc_cond_init_stub(cond_t *c, const condattr_t *a) 152 { 153 /* LINTED deliberate lack of effect */ 154 (void)c; 155 /* LINTED deliberate lack of effect */ 156 (void)a; 157 158 CHECK_NOT_THREADED(); 159 160 return (0); 161 } 162 163 int 164 __libc_cond_wait_stub(cond_t *c, mutex_t *m) 165 { 166 /* LINTED deliberate lack of effect */ 167 (void)c; 168 /* LINTED deliberate lack of effect */ 169 (void)m; 170 171 CHECK_NOT_THREADED(); 172 173 return (0); 174 } 175 176 int 177 __libc_cond_timedwait_stub(cond_t *c, mutex_t *m, const struct timespec *t) 178 { 179 /* LINTED deliberate lack of effect */ 180 (void)c; 181 /* LINTED deliberate lack of effect */ 182 (void)m; 183 /* LINTED deliberate lack of effect */ 184 (void)t; 185 186 CHECK_NOT_THREADED(); 187 188 return (0); 189 } 190 191 int 192 __libc_cond_catchall_stub(cond_t *c) 193 { 194 /* LINTED deliberate lack of effect */ 195 (void)c; 196 197 CHECK_NOT_THREADED(); 198 199 return (0); 200 } 201 202 203 /* read-write locks */ 204 205 int __libc_rwlock_init_stub(rwlock_t *, rwlockattr_t *); 206 int __libc_rwlock_catchall_stub(rwlock_t *); 207 208 __weak_alias(__libc_rwlock_init,__libc_rwlock_init_stub) 209 __weak_alias(__libc_rwlock_rdlock,__libc_rwlock_catchall_stub) 210 __weak_alias(__libc_rwlock_wrlock,__libc_rwlock_catchall_stub) 211 __weak_alias(__libc_rwlock_tryrdlock,__libc_rwlock_catchall_stub) 212 __weak_alias(__libc_rwlock_trywrlock,__libc_rwlock_catchall_stub) 213 __weak_alias(__libc_rwlock_unlock,__libc_rwlock_catchall_stub) 214 __weak_alias(__libc_rwlock_destroy,__libc_rwlock_catchall_stub) 215 216 int 217 __libc_rwlock_init_stub(rwlock_t *l, rwlockattr_t *a) 218 { 219 /* LINTED deliberate lack of effect */ 220 (void)l; 221 /* LINTED deliberate lack of effect */ 222 (void)a; 223 224 CHECK_NOT_THREADED(); 225 226 return (0); 227 } 228 229 int 230 __libc_rwlock_catchall_stub(rwlock_t *l) 231 { 232 /* LINTED deliberate lack of effect */ 233 (void)l; 234 235 CHECK_NOT_THREADED(); 236 237 return (0); 238 } 239 240 241 /* 242 * thread-specific data; we need to actually provide a simple TSD 243 * implementation, since some thread-safe libraries want to use it. 244 */ 245 246 #define TSD_KEYS_MAX 64 247 248 static struct { 249 void *tsd_val; 250 void (*tsd_dtor)(void *); 251 int tsd_inuse; 252 } __libc_tsd[TSD_KEYS_MAX]; 253 static int __libc_tsd_nextkey; 254 255 int __libc_thr_keycreate_stub(thread_key_t *, void (*)(void *)); 256 int __libc_thr_setspecific_stub(thread_key_t, const void *); 257 void *__libc_thr_getspecific_stub(thread_key_t); 258 int __libc_thr_keydelete_stub(thread_key_t); 259 260 __weak_alias(__libc_thr_keycreate,__libc_thr_keycreate_stub) 261 __weak_alias(__libc_thr_setspecific,__libc_thr_setspecific_stub) 262 __weak_alias(__libc_thr_getspecific,__libc_thr_getspecific_stub) 263 __weak_alias(__libc_thr_keydelete,__libc_thr_keydelete_stub) 264 265 int 266 __libc_thr_keycreate_stub(thread_key_t *k, void (*d)(void *)) 267 { 268 int i; 269 270 for (i = __libc_tsd_nextkey; i < TSD_KEYS_MAX; i++) { 271 if (__libc_tsd[i].tsd_inuse == 0) 272 goto out; 273 } 274 275 for (i = 0; i < __libc_tsd_nextkey; i++) { 276 if (__libc_tsd[i].tsd_inuse == 0) 277 goto out; 278 } 279 280 return (EAGAIN); 281 282 out: 283 /* 284 * XXX We don't actually do anything with the destructor. We 285 * XXX probably should. 286 */ 287 __libc_tsd[i].tsd_inuse = 1; 288 __libc_tsd_nextkey = (i + i) % TSD_KEYS_MAX; 289 __libc_tsd[i].tsd_dtor = d; 290 *k = i; 291 292 return (0); 293 } 294 295 int 296 __libc_thr_setspecific_stub(thread_key_t k, const void *v) 297 { 298 299 /* LINTED cast away const */ 300 __libc_tsd[k].tsd_val = (void *) v; 301 302 return (0); 303 } 304 305 void * 306 __libc_thr_getspecific_stub(thread_key_t k) 307 { 308 309 return (__libc_tsd[k].tsd_val); 310 } 311 312 int 313 __libc_thr_keydelete_stub(thread_key_t k) 314 { 315 316 /* 317 * XXX Do not recycle key; see big comment in libpthread. 318 */ 319 320 __libc_tsd[k].tsd_dtor = NULL; 321 322 return (0); 323 } 324 325 326 /* misc. */ 327 328 int __libc_thr_once_stub(once_t *, void (*)(void)); 329 int __libc_thr_sigsetmask_stub(int, const sigset_t *, sigset_t *); 330 thr_t __libc_thr_self_stub(void); 331 void __libc_thr_yield_stub(void); 332 int __libc_thr_create_stub(thr_t *, const thrattr_t *, 333 void *(*)(void *), void *); 334 void __libc_thr_exit_stub(void *); 335 int *__libc_thr_errno_stub(void); 336 337 __weak_alias(__libc_thr_once,__libc_thr_once_stub) 338 __weak_alias(__libc_thr_sigsetmask,__libc_thr_sigsetmask_stub) 339 __weak_alias(__libc_thr_self,__libc_thr_self_stub) 340 __weak_alias(__libc_thr_yield,__libc_thr_yield_stub) 341 __weak_alias(__libc_thr_create,__libc_thr_create_stub) 342 __weak_alias(__libc_thr_exit,__libc_thr_exit_stub) 343 __weak_alias(__libc_thr_errno,__libc_thr_errno_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 /* LINTED deliberate lack of effect */ 364 (void)h; 365 /* LINTED deliberate lack of effect */ 366 (void)s; 367 /* LINTED deliberate lack of effect */ 368 (void)o; 369 370 CHECK_NOT_THREADED(); 371 372 /* XXX just use sigmask(2)? abort? */ 373 374 return (0); 375 } 376 377 thr_t 378 __libc_thr_self_stub(void) 379 { 380 381 return ((thr_t) -1); 382 } 383 384 void 385 __libc_thr_yield_stub(void) 386 { 387 388 /* Nothing to do. */ 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 415 exit(0); 416 } 417 418 int * 419 __libc_thr_errno_stub(void) 420 { 421 422 DIE(); 423 424 return (NULL); 425 } 426 427 #endif /* _REENTRANT */ 428