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