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_module.h"
36 #include "gp-experiment.h"
37 #include "data_pckts.h"
40 #include "cc_libcollector.h"
42 /* TprintfT(<level>,...) definitions. Adjust per module as needed */
43 #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
44 #define DBG_LTT 0 // for interposition on GLIBC functions
45 #define DBG_LT1 1 // for configuration details, warnings
49 /* define the packet that will be written out */
50 typedef struct Sync_packet
51 { /* Synchronization delay tracing packet */
53 hrtime_t requested
; /* time of synchronization request */
54 Vaddr_type objp
; /* vaddr of synchronization object */
57 static int open_experiment (const char *);
58 static int start_data_collection (void);
59 static int stop_data_collection (void);
60 static int close_experiment (void);
61 static int detach_experiment (void);
62 static int init_thread_intf ();
63 static int sync_calibrate ();
65 static ModuleInterface module_interface
={
66 SP_SYNCTRACE_FILE
, /* description */
67 NULL
, /* initInterface */
68 open_experiment
, /* openExperiment */
69 start_data_collection
, /* startDataCollection */
70 stop_data_collection
, /* stopDataCollection */
71 close_experiment
, /* closeExperiment */
72 detach_experiment
/* detachExperiment (fork child) */
75 static CollectorInterface
*collector_interface
= NULL
;
76 static int sync_mode
= 0;
77 static long sync_scope
= 0;
78 static int sync_native
= 0;
79 static int sync_java
= 0;
80 static CollectorModule sync_hndl
= COLLECTOR_MODULE_ERR
;
81 static unsigned sync_key
= COLLECTOR_TSD_INVALID_KEY
;
82 static long sync_threshold
= -1; /* calibrate the value */
83 static int init_thread_intf_started
= 0;
84 static int init_thread_intf_finished
= 0;
86 #define CHCK_NREENTRANCE(x) (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
87 #define RECHCK_NREENTRANCE(x) (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
88 #define CHCK_JREENTRANCE(x) (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
89 #define RECHCK_JREENTRANCE(x) (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
90 #define PUSH_REENTRANCE(x) ((*(x))++)
91 #define POP_REENTRANCE(x) ((*(x))--)
93 #define CALL_REAL(x) (*(int(*)())__real_##x)
94 #define NULL_PTR(x) ( __real_##x == NULL )
95 #define gethrtime collector_interface->getHiResTime
98 #define Tprintf(...) if (collector_interface) collector_interface->writeDebugInfo( 0, __VA_ARGS__ )
99 #define TprintfT(...) if (collector_interface) collector_interface->writeDebugInfo( 1, __VA_ARGS__ )
102 #define TprintfT(...)
106 * In most cases, the functions which require interposition are implemented as
107 * weak symbols corresponding to an associated internal function named with a
108 * leading underscore: e.g., mutex_lock() is simply an alias for _mutex_lock().
109 * For the wait functions, however, the published version (used by applications)
110 * is distinct from the internal version (used by system libraries), i.e.,
111 * cond_wait() is an alias for _cond_wait_cancel() rather than _cond_wait().
113 static void *__real_strtol
= NULL
;
114 static void *__real_fprintf
= NULL
;
115 static void *__real___collector_jprofile_enable_synctrace
= NULL
;
116 static void *__real_pthread_mutex_lock
= NULL
;
117 static void *__real_pthread_mutex_unlock
= NULL
; /* not interposed, used in calibrate */
118 static void *__real_pthread_cond_wait
= NULL
;
119 static void *__real_pthread_cond_timedwait
= NULL
;
120 static void *__real_pthread_join
= NULL
;
121 static void *__real_sem_wait
= NULL
;
122 static void *__real_pthread_cond_wait_2_3_2
= NULL
;
123 static void *__real_pthread_cond_timedwait_2_3_2
= NULL
;
126 static void *__real_sem_wait_2_1
= NULL
;
127 static void *__real_sem_wait_2_0
= NULL
;
128 static void *__real_pthread_cond_wait_2_0
= NULL
;
129 static void *__real_pthread_cond_timedwait_2_0
= NULL
;
132 static void *__real_pthread_cond_wait_2_2_5
= NULL
;
133 static void *__real_pthread_cond_timedwait_2_2_5
= NULL
;
135 static void *__real_pthread_cond_wait_2_2
= NULL
;
136 static void *__real_pthread_cond_timedwait_2_2
= NULL
;
141 collector_memset (void *s
, int c
, size_t n
)
143 unsigned char *s1
= s
;
145 *s1
++ = (unsigned char) c
;
149 __collector_module_init (CollectorInterface
*_collector_interface
)
151 if (_collector_interface
== NULL
)
153 collector_interface
= _collector_interface
;
154 TprintfT (0, "synctrace: __collector_module_init\n");
155 sync_hndl
= collector_interface
->registerModule (&module_interface
);
157 /* Initialize next module */
158 ModuleInitFunc next_init
= (ModuleInitFunc
) dlsym (RTLD_NEXT
, "__collector_module_init");
159 if (next_init
!= NULL
)
160 next_init (_collector_interface
);
164 open_experiment (const char *exp
)
167 if (init_thread_intf_finished
== 0)
169 if (collector_interface
== NULL
)
171 Tprintf (0, "synctrace: collector_interface is null.\n");
172 return COL_ERROR_SYNCINIT
;
174 if (sync_hndl
== COLLECTOR_MODULE_ERR
)
176 Tprintf (0, "synctrace: handle create failed.\n");
177 collector_interface
->writeLog ("<event kind=\"%s\" id=\"%d\">data handle not created</event>\n",
178 SP_JCMD_CERROR
, COL_ERROR_SYNCINIT
);
179 return COL_ERROR_SYNCINIT
;
181 TprintfT (0, "synctrace: open_experiment %s\n", exp
);
183 char *params
= (char *) collector_interface
->getParams ();
186 if ((params
[0] == 's') && (params
[1] == ':'))
188 char *ptr
= params
+ 2;
189 Tprintf (DBG_LT1
, "synctrace: open_experiment s: parameter = %s\n", ptr
);
190 while (*ptr
!= ',' && *ptr
!= ';')
195 sync_scope
= CALL_REAL (strtol
) (ptr
+ 1, NULL
, 0);
212 Tprintf (0, "\tsynctrace: sync_scope found as %ld\n", sync_scope
);
216 /* the old-style descriptor, without scope */
217 /* if there was no comma, use the old default */
221 Tprintf (0, "\tsynctrace: sync_scope not found set to %ld\n", sync_scope
);
223 if (__real___collector_jprofile_enable_synctrace
== NULL
)
225 thresh
= CALL_REAL (strtol
)(params
+ 2, NULL
, 0);
226 break; /* from the loop to find the "s:thresh,scope" entry */
231 if (params
== NULL
) /* Sync data collection not specified */
232 return COL_ERROR_SYNCINIT
;
233 if (thresh
< 0) /* calibrate the threshold, keep it as a negative number */
234 thresh
= -sync_calibrate ();
236 sync_key
= collector_interface
->createKey (sizeof ( int), NULL
, NULL
);
237 if (sync_key
== (unsigned) - 1)
239 Tprintf (0, "synctrace: TSD key create failed.\n");
240 collector_interface
->writeLog ("<event kind=\"%s\" id=\"%d\">TSD key not created</event>\n",
241 SP_JCMD_CERROR
, COL_ERROR_SYNCINIT
);
242 return COL_ERROR_SYNCINIT
;
244 /* if Java synctrace was requested, tell the jprofile module */
247 TprintfT (0, "synctrace: enabling Java synctrace\n");
248 CALL_REAL (__collector_jprofile_enable_synctrace
)();
250 collector_interface
->writeLog ("<profile name=\"%s\" threshold=\"%ld\" scope=\"%ld\">\n",
251 SP_JCMD_SYNCTRACE
, thresh
, sync_scope
);
252 collector_interface
->writeLog (" <profdata fname=\"%s\"/>\n",
253 module_interface
.description
);
254 /* Record Sync_packet description */
255 Sync_packet
*pp
= NULL
;
256 collector_interface
->writeLog (" <profpckt kind=\"%d\" uname=\"Synchronization tracing data\">\n", SYNC_PCKT
);
257 collector_interface
->writeLog (" <field name=\"LWPID\" uname=\"Lightweight process id\" offset=\"%d\" type=\"%s\"/>\n",
258 &pp
->comm
.lwp_id
, sizeof (pp
->comm
.lwp_id
) == 4 ? "INT32" : "INT64");
259 collector_interface
->writeLog (" <field name=\"THRID\" uname=\"Thread number\" offset=\"%d\" type=\"%s\"/>\n",
260 &pp
->comm
.thr_id
, sizeof (pp
->comm
.thr_id
) == 4 ? "INT32" : "INT64");
261 collector_interface
->writeLog (" <field name=\"CPUID\" uname=\"CPU id\" offset=\"%d\" type=\"%s\"/>\n",
262 &pp
->comm
.cpu_id
, sizeof (pp
->comm
.cpu_id
) == 4 ? "INT32" : "INT64");
263 collector_interface
->writeLog (" <field name=\"TSTAMP\" uname=\"High resolution timestamp\" offset=\"%d\" type=\"%s\"/>\n",
264 &pp
->comm
.tstamp
, sizeof (pp
->comm
.tstamp
) == 4 ? "INT32" : "INT64");
265 collector_interface
->writeLog (" <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
266 &pp
->comm
.frinfo
, sizeof (pp
->comm
.frinfo
) == 4 ? "INT32" : "INT64");
267 collector_interface
->writeLog (" <field name=\"SRQST\" uname=\"Synchronization start time\" offset=\"%d\" type=\"%s\"/>\n",
268 &pp
->requested
, sizeof (pp
->requested
) == 4 ? "INT32" : "INT64");
269 collector_interface
->writeLog (" <field name=\"SOBJ\" uname=\"Synchronization object address\" offset=\"%d\" type=\"%s\"/>\n",
270 &pp
->objp
, sizeof (pp
->objp
) == 4 ? "INT32" : "INT64");
271 collector_interface
->writeLog (" </profpckt>\n");
272 collector_interface
->writeLog ("</profile>\n");
274 /* Convert threshold from microsec to nanosec */
275 sync_threshold
= (thresh
> 0 ? thresh
: -thresh
) * 1000;
276 TprintfT (0, "synctrace: open_experiment complete %ld\n", sync_threshold
);
277 return COL_ERROR_NONE
;
281 start_data_collection (void)
284 TprintfT (0, "synctrace: start_data_collection\n");
289 stop_data_collection (void)
292 TprintfT (0, "synctrace: stop_data_collection\n");
297 close_experiment (void)
301 sync_key
= COLLECTOR_TSD_INVALID_KEY
;
302 TprintfT (0, "synctrace: close_experiment\n");
306 /* fork child. Clean up state but don't write to experiment */
308 detach_experiment (void)
312 sync_key
= COLLECTOR_TSD_INVALID_KEY
;
313 TprintfT (0, "synctrace: detach_experiment\n");
317 #define NUM_ITER 100 /* number of iterations in calibration */
318 #define NUM_WARMUP 3 /* number of warm up iterations */
323 pthread_mutex_t mt
= PTHREAD_MUTEX_INITIALIZER
;
324 hrtime_t bt
, at
, delta
;
325 hrtime_t avg
, max
, min
;
329 min
= max
= (hrtime_t
) 0;
330 for (i
= 0; i
< NUM_ITER
+ NUM_WARMUP
; i
++)
332 /* Here we simulate a real call */
334 ret
= CALL_REAL (pthread_mutex_lock
)(&mt
);
336 CALL_REAL (pthread_mutex_unlock
)(&mt
);
337 if (i
< NUM_WARMUP
) /* skip these iterations */
339 /* add the time of this one */
349 /* compute average time */
350 avg
= avg
/ NUM_ITER
;
352 /* pretty simple, let's see how it works */
355 /* round up to the nearest microsecond */
356 ret
= (int) ((max
+ 999) / 1000);
363 void *dlflag
= RTLD_NEXT
;
365 /* if we detect recursion/reentrance, SEGV so we can get a stack */
366 init_thread_intf_started
++;
367 if (!init_thread_intf_finished
&& init_thread_intf_started
>= 3)
369 /* pull the plug if recursion occurs... */
372 /* lookup fprint to print fatal error message */
373 void *ptr
= dlsym (RTLD_DEFAULT
, "fprintf");
376 __real_fprintf
= (void *) ptr
;
383 /* find the __collector_jprofile_enable_synctrace routine in jprofile module */
384 ptr
= dlsym (RTLD_DEFAULT
, "__collector_jprofile_enable_synctrace");
386 __real___collector_jprofile_enable_synctrace
= (void *) ptr
;
389 #if defined(GPROFNG_JAVA_PROFILING)
390 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT __collector_jprofile_enable_synctrace\n");
391 err
= COL_ERROR_SYNCINIT
;
397 /* ########################################## begin WSIZE(32) */
398 /* IMPORTANT!! The GLIBC_* versions below must match those in the er_sync.*.mapfile ! */
400 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.0");
403 /* We are probably dlopened after libthread/libc,
404 * try to search in the previously loaded objects
406 dlflag
= RTLD_DEFAULT
;
407 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.0");
410 __real_pthread_mutex_lock
= ptr
;
411 Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for OS sync routines\n");
415 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
416 err
= COL_ERROR_SYNCINIT
;
420 __real_pthread_mutex_lock
= ptr
;
422 ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.0");
424 __real_pthread_mutex_unlock
= (void *) ptr
;
427 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
428 err
= COL_ERROR_SYNCINIT
;
430 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.3.2");
432 __real_pthread_cond_wait
= (void *) ptr
;
435 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
436 err
= COL_ERROR_SYNCINIT
;
438 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.3.2");
440 __real_pthread_cond_timedwait
= (void *) ptr
;
443 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
444 err
= COL_ERROR_SYNCINIT
;
446 ptr
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.0");
448 __real_pthread_join
= (void *) ptr
;
451 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
452 err
= COL_ERROR_SYNCINIT
;
454 ptr
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.1");
456 __real_sem_wait
= (void *) ptr
;
459 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
460 err
= COL_ERROR_SYNCINIT
;
464 /* ############## Intel specific additional pointers for 32-bits */
465 ptr
= __real_sem_wait_2_1
= __real_sem_wait
;
466 ptr
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.0");
468 __real_sem_wait_2_0
= (void *) ptr
;
471 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT sem_wait_2_0\n");
472 err
= COL_ERROR_SYNCINIT
;
474 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.0");
476 __real_pthread_cond_wait_2_0
= (void *) ptr
;
479 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_0\n");
480 err
= COL_ERROR_SYNCINIT
;
482 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.0");
484 __real_pthread_cond_timedwait_2_0
= (void *) ptr
;
487 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT __real_pthread_cond_timedwait_2_0\n");
488 err
= COL_ERROR_SYNCINIT
;
490 #endif /* ARCH(Intel) */
492 #else /* WSIZE(64) */
493 /* # most versions are different between platforms */
494 /* # the few that are common are set after the ARCH ifdef */
497 #define GLIBC_N "GLIBC_2.17"
498 __real_pthread_mutex_lock
= dlvsym(dlflag
, "pthread_mutex_lock", GLIBC_N
);
499 __real_pthread_mutex_unlock
= dlvsym(dlflag
, "pthread_mutex_unlock", GLIBC_N
);
500 __real_pthread_cond_wait
= dlvsym(dlflag
, "pthread_cond_wait", GLIBC_N
);
501 __real_pthread_cond_timedwait
= dlvsym(dlflag
, "pthread_cond_timedwait", GLIBC_N
);
502 __real_pthread_join
= dlvsym(dlflag
, "pthread_join", GLIBC_N
);
503 __real_sem_wait
= dlvsym(dlflag
, "sem_wait", GLIBC_N
);
507 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.2.5");
510 /* We are probably dlopened after libthread/libc,
511 * try to search in the previously loaded objects
513 dlflag
= RTLD_DEFAULT
;
514 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.2.5");
517 __real_pthread_mutex_lock
= ptr
;
518 Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for Solaris sync routines\n");
522 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
523 err
= COL_ERROR_SYNCINIT
;
527 __real_pthread_mutex_lock
= ptr
;
528 ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.2.5");
530 __real_pthread_mutex_unlock
= (void *) ptr
;
533 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
534 err
= COL_ERROR_SYNCINIT
;
536 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.3.2");
538 __real_pthread_cond_wait
= (void *) ptr
;
541 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
542 err
= COL_ERROR_SYNCINIT
;
544 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.3.2");
546 __real_pthread_cond_timedwait
= (void *) ptr
;
549 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
550 err
= COL_ERROR_SYNCINIT
;
552 ptr
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.2.5");
554 __real_pthread_join
= (void *) ptr
;
557 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
558 err
= COL_ERROR_SYNCINIT
;
560 ptr
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.2.5");
562 __real_sem_wait
= (void *) ptr
;
565 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
566 err
= COL_ERROR_SYNCINIT
;
568 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.2.5");
570 __real_pthread_cond_wait_2_2_5
= (void *) ptr
;
573 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_2_5\n");
574 err
= COL_ERROR_SYNCINIT
;
576 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.2.5");
578 __real_pthread_cond_timedwait_2_2_5
= (void *) ptr
;
581 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait_2_2_5\n");
582 err
= COL_ERROR_SYNCINIT
;
587 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.2");
590 /* We are probably dlopened after libthread/libc,
591 * try to search in the previously loaded objects
593 dlflag
= RTLD_DEFAULT
;
594 ptr
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.2");
597 __real_pthread_mutex_lock
= ptr
;
598 Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for Solaris sync routines\n");
602 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT mutex_lock\n");
603 err
= COL_ERROR_SYNCINIT
;
607 __real_pthread_mutex_lock
= ptr
;
608 ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.2");
610 __real_pthread_mutex_unlock
= (void *) ptr
;
613 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
614 err
= COL_ERROR_SYNCINIT
;
616 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.3.2");
618 __real_pthread_cond_wait
= (void *) ptr
;
621 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
622 err
= COL_ERROR_SYNCINIT
;
624 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.3.2");
626 __real_pthread_cond_timedwait
= (void *) ptr
;
629 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
630 err
= COL_ERROR_SYNCINIT
;
632 ptr
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.2");
634 __real_pthread_join
= (void *) ptr
;
637 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
638 err
= COL_ERROR_SYNCINIT
;
640 ptr
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.2");
642 __real_sem_wait
= (void *) ptr
;
645 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
646 err
= COL_ERROR_SYNCINIT
;
648 ptr
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.2");
650 __real_pthread_cond_wait_2_2
= (void *) ptr
;
653 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_2_5\n");
654 err
= COL_ERROR_SYNCINIT
;
656 ptr
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.2");
658 __real_pthread_cond_timedwait_2_2
= (void *) ptr
;
661 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait_2_2\n");
662 err
= COL_ERROR_SYNCINIT
;
665 #endif /* WSIZE(64) */
666 /* the pointers that are common to 32- and 64-bits, and to SPARC and Intel */
668 __real_pthread_cond_wait_2_3_2
= __real_pthread_cond_wait
;
669 __real_pthread_cond_timedwait_2_3_2
= __real_pthread_cond_timedwait
;
670 ptr
= dlsym (dlflag
, "strtol");
672 __real_strtol
= (void *) ptr
;
675 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT strtol\n");
676 err
= COL_ERROR_SYNCINIT
;
678 init_thread_intf_finished
++;
679 TprintfT (0, "synctrace init_thread_intf complete\n");
683 /* These next two routines are used from jprofile to record Java synctrace data */
685 __collector_jsync_begin ()
688 if (CHCK_JREENTRANCE (guard
))
690 Tprintf (DBG_LT1
, "__collector_jsync_begin: skipped\n");
693 Tprintf (DBG_LT1
, "__collector_jsync_begin: start event\n");
694 PUSH_REENTRANCE (guard
);
698 __collector_jsync_end (hrtime_t reqt
, void *object
)
701 if (RECHCK_JREENTRANCE (guard
))
703 Tprintf (DBG_LT1
, "__collector_jsync_end: skipped\n");
706 hrtime_t grnt
= gethrtime ();
707 if (grnt
- reqt
>= sync_threshold
)
710 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
711 spacket
.comm
.tsize
= sizeof (Sync_packet
);
712 spacket
.comm
.tstamp
= grnt
;
713 spacket
.requested
= reqt
;
714 spacket
.objp
= (intptr_t) object
;
715 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
, spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
716 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) & spacket
);
718 Tprintf (DBG_LT1
, "__collector_jsync_begin: end event\n");
719 POP_REENTRANCE (guard
);
722 /*-------------------------------------------------------- pthread_mutex_lock */
724 pthread_mutex_lock (pthread_mutex_t
*mp
)
727 if (NULL_PTR (pthread_mutex_lock
))
729 if (CHCK_NREENTRANCE (guard
))
730 return CALL_REAL (pthread_mutex_lock
)(mp
);
731 PUSH_REENTRANCE (guard
);
732 hrtime_t reqt
= gethrtime ();
733 int ret
= CALL_REAL (pthread_mutex_lock
)(mp
);
734 if (RECHCK_NREENTRANCE (guard
))
736 POP_REENTRANCE (guard
);
739 hrtime_t grnt
= gethrtime ();
740 if (grnt
- reqt
>= sync_threshold
)
743 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
744 spacket
.comm
.tsize
= sizeof (Sync_packet
);
745 spacket
.comm
.tstamp
= grnt
;
746 spacket
.requested
= reqt
;
747 spacket
.objp
= (intptr_t) mp
;
748 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
, spacket
.comm
.tstamp
, FRINFO_FROM_STACK
, &spacket
);
749 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) & spacket
);
751 POP_REENTRANCE (guard
);
756 /*------------------------------------------------------------- pthread_cond_wait */
757 // map interposed symbol versions
759 __collector_pthread_cond_wait_symver (int(real_pthread_cond_wait
) (), pthread_cond_t
*cond
, pthread_mutex_t
*mutex
);
761 #if ARCH(Intel) || ARCH(SPARC)
762 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_3_2
,
763 pthread_cond_wait@@GLIBC_2
.3
.2)
766 __collector_pthread_cond_wait_2_3_2 (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
768 if (NULL_PTR (pthread_cond_wait
))
770 TprintfT (DBG_LTT
, "linetrace: GLIBC: __collector_pthread_cond_wait_2_3_2@%p\n", CALL_REAL (pthread_cond_wait_2_3_2
));
771 return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_3_2
), cond
, mutex
);
776 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_0
,
777 pthread_cond_wait@GLIBC_2
.0
)
779 __collector_pthread_cond_wait_2_0 (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
781 if (NULL_PTR (pthread_cond_wait
))
783 TprintfT (DBG_LTT
, "linetrace: GLIBC: __collector_pthread_cond_wait_2_0@%p\n", CALL_REAL (pthread_cond_wait_2_0
));
784 return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_0
), cond
, mutex
);
788 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2_5
,
789 pthread_cond_wait@GLIBC_2
.2
.5)
791 __collector_pthread_cond_wait_2_2_5 (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
793 if (NULL_PTR (pthread_cond_wait
))
795 TprintfT (DBG_LTT
, "linetrace: GLIBC: __collector_pthread_cond_wait_2_2_5@%p\n", CALL_REAL (pthread_cond_wait_2_2_5
));
796 return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_2_5
), cond
, mutex
);
800 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2
,
801 pthread_cond_wait@GLIBC_2
.2
)
803 __collector_pthread_cond_wait_2_2 (pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
805 if (NULL_PTR (pthread_cond_wait
))
807 TprintfT (DBG_LTT
, "linetrace: GLIBC: __collector_pthread_cond_wait_2_2@%p\n", CALL_REAL (pthread_cond_wait_2_2
));
808 return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_2
), cond
, mutex
);
814 __collector_pthread_cond_wait_symver (int(real_pthread_cond_wait
) (), pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
817 if (NULL_PTR (pthread_cond_wait
))
819 if (CHCK_NREENTRANCE (guard
))
820 return (real_pthread_cond_wait
) (cond
, mutex
);
821 PUSH_REENTRANCE (guard
);
822 hrtime_t reqt
= gethrtime ();
824 ret
= (real_pthread_cond_wait
) (cond
, mutex
);
825 if (RECHCK_NREENTRANCE (guard
))
827 POP_REENTRANCE (guard
);
830 hrtime_t grnt
= gethrtime ();
831 if (grnt
- reqt
>= sync_threshold
)
834 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
835 spacket
.comm
.tsize
= sizeof (Sync_packet
);
836 spacket
.comm
.tstamp
= grnt
;
837 spacket
.requested
= reqt
;
838 spacket
.objp
= (intptr_t) mutex
;
839 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
, spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
840 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) & spacket
);
842 POP_REENTRANCE (guard
);
846 /*---------------------------------------------------- pthread_cond_timedwait */
847 // map interposed symbol versions
849 __collector_pthread_cond_timedwait_symver (int(real_pthread_cond_timedwait
) (),
850 pthread_cond_t
*cond
,
851 pthread_mutex_t
*mutex
,
852 const struct timespec
*abstime
);
854 #if ARCH(Intel) || ARCH(SPARC)
855 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_3_2
,
856 pthread_cond_timedwait@@GLIBC_2
.3
.2)
859 __collector_pthread_cond_timedwait_2_3_2 (pthread_cond_t
*cond
,
860 pthread_mutex_t
*mutex
,
861 const struct timespec
*abstime
)
863 if (NULL_PTR (pthread_cond_timedwait
))
865 TprintfT (DBG_LTT
, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_3_2@%p\n", CALL_REAL (pthread_cond_timedwait_2_3_2
));
866 return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_3_2
), cond
, mutex
, abstime
);
870 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_0
,
871 pthread_cond_timedwait@GLIBC_2
.0
)
873 __collector_pthread_cond_timedwait_2_0 (pthread_cond_t
*cond
,
874 pthread_mutex_t
*mutex
,
875 const struct timespec
*abstime
)
877 if (NULL_PTR (pthread_cond_timedwait
))
879 TprintfT (DBG_LTT
, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_0@%p\n", CALL_REAL (pthread_cond_timedwait_2_0
));
880 return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_0
), cond
, mutex
, abstime
);
884 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2_5
,
885 pthread_cond_timedwait@GLIBC_2
.2
.5)
887 __collector_pthread_cond_timedwait_2_2_5 (pthread_cond_t
*cond
,
888 pthread_mutex_t
*mutex
,
889 const struct timespec
*abstime
)
891 if (NULL_PTR (pthread_cond_timedwait
))
893 TprintfT (DBG_LTT
, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_2_5@%p\n", CALL_REAL (pthread_cond_timedwait_2_2_5
));
894 return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_2_5
), cond
, mutex
, abstime
);
898 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2
,
899 pthread_cond_timedwait@GLIBC_2
.2
)
901 __collector_pthread_cond_timedwait_2_2 (pthread_cond_t
*cond
,
902 pthread_mutex_t
*mutex
,
903 const struct timespec
*abstime
)
905 if (NULL_PTR (pthread_cond_timedwait
))
907 TprintfT (DBG_LTT
, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_2@%p\n", CALL_REAL (pthread_cond_timedwait_2_2
));
908 return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_2
), cond
, mutex
, abstime
);
914 __collector_pthread_cond_timedwait_symver (int(real_pthread_cond_timedwait
) (),
915 pthread_cond_t
*cond
,
916 pthread_mutex_t
*mutex
,
917 const struct timespec
*abstime
)
920 if (NULL_PTR (pthread_cond_timedwait
))
922 if (CHCK_NREENTRANCE (guard
))
923 return (real_pthread_cond_timedwait
) (cond
, mutex
, abstime
);
924 PUSH_REENTRANCE (guard
);
925 hrtime_t reqt
= gethrtime ();
927 ret
= (real_pthread_cond_timedwait
) (cond
, mutex
, abstime
);
928 if (RECHCK_NREENTRANCE (guard
))
930 POP_REENTRANCE (guard
);
933 hrtime_t grnt
= gethrtime ();
934 if (grnt
- reqt
>= sync_threshold
)
937 collector_memset (&spacket
, 0, sizeof ( Sync_packet
));
938 spacket
.comm
.tsize
= sizeof ( Sync_packet
);
939 spacket
.comm
.tstamp
= grnt
;
940 spacket
.requested
= reqt
;
941 spacket
.objp
= (intptr_t) mutex
;
942 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
, spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
943 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) & spacket
);
945 POP_REENTRANCE (guard
);
949 /*------------------------------------------------------------- pthread_join */
951 pthread_join (pthread_t target_thread
, void **status
)
954 if (NULL_PTR (pthread_join
))
956 if (CHCK_NREENTRANCE (guard
))
957 return CALL_REAL (pthread_join
)(target_thread
, status
);
958 PUSH_REENTRANCE (guard
);
959 hrtime_t reqt
= gethrtime ();
960 int ret
= CALL_REAL (pthread_join
)(target_thread
, status
);
961 if (RECHCK_NREENTRANCE (guard
))
963 POP_REENTRANCE (guard
);
966 hrtime_t grnt
= gethrtime ();
967 if (grnt
- reqt
>= sync_threshold
)
970 collector_memset (&spacket
, 0, sizeof ( Sync_packet
));
971 spacket
.comm
.tsize
= sizeof ( Sync_packet
);
972 spacket
.comm
.tstamp
= grnt
;
973 spacket
.requested
= reqt
;
974 spacket
.objp
= (Vaddr_type
) target_thread
;
975 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
, spacket
.comm
.tstamp
, FRINFO_FROM_STACK
, &spacket
);
976 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) & spacket
);
978 POP_REENTRANCE (guard
);
982 /*------------------------------------------------------------- sem_wait */
983 // map interposed symbol versions
984 #if ARCH(Intel) && WSIZE(32)
986 __collector_sem_wait_symver (int(real_sem_wait
) (), sem_t
*sp
);
988 SYMVER_ATTRIBUTE (__collector_sem_wait_2_1
, sem_wait@@GLIBC_2
.1
)
990 __collector_sem_wait_2_1 (sem_t
*sp
)
992 if (NULL_PTR (sem_wait
))
994 TprintfT (DBG_LTT
, "linetrace: GLIBC: __collector_sem_wait_2_1@%p\n", CALL_REAL (sem_wait_2_1
));
995 return __collector_sem_wait_symver (CALL_REAL (sem_wait_2_1
), sp
);
998 SYMVER_ATTRIBUTE (__collector_sem_wait_2_0
, sem_wait@GLIBC_2
.0
)
1000 __collector_sem_wait_2_0 (sem_t
*sp
)
1002 if (NULL_PTR (sem_wait
))
1003 init_thread_intf ();
1004 TprintfT (DBG_LTT
, "linetrace: GLIBC: __collector_sem_wait_2_0@%p\n", CALL_REAL (sem_wait_2_0
));
1005 return __collector_sem_wait_symver (CALL_REAL (sem_wait_2_0
), sp
);
1009 #if ARCH(Intel) && WSIZE(32)
1011 __collector_sem_wait_symver (int(real_sem_wait
) (), sem_t
*sp
)
1015 sem_wait (sem_t
*sp
)
1019 if (NULL_PTR (sem_wait
))
1020 init_thread_intf ();
1021 if (CHCK_NREENTRANCE (guard
))
1023 #if ARCH(Intel) && WSIZE(32)
1024 return (real_sem_wait
) (sp
);
1026 return CALL_REAL (sem_wait
)(sp
);
1029 PUSH_REENTRANCE (guard
);
1030 hrtime_t reqt
= gethrtime ();
1032 #if ARCH(Intel) && WSIZE(32)
1033 ret
= (real_sem_wait
) (sp
);
1035 ret
= CALL_REAL (sem_wait
)(sp
);
1037 if (RECHCK_NREENTRANCE (guard
))
1039 POP_REENTRANCE (guard
);
1042 hrtime_t grnt
= gethrtime ();
1043 if (grnt
- reqt
>= sync_threshold
)
1045 Sync_packet spacket
;
1046 collector_memset (&spacket
, 0, sizeof ( Sync_packet
));
1047 spacket
.comm
.tsize
= sizeof ( Sync_packet
);
1048 spacket
.comm
.tstamp
= grnt
;
1049 spacket
.requested
= reqt
;
1050 spacket
.objp
= (intptr_t) sp
;
1052 #if ARCH(Intel) && WSIZE(32)
1053 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
, spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
1055 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
, spacket
.comm
.tstamp
, FRINFO_FROM_STACK
, &spacket
);
1057 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) & spacket
);
1059 POP_REENTRANCE (guard
);