]> Git Repo - binutils.git/blob - gprofng/libcollector/synctrace.c
Automatic date update in version.in
[binutils.git] / gprofng / libcollector / synctrace.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  *      Synchronization events
23  */
24 #include "config.h"
25 #include <alloca.h>
26 #include <dlfcn.h>
27 #include <unistd.h>
28 #include <semaphore.h>          /* sem_wait() */
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/param.h>
32 #include <pthread.h>
33
34 #include "gp-defs.h"
35 #include "collector.h"
36 #include "gp-experiment.h"
37 #include "data_pckts.h"
38 #include "tsd.h"
39 #include "cc_libcollector.h"
40
41 /* TprintfT(<level>,...) definitions.  Adjust per module as needed */
42 #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
43 #define DBG_LTT 0 // for interposition on GLIBC functions
44 #define DBG_LT1 1 // for configuration details, warnings
45 #define DBG_LT2 2
46 #define DBG_LT3 3
47
48 /* define the packet that will be written out */
49 typedef struct Sync_packet
50 { /* Synchronization delay tracing packet */
51   Common_packet comm;
52   hrtime_t requested;       /* time of synchronization request */
53   Vaddr_type objp;          /* vaddr of synchronization object */
54 } Sync_packet;
55
56 static int open_experiment (const char *);
57 static int start_data_collection (void);
58 static int stop_data_collection (void);
59 static int close_experiment (void);
60 static int detach_experiment (void);
61 static int init_thread_intf ();
62 static int sync_calibrate ();
63
64 static ModuleInterface module_interface ={
65   SP_SYNCTRACE_FILE,        /* description */
66   NULL,                     /* initInterface */
67   open_experiment,          /* openExperiment */
68   start_data_collection,    /* startDataCollection */
69   stop_data_collection,     /* stopDataCollection */
70   close_experiment,         /* closeExperiment */
71   detach_experiment         /* detachExperiment (fork child) */
72 };
73
74 static CollectorInterface *collector_interface = NULL;
75 static int sync_mode = 0;
76 static long sync_scope = 0;
77 static int sync_native = 0;
78 static int sync_java = 0;
79 static CollectorModule sync_hndl = COLLECTOR_MODULE_ERR;
80 static unsigned sync_key = COLLECTOR_TSD_INVALID_KEY;
81 static long sync_threshold = -1; /* calibrate the value */
82 static int init_thread_intf_started = 0;
83 static int init_thread_intf_finished = 0;
84
85 #define CHCK_NREENTRANCE(x)     (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
86 #define RECHCK_NREENTRANCE(x)   (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
87 #define CHCK_JREENTRANCE(x)     (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
88 #define RECHCK_JREENTRANCE(x)   (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
89 #define PUSH_REENTRANCE(x)      ((*(x))++)
90 #define POP_REENTRANCE(x)       ((*(x))--)
91
92 #define CALL_REAL(x)            (*(int(*)())__real_##x)
93 #define NULL_PTR(x)             ( __real_##x == NULL )
94 #define gethrtime       collector_interface->getHiResTime
95
96 #ifdef DEBUG
97 #define Tprintf(...)   if (collector_interface) collector_interface->writeDebugInfo( 0, __VA_ARGS__ )
98 #define TprintfT(...)  if (collector_interface) collector_interface->writeDebugInfo( 1, __VA_ARGS__ )
99 #else
100 #define Tprintf(...)
101 #define TprintfT(...)
102 #endif
103
104 /*
105  * In most cases, the functions which require interposition are implemented as
106  * weak symbols corresponding to an associated internal function named with a
107  * leading underscore: e.g., mutex_lock() is simply an alias for _mutex_lock().
108  * For the wait functions, however, the published version (used by applications)
109  * is distinct from the internal version (used by system libraries), i.e.,
110  * cond_wait() is an alias for _cond_wait_cancel() rather than _cond_wait().
111  */
112 static void *__real_strtol = NULL;
113 static void *__real_fprintf = NULL;
114 static void *__real___collector_jprofile_enable_synctrace = NULL;
115 static void *__real_pthread_mutex_lock = NULL;
116 static void *__real_pthread_mutex_unlock = NULL; /* not interposed, used in calibrate */
117 static void *__real_pthread_cond_wait = NULL;
118 static void *__real_pthread_cond_timedwait = NULL;
119 static void *__real_pthread_join = NULL;
120 static void *__real_sem_wait = NULL;
121 static void *__real_pthread_cond_wait_2_3_2 = NULL;
122 static void *__real_pthread_cond_timedwait_2_3_2 = NULL;
123
124 #if WSIZE(32)
125 static void *__real_sem_wait_2_1 = NULL;
126 static void *__real_sem_wait_2_0 = NULL;
127 static void *__real_pthread_cond_wait_2_0 = NULL;
128 static void *__real_pthread_cond_timedwait_2_0 = NULL;
129 #elif WSIZE(64)
130 #if ARCH(Intel)
131 static void *__real_pthread_cond_wait_2_2_5 = NULL;
132 static void *__real_pthread_cond_timedwait_2_2_5 = NULL;
133 #elif ARCH(SPARC)
134 static void *__real_pthread_cond_wait_2_2 = NULL;
135 static void *__real_pthread_cond_timedwait_2_2 = NULL;
136 #endif  /* ARCH() */
137 #endif /* WSIZE() */
138
139 static void
140 collector_memset (void *s, int c, size_t n)
141 {
142   unsigned char *s1 = s;
143   while (n--)
144     *s1++ = (unsigned char) c;
145 }
146
147 void
148 __collector_module_init (CollectorInterface *_collector_interface)
149 {
150   if (_collector_interface == NULL)
151     return;
152   collector_interface = _collector_interface;
153   TprintfT (0, "synctrace: __collector_module_init\n");
154   sync_hndl = collector_interface->registerModule (&module_interface);
155
156   /* Initialize next module */
157   ModuleInitFunc next_init = (ModuleInitFunc) dlsym (RTLD_NEXT, "__collector_module_init");
158   if (next_init != NULL)
159     next_init (_collector_interface);
160 }
161
162 static int
163 open_experiment (const char *exp)
164 {
165   long thresh = 0;
166   if (init_thread_intf_finished == 0)
167     init_thread_intf ();
168   if (collector_interface == NULL)
169     {
170       Tprintf (0, "synctrace: collector_interface is null.\n");
171       return COL_ERROR_SYNCINIT;
172     }
173   if (sync_hndl == COLLECTOR_MODULE_ERR)
174     {
175       Tprintf (0, "synctrace: handle create failed.\n");
176       collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">data handle not created</event>\n",
177                                      SP_JCMD_CERROR, COL_ERROR_SYNCINIT);
178       return COL_ERROR_SYNCINIT;
179     }
180   TprintfT (0, "synctrace: open_experiment %s\n", exp);
181
182   char *params = (char *) collector_interface->getParams ();
183   while (params)
184     {
185       if ((params[0] == 's') && (params[1] == ':'))
186         {
187           char *ptr = params + 2;
188           Tprintf (DBG_LT1, "synctrace: open_experiment s: parameter = %s\n", ptr);
189           while (*ptr != ',' && *ptr != ';')
190             ptr++;
191           sync_scope = 0;
192           if (*ptr == ',')
193             {
194               sync_scope = CALL_REAL (strtol) (ptr + 1, NULL, 0);
195               switch (sync_scope)
196                 {
197                 case 1:
198                   sync_java = 0;
199                   sync_native = 1;
200                   break;
201                 case 2:
202                   sync_java = 1;
203                   sync_native = 0;
204                   break;
205                 default:
206                 case 3:
207                   sync_native = 1;
208                   sync_java = 1;
209                   break;
210                 }
211               Tprintf (0, "\tsynctrace: sync_scope found as %ld\n", sync_scope);
212             }
213           else
214             {
215               /* the old-style descriptor, without scope */
216               /* if there was no comma, use the old default */
217               sync_scope = 3;
218               sync_java = 1;
219               sync_native = 1;
220               Tprintf (0, "\tsynctrace: sync_scope not found set to %ld\n", sync_scope);
221             }
222           if (__real___collector_jprofile_enable_synctrace == NULL)
223             sync_java = 0;
224           thresh = CALL_REAL (strtol)(params + 2, NULL, 0);
225           break; /* from the loop to find the "s:thresh,scope" entry */
226         }
227       else
228         params++;
229     }
230   if (params == NULL)  /* Sync data collection not specified */
231     return COL_ERROR_SYNCINIT;
232   if (thresh < 0)  /* calibrate the threshold, keep it as a negative number */
233     thresh = -sync_calibrate ();
234
235   sync_key = collector_interface->createKey (sizeof ( int), NULL, NULL);
236   if (sync_key == (unsigned) - 1)
237     {
238       Tprintf (0, "synctrace: TSD key create failed.\n");
239       collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">TSD key not created</event>\n",
240                                      SP_JCMD_CERROR, COL_ERROR_SYNCINIT);
241       return COL_ERROR_SYNCINIT;
242     }
243   /* if Java synctrace was requested, tell the jprofile module */
244   if (sync_java)
245     {
246       TprintfT (0, "synctrace: enabling Java synctrace\n");
247       CALL_REAL (__collector_jprofile_enable_synctrace)();
248     }
249   collector_interface->writeLog ("<profile name=\"%s\" threshold=\"%ld\" scope=\"%ld\">\n",
250                                  SP_JCMD_SYNCTRACE, thresh, sync_scope);
251   collector_interface->writeLog ("  <profdata fname=\"%s\"/>\n",
252                                  module_interface.description);
253   /* Record Sync_packet description */
254   Sync_packet *pp = NULL;
255   collector_interface->writeLog ("  <profpckt kind=\"%d\" uname=\"Synchronization tracing data\">\n", SYNC_PCKT);
256   collector_interface->writeLog ("    <field name=\"LWPID\" uname=\"Lightweight process id\" offset=\"%d\" type=\"%s\"/>\n",
257                                  &pp->comm.lwp_id, sizeof (pp->comm.lwp_id) == 4 ? "INT32" : "INT64");
258   collector_interface->writeLog ("    <field name=\"THRID\" uname=\"Thread number\" offset=\"%d\" type=\"%s\"/>\n",
259                                  &pp->comm.thr_id, sizeof (pp->comm.thr_id) == 4 ? "INT32" : "INT64");
260   collector_interface->writeLog ("    <field name=\"CPUID\" uname=\"CPU id\" offset=\"%d\" type=\"%s\"/>\n",
261                                  &pp->comm.cpu_id, sizeof (pp->comm.cpu_id) == 4 ? "INT32" : "INT64");
262   collector_interface->writeLog ("    <field name=\"TSTAMP\" uname=\"High resolution timestamp\" offset=\"%d\" type=\"%s\"/>\n",
263                                  &pp->comm.tstamp, sizeof (pp->comm.tstamp) == 4 ? "INT32" : "INT64");
264   collector_interface->writeLog ("    <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
265                                  &pp->comm.frinfo, sizeof (pp->comm.frinfo) == 4 ? "INT32" : "INT64");
266   collector_interface->writeLog ("    <field name=\"SRQST\" uname=\"Synchronization start time\" offset=\"%d\" type=\"%s\"/>\n",
267                                  &pp->requested, sizeof (pp->requested) == 4 ? "INT32" : "INT64");
268   collector_interface->writeLog ("    <field name=\"SOBJ\" uname=\"Synchronization object address\" offset=\"%d\" type=\"%s\"/>\n",
269                                  &pp->objp, sizeof (pp->objp) == 4 ? "INT32" : "INT64");
270   collector_interface->writeLog ("  </profpckt>\n");
271   collector_interface->writeLog ("</profile>\n");
272
273   /* Convert threshold from microsec to nanosec */
274   sync_threshold = (thresh > 0 ? thresh : -thresh) * 1000;
275   TprintfT (0, "synctrace: open_experiment complete %ld\n", sync_threshold);
276   return COL_ERROR_NONE;
277 }
278
279 static int
280 start_data_collection (void)
281 {
282   sync_mode = 1;
283   TprintfT (0, "synctrace: start_data_collection\n");
284   return 0;
285 }
286
287 static int
288 stop_data_collection (void)
289 {
290   sync_mode = 0;
291   TprintfT (0, "synctrace: stop_data_collection\n");
292   return 0;
293 }
294
295 static int
296 close_experiment (void)
297 {
298   sync_mode = 0;
299   sync_threshold = -1;
300   sync_key = COLLECTOR_TSD_INVALID_KEY;
301   TprintfT (0, "synctrace: close_experiment\n");
302   return 0;
303 }
304
305 /* fork child.  Clean up state but don't write to experiment */
306 static int
307 detach_experiment (void)
308 {
309   sync_mode = 0;
310   sync_threshold = -1;
311   sync_key = COLLECTOR_TSD_INVALID_KEY;
312   TprintfT (0, "synctrace: detach_experiment\n");
313   return 0;
314 }
315
316 #define NUM_ITER    100     /* number of iterations in calibration */
317 #define NUM_WARMUP    3     /* number of warm up iterations */
318
319 static int
320 sync_calibrate ()
321 {
322   pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER;
323   hrtime_t bt, at, delta;
324   hrtime_t avg, max, min;
325   int i;
326   int ret;
327   avg = (hrtime_t) 0;
328   min = max = (hrtime_t) 0;
329   for (i = 0; i < NUM_ITER + NUM_WARMUP; i++)
330     {
331       /* Here we simulate a real call */
332       bt = gethrtime ();
333       ret = CALL_REAL (pthread_mutex_lock)(&mt);
334       at = gethrtime ();
335       CALL_REAL (pthread_mutex_unlock)(&mt);
336       if (i < NUM_WARMUP)   /* skip these iterations */
337         continue;
338       /* add the time of this one */
339       delta = at - bt;
340       avg += delta;
341       if (min == 0)
342         min = delta;
343       if (delta < min)
344         min = delta;
345       if (delta > max)
346         max = delta;
347     }
348   /* compute average time */
349   avg = avg / NUM_ITER;
350
351   /* pretty simple, let's see how it works */
352   if (max < 6 * avg)
353     max = 6 * avg;
354   /* round up to the nearest microsecond */
355   ret = (int) ((max + 999) / 1000);
356   return ret;
357 }
358
359 static int
360 init_thread_intf ()
361 {
362   void *dlflag = RTLD_NEXT;
363   int err = 0;
364   /* if we detect recursion/reentrance, SEGV so we can get a stack */
365   init_thread_intf_started++;
366   if (!init_thread_intf_finished && init_thread_intf_started >= 3)
367     {
368       /* pull the plug if recursion occurs... */
369       abort ();
370     }
371   /* lookup fprint to print fatal error message */
372   void *ptr = dlsym (RTLD_DEFAULT, "fprintf");
373   if (ptr)
374     {
375       __real_fprintf = (void *) ptr;
376     }
377   else
378     {
379       abort ();
380     }
381
382   /* find the __collector_jprofile_enable_synctrace routine in jprofile module */
383   ptr = dlsym (RTLD_DEFAULT, "__collector_jprofile_enable_synctrace");
384   if (ptr)
385     __real___collector_jprofile_enable_synctrace = (void *) ptr;
386   else
387     {
388 #if defined(GPROFNG_JAVA_PROFILING)
389       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT __collector_jprofile_enable_synctrace\n");
390       err = COL_ERROR_SYNCINIT;
391 #endif
392       sync_java = 0;
393     }
394
395 #if WSIZE(32)
396   /* ########################################## begin WSIZE(32) */
397   /* IMPORTANT!!  The GLIBC_* versions below must match those in the er_sync.*.mapfile ! */
398   dlflag = RTLD_NEXT;
399   ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.0");
400   if (ptr == NULL)
401     {
402       /* We are probably dlopened after libthread/libc,
403        * try to search in the previously loaded objects
404        */
405       dlflag = RTLD_DEFAULT;
406       ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.0");
407       if (ptr != NULL)
408         {
409           __real_pthread_mutex_lock = ptr;
410           Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for OS sync routines\n");
411         }
412       else
413         {
414           CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
415           err = COL_ERROR_SYNCINIT;
416         }
417     }
418   else
419     __real_pthread_mutex_lock = ptr;
420
421   ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.0");
422   if (ptr)
423     __real_pthread_mutex_unlock = (void *) ptr;
424   else
425     {
426       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
427       err = COL_ERROR_SYNCINIT;
428     }
429   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.3.2");
430   if (ptr)
431     __real_pthread_cond_wait = (void *) ptr;
432   else
433     {
434       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
435       err = COL_ERROR_SYNCINIT;
436     }
437   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.3.2");
438   if (ptr)
439     __real_pthread_cond_timedwait = (void *) ptr;
440   else
441     {
442       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
443       err = COL_ERROR_SYNCINIT;
444     }
445   ptr = dlvsym (dlflag, "pthread_join", "GLIBC_2.0");
446   if (ptr)
447     __real_pthread_join = (void *) ptr;
448   else
449     {
450       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
451       err = COL_ERROR_SYNCINIT;
452     }
453   ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.1");
454   if (ptr)
455     __real_sem_wait = (void *) ptr;
456   else
457     {
458       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
459       err = COL_ERROR_SYNCINIT;
460     }
461
462 #if ARCH(Intel)
463   /* ############## Intel specific additional pointers for 32-bits */
464   ptr = __real_sem_wait_2_1 = __real_sem_wait;
465   ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.0");
466   if (ptr)
467     __real_sem_wait_2_0 = (void *) ptr;
468   else
469     {
470       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait_2_0\n");
471       err = COL_ERROR_SYNCINIT;
472     }
473   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.0");
474   if (ptr)
475     __real_pthread_cond_wait_2_0 = (void *) ptr;
476   else
477     {
478       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_0\n");
479       err = COL_ERROR_SYNCINIT;
480     }
481   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.0");
482   if (ptr)
483     __real_pthread_cond_timedwait_2_0 = (void *) ptr;
484   else
485     {
486       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT __real_pthread_cond_timedwait_2_0\n");
487       err = COL_ERROR_SYNCINIT;
488     }
489 #endif /* ARCH(Intel) */
490
491 #else /* WSIZE(64) */
492   /* # most versions are different between platforms    */
493   /* # the few that are common are set after the ARCH ifdef */
494 #if ARCH(Aarch64)
495   dlflag = RTLD_NEXT;
496 #define GLIBC_N    "GLIBC_2.17"
497   __real_pthread_mutex_lock = dlvsym(dlflag, "pthread_mutex_lock", GLIBC_N);
498   __real_pthread_mutex_unlock = dlvsym(dlflag, "pthread_mutex_unlock", GLIBC_N);
499   __real_pthread_cond_wait = dlvsym(dlflag, "pthread_cond_wait", GLIBC_N);
500   __real_pthread_cond_timedwait = dlvsym(dlflag, "pthread_cond_timedwait", GLIBC_N);
501   __real_pthread_join = dlvsym(dlflag, "pthread_join", GLIBC_N);
502   __real_sem_wait = dlvsym(dlflag, "sem_wait", GLIBC_N);
503
504 #elif ARCH(Intel)
505   dlflag = RTLD_NEXT;
506   ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2.5");
507   if (ptr == NULL)
508     {
509       /* We are probably dlopened after libthread/libc,
510        * try to search in the previously loaded objects
511        */
512       dlflag = RTLD_DEFAULT;
513       ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2.5");
514       if (ptr != NULL)
515         {
516           __real_pthread_mutex_lock = ptr;
517           Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for Solaris sync routines\n");
518         }
519       else
520         {
521           CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
522           err = COL_ERROR_SYNCINIT;
523         }
524     }
525   else
526     __real_pthread_mutex_lock = ptr;
527   ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.2.5");
528   if (ptr)
529     __real_pthread_mutex_unlock = (void *) ptr;
530   else
531     {
532       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
533       err = COL_ERROR_SYNCINIT;
534     }
535   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.3.2");
536   if (ptr)
537     __real_pthread_cond_wait = (void *) ptr;
538   else
539     {
540       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
541       err = COL_ERROR_SYNCINIT;
542     }
543   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.3.2");
544   if (ptr)
545     __real_pthread_cond_timedwait = (void *) ptr;
546   else
547     {
548       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
549       err = COL_ERROR_SYNCINIT;
550     }
551   ptr = dlvsym (dlflag, "pthread_join", "GLIBC_2.2.5");
552   if (ptr)
553     __real_pthread_join = (void *) ptr;
554   else
555     {
556       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
557       err = COL_ERROR_SYNCINIT;
558     }
559   ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.2.5");
560   if (ptr)
561     __real_sem_wait = (void *) ptr;
562   else
563     {
564       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
565       err = COL_ERROR_SYNCINIT;
566     }
567   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.2.5");
568   if (ptr)
569     __real_pthread_cond_wait_2_2_5 = (void *) ptr;
570   else
571     {
572       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_2_5\n");
573       err = COL_ERROR_SYNCINIT;
574     }
575   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.2.5");
576   if (ptr)
577     __real_pthread_cond_timedwait_2_2_5 = (void *) ptr;
578   else
579     {
580       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait_2_2_5\n");
581       err = COL_ERROR_SYNCINIT;
582     }
583
584 #elif ARCH(SPARC)
585   dlflag = RTLD_NEXT;
586   ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2");
587   if (ptr == NULL)
588     {
589       /* We are probably dlopened after libthread/libc,
590        * try to search in the previously loaded objects
591        */
592       dlflag = RTLD_DEFAULT;
593       ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2");
594       if (ptr != NULL)
595         {
596           __real_pthread_mutex_lock = ptr;
597           Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for Solaris sync routines\n");
598         }
599       else
600         {
601           CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT mutex_lock\n");
602           err = COL_ERROR_SYNCINIT;
603         }
604     }
605   else
606     __real_pthread_mutex_lock = ptr;
607   ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.2");
608   if (ptr)
609     __real_pthread_mutex_unlock = (void *) ptr;
610   else
611     {
612       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
613       err = COL_ERROR_SYNCINIT;
614     }
615   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.3.2");
616   if (ptr)
617     __real_pthread_cond_wait = (void *) ptr;
618   else
619     {
620       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
621       err = COL_ERROR_SYNCINIT;
622     }
623   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.3.2");
624   if (ptr)
625     __real_pthread_cond_timedwait = (void *) ptr;
626   else
627     {
628       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
629       err = COL_ERROR_SYNCINIT;
630     }
631   ptr = dlvsym (dlflag, "pthread_join", "GLIBC_2.2");
632   if (ptr)
633     __real_pthread_join = (void *) ptr;
634   else
635     {
636       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
637       err = COL_ERROR_SYNCINIT;
638     }
639   ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.2");
640   if (ptr)
641     __real_sem_wait = (void *) ptr;
642   else
643     {
644       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
645       err = COL_ERROR_SYNCINIT;
646     }
647   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.2");
648   if (ptr)
649     __real_pthread_cond_wait_2_2 = (void *) ptr;
650   else
651     {
652       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_2_5\n");
653       err = COL_ERROR_SYNCINIT;
654     }
655   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.2");
656   if (ptr)
657     __real_pthread_cond_timedwait_2_2 = (void *) ptr;
658   else
659     {
660       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait_2_2\n");
661       err = COL_ERROR_SYNCINIT;
662     }
663 #endif /* ARCH() */
664 #endif /* WSIZE(64) */
665   /*  the pointers that are common to 32- and 64-bits, and to SPARC and Intel */
666
667   __real_pthread_cond_wait_2_3_2 = __real_pthread_cond_wait;
668   __real_pthread_cond_timedwait_2_3_2 = __real_pthread_cond_timedwait;
669   ptr = dlsym (dlflag, "strtol");
670   if (ptr)
671     __real_strtol = (void *) ptr;
672   else
673     {
674       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT strtol\n");
675       err = COL_ERROR_SYNCINIT;
676     }
677   init_thread_intf_finished++;
678   TprintfT (0, "synctrace init_thread_intf complete\n");
679   return err;
680 }
681
682 /* These next two routines are used from jprofile to record Java synctrace data */
683 void
684 __collector_jsync_begin ()
685 {
686   int *guard;
687   if (CHCK_JREENTRANCE (guard))
688     {
689       Tprintf (DBG_LT1, "__collector_jsync_begin: skipped\n");
690       return;
691     }
692   Tprintf (DBG_LT1, "__collector_jsync_begin: start event\n");
693   PUSH_REENTRANCE (guard);
694 }
695
696 void
697 __collector_jsync_end (hrtime_t reqt, void *object)
698 {
699   int *guard;
700   if (RECHCK_JREENTRANCE (guard))
701     {
702       Tprintf (DBG_LT1, "__collector_jsync_end: skipped\n");
703       return;
704     }
705   hrtime_t grnt = gethrtime ();
706   if (grnt - reqt >= sync_threshold)
707     {
708       Sync_packet spacket;
709       collector_memset (&spacket, 0, sizeof (Sync_packet));
710       spacket.comm.tsize = sizeof (Sync_packet);
711       spacket.comm.tstamp = grnt;
712       spacket.requested = reqt;
713       spacket.objp = (intptr_t) object;
714       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
715       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
716     }
717   Tprintf (DBG_LT1, "__collector_jsync_begin: end event\n");
718   POP_REENTRANCE (guard);
719 }
720
721 /*-------------------------------------------------------- pthread_mutex_lock */
722 int
723 pthread_mutex_lock (pthread_mutex_t *mp)
724 {
725   int *guard;
726   if (NULL_PTR (pthread_mutex_lock))
727     init_thread_intf ();
728   if (CHCK_NREENTRANCE (guard))
729     return CALL_REAL (pthread_mutex_lock)(mp);
730   PUSH_REENTRANCE (guard);
731   hrtime_t reqt = gethrtime ();
732   int ret = CALL_REAL (pthread_mutex_lock)(mp);
733   if (RECHCK_NREENTRANCE (guard))
734     {
735       POP_REENTRANCE (guard);
736       return ret;
737     }
738   hrtime_t grnt = gethrtime ();
739   if (grnt - reqt >= sync_threshold)
740     {
741       Sync_packet spacket;
742       collector_memset (&spacket, 0, sizeof (Sync_packet));
743       spacket.comm.tsize = sizeof (Sync_packet);
744       spacket.comm.tstamp = grnt;
745       spacket.requested = reqt;
746       spacket.objp = (intptr_t) mp;
747       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK, &spacket);
748       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
749     }
750   POP_REENTRANCE (guard);
751   return ret;
752 }
753
754
755 /*------------------------------------------------------------- pthread_cond_wait */
756 // map interposed symbol versions
757 static int
758 __collector_pthread_cond_wait_symver (int(real_pthread_cond_wait) (), pthread_cond_t *cond, pthread_mutex_t *mutex);
759
760 #if ARCH(Intel) || ARCH(SPARC)
761 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_3_2,
762                   pthread_cond_wait@GLIBC_2.3.2)
763 #endif
764 int
765 __collector_pthread_cond_wait_2_3_2 (pthread_cond_t *cond, pthread_mutex_t *mutex)
766 {
767   if (NULL_PTR (pthread_cond_wait))
768     init_thread_intf ();
769   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_wait_2_3_2@%p\n", CALL_REAL (pthread_cond_wait_2_3_2));
770   return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_3_2), cond, mutex);
771 }
772
773 #if WSIZE(32)
774
775 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_0,
776                   pthread_cond_wait@GLIBC_2.0)
777 int
778 __collector_pthread_cond_wait_2_0 (pthread_cond_t *cond, pthread_mutex_t *mutex)
779 {
780   if (NULL_PTR (pthread_cond_wait))
781     init_thread_intf ();
782   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_wait_2_0@%p\n", CALL_REAL (pthread_cond_wait_2_0));
783   return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_0), cond, mutex);
784 }
785 #else // WSIZE(64)
786 #if ARCH(Intel)
787 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2_5,
788                   pthread_cond_wait@GLIBC_2.2.5)
789 int
790 __collector_pthread_cond_wait_2_2_5 (pthread_cond_t *cond, pthread_mutex_t *mutex)
791 {
792   if (NULL_PTR (pthread_cond_wait))
793     init_thread_intf ();
794   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_wait_2_2_5@%p\n", CALL_REAL (pthread_cond_wait_2_2_5));
795   return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_2_5), cond, mutex);
796 }
797 #elif ARCH(SPARC)
798
799 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2,
800                   pthread_cond_wait@GLIBC_2.2)
801 int
802 __collector_pthread_cond_wait_2_2 (pthread_cond_t *cond, pthread_mutex_t *mutex)
803 {
804   if (NULL_PTR (pthread_cond_wait))
805     init_thread_intf ();
806   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_wait_2_2@%p\n", CALL_REAL (pthread_cond_wait_2_2));
807   return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_2), cond, mutex);
808 }
809 #endif  // ARCH()
810 #endif  // WSIZE()
811
812 static int
813 __collector_pthread_cond_wait_symver (int(real_pthread_cond_wait) (), pthread_cond_t *cond, pthread_mutex_t *mutex)
814 {
815   int *guard;
816   if (NULL_PTR (pthread_cond_wait))
817     init_thread_intf ();
818   if (CHCK_NREENTRANCE (guard))
819     return (real_pthread_cond_wait) (cond, mutex);
820   PUSH_REENTRANCE (guard);
821   hrtime_t reqt = gethrtime ();
822   int ret = -1;
823   ret = (real_pthread_cond_wait) (cond, mutex);
824   if (RECHCK_NREENTRANCE (guard))
825     {
826       POP_REENTRANCE (guard);
827       return ret;
828     }
829   hrtime_t grnt = gethrtime ();
830   if (grnt - reqt >= sync_threshold)
831     {
832       Sync_packet spacket;
833       collector_memset (&spacket, 0, sizeof (Sync_packet));
834       spacket.comm.tsize = sizeof (Sync_packet);
835       spacket.comm.tstamp = grnt;
836       spacket.requested = reqt;
837       spacket.objp = (intptr_t) mutex;
838       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
839       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
840     }
841   POP_REENTRANCE (guard);
842   return ret;
843 }
844
845 /*---------------------------------------------------- pthread_cond_timedwait */
846 // map interposed symbol versions
847 static int
848 __collector_pthread_cond_timedwait_symver (int(real_pthread_cond_timedwait) (),
849                                            pthread_cond_t *cond,
850                                            pthread_mutex_t *mutex,
851                                            const struct timespec *abstime);
852
853 #if ARCH(Intel) || ARCH(SPARC)
854 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_3_2,
855                   pthread_cond_timedwait@GLIBC_2.3.2)
856 #endif  // ARCH()
857 int
858 __collector_pthread_cond_timedwait_2_3_2 (pthread_cond_t *cond,
859                                           pthread_mutex_t *mutex,
860                                           const struct timespec *abstime)
861 {
862   if (NULL_PTR (pthread_cond_timedwait))
863     init_thread_intf ();
864   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_3_2@%p\n", CALL_REAL (pthread_cond_timedwait_2_3_2));
865   return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_3_2), cond, mutex, abstime);
866 }
867
868 #if WSIZE(32)
869 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_0,
870                   pthread_cond_timedwait@GLIBC_2.0)
871 int
872 __collector_pthread_cond_timedwait_2_0 (pthread_cond_t *cond,
873                                         pthread_mutex_t *mutex,
874                                         const struct timespec *abstime)
875 {
876   if (NULL_PTR (pthread_cond_timedwait))
877     init_thread_intf ();
878   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_0@%p\n", CALL_REAL (pthread_cond_timedwait_2_0));
879   return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_0), cond, mutex, abstime);
880 }
881 #else // WSIZE(64)
882 #if ARCH(Intel)
883 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2_5,
884                   pthread_cond_timedwait@GLIBC_2.2.5)
885 int
886 __collector_pthread_cond_timedwait_2_2_5 (pthread_cond_t *cond,
887                                           pthread_mutex_t *mutex,
888                                           const struct timespec *abstime)
889 {
890   if (NULL_PTR (pthread_cond_timedwait))
891     init_thread_intf ();
892   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_2_5@%p\n", CALL_REAL (pthread_cond_timedwait_2_2_5));
893   return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_2_5), cond, mutex, abstime);
894 }
895 #elif ARCH(SPARC)
896
897 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2,
898                   pthread_cond_timedwait@GLIBC_2.2)
899 int
900 __collector_pthread_cond_timedwait_2_2 (pthread_cond_t *cond,
901                                         pthread_mutex_t *mutex,
902                                         const struct timespec *abstime)
903 {
904   if (NULL_PTR (pthread_cond_timedwait))
905     init_thread_intf ();
906   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_2@%p\n", CALL_REAL (pthread_cond_timedwait_2_2));
907   return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_2), cond, mutex, abstime);
908 }
909 #endif  // ARCH()
910 #endif  // WSIZE()
911
912 static int
913 __collector_pthread_cond_timedwait_symver (int(real_pthread_cond_timedwait) (),
914                                            pthread_cond_t *cond,
915                                            pthread_mutex_t *mutex,
916                                            const struct timespec *abstime)
917 {
918   int *guard;
919   if (NULL_PTR (pthread_cond_timedwait))
920     init_thread_intf ();
921   if (CHCK_NREENTRANCE (guard))
922     return (real_pthread_cond_timedwait) (cond, mutex, abstime);
923   PUSH_REENTRANCE (guard);
924   hrtime_t reqt = gethrtime ();
925   int ret = -1;
926   ret = (real_pthread_cond_timedwait) (cond, mutex, abstime);
927   if (RECHCK_NREENTRANCE (guard))
928     {
929       POP_REENTRANCE (guard);
930       return ret;
931     }
932   hrtime_t grnt = gethrtime ();
933   if (grnt - reqt >= sync_threshold)
934     {
935       Sync_packet spacket;
936       collector_memset (&spacket, 0, sizeof ( Sync_packet));
937       spacket.comm.tsize = sizeof ( Sync_packet);
938       spacket.comm.tstamp = grnt;
939       spacket.requested = reqt;
940       spacket.objp = (intptr_t) mutex;
941       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
942       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
943     }
944   POP_REENTRANCE (guard);
945   return ret;
946 }
947
948 /*------------------------------------------------------------- pthread_join */
949 int
950 pthread_join (pthread_t target_thread, void **status)
951 {
952   int *guard;
953   if (NULL_PTR (pthread_join))
954     init_thread_intf ();
955   if (CHCK_NREENTRANCE (guard))
956     return CALL_REAL (pthread_join)(target_thread, status);
957   PUSH_REENTRANCE (guard);
958   hrtime_t reqt = gethrtime ();
959   int ret = CALL_REAL (pthread_join)(target_thread, status);
960   if (RECHCK_NREENTRANCE (guard))
961     {
962       POP_REENTRANCE (guard);
963       return ret;
964     }
965   hrtime_t grnt = gethrtime ();
966   if (grnt - reqt >= sync_threshold)
967     {
968       Sync_packet spacket;
969       collector_memset (&spacket, 0, sizeof ( Sync_packet));
970       spacket.comm.tsize = sizeof ( Sync_packet);
971       spacket.comm.tstamp = grnt;
972       spacket.requested = reqt;
973       spacket.objp = (Vaddr_type) target_thread;
974       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK, &spacket);
975       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
976     }
977   POP_REENTRANCE (guard);
978   return ret;
979 }
980
981 /*------------------------------------------------------------- sem_wait */
982 // map interposed symbol versions
983 #if ARCH(Intel) && WSIZE(32)
984 static int
985 __collector_sem_wait_symver (int(real_sem_wait) (), sem_t *sp);
986
987 SYMVER_ATTRIBUTE (__collector_sem_wait_2_1, sem_wait@GLIBC_2.1)
988 int
989 __collector_sem_wait_2_1 (sem_t *sp)
990 {
991   if (NULL_PTR (sem_wait))
992     init_thread_intf ();
993   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_sem_wait_2_1@%p\n", CALL_REAL (sem_wait_2_1));
994   return __collector_sem_wait_symver (CALL_REAL (sem_wait_2_1), sp);
995 }
996
997 SYMVER_ATTRIBUTE (__collector_sem_wait_2_0, sem_wait@GLIBC_2.0)
998 int
999 __collector_sem_wait_2_0 (sem_t *sp)
1000 {
1001   if (NULL_PTR (sem_wait))
1002     init_thread_intf ();
1003   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_sem_wait_2_0@%p\n", CALL_REAL (sem_wait_2_0));
1004   return __collector_sem_wait_symver (CALL_REAL (sem_wait_2_0), sp);
1005 }
1006 #endif
1007
1008 #if ARCH(Intel) && WSIZE(32)
1009 static int
1010 __collector_sem_wait_symver (int(real_sem_wait) (), sem_t *sp)
1011 {
1012 #else
1013 int
1014 sem_wait (sem_t *sp)
1015 {
1016 #endif
1017   int *guard;
1018   if (NULL_PTR (sem_wait))
1019     init_thread_intf ();
1020   if (CHCK_NREENTRANCE (guard))
1021     {
1022 #if ARCH(Intel) && WSIZE(32)
1023       return (real_sem_wait) (sp);
1024 #else
1025       return CALL_REAL (sem_wait)(sp);
1026 #endif
1027     }
1028   PUSH_REENTRANCE (guard);
1029   hrtime_t reqt = gethrtime ();
1030   int ret = -1;
1031 #if ARCH(Intel) && WSIZE(32)
1032   ret = (real_sem_wait) (sp);
1033 #else
1034   ret = CALL_REAL (sem_wait)(sp);
1035 #endif
1036   if (RECHCK_NREENTRANCE (guard))
1037     {
1038       POP_REENTRANCE (guard);
1039       return ret;
1040     }
1041   hrtime_t grnt = gethrtime ();
1042   if (grnt - reqt >= sync_threshold)
1043     {
1044       Sync_packet spacket;
1045       collector_memset (&spacket, 0, sizeof ( Sync_packet));
1046       spacket.comm.tsize = sizeof ( Sync_packet);
1047       spacket.comm.tstamp = grnt;
1048       spacket.requested = reqt;
1049       spacket.objp = (intptr_t) sp;
1050
1051 #if ARCH(Intel) && WSIZE(32)
1052       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
1053 #else
1054       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK, &spacket);
1055 #endif
1056       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
1057     }
1058   POP_REENTRANCE (guard);
1059   return ret;
1060 }
This page took 0.086748 seconds and 4 git commands to generate.