gprofng: adjust GPROFNG_VARIANT
[binutils-gdb.git] / gprofng / libcollector / dispatcher.c
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
55 static void collector_sigprof_dispatcher (int, siginfo_t*, void*);
56 static int init_interposition_intf ();
57 #include "memmgr.h"
58 static int collector_timer_create (timer_t * ptimerid);
59 static int collector_timer_settime (int period, timer_t timerid);
60 static int collector_timer_gettime (timer_t timerid);
61 static volatile int collector_sigprof_entries = 0; /* counter for SIGPROF signals in DISPATCH_TST mode */
62 static timer_t collector_master_thread_timerid = NULL;
63 static collector_mutex_t collector_clone_libc_lock = COLLECTOR_MUTEX_INITIALIZER;
64 static unsigned dispatcher_key = COLLECTOR_TSD_INVALID_KEY;
65
66 static void *__real_clone = NULL;
67 static void *__real_timer_create = NULL;
68 static void *__real_timer_settime = NULL;
69 static void *__real_timer_delete = NULL;
70 static void *__real_timer_gettime = NULL;
71 #if ARCH(Intel) && WSIZE(32)
72 static void *__real_pthread_create_2_1 = NULL;
73 static void *__real_pthread_create_2_0 = NULL;
74 #elif ARCH(Intel) && WSIZE(64)
75 static void *__real_timer_create_2_3_3 = NULL;
76 static void *__real_timer_create_2_2_5 = NULL;
77 #elif ARCH(SPARC) && WSIZE(64)
78 static void *__real_timer_create_2_3_3 = NULL;
79 static 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. */
84 static struct sigaction original_sigprof_handler;
85
86 enum
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
94 static int dispatch_mode = DISPATCH_NYI; /* controls SIGPROF dispatching */
95 static int itimer_period_requested = 0; /* dispatcher itimer period */
96 static 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
101 static void *__real_sigaction = NULL;
102 static void *__real_setitimer = NULL;
103 static void *__real_libc_setitimer = NULL;
104 static void *__real_sigprocmask = NULL;
105 static void *__real_thr_sigsetmask = NULL;
106 static void *__real_pthread_sigmask = NULL;
107 static 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 */
116 static void
117 collector_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 */
231 int
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 */
262 void
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 */
272 int
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
311 int
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 */
334 void
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 */
353 void
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
362 int
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
380 void
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
398 void
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
426 void
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 */
486 void
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 */
505 int
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
549 static int
550 collector_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
568 static int
569 collector_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
587 static int
588 collector_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
606 static void
607 protect_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
641 static int
642 init_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" */
726 int
727 sigaction (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 */
790 sighandler_t
791 signal (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
805 sighandler_t
806 sigset (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)
817 static int
818 __collector_timer_create_symver (int(real_timer_create) (), clockid_t clockid, struct sigevent *sevp,
819 timer_t *timerid);
820
821 SYMVER_ATTRIBUTE (__collector_timer_create_2_3_3, timer_create@@GLIBC_2.3.3)
822 int
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
835 SYMVER_ATTRIBUTE (__collector_timer_create_2_2, timer_create@GLIBC_2.2)
836 int
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
848 SYMVER_ATTRIBUTE (__collector_timer_create_2_2_5, timer_create@GLIBC_2.2.5)
849 int
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))
862 int timer_create (clockid_t clockid, struct sigevent *sevp, timer_t *timerid)
863 #else
864 static 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 */
898 int
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 */
948 int
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 */
972 int
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
994 int
995 pthread_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 */
1014 typedef struct _CollectorArgs
1015 {
1016 void *(*func)(void*);
1017 void *arg;
1018 void *stack;
1019 int isPthread;
1020 } CollectorArgs;
1021
1022 static void *
1023 collector_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)
1074 static 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
1081 SYMVER_ATTRIBUTE (__collector_pthread_create_2_1, pthread_create@@GLIBC_2.1)
1082 int
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
1094 SYMVER_ATTRIBUTE (__collector_pthread_create_2_0, pthread_create@GLIBC_2.0)
1095 int
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)
1110 static 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
1117 int
1118 pthread_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
1161 int
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:
1259 int sigprocmask () __attribute__ ((weak, alias ("__collector_sigprocmask")));
1260 int thr_sigsetmask () __attribute__ ((weak, alias ("__collector_thr_sigsetmask")));
1261 int setitimer () __attribute__ ((weak, alias ("_setitimer")));