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);