1 /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
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)
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.
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. */
22 * Central SIGPROF dispatcher to various module event handlers
23 * (REALPROF profile, HWC check, overview sample, manual sample)
33 #include <sys/param.h>
34 #include <sys/syscall.h>
39 #include "gp-experiment.h"
40 #include "collector.h"
41 #include "collector_module.h"
46 static void collector_sigprof_dispatcher (int, siginfo_t
*, void*);
47 static int init_interposition_intf ();
48 static int collector_timer_create (timer_t
* ptimerid
);
49 static int collector_timer_settime (int period
, timer_t timerid
);
50 static int collector_timer_gettime (timer_t timerid
);
51 static volatile int collector_sigprof_entries
= 0; /* counter for SIGPROF signals in DISPATCH_TST mode */
52 static timer_t collector_master_thread_timerid
= NULL
;
53 static collector_mutex_t collector_clone_libc_lock
= COLLECTOR_MUTEX_INITIALIZER
;
54 static unsigned dispatcher_key
= COLLECTOR_TSD_INVALID_KEY
;
56 static int (*__real_clone
) (int (*fn
)(void *), void *child_stack
, int flags
,
57 void *arg
, ...) = NULL
;
58 static int (*__real_timer_create
) (clockid_t clockid
,
59 struct sigevent
*sevp
, timer_t
*timerid
) = NULL
;
60 static int (*__real_timer_settime
) (timer_t timerid
, int flags
,
61 const struct itimerspec
*new_value
,
62 struct itimerspec
*old_value
) = NULL
;
63 static int (*__real_timer_delete
) (timer_t timerid
) = NULL
;
64 static int (*__real_timer_gettime
) (timer_t timerid
,
65 struct itimerspec
*curr_value
) = NULL
;
67 static int (*__real_pthread_create_2_34
) (pthread_t
*thread
,
68 const pthread_attr_t
*attr
,
69 void *(*start_routine
) (void *), void *arg
) = NULL
;
70 static int (*__real_pthread_create_2_17
) (pthread_t
*thread
,
71 const pthread_attr_t
*attr
,
72 void *(*start_routine
) (void *), void *arg
) = NULL
;
73 static int (*__real_pthread_create_2_2_5
) (pthread_t
*thread
,
74 const pthread_attr_t
*attr
,
75 void *(*start_routine
) (void *), void *arg
) = NULL
;
76 static int (*__real_pthread_create_2_1
) (pthread_t
*thread
,
77 const pthread_attr_t
*attr
,
78 void *(*start_routine
) (void *), void *arg
) = NULL
;
79 static int (*__real_pthread_create_2_0
) (pthread_t
*thread
,
80 const pthread_attr_t
*attr
,
81 void *(*start_routine
) (void *), void *arg
) = NULL
;
83 static int (*__real_timer_create_2_34
) (clockid_t clockid
,
84 struct sigevent
*sevp
, timer_t
*timerid
) = NULL
;
85 static int (*__real_timer_create_2_17
) (clockid_t clockid
,
86 struct sigevent
*sevp
, timer_t
*timerid
) = NULL
;
87 static int (*__real_timer_create_2_3_3
) (clockid_t clockid
,
88 struct sigevent
*sevp
, timer_t
*timerid
) = NULL
;
89 static int (*__real_timer_create_2_2_5
) (clockid_t clockid
,
90 struct sigevent
*sevp
, timer_t
*timerid
) = NULL
;
91 static int (*__real_timer_create_2_2
) (clockid_t clockid
,
92 struct sigevent
*sevp
, timer_t
*timerid
) = NULL
;
94 int (*__real_pthread_sigmask_2_32
) (int, const sigset_t
*, sigset_t
*) = NULL
;
95 int (*__real_pthread_sigmask_2_17
) (int, const sigset_t
*, sigset_t
*) = NULL
;
96 int (*__real_pthread_sigmask_2_2_5
) (int, const sigset_t
*, sigset_t
*) = NULL
;
97 int (*__real_pthread_sigmask_2_0
) (int, const sigset_t
*, sigset_t
*) = NULL
;
100 /* Original SIGPROF handler which will be replaced with the dispatcher. Used
101 * to properly interact with libaio, which uses SIGPROF as its SIGAIOCANCEL. */
102 static struct sigaction original_sigprof_handler
;
106 DISPATCH_NYI
= -1, /* dispatcher not yet installed */
107 DISPATCH_OFF
= 0, /* dispatcher installed, but disabled */
108 DISPATCH_ON
= 1, /* dispatcher installed, and enabled */
109 DISPATCH_TST
= 2 /* dispatcher installed, and enabled in testing mode */
112 static int dispatch_mode
= DISPATCH_NYI
; /* controls SIGPROF dispatching */
113 static int itimer_period_requested
= 0; /* dispatcher itimer period */
114 static int itimer_period_actual
= 0; /* actual dispatcher itimer period */
116 static int (*__real_sigaction
) (int signum
, const struct sigaction
*act
,
117 struct sigaction
*oldact
) = NULL
;
118 static int (*__real_setitimer
) (int which
, const struct itimerval
*new_value
,
119 struct itimerval
*old_value
) = NULL
;
120 static int (*__real_libc_setitimer
) (int which
,
121 const struct itimerval
*new_value
, struct itimerval
*old_value
) = NULL
;
122 static int (*__real_sigprocmask
) (int how
, const sigset_t
*set
,
123 sigset_t
*oldset
) = NULL
;
124 static int (*__real_thr_sigsetmask
) (int how
, const sigset_t
*iset
,
125 sigset_t
*oset
) = NULL
;
126 static int (*__real_pthread_sigmask
) (int how
, const sigset_t
*set
,
127 sigset_t
*oldset
) = NULL
;
128 static int (*__real_pthread_create
) (pthread_t
*thread
,
129 const pthread_attr_t
*attr
,
130 void *(*start_routine
) (void *), void *arg
) = NULL
;
133 * void collector_sigprof_dispatcher()
135 * Common SIGPROF event handler which dispatches events to appropriate
136 * module handlers, if they are active for this collection and due.
137 * Dispatch sequence, logic and handlers currently hardcoded in dispatcher.
140 collector_sigprof_dispatcher (int sig
, siginfo_t
*info
, void *context
)
142 if (info
== NULL
|| (info
->si_code
<= 0 && info
->si_code
!= SI_TIMER
))
144 TprintfT (DBG_LT2
, "collector_sigprof_dispatcher signal for %p\n",
145 original_sigprof_handler
.sa_handler
);
146 /* pass signal to previous handler */
147 /* watch for recursion, SIG_IGN, and SIG_DFL */
148 if (original_sigprof_handler
.sa_handler
== SIG_DFL
)
149 __collector_SIGDFL_handler (SIGPROF
);
150 else if (original_sigprof_handler
.sa_handler
!= SIG_IGN
&&
151 original_sigprof_handler
.sa_sigaction
!= &collector_sigprof_dispatcher
)
153 (original_sigprof_handler
.sa_sigaction
)(sig
, info
, context
);
154 TprintfT (DBG_LT2
, "collector_sigprof_dispatcher handled\n");
157 else if (dispatch_mode
== DISPATCH_ON
)
161 ucontext_t
*uctx
= &uctxmem
;
162 uctx
->uc_link
= NULL
;
163 /* 23340823 signal handler third argument should point to a ucontext_t */
164 /* Convert sigcontext to ucontext_t on sparc-Linux */
165 struct sigcontext
*sctx
= (struct sigcontext
*) context
;
167 uctx
->uc_mcontext
.gregs
[REG_PC
] = sctx
->si_regs
.pc
;
168 __collector_memcpy (&uctx
->uc_mcontext
.gregs
[3],
169 sctx
->si_regs
.u_regs
,
170 sizeof (sctx
->si_regs
.u_regs
));
172 uctx
->uc_mcontext
.mc_gregs
[MC_PC
] = sctx
->sigc_regs
.tpc
;
173 __collector_memcpy (&uctx
->uc_mcontext
.mc_gregs
[3],
174 sctx
->sigc_regs
.u_regs
,
175 sizeof (sctx
->sigc_regs
.u_regs
));
178 #else /* not sparc-Linux */
179 ucontext_t
*uctx
= (ucontext_t
*) context
;
181 TprintfT (DBG_LT3
, "collector_sigprof_dispatcher dispatching signal\n");
183 /* XXXX the order of these checks/activities may need adjustment */
184 /* XXXX should also check (first) for a "cached" manual sample */
185 /* HWC check for each LWP: required even if collection is paused */
186 /* This should be first, otherwise it's likely to find the counters
187 * stopped due to an event/overflow during some of the other activities.
189 /* XXXX HWC check performed every time (skipping if HWC profiling inactive)
190 * to avoid complexity of maintaining separate check times for each LWP
192 __collector_ext_hwc_check (info
, uctx
);
194 /* XXXX if sigemtpending, should perhaps skip __collector_ext_usage_sample
195 * (and get it next time through)
198 /* check for experiment past delay start */
199 if (__collector_delay_start
!= 0)
201 hrtime_t now
= __collector_gethrtime ();
202 if (__collector_delay_start
< now
)
204 TprintfT (0, "__collector_ext_usage_sample: now (%lld) > delay_start (%lld)\n",
205 (now
- __collector_start_time
), (__collector_delay_start
- __collector_start_time
));
207 /* resume the data collection */
208 __collector_delay_start
= 0;
209 __collector_resume ();
211 /* don't take a periodic sample, just let the resume sample cover it */
212 if (__collector_sample_period
!= 0)
214 /* this update should only be done for periodic samples */
215 while (__collector_next_sample
< now
)
216 __collector_next_sample
+= ((hrtime_t
) NANOSEC
) * __collector_sample_period
;
221 /* check for periodic sampling */
222 if (__collector_gethrtime () > __collector_next_sample
)
223 __collector_ext_usage_sample (PERIOD_SMPL
, "periodic");
225 /* check for experiment past termination time */
226 if (__collector_exp_active
&& __collector_terminate_time
!= 0)
228 hrtime_t now
= __collector_gethrtime ();
229 if (__collector_terminate_time
< now
)
231 TprintfT (0, "__collector_ext_usage_sample: now (%lld) > terminate_time (%lld); closing experiment\n",
232 (now
- __collector_start_time
), (__collector_terminate_time
- __collector_start_time
));
233 /* close the experiment */
234 __collector_close_experiment ();
238 /* call the code to process the profile data, and generate the packet */
239 /* (must always be called, otherwise profile data must be aggregated,
240 * but can be left till last, as already have the required data)
242 __collector_ext_profile_handler (info
, uctx
);
244 else if (dispatch_mode
== DISPATCH_TST
)
246 collector_sigprof_entries
++;
252 * __collector_sigprof_install
255 __collector_sigprof_install ()
257 TprintfT (DBG_LT2
, "__collector_sigprof_install\n");
258 struct sigaction oact
;
259 if (__collector_sigaction (SIGPROF
, NULL
, &oact
) != 0)
260 return COL_ERROR_DISPINIT
;
261 if (oact
.sa_sigaction
== collector_sigprof_dispatcher
)
262 /* signal handler is already in place; we are probably in a fork-child */
263 TprintfT (DBG_LT1
, "dispatcher: __collector_ext_dispatcher_install() collector_sigprof_dispatcher already installed\n");
266 struct sigaction c_act
;
267 CALL_UTIL (memset
)(&c_act
, 0, sizeof c_act
);
268 sigemptyset (&c_act
.sa_mask
);
269 sigaddset (&c_act
.sa_mask
, HWCFUNCS_SIGNAL
); /* block SIGEMT delivery in handler */
270 c_act
.sa_sigaction
= collector_sigprof_dispatcher
;
271 c_act
.sa_flags
= SA_RESTART
| SA_SIGINFO
;
272 if (__collector_sigaction (SIGPROF
, &c_act
, &original_sigprof_handler
))
273 return COL_ERROR_DISPINIT
;
275 dispatch_mode
= DISPATCH_OFF
; /* don't dispatch yet */
276 TprintfT (DBG_LT2
, "__collector_sigprof_install done\n");
277 return COL_ERROR_NONE
;
281 * void __collector_ext_dispatcher_tsd_create_key()
283 * create tsd key for dispatcher
286 __collector_ext_dispatcher_tsd_create_key ()
288 dispatcher_key
= __collector_tsd_create_key (sizeof (timer_t
), NULL
, NULL
);
291 * int __collector_ext_dispatcher_install()
293 * installs a common handler/dispatcher (and itimer) for SIGPROF events
296 __collector_ext_dispatcher_install ()
299 TprintfT (DBG_LT2
, "__collector_ext_dispatcher_install\n");
301 /* check period set for interval timer, which will be used as the basis
302 * for all timed activities: if not set, no role for SIGPROF dispatcher
304 if (itimer_period_requested
<= 0)
306 TprintfT (DBG_LT1
, "No interval timer set: skipping dispatcher install!\n");
307 return COL_ERROR_NONE
; /* no itimer/dispatcher required */
310 /* check for an existing interval timer */
311 if (collector_master_thread_timerid
== NULL
)
312 if (collector_timer_create (&collector_master_thread_timerid
) < 0)
313 return COL_ERROR_ITMRINIT
;
314 timer_t
*timeridptr
= __collector_tsd_get_by_key (dispatcher_key
);
315 if (timeridptr
!= NULL
)
316 *timeridptr
= collector_master_thread_timerid
; // store for per thread timer stop/start
317 TprintfT (DBG_LT3
, "__collector_ext_dispatcher_install: collector_master_thread_timerid=%p\n",
318 collector_master_thread_timerid
);
319 timer_period
= collector_timer_gettime (collector_master_thread_timerid
);
320 if (timer_period
> 0)
322 TprintfT (DBG_LT1
, "Overriding app-set interval timer with period %d\n", timer_period
);
323 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d->%d</event>\n",
324 SP_JCMD_CWARN
, COL_WARN_ITMRPOVR
, timer_period
, itimer_period_requested
);
326 /* install the interval timer used for all timed activities */
327 if (collector_timer_settime (itimer_period_requested
, collector_master_thread_timerid
) < 0)
328 return COL_ERROR_ITMRINIT
;
329 TprintfT (DBG_LT2
, "__collector_ext_dispatcher_install done\n");
330 dispatch_mode
= DISPATCH_ON
; /* activate SIGPROF dispatch to event handlers */
331 return COL_ERROR_NONE
;
335 __collector_sigaction (int sig
, const struct sigaction
*nact
, struct sigaction
*oact
)
337 TprintfT (DBG_LT1
, "__collector_sigaction: %d, %p\n", sig
, nact
? nact
->sa_sigaction
: NULL
);
338 if (NULL_PTR (sigaction
))
339 init_interposition_intf ();
341 /* Whether we change the signal handler in the kernel
342 * or not make sure the real sigaction is aware about
343 * our new handler (6227565)
345 return CALL_REAL (sigaction
)(sig
, nact
, oact
);
349 * We have special dispatchers for SIGPROF and HWCFUNCS_SIGNAL to
350 * decide whether the signal was intended for us or for the user.
351 * One special case is SIGDFL, in which case we don't have a
352 * user-function address to call. If the user did indeed set
353 * default disposition for one of these signals and sent that
354 * signal, we honor that action, even though it will lead to
358 __collector_SIGDFL_handler (int sig
)
360 /* remove our dispatcher, replacing it with the default disposition */
361 struct sigaction act
;
362 CALL_UTIL (memset
)(&act
, 0, sizeof (act
));
363 act
.sa_handler
= SIG_DFL
;
364 if (__collector_sigaction (sig
, &act
, NULL
))
366 /* XXXXXX what are we supposed to do here? we're committing suicide anyhow */
368 /* resend the signal we intercepted earlier */
369 // XXXX Bug 18177509 - additional sigprof signal kills target program
370 kill (getpid (), sig
);
374 * suspend/resume timer per thread
377 __collector_ext_dispatcher_thread_timer_suspend ()
379 timer_t
* timeridptr
= __collector_tsd_get_by_key (dispatcher_key
);
380 if (timeridptr
!= NULL
&& *timeridptr
!= NULL
)
381 (void) collector_timer_settime (0, *timeridptr
);
386 __collector_ext_dispatcher_thread_timer_resume ()
388 timer_t
* timeridptr
= __collector_tsd_get_by_key (dispatcher_key
);
389 if (timeridptr
== NULL
)
391 if (*timeridptr
== NULL
)
392 { // timer id not initialized yet
393 TprintfT (DBG_LT2
, "__collector_ext_dispatcher_thread_timer_resume: timer not initialized yet, create it\n");
394 if (collector_timer_create (timeridptr
) == -1)
396 TprintfT (0, "__collector_ext_dispatcher_thread_timer_resume(): WARNING: No timer created\n");
400 return collector_timer_settime (itimer_period_requested
, *timeridptr
);
404 __collector_ext_dispatcher_suspend ()
406 TprintfT (DBG_LT2
, "__collector_ext_dispatcher_suspend\n");
407 if (dispatch_mode
== DISPATCH_NYI
)
409 TprintfT (0, "__collector_ext_dispatcher_suspend(): WARNING: No dispatcher installed\n");
413 /* disable SIGPROF dispatching */
414 dispatch_mode
= DISPATCH_OFF
;
416 /* disable the interval timer; ignore any failures */
417 __collector_ext_dispatcher_thread_timer_suspend ();
422 __collector_ext_dispatcher_restart ()
424 TprintfT (DBG_LT2
, "__collector_ext_dispatcher_restart(ip=%d)\n", itimer_period_requested
);
425 if (dispatch_mode
== DISPATCH_NYI
)
427 TprintfT (0, "__collector_ext_dispatcher_restart(): WARNING: No dispatcher installed\n");
431 /* restart the interval timer used for all timed activities */
432 if (__collector_ext_dispatcher_thread_timer_resume () == 0)
433 dispatch_mode
= DISPATCH_ON
; /* re-activate SIGPROF dispatch to handlers */
437 * void __collector_ext_dispatcher_deinstall()
439 * If installed, disables SIGPROF dispatch and interval timer.
440 * Includes checks for last SIGPROF dispatch time, interval timer period,
441 * and currently installed SIGPROF handler, with appropriate warnings logged.
442 * The dispatcher remains installed to handle pending collector SIGPROFs and
443 * forward non-collector SIGPROFs to the application's handler(s).
444 * If the decision is ever made actually to deinstall the dispatcher,
445 * consider bug 4183714 and what to do about any possible pending
450 __collector_ext_dispatcher_deinstall ()
452 TprintfT (DBG_LT1
, "__collector_ext_dispatcher_deinstall()\n");
453 if (dispatch_mode
== DISPATCH_NYI
)
455 TprintfT (0, "__collector_ext_dispatcher_deinstall(): WARNING: No dispatcher installed\n");
458 dispatch_mode
= DISPATCH_OFF
; /* disable SIGPROF dispatching */
460 /* verify that interval timer is still installed with expected period */
461 int timer_period
= collector_timer_gettime (collector_master_thread_timerid
);
462 if (timer_period
!= itimer_period_actual
)
464 TprintfT (DBG_LT2
, "dispatcher: Collector interval timer period changed %d -> %d\n",
465 itimer_period_actual
, timer_period
);
466 if ((itimer_period_actual
>= (timer_period
+ timer_period
/ 10)) ||
467 (itimer_period_actual
<= (timer_period
- timer_period
/ 10)))
468 __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n",
469 SP_JCMD_CWARN
, COL_WARN_ITMRREP
,
470 itimer_period_actual
, timer_period
);
472 __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n",
473 SP_JCMD_COMMENT
, COL_WARN_PROFRND
,
474 itimer_period_actual
, timer_period
);
477 /* Verify that SIGPROF dispatcher is still installed.
478 * (still required with sigaction interposition and management,
479 * since interposition is not done for attach experiments)
481 struct sigaction curr
;
482 if (__collector_sigaction (SIGPROF
, NULL
, &curr
) == -1)
483 TprintfT (0, "ERROR: dispatcher sigaction check failed: errno=%d\n", errno
);
484 else if (curr
.sa_sigaction
!= collector_sigprof_dispatcher
)
486 TprintfT (0, "ERROR: collector dispatcher replaced by %p!\n", curr
.sa_handler
);
487 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%p</event>\n",
488 SP_JCMD_CWARN
, COL_WARN_SIGPROF
, curr
.sa_handler
);
491 TprintfT (DBG_LT2
, "collector dispatcher integrity verified!\n");
493 /* disable the interval timer; ignore any failures */
494 if (collector_master_thread_timerid
!= NULL
)
496 (void) CALL_REAL (timer_delete
)(collector_master_thread_timerid
);
497 collector_master_thread_timerid
= NULL
;
499 dispatcher_key
= COLLECTOR_TSD_INVALID_KEY
;
500 itimer_period_requested
= 0;
501 itimer_period_actual
= 0;
505 * void __collector_ext_dispatcher_fork_child_cleanup()
507 * delete timer, clear timer interval
510 __collector_ext_dispatcher_fork_child_cleanup ()
512 if (collector_master_thread_timerid
!= NULL
)
514 (void) CALL_REAL (timer_delete
)(collector_master_thread_timerid
);
515 collector_master_thread_timerid
= NULL
;
517 __collector_mutex_init (&collector_clone_libc_lock
);
518 dispatcher_key
= COLLECTOR_TSD_INVALID_KEY
;
519 itimer_period_requested
= 0;
520 itimer_period_actual
= 0;
523 * int __collector_ext_itimer_set (int rperiod)
525 * set itimer period, if not yet set to a positive number of microseconds,
526 * (after rounding to sys_resolution if necessary) and return its value
529 __collector_ext_itimer_set (int rperiod
)
532 /* if rperiod is negative, force setting */
535 itimer_period_actual
= 0;
541 // ignore SIGPROF while testing itimer interval setting
542 int saved
= dispatch_mode
;
543 dispatch_mode
= DISPATCH_OFF
;
544 if (collector_timer_create (&collector_master_thread_timerid
) == -1)
546 TprintfT (0, "__collector_ext_itimer_set(): WARNING: No timer created\n");
547 return itimer_period_actual
;
549 if (collector_timer_settime (period
, collector_master_thread_timerid
) == 0)
551 itimer_period_actual
= collector_timer_gettime (collector_master_thread_timerid
);
552 (void) collector_timer_settime (0, collector_master_thread_timerid
); /* XXXX unset for now */
553 itimer_period_requested
= period
;
554 if (itimer_period_requested
!= itimer_period_actual
)
556 TprintfT (DBG_LT2
, " itimer period %d adjusted to %d\n",
557 itimer_period_requested
, itimer_period_actual
);
558 // (void) __collector_log_write("<event kind=\"%s\" id=\"%d\">%d -> %d</event>\n",
559 // SP_JCMD_CWARN, COL_WARN_PROFRND, itimer_period_requested, itimer_period_actual);
562 TprintfT (DBG_LT2
, " itimer period %d accepted\n", period
);
565 // restore dispatching SIGPROF handler
566 dispatch_mode
= saved
;
567 TprintfT (0, "__collector_ext_itimer_set(%d), requested=%d, actual=%d)\n",
568 rperiod
, itimer_period_requested
, itimer_period_actual
);
569 return (itimer_period_actual
);
573 collector_timer_gettime (timer_t timerid
)
576 struct itimerspec itimer
;
578 return (0); // timer was not initialized
579 if (CALL_REAL (timer_gettime
)(timerid
, &itimer
) == -1)
581 /* this should never reasonably fail, so not worth logging */
582 TprintfT (DBG_LT1
, "WARNING: timer_gettime failed: errno=%d\n", errno
);
585 timer_period
= ((itimer
.it_interval
.tv_sec
* NANOSEC
) +
586 itimer
.it_interval
.tv_nsec
) / 1000;
587 TprintfT (DBG_LT2
, "collector_timer_gettime (period=%d)\n", timer_period
);
588 return (timer_period
);
592 collector_timer_create (timer_t
* ptimerid
)
594 struct sigevent sigev
;
595 if (NULL_PTR (timer_create
))
596 init_interposition_intf ();
597 TprintfT (DBG_LT2
, "collector_timer_settime(): timer_create is %p\n", __real_timer_create
);
598 sigev
.sigev_notify
= SIGEV_THREAD_ID
| SIGEV_SIGNAL
;
599 sigev
.sigev_signo
= SIGPROF
;
600 sigev
.sigev_value
.sival_ptr
= ptimerid
;
601 #if !defined(__MUSL_LIBC)
602 sigev
._sigev_un
._tid
= __collector_gettid ();
604 if (CALL_REAL (timer_create
)(CLOCK_THREAD_CPUTIME_ID
, &sigev
, ptimerid
) == -1)
606 TprintfT (DBG_LT2
, "collector_timer_settime() failed! errno=%d\n", errno
);
613 collector_timer_settime (int period
, timer_t timerid
)
615 struct itimerspec itimer
;
616 if (NULL_PTR (timer_settime
))
617 init_interposition_intf ();
618 TprintfT (DBG_LT2
, "collector_timer_settime(period=%d)\n", period
);
620 itimer
.it_interval
.tv_sec
= NPM
* period
/ NANOSEC
;
621 itimer
.it_interval
.tv_nsec
= (NPM
* period
) % NANOSEC
;
622 itimer
.it_value
= itimer
.it_interval
;
623 if (CALL_REAL (timer_settime
)(timerid
, 0, &itimer
, NULL
) == -1)
625 TprintfT (DBG_LT2
, "collector_timer_settime(%d) failed! errno=%d\n", period
, errno
);
632 protect_profiling_signals (sigset_t
* lset
)
634 static unsigned int protected_sigprof
= 0;
635 static unsigned int protected_sigemt
= 0;
636 // T1 relies on thread signal masking, so best not to mess with it:
637 // T1 users have already been warned about the dangers of its use
638 if (__collector_libthread_T1
)
640 if (sigismember (lset
, SIGPROF
) && (dispatch_mode
== DISPATCH_ON
))
642 TprintfT (0, "WARNING: ignoring %s block while profiling\n", "SIGPROF");
643 if (protected_sigprof
== 0)
644 __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
645 SP_JCMD_CWARN
, COL_WARN_SIGMASK
, "SIGPROF");
646 sigdelset (lset
, SIGPROF
);
649 if (sigismember (lset
, HWCFUNCS_SIGNAL
) && __collector_ext_hwc_active ())
651 TprintfT (0, "WARNING: ignoring %s block while profiling\n", "SIGEMT");
652 if (protected_sigemt
== 0)
653 __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
654 SP_JCMD_CWARN
, COL_WARN_SIGMASK
, HWCFUNCS_SIGNAL_STRING
);
655 sigdelset (lset
, HWCFUNCS_SIGNAL
);
661 init_interposition_intf ()
663 if (__collector_dlsym_guard
)
666 /* Linux requires RTLD_LAZY, Solaris can do just RTLD_NOLOAD */
667 void *handle
= dlopen (SYS_LIBC_NAME
, RTLD_LAZY
| RTLD_NOLOAD
);
669 __real_setitimer
= dlsym (RTLD_NEXT
, "setitimer");
670 if (__real_setitimer
== NULL
)
672 __real_setitimer
= dlsym (RTLD_DEFAULT
, "setitimer");
673 if (__real_setitimer
== NULL
)
675 TprintfT (DBG_LT2
, "init_interposition_intf() setitimer not found\n");
678 dlflag
= RTLD_DEFAULT
;
683 TprintfT (DBG_LT2
, "init_interposition_intf() using RTLD_%s\n",
684 (dlflag
== RTLD_DEFAULT
) ? "DEFAULT" : "NEXT");
686 __real_sigaction
= dlsym (dlflag
, "sigaction");
688 /* also explicitly get libc.so/setitimer (as a backup) */
689 __real_libc_setitimer
= dlsym (handle
, "setitimer");
691 __real_sigprocmask
= dlsym (dlflag
, "sigprocmask");
692 __real_thr_sigsetmask
= dlsym (dlflag
, "thr_sigsetmask");
694 __real_pthread_sigmask_2_32
= dlvsym (dlflag
, "pthread_sigmask", "GLIBC_2.32");
695 __real_pthread_sigmask_2_17
= dlvsym (dlflag
, "pthread_sigmask", "GLIBC_2.17");
696 __real_pthread_sigmask_2_2_5
= dlvsym (dlflag
, "pthread_sigmask", "GLIBC_2.2.5");
697 __real_pthread_sigmask_2_0
= dlvsym (dlflag
, "pthread_sigmask", "GLIBC_2.0");
698 if (__real_pthread_sigmask_2_32
)
699 __real_pthread_sigmask
= __real_pthread_sigmask_2_32
;
700 else if (__real_pthread_sigmask_2_17
)
701 __real_pthread_sigmask
= __real_pthread_sigmask_2_17
;
702 else if (__real_pthread_sigmask_2_2_5
)
703 __real_pthread_sigmask
= __real_pthread_sigmask_2_2_5
;
704 else if (__real_pthread_sigmask_2_0
)
705 __real_pthread_sigmask
= __real_pthread_sigmask_2_0
;
707 __real_pthread_sigmask
= dlsym (dlflag
, "pthread_sigmask");
709 __real_pthread_create_2_34
= dlvsym (dlflag
, "pthread_create", "GLIBC_2.34");
710 __real_pthread_create_2_17
= dlvsym (dlflag
, "pthread_create", "GLIBC_2.17");
711 __real_pthread_create_2_2_5
= dlvsym (dlflag
, "pthread_create", "GLIBC_2.2.5");
712 __real_pthread_create_2_1
= dlvsym (dlflag
, "pthread_create", "GLIBC_2.1");
713 __real_pthread_create_2_0
= dlvsym (dlflag
, "pthread_create", "GLIBC_2.0");
714 if (__real_pthread_create_2_34
)
715 __real_pthread_create
= __real_pthread_create_2_34
;
716 else if (__real_pthread_create_2_17
)
717 __real_pthread_create
= __real_pthread_create_2_17
;
718 else if (__real_pthread_create_2_2_5
)
719 __real_pthread_create
= __real_pthread_create_2_2_5
;
720 else if (__real_pthread_create_2_1
)
721 __real_pthread_create
= __real_pthread_create_2_1
;
722 else if (__real_pthread_create_2_0
)
723 __real_pthread_create
= __real_pthread_create_2_0
;
725 __real_pthread_create
= dlsym (dlflag
, "pthread_create");
727 __real_timer_create_2_34
= dlvsym (dlflag
, "timer_create", "GLIBC_2.34");
728 __real_timer_create_2_17
= dlvsym (dlflag
, "timer_create", "GLIBC_2.17");
729 __real_timer_create_2_3_3
= dlvsym (dlflag
, "timer_create", "GLIBC_2.3.3");
730 __real_timer_create_2_2_5
= dlvsym (dlflag
, "timer_create", "GLIBC_2.2.5");
731 __real_timer_create_2_2
= dlvsym (dlflag
, "timer_create", "GLIBC_2.2");
732 if (__real_timer_create_2_34
)
733 __real_timer_create
= __real_timer_create_2_34
;
734 else if (__real_timer_create_2_17
)
735 __real_timer_create
= __real_timer_create_2_17
;
736 else if (__real_timer_create_2_3_3
)
737 __real_timer_create
= __real_timer_create_2_3_3
;
738 else if (__real_timer_create_2_2_5
)
739 __real_timer_create
= __real_timer_create_2_2_5
;
740 else if (__real_timer_create_2_2
)
741 __real_timer_create
= __real_timer_create_2_2
;
743 __real_timer_create
= dlsym (dlflag
, "timer_create");
746 if ((t
= dlvsym (dlflag
, "timer_settime", "GLIBC_2.34")) != NULL
)
747 __real_timer_settime
= t
;
748 else if ((t
= dlvsym (dlflag
, "timer_settime", "GLIBC_2.17")) != NULL
)
749 __real_timer_settime
= t
;
750 else if ((t
= dlvsym (dlflag
, "timer_settime", "GLIBC_2.3.3")) != NULL
)
751 __real_timer_settime
= t
;
752 else if ((t
= dlvsym (dlflag
, "timer_settime", "GLIBC_2.2.5")) != NULL
)
753 __real_timer_settime
= t
;
754 else if ((t
= dlvsym (dlflag
, "timer_settime", "GLIBC_2.0")) != NULL
)
755 __real_timer_settime
= t
;
757 __real_timer_settime
= dlsym (dlflag
, "timer_settime");
759 if ((t
= dlvsym (dlflag
, "timer_delete", "GLIBC_2.34")) != NULL
)
760 __real_timer_delete
= t
;
761 else if ((t
= dlvsym (dlflag
, "timer_delete", "GLIBC_2.17")) != NULL
)
762 __real_timer_delete
= t
;
763 else if ((t
= dlvsym (dlflag
, "timer_delete", "GLIBC_2.3.3")) != NULL
)
764 __real_timer_delete
= t
;
765 else if ((t
= dlvsym (dlflag
, "timer_delete", "GLIBC_2.2.5")) != NULL
)
766 __real_timer_delete
= t
;
767 else if ((t
= dlvsym (dlflag
, "timer_delete", "GLIBC_2.2")) != NULL
)
768 __real_timer_delete
= t
;
770 __real_timer_delete
= dlsym (dlflag
, "timer_delete");
772 if ((t
= dlvsym (dlflag
, "timer_gettime", "GLIBC_2.34")) != NULL
)
773 __real_timer_gettime
= t
;
774 else if ((t
= dlvsym (dlflag
, "timer_gettime", "GLIBC_2.17")) != NULL
)
775 __real_timer_gettime
= t
;
776 else if ((t
= dlvsym (dlflag
, "timer_gettime", "GLIBC_2.3.3")) != NULL
)
777 __real_timer_gettime
= t
;
778 else if ((t
= dlvsym (dlflag
, "timer_gettime", "GLIBC_2.2.5")) != NULL
)
779 __real_timer_gettime
= t
;
780 else if ((t
= dlvsym (dlflag
, "timer_gettime", "GLIBC_2.0")) != NULL
)
781 __real_timer_gettime
= t
;
783 __real_timer_gettime
= dlsym (dlflag
, "timer_gettime");
785 __real_clone
= dlsym (dlflag
, "clone");
787 #define PR_FUNC(f) TprintfT (DBG_LT2, " dispetcher.c: " #f ": @%p\n", f)
788 PR_FUNC (__real_clone
);
789 PR_FUNC (__real_libc_setitimer
);
790 PR_FUNC (__real_pthread_create
);
791 PR_FUNC (__real_pthread_create_2_0
);
792 PR_FUNC (__real_pthread_create_2_1
);
793 PR_FUNC (__real_pthread_create_2_17
);
794 PR_FUNC (__real_pthread_create_2_2_5
);
795 PR_FUNC (__real_pthread_create_2_34
);
796 PR_FUNC (__real_pthread_sigmask
);
797 PR_FUNC (__real_pthread_sigmask_2_0
);
798 PR_FUNC (__real_pthread_sigmask_2_2_5
);
799 PR_FUNC (__real_pthread_sigmask_2_17
);
800 PR_FUNC (__real_pthread_sigmask_2_32
);
801 PR_FUNC (__real_setitimer
);
802 PR_FUNC (__real_sigaction
);
803 PR_FUNC (__real_sigprocmask
);
804 PR_FUNC (__real_thr_sigsetmask
);
805 PR_FUNC (__real_timer_create
);
806 PR_FUNC (__real_timer_create_2_17
);
807 PR_FUNC (__real_timer_create_2_2
);
808 PR_FUNC (__real_timer_create_2_2_5
);
809 PR_FUNC (__real_timer_create_2_3_3
);
810 PR_FUNC (__real_timer_create_2_34
);
811 PR_FUNC (__real_timer_delete
);
812 PR_FUNC (__real_timer_gettime
);
813 PR_FUNC (__real_timer_settime
);
819 /*------------------------------------------------------------- sigaction */
821 /* NB: need a global interposing function called "sigaction" */
823 sigaction (int sig
, const struct sigaction
*nact
, struct sigaction
*oact
)
827 if (NULL_PTR (sigaction
))
828 err
= init_interposition_intf ();
831 TprintfT (DBG_LT3
, "sigaction(sig=%02d, nact=%p) interposing\n", sig
, nact
);
832 if (sig
== SIGPROF
&& dispatch_mode
!= DISPATCH_NYI
)
836 oact
->sa_handler
= original_sigprof_handler
.sa_handler
;
837 oact
->sa_mask
= original_sigprof_handler
.sa_mask
;
838 oact
->sa_flags
= original_sigprof_handler
.sa_flags
;
842 original_sigprof_handler
.sa_handler
= nact
->sa_handler
;
843 original_sigprof_handler
.sa_mask
= nact
->sa_mask
;
844 original_sigprof_handler
.sa_flags
= nact
->sa_flags
;
845 TprintfT (DBG_LT1
, "dispatcher: new sigaction(sig=%02d) set\n", sig
);
848 else if (sig
== HWCFUNCS_SIGNAL
)
849 ret
= collector_sigemt_sigaction (nact
, oact
);
852 if (sig
!= SIGCHLD
|| collector_sigchld_sigaction (nact
, oact
))
853 ret
= CALL_REAL (sigaction
)(sig
, nact
, oact
);
854 TprintfT (DBG_LT3
, "Real sigaction(sig=%02d) returned %d (oact=%p)\n",
856 /* but check for other important signals */
857 /* check for sample and pause/resume signals; give warning once, if need be */
858 if ((sig
== __collector_sample_sig
) && (__collector_sample_sig_warn
== 0))
860 /* give user a warning */
861 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n",
862 SP_JCMD_CWARN
, COL_WARN_SAMPSIGUSED
, __collector_sample_sig
);
863 __collector_sample_sig_warn
= 1;
865 if ((sig
== __collector_pause_sig
) && (__collector_pause_sig_warn
== 0))
867 /* give user a warning */
868 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n",
869 SP_JCMD_CWARN
, COL_WARN_PAUSESIGUSED
, __collector_pause_sig
);
870 __collector_pause_sig_warn
= 1;
873 TprintfT (DBG_LT3
, "sigaction() returning %d (oact=%p)\n", ret
, oact
);
878 * In addition to interposing on sigaction(), should we also interpose
879 * on other important signal functions like signal() or sigset()?
880 * - On Solaris, those other functions apparently call sigaction().
881 * So, we only have to interpose on it.
882 * - On Linux, we should perhaps interpose on these other functions,
883 * but they are less portable than sigaction() and deprecated or even obsolete.
884 * So, we interpose, but don't overly worry about doing a good job.
887 signal (int sig
, sighandler_t handler
)
889 struct sigaction nact
;
890 struct sigaction oact
;
891 TprintfT (DBG_LT3
, "signal(sig=%02d, handler=%p) interposing\n", sig
, handler
);
892 sigemptyset (&nact
.sa_mask
);
893 nact
.sa_handler
= handler
;
894 nact
.sa_flags
= SA_RESTART
;
895 if (sigaction (sig
, &nact
, &oact
))
897 TprintfT (DBG_LT3
, "signal() returning %p\n", oact
.sa_handler
);
898 return oact
.sa_handler
;
902 sigset (int sig
, sighandler_t handler
)
904 TprintfT (DBG_LT3
, "sigset(sig=%02d, handler=%p) interposing\n", sig
, handler
);
905 return signal (sig
, handler
);
908 /*------------------------------------------------------------- timer_create */
910 // map interposed symbol versions
912 gprofng_timer_create (int (real_func
) (), clockid_t clockid
,
913 struct sigevent
*sevp
, timer_t
*timerid
)
915 // collector reserves SIGPROF
916 if (sevp
== NULL
|| sevp
->sigev_notify
!= SIGEV_SIGNAL
||
917 sevp
->sigev_signo
!= SIGPROF
)
919 int ret
= real_func (clockid
, sevp
, timerid
);
920 TprintfT (DBG_LT2
, "timer_create @%p (%d) ret=%d\n", real_func
,
925 /* log that application's timer_create request is overridden */
926 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n",
927 SP_JCMD_CWARN
, COL_WARN_ITMROVR
, -1);
929 TprintfT (DBG_LT2
, "timer_create @%p (%d) ret=%d\n", real_func
,
930 (int) clockid
, -1); \
934 #define DCL_TIMER_CREATE(dcl_f) \
935 int dcl_f (clockid_t clockid, struct sigevent *sevp, timer_t *timerid) \
937 if (__real_timer_create == NULL) \
938 init_interposition_intf (); \
939 return gprofng_timer_create (__real_timer_create, clockid, sevp, timerid); \
942 DCL_FUNC_VER (DCL_TIMER_CREATE
, timer_create_2_34
, timer_create@GLIBC_2
.34
)
943 DCL_FUNC_VER (DCL_TIMER_CREATE
, timer_create_2_17
, timer_create@GLIBC_2
.17
)
944 DCL_FUNC_VER (DCL_TIMER_CREATE
, timer_create_2_3_3
, timer_create@GLIBC_2
.3
.3)
945 DCL_FUNC_VER (DCL_TIMER_CREATE
, timer_create_2_2_5
, timer_create@GLIBC_2
.2
.5)
946 DCL_FUNC_VER (DCL_TIMER_CREATE
, timer_create_2_2
, timer_create@GLIBC_2
.2
)
947 DCL_TIMER_CREATE (timer_create
)
949 /*------------------------------------------------------------- setitimer */
951 _setitimer (int which
, const struct itimerval
*nval
,
952 struct itimerval
*oval
)
957 if (NULL_PTR (setitimer
))
958 init_interposition_intf ();
963 period
= (nval
->it_interval
.tv_sec
* MICROSEC
) +
964 nval
->it_interval
.tv_usec
;
965 TprintfT (DBG_LT1
, "setitimer(which=%d,nval=%dus) interposing\n", which
, period
);
967 /* collector reserves ITIMER_REALPROF for its own use, and ITIMER_PROF
968 * uses the same signal (SIGPROF) so it must also be reserved
970 if (((which
!= ITIMER_REALPROF
) && (which
!= ITIMER_PROF
)) || (nval
== NULL
))
972 ret
= CALL_REAL (setitimer
)(which
, nval
, oval
);
976 period
= (oval
->it_interval
.tv_sec
* MICROSEC
) +
977 oval
->it_interval
.tv_usec
;
978 TprintfT (DBG_LT2
, "Real setitimer(%d) returned %d (oval=%dus)\n",
982 /* log that application's setitimer request is overridden */
983 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%d</event>\n",
984 SP_JCMD_CWARN
, COL_WARN_ITMROVR
, period
);
989 getitimer (which
, oval
); /* return current itimer setting */
990 period
= (oval
->it_interval
.tv_sec
* MICROSEC
) +
991 oval
->it_interval
.tv_usec
;
995 TprintfT (DBG_LT2
, "setitimer() returning %d (oval=%dus)\n", ret
, period
);
999 /*--------------------------------------------------------------- sigprocmask */
1001 __collector_sigprocmask (int how
, const sigset_t
* iset
, sigset_t
* oset
)
1004 if (NULL_PTR (sigprocmask
))
1005 err
= init_interposition_intf ();
1008 TprintfT (DBG_LT2
, "__collector_sigprocmask(%d) interposing\n", how
);
1010 sigset_t
* lset
= NULL
;
1015 if ((how
== SIG_BLOCK
) || (how
== SIG_SETMASK
))
1016 protect_profiling_signals (lset
);
1018 int ret
= CALL_REAL (sigprocmask
)(how
, lset
, oset
);
1019 TprintfT (DBG_LT2
, "__collector_sigprocmask(%d) returning %d\n", how
, ret
);
1023 /*------------------------------------------------------------ thr_sigsetmask */
1025 __collector_thr_sigsetmask (int how
, const sigset_t
* iset
, sigset_t
* oset
)
1027 if (NULL_PTR (thr_sigsetmask
))
1028 init_interposition_intf ();
1029 TprintfT (DBG_LT1
, "__collector_thr_sigsetmask(%d) interposing\n", how
);
1031 sigset_t
* lset
= NULL
;
1036 if ((how
== SIG_BLOCK
) || (how
== SIG_SETMASK
))
1037 protect_profiling_signals (lset
);
1039 int ret
= CALL_REAL (thr_sigsetmask
)(how
, lset
, oset
);
1040 TprintfT (DBG_LT1
, "__collector_thr_sigsetmask(%d) returning %d\n", how
, ret
);
1044 /*----------------------------------------------------------- pthread_sigmask */
1045 // map interposed symbol versions
1048 gprofng_pthread_sigmask (int (real_func
) (),
1049 int how
, const sigset_t
*iset
, sigset_t
* oset
)
1052 sigset_t
* lset
= NULL
;
1057 if (how
== SIG_BLOCK
|| how
== SIG_SETMASK
)
1058 protect_profiling_signals (lset
);
1060 int ret
= (real_func
) (how
, lset
, oset
);
1061 TprintfT (DBG_LT1
, "real_pthread_sigmask @%p (%d) ret=%d\n",
1062 real_func
, how
, ret
);
1067 #define DCL_PTHREAD_SIGMASK(dcl_f) \
1068 int dcl_f (int how, const sigset_t *iset, sigset_t* oset) \
1070 if (__real_pthread_sigmask == NULL) \
1071 init_interposition_intf (); \
1072 return gprofng_pthread_sigmask (__real_pthread_sigmask, how, iset, oset); \
1075 DCL_FUNC_VER (DCL_PTHREAD_SIGMASK
, pthread_sigmask_2_32
, pthread_sigmask@GLIBC_2
.32
)
1076 DCL_FUNC_VER (DCL_PTHREAD_SIGMASK
, pthread_sigmask_2_17
, pthread_sigmask@GLIBC_2
.17
)
1077 DCL_FUNC_VER (DCL_PTHREAD_SIGMASK
, pthread_sigmask_2_2_5
, pthread_sigmask@GLIBC_2
.2
.5)
1078 DCL_FUNC_VER (DCL_PTHREAD_SIGMASK
, pthread_sigmask_2_0
, pthread_sigmask@GLIBC_2
.0
)
1079 DCL_PTHREAD_SIGMASK (pthread_sigmask
)
1081 /*----------------------------------------------------------- pthread_create */
1082 typedef struct _CollectorArgs
1084 void *(*func
)(void*);
1091 collector_root (void *cargs
)
1093 /* save the real arguments and free cargs */
1094 void *(*func
)(void*) = ((CollectorArgs
*) cargs
)->func
;
1095 void *arg
= ((CollectorArgs
*) cargs
)->arg
;
1096 void *stack
= ((CollectorArgs
*) cargs
)->stack
;
1097 int isPthread
= ((CollectorArgs
*) cargs
)->isPthread
;
1098 __collector_freeCSize (__collector_heap
, cargs
, sizeof (CollectorArgs
));
1100 /* initialize tsd for this thread */
1101 if (__collector_tsd_allocate () == 0)
1102 /* init tsd for unwind, called right after __collector_tsd_allocate()*/
1103 __collector_ext_unwind_key_init (isPthread
, stack
);
1106 __collector_mutex_lock (&collector_clone_libc_lock
);
1108 /* set the profile timer */
1109 timer_t
*timeridptr
= __collector_tsd_get_by_key (dispatcher_key
);
1110 timer_t timerid
= NULL
;
1111 if (timeridptr
!= NULL
)
1113 collector_timer_create (timeridptr
);
1114 if (*timeridptr
!= NULL
)
1115 collector_timer_settime (itimer_period_requested
, *timeridptr
);
1116 timerid
= *timeridptr
;
1118 int hwc_rc
= __collector_ext_hwc_lwp_init ();
1121 __collector_mutex_unlock (&collector_clone_libc_lock
);
1122 /* call the real function */
1123 void *ret
= func (arg
);
1125 __collector_mutex_lock (&collector_clone_libc_lock
);
1126 if (timerid
!= NULL
)
1127 CALL_REAL (timer_delete
)(timerid
);
1129 /* pthread_kill not handled here */
1130 __collector_ext_hwc_lwp_fini ();
1133 __collector_mutex_unlock (&collector_clone_libc_lock
);
1134 /* if we have this chance, release tsd */
1135 __collector_tsd_release ();
1140 // map interposed symbol versions
1143 gprofng_pthread_create (int (real_func
) (), pthread_t
*thread
,
1144 const pthread_attr_t
*attr
,
1145 void *(*func
)(void*), void *arg
)
1147 TprintfT (DBG_LTT
, "gprofng_pthread_create @%p\n", real_func
);
1148 if (dispatch_mode
!= DISPATCH_ON
)
1149 return (real_func
) (thread
, attr
, func
, arg
);
1150 CollectorArgs
*cargs
= __collector_allocCSize (__collector_heap
,
1151 sizeof (CollectorArgs
), 1);
1153 return (real_func
) (thread
, attr
, func
, arg
);
1156 cargs
->stack
= NULL
;
1157 cargs
->isPthread
= 1;
1158 int ret
= (real_func
) (thread
, attr
, &collector_root
, cargs
);
1160 __collector_freeCSize (__collector_heap
, cargs
, sizeof (CollectorArgs
));
1161 TprintfT (DBG_LT1
, "gprofng_pthread_create @%p returns %d\n", real_func
, ret
);
1166 #define DCL_PTHREAD_CREATE(dcl_f) \
1167 int dcl_f (pthread_t *thread, const pthread_attr_t *attr, \
1168 void *(*func)(void*), void *arg) \
1170 if (__real_pthread_create == NULL) \
1171 init_interposition_intf (); \
1172 return gprofng_pthread_create (__real_pthread_create, thread, attr, func, arg); \
1175 DCL_FUNC_VER (DCL_PTHREAD_CREATE
, pthread_create_2_34
, pthread_create@GLIBC_2
.34
)
1176 DCL_FUNC_VER (DCL_PTHREAD_CREATE
, pthread_create_2_17
, pthread_create@GLIBC_2
.17
)
1177 DCL_FUNC_VER (DCL_PTHREAD_CREATE
, pthread_create_2_2_5
, pthread_create@GLIBC_2
.2
.5)
1178 DCL_FUNC_VER (DCL_PTHREAD_CREATE
, pthread_create_2_1
, pthread_create@GLIBC_2
.1
)
1179 DCL_FUNC_VER (DCL_PTHREAD_CREATE
, pthread_create_2_0
, pthread_create@GLIBC_2
.0
)
1180 DCL_PTHREAD_CREATE (pthread_create
)
1183 __collector_ext_clone_pthread (int (*fn
)(void *), void *child_stack
, int flags
, void *arg
,
1184 va_list va
/* pid_t *ptid, struct user_desc *tls, pid_t *" ctid" */)
1186 if (NULL_PTR (clone
))
1187 init_interposition_intf ();
1188 TprintfT (0, "clone thread interposing\n");
1189 pid_t
* ptid
= NULL
;
1190 struct user_desc
* tls
= NULL
;
1191 pid_t
* ctid
= NULL
;
1193 if (flags
& (CLONE_CHILD_SETTID
| CLONE_CHILD_CLEARTID
))
1195 ptid
= va_arg (va
, pid_t
*);
1196 tls
= va_arg (va
, struct user_desc
*);
1197 ctid
= va_arg (va
, pid_t
*);
1200 else if (flags
& CLONE_SETTLS
)
1202 ptid
= va_arg (va
, pid_t
*);
1203 tls
= va_arg (va
, struct user_desc
*);
1206 else if (flags
& CLONE_PARENT_SETTID
)
1208 ptid
= va_arg (va
, pid_t
*);
1212 if (dispatch_mode
!= DISPATCH_ON
)
1217 ret
= CALL_REAL (clone
)(fn
, child_stack
, flags
, arg
, ptid
, tls
, ctid
);
1220 ret
= CALL_REAL (clone
)(fn
, child_stack
, flags
, arg
, ptid
, tls
);
1223 ret
= CALL_REAL (clone
)(fn
, child_stack
, flags
, arg
, ptid
);
1226 ret
= CALL_REAL (clone
)(fn
, child_stack
, flags
, arg
);
1231 CollectorArgs
*cargs
= __collector_allocCSize (__collector_heap
, sizeof (CollectorArgs
), 1);
1237 ret
= CALL_REAL (clone
)(fn
, child_stack
, flags
, arg
, ptid
, tls
, ctid
);
1240 ret
= CALL_REAL (clone
)(fn
, child_stack
, flags
, arg
, ptid
, tls
);
1243 ret
= CALL_REAL (clone
)(fn
, child_stack
, flags
, arg
, ptid
);
1246 ret
= CALL_REAL (clone
)(fn
, child_stack
, flags
, arg
);
1252 cargs
->func
= (void *(*)(void*))fn
;
1254 cargs
->stack
= child_stack
;
1255 cargs
->isPthread
= 0;
1260 ret
= CALL_REAL (clone
)((int(*)(void*))collector_root
, child_stack
, flags
, cargs
, ptid
, tls
, ctid
);
1263 ret
= CALL_REAL (clone
)((int(*)(void*))collector_root
, child_stack
, flags
, cargs
, ptid
, tls
);
1266 ret
= CALL_REAL (clone
)((int(*)(void*))collector_root
, child_stack
, flags
, cargs
, ptid
);
1269 ret
= CALL_REAL (clone
)((int(*)(void*))collector_root
, child_stack
, flags
, cargs
);
1274 __collector_freeCSize (__collector_heap
, cargs
, sizeof (CollectorArgs
));
1275 TprintfT (DBG_LT1
, "clone thread returning %d\n", ret
);
1280 int sigprocmask () __attribute__ ((weak
, alias ("__collector_sigprocmask")));
1281 int thr_sigsetmask () __attribute__ ((weak
, alias ("__collector_thr_sigsetmask")));
1282 int setitimer () __attribute__ ((weak
, alias ("_setitimer")));