1 /* 2 * Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <signal.h> 31 #include <pthread.h> 32 33 #include "libc_private.h" 34 35 /* 36 * Weak symbols: All libc internal usage of these functions should 37 * use the weak symbol versions (_pthread_XXX). If libpthread is 38 * linked, it will override these functions with (non-weak) routines. 39 * The _pthread_XXX functions are provided solely for internal libc 40 * usage to avoid unwanted cancellation points and to differentiate 41 * between application locks and libc locks (threads holding the 42 * latter can't be allowed to exit/terminate). 43 */ 44 45 /* Define a null pthread structure just to satisfy _pthread_self. */ 46 struct pthread { 47 }; 48 49 static struct pthread main_thread; 50 51 static int stub_main(void); 52 static void *stub_null(void); 53 static struct pthread *stub_self(void); 54 static int stub_zero(void); 55 56 #define PJT_DUAL_ENTRY(entry) \ 57 (pthread_func_t)entry, (pthread_func_t)entry 58 59 pthread_func_entry_t __thr_jtable[PJT_MAX] = { 60 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_BROADCAST */ 61 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_DESTROY */ 62 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_INIT */ 63 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_SIGNAL */ 64 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_WAIT */ 65 {PJT_DUAL_ENTRY(stub_null)}, /* PJT_GETSPECIFIC */ 66 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_KEY_CREATE */ 67 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_KEY_DELETE */ 68 {PJT_DUAL_ENTRY(stub_main)}, /* PJT_MAIN_NP */ 69 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_DESTROY */ 70 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_INIT */ 71 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_LOCK */ 72 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_TRYLOCK */ 73 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_UNLOCK */ 74 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEXATTR_DESTROY */ 75 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEXATTR_INIT */ 76 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEXATTR_SETTYPE */ 77 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ONCE */ 78 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_DESTROY */ 79 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_INIT */ 80 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_RDLOCK */ 81 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_TRYRDLOCK */ 82 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_TRYWRLOCK */ 83 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_UNLOCK */ 84 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_WRLOCK */ 85 {PJT_DUAL_ENTRY(stub_self)}, /* PJT_SELF */ 86 {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_SETSPECIFIC */ 87 {PJT_DUAL_ENTRY(stub_zero)} /* PJT_SIGMASK */ 88 }; 89 90 /* 91 * Weak aliases for exported (pthread_*) and internal (_pthread_*) routines. 92 */ 93 #define WEAK_REF(sym, alias) __weak_reference(sym, alias) 94 95 #define FUNC_TYPE(name) __CONCAT(name, _func_t) 96 #define FUNC_INT(name) __CONCAT(name, _int) 97 #define FUNC_EXP(name) __CONCAT(name, _exp) 98 99 #define STUB_FUNC(name, idx, ret) \ 100 static ret FUNC_EXP(name)(void) __used; \ 101 static ret FUNC_INT(name)(void) __used; \ 102 WEAK_REF(FUNC_EXP(name), name); \ 103 WEAK_REF(FUNC_INT(name), __CONCAT(_, name)); \ 104 typedef ret (*FUNC_TYPE(name))(void); \ 105 static ret FUNC_EXP(name)(void) \ 106 { \ 107 FUNC_TYPE(name) func; \ 108 func = (FUNC_TYPE(name))__thr_jtable[idx][0]; \ 109 return (func()); \ 110 } \ 111 static ret FUNC_INT(name)(void) \ 112 { \ 113 FUNC_TYPE(name) func; \ 114 func = (FUNC_TYPE(name))__thr_jtable[idx][1]; \ 115 return (func()); \ 116 } 117 118 #define STUB_FUNC1(name, idx, ret, p0_type) \ 119 static ret FUNC_EXP(name)(p0_type) __used; \ 120 static ret FUNC_INT(name)(p0_type) __used; \ 121 WEAK_REF(FUNC_EXP(name), name); \ 122 WEAK_REF(FUNC_INT(name), __CONCAT(_, name)); \ 123 typedef ret (*FUNC_TYPE(name))(p0_type); \ 124 static ret FUNC_EXP(name)(p0_type p0) \ 125 { \ 126 FUNC_TYPE(name) func; \ 127 func = (FUNC_TYPE(name))__thr_jtable[idx][0]; \ 128 return (func(p0)); \ 129 } \ 130 static ret FUNC_INT(name)(p0_type p0) \ 131 { \ 132 FUNC_TYPE(name) func; \ 133 func = (FUNC_TYPE(name))__thr_jtable[idx][1]; \ 134 return (func(p0)); \ 135 } 136 137 #define STUB_FUNC2(name, idx, ret, p0_type, p1_type) \ 138 static ret FUNC_EXP(name)(p0_type, p1_type) __used; \ 139 static ret FUNC_INT(name)(p0_type, p1_type) __used; \ 140 WEAK_REF(FUNC_EXP(name), name); \ 141 WEAK_REF(FUNC_INT(name), __CONCAT(_, name)); \ 142 typedef ret (*FUNC_TYPE(name))(p0_type, p1_type); \ 143 static ret FUNC_EXP(name)(p0_type p0, p1_type p1) \ 144 { \ 145 FUNC_TYPE(name) func; \ 146 func = (FUNC_TYPE(name))__thr_jtable[idx][0]; \ 147 return (func(p0, p1)); \ 148 } \ 149 static ret FUNC_INT(name)(p0_type p0, p1_type p1) \ 150 { \ 151 FUNC_TYPE(name) func; \ 152 func = (FUNC_TYPE(name))__thr_jtable[idx][1]; \ 153 return (func(p0, p1)); \ 154 } 155 156 #define STUB_FUNC3(name, idx, ret, p0_type, p1_type, p2_type) \ 157 static ret FUNC_EXP(name)(p0_type, p1_type, p2_type) __used; \ 158 static ret FUNC_INT(name)(p0_type, p1_type, p2_type) __used; \ 159 WEAK_REF(FUNC_EXP(name), name); \ 160 WEAK_REF(FUNC_INT(name), __CONCAT(_, name)); \ 161 typedef ret (*FUNC_TYPE(name))(p0_type, p1_type, p2_type); \ 162 static ret FUNC_EXP(name)(p0_type p0, p1_type p1, p2_type p2) \ 163 { \ 164 FUNC_TYPE(name) func; \ 165 func = (FUNC_TYPE(name))__thr_jtable[idx][0]; \ 166 return (func(p0, p1, p2)); \ 167 } \ 168 static ret FUNC_INT(name)(p0_type p0, p1_type p1, p2_type p2) \ 169 { \ 170 FUNC_TYPE(name) func; \ 171 func = (FUNC_TYPE(name))__thr_jtable[idx][1]; \ 172 return (func(p0, p1, p2)); \ 173 } 174 175 STUB_FUNC1(pthread_cond_broadcast, PJT_COND_BROADCAST, int, void *) 176 STUB_FUNC1(pthread_cond_destroy, PJT_COND_DESTROY, int, void *) 177 STUB_FUNC2(pthread_cond_init, PJT_COND_INIT, int, void *, void *) 178 STUB_FUNC1(pthread_cond_signal, PJT_COND_SIGNAL, int, void *) 179 STUB_FUNC1(pthread_cond_wait, PJT_COND_WAIT, int, void *) 180 STUB_FUNC1(pthread_getspecific, PJT_GETSPECIFIC, void *, pthread_key_t) 181 STUB_FUNC2(pthread_key_create, PJT_KEY_CREATE, int, void *, void *) 182 STUB_FUNC1(pthread_key_delete, PJT_KEY_DELETE, int, pthread_key_t) 183 STUB_FUNC(pthread_main_np, PJT_MAIN_NP, int) 184 STUB_FUNC1(pthread_mutex_destroy, PJT_MUTEX_DESTROY, int, void *) 185 STUB_FUNC2(pthread_mutex_init, PJT_MUTEX_INIT, int, void *, void *) 186 STUB_FUNC1(pthread_mutex_lock, PJT_MUTEX_LOCK, int, void *) 187 STUB_FUNC1(pthread_mutex_trylock, PJT_MUTEX_TRYLOCK, int, void *) 188 STUB_FUNC1(pthread_mutex_unlock, PJT_MUTEX_UNLOCK, int, void *) 189 STUB_FUNC1(pthread_mutexattr_destroy, PJT_MUTEXATTR_DESTROY, int, void *) 190 STUB_FUNC1(pthread_mutexattr_init, PJT_MUTEXATTR_INIT, int, void *) 191 STUB_FUNC1(pthread_mutexattr_settype, PJT_MUTEXATTR_SETTYPE, int, void *) 192 STUB_FUNC2(pthread_once, PJT_ONCE, int, void *, void *) 193 STUB_FUNC1(pthread_rwlock_destroy, PJT_RWLOCK_DESTROY, int, void *) 194 STUB_FUNC2(pthread_rwlock_init, PJT_RWLOCK_INIT, int, void *, void *) 195 STUB_FUNC1(pthread_rwlock_rdlock, PJT_RWLOCK_RDLOCK, int, void *) 196 STUB_FUNC1(pthread_rwlock_tryrdlock, PJT_RWLOCK_TRYRDLOCK, int, void *) 197 STUB_FUNC1(pthread_rwlock_trywrlock, PJT_RWLOCK_TRYWRLOCK, int, void *) 198 STUB_FUNC1(pthread_rwlock_unlock, PJT_RWLOCK_UNLOCK, int, void *) 199 STUB_FUNC1(pthread_rwlock_wrlock, PJT_RWLOCK_WRLOCK, int, void *) 200 STUB_FUNC(pthread_self, PJT_SELF, pthread_t) 201 STUB_FUNC2(pthread_setspecific, PJT_SETSPECIFIC, int, pthread_key_t, void *) 202 STUB_FUNC3(pthread_sigmask, PJT_SIGMASK, int, int, void *, void *) 203 204 static int 205 stub_zero(void) 206 { 207 return (0); 208 } 209 210 static void * 211 stub_null(void) 212 { 213 return (NULL); 214 } 215 216 static struct pthread * 217 stub_self(void) 218 { 219 return (&main_thread); 220 } 221 222 static int 223 stub_main(void) 224 { 225 return (-1); 226 } 227