1 /* 2 * Copyright (c) 2014 Philip Guenther <guenther@openbsd.org> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <pthread.h> 18 #include <signal.h> 19 #include <stdio.h> 20 #include <string.h> 21 #include <unistd.h> 22 23 #include "thread_private.h" 24 #include "rthread_cb.h" 25 26 static __dead void 27 _thread_canceled(void) 28 { 29 pthread_exit(PTHREAD_CANCELED); 30 } 31 32 void 33 _thread_set_callbacks(const struct thread_callbacks *cb, size_t len) 34 { 35 sigset_t allmask, omask; 36 37 if (sizeof(*cb) != len) { 38 fprintf(stderr, "library mismatch: libc expected %zu but" 39 " libpthread gave %zu\n", sizeof(*cb), len); 40 fflush(stderr); 41 _exit(44); 42 } 43 44 sigfillset(&allmask); 45 if (sigprocmask(SIG_BLOCK, &allmask, &omask) == 0) { 46 /* mprotect RW */ 47 memcpy(&_thread_cb, cb, sizeof(_thread_cb)); 48 49 /* 50 * These are supplied by libc, but only enabled 51 * here when we actually need to prep for doing MT. 52 */ 53 _thread_cb.tc_canceled = _thread_canceled; 54 _thread_cb.tc_flockfile = _thread_flockfile; 55 _thread_cb.tc_ftrylockfile = _thread_ftrylockfile; 56 _thread_cb.tc_funlockfile = _thread_funlockfile; 57 _thread_cb.tc_malloc_lock = _thread_malloc_lock; 58 _thread_cb.tc_malloc_unlock = _thread_malloc_unlock; 59 _thread_cb.tc_atexit_lock = _thread_atexit_lock; 60 _thread_cb.tc_atexit_unlock = _thread_atexit_unlock; 61 _thread_cb.tc_atfork_lock = _thread_atfork_lock; 62 _thread_cb.tc_atfork_unlock = _thread_atfork_unlock; 63 _thread_cb.tc_arc4_lock = _thread_arc4_lock; 64 _thread_cb.tc_arc4_unlock = _thread_arc4_unlock; 65 _thread_cb.tc_mutex_lock = _thread_mutex_lock; 66 _thread_cb.tc_mutex_unlock = _thread_mutex_unlock; 67 _thread_cb.tc_mutex_destroy = _thread_mutex_destroy; 68 _thread_cb.tc_tag_lock = _thread_tag_lock; 69 _thread_cb.tc_tag_unlock = _thread_tag_unlock; 70 _thread_cb.tc_tag_storage = _thread_tag_storage; 71 72 /* mprotect RO | LOCKPERM | NOUNMAP */ 73 sigprocmask(SIG_SETMASK, &omask, NULL); 74 } 75 } 76