1 1.1.1.3 christos /* Copyright (C) 2021-2025 Free Software Foundation, Inc. 2 1.1 christos Contributed by Oracle. 3 1.1 christos 4 1.1 christos This file is part of GNU Binutils. 5 1.1 christos 6 1.1 christos This program is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3, or (at your option) 9 1.1 christos any later version. 10 1.1 christos 11 1.1 christos This program is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 christos GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with this program; if not, write to the Free Software 18 1.1 christos Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 1.1 christos MA 02110-1301, USA. */ 20 1.1 christos 21 1.1 christos /* 22 1.1 christos * Central SIGPROF dispatcher to various module event handlers 23 1.1 christos * (REALPROF profile, HWC check, overview sample, manual sample) 24 1.1 christos */ 25 1.1 christos 26 1.1 christos #include "config.h" 27 1.1 christos #include <dlfcn.h> 28 1.1 christos #include <errno.h> 29 1.1 christos #include <fcntl.h> 30 1.1 christos #include <unistd.h> 31 1.1 christos #include <stdlib.h> 32 1.1 christos #include <string.h> 33 1.1 christos #include <sys/param.h> 34 1.1 christos #include <sys/syscall.h> 35 1.1 christos #include <time.h> 36 1.1 christos #include <signal.h> 37 1.1 christos 38 1.1 christos #include "gp-defs.h" 39 1.1 christos #include "gp-experiment.h" 40 1.1 christos #include "collector.h" 41 1.1 christos #include "collector_module.h" 42 1.1 christos #include "tsd.h" 43 1.1 christos #include "hwcdrv.h" 44 1.1.1.2 christos #include "memmgr.h" 45 1.1 christos 46 1.1 christos static void collector_sigprof_dispatcher (int, siginfo_t*, void*); 47 1.1 christos static int init_interposition_intf (); 48 1.1 christos static int collector_timer_create (timer_t * ptimerid); 49 1.1 christos static int collector_timer_settime (int period, timer_t timerid); 50 1.1 christos static int collector_timer_gettime (timer_t timerid); 51 1.1 christos static volatile int collector_sigprof_entries = 0; /* counter for SIGPROF signals in DISPATCH_TST mode */ 52 1.1 christos static timer_t collector_master_thread_timerid = NULL; 53 1.1 christos static collector_mutex_t collector_clone_libc_lock = COLLECTOR_MUTEX_INITIALIZER; 54 1.1 christos static unsigned dispatcher_key = COLLECTOR_TSD_INVALID_KEY; 55 1.1 christos 56 1.1.1.2 christos static int (*__real_clone) (int (*fn)(void *), void *child_stack, int flags, 57 1.1.1.2 christos void *arg, ...) = NULL; 58 1.1.1.2 christos static int (*__real_timer_create) (clockid_t clockid, 59 1.1.1.2 christos struct sigevent *sevp, timer_t *timerid) = NULL; 60 1.1.1.2 christos static int (*__real_timer_settime) (timer_t timerid, int flags, 61 1.1.1.2 christos const struct itimerspec *new_value, 62 1.1.1.2 christos struct itimerspec *old_value) = NULL; 63 1.1.1.2 christos static int (*__real_timer_delete) (timer_t timerid) = NULL; 64 1.1.1.2 christos static int (*__real_timer_gettime) (timer_t timerid, 65 1.1.1.2 christos struct itimerspec *curr_value) = NULL; 66 1.1.1.2 christos 67 1.1.1.2 christos static int (*__real_pthread_create_2_34) (pthread_t *thread, 68 1.1.1.2 christos const pthread_attr_t *attr, 69 1.1.1.2 christos void *(*start_routine) (void *), void *arg) = NULL; 70 1.1.1.2 christos static int (*__real_pthread_create_2_17) (pthread_t *thread, 71 1.1.1.2 christos const pthread_attr_t *attr, 72 1.1.1.2 christos void *(*start_routine) (void *), void *arg) = NULL; 73 1.1.1.2 christos static int (*__real_pthread_create_2_2_5) (pthread_t *thread, 74 1.1.1.2 christos const pthread_attr_t *attr, 75 1.1.1.2 christos void *(*start_routine) (void *), void *arg) = NULL; 76 1.1.1.2 christos static int (*__real_pthread_create_2_1) (pthread_t *thread, 77 1.1.1.2 christos const pthread_attr_t *attr, 78 1.1.1.2 christos void *(*start_routine) (void *), void *arg) = NULL; 79 1.1.1.2 christos static int (*__real_pthread_create_2_0) (pthread_t *thread, 80 1.1.1.2 christos const pthread_attr_t *attr, 81 1.1.1.2 christos void *(*start_routine) (void *), void *arg) = NULL; 82 1.1.1.2 christos 83 1.1.1.2 christos static int (*__real_timer_create_2_34) (clockid_t clockid, 84 1.1.1.2 christos struct sigevent *sevp, timer_t *timerid) = NULL; 85 1.1.1.2 christos static int (*__real_timer_create_2_17) (clockid_t clockid, 86 1.1.1.2 christos struct sigevent *sevp, timer_t *timerid) = NULL; 87 1.1.1.2 christos static int (*__real_timer_create_2_3_3) (clockid_t clockid, 88 1.1.1.2 christos struct sigevent *sevp, timer_t *timerid) = NULL; 89 1.1.1.2 christos static int (*__real_timer_create_2_2_5) (clockid_t clockid, 90 1.1.1.2 christos struct sigevent *sevp, timer_t *timerid) = NULL; 91 1.1.1.2 christos static int (*__real_timer_create_2_2) (clockid_t clockid, 92 1.1.1.2 christos struct sigevent *sevp, timer_t *timerid) = NULL; 93 1.1.1.2 christos 94 1.1.1.2 christos int (*__real_pthread_sigmask_2_32) (int, const sigset_t *, sigset_t *) = NULL; 95 1.1.1.2 christos int (*__real_pthread_sigmask_2_17) (int, const sigset_t *, sigset_t *) = NULL; 96 1.1.1.2 christos int (*__real_pthread_sigmask_2_2_5) (int, const sigset_t *, sigset_t *) = NULL; 97 1.1.1.2 christos int (*__real_pthread_sigmask_2_0) (int, const sigset_t *, sigset_t *) = NULL; 98 1.1.1.2 christos 99 1.1 christos 100 1.1 christos /* Original SIGPROF handler which will be replaced with the dispatcher. Used 101 1.1 christos * to properly interact with libaio, which uses SIGPROF as its SIGAIOCANCEL. */ 102 1.1 christos static struct sigaction original_sigprof_handler; 103 1.1 christos 104 1.1 christos enum 105 1.1 christos { 106 1.1 christos DISPATCH_NYI = -1, /* dispatcher not yet installed */ 107 1.1 christos DISPATCH_OFF = 0, /* dispatcher installed, but disabled */ 108 1.1 christos DISPATCH_ON = 1, /* dispatcher installed, and enabled */ 109 1.1 christos DISPATCH_TST = 2 /* dispatcher installed, and enabled in testing mode */ 110 1.1 christos }; 111 1.1 christos 112 1.1.1.3 christos static struct sigaction sigaction_0; 113 1.1 christos static int dispatch_mode = DISPATCH_NYI; /* controls SIGPROF dispatching */ 114 1.1 christos static int itimer_period_requested = 0; /* dispatcher itimer period */ 115 1.1 christos static int itimer_period_actual = 0; /* actual dispatcher itimer period */ 116 1.1 christos 117 1.1.1.2 christos static int (*__real_sigaction) (int signum, const struct sigaction *act, 118 1.1.1.2 christos struct sigaction *oldact) = NULL; 119 1.1.1.2 christos static int (*__real_setitimer) (int which, const struct itimerval *new_value, 120 1.1.1.2 christos struct itimerval *old_value) = NULL; 121 1.1.1.2 christos static int (*__real_libc_setitimer) (int which, 122 1.1.1.2 christos const struct itimerval *new_value, struct itimerval *old_value) = NULL; 123 1.1.1.2 christos static int (*__real_sigprocmask) (int how, const sigset_t *set, 124 1.1.1.2 christos sigset_t *oldset) = NULL; 125 1.1.1.2 christos static int (*__real_thr_sigsetmask) (int how, const sigset_t *iset, 126 1.1.1.2 christos sigset_t *oset) = NULL; 127 1.1.1.2 christos static int (*__real_pthread_sigmask) (int how, const sigset_t *set, 128 1.1.1.2 christos sigset_t *oldset) = NULL; 129 1.1.1.2 christos static int (*__real_pthread_create) (pthread_t *thread, 130 1.1.1.2 christos const pthread_attr_t *attr, 131 1.1.1.2 christos void *(*start_routine) (void *), void *arg) = NULL; 132 1.1 christos 133 1.1 christos /* 134 1.1 christos * void collector_sigprof_dispatcher() 135 1.1 christos * 136 1.1 christos * Common SIGPROF event handler which dispatches events to appropriate 137 1.1 christos * module handlers, if they are active for this collection and due. 138 1.1 christos * Dispatch sequence, logic and handlers currently hardcoded in dispatcher. 139 1.1 christos */ 140 1.1 christos static void 141 1.1 christos collector_sigprof_dispatcher (int sig, siginfo_t *info, void *context) 142 1.1 christos { 143 1.1 christos if (info == NULL || (info->si_code <= 0 && info->si_code != SI_TIMER)) 144 1.1 christos { 145 1.1 christos TprintfT (DBG_LT2, "collector_sigprof_dispatcher signal for %p\n", 146 1.1 christos original_sigprof_handler.sa_handler); 147 1.1 christos /* pass signal to previous handler */ 148 1.1 christos /* watch for recursion, SIG_IGN, and SIG_DFL */ 149 1.1 christos if (original_sigprof_handler.sa_handler == SIG_DFL) 150 1.1 christos __collector_SIGDFL_handler (SIGPROF); 151 1.1 christos else if (original_sigprof_handler.sa_handler != SIG_IGN && 152 1.1 christos original_sigprof_handler.sa_sigaction != &collector_sigprof_dispatcher) 153 1.1 christos { 154 1.1 christos (original_sigprof_handler.sa_sigaction)(sig, info, context); 155 1.1 christos TprintfT (DBG_LT2, "collector_sigprof_dispatcher handled\n"); 156 1.1 christos } 157 1.1 christos } 158 1.1 christos else if (dispatch_mode == DISPATCH_ON) 159 1.1 christos { 160 1.1 christos #if ARCH(SPARC) 161 1.1 christos ucontext_t uctxmem; 162 1.1 christos ucontext_t *uctx = &uctxmem; 163 1.1 christos uctx->uc_link = NULL; 164 1.1 christos /* 23340823 signal handler third argument should point to a ucontext_t */ 165 1.1 christos /* Convert sigcontext to ucontext_t on sparc-Linux */ 166 1.1 christos struct sigcontext *sctx = (struct sigcontext*) context; 167 1.1 christos #if WSIZE(32) 168 1.1 christos uctx->uc_mcontext.gregs[REG_PC] = sctx->si_regs.pc; 169 1.1 christos __collector_memcpy (&uctx->uc_mcontext.gregs[3], 170 1.1 christos sctx->si_regs.u_regs, 171 1.1 christos sizeof (sctx->si_regs.u_regs)); 172 1.1 christos #else 173 1.1 christos uctx->uc_mcontext.mc_gregs[MC_PC] = sctx->sigc_regs.tpc; 174 1.1 christos __collector_memcpy (&uctx->uc_mcontext.mc_gregs[3], 175 1.1 christos sctx->sigc_regs.u_regs, 176 1.1 christos sizeof (sctx->sigc_regs.u_regs)); 177 1.1 christos #endif /* WSIZE() */ 178 1.1 christos 179 1.1 christos #else /* not sparc-Linux */ 180 1.1 christos ucontext_t *uctx = (ucontext_t*) context; 181 1.1 christos #endif /* ARCH() */ 182 1.1 christos TprintfT (DBG_LT3, "collector_sigprof_dispatcher dispatching signal\n"); 183 1.1 christos 184 1.1 christos /* XXXX the order of these checks/activities may need adjustment */ 185 1.1 christos /* XXXX should also check (first) for a "cached" manual sample */ 186 1.1 christos /* HWC check for each LWP: required even if collection is paused */ 187 1.1 christos /* This should be first, otherwise it's likely to find the counters 188 1.1 christos * stopped due to an event/overflow during some of the other activities. 189 1.1 christos */ 190 1.1 christos /* XXXX HWC check performed every time (skipping if HWC profiling inactive) 191 1.1 christos * to avoid complexity of maintaining separate check times for each LWP 192 1.1 christos */ 193 1.1 christos __collector_ext_hwc_check (info, uctx); 194 1.1 christos 195 1.1 christos /* XXXX if sigemtpending, should perhaps skip __collector_ext_usage_sample 196 1.1 christos * (and get it next time through) 197 1.1 christos */ 198 1.1 christos 199 1.1 christos /* check for experiment past delay start */ 200 1.1 christos if (__collector_delay_start != 0) 201 1.1 christos { 202 1.1 christos hrtime_t now = __collector_gethrtime (); 203 1.1 christos if (__collector_delay_start < now) 204 1.1 christos { 205 1.1 christos TprintfT (0, "__collector_ext_usage_sample: now (%lld) > delay_start (%lld)\n", 206 1.1 christos (now - __collector_start_time), (__collector_delay_start - __collector_start_time)); 207 1.1 christos 208 1.1 christos /* resume the data collection */ 209 1.1 christos __collector_delay_start = 0; 210 1.1 christos __collector_resume (); 211 1.1 christos 212 1.1 christos /* don't take a periodic sample, just let the resume sample cover it */ 213 1.1 christos if (__collector_sample_period != 0) 214 1.1 christos { 215 1.1 christos /* this update should only be done for periodic samples */ 216 1.1 christos while (__collector_next_sample < now) 217 1.1 christos __collector_next_sample += ((hrtime_t) NANOSEC) * __collector_sample_period; 218 1.1 christos } 219 1.1 christos /* return; */ 220 1.1 christos } 221 1.1 christos } 222 1.1 christos /* check for periodic sampling */ 223 1.1 christos if (__collector_gethrtime () > __collector_next_sample) 224 1.1 christos __collector_ext_usage_sample (PERIOD_SMPL, "periodic"); 225 1.1 christos 226 1.1 christos /* check for experiment past termination time */ 227 1.1 christos if (__collector_exp_active && __collector_terminate_time != 0) 228 1.1 christos { 229 1.1 christos hrtime_t now = __collector_gethrtime (); 230 1.1 christos if (__collector_terminate_time < now) 231 1.1 christos { 232 1.1 christos TprintfT (0, "__collector_ext_usage_sample: now (%lld) > terminate_time (%lld); closing experiment\n", 233 1.1 christos (now - __collector_start_time), (__collector_terminate_time - __collector_start_time)); 234 1.1 christos /* close the experiment */ 235 1.1 christos __collector_close_experiment (); 236 1.1 christos } 237 1.1 christos } 238 1.1 christos 239 1.1 christos /* call the code to process the profile data, and generate the packet */ 240 1.1 christos /* (must always be called, otherwise profile data must be aggregated, 241 1.1 christos * but can be left till last, as already have the required data) 242 1.1 christos */ 243 1.1 christos __collector_ext_profile_handler (info, uctx); 244 1.1 christos } 245 1.1 christos else if (dispatch_mode == DISPATCH_TST) 246 1.1 christos { 247 1.1 christos collector_sigprof_entries++; 248 1.1 christos return; 249 1.1 christos } 250 1.1 christos } 251 1.1 christos 252 1.1 christos /* 253 1.1 christos * __collector_sigprof_install 254 1.1 christos */ 255 1.1 christos int 256 1.1 christos __collector_sigprof_install () 257 1.1 christos { 258 1.1 christos TprintfT (DBG_LT2, "__collector_sigprof_install\n"); 259 1.1 christos struct sigaction oact; 260 1.1 christos if (__collector_sigaction (SIGPROF, NULL, &oact) != 0) 261 1.1 christos return COL_ERROR_DISPINIT; 262 1.1 christos if (oact.sa_sigaction == collector_sigprof_dispatcher) 263 1.1 christos /* signal handler is already in place; we are probably in a fork-child */ 264 1.1 christos TprintfT (DBG_LT1, "dispatcher: __collector_ext_dispatcher_install() collector_sigprof_dispatcher already installed\n"); 265 1.1 christos else 266 1.1 christos { 267 1.1.1.3 christos struct sigaction c_act = sigaction_0; 268 1.1 christos sigemptyset (&c_act.sa_mask); 269 1.1 christos sigaddset (&c_act.sa_mask, HWCFUNCS_SIGNAL); /* block SIGEMT delivery in handler */ 270 1.1 christos c_act.sa_sigaction = collector_sigprof_dispatcher; 271 1.1 christos c_act.sa_flags = SA_RESTART | SA_SIGINFO; 272 1.1 christos if (__collector_sigaction (SIGPROF, &c_act, &original_sigprof_handler)) 273 1.1 christos return COL_ERROR_DISPINIT; 274 1.1 christos } 275 1.1 christos dispatch_mode = DISPATCH_OFF; /* don't dispatch yet */ 276 1.1 christos TprintfT (DBG_LT2, "__collector_sigprof_install done\n"); 277 1.1 christos return COL_ERROR_NONE; 278 1.1 christos } 279 1.1 christos 280 1.1 christos /* 281 1.1 christos * void __collector_ext_dispatcher_tsd_create_key() 282 1.1 christos * 283 1.1 christos * create tsd key for dispatcher 284 1.1 christos */ 285 1.1 christos void 286 1.1 christos __collector_ext_dispatcher_tsd_create_key () 287 1.1 christos { 288 1.1 christos dispatcher_key = __collector_tsd_create_key (sizeof (timer_t), NULL, NULL); 289 1.1 christos } 290 1.1 christos /* 291 1.1 christos * int __collector_ext_dispatcher_install() 292 1.1 christos * 293 1.1 christos * installs a common handler/dispatcher (and itimer) for SIGPROF events 294 1.1 christos */ 295 1.1 christos int 296 1.1 christos __collector_ext_dispatcher_install () 297 1.1 christos { 298 1.1 christos int timer_period; 299 1.1 christos TprintfT (DBG_LT2, "__collector_ext_dispatcher_install\n"); 300 1.1 christos 301 1.1 christos /* check period set for interval timer, which will be used as the basis 302 1.1 christos * for all timed activities: if not set, no role for SIGPROF dispatcher 303 1.1 christos */ 304 1.1 christos if (itimer_period_requested <= 0) 305 1.1 christos { 306 1.1 christos TprintfT (DBG_LT1, "No interval timer set: skipping dispatcher install!\n"); 307 1.1 christos return COL_ERROR_NONE; /* no itimer/dispatcher required */ 308 1.1 christos } 309 1.1 christos 310 1.1 christos /* check for an existing interval timer */ 311 1.1 christos if (collector_master_thread_timerid == NULL) 312 1.1 christos if (collector_timer_create (&collector_master_thread_timerid) < 0) 313 1.1 christos return COL_ERROR_ITMRINIT; 314 1.1 christos timer_t *timeridptr = __collector_tsd_get_by_key (dispatcher_key); 315 1.1 christos if (timeridptr != NULL) 316 1.1 christos *timeridptr = collector_master_thread_timerid; // store for per thread timer stop/start 317 1.1 christos TprintfT (DBG_LT3, "__collector_ext_dispatcher_install: collector_master_thread_timerid=%p\n", 318 1.1 christos collector_master_thread_timerid); 319 1.1 christos timer_period = collector_timer_gettime (collector_master_thread_timerid); 320 1.1 christos if (timer_period > 0) 321 1.1 christos { 322 1.1 christos TprintfT (DBG_LT1, "Overriding app-set interval timer with period %d\n", timer_period); 323 1.1 christos (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d->%d</event>\n", 324 1.1 christos SP_JCMD_CWARN, COL_WARN_ITMRPOVR, timer_period, itimer_period_requested); 325 1.1 christos } 326 1.1 christos /* install the interval timer used for all timed activities */ 327 1.1 christos if (collector_timer_settime (itimer_period_requested, collector_master_thread_timerid) < 0) 328 1.1 christos return COL_ERROR_ITMRINIT; 329 1.1 christos TprintfT (DBG_LT2, "__collector_ext_dispatcher_install done\n"); 330 1.1 christos dispatch_mode = DISPATCH_ON; /* activate SIGPROF dispatch to event handlers */ 331 1.1 christos return COL_ERROR_NONE; 332 1.1 christos } 333 1.1 christos 334 1.1 christos int 335 1.1 christos __collector_sigaction (int sig, const struct sigaction *nact, struct sigaction *oact) 336 1.1 christos { 337 1.1 christos TprintfT (DBG_LT1, "__collector_sigaction: %d, %p\n", sig, nact ? nact->sa_sigaction : NULL); 338 1.1 christos if (NULL_PTR (sigaction)) 339 1.1 christos init_interposition_intf (); 340 1.1 christos 341 1.1 christos /* Whether we change the signal handler in the kernel 342 1.1 christos * or not make sure the real sigaction is aware about 343 1.1 christos * our new handler (6227565) 344 1.1 christos */ 345 1.1 christos return CALL_REAL (sigaction)(sig, nact, oact); 346 1.1 christos } 347 1.1 christos 348 1.1 christos /* 349 1.1 christos * We have special dispatchers for SIGPROF and HWCFUNCS_SIGNAL to 350 1.1 christos * decide whether the signal was intended for us or for the user. 351 1.1 christos * One special case is SIGDFL, in which case we don't have a 352 1.1 christos * user-function address to call. If the user did indeed set 353 1.1 christos * default disposition for one of these signals and sent that 354 1.1 christos * signal, we honor that action, even though it will lead to 355 1.1 christos * termination. 356 1.1 christos */ 357 1.1 christos void 358 1.1 christos __collector_SIGDFL_handler (int sig) 359 1.1 christos { 360 1.1 christos /* remove our dispatcher, replacing it with the default disposition */ 361 1.1.1.3 christos struct sigaction act = sigaction_0; 362 1.1 christos act.sa_handler = SIG_DFL; 363 1.1 christos if (__collector_sigaction (sig, &act, NULL)) 364 1.1 christos { 365 1.1 christos /* XXXXXX what are we supposed to do here? we're committing suicide anyhow */ 366 1.1 christos } 367 1.1 christos /* resend the signal we intercepted earlier */ 368 1.1 christos // XXXX Bug 18177509 - additional sigprof signal kills target program 369 1.1 christos kill (getpid (), sig); 370 1.1 christos } 371 1.1 christos 372 1.1 christos /* 373 1.1 christos * suspend/resume timer per thread 374 1.1 christos */ 375 1.1 christos void 376 1.1 christos __collector_ext_dispatcher_thread_timer_suspend () 377 1.1 christos { 378 1.1 christos timer_t * timeridptr = __collector_tsd_get_by_key (dispatcher_key); 379 1.1 christos if (timeridptr != NULL && *timeridptr != NULL) 380 1.1 christos (void) collector_timer_settime (0, *timeridptr); 381 1.1 christos return; 382 1.1 christos } 383 1.1 christos 384 1.1 christos int 385 1.1 christos __collector_ext_dispatcher_thread_timer_resume () 386 1.1 christos { 387 1.1 christos timer_t * timeridptr = __collector_tsd_get_by_key (dispatcher_key); 388 1.1 christos if (timeridptr == NULL) 389 1.1 christos return -1; 390 1.1 christos if (*timeridptr == NULL) 391 1.1 christos { // timer id not initialized yet 392 1.1 christos TprintfT (DBG_LT2, "__collector_ext_dispatcher_thread_timer_resume: timer not initialized yet, create it\n"); 393 1.1 christos if (collector_timer_create (timeridptr) == -1) 394 1.1 christos { 395 1.1 christos TprintfT (0, "__collector_ext_dispatcher_thread_timer_resume(): WARNING: No timer created\n"); 396 1.1 christos return -1; 397 1.1 christos } 398 1.1 christos } 399 1.1 christos return collector_timer_settime (itimer_period_requested, *timeridptr); 400 1.1 christos } 401 1.1 christos 402 1.1 christos void 403 1.1 christos __collector_ext_dispatcher_suspend () 404 1.1 christos { 405 1.1 christos TprintfT (DBG_LT2, "__collector_ext_dispatcher_suspend\n"); 406 1.1 christos if (dispatch_mode == DISPATCH_NYI) 407 1.1 christos { 408 1.1 christos TprintfT (0, "__collector_ext_dispatcher_suspend(): WARNING: No dispatcher installed\n"); 409 1.1 christos return; 410 1.1 christos } 411 1.1 christos 412 1.1 christos /* disable SIGPROF dispatching */ 413 1.1 christos dispatch_mode = DISPATCH_OFF; 414 1.1 christos 415 1.1 christos /* disable the interval timer; ignore any failures */ 416 1.1 christos __collector_ext_dispatcher_thread_timer_suspend (); 417 1.1 christos return; 418 1.1 christos } 419 1.1 christos 420 1.1 christos void 421 1.1 christos __collector_ext_dispatcher_restart () 422 1.1 christos { 423 1.1 christos TprintfT (DBG_LT2, "__collector_ext_dispatcher_restart(ip=%d)\n", itimer_period_requested); 424 1.1 christos if (dispatch_mode == DISPATCH_NYI) 425 1.1 christos { 426 1.1 christos TprintfT (0, "__collector_ext_dispatcher_restart(): WARNING: No dispatcher installed\n"); 427 1.1 christos return; 428 1.1 christos } 429 1.1 christos 430 1.1 christos /* restart the interval timer used for all timed activities */ 431 1.1 christos if (__collector_ext_dispatcher_thread_timer_resume () == 0) 432 1.1 christos dispatch_mode = DISPATCH_ON; /* re-activate SIGPROF dispatch to handlers */ 433 1.1 christos return; 434 1.1 christos } 435 1.1 christos /* 436 1.1 christos * void __collector_ext_dispatcher_deinstall() 437 1.1 christos * 438 1.1 christos * If installed, disables SIGPROF dispatch and interval timer. 439 1.1 christos * Includes checks for last SIGPROF dispatch time, interval timer period, 440 1.1 christos * and currently installed SIGPROF handler, with appropriate warnings logged. 441 1.1 christos * The dispatcher remains installed to handle pending collector SIGPROFs and 442 1.1 christos * forward non-collector SIGPROFs to the application's handler(s). 443 1.1 christos * If the decision is ever made actually to deinstall the dispatcher, 444 1.1 christos * consider bug 4183714 and what to do about any possible pending 445 1.1 christos * SIGPROFs. 446 1.1 christos */ 447 1.1 christos 448 1.1 christos void 449 1.1 christos __collector_ext_dispatcher_deinstall () 450 1.1 christos { 451 1.1 christos TprintfT (DBG_LT1, "__collector_ext_dispatcher_deinstall()\n"); 452 1.1 christos if (dispatch_mode == DISPATCH_NYI) 453 1.1 christos { 454 1.1 christos TprintfT (0, "__collector_ext_dispatcher_deinstall(): WARNING: No dispatcher installed\n"); 455 1.1 christos return; 456 1.1 christos } 457 1.1 christos dispatch_mode = DISPATCH_OFF; /* disable SIGPROF dispatching */ 458 1.1 christos 459 1.1 christos /* verify that interval timer is still installed with expected period */ 460 1.1 christos int timer_period = collector_timer_gettime (collector_master_thread_timerid); 461 1.1 christos if (timer_period != itimer_period_actual) 462 1.1 christos { 463 1.1 christos TprintfT (DBG_LT2, "dispatcher: Collector interval timer period changed %d -> %d\n", 464 1.1 christos itimer_period_actual, timer_period); 465 1.1 christos if ((itimer_period_actual >= (timer_period + timer_period / 10)) || 466 1.1 christos (itimer_period_actual <= (timer_period - timer_period / 10))) 467 1.1 christos __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n", 468 1.1 christos SP_JCMD_CWARN, COL_WARN_ITMRREP, 469 1.1 christos itimer_period_actual, timer_period); 470 1.1 christos else 471 1.1 christos __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n", 472 1.1 christos SP_JCMD_COMMENT, COL_WARN_PROFRND, 473 1.1 christos itimer_period_actual, timer_period); 474 1.1 christos } 475 1.1 christos 476 1.1 christos /* Verify that SIGPROF dispatcher is still installed. 477 1.1 christos * (still required with sigaction interposition and management, 478 1.1 christos * since interposition is not done for attach experiments) 479 1.1 christos */ 480 1.1 christos struct sigaction curr; 481 1.1 christos if (__collector_sigaction (SIGPROF, NULL, &curr) == -1) 482 1.1 christos TprintfT (0, "ERROR: dispatcher sigaction check failed: errno=%d\n", errno); 483 1.1 christos else if (curr.sa_sigaction != collector_sigprof_dispatcher) 484 1.1 christos { 485 1.1 christos TprintfT (0, "ERROR: collector dispatcher replaced by %p!\n", curr.sa_handler); 486 1.1 christos (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%p</event>\n", 487 1.1 christos SP_JCMD_CWARN, COL_WARN_SIGPROF, curr.sa_handler); 488 1.1 christos } 489 1.1 christos else 490 1.1 christos TprintfT (DBG_LT2, "collector dispatcher integrity verified!\n"); 491 1.1 christos 492 1.1 christos /* disable the interval timer; ignore any failures */ 493 1.1 christos if (collector_master_thread_timerid != NULL) 494 1.1 christos { 495 1.1 christos (void) CALL_REAL (timer_delete)(collector_master_thread_timerid); 496 1.1 christos collector_master_thread_timerid = NULL; 497 1.1 christos } 498 1.1 christos dispatcher_key = COLLECTOR_TSD_INVALID_KEY; 499 1.1 christos itimer_period_requested = 0; 500 1.1 christos itimer_period_actual = 0; 501 1.1 christos } 502 1.1 christos 503 1.1 christos /* 504 1.1 christos * void __collector_ext_dispatcher_fork_child_cleanup() 505 1.1 christos * 506 1.1 christos * delete timer, clear timer interval 507 1.1 christos */ 508 1.1 christos void 509 1.1 christos __collector_ext_dispatcher_fork_child_cleanup () 510 1.1 christos { 511 1.1 christos if (collector_master_thread_timerid != NULL) 512 1.1 christos { 513 1.1 christos (void) CALL_REAL (timer_delete)(collector_master_thread_timerid); 514 1.1 christos collector_master_thread_timerid = NULL; 515 1.1 christos } 516 1.1 christos __collector_mutex_init (&collector_clone_libc_lock); 517 1.1 christos dispatcher_key = COLLECTOR_TSD_INVALID_KEY; 518 1.1 christos itimer_period_requested = 0; 519 1.1 christos itimer_period_actual = 0; 520 1.1 christos } 521 1.1 christos /* 522 1.1 christos * int __collector_ext_itimer_set (int rperiod) 523 1.1 christos * 524 1.1 christos * set itimer period, if not yet set to a positive number of microseconds, 525 1.1 christos * (after rounding to sys_resolution if necessary) and return its value 526 1.1 christos */ 527 1.1 christos int 528 1.1 christos __collector_ext_itimer_set (int rperiod) 529 1.1 christos { 530 1.1 christos int period; 531 1.1 christos /* if rperiod is negative, force setting */ 532 1.1 christos if (rperiod < 0) 533 1.1 christos { 534 1.1 christos itimer_period_actual = 0; 535 1.1 christos period = -rperiod; 536 1.1 christos } 537 1.1 christos else 538 1.1 christos period = rperiod; 539 1.1 christos 540 1.1 christos // ignore SIGPROF while testing itimer interval setting 541 1.1 christos int saved = dispatch_mode; 542 1.1 christos dispatch_mode = DISPATCH_OFF; 543 1.1 christos if (collector_timer_create (&collector_master_thread_timerid) == -1) 544 1.1 christos { 545 1.1 christos TprintfT (0, "__collector_ext_itimer_set(): WARNING: No timer created\n"); 546 1.1 christos return itimer_period_actual; 547 1.1 christos } 548 1.1 christos if (collector_timer_settime (period, collector_master_thread_timerid) == 0) 549 1.1 christos { 550 1.1 christos itimer_period_actual = collector_timer_gettime (collector_master_thread_timerid); 551 1.1 christos (void) collector_timer_settime (0, collector_master_thread_timerid); /* XXXX unset for now */ 552 1.1 christos itimer_period_requested = period; 553 1.1 christos if (itimer_period_requested != itimer_period_actual) 554 1.1 christos { 555 1.1 christos TprintfT (DBG_LT2, " itimer period %d adjusted to %d\n", 556 1.1 christos itimer_period_requested, itimer_period_actual); 557 1.1 christos // (void) __collector_log_write("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n", 558 1.1 christos // SP_JCMD_CWARN, COL_WARN_PROFRND, itimer_period_requested, itimer_period_actual); 559 1.1 christos } 560 1.1 christos else 561 1.1 christos TprintfT (DBG_LT2, " itimer period %d accepted\n", period); 562 1.1 christos } 563 1.1 christos 564 1.1 christos // restore dispatching SIGPROF handler 565 1.1 christos dispatch_mode = saved; 566 1.1 christos TprintfT (0, "__collector_ext_itimer_set(%d), requested=%d, actual=%d)\n", 567 1.1 christos rperiod, itimer_period_requested, itimer_period_actual); 568 1.1 christos return (itimer_period_actual); 569 1.1 christos } 570 1.1 christos 571 1.1 christos static int 572 1.1 christos collector_timer_gettime (timer_t timerid) 573 1.1 christos { 574 1.1 christos int timer_period; 575 1.1 christos struct itimerspec itimer; 576 1.1 christos if (timerid == NULL) 577 1.1 christos return (0); // timer was not initialized 578 1.1 christos if (CALL_REAL (timer_gettime)(timerid, &itimer) == -1) 579 1.1 christos { 580 1.1 christos /* this should never reasonably fail, so not worth logging */ 581 1.1 christos TprintfT (DBG_LT1, "WARNING: timer_gettime failed: errno=%d\n", errno); 582 1.1 christos return (-1); 583 1.1 christos } 584 1.1 christos timer_period = ((itimer.it_interval.tv_sec * NANOSEC) + 585 1.1 christos itimer.it_interval.tv_nsec) / 1000; 586 1.1 christos TprintfT (DBG_LT2, "collector_timer_gettime (period=%d)\n", timer_period); 587 1.1 christos return (timer_period); 588 1.1 christos } 589 1.1 christos 590 1.1 christos static int 591 1.1 christos collector_timer_create (timer_t * ptimerid) 592 1.1 christos { 593 1.1 christos struct sigevent sigev; 594 1.1 christos if (NULL_PTR (timer_create)) 595 1.1 christos init_interposition_intf (); 596 1.1 christos TprintfT (DBG_LT2, "collector_timer_settime(): timer_create is %p\n", __real_timer_create); 597 1.1 christos sigev.sigev_notify = SIGEV_THREAD_ID | SIGEV_SIGNAL; 598 1.1 christos sigev.sigev_signo = SIGPROF; 599 1.1 christos sigev.sigev_value.sival_ptr = ptimerid; 600 1.1.1.2 christos #if !defined(__MUSL_LIBC) 601 1.1 christos sigev._sigev_un._tid = __collector_gettid (); 602 1.1.1.2 christos #endif 603 1.1 christos if (CALL_REAL (timer_create)(CLOCK_THREAD_CPUTIME_ID, &sigev, ptimerid) == -1) 604 1.1 christos { 605 1.1 christos TprintfT (DBG_LT2, "collector_timer_settime() failed! errno=%d\n", errno); 606 1.1 christos return -1; 607 1.1 christos } 608 1.1 christos return 0; 609 1.1 christos } 610 1.1 christos 611 1.1 christos static int 612 1.1 christos collector_timer_settime (int period, timer_t timerid) 613 1.1 christos { 614 1.1 christos struct itimerspec itimer; 615 1.1 christos if (NULL_PTR (timer_settime)) 616 1.1 christos init_interposition_intf (); 617 1.1 christos TprintfT (DBG_LT2, "collector_timer_settime(period=%d)\n", period); 618 1.1 christos time_t NPM = 1000; 619 1.1 christos itimer.it_interval.tv_sec = NPM * period / NANOSEC; 620 1.1 christos itimer.it_interval.tv_nsec = (NPM * period) % NANOSEC; 621 1.1 christos itimer.it_value = itimer.it_interval; 622 1.1 christos if (CALL_REAL (timer_settime)(timerid, 0, &itimer, NULL) == -1) 623 1.1 christos { 624 1.1 christos TprintfT (DBG_LT2, "collector_timer_settime(%d) failed! errno=%d\n", period, errno); 625 1.1 christos return -1; 626 1.1 christos } 627 1.1 christos return 0; 628 1.1 christos } 629 1.1 christos 630 1.1 christos static void 631 1.1 christos protect_profiling_signals (sigset_t* lset) 632 1.1 christos { 633 1.1 christos static unsigned int protected_sigprof = 0; 634 1.1 christos static unsigned int protected_sigemt = 0; 635 1.1 christos // T1 relies on thread signal masking, so best not to mess with it: 636 1.1 christos // T1 users have already been warned about the dangers of its use 637 1.1 christos if (__collector_libthread_T1) 638 1.1 christos return; 639 1.1 christos if (sigismember (lset, SIGPROF) && (dispatch_mode == DISPATCH_ON)) 640 1.1 christos { 641 1.1 christos TprintfT (0, "WARNING: ignoring %s block while profiling\n", "SIGPROF"); 642 1.1 christos if (protected_sigprof == 0) 643 1.1 christos __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", 644 1.1 christos SP_JCMD_CWARN, COL_WARN_SIGMASK, "SIGPROF"); 645 1.1 christos sigdelset (lset, SIGPROF); 646 1.1 christos protected_sigprof++; 647 1.1 christos } 648 1.1 christos if (sigismember (lset, HWCFUNCS_SIGNAL) && __collector_ext_hwc_active ()) 649 1.1 christos { 650 1.1 christos TprintfT (0, "WARNING: ignoring %s block while profiling\n", "SIGEMT"); 651 1.1 christos if (protected_sigemt == 0) 652 1.1 christos __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", 653 1.1 christos SP_JCMD_CWARN, COL_WARN_SIGMASK, HWCFUNCS_SIGNAL_STRING); 654 1.1 christos sigdelset (lset, HWCFUNCS_SIGNAL); 655 1.1 christos protected_sigemt++; 656 1.1 christos } 657 1.1 christos } 658 1.1 christos 659 1.1 christos static int 660 1.1 christos init_interposition_intf () 661 1.1 christos { 662 1.1 christos if (__collector_dlsym_guard) 663 1.1 christos return 1; 664 1.1 christos void *dlflag; 665 1.1 christos /* Linux requires RTLD_LAZY, Solaris can do just RTLD_NOLOAD */ 666 1.1 christos void *handle = dlopen (SYS_LIBC_NAME, RTLD_LAZY | RTLD_NOLOAD); 667 1.1 christos 668 1.1.1.2 christos __real_setitimer = dlsym (RTLD_NEXT, "setitimer"); 669 1.1 christos if (__real_setitimer == NULL) 670 1.1 christos { 671 1.1.1.2 christos __real_setitimer = dlsym (RTLD_DEFAULT, "setitimer"); 672 1.1 christos if (__real_setitimer == NULL) 673 1.1 christos { 674 1.1 christos TprintfT (DBG_LT2, "init_interposition_intf() setitimer not found\n"); 675 1.1 christos return 1; 676 1.1 christos } 677 1.1 christos dlflag = RTLD_DEFAULT; 678 1.1 christos } 679 1.1 christos else 680 1.1 christos dlflag = RTLD_NEXT; 681 1.1 christos 682 1.1 christos TprintfT (DBG_LT2, "init_interposition_intf() using RTLD_%s\n", 683 1.1 christos (dlflag == RTLD_DEFAULT) ? "DEFAULT" : "NEXT"); 684 1.1 christos 685 1.1.1.2 christos __real_sigaction = dlsym (dlflag, "sigaction"); 686 1.1 christos 687 1.1 christos /* also explicitly get libc.so/setitimer (as a backup) */ 688 1.1.1.2 christos __real_libc_setitimer = dlsym (handle, "setitimer"); 689 1.1 christos 690 1.1.1.2 christos __real_sigprocmask = dlsym (dlflag, "sigprocmask"); 691 1.1.1.2 christos __real_thr_sigsetmask = dlsym (dlflag, "thr_sigsetmask"); 692 1.1 christos 693 1.1.1.2 christos __real_pthread_sigmask_2_32 = dlvsym (dlflag, "pthread_sigmask", "GLIBC_2.32"); 694 1.1.1.2 christos __real_pthread_sigmask_2_17 = dlvsym (dlflag, "pthread_sigmask", "GLIBC_2.17"); 695 1.1.1.2 christos __real_pthread_sigmask_2_2_5 = dlvsym (dlflag, "pthread_sigmask", "GLIBC_2.2.5"); 696 1.1.1.2 christos __real_pthread_sigmask_2_0 = dlvsym (dlflag, "pthread_sigmask", "GLIBC_2.0"); 697 1.1.1.2 christos if (__real_pthread_sigmask_2_32) 698 1.1.1.2 christos __real_pthread_sigmask = __real_pthread_sigmask_2_32; 699 1.1.1.2 christos else if (__real_pthread_sigmask_2_17) 700 1.1.1.2 christos __real_pthread_sigmask = __real_pthread_sigmask_2_17; 701 1.1.1.2 christos else if (__real_pthread_sigmask_2_2_5) 702 1.1.1.2 christos __real_pthread_sigmask = __real_pthread_sigmask_2_2_5; 703 1.1.1.2 christos else if (__real_pthread_sigmask_2_0) 704 1.1.1.2 christos __real_pthread_sigmask = __real_pthread_sigmask_2_0; 705 1.1.1.2 christos else 706 1.1.1.2 christos __real_pthread_sigmask = dlsym (dlflag, "pthread_sigmask"); 707 1.1 christos 708 1.1.1.2 christos __real_pthread_create_2_34 = dlvsym (dlflag, "pthread_create", "GLIBC_2.34"); 709 1.1.1.2 christos __real_pthread_create_2_17 = dlvsym (dlflag, "pthread_create", "GLIBC_2.17"); 710 1.1.1.2 christos __real_pthread_create_2_2_5 = dlvsym (dlflag, "pthread_create", "GLIBC_2.2.5"); 711 1.1.1.2 christos __real_pthread_create_2_1 = dlvsym (dlflag, "pthread_create", "GLIBC_2.1"); 712 1.1 christos __real_pthread_create_2_0 = dlvsym (dlflag, "pthread_create", "GLIBC_2.0"); 713 1.1.1.2 christos if (__real_pthread_create_2_34) 714 1.1.1.2 christos __real_pthread_create = __real_pthread_create_2_34; 715 1.1.1.2 christos else if (__real_pthread_create_2_17) 716 1.1.1.2 christos __real_pthread_create = __real_pthread_create_2_17; 717 1.1.1.2 christos else if (__real_pthread_create_2_2_5) 718 1.1.1.2 christos __real_pthread_create = __real_pthread_create_2_2_5; 719 1.1.1.2 christos else if (__real_pthread_create_2_1) 720 1.1.1.2 christos __real_pthread_create = __real_pthread_create_2_1; 721 1.1.1.2 christos else if (__real_pthread_create_2_0) 722 1.1.1.2 christos __real_pthread_create = __real_pthread_create_2_0; 723 1.1.1.2 christos else 724 1.1.1.2 christos __real_pthread_create = dlsym (dlflag, "pthread_create"); 725 1.1.1.2 christos 726 1.1.1.2 christos __real_timer_create_2_34 = dlvsym (dlflag, "timer_create", "GLIBC_2.34"); 727 1.1.1.2 christos __real_timer_create_2_17 = dlvsym (dlflag, "timer_create", "GLIBC_2.17"); 728 1.1.1.2 christos __real_timer_create_2_3_3 = dlvsym (dlflag, "timer_create", "GLIBC_2.3.3"); 729 1.1 christos __real_timer_create_2_2_5 = dlvsym (dlflag, "timer_create", "GLIBC_2.2.5"); 730 1.1 christos __real_timer_create_2_2 = dlvsym (dlflag, "timer_create", "GLIBC_2.2"); 731 1.1.1.2 christos if (__real_timer_create_2_34) 732 1.1.1.2 christos __real_timer_create = __real_timer_create_2_34; 733 1.1.1.2 christos else if (__real_timer_create_2_17) 734 1.1.1.2 christos __real_timer_create = __real_timer_create_2_17; 735 1.1.1.2 christos else if (__real_timer_create_2_3_3) 736 1.1.1.2 christos __real_timer_create = __real_timer_create_2_3_3; 737 1.1.1.2 christos else if (__real_timer_create_2_2_5) 738 1.1.1.2 christos __real_timer_create = __real_timer_create_2_2_5; 739 1.1.1.2 christos else if (__real_timer_create_2_2) 740 1.1.1.2 christos __real_timer_create = __real_timer_create_2_2; 741 1.1.1.2 christos else 742 1.1.1.2 christos __real_timer_create = dlsym (dlflag, "timer_create"); 743 1.1.1.2 christos 744 1.1.1.2 christos void *t; 745 1.1.1.2 christos if ((t = dlvsym (dlflag, "timer_settime", "GLIBC_2.34")) != NULL) 746 1.1.1.2 christos __real_timer_settime = t; 747 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_settime", "GLIBC_2.17")) != NULL) 748 1.1.1.2 christos __real_timer_settime = t; 749 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_settime", "GLIBC_2.3.3")) != NULL) 750 1.1.1.2 christos __real_timer_settime = t; 751 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_settime", "GLIBC_2.2.5")) != NULL) 752 1.1.1.2 christos __real_timer_settime = t; 753 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_settime", "GLIBC_2.0")) != NULL) 754 1.1.1.2 christos __real_timer_settime = t; 755 1.1.1.2 christos else 756 1.1.1.2 christos __real_timer_settime = dlsym (dlflag, "timer_settime"); 757 1.1.1.2 christos 758 1.1.1.2 christos if ((t = dlvsym (dlflag, "timer_delete", "GLIBC_2.34")) != NULL) 759 1.1.1.2 christos __real_timer_delete = t; 760 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_delete", "GLIBC_2.17")) != NULL) 761 1.1.1.2 christos __real_timer_delete = t; 762 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_delete", "GLIBC_2.3.3")) != NULL) 763 1.1.1.2 christos __real_timer_delete = t; 764 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_delete", "GLIBC_2.2.5")) != NULL) 765 1.1.1.2 christos __real_timer_delete = t; 766 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_delete", "GLIBC_2.2")) != NULL) 767 1.1.1.2 christos __real_timer_delete = t; 768 1.1.1.2 christos else 769 1.1.1.2 christos __real_timer_delete = dlsym (dlflag, "timer_delete"); 770 1.1.1.2 christos 771 1.1.1.2 christos if ((t = dlvsym (dlflag, "timer_gettime", "GLIBC_2.34")) != NULL) 772 1.1.1.2 christos __real_timer_gettime = t; 773 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_gettime", "GLIBC_2.17")) != NULL) 774 1.1.1.2 christos __real_timer_gettime = t; 775 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_gettime", "GLIBC_2.3.3")) != NULL) 776 1.1.1.2 christos __real_timer_gettime = t; 777 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_gettime", "GLIBC_2.2.5")) != NULL) 778 1.1.1.2 christos __real_timer_gettime = t; 779 1.1.1.2 christos else if ((t = dlvsym (dlflag, "timer_gettime", "GLIBC_2.0")) != NULL) 780 1.1.1.2 christos __real_timer_gettime = t; 781 1.1.1.2 christos else 782 1.1.1.2 christos __real_timer_gettime = dlsym (dlflag, "timer_gettime"); 783 1.1.1.2 christos 784 1.1.1.2 christos __real_clone = dlsym (dlflag, "clone"); 785 1.1.1.2 christos 786 1.1.1.2 christos #define PR_FUNC(f) TprintfT (DBG_LT2, " dispetcher.c: " #f ": @%p\n", f) 787 1.1.1.2 christos PR_FUNC (__real_clone); 788 1.1.1.2 christos PR_FUNC (__real_libc_setitimer); 789 1.1.1.2 christos PR_FUNC (__real_pthread_create); 790 1.1.1.2 christos PR_FUNC (__real_pthread_create_2_0); 791 1.1.1.2 christos PR_FUNC (__real_pthread_create_2_1); 792 1.1.1.2 christos PR_FUNC (__real_pthread_create_2_17); 793 1.1.1.2 christos PR_FUNC (__real_pthread_create_2_2_5); 794 1.1.1.2 christos PR_FUNC (__real_pthread_create_2_34); 795 1.1.1.2 christos PR_FUNC (__real_pthread_sigmask); 796 1.1.1.2 christos PR_FUNC (__real_pthread_sigmask_2_0); 797 1.1.1.2 christos PR_FUNC (__real_pthread_sigmask_2_2_5); 798 1.1.1.2 christos PR_FUNC (__real_pthread_sigmask_2_17); 799 1.1.1.2 christos PR_FUNC (__real_pthread_sigmask_2_32); 800 1.1.1.2 christos PR_FUNC (__real_setitimer); 801 1.1.1.2 christos PR_FUNC (__real_sigaction); 802 1.1.1.2 christos PR_FUNC (__real_sigprocmask); 803 1.1.1.2 christos PR_FUNC (__real_thr_sigsetmask); 804 1.1.1.2 christos PR_FUNC (__real_timer_create); 805 1.1.1.2 christos PR_FUNC (__real_timer_create_2_17); 806 1.1.1.2 christos PR_FUNC (__real_timer_create_2_2); 807 1.1.1.2 christos PR_FUNC (__real_timer_create_2_2_5); 808 1.1.1.2 christos PR_FUNC (__real_timer_create_2_3_3); 809 1.1.1.2 christos PR_FUNC (__real_timer_create_2_34); 810 1.1.1.2 christos PR_FUNC (__real_timer_delete); 811 1.1.1.2 christos PR_FUNC (__real_timer_gettime); 812 1.1.1.2 christos PR_FUNC (__real_timer_settime); 813 1.1.1.2 christos 814 1.1 christos return 0; 815 1.1 christos } 816 1.1 christos 817 1.1 christos 818 1.1 christos /*------------------------------------------------------------- sigaction */ 819 1.1 christos 820 1.1 christos /* NB: need a global interposing function called "sigaction" */ 821 1.1 christos int 822 1.1 christos sigaction (int sig, const struct sigaction *nact, struct sigaction *oact) 823 1.1 christos { 824 1.1 christos int ret = 0; 825 1.1 christos int err = 0; 826 1.1 christos if (NULL_PTR (sigaction)) 827 1.1 christos err = init_interposition_intf (); 828 1.1 christos if (err) 829 1.1 christos return -1; 830 1.1 christos TprintfT (DBG_LT3, "sigaction(sig=%02d, nact=%p) interposing\n", sig, nact); 831 1.1 christos if (sig == SIGPROF && dispatch_mode != DISPATCH_NYI) 832 1.1 christos { 833 1.1 christos if (oact != NULL) 834 1.1 christos { 835 1.1 christos oact->sa_handler = original_sigprof_handler.sa_handler; 836 1.1 christos oact->sa_mask = original_sigprof_handler.sa_mask; 837 1.1 christos oact->sa_flags = original_sigprof_handler.sa_flags; 838 1.1 christos } 839 1.1 christos if (nact != NULL) 840 1.1 christos { 841 1.1 christos original_sigprof_handler.sa_handler = nact->sa_handler; 842 1.1 christos original_sigprof_handler.sa_mask = nact->sa_mask; 843 1.1 christos original_sigprof_handler.sa_flags = nact->sa_flags; 844 1.1 christos TprintfT (DBG_LT1, "dispatcher: new sigaction(sig=%02d) set\n", sig); 845 1.1 christos } 846 1.1 christos } 847 1.1 christos else if (sig == HWCFUNCS_SIGNAL) 848 1.1 christos ret = collector_sigemt_sigaction (nact, oact); 849 1.1 christos else 850 1.1 christos { 851 1.1 christos if (sig != SIGCHLD || collector_sigchld_sigaction (nact, oact)) 852 1.1 christos ret = CALL_REAL (sigaction)(sig, nact, oact); 853 1.1 christos TprintfT (DBG_LT3, "Real sigaction(sig=%02d) returned %d (oact=%p)\n", 854 1.1 christos sig, ret, oact); 855 1.1 christos /* but check for other important signals */ 856 1.1 christos /* check for sample and pause/resume signals; give warning once, if need be */ 857 1.1 christos if ((sig == __collector_sample_sig) && (__collector_sample_sig_warn == 0)) 858 1.1 christos { 859 1.1 christos /* give user a warning */ 860 1.1 christos (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n", 861 1.1 christos SP_JCMD_CWARN, COL_WARN_SAMPSIGUSED, __collector_sample_sig); 862 1.1 christos __collector_sample_sig_warn = 1; 863 1.1 christos } 864 1.1 christos if ((sig == __collector_pause_sig) && (__collector_pause_sig_warn == 0)) 865 1.1 christos { 866 1.1 christos /* give user a warning */ 867 1.1 christos (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n", 868 1.1 christos SP_JCMD_CWARN, COL_WARN_PAUSESIGUSED, __collector_pause_sig); 869 1.1 christos __collector_pause_sig_warn = 1; 870 1.1 christos } 871 1.1 christos } 872 1.1 christos TprintfT (DBG_LT3, "sigaction() returning %d (oact=%p)\n", ret, oact); 873 1.1 christos return ret; 874 1.1 christos } 875 1.1 christos 876 1.1 christos /* 877 1.1 christos * In addition to interposing on sigaction(), should we also interpose 878 1.1 christos * on other important signal functions like signal() or sigset()? 879 1.1 christos * - On Solaris, those other functions apparently call sigaction(). 880 1.1 christos * So, we only have to interpose on it. 881 1.1 christos * - On Linux, we should perhaps interpose on these other functions, 882 1.1 christos * but they are less portable than sigaction() and deprecated or even obsolete. 883 1.1 christos * So, we interpose, but don't overly worry about doing a good job. 884 1.1 christos */ 885 1.1 christos sighandler_t 886 1.1 christos signal (int sig, sighandler_t handler) 887 1.1 christos { 888 1.1 christos struct sigaction nact; 889 1.1 christos struct sigaction oact; 890 1.1 christos TprintfT (DBG_LT3, "signal(sig=%02d, handler=%p) interposing\n", sig, handler); 891 1.1 christos sigemptyset (&nact.sa_mask); 892 1.1 christos nact.sa_handler = handler; 893 1.1 christos nact.sa_flags = SA_RESTART; 894 1.1 christos if (sigaction (sig, &nact, &oact)) 895 1.1 christos return SIG_ERR; 896 1.1 christos TprintfT (DBG_LT3, "signal() returning %p\n", oact.sa_handler); 897 1.1 christos return oact.sa_handler; 898 1.1 christos } 899 1.1 christos 900 1.1 christos sighandler_t 901 1.1 christos sigset (int sig, sighandler_t handler) 902 1.1 christos { 903 1.1 christos TprintfT (DBG_LT3, "sigset(sig=%02d, handler=%p) interposing\n", sig, handler); 904 1.1 christos return signal (sig, handler); 905 1.1 christos } 906 1.1 christos 907 1.1 christos /*------------------------------------------------------------- timer_create */ 908 1.1 christos 909 1.1 christos // map interposed symbol versions 910 1.1 christos static int 911 1.1.1.3 christos gprofng_timer_create (int (real_func) (clockid_t, struct sigevent *, timer_t *), 912 1.1.1.3 christos clockid_t clockid, 913 1.1.1.3 christos struct sigevent *sevp, timer_t *timerid) 914 1.1 christos { 915 1.1.1.2 christos // collector reserves SIGPROF 916 1.1.1.2 christos if (sevp == NULL || sevp->sigev_notify != SIGEV_SIGNAL || 917 1.1.1.2 christos sevp->sigev_signo != SIGPROF) 918 1.1.1.2 christos { 919 1.1.1.2 christos int ret = real_func (clockid, sevp, timerid); 920 1.1.1.2 christos TprintfT (DBG_LT2, "timer_create @%p (%d) ret=%d\n", real_func, 921 1.1.1.2 christos (int) clockid, ret); 922 1.1 christos return ret; 923 1.1 christos } 924 1.1 christos 925 1.1 christos /* log that application's timer_create request is overridden */ 926 1.1 christos (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n", 927 1.1 christos SP_JCMD_CWARN, COL_WARN_ITMROVR, -1); 928 1.1 christos errno = EBUSY; 929 1.1.1.2 christos TprintfT (DBG_LT2, "timer_create @%p (%d) ret=%d\n", real_func, 930 1.1.1.2 christos (int) clockid, -1); \ 931 1.1.1.2 christos return -1; 932 1.1.1.2 christos } 933 1.1.1.2 christos 934 1.1.1.2 christos #define DCL_TIMER_CREATE(dcl_f) \ 935 1.1.1.2 christos int dcl_f (clockid_t clockid, struct sigevent *sevp, timer_t *timerid) \ 936 1.1.1.2 christos { \ 937 1.1.1.2 christos if (__real_timer_create == NULL) \ 938 1.1.1.2 christos init_interposition_intf (); \ 939 1.1.1.2 christos return gprofng_timer_create (__real_timer_create, clockid, sevp, timerid); \ 940 1.1.1.2 christos } 941 1.1.1.2 christos 942 1.1.1.2 christos DCL_FUNC_VER (DCL_TIMER_CREATE, timer_create_2_34, timer_create@GLIBC_2.34) 943 1.1.1.2 christos DCL_FUNC_VER (DCL_TIMER_CREATE, timer_create_2_17, timer_create@GLIBC_2.17) 944 1.1.1.2 christos DCL_FUNC_VER (DCL_TIMER_CREATE, timer_create_2_3_3, timer_create@GLIBC_2.3.3) 945 1.1.1.2 christos DCL_FUNC_VER (DCL_TIMER_CREATE, timer_create_2_2_5, timer_create@GLIBC_2.2.5) 946 1.1.1.2 christos DCL_FUNC_VER (DCL_TIMER_CREATE, timer_create_2_2, timer_create@GLIBC_2.2) 947 1.1.1.2 christos DCL_TIMER_CREATE (timer_create) 948 1.1.1.2 christos 949 1.1 christos /*------------------------------------------------------------- setitimer */ 950 1.1 christos int 951 1.1 christos _setitimer (int which, const struct itimerval *nval, 952 1.1 christos struct itimerval *oval) 953 1.1 christos { 954 1.1 christos int ret; 955 1.1 christos int period; 956 1.1 christos 957 1.1 christos if (NULL_PTR (setitimer)) 958 1.1 christos init_interposition_intf (); 959 1.1 christos 960 1.1 christos if (nval == NULL) 961 1.1 christos period = -1; 962 1.1 christos else 963 1.1 christos period = (nval->it_interval.tv_sec * MICROSEC) + 964 1.1 christos nval->it_interval.tv_usec; 965 1.1 christos TprintfT (DBG_LT1, "setitimer(which=%d,nval=%dus) interposing\n", which, period); 966 1.1 christos 967 1.1 christos /* collector reserves ITIMER_REALPROF for its own use, and ITIMER_PROF 968 1.1 christos * uses the same signal (SIGPROF) so it must also be reserved 969 1.1 christos */ 970 1.1 christos if (((which != ITIMER_REALPROF) && (which != ITIMER_PROF)) || (nval == NULL)) 971 1.1 christos { 972 1.1 christos ret = CALL_REAL (setitimer)(which, nval, oval); 973 1.1 christos if (oval == NULL) 974 1.1 christos period = -1; 975 1.1 christos else 976 1.1 christos period = (oval->it_interval.tv_sec * MICROSEC) + 977 1.1 christos oval->it_interval.tv_usec; 978 1.1 christos TprintfT (DBG_LT2, "Real setitimer(%d) returned %d (oval=%dus)\n", 979 1.1 christos which, ret, period); 980 1.1 christos return ret; 981 1.1 christos } 982 1.1 christos /* log that application's setitimer request is overridden */ 983 1.1 christos (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n", 984 1.1 christos SP_JCMD_CWARN, COL_WARN_ITMROVR, period); 985 1.1 christos if (oval == NULL) 986 1.1 christos period = -1; 987 1.1 christos else 988 1.1 christos { 989 1.1 christos getitimer (which, oval); /* return current itimer setting */ 990 1.1 christos period = (oval->it_interval.tv_sec * MICROSEC) + 991 1.1 christos oval->it_interval.tv_usec; 992 1.1 christos } 993 1.1 christos ret = -1; 994 1.1 christos errno = EBUSY; 995 1.1 christos TprintfT (DBG_LT2, "setitimer() returning %d (oval=%dus)\n", ret, period); 996 1.1 christos return ret; 997 1.1 christos } 998 1.1 christos 999 1.1 christos /*--------------------------------------------------------------- sigprocmask */ 1000 1.1 christos int 1001 1.1 christos __collector_sigprocmask (int how, const sigset_t* iset, sigset_t* oset) 1002 1.1 christos { 1003 1.1 christos int err = 0; 1004 1.1 christos if (NULL_PTR (sigprocmask)) 1005 1.1 christos err = init_interposition_intf (); 1006 1.1 christos if (err) 1007 1.1 christos return -1; 1008 1.1 christos TprintfT (DBG_LT2, "__collector_sigprocmask(%d) interposing\n", how); 1009 1.1 christos sigset_t lsigset; 1010 1.1 christos sigset_t* lset = NULL; 1011 1.1 christos if (iset) 1012 1.1 christos { 1013 1.1 christos lsigset = *iset; 1014 1.1 christos lset = &lsigset; 1015 1.1 christos if ((how == SIG_BLOCK) || (how == SIG_SETMASK)) 1016 1.1 christos protect_profiling_signals (lset); 1017 1.1 christos } 1018 1.1 christos int ret = CALL_REAL (sigprocmask)(how, lset, oset); 1019 1.1 christos TprintfT (DBG_LT2, "__collector_sigprocmask(%d) returning %d\n", how, ret); 1020 1.1 christos return ret; 1021 1.1 christos } 1022 1.1 christos 1023 1.1 christos /*------------------------------------------------------------ thr_sigsetmask */ 1024 1.1 christos int 1025 1.1 christos __collector_thr_sigsetmask (int how, const sigset_t* iset, sigset_t* oset) 1026 1.1 christos { 1027 1.1 christos if (NULL_PTR (thr_sigsetmask)) 1028 1.1 christos init_interposition_intf (); 1029 1.1 christos TprintfT (DBG_LT1, "__collector_thr_sigsetmask(%d) interposing\n", how); 1030 1.1 christos sigset_t lsigset; 1031 1.1 christos sigset_t* lset = NULL; 1032 1.1 christos if (iset) 1033 1.1 christos { 1034 1.1 christos lsigset = *iset; 1035 1.1 christos lset = &lsigset; 1036 1.1 christos if ((how == SIG_BLOCK) || (how == SIG_SETMASK)) 1037 1.1 christos protect_profiling_signals (lset); 1038 1.1 christos } 1039 1.1 christos int ret = CALL_REAL (thr_sigsetmask)(how, lset, oset); 1040 1.1 christos TprintfT (DBG_LT1, "__collector_thr_sigsetmask(%d) returning %d\n", how, ret); 1041 1.1 christos return ret; 1042 1.1 christos } 1043 1.1 christos 1044 1.1 christos /*----------------------------------------------------------- pthread_sigmask */ 1045 1.1.1.2 christos // map interposed symbol versions 1046 1.1 christos 1047 1.1.1.2 christos static int 1048 1.1.1.3 christos gprofng_pthread_sigmask (int (real_func) (int, const sigset_t *, sigset_t*), 1049 1.1.1.2 christos int how, const sigset_t *iset, sigset_t* oset) 1050 1.1 christos { 1051 1.1 christos sigset_t lsigset; 1052 1.1 christos sigset_t* lset = NULL; 1053 1.1 christos if (iset) 1054 1.1 christos { 1055 1.1 christos lsigset = *iset; 1056 1.1 christos lset = &lsigset; 1057 1.1.1.2 christos if (how == SIG_BLOCK || how == SIG_SETMASK) 1058 1.1.1.2 christos protect_profiling_signals (lset); 1059 1.1 christos } 1060 1.1.1.2 christos int ret = (real_func) (how, lset, oset); 1061 1.1.1.2 christos TprintfT (DBG_LT1, "real_pthread_sigmask @%p (%d) ret=%d\n", 1062 1.1.1.2 christos real_func, how, ret); 1063 1.1 christos return ret; 1064 1.1.1.2 christos 1065 1.1 christos } 1066 1.1.1.2 christos 1067 1.1.1.2 christos #define DCL_PTHREAD_SIGMASK(dcl_f) \ 1068 1.1.1.2 christos int dcl_f (int how, const sigset_t *iset, sigset_t* oset) \ 1069 1.1.1.2 christos { \ 1070 1.1.1.2 christos if (__real_pthread_sigmask == NULL) \ 1071 1.1.1.2 christos init_interposition_intf (); \ 1072 1.1.1.2 christos return gprofng_pthread_sigmask (__real_pthread_sigmask, how, iset, oset); \ 1073 1.1.1.2 christos } 1074 1.1.1.2 christos 1075 1.1.1.2 christos DCL_FUNC_VER (DCL_PTHREAD_SIGMASK, pthread_sigmask_2_32, pthread_sigmask@GLIBC_2.32) 1076 1.1.1.2 christos DCL_FUNC_VER (DCL_PTHREAD_SIGMASK, pthread_sigmask_2_17, pthread_sigmask@GLIBC_2.17) 1077 1.1.1.2 christos DCL_FUNC_VER (DCL_PTHREAD_SIGMASK, pthread_sigmask_2_2_5, pthread_sigmask@GLIBC_2.2.5) 1078 1.1.1.2 christos DCL_FUNC_VER (DCL_PTHREAD_SIGMASK, pthread_sigmask_2_0, pthread_sigmask@GLIBC_2.0) 1079 1.1.1.2 christos DCL_PTHREAD_SIGMASK (pthread_sigmask) 1080 1.1.1.2 christos 1081 1.1 christos /*----------------------------------------------------------- pthread_create */ 1082 1.1 christos typedef struct _CollectorArgs 1083 1.1 christos { 1084 1.1 christos void *(*func)(void*); 1085 1.1 christos void *arg; 1086 1.1 christos void *stack; 1087 1.1 christos int isPthread; 1088 1.1 christos } CollectorArgs; 1089 1.1 christos 1090 1.1 christos static void * 1091 1.1 christos collector_root (void *cargs) 1092 1.1 christos { 1093 1.1 christos /* save the real arguments and free cargs */ 1094 1.1 christos void *(*func)(void*) = ((CollectorArgs*) cargs)->func; 1095 1.1 christos void *arg = ((CollectorArgs*) cargs)->arg; 1096 1.1 christos void *stack = ((CollectorArgs*) cargs)->stack; 1097 1.1 christos int isPthread = ((CollectorArgs*) cargs)->isPthread; 1098 1.1 christos __collector_freeCSize (__collector_heap, cargs, sizeof (CollectorArgs)); 1099 1.1 christos 1100 1.1 christos /* initialize tsd for this thread */ 1101 1.1 christos if (__collector_tsd_allocate () == 0) 1102 1.1 christos /* init tsd for unwind, called right after __collector_tsd_allocate()*/ 1103 1.1 christos __collector_ext_unwind_key_init (isPthread, stack); 1104 1.1 christos 1105 1.1 christos if (!isPthread) 1106 1.1 christos __collector_mutex_lock (&collector_clone_libc_lock); 1107 1.1 christos 1108 1.1 christos /* set the profile timer */ 1109 1.1 christos timer_t *timeridptr = __collector_tsd_get_by_key (dispatcher_key); 1110 1.1 christos timer_t timerid = NULL; 1111 1.1 christos if (timeridptr != NULL) 1112 1.1 christos { 1113 1.1 christos collector_timer_create (timeridptr); 1114 1.1 christos if (*timeridptr != NULL) 1115 1.1 christos collector_timer_settime (itimer_period_requested, *timeridptr); 1116 1.1 christos timerid = *timeridptr; 1117 1.1 christos } 1118 1.1 christos int hwc_rc = __collector_ext_hwc_lwp_init (); 1119 1.1 christos 1120 1.1 christos if (!isPthread) 1121 1.1 christos __collector_mutex_unlock (&collector_clone_libc_lock); 1122 1.1 christos /* call the real function */ 1123 1.1 christos void *ret = func (arg); 1124 1.1 christos if (!isPthread) 1125 1.1 christos __collector_mutex_lock (&collector_clone_libc_lock); 1126 1.1 christos if (timerid != NULL) 1127 1.1 christos CALL_REAL (timer_delete)(timerid); 1128 1.1 christos if (!hwc_rc) 1129 1.1 christos /* pthread_kill not handled here */ 1130 1.1 christos __collector_ext_hwc_lwp_fini (); 1131 1.1 christos 1132 1.1 christos if (!isPthread) 1133 1.1 christos __collector_mutex_unlock (&collector_clone_libc_lock); 1134 1.1 christos /* if we have this chance, release tsd */ 1135 1.1 christos __collector_tsd_release (); 1136 1.1 christos 1137 1.1 christos return ret; 1138 1.1 christos } 1139 1.1 christos 1140 1.1 christos // map interposed symbol versions 1141 1.1 christos 1142 1.1 christos static int 1143 1.1.1.3 christos gprofng_pthread_create (int (real_func) (pthread_t *, const pthread_attr_t *, 1144 1.1.1.3 christos void *(*)(void *), void *), 1145 1.1.1.3 christos pthread_t *thread, const pthread_attr_t *attr, 1146 1.1.1.3 christos void *(*func)(void*), void *arg) 1147 1.1 christos { 1148 1.1.1.2 christos TprintfT (DBG_LTT, "gprofng_pthread_create @%p\n", real_func); 1149 1.1 christos if (dispatch_mode != DISPATCH_ON) 1150 1.1.1.2 christos return (real_func) (thread, attr, func, arg); 1151 1.1.1.2 christos CollectorArgs *cargs = __collector_allocCSize (__collector_heap, 1152 1.1.1.2 christos sizeof (CollectorArgs), 1); 1153 1.1 christos if (cargs == NULL) 1154 1.1.1.2 christos return (real_func) (thread, attr, func, arg); 1155 1.1 christos cargs->func = func; 1156 1.1 christos cargs->arg = arg; 1157 1.1 christos cargs->stack = NULL; 1158 1.1 christos cargs->isPthread = 1; 1159 1.1.1.2 christos int ret = (real_func) (thread, attr, &collector_root, cargs); 1160 1.1 christos if (ret) 1161 1.1 christos __collector_freeCSize (__collector_heap, cargs, sizeof (CollectorArgs)); 1162 1.1.1.2 christos TprintfT (DBG_LT1, "gprofng_pthread_create @%p returns %d\n", real_func, ret); 1163 1.1 christos return ret; 1164 1.1 christos } 1165 1.1 christos 1166 1.1.1.2 christos 1167 1.1.1.2 christos #define DCL_PTHREAD_CREATE(dcl_f) \ 1168 1.1.1.2 christos int dcl_f (pthread_t *thread, const pthread_attr_t *attr, \ 1169 1.1.1.2 christos void *(*func)(void*), void *arg) \ 1170 1.1.1.2 christos { \ 1171 1.1.1.2 christos if (__real_pthread_create == NULL) \ 1172 1.1.1.2 christos init_interposition_intf (); \ 1173 1.1.1.2 christos return gprofng_pthread_create (__real_pthread_create, thread, attr, func, arg); \ 1174 1.1.1.2 christos } 1175 1.1.1.2 christos 1176 1.1.1.2 christos DCL_FUNC_VER (DCL_PTHREAD_CREATE, pthread_create_2_34, pthread_create@GLIBC_2.34) 1177 1.1.1.2 christos DCL_FUNC_VER (DCL_PTHREAD_CREATE, pthread_create_2_17, pthread_create@GLIBC_2.17) 1178 1.1.1.2 christos DCL_FUNC_VER (DCL_PTHREAD_CREATE, pthread_create_2_2_5, pthread_create@GLIBC_2.2.5) 1179 1.1.1.2 christos DCL_FUNC_VER (DCL_PTHREAD_CREATE, pthread_create_2_1, pthread_create@GLIBC_2.1) 1180 1.1.1.2 christos DCL_FUNC_VER (DCL_PTHREAD_CREATE, pthread_create_2_0, pthread_create@GLIBC_2.0) 1181 1.1.1.2 christos DCL_PTHREAD_CREATE (pthread_create) 1182 1.1.1.2 christos 1183 1.1 christos int 1184 1.1 christos __collector_ext_clone_pthread (int (*fn)(void *), void *child_stack, int flags, void *arg, 1185 1.1 christos va_list va /* pid_t *ptid, struct user_desc *tls, pid_t *" ctid" */) 1186 1.1 christos { 1187 1.1 christos if (NULL_PTR (clone)) 1188 1.1 christos init_interposition_intf (); 1189 1.1 christos TprintfT (0, "clone thread interposing\n"); 1190 1.1 christos pid_t * ptid = NULL; 1191 1.1 christos struct user_desc * tls = NULL; 1192 1.1 christos pid_t * ctid = NULL; 1193 1.1 christos int num_args = 0; 1194 1.1 christos if (flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) 1195 1.1 christos { 1196 1.1 christos ptid = va_arg (va, pid_t *); 1197 1.1 christos tls = va_arg (va, struct user_desc*); 1198 1.1 christos ctid = va_arg (va, pid_t *); 1199 1.1 christos num_args = 3; 1200 1.1 christos } 1201 1.1 christos else if (flags & CLONE_SETTLS) 1202 1.1 christos { 1203 1.1 christos ptid = va_arg (va, pid_t *); 1204 1.1 christos tls = va_arg (va, struct user_desc*); 1205 1.1 christos num_args = 2; 1206 1.1 christos } 1207 1.1 christos else if (flags & CLONE_PARENT_SETTID) 1208 1.1 christos { 1209 1.1 christos ptid = va_arg (va, pid_t *); 1210 1.1 christos num_args = 1; 1211 1.1 christos } 1212 1.1 christos int ret = 0; 1213 1.1 christos if (dispatch_mode != DISPATCH_ON) 1214 1.1 christos { 1215 1.1 christos switch (num_args) 1216 1.1 christos { 1217 1.1 christos case 3: 1218 1.1 christos ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid, tls, ctid); 1219 1.1 christos break; 1220 1.1 christos case 2: 1221 1.1 christos ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid, tls); 1222 1.1 christos break; 1223 1.1 christos case 1: 1224 1.1 christos ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid); 1225 1.1 christos break; 1226 1.1 christos default: 1227 1.1 christos ret = CALL_REAL (clone)(fn, child_stack, flags, arg); 1228 1.1 christos break; 1229 1.1 christos } 1230 1.1 christos return ret; 1231 1.1 christos } 1232 1.1 christos CollectorArgs *cargs = __collector_allocCSize (__collector_heap, sizeof (CollectorArgs), 1); 1233 1.1 christos if (cargs == NULL) 1234 1.1 christos { 1235 1.1 christos switch (num_args) 1236 1.1 christos { 1237 1.1 christos case 3: 1238 1.1 christos ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid, tls, ctid); 1239 1.1 christos break; 1240 1.1 christos case 2: 1241 1.1 christos ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid, tls); 1242 1.1 christos break; 1243 1.1 christos case 1: 1244 1.1 christos ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid); 1245 1.1 christos break; 1246 1.1 christos default: 1247 1.1 christos ret = CALL_REAL (clone)(fn, child_stack, flags, arg); 1248 1.1 christos break; 1249 1.1 christos } 1250 1.1 christos return ret; 1251 1.1 christos } 1252 1.1 christos 1253 1.1 christos cargs->func = (void *(*)(void*))fn; 1254 1.1 christos cargs->arg = arg; 1255 1.1 christos cargs->stack = child_stack; 1256 1.1 christos cargs->isPthread = 0; 1257 1.1 christos 1258 1.1 christos switch (num_args) 1259 1.1 christos { 1260 1.1 christos case 3: 1261 1.1 christos ret = CALL_REAL (clone)((int(*)(void*))collector_root, child_stack, flags, cargs, ptid, tls, ctid); 1262 1.1 christos break; 1263 1.1 christos case 2: 1264 1.1 christos ret = CALL_REAL (clone)((int(*)(void*))collector_root, child_stack, flags, cargs, ptid, tls); 1265 1.1 christos break; 1266 1.1 christos case 1: 1267 1.1 christos ret = CALL_REAL (clone)((int(*)(void*))collector_root, child_stack, flags, cargs, ptid); 1268 1.1 christos break; 1269 1.1 christos default: 1270 1.1 christos ret = CALL_REAL (clone)((int(*)(void*))collector_root, child_stack, flags, cargs); 1271 1.1 christos break; 1272 1.1 christos } 1273 1.1 christos 1274 1.1 christos if (ret < 0) 1275 1.1 christos __collector_freeCSize (__collector_heap, cargs, sizeof (CollectorArgs)); 1276 1.1 christos TprintfT (DBG_LT1, "clone thread returning %d\n", ret); 1277 1.1 christos return ret; 1278 1.1 christos } 1279 1.1 christos 1280 1.1 christos // weak symbols: 1281 1.1.1.3 christos int sigprocmask (int, const sigset_t*, sigset_t*) __attribute__ ((weak, alias ("__collector_sigprocmask"))); 1282 1.1.1.3 christos int thr_sigsetmask (int, const sigset_t*, sigset_t*) __attribute__ ((weak, alias ("__collector_thr_sigsetmask"))); 1283 1.1.1.3 christos __typeof(setitimer) setitimer __attribute__ ((weak, alias ("_setitimer"))); 1284