xref: /netbsd-src/external/gpl3/binutils.old/dist/gprofng/libcollector/dispatcher.c (revision c42dbd0ed2e61fe6eda8590caa852ccf34719964)
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
collector_sigprof_dispatcher(int sig,siginfo_t * info,void * context)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
__collector_sigprof_install()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
__collector_ext_dispatcher_tsd_create_key()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
__collector_ext_dispatcher_install()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
__collector_sigaction(int sig,const struct sigaction * nact,struct sigaction * oact)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
__collector_SIGDFL_handler(int sig)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
__collector_ext_dispatcher_thread_timer_suspend()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
__collector_ext_dispatcher_thread_timer_resume()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
__collector_ext_dispatcher_suspend()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
__collector_ext_dispatcher_restart()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
__collector_ext_dispatcher_deinstall()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
__collector_ext_dispatcher_fork_child_cleanup()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
__collector_ext_itimer_set(int rperiod)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
collector_timer_gettime(timer_t timerid)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
collector_timer_create(timer_t * ptimerid)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
collector_timer_settime(int period,timer_t timerid)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
protect_profiling_signals(sigset_t * lset)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
init_interposition_intf()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
sigaction(int sig,const struct sigaction * nact,struct sigaction * oact)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
signal(int sig,sighandler_t handler)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
sigset(int sig,sighandler_t handler)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
__collector_timer_create_2_3_3(clockid_t clockid,struct sigevent * sevp,timer_t * timerid)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
__collector_timer_create_2_2(clockid_t clockid,struct sigevent * sevp,timer_t * timerid)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
__collector_timer_create_2_2_5(clockid_t clockid,struct sigevent * sevp,timer_t * timerid)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))
timer_create(clockid_t clockid,struct sigevent * sevp,timer_t * timerid)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
_setitimer(int which,const struct itimerval * nval,struct itimerval * oval)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
__collector_sigprocmask(int how,const sigset_t * iset,sigset_t * oset)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
__collector_thr_sigsetmask(int how,const sigset_t * iset,sigset_t * oset)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
pthread_sigmask(int how,const sigset_t * iset,sigset_t * oset)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 *
collector_root(void * cargs)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
__collector_pthread_create_2_1(pthread_t * thread,const pthread_attr_t * attr,void * (* func)(void *),void * arg)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
__collector_pthread_create_2_0(pthread_t * thread,const pthread_attr_t * attr,void * (* func)(void *),void * arg)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
__collector_pthread_create_symver(int (real_pthread_create)(),pthread_t * thread,const pthread_attr_t * attr,void * (* func)(void *),void * arg)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
__collector_ext_clone_pthread(int (* fn)(void *),void * child_stack,int flags,void * arg,va_list va)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")));
1262