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() */
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 /* define the packet that will be written out */
42 typedef struct Sync_packet
43 { /* Synchronization delay tracing packet */
45 hrtime_t requested
; /* time of synchronization request */
46 Vaddr_type objp
; /* vaddr of synchronization object */
49 static int open_experiment (const char *);
50 static int start_data_collection (void);
51 static int stop_data_collection (void);
52 static int close_experiment (void);
53 static int detach_experiment (void);
54 static int init_thread_intf ();
55 static int sync_calibrate ();
57 static ModuleInterface module_interface
={
58 SP_SYNCTRACE_FILE
, /* description */
59 NULL
, /* initInterface */
60 open_experiment
, /* openExperiment */
61 start_data_collection
, /* startDataCollection */
62 stop_data_collection
, /* stopDataCollection */
63 close_experiment
, /* closeExperiment */
64 detach_experiment
/* detachExperiment (fork child) */
67 static CollectorInterface
*collector_interface
= NULL
;
68 static int sync_mode
= 0;
69 static long sync_scope
= 0;
70 static int sync_native
= 0;
71 static int sync_java
= 0;
72 static CollectorModule sync_hndl
= COLLECTOR_MODULE_ERR
;
73 static unsigned sync_key
= COLLECTOR_TSD_INVALID_KEY
;
74 static long sync_threshold
= -1; /* calibrate the value */
75 static int init_thread_intf_started
= 0;
76 static int init_thread_intf_finished
= 0;
78 #define CHCK_NREENTRANCE(x) (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
79 #define RECHCK_NREENTRANCE(x) (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
80 #define CHCK_JREENTRANCE(x) (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
81 #define RECHCK_JREENTRANCE(x) (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
82 #define PUSH_REENTRANCE(x) ((*(x))++)
83 #define POP_REENTRANCE(x) ((*(x))--)
84 #define gethrtime collector_interface->getHiResTime
87 * In most cases, the functions which require interposition are implemented as
88 * weak symbols corresponding to an associated internal function named with a
89 * leading underscore: e.g., mutex_lock() is simply an alias for _mutex_lock().
90 * For the wait functions, however, the published version (used by applications)
91 * is distinct from the internal version (used by system libraries), i.e.,
92 * cond_wait() is an alias for _cond_wait_cancel() rather than _cond_wait().
94 static long int (*__real_strtol
)(const char *nptr
, char **endptr
, int base
) = NULL
;
95 static int (*__real_fprintf
) (FILE *stream
, const char *format
, ...) = NULL
;
96 static void (*__real___collector_jprofile_enable_synctrace
) (void) = NULL
;
97 static int (*__real_pthread_mutex_lock
) (pthread_mutex_t
*mutex
) = NULL
;
98 static int (*__real_pthread_mutex_lock_2_17
) (pthread_mutex_t
*mutex
) = NULL
;
99 static int (*__real_pthread_mutex_lock_2_2_5
) (pthread_mutex_t
*mutex
) = NULL
;
100 static int (*__real_pthread_mutex_lock_2_0
) (pthread_mutex_t
*mutex
) = NULL
;
101 static int (*__real_pthread_mutex_unlock
) (pthread_mutex_t
*mutex
) = NULL
;
102 static int (*__real_pthread_cond_wait
) (pthread_cond_t
*restrict cond
,
103 pthread_mutex_t
*restrict mutex
) = NULL
;
104 static int (*__real_pthread_cond_timedwait
) (pthread_cond_t
*restrict cond
,
105 pthread_mutex_t
*restrict mutex
,
106 const struct timespec
*restrict abstime
) = NULL
;
107 static int (*__real_pthread_join
) (pthread_t thread
, void **retval
) = NULL
;
108 static int (*__real_pthread_join_2_34
) (pthread_t thread
, void **retval
) = NULL
;
109 static int (*__real_pthread_join_2_17
) (pthread_t thread
, void **retval
) = NULL
;
110 static int (*__real_pthread_join_2_2_5
) (pthread_t thread
, void **retval
) = NULL
;
111 static int (*__real_pthread_join_2_0
) (pthread_t thread
, void **retval
) = NULL
;
112 static int (*__real_sem_wait
) (sem_t
*sem
) = NULL
;
113 static int (*__real_sem_wait_2_34
) (sem_t
*sem
) = NULL
;
114 static int (*__real_sem_wait_2_17
) (sem_t
*sem
) = NULL
;
115 static int (*__real_sem_wait_2_2_5
) (sem_t
*sem
) = NULL
;
116 static int (*__real_sem_wait_2_1
) (sem_t
*sem
) = NULL
;
117 static int (*__real_sem_wait_2_0
) (sem_t
*sem
) = NULL
;
118 static int (*__real_pthread_cond_wait_2_17
) (pthread_cond_t
*restrict cond
,
119 pthread_mutex_t
*restrict mutex
) = NULL
;
120 static int (*__real_pthread_cond_wait_2_3_2
) (pthread_cond_t
*restrict cond
,
121 pthread_mutex_t
*restrict mutex
) = NULL
;
122 static int (*__real_pthread_cond_wait_2_2_5
) (pthread_cond_t
*restrict cond
,
123 pthread_mutex_t
*restrict mutex
) = NULL
;
124 static int (*__real_pthread_cond_wait_2_0
) (pthread_cond_t
*restrict cond
,
125 pthread_mutex_t
*restrict mutex
) = NULL
;
126 static int (*__real_pthread_cond_timedwait_2_17
) (pthread_cond_t
*restrict cond
,
127 pthread_mutex_t
*restrict mutex
,
128 const struct timespec
*restrict abstime
) = NULL
;
129 static int (*__real_pthread_cond_timedwait_2_3_2
) (pthread_cond_t
*restrict cond
,
130 pthread_mutex_t
*restrict mutex
,
131 const struct timespec
*restrict abstime
) = NULL
;
132 static int (*__real_pthread_cond_timedwait_2_2_5
) (pthread_cond_t
*restrict cond
,
133 pthread_mutex_t
*restrict mutex
,
134 const struct timespec
*restrict abstime
) = NULL
;
135 static int (*__real_pthread_cond_timedwait_2_0
) (pthread_cond_t
*restrict cond
,
136 pthread_mutex_t
*restrict mutex
,
137 const struct timespec
*restrict abstime
) = 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);
361 init_pthread_mutex_lock (void *dlflag
)
363 __real_pthread_mutex_lock_2_17
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.17");
364 __real_pthread_mutex_lock_2_2_5
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.2.5");
365 __real_pthread_mutex_lock_2_0
= dlvsym (dlflag
, "pthread_mutex_lock", "GLIBC_2.0");
366 if (__real_pthread_mutex_lock_2_17
)
367 __real_pthread_mutex_lock
= __real_pthread_mutex_lock_2_17
;
368 else if (__real_pthread_mutex_lock_2_2_5
)
369 __real_pthread_mutex_lock
= __real_pthread_mutex_lock_2_2_5
;
370 else if (__real_pthread_mutex_lock_2_0
)
371 __real_pthread_mutex_lock
= __real_pthread_mutex_lock_2_0
;
373 __real_pthread_mutex_lock
= dlsym (dlflag
, "pthread_mutex_lock");
374 return __real_pthread_mutex_lock
? 1 : 0;
380 void *dlflag
= RTLD_NEXT
;
382 /* if we detect recursion/reentrance, SEGV so we can get a stack */
383 init_thread_intf_started
++;
384 if (!init_thread_intf_finished
&& init_thread_intf_started
>= 3)
386 /* pull the plug if recursion occurs... */
389 /* lookup fprint to print fatal error message */
390 void *ptr
= dlsym (RTLD_DEFAULT
, "fprintf");
393 __real_fprintf
= (void *) ptr
;
400 /* find the __collector_jprofile_enable_synctrace routine in jprofile module */
401 ptr
= dlsym (RTLD_DEFAULT
, "__collector_jprofile_enable_synctrace");
403 __real___collector_jprofile_enable_synctrace
= (void *) ptr
;
406 #if defined(GPROFNG_JAVA_PROFILING)
407 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT __collector_jprofile_enable_synctrace\n");
408 err
= COL_ERROR_SYNCINIT
;
414 if (init_pthread_mutex_lock (dlflag
) == 0)
416 /* We are probably dlopened after libthread/libc,
417 * try to search in the previously loaded objects
419 dlflag
= RTLD_DEFAULT
;
420 if (init_pthread_mutex_lock (dlflag
) == 0)
422 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
423 err
= COL_ERROR_SYNCINIT
;
427 if ((ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.17")) != NULL
)
428 __real_pthread_mutex_unlock
= ptr
;
429 else if ((ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.2.5")) != NULL
)
430 __real_pthread_mutex_unlock
= ptr
;
431 else if ((ptr
= dlvsym (dlflag
, "pthread_mutex_unlock", "GLIBC_2.0")) != NULL
)
432 __real_pthread_mutex_unlock
= ptr
;
434 __real_pthread_mutex_unlock
= dlsym (dlflag
, "pthread_mutex_unlock");
435 if (__real_pthread_mutex_unlock
== NULL
)
437 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
438 err
= COL_ERROR_SYNCINIT
;
441 __real_pthread_cond_wait_2_17
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.17");
442 __real_pthread_cond_wait_2_3_2
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.3.2");
443 __real_pthread_cond_wait_2_2_5
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.2.5");
444 __real_pthread_cond_wait_2_0
= dlvsym (dlflag
, "pthread_cond_wait", "GLIBC_2.0");
445 if (__real_pthread_cond_wait_2_17
)
446 __real_pthread_cond_wait
= __real_pthread_cond_wait_2_17
;
447 else if (__real_pthread_cond_wait_2_3_2
)
448 __real_pthread_cond_wait
= __real_pthread_cond_wait_2_3_2
;
449 else if (__real_pthread_cond_wait_2_2_5
)
450 __real_pthread_cond_wait
= __real_pthread_cond_wait_2_2_5
;
451 else if (__real_pthread_cond_wait_2_0
)
452 __real_pthread_cond_wait
= __real_pthread_cond_wait_2_0
;
454 __real_pthread_cond_wait
= dlsym (dlflag
, "pthread_cond_wait");
455 if (__real_pthread_cond_wait
== NULL
)
457 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
458 err
= COL_ERROR_SYNCINIT
;
461 __real_pthread_cond_timedwait_2_17
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.17");
462 __real_pthread_cond_timedwait_2_3_2
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.3.2");
463 __real_pthread_cond_timedwait_2_2_5
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.2.5");
464 __real_pthread_cond_timedwait_2_0
= dlvsym (dlflag
, "pthread_cond_timedwait", "GLIBC_2.0");
465 if (__real_pthread_cond_timedwait_2_17
)
466 __real_pthread_cond_timedwait
= __real_pthread_cond_timedwait_2_17
;
467 else if (__real_pthread_cond_timedwait_2_3_2
)
468 __real_pthread_cond_timedwait
= __real_pthread_cond_timedwait_2_3_2
;
469 else if (__real_pthread_cond_timedwait_2_2_5
)
470 __real_pthread_cond_timedwait
= __real_pthread_cond_timedwait_2_2_5
;
471 else if (__real_pthread_cond_timedwait_2_0
)
472 __real_pthread_cond_timedwait
= __real_pthread_cond_timedwait_2_0
;
474 __real_pthread_cond_timedwait
= dlsym (dlflag
, "pthread_cond_timedwait");
475 if (__real_pthread_cond_timedwait
== NULL
)
477 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
478 err
= COL_ERROR_SYNCINIT
;
481 __real_pthread_join_2_34
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.34");
482 __real_pthread_join_2_17
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.17");
483 __real_pthread_join_2_2_5
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.2.5");
484 __real_pthread_join_2_0
= dlvsym (dlflag
, "pthread_join", "GLIBC_2.0");
485 if (__real_pthread_join_2_34
)
486 __real_pthread_join
= __real_pthread_join_2_34
;
487 else if (__real_pthread_join_2_17
)
488 __real_pthread_join
= __real_pthread_join_2_17
;
489 else if (__real_pthread_join_2_2_5
)
490 __real_pthread_join
= __real_pthread_join_2_2_5
;
491 else if (__real_pthread_join_2_0
)
492 __real_pthread_join
= __real_pthread_join_2_0
;
494 __real_pthread_join
= dlsym (dlflag
, "pthread_join");
495 if (__real_pthread_join
== NULL
)
497 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
498 err
= COL_ERROR_SYNCINIT
;
501 __real_sem_wait_2_34
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.34");
502 __real_sem_wait_2_17
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.17");
503 __real_sem_wait_2_2_5
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.2.5");
504 __real_sem_wait_2_1
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.1");
505 __real_sem_wait_2_0
= dlvsym (dlflag
, "sem_wait", "GLIBC_2.0");
506 if (__real_sem_wait_2_34
)
507 __real_sem_wait
= __real_sem_wait_2_34
;
508 else if (__real_sem_wait_2_17
)
509 __real_sem_wait
= __real_sem_wait_2_17
;
510 else if (__real_sem_wait_2_2_5
)
511 __real_sem_wait
= __real_sem_wait_2_2_5
;
512 else if (__real_sem_wait_2_1
)
513 __real_sem_wait
= __real_sem_wait_2_1
;
514 else if (__real_sem_wait_2_0
)
515 __real_sem_wait
= __real_sem_wait_2_0
;
517 __real_sem_wait
= dlsym (dlflag
, "sem_wait");
518 if (__real_sem_wait
== NULL
)
520 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
521 err
= COL_ERROR_SYNCINIT
;
525 ptr
= dlsym (dlflag
, "strtol");
527 __real_strtol
= (void *) ptr
;
530 CALL_REAL (fprintf
)(stderr
, "synctrace_init COL_ERROR_SYNCINIT strtol\n");
531 err
= COL_ERROR_SYNCINIT
;
533 init_thread_intf_finished
++;
534 TprintfT (0, "synctrace init_thread_intf complete\n");
538 /* These next two routines are used from jprofile to record Java synctrace data */
540 __collector_jsync_begin ()
543 if (CHCK_JREENTRANCE (guard
))
545 Tprintf (DBG_LT1
, "__collector_jsync_begin: skipped\n");
548 Tprintf (DBG_LT1
, "__collector_jsync_begin: start event\n");
549 PUSH_REENTRANCE (guard
);
553 __collector_jsync_end (hrtime_t reqt
, void *object
)
556 if (RECHCK_JREENTRANCE (guard
))
558 Tprintf (DBG_LT1
, "__collector_jsync_end: skipped\n");
561 hrtime_t grnt
= gethrtime ();
562 if (grnt
- reqt
>= sync_threshold
)
565 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
566 spacket
.comm
.tsize
= sizeof (Sync_packet
);
567 spacket
.comm
.tstamp
= grnt
;
568 spacket
.requested
= reqt
;
569 spacket
.objp
= (intptr_t) object
;
570 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
571 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
572 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
574 Tprintf (DBG_LT1
, "__collector_jsync_begin: end event\n");
575 POP_REENTRANCE (guard
);
577 /*-------------------------------------------------------- pthread_mutex_lock */
579 gprofng_pthread_mutex_lock (int (real_func
) (pthread_mutex_t
*),
583 if (CHCK_NREENTRANCE (guard
))
584 return (real_func
) (mp
);
585 PUSH_REENTRANCE (guard
);
586 hrtime_t reqt
= gethrtime ();
587 int ret
= (real_func
) (mp
);
588 if (RECHCK_NREENTRANCE (guard
))
590 POP_REENTRANCE (guard
);
593 hrtime_t grnt
= gethrtime ();
594 if (grnt
- reqt
>= sync_threshold
)
597 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
598 spacket
.comm
.tsize
= sizeof (Sync_packet
);
599 spacket
.comm
.tstamp
= grnt
;
600 spacket
.requested
= reqt
;
601 spacket
.objp
= (intptr_t) mp
;
602 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
603 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
604 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
606 POP_REENTRANCE (guard
);
610 #define DCL_PTHREAD_MUTEX_LOCK(dcl_f) \
611 int dcl_f (pthread_mutex_t *mp) \
613 if (__real_pthread_mutex_lock == NULL) \
614 init_thread_intf (); \
615 return gprofng_pthread_mutex_lock (__real_pthread_mutex_lock, mp); \
618 DCL_FUNC_VER (DCL_PTHREAD_MUTEX_LOCK
, pthread_mutex_lock_2_17
, pthread_mutex_lock@GLIBC_2
.17
)
619 DCL_FUNC_VER (DCL_PTHREAD_MUTEX_LOCK
, pthread_mutex_lock_2_2_5
, pthread_mutex_lock@GLIBC_2
.2
.5)
620 DCL_FUNC_VER (DCL_PTHREAD_MUTEX_LOCK
, pthread_mutex_lock_2_0
, pthread_mutex_lock@GLIBC_2
.0
)
621 DCL_PTHREAD_MUTEX_LOCK (pthread_mutex_lock
)
623 /*------------------------------------------------------------- pthread_cond_wait */
625 gprofng_pthread_cond_wait (int(real_func
) (pthread_cond_t
*, pthread_mutex_t
*),
626 pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
629 if (CHCK_NREENTRANCE (guard
))
630 return (real_func
) (cond
, mutex
);
631 PUSH_REENTRANCE (guard
);
632 hrtime_t reqt
= gethrtime ();
634 ret
= (real_func
) (cond
, mutex
);
635 if (RECHCK_NREENTRANCE (guard
))
637 POP_REENTRANCE (guard
);
640 hrtime_t grnt
= gethrtime ();
641 if (grnt
- reqt
>= sync_threshold
)
644 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
645 spacket
.comm
.tsize
= sizeof (Sync_packet
);
646 spacket
.comm
.tstamp
= grnt
;
647 spacket
.requested
= reqt
;
648 spacket
.objp
= (intptr_t) mutex
;
649 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
650 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
651 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
653 POP_REENTRANCE (guard
);
657 #define DCL_PTHREAD_COND_WAIT(dcl_f) \
658 int dcl_f (pthread_cond_t *cond, pthread_mutex_t *mutex) \
660 if (__real_pthread_cond_wait == NULL) \
661 init_thread_intf (); \
662 return gprofng_pthread_cond_wait (__real_pthread_cond_wait, cond, mutex); \
665 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT
, pthread_cond_wait_2_17
, pthread_cond_wait@GLIBC_2
.17
)
666 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT
, pthread_cond_wait_2_3_2
, pthread_cond_wait@GLIBC_2
.3
.2)
667 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT
, pthread_cond_wait_2_2_5
, pthread_cond_wait@GLIBC_2
.2
.5)
668 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT
, pthread_cond_wait_2_0
, pthread_cond_wait@GLIBC_2
.0
)
669 DCL_PTHREAD_COND_WAIT (pthread_cond_wait
)
671 /*---------------------------------------------------- pthread_cond_timedwait */
673 gprofng_pthread_cond_timedwait (int(real_func
) (pthread_cond_t
*,
674 pthread_mutex_t
*, const struct timespec
*),
675 pthread_cond_t
*cond
, pthread_mutex_t
*mutex
,
676 const struct timespec
*abstime
)
679 if (CHCK_NREENTRANCE (guard
))
680 return (real_func
) (cond
, mutex
, abstime
);
681 PUSH_REENTRANCE (guard
);
682 hrtime_t reqt
= gethrtime ();
684 ret
= (real_func
) (cond
, mutex
, abstime
);
685 if (RECHCK_NREENTRANCE (guard
))
687 POP_REENTRANCE (guard
);
690 hrtime_t grnt
= gethrtime ();
691 if (grnt
- reqt
>= sync_threshold
)
694 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
695 spacket
.comm
.tsize
= sizeof (Sync_packet
);
696 spacket
.comm
.tstamp
= grnt
;
697 spacket
.requested
= reqt
;
698 spacket
.objp
= (intptr_t) mutex
;
699 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
700 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
701 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
703 POP_REENTRANCE (guard
);
707 #define DCL_PTHREAD_COND_TIMEDWAIT(dcl_f) \
708 int dcl_f (pthread_cond_t *cond, pthread_mutex_t *mutex, \
709 const struct timespec *abstime) \
711 if (__real_pthread_cond_timedwait == NULL) \
712 init_thread_intf (); \
713 return gprofng_pthread_cond_timedwait (__real_pthread_cond_timedwait, cond, mutex, abstime); \
716 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT
, pthread_cond_timedwait_2_17
, pthread_cond_timedwait@GLIBC_2
.17
)
717 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT
, pthread_cond_timedwait_2_3_2
, pthread_cond_timedwait@GLIBC_2
.3
.2)
718 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT
, pthread_cond_timedwait_2_2_5
, pthread_cond_timedwait@GLIBC_2
.2
.5)
719 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT
, pthread_cond_timedwait_2_0
, pthread_cond_timedwait@GLIBC_2
.0
)
720 DCL_PTHREAD_COND_TIMEDWAIT (pthread_cond_timedwait
)
723 /*------------------------------------------------------------- pthread_join */
725 gprofng_pthread_join (int(real_func
) (pthread_t
, void **),
726 pthread_t target_thread
, void **status
)
729 if (CHCK_NREENTRANCE (guard
))
730 return real_func (target_thread
, status
);
731 PUSH_REENTRANCE (guard
);
732 hrtime_t reqt
= gethrtime ();
733 int ret
= real_func(target_thread
, status
);
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
= (Vaddr_type
) target_thread
;
748 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
749 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
750 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
752 POP_REENTRANCE (guard
);
756 #define DCL_PTHREAD_JOIN(dcl_f) \
757 int dcl_f (pthread_t target_thread, void **status) \
759 if (__real_pthread_join == NULL) \
760 init_thread_intf (); \
761 return gprofng_pthread_join (__real_pthread_join, target_thread, status); \
764 DCL_FUNC_VER (DCL_PTHREAD_JOIN
, pthread_join_2_34
, pthread_join@GLIBC_2
.34
)
765 DCL_FUNC_VER (DCL_PTHREAD_JOIN
, pthread_join_2_17
, pthread_join@GLIBC_2
.17
)
766 DCL_FUNC_VER (DCL_PTHREAD_JOIN
, pthread_join_2_2_5
, pthread_join@GLIBC_2
.2
.5)
767 DCL_FUNC_VER (DCL_PTHREAD_JOIN
, pthread_join_2_0
, pthread_join@GLIBC_2
.0
)
768 DCL_PTHREAD_JOIN (pthread_join
)
770 /*------------------------------------------------------------- sem_wait */
772 gprofng_sem_wait (int (real_func
) (sem_t
*), sem_t
*sp
)
775 if (CHCK_NREENTRANCE (guard
))
776 return real_func (sp
);
777 PUSH_REENTRANCE (guard
);
778 hrtime_t reqt
= gethrtime ();
780 ret
= real_func (sp
);
781 if (RECHCK_NREENTRANCE (guard
))
783 POP_REENTRANCE (guard
);
786 hrtime_t grnt
= gethrtime ();
787 if (grnt
- reqt
>= sync_threshold
)
790 collector_memset (&spacket
, 0, sizeof (Sync_packet
));
791 spacket
.comm
.tsize
= sizeof (Sync_packet
);
792 spacket
.comm
.tstamp
= grnt
;
793 spacket
.requested
= reqt
;
794 spacket
.objp
= (intptr_t) sp
;
795 spacket
.comm
.frinfo
= collector_interface
->getFrameInfo (sync_hndl
,
796 spacket
.comm
.tstamp
, FRINFO_FROM_STACK_ARG
, &spacket
);
797 collector_interface
->writeDataRecord (sync_hndl
, (Common_packet
*) &spacket
);
799 POP_REENTRANCE (guard
);
803 #define DCL_SEM_WAIT(dcl_f) \
804 int dcl_f (sem_t *sp) \
806 if (__real_sem_wait == NULL) \
807 init_thread_intf (); \
808 return gprofng_sem_wait (__real_sem_wait, sp); \
811 DCL_FUNC_VER (DCL_SEM_WAIT
, sem_wait_2_34
, sem_wait@GLIBC_2
.34
)
812 DCL_FUNC_VER (DCL_SEM_WAIT
, sem_wait_2_17
, sem_wait@GLIBC_2
.17
)
813 DCL_FUNC_VER (DCL_SEM_WAIT
, sem_wait_2_2_5
, sem_wait@GLIBC_2
.2
.5)
814 DCL_FUNC_VER (DCL_SEM_WAIT
, sem_wait_2_0
, sem_wait@GLIBC_2
.0
)
815 DCL_FUNC_VER (DCL_SEM_WAIT
, sem_wait_2_1
, sem_wait@GLIBC_2
.1
)
816 DCL_SEM_WAIT (sem_wait
)