1 /* Copyright (C) 2021 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
22 * Synchronization events
28 #include <semaphore.h> /* sem_wait() */
31 #include <sys/param.h>
35 #include "collector.h"
36 #include "gp-experiment.h"
37 #include "data_pckts.h"
39 #include "cc_libcollector.h"
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
48 /* define the packet that will be written out */
49 typedef struct Sync_packet
50 { /* Synchronization delay tracing packet */
52 hrtime_t requested
; /* time of synchronization request */
53 Vaddr_type objp
; /* vaddr of synchronization object */
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 ();
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) */
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;
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))--)
92 #define CALL_REAL(x) (*(int(*)())__real_##x)
93 #define NULL_PTR(x) ( __real_##x == NULL )
94 #define gethrtime collector_interface->getHiResTime
97 #define Tprintf(...) if (collector_interface) collector_interface->writeDebugInfo( 0, __VA_ARGS__ )
98 #define TprintfT(...) if (collector_interface) collector_interface->writeDebugInfo( 1, __VA_ARGS__ )
101 #define TprintfT(...)
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().
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
;
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
;
131 static void *__real_pthread_cond_wait_2_2_5
= NULL
;
132 static void *__real_pthread_cond_timedwait_2_2_5
= NULL
;
134 static void *__real_pthread_cond_wait_2_2
= NULL
;
135 static void *__real_pthread_cond_timedwait_2_2
= NULL
;
140 collector_memset (void *s
, int c
, size_t n
)
142 unsigned char *s1
= s
;
144 *s1
++ = (unsigned char) c
;
148 __collector_module_init (CollectorInterface
*_collector_interface
)
150 if (_collector_interface
== NULL
)
152 collector_interface
= _collector_interface
;
153 TprintfT (0, "synctrace: __collector_module_init\n");
154 sync_hndl
= collector_interface
->registerModule (&module_interface
);
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
);
163 open_experiment (const char *exp
)
166 if (init_thread_intf_finished
== 0)
168 if (collector_interface
== NULL
)
170 Tprintf (0, "synctrace: collector_interface is null.\n");
171 return COL_ERROR_SYNCINIT
;
173 if (sync_hndl
== COLLECTOR_MODULE_ERR
)
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
;
180 TprintfT (0, "synctrace: open_experiment %s\n", exp
);
182 char *params
= (char *) collector_interface
->getParams ();
185 if ((params
[0] == 's') && (params
[1] == ':'))
187 char *ptr
= params
+ 2;
188 Tprintf (DBG_LT1
, "synctrace: open_experiment s: parameter = %s\n", ptr
);
189 while (*ptr
!= ',' && *ptr
!= ';')
194 sync_scope
= CALL_REAL (strtol
) (ptr
+ 1, NULL
, 0);
211 Tprintf (0, "\tsynctrace: sync_scope found as %ld\n", sync_scope
);
215 /* the old-style descriptor, without scope */
216 /* if there was no comma, use the old default */
220 Tprintf (0, "\tsynctrace: sync_scope not found set to %ld\n", sync_scope
);
222 if (__real___collector_jprofile_enable_synctrace
== NULL
)
224 thresh
= CALL_REAL (strtol
)(params
+ 2, NULL
, 0);
225 break; /* from the loop to find the "s:thresh,scope" entry */
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 ();
235 sync_key
= collector_interface
->createKey (sizeof ( int), NULL
, NULL
);
236 if (sync_key
== (unsigned) - 1)
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
;
243 /* if Java synctrace was requested, tell the jprofile module */
246 TprintfT (0, "synctrace: enabling Java synctrace\n");
247 CALL_REAL (__collector_jprofile_enable_synctrace
)();
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");
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
;
280 start_data_collection (void)
283 TprintfT (0, "synctrace: start_data_collection\n");
288 stop_data_collection (void)
291 TprintfT (0, "synctrace: stop_data_collection\n");
296 close_experiment (void)
300 sync_key
= COLLECTOR_TSD_INVALID_KEY
;
301 TprintfT (0, "synctrace: close_experiment\n");
305 /* fork child. Clean up state but don't write to experiment */
307 detach_experiment (void)
311 sync_key
= COLLECTOR_TSD_INVALID_KEY
;
312 TprintfT (0, "synctrace: detach_experiment\n");
316 #define NUM_ITER 100 /* number of iterations in calibration */
317 #define NUM_WARMUP 3 /* number of warm up iterations */
322 pthread_mutex_t mt
= PTHREAD_MUTEX_INITIALIZER
;
323 hrtime_t bt
, at
, delta
;
324 hrtime_t avg
, max
, min
;
328 min
= max
= (hrtime_t
) 0;
329 for (i
= 0; i
< NUM_ITER
+ NUM_WARMUP
; i
++)
331 /* Here we simulate a real call */
333 ret
= CALL_REAL (pthread_mutex_lock
)(&mt
);
335 CALL_REAL (pthread_mutex_unlock
)(&mt
);
336 if (i
< NUM_WARMUP
) /* skip these iterations */
338 /* add the time of this one */
348 /* compute average time */
349 avg
= avg
/ NUM_ITER
;
351 /* pretty simple, let's see how it works */
354 /* round up to the nearest microsecond */
355 ret
= (int) ((max
+ 999) / 1000);
362 void *dlflag
= RTLD_NEXT
;
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)
368 /* pull the plug if recursion occurs... */
371 /* lookup fprint to print fatal error message */
372 void *ptr
= dlsym (RTLD_DEFAULT
, "fprintf");
375 __real_fprintf
= (void *) ptr
;
382 /* find the __collector_jprofile_enable_synctrace routine in jprofile module */
383 ptr
= dlsym (RTLD_DEFAULT
, "__collector_jprofile_enable_synctrace");
385 __real___collector_jprofile_enable_synctrace
= (void *) ptr
;
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
;
396 /* ########################################## begin WSIZE(32) */
397 /* IMPORTANT!! The GLIBC_* versions below must match those in the er_sync.*.mapfile ! */
399 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.0");
402 /* We are probably dlopened after libthread/libc,
403 * try to search in the previously loaded objects
405 dlflag
= RTLD_DEFAULT
;
406 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.0");
409 __real_pthread_mutex_lock
= ptr
;
410 Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for OS sync routines\n");
414 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
415 err
= COL_ERROR_SYNCINIT
;
419 __real_pthread_mutex_lock
= ptr
;
421 ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.0");
423 __real_pthread_mutex_unlock
= (void *) ptr
;
426 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
427 err
= COL_ERROR_SYNCINIT
;
429 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.3.2");
431 __real_pthread_cond_wait
= (void *) ptr
;
434 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
435 err
= COL_ERROR_SYNCINIT
;
437 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.3.2");
439 __real_pthread_cond_timedwait
= (void *) ptr
;
442 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
443 err
= COL_ERROR_SYNCINIT
;
445 ptr
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.0");
447 __real_pthread_join
= (void *) ptr
;
450 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
451 err
= COL_ERROR_SYNCINIT
;
453 ptr
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.1");
455 __real_sem_wait
= (void *) ptr
;
458 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
459 err
= COL_ERROR_SYNCINIT
;
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");
467 __real_sem_wait_2_0
= (void *) ptr
;
470 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT sem_wait_2_0\n");
471 err
= COL_ERROR_SYNCINIT
;
473 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.0");
475 __real_pthread_cond_wait_2_0
= (void *) ptr
;
478 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_0\n");
479 err
= COL_ERROR_SYNCINIT
;
481 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.0");
483 __real_pthread_cond_timedwait_2_0
= (void *) ptr
;
486 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT __real_pthread_cond_timedwait_2_0\n");
487 err
= COL_ERROR_SYNCINIT
;
489 #endif /* ARCH(Intel) */
491 #else /* WSIZE(64) */
492 /* # most versions are different between platforms */
493 /* # the few that are common are set after the ARCH ifdef */
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
);
506 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.2.5");
509 /* We are probably dlopened after libthread/libc,
510 * try to search in the previously loaded objects
512 dlflag
= RTLD_DEFAULT
;
513 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.2.5");
516 __real_pthread_mutex_lock
= ptr
;
517 Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for Solaris sync routines\n");
521 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
522 err
= COL_ERROR_SYNCINIT
;
526 __real_pthread_mutex_lock
= ptr
;
527 ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.2.5");
529 __real_pthread_mutex_unlock
= (void *) ptr
;
532 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
533 err
= COL_ERROR_SYNCINIT
;
535 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.3.2");
537 __real_pthread_cond_wait
= (void *) ptr
;
540 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
541 err
= COL_ERROR_SYNCINIT
;
543 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.3.2");
545 __real_pthread_cond_timedwait
= (void *) ptr
;
548 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
549 err
= COL_ERROR_SYNCINIT
;
551 ptr
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.2.5");
553 __real_pthread_join
= (void *) ptr
;
556 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
557 err
= COL_ERROR_SYNCINIT
;
559 ptr
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.2.5");
561 __real_sem_wait
= (void *) ptr
;
564 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
565 err
= COL_ERROR_SYNCINIT
;
567 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.2.5");
569 __real_pthread_cond_wait_2_2_5
= (void *) ptr
;
572 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_2_5\n");
573 err
= COL_ERROR_SYNCINIT
;
575 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.2.5");
577 __real_pthread_cond_timedwait_2_2_5
= (void *) ptr
;
580 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait_2_2_5\n");
581 err
= COL_ERROR_SYNCINIT
;
586 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.2");
589 /* We are probably dlopened after libthread/libc,
590 * try to search in the previously loaded objects
592 dlflag
= RTLD_DEFAULT
;
593 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.2");
596 __real_pthread_mutex_lock
= ptr
;
597 Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for Solaris sync routines\n");
601 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT mutex_lock\n");
602 err
= COL_ERROR_SYNCINIT
;
606 __real_pthread_mutex_lock
= ptr
;
607 ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.2");
609 __real_pthread_mutex_unlock
= (void *) ptr
;
612 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
613 err
= COL_ERROR_SYNCINIT
;
615 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.3.2");
617 __real_pthread_cond_wait
= (void *) ptr
;
620 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
621 err
= COL_ERROR_SYNCINIT
;
623 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.3.2");
625 __real_pthread_cond_timedwait
= (void *) ptr
;
628 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
629 err
= COL_ERROR_SYNCINIT
;
631 ptr
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.2");
633 __real_pthread_join
= (void *) ptr
;
636 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
637 err
= COL_ERROR_SYNCINIT
;
639 ptr
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.2");
641 __real_sem_wait
= (void *) ptr
;
644 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
645 err
= COL_ERROR_SYNCINIT
;
647 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.2");
649 __real_pthread_cond_wait_2_2
= (void *) ptr
;
652 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_2_5\n");
653 err
= COL_ERROR_SYNCINIT
;
655 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.2");
657 __real_pthread_cond_timedwait_2_2
= (void *) ptr
;
660 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait_2_2\n");
661 err
= COL_ERROR_SYNCINIT
;
664 #endif /* WSIZE(64) */
665 /* the pointers that are common to 32- and 64-bits, and to SPARC and Intel */
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");
671 __real_strtol
= (void *) ptr
;
674 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT strtol\n");
675 err
= COL_ERROR_SYNCINIT
;
677 init_thread_intf_finished
++;
678 TprintfT (0, "synctrace init_thread_intf complete\n");
682 /* These next two routines are used from jprofile to record Java synctrace data */
684 __collector_jsync_begin ()
687 if (CHCK_JREENTRANCE (guard
))
689 Tprintf (DBG_LT1
, "__collector_jsync_begin: skipped\n");
692 Tprintf (DBG_LT1
, "__collector_jsync_begin: start event\n");
693 PUSH_REENTRANCE (guard
);
697 __collector_jsync_end (hrtime_t reqt
, void *object
)
700 if (RECHCK_JREENTRANCE (guard
))
702 Tprintf (DBG_LT1
, "__collector_jsync_end: skipped\n");
705 hrtime_t grnt
= gethrtime ();
706 if (grnt
- reqt
>= sync_threshold
)
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
);
717 Tprintf (DBG_LT1
, "__collector_jsync_begin: end event\n");
718 POP_REENTRANCE (guard
);
721 /*-------------------------------------------------------- pthread_mutex_lock */
723 pthread_mutex_lock (pthread_mutex_t
*mp
)
726 if (NULL_PTR (pthread_mutex_lock
))
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
))
735 POP_REENTRANCE (guard
);
738 hrtime_t grnt
= gethrtime ();
739 if (grnt
- reqt
>= sync_threshold
)
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
);
750 POP_REENTRANCE (guard
);
755 /*------------------------------------------------------------- pthread_cond_wait */
756 // map interposed symbol versions
758 __collector_pthread_cond_wait_symver (int(real_pthread_cond_wait
) (), pthread_cond_t
*cond
, pthread_mutex_t
*mutex
);
760 #if ARCH(Intel) || ARCH(SPARC)
761 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_3_2
,
762 pthread_cond_wait@GLIBC_2
.3
.2)
765 __collector_pthread_cond_wait_2_3_2 (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
767 if (NULL_PTR (pthread_cond_wait
))
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
);
775 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_0
,
776 pthread_cond_wait@GLIBC_2
.0
)
778 __collector_pthread_cond_wait_2_0 (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
780 if (NULL_PTR (pthread_cond_wait
))
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
);
787 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2_5
,
788 pthread_cond_wait@GLIBC_2
.2
.5)
790 __collector_pthread_cond_wait_2_2_5 (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
792 if (NULL_PTR (pthread_cond_wait
))
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
);
799 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2
,
800 pthread_cond_wait@GLIBC_2
.2
)
802 __collector_pthread_cond_wait_2_2 (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
804 if (NULL_PTR (pthread_cond_wait
))
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
);
813 __collector_pthread_cond_wait_symver (int(real_pthread_cond_wait
) (), pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
816 if (NULL_PTR (pthread_cond_wait
))
818 if (CHCK_NREENTRANCE (guard
))
819 return (real_pthread_cond_wait
) (cond
, mutex
);
820 PUSH_REENTRANCE (guard
);
821 hrtime_t reqt
= gethrtime ();
823 ret
= (real_pthread_cond_wait
) (cond
, mutex
);
824 if (RECHCK_NREENTRANCE (guard
))
826 POP_REENTRANCE (guard
);
829 hrtime_t grnt
= gethrtime ();
830 if (grnt
- reqt
>= sync_threshold
)
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
);
841 POP_REENTRANCE (guard
);
845 /*---------------------------------------------------- pthread_cond_timedwait */
846 // map interposed symbol versions
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
);
853 #if ARCH(Intel) || ARCH(SPARC)
854 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_3_2
,
855 pthread_cond_timedwait@GLIBC_2
.3
.2)
858 __collector_pthread_cond_timedwait_2_3_2 (pthread_cond_t
*cond
,
859 pthread_mutex_t
*mutex
,
860 const struct timespec
*abstime
)
862 if (NULL_PTR (pthread_cond_timedwait
))
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
);
869 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_0
,
870 pthread_cond_timedwait@GLIBC_2
.0
)
872 __collector_pthread_cond_timedwait_2_0 (pthread_cond_t
*cond
,
873 pthread_mutex_t
*mutex
,
874 const struct timespec
*abstime
)
876 if (NULL_PTR (pthread_cond_timedwait
))
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
);
883 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2_5
,
884 pthread_cond_timedwait@GLIBC_2
.2
.5)
886 __collector_pthread_cond_timedwait_2_2_5 (pthread_cond_t
*cond
,
887 pthread_mutex_t
*mutex
,
888 const struct timespec
*abstime
)
890 if (NULL_PTR (pthread_cond_timedwait
))
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
);
897 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2
,
898 pthread_cond_timedwait@GLIBC_2
.2
)
900 __collector_pthread_cond_timedwait_2_2 (pthread_cond_t
*cond
,
901 pthread_mutex_t
*mutex
,
902 const struct timespec
*abstime
)
904 if (NULL_PTR (pthread_cond_timedwait
))
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
);
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
)
919 if (NULL_PTR (pthread_cond_timedwait
))
921 if (CHCK_NREENTRANCE (guard
))
922 return (real_pthread_cond_timedwait
) (cond
, mutex
, abstime
);
923 PUSH_REENTRANCE (guard
);
924 hrtime_t reqt
= gethrtime ();
926 ret
= (real_pthread_cond_timedwait
) (cond
, mutex
, abstime
);
927 if (RECHCK_NREENTRANCE (guard
))
929 POP_REENTRANCE (guard
);
932 hrtime_t grnt
= gethrtime ();
933 if (grnt
- reqt
>= sync_threshold
)
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
);
944 POP_REENTRANCE (guard
);
948 /*------------------------------------------------------------- pthread_join */
950 pthread_join (pthread_t target_thread
, void **status
)
953 if (NULL_PTR (pthread_join
))
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
))
962 POP_REENTRANCE (guard
);
965 hrtime_t grnt
= gethrtime ();
966 if (grnt
- reqt
>= sync_threshold
)
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
);
977 POP_REENTRANCE (guard
);
981 /*------------------------------------------------------------- sem_wait */
982 // map interposed symbol versions
983 #if ARCH(Intel) && WSIZE(32)
985 __collector_sem_wait_symver (int(real_sem_wait
) (), sem_t
*sp
);
987 SYMVER_ATTRIBUTE (__collector_sem_wait_2_1
, sem_wait@GLIBC_2
.1
)
989 __collector_sem_wait_2_1 (sem_t
*sp
)
991 if (NULL_PTR (sem_wait
))
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
);
997 SYMVER_ATTRIBUTE (__collector_sem_wait_2_0
, sem_wait@GLIBC_2
.0
)
999 __collector_sem_wait_2_0 (sem_t
*sp
)
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
);
1008 #if ARCH(Intel) && WSIZE(32)
1010 __collector_sem_wait_symver (int(real_sem_wait
) (), sem_t
*sp
)
1014 sem_wait (sem_t
*sp
)
1018 if (NULL_PTR (sem_wait
))
1019 init_thread_intf ();
1020 if (CHCK_NREENTRANCE (guard
))
1022 #if ARCH(Intel) && WSIZE(32)
1023 return (real_sem_wait
) (sp
);
1025 return CALL_REAL (sem_wait
)(sp
);
1028 PUSH_REENTRANCE (guard
);
1029 hrtime_t reqt
= gethrtime ();
1031 #if ARCH(Intel) && WSIZE(32)
1032 ret
= (real_sem_wait
) (sp
);
1034 ret
= CALL_REAL (sem_wait
)(sp
);
1036 if (RECHCK_NREENTRANCE (guard
))
1038 POP_REENTRANCE (guard
);
1041 hrtime_t grnt
= gethrtime ();
1042 if (grnt
- reqt
>= sync_threshold
)
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
;
1051 #if ARCH(Intel) && WSIZE(32)
1052 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
, spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
1054 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
, spacket
.comm
.tstamp
, FRINFO_FROM_STACK
, &spacket
);
1056 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) & spacket
);
1058 POP_REENTRANCE (guard
);