1 /* Copyright (C) 2021-2023 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() */
32 #include <sys/param.h>
36 #include "collector.h"
37 #include "gp-experiment.h"
38 #include "data_pckts.h"
40 #include "cc_libcollector.h"
42 /* define the packet that will be written out */
43 typedef struct Sync_packet
44 { /* Synchronization delay tracing packet */
46 hrtime_t requested
; /* time of synchronization request */
47 Vaddr_type objp
; /* vaddr of synchronization object */
50 static int open_experiment (const char *);
51 static int start_data_collection (void);
52 static int stop_data_collection (void);
53 static int close_experiment (void);
54 static int detach_experiment (void);
55 static int init_thread_intf ();
56 static int sync_calibrate ();
58 static ModuleInterface module_interface
={
59 SP_SYNCTRACE_FILE
, /* description */
60 NULL
, /* initInterface */
61 open_experiment
, /* openExperiment */
62 start_data_collection
, /* startDataCollection */
63 stop_data_collection
, /* stopDataCollection */
64 close_experiment
, /* closeExperiment */
65 detach_experiment
/* detachExperiment (fork child) */
68 static CollectorInterface
*collector_interface
= NULL
;
69 static int sync_mode
= 0;
70 static long sync_scope
= 0;
71 static int sync_native
= 0;
72 static int sync_java
= 0;
73 static CollectorModule sync_hndl
= COLLECTOR_MODULE_ERR
;
74 static unsigned sync_key
= COLLECTOR_TSD_INVALID_KEY
;
75 static long sync_threshold
= -1; /* calibrate the value */
76 static int init_thread_intf_started
= 0;
77 static int init_thread_intf_finished
= 0;
79 #define CHCK_NREENTRANCE(x) (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
80 #define RECHCK_NREENTRANCE(x) (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
81 #define CHCK_JREENTRANCE(x) (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
82 #define RECHCK_JREENTRANCE(x) (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
83 #define PUSH_REENTRANCE(x) ((*(x))++)
84 #define POP_REENTRANCE(x) ((*(x))--)
85 #define gethrtime collector_interface->getHiResTime
88 * In most cases, the functions which require interposition are implemented as
89 * weak symbols corresponding to an associated internal function named with a
90 * leading underscore: e.g., mutex_lock() is simply an alias for _mutex_lock().
91 * For the wait functions, however, the published version (used by applications)
92 * is distinct from the internal version (used by system libraries), i.e.,
93 * cond_wait() is an alias for _cond_wait_cancel() rather than _cond_wait().
95 static long int (*__real_strtol
)(const char *nptr
, char **endptr
, int base
) = NULL
;
96 static int (*__real_fprintf
) (FILE *stream
, const char *format
, ...) = NULL
;
97 static void (*__real___collector_jprofile_enable_synctrace
) (void) = NULL
;
98 static int (*__real_pthread_mutex_lock
) (pthread_mutex_t
*mutex
) = NULL
;
99 static int (*__real_pthread_mutex_lock_2_17
) (pthread_mutex_t
*mutex
) = NULL
;
100 static int (*__real_pthread_mutex_lock_2_2_5
) (pthread_mutex_t
*mutex
) = NULL
;
101 static int (*__real_pthread_mutex_lock_2_0
) (pthread_mutex_t
*mutex
) = NULL
;
102 static int (*__real_pthread_mutex_unlock
) (pthread_mutex_t
*mutex
) = NULL
;
103 static int (*__real_pthread_cond_wait
) (pthread_cond_t
*restrict cond
,
104 pthread_mutex_t
*restrict mutex
) = NULL
;
105 static int (*__real_pthread_cond_timedwait
) (pthread_cond_t
*restrict cond
,
106 pthread_mutex_t
*restrict mutex
,
107 const struct timespec
*restrict abstime
) = NULL
;
108 static int (*__real_pthread_join
) (pthread_t thread
, void **retval
) = NULL
;
109 static int (*__real_pthread_join_2_34
) (pthread_t thread
, void **retval
) = NULL
;
110 static int (*__real_pthread_join_2_17
) (pthread_t thread
, void **retval
) = NULL
;
111 static int (*__real_pthread_join_2_2_5
) (pthread_t thread
, void **retval
) = NULL
;
112 static int (*__real_pthread_join_2_0
) (pthread_t thread
, void **retval
) = NULL
;
113 static int (*__real_sem_wait
) (sem_t
*sem
) = NULL
;
114 static int (*__real_sem_wait_2_34
) (sem_t
*sem
) = NULL
;
115 static int (*__real_sem_wait_2_17
) (sem_t
*sem
) = NULL
;
116 static int (*__real_sem_wait_2_2_5
) (sem_t
*sem
) = NULL
;
117 static int (*__real_sem_wait_2_1
) (sem_t
*sem
) = NULL
;
118 static int (*__real_sem_wait_2_0
) (sem_t
*sem
) = NULL
;
119 static int (*__real_pthread_cond_wait_2_17
) (pthread_cond_t
*restrict cond
,
120 pthread_mutex_t
*restrict mutex
) = NULL
;
121 static int (*__real_pthread_cond_wait_2_3_2
) (pthread_cond_t
*restrict cond
,
122 pthread_mutex_t
*restrict mutex
) = NULL
;
123 static int (*__real_pthread_cond_wait_2_2_5
) (pthread_cond_t
*restrict cond
,
124 pthread_mutex_t
*restrict mutex
) = NULL
;
125 static int (*__real_pthread_cond_wait_2_0
) (pthread_cond_t
*restrict cond
,
126 pthread_mutex_t
*restrict mutex
) = NULL
;
127 static int (*__real_pthread_cond_timedwait_2_17
) (pthread_cond_t
*restrict cond
,
128 pthread_mutex_t
*restrict mutex
,
129 const struct timespec
*restrict abstime
) = NULL
;
130 static int (*__real_pthread_cond_timedwait_2_3_2
) (pthread_cond_t
*restrict cond
,
131 pthread_mutex_t
*restrict mutex
,
132 const struct timespec
*restrict abstime
) = NULL
;
133 static int (*__real_pthread_cond_timedwait_2_2_5
) (pthread_cond_t
*restrict cond
,
134 pthread_mutex_t
*restrict mutex
,
135 const struct timespec
*restrict abstime
) = NULL
;
136 static int (*__real_pthread_cond_timedwait_2_0
) (pthread_cond_t
*restrict cond
,
137 pthread_mutex_t
*restrict mutex
,
138 const struct timespec
*restrict abstime
) = NULL
;
142 collector_memset (void *s
, int c
, size_t n
)
144 unsigned char *s1
= s
;
146 *s1
++ = (unsigned char) c
;
150 __collector_module_init (CollectorInterface
*_collector_interface
)
152 if (_collector_interface
== NULL
)
154 collector_interface
= _collector_interface
;
155 TprintfT (0, "synctrace: __collector_module_init\n");
156 sync_hndl
= collector_interface
->registerModule (&module_interface
);
158 /* Initialize next module */
159 ModuleInitFunc next_init
= (ModuleInitFunc
) dlsym (RTLD_NEXT
, "__collector_module_init");
160 if (next_init
!= NULL
)
161 next_init (_collector_interface
);
165 open_experiment (const char *exp
)
168 if (init_thread_intf_finished
== 0)
170 if (collector_interface
== NULL
)
172 Tprintf (0, "synctrace: collector_interface is null.\n");
173 return COL_ERROR_SYNCINIT
;
175 if (sync_hndl
== COLLECTOR_MODULE_ERR
)
177 Tprintf (0, "synctrace: handle create failed.\n");
178 collector_interface
->writeLog ("<event kind=\"%s\" id=\"%d\">data handle not created</event>\n",
179 SP_JCMD_CERROR
, COL_ERROR_SYNCINIT
);
180 return COL_ERROR_SYNCINIT
;
182 TprintfT (0, "synctrace: open_experiment %s\n", exp
);
184 char *params
= (char *) collector_interface
->getParams ();
187 if ((params
[0] == 's') && (params
[1] == ':'))
189 char *ptr
= params
+ 2;
190 Tprintf (DBG_LT1
, "synctrace: open_experiment s: parameter = %s\n", ptr
);
191 while (*ptr
!= ',' && *ptr
!= ';')
196 sync_scope
= CALL_REAL (strtol
) (ptr
+ 1, NULL
, 0);
213 Tprintf (0, "\tsynctrace: sync_scope found as %ld\n", sync_scope
);
217 /* the old-style descriptor, without scope */
218 /* if there was no comma, use the old default */
222 Tprintf (0, "\tsynctrace: sync_scope not found set to %ld\n", sync_scope
);
224 if (__real___collector_jprofile_enable_synctrace
== NULL
)
226 thresh
= CALL_REAL (strtol
)(params
+ 2, NULL
, 0);
227 break; /* from the loop to find the "s:thresh,scope" entry */
232 if (params
== NULL
) /* Sync data collection not specified */
233 return COL_ERROR_SYNCINIT
;
234 if (thresh
< 0) /* calibrate the threshold, keep it as a negative number */
235 thresh
= -sync_calibrate ();
237 sync_key
= collector_interface
->createKey (sizeof ( int), NULL
, NULL
);
238 if (sync_key
== (unsigned) - 1)
240 Tprintf (0, "synctrace: TSD key create failed.\n");
241 collector_interface
->writeLog ("<event kind=\"%s\" id=\"%d\">TSD key not created</event>\n",
242 SP_JCMD_CERROR
, COL_ERROR_SYNCINIT
);
243 return COL_ERROR_SYNCINIT
;
245 /* if Java synctrace was requested, tell the jprofile module */
248 TprintfT (0, "synctrace: enabling Java synctrace\n");
249 CALL_REAL (__collector_jprofile_enable_synctrace
)();
251 collector_interface
->writeLog ("<profile name=\"%s\" threshold=\"%ld\" scope=\"%ld\">\n",
252 SP_JCMD_SYNCTRACE
, thresh
, sync_scope
);
253 collector_interface
->writeLog (" <profdata fname=\"%s\"/>\n",
254 module_interface
.description
);
255 /* Record Sync_packet description */
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 (int) offsetof (Sync_packet
, comm
.lwp_id
),
259 fld_sizeof (Sync_packet
, comm
.lwp_id
) == 4 ? "INT32" : "INT64");
260 collector_interface
->writeLog (" <field name=\"THRID\" uname=\"Thread number\" offset=\"%d\" type=\"%s\"/>\n",
261 (int) offsetof (Sync_packet
, comm
.thr_id
),
262 fld_sizeof (Sync_packet
, comm
.thr_id
) == 4 ? "INT32" : "INT64");
263 collector_interface
->writeLog (" <field name=\"CPUID\" uname=\"CPU id\" offset=\"%d\" type=\"%s\"/>\n",
264 (int) offsetof (Sync_packet
, comm
.cpu_id
),
265 fld_sizeof (Sync_packet
, comm
.cpu_id
) == 4 ? "INT32" : "INT64");
266 collector_interface
->writeLog (" <field name=\"TSTAMP\" uname=\"High resolution timestamp\" offset=\"%d\" type=\"%s\"/>\n",
267 (int) offsetof (Sync_packet
, comm
.tstamp
),
268 fld_sizeof (Sync_packet
, comm
.tstamp
) == 4 ? "INT32" : "INT64");
269 collector_interface
->writeLog (" <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
270 (int) offsetof (Sync_packet
, comm
.frinfo
),
271 fld_sizeof (Sync_packet
, comm
.frinfo
) == 4 ? "INT32" : "INT64");
272 collector_interface
->writeLog (" <field name=\"SRQST\" uname=\"Synchronization start time\" offset=\"%d\" type=\"%s\"/>\n",
273 (int) offsetof (Sync_packet
, requested
),
274 fld_sizeof (Sync_packet
, requested
) == 4 ? "INT32" : "INT64");
275 collector_interface
->writeLog (" <field name=\"SOBJ\" uname=\"Synchronization object address\" offset=\"%d\" type=\"%s\"/>\n",
276 (int) offsetof (Sync_packet
, objp
),
277 fld_sizeof (Sync_packet
, objp
) == 4 ? "INT32" : "INT64");
278 collector_interface
->writeLog (" </profpckt>\n");
279 collector_interface
->writeLog ("</profile>\n");
281 /* Convert threshold from microsec to nanosec */
282 sync_threshold
= (thresh
> 0 ? thresh
: -thresh
) * 1000;
283 TprintfT (0, "synctrace: open_experiment complete %ld\n", sync_threshold
);
284 return COL_ERROR_NONE
;
288 start_data_collection (void)
291 TprintfT (0, "synctrace: start_data_collection\n");
296 stop_data_collection (void)
299 TprintfT (0, "synctrace: stop_data_collection\n");
304 close_experiment (void)
308 sync_key
= COLLECTOR_TSD_INVALID_KEY
;
309 TprintfT (0, "synctrace: close_experiment\n");
313 /* fork child. Clean up state but don't write to experiment */
315 detach_experiment (void)
319 sync_key
= COLLECTOR_TSD_INVALID_KEY
;
320 TprintfT (0, "synctrace: detach_experiment\n");
324 #define NUM_ITER 100 /* number of iterations in calibration */
325 #define NUM_WARMUP 3 /* number of warm up iterations */
330 pthread_mutex_t mt
= PTHREAD_MUTEX_INITIALIZER
;
331 hrtime_t bt
, at
, delta
;
332 hrtime_t avg
, max
, min
;
336 min
= max
= (hrtime_t
) 0;
337 for (i
= 0; i
< NUM_ITER
+ NUM_WARMUP
; i
++)
339 /* Here we simulate a real call */
341 ret
= CALL_REAL (pthread_mutex_lock
)(&mt
);
343 CALL_REAL (pthread_mutex_unlock
)(&mt
);
344 if (i
< NUM_WARMUP
) /* skip these iterations */
346 /* add the time of this one */
356 /* compute average time */
357 avg
= avg
/ NUM_ITER
;
359 /* pretty simple, let's see how it works */
362 /* round up to the nearest microsecond */
363 ret
= (int) ((max
+ 999) / 1000);
368 init_pthread_mutex_lock (void *dlflag
)
370 __real_pthread_mutex_lock_2_17
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.17");
371 __real_pthread_mutex_lock_2_2_5
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.2.5");
372 __real_pthread_mutex_lock_2_0
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.0");
373 if (__real_pthread_mutex_lock_2_17
)
374 __real_pthread_mutex_lock
= __real_pthread_mutex_lock_2_17
;
375 else if (__real_pthread_mutex_lock_2_2_5
)
376 __real_pthread_mutex_lock
= __real_pthread_mutex_lock_2_2_5
;
377 else if (__real_pthread_mutex_lock_2_0
)
378 __real_pthread_mutex_lock
= __real_pthread_mutex_lock_2_0
;
380 __real_pthread_mutex_lock
= dlsym (dlflag
, "pthread_mutex_lock");
381 return __real_pthread_mutex_lock
? 1 : 0;
387 void *dlflag
= RTLD_NEXT
;
389 /* if we detect recursion/reentrance, SEGV so we can get a stack */
390 init_thread_intf_started
++;
391 if (!init_thread_intf_finished
&& init_thread_intf_started
>= 3)
393 /* pull the plug if recursion occurs... */
396 /* lookup fprint to print fatal error message */
397 void *ptr
= dlsym (RTLD_DEFAULT
, "fprintf");
400 __real_fprintf
= (void *) ptr
;
407 /* find the __collector_jprofile_enable_synctrace routine in jprofile module */
408 ptr
= dlsym (RTLD_DEFAULT
, "__collector_jprofile_enable_synctrace");
410 __real___collector_jprofile_enable_synctrace
= (void *) ptr
;
413 #if defined(GPROFNG_JAVA_PROFILING)
414 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT __collector_jprofile_enable_synctrace\n");
415 err
= COL_ERROR_SYNCINIT
;
421 if (init_pthread_mutex_lock (dlflag
) == 0)
423 /* We are probably dlopened after libthread/libc,
424 * try to search in the previously loaded objects
426 dlflag
= RTLD_DEFAULT
;
427 if (init_pthread_mutex_lock (dlflag
) == 0)
429 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
430 err
= COL_ERROR_SYNCINIT
;
434 if ((ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.17")) != NULL
)
435 __real_pthread_mutex_unlock
= ptr
;
436 else if ((ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.2.5")) != NULL
)
437 __real_pthread_mutex_unlock
= ptr
;
438 else if ((ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.0")) != NULL
)
439 __real_pthread_mutex_unlock
= ptr
;
441 __real_pthread_mutex_unlock
= dlsym (dlflag
, "pthread_mutex_unlock");
442 if (__real_pthread_mutex_unlock
== NULL
)
444 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
445 err
= COL_ERROR_SYNCINIT
;
448 __real_pthread_cond_wait_2_17
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.17");
449 __real_pthread_cond_wait_2_3_2
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.3.2");
450 __real_pthread_cond_wait_2_2_5
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.2.5");
451 __real_pthread_cond_wait_2_0
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.0");
452 if (__real_pthread_cond_wait_2_17
)
453 __real_pthread_cond_wait
= __real_pthread_cond_wait_2_17
;
454 else if (__real_pthread_cond_wait_2_3_2
)
455 __real_pthread_cond_wait
= __real_pthread_cond_wait_2_3_2
;
456 else if (__real_pthread_cond_wait_2_2_5
)
457 __real_pthread_cond_wait
= __real_pthread_cond_wait_2_2_5
;
458 else if (__real_pthread_cond_wait_2_0
)
459 __real_pthread_cond_wait
= __real_pthread_cond_wait_2_0
;
461 __real_pthread_cond_wait
= dlsym (dlflag
, "pthread_cond_wait");
462 if (__real_pthread_cond_wait
== NULL
)
464 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
465 err
= COL_ERROR_SYNCINIT
;
468 __real_pthread_cond_timedwait_2_17
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.17");
469 __real_pthread_cond_timedwait_2_3_2
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.3.2");
470 __real_pthread_cond_timedwait_2_2_5
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.2.5");
471 __real_pthread_cond_timedwait_2_0
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.0");
472 if (__real_pthread_cond_timedwait_2_17
)
473 __real_pthread_cond_timedwait
= __real_pthread_cond_timedwait_2_17
;
474 else if (__real_pthread_cond_timedwait_2_3_2
)
475 __real_pthread_cond_timedwait
= __real_pthread_cond_timedwait_2_3_2
;
476 else if (__real_pthread_cond_timedwait_2_2_5
)
477 __real_pthread_cond_timedwait
= __real_pthread_cond_timedwait_2_2_5
;
478 else if (__real_pthread_cond_timedwait_2_0
)
479 __real_pthread_cond_timedwait
= __real_pthread_cond_timedwait_2_0
;
481 __real_pthread_cond_timedwait
= dlsym (dlflag
, "pthread_cond_timedwait");
482 if (__real_pthread_cond_timedwait
== NULL
)
484 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
485 err
= COL_ERROR_SYNCINIT
;
488 __real_pthread_join_2_34
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.34");
489 __real_pthread_join_2_17
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.17");
490 __real_pthread_join_2_2_5
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.2.5");
491 __real_pthread_join_2_0
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.0");
492 if (__real_pthread_join_2_34
)
493 __real_pthread_join
= __real_pthread_join_2_34
;
494 else if (__real_pthread_join_2_17
)
495 __real_pthread_join
= __real_pthread_join_2_17
;
496 else if (__real_pthread_join_2_2_5
)
497 __real_pthread_join
= __real_pthread_join_2_2_5
;
498 else if (__real_pthread_join_2_0
)
499 __real_pthread_join
= __real_pthread_join_2_0
;
501 __real_pthread_join
= dlsym (dlflag
, "pthread_join");
502 if (__real_pthread_join
== NULL
)
504 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
505 err
= COL_ERROR_SYNCINIT
;
508 __real_sem_wait_2_34
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.34");
509 __real_sem_wait_2_17
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.17");
510 __real_sem_wait_2_2_5
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.2.5");
511 __real_sem_wait_2_1
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.1");
512 __real_sem_wait_2_0
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.0");
513 if (__real_sem_wait_2_34
)
514 __real_sem_wait
= __real_sem_wait_2_34
;
515 else if (__real_sem_wait_2_17
)
516 __real_sem_wait
= __real_sem_wait_2_17
;
517 else if (__real_sem_wait_2_2_5
)
518 __real_sem_wait
= __real_sem_wait_2_2_5
;
519 else if (__real_sem_wait_2_1
)
520 __real_sem_wait
= __real_sem_wait_2_1
;
521 else if (__real_sem_wait_2_0
)
522 __real_sem_wait
= __real_sem_wait_2_0
;
524 __real_sem_wait
= dlsym (dlflag
, "sem_wait");
525 if (__real_sem_wait
== NULL
)
527 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
528 err
= COL_ERROR_SYNCINIT
;
532 ptr
= dlsym (dlflag
, "strtol");
534 __real_strtol
= (void *) ptr
;
537 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT strtol\n");
538 err
= COL_ERROR_SYNCINIT
;
540 init_thread_intf_finished
++;
541 TprintfT (0, "synctrace init_thread_intf complete\n");
545 /* These next two routines are used from jprofile to record Java synctrace data */
547 __collector_jsync_begin ()
550 if (CHCK_JREENTRANCE (guard
))
552 Tprintf (DBG_LT1
, "__collector_jsync_begin: skipped\n");
555 Tprintf (DBG_LT1
, "__collector_jsync_begin: start event\n");
556 PUSH_REENTRANCE (guard
);
560 __collector_jsync_end (hrtime_t reqt
, void *object
)
563 if (RECHCK_JREENTRANCE (guard
))
565 Tprintf (DBG_LT1
, "__collector_jsync_end: skipped\n");
568 hrtime_t grnt
= gethrtime ();
569 if (grnt
- reqt
>= sync_threshold
)
572 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
573 spacket
.comm
.tsize
= sizeof (Sync_packet
);
574 spacket
.comm
.tstamp
= grnt
;
575 spacket
.requested
= reqt
;
576 spacket
.objp
= (intptr_t) object
;
577 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
578 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
579 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
581 Tprintf (DBG_LT1
, "__collector_jsync_begin: end event\n");
582 POP_REENTRANCE (guard
);
584 /*-------------------------------------------------------- pthread_mutex_lock */
586 gprofng_pthread_mutex_lock (int (real_func
) (pthread_mutex_t
*),
590 if (CHCK_NREENTRANCE (guard
))
591 return (real_func
) (mp
);
592 PUSH_REENTRANCE (guard
);
593 hrtime_t reqt
= gethrtime ();
594 int ret
= (real_func
) (mp
);
595 if (RECHCK_NREENTRANCE (guard
))
597 POP_REENTRANCE (guard
);
600 hrtime_t grnt
= gethrtime ();
601 if (grnt
- reqt
>= sync_threshold
)
604 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
605 spacket
.comm
.tsize
= sizeof (Sync_packet
);
606 spacket
.comm
.tstamp
= grnt
;
607 spacket
.requested
= reqt
;
608 spacket
.objp
= (intptr_t) mp
;
609 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
610 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
611 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
613 POP_REENTRANCE (guard
);
617 #define DCL_PTHREAD_MUTEX_LOCK(dcl_f) \
618 int dcl_f (pthread_mutex_t *mp) \
620 if (__real_pthread_mutex_lock == NULL) \
621 init_thread_intf (); \
622 return gprofng_pthread_mutex_lock (__real_pthread_mutex_lock, mp); \
625 DCL_FUNC_VER (DCL_PTHREAD_MUTEX_LOCK
, pthread_mutex_lock_2_17
, pthread_mutex_lock@GLIBC_2
.17
)
626 DCL_FUNC_VER (DCL_PTHREAD_MUTEX_LOCK
, pthread_mutex_lock_2_2_5
, pthread_mutex_lock@GLIBC_2
.2
.5)
627 DCL_FUNC_VER (DCL_PTHREAD_MUTEX_LOCK
, pthread_mutex_lock_2_0
, pthread_mutex_lock@GLIBC_2
.0
)
628 DCL_PTHREAD_MUTEX_LOCK (pthread_mutex_lock
)
630 /*------------------------------------------------------------- pthread_cond_wait */
632 gprofng_pthread_cond_wait (int(real_func
) (pthread_cond_t
*, pthread_mutex_t
*),
633 pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
636 if (CHCK_NREENTRANCE (guard
))
637 return (real_func
) (cond
, mutex
);
638 PUSH_REENTRANCE (guard
);
639 hrtime_t reqt
= gethrtime ();
641 ret
= (real_func
) (cond
, mutex
);
642 if (RECHCK_NREENTRANCE (guard
))
644 POP_REENTRANCE (guard
);
647 hrtime_t grnt
= gethrtime ();
648 if (grnt
- reqt
>= sync_threshold
)
651 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
652 spacket
.comm
.tsize
= sizeof (Sync_packet
);
653 spacket
.comm
.tstamp
= grnt
;
654 spacket
.requested
= reqt
;
655 spacket
.objp
= (intptr_t) mutex
;
656 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
657 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
658 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
660 POP_REENTRANCE (guard
);
664 #define DCL_PTHREAD_COND_WAIT(dcl_f) \
665 int dcl_f (pthread_cond_t *cond, pthread_mutex_t *mutex) \
667 if (__real_pthread_cond_wait == NULL) \
668 init_thread_intf (); \
669 return gprofng_pthread_cond_wait (__real_pthread_cond_wait, cond, mutex); \
672 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT
, pthread_cond_wait_2_17
, pthread_cond_wait@GLIBC_2
.17
)
673 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT
, pthread_cond_wait_2_3_2
, pthread_cond_wait@GLIBC_2
.3
.2)
674 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT
, pthread_cond_wait_2_2_5
, pthread_cond_wait@GLIBC_2
.2
.5)
675 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT
, pthread_cond_wait_2_0
, pthread_cond_wait@GLIBC_2
.0
)
676 DCL_PTHREAD_COND_WAIT (pthread_cond_wait
)
678 /*---------------------------------------------------- pthread_cond_timedwait */
680 gprofng_pthread_cond_timedwait (int(real_func
) (pthread_cond_t
*,
681 pthread_mutex_t
*, const struct timespec
*),
682 pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
683 const struct timespec
*abstime
)
686 if (CHCK_NREENTRANCE (guard
))
687 return (real_func
) (cond
, mutex
, abstime
);
688 PUSH_REENTRANCE (guard
);
689 hrtime_t reqt
= gethrtime ();
691 ret
= (real_func
) (cond
, mutex
, abstime
);
692 if (RECHCK_NREENTRANCE (guard
))
694 POP_REENTRANCE (guard
);
697 hrtime_t grnt
= gethrtime ();
698 if (grnt
- reqt
>= sync_threshold
)
701 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
702 spacket
.comm
.tsize
= sizeof (Sync_packet
);
703 spacket
.comm
.tstamp
= grnt
;
704 spacket
.requested
= reqt
;
705 spacket
.objp
= (intptr_t) mutex
;
706 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
707 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
708 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
710 POP_REENTRANCE (guard
);
714 #define DCL_PTHREAD_COND_TIMEDWAIT(dcl_f) \
715 int dcl_f (pthread_cond_t *cond, pthread_mutex_t *mutex, \
716 const struct timespec *abstime) \
718 if (__real_pthread_cond_timedwait == NULL) \
719 init_thread_intf (); \
720 return gprofng_pthread_cond_timedwait (__real_pthread_cond_timedwait, cond, mutex, abstime); \
723 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT
, pthread_cond_timedwait_2_17
, pthread_cond_timedwait@GLIBC_2
.17
)
724 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT
, pthread_cond_timedwait_2_3_2
, pthread_cond_timedwait@GLIBC_2
.3
.2)
725 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT
, pthread_cond_timedwait_2_2_5
, pthread_cond_timedwait@GLIBC_2
.2
.5)
726 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT
, pthread_cond_timedwait_2_0
, pthread_cond_timedwait@GLIBC_2
.0
)
727 DCL_PTHREAD_COND_TIMEDWAIT (pthread_cond_timedwait
)
730 /*------------------------------------------------------------- pthread_join */
732 gprofng_pthread_join (int(real_func
) (pthread_t
, void **),
733 pthread_t target_thread
, void **status
)
736 if (CHCK_NREENTRANCE (guard
))
737 return real_func (target_thread
, status
);
738 PUSH_REENTRANCE (guard
);
739 hrtime_t reqt
= gethrtime ();
740 int ret
= real_func(target_thread
, status
);
741 if (RECHCK_NREENTRANCE (guard
))
743 POP_REENTRANCE (guard
);
746 hrtime_t grnt
= gethrtime ();
747 if (grnt
- reqt
>= sync_threshold
)
750 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
751 spacket
.comm
.tsize
= sizeof (Sync_packet
);
752 spacket
.comm
.tstamp
= grnt
;
753 spacket
.requested
= reqt
;
754 spacket
.objp
= (Vaddr_type
) target_thread
;
755 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
756 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
757 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
759 POP_REENTRANCE (guard
);
763 #define DCL_PTHREAD_JOIN(dcl_f) \
764 int dcl_f (pthread_t target_thread, void **status) \
766 if (__real_pthread_join == NULL) \
767 init_thread_intf (); \
768 return gprofng_pthread_join (__real_pthread_join, target_thread, status); \
771 DCL_FUNC_VER (DCL_PTHREAD_JOIN
, pthread_join_2_34
, pthread_join@GLIBC_2
.34
)
772 DCL_FUNC_VER (DCL_PTHREAD_JOIN
, pthread_join_2_17
, pthread_join@GLIBC_2
.17
)
773 DCL_FUNC_VER (DCL_PTHREAD_JOIN
, pthread_join_2_2_5
, pthread_join@GLIBC_2
.2
.5)
774 DCL_FUNC_VER (DCL_PTHREAD_JOIN
, pthread_join_2_0
, pthread_join@GLIBC_2
.0
)
775 DCL_PTHREAD_JOIN (pthread_join
)
777 /*------------------------------------------------------------- sem_wait */
779 gprofng_sem_wait (int (real_func
) (sem_t
*), sem_t
*sp
)
782 if (CHCK_NREENTRANCE (guard
))
783 return real_func (sp
);
784 PUSH_REENTRANCE (guard
);
785 hrtime_t reqt
= gethrtime ();
787 ret
= real_func (sp
);
788 if (RECHCK_NREENTRANCE (guard
))
790 POP_REENTRANCE (guard
);
793 hrtime_t grnt
= gethrtime ();
794 if (grnt
- reqt
>= sync_threshold
)
797 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
798 spacket
.comm
.tsize
= sizeof (Sync_packet
);
799 spacket
.comm
.tstamp
= grnt
;
800 spacket
.requested
= reqt
;
801 spacket
.objp
= (intptr_t) sp
;
802 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
803 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
804 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
806 POP_REENTRANCE (guard
);
810 #define DCL_SEM_WAIT(dcl_f) \
811 int dcl_f (sem_t *sp) \
813 if (__real_sem_wait == NULL) \
814 init_thread_intf (); \
815 return gprofng_sem_wait (__real_sem_wait, sp); \
818 DCL_FUNC_VER (DCL_SEM_WAIT
, sem_wait_2_34
, sem_wait@GLIBC_2
.34
)
819 DCL_FUNC_VER (DCL_SEM_WAIT
, sem_wait_2_17
, sem_wait@GLIBC_2
.17
)
820 DCL_FUNC_VER (DCL_SEM_WAIT
, sem_wait_2_2_5
, sem_wait@GLIBC_2
.2
.5)
821 DCL_FUNC_VER (DCL_SEM_WAIT
, sem_wait_2_0
, sem_wait@GLIBC_2
.0
)
822 DCL_FUNC_VER (DCL_SEM_WAIT
, sem_wait_2_1
, sem_wait@GLIBC_2
.1
)
823 DCL_SEM_WAIT (sem_wait
)