gprofng: adjust GPROFNG_VARIANT
[binutils-gdb.git] / gprofng / libcollector / synctrace.c
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2 Contributed by Oracle.
3
4 This file is part of GNU Binutils.
5
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)
9 any later version.
10
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.
15
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. */
20
21 /*
22 * Synchronization events
23 */
24 #include "config.h"
25 #include <alloca.h>
26 #include <dlfcn.h>
27 #include <unistd.h>
28 #include <semaphore.h> /* sem_wait() */
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/param.h>
32 #include <pthread.h>
33
34 #include "gp-defs.h"
35 #include "collector_module.h"
36 #include "gp-experiment.h"
37 #include "data_pckts.h"
38 #include "i18n.h"
39 #include "tsd.h"
40 #include "cc_libcollector.h"
41
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
46 #define DBG_LT2 2
47 #define DBG_LT3 3
48
49 /* define the packet that will be written out */
50 typedef struct Sync_packet
51 { /* Synchronization delay tracing packet */
52 Common_packet comm;
53 hrtime_t requested; /* time of synchronization request */
54 Vaddr_type objp; /* vaddr of synchronization object */
55 } Sync_packet;
56
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 ();
64
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) */
73 };
74
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;
85
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))--)
92
93 #define CALL_REAL(x) (*(int(*)())__real_##x)
94 #define NULL_PTR(x) ( __real_##x == NULL )
95 #define gethrtime collector_interface->getHiResTime
96
97 #ifdef DEBUG
98 #define Tprintf(...) if (collector_interface) collector_interface->writeDebugInfo( 0, __VA_ARGS__ )
99 #define TprintfT(...) if (collector_interface) collector_interface->writeDebugInfo( 1, __VA_ARGS__ )
100 #else
101 #define Tprintf(...)
102 #define TprintfT(...)
103 #endif
104
105 /*
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().
112 */
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;
124
125 #if WSIZE(32)
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;
130 #elif WSIZE(64)
131 #if ARCH(Intel)
132 static void *__real_pthread_cond_wait_2_2_5 = NULL;
133 static void *__real_pthread_cond_timedwait_2_2_5 = NULL;
134 #elif ARCH(SPARC)
135 static void *__real_pthread_cond_wait_2_2 = NULL;
136 static void *__real_pthread_cond_timedwait_2_2 = NULL;
137 #endif /* ARCH() */
138 #endif /* WSIZE() */
139
140 static void
141 collector_memset (void *s, int c, size_t n)
142 {
143 unsigned char *s1 = s;
144 while (n--)
145 *s1++ = (unsigned char) c;
146 }
147
148 void
149 __collector_module_init (CollectorInterface *_collector_interface)
150 {
151 if (_collector_interface == NULL)
152 return;
153 collector_interface = _collector_interface;
154 TprintfT (0, "synctrace: __collector_module_init\n");
155 sync_hndl = collector_interface->registerModule (&module_interface);
156
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);
161 }
162
163 static int
164 open_experiment (const char *exp)
165 {
166 long thresh = 0;
167 if (init_thread_intf_finished == 0)
168 init_thread_intf ();
169 if (collector_interface == NULL)
170 {
171 Tprintf (0, "synctrace: collector_interface is null.\n");
172 return COL_ERROR_SYNCINIT;
173 }
174 if (sync_hndl == COLLECTOR_MODULE_ERR)
175 {
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;
180 }
181 TprintfT (0, "synctrace: open_experiment %s\n", exp);
182
183 char *params = (char *) collector_interface->getParams ();
184 while (params)
185 {
186 if ((params[0] == 's') && (params[1] == ':'))
187 {
188 char *ptr = params + 2;
189 Tprintf (DBG_LT1, "synctrace: open_experiment s: parameter = %s\n", ptr);
190 while (*ptr != ',' && *ptr != ';')
191 ptr++;
192 sync_scope = 0;
193 if (*ptr == ',')
194 {
195 sync_scope = CALL_REAL (strtol) (ptr + 1, NULL, 0);
196 switch (sync_scope)
197 {
198 case 1:
199 sync_java = 0;
200 sync_native = 1;
201 break;
202 case 2:
203 sync_java = 1;
204 sync_native = 0;
205 break;
206 default:
207 case 3:
208 sync_native = 1;
209 sync_java = 1;
210 break;
211 }
212 Tprintf (0, "\tsynctrace: sync_scope found as %ld\n", sync_scope);
213 }
214 else
215 {
216 /* the old-style descriptor, without scope */
217 /* if there was no comma, use the old default */
218 sync_scope = 3;
219 sync_java = 1;
220 sync_native = 1;
221 Tprintf (0, "\tsynctrace: sync_scope not found set to %ld\n", sync_scope);
222 }
223 if (__real___collector_jprofile_enable_synctrace == NULL)
224 sync_java = 0;
225 thresh = CALL_REAL (strtol)(params + 2, NULL, 0);
226 break; /* from the loop to find the "s:thresh,scope" entry */
227 }
228 else
229 params++;
230 }
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 ();
235
236 sync_key = collector_interface->createKey (sizeof ( int), NULL, NULL);
237 if (sync_key == (unsigned) - 1)
238 {
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;
243 }
244 /* if Java synctrace was requested, tell the jprofile module */
245 if (sync_java)
246 {
247 TprintfT (0, "synctrace: enabling Java synctrace\n");
248 CALL_REAL (__collector_jprofile_enable_synctrace)();
249 }
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");
273
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;
278 }
279
280 static int
281 start_data_collection (void)
282 {
283 sync_mode = 1;
284 TprintfT (0, "synctrace: start_data_collection\n");
285 return 0;
286 }
287
288 static int
289 stop_data_collection (void)
290 {
291 sync_mode = 0;
292 TprintfT (0, "synctrace: stop_data_collection\n");
293 return 0;
294 }
295
296 static int
297 close_experiment (void)
298 {
299 sync_mode = 0;
300 sync_threshold = -1;
301 sync_key = COLLECTOR_TSD_INVALID_KEY;
302 TprintfT (0, "synctrace: close_experiment\n");
303 return 0;
304 }
305
306 /* fork child. Clean up state but don't write to experiment */
307 static int
308 detach_experiment (void)
309 {
310 sync_mode = 0;
311 sync_threshold = -1;
312 sync_key = COLLECTOR_TSD_INVALID_KEY;
313 TprintfT (0, "synctrace: detach_experiment\n");
314 return 0;
315 }
316
317 #define NUM_ITER 100 /* number of iterations in calibration */
318 #define NUM_WARMUP 3 /* number of warm up iterations */
319
320 static int
321 sync_calibrate ()
322 {
323 pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER;
324 hrtime_t bt, at, delta;
325 hrtime_t avg, max, min;
326 int i;
327 int ret;
328 avg = (hrtime_t) 0;
329 min = max = (hrtime_t) 0;
330 for (i = 0; i < NUM_ITER + NUM_WARMUP; i++)
331 {
332 /* Here we simulate a real call */
333 bt = gethrtime ();
334 ret = CALL_REAL (pthread_mutex_lock)(&mt);
335 at = gethrtime ();
336 CALL_REAL (pthread_mutex_unlock)(&mt);
337 if (i < NUM_WARMUP) /* skip these iterations */
338 continue;
339 /* add the time of this one */
340 delta = at - bt;
341 avg += delta;
342 if (min == 0)
343 min = delta;
344 if (delta < min)
345 min = delta;
346 if (delta > max)
347 max = delta;
348 }
349 /* compute average time */
350 avg = avg / NUM_ITER;
351
352 /* pretty simple, let's see how it works */
353 if (max < 6 * avg)
354 max = 6 * avg;
355 /* round up to the nearest microsecond */
356 ret = (int) ((max + 999) / 1000);
357 return ret;
358 }
359
360 static int
361 init_thread_intf ()
362 {
363 void *dlflag = RTLD_NEXT;
364 int err = 0;
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)
368 {
369 /* pull the plug if recursion occurs... */
370 abort ();
371 }
372 /* lookup fprint to print fatal error message */
373 void *ptr = dlsym (RTLD_DEFAULT, "fprintf");
374 if (ptr)
375 {
376 __real_fprintf = (void *) ptr;
377 }
378 else
379 {
380 abort ();
381 }
382
383 /* find the __collector_jprofile_enable_synctrace routine in jprofile module */
384 ptr = dlsym (RTLD_DEFAULT, "__collector_jprofile_enable_synctrace");
385 if (ptr)
386 __real___collector_jprofile_enable_synctrace = (void *) ptr;
387 else
388 {
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;
392 #endif
393 sync_java = 0;
394 }
395
396 #if WSIZE(32)
397 /* ########################################## begin WSIZE(32) */
398 /* IMPORTANT!! The GLIBC_* versions below must match those in the er_sync.*.mapfile ! */
399 dlflag = RTLD_NEXT;
400 ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.0");
401 if (ptr == NULL)
402 {
403 /* We are probably dlopened after libthread/libc,
404 * try to search in the previously loaded objects
405 */
406 dlflag = RTLD_DEFAULT;
407 ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.0");
408 if (ptr != NULL)
409 {
410 __real_pthread_mutex_lock = ptr;
411 Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for OS sync routines\n");
412 }
413 else
414 {
415 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
416 err = COL_ERROR_SYNCINIT;
417 }
418 }
419 else
420 __real_pthread_mutex_lock = ptr;
421
422 ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.0");
423 if (ptr)
424 __real_pthread_mutex_unlock = (void *) ptr;
425 else
426 {
427 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
428 err = COL_ERROR_SYNCINIT;
429 }
430 ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.3.2");
431 if (ptr)
432 __real_pthread_cond_wait = (void *) ptr;
433 else
434 {
435 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
436 err = COL_ERROR_SYNCINIT;
437 }
438 ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.3.2");
439 if (ptr)
440 __real_pthread_cond_timedwait = (void *) ptr;
441 else
442 {
443 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
444 err = COL_ERROR_SYNCINIT;
445 }
446 ptr = dlvsym (dlflag, "pthread_join", "GLIBC_2.0");
447 if (ptr)
448 __real_pthread_join = (void *) ptr;
449 else
450 {
451 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
452 err = COL_ERROR_SYNCINIT;
453 }
454 ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.1");
455 if (ptr)
456 __real_sem_wait = (void *) ptr;
457 else
458 {
459 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
460 err = COL_ERROR_SYNCINIT;
461 }
462
463 #if ARCH(Intel)
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");
467 if (ptr)
468 __real_sem_wait_2_0 = (void *) ptr;
469 else
470 {
471 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait_2_0\n");
472 err = COL_ERROR_SYNCINIT;
473 }
474 ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.0");
475 if (ptr)
476 __real_pthread_cond_wait_2_0 = (void *) ptr;
477 else
478 {
479 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_0\n");
480 err = COL_ERROR_SYNCINIT;
481 }
482 ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.0");
483 if (ptr)
484 __real_pthread_cond_timedwait_2_0 = (void *) ptr;
485 else
486 {
487 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT __real_pthread_cond_timedwait_2_0\n");
488 err = COL_ERROR_SYNCINIT;
489 }
490 #endif /* ARCH(Intel) */
491
492 #else /* WSIZE(64) */
493 /* # most versions are different between platforms */
494 /* # the few that are common are set after the ARCH ifdef */
495 #if ARCH(Aarch64)
496 dlflag = RTLD_NEXT;
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);
504
505 #elif ARCH(Intel)
506 dlflag = RTLD_NEXT;
507 ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2.5");
508 if (ptr == NULL)
509 {
510 /* We are probably dlopened after libthread/libc,
511 * try to search in the previously loaded objects
512 */
513 dlflag = RTLD_DEFAULT;
514 ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2.5");
515 if (ptr != NULL)
516 {
517 __real_pthread_mutex_lock = ptr;
518 Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for Solaris sync routines\n");
519 }
520 else
521 {
522 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
523 err = COL_ERROR_SYNCINIT;
524 }
525 }
526 else
527 __real_pthread_mutex_lock = ptr;
528 ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.2.5");
529 if (ptr)
530 __real_pthread_mutex_unlock = (void *) ptr;
531 else
532 {
533 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
534 err = COL_ERROR_SYNCINIT;
535 }
536 ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.3.2");
537 if (ptr)
538 __real_pthread_cond_wait = (void *) ptr;
539 else
540 {
541 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
542 err = COL_ERROR_SYNCINIT;
543 }
544 ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.3.2");
545 if (ptr)
546 __real_pthread_cond_timedwait = (void *) ptr;
547 else
548 {
549 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
550 err = COL_ERROR_SYNCINIT;
551 }
552 ptr = dlvsym (dlflag, "pthread_join", "GLIBC_2.2.5");
553 if (ptr)
554 __real_pthread_join = (void *) ptr;
555 else
556 {
557 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
558 err = COL_ERROR_SYNCINIT;
559 }
560 ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.2.5");
561 if (ptr)
562 __real_sem_wait = (void *) ptr;
563 else
564 {
565 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
566 err = COL_ERROR_SYNCINIT;
567 }
568 ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.2.5");
569 if (ptr)
570 __real_pthread_cond_wait_2_2_5 = (void *) ptr;
571 else
572 {
573 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_2_5\n");
574 err = COL_ERROR_SYNCINIT;
575 }
576 ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.2.5");
577 if (ptr)
578 __real_pthread_cond_timedwait_2_2_5 = (void *) ptr;
579 else
580 {
581 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait_2_2_5\n");
582 err = COL_ERROR_SYNCINIT;
583 }
584
585 #elif ARCH(SPARC)
586 dlflag = RTLD_NEXT;
587 ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2");
588 if (ptr == NULL)
589 {
590 /* We are probably dlopened after libthread/libc,
591 * try to search in the previously loaded objects
592 */
593 dlflag = RTLD_DEFAULT;
594 ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2");
595 if (ptr != NULL)
596 {
597 __real_pthread_mutex_lock = ptr;
598 Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for Solaris sync routines\n");
599 }
600 else
601 {
602 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT mutex_lock\n");
603 err = COL_ERROR_SYNCINIT;
604 }
605 }
606 else
607 __real_pthread_mutex_lock = ptr;
608 ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.2");
609 if (ptr)
610 __real_pthread_mutex_unlock = (void *) ptr;
611 else
612 {
613 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
614 err = COL_ERROR_SYNCINIT;
615 }
616 ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.3.2");
617 if (ptr)
618 __real_pthread_cond_wait = (void *) ptr;
619 else
620 {
621 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
622 err = COL_ERROR_SYNCINIT;
623 }
624 ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.3.2");
625 if (ptr)
626 __real_pthread_cond_timedwait = (void *) ptr;
627 else
628 {
629 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
630 err = COL_ERROR_SYNCINIT;
631 }
632 ptr = dlvsym (dlflag, "pthread_join", "GLIBC_2.2");
633 if (ptr)
634 __real_pthread_join = (void *) ptr;
635 else
636 {
637 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
638 err = COL_ERROR_SYNCINIT;
639 }
640 ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.2");
641 if (ptr)
642 __real_sem_wait = (void *) ptr;
643 else
644 {
645 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
646 err = COL_ERROR_SYNCINIT;
647 }
648 ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.2");
649 if (ptr)
650 __real_pthread_cond_wait_2_2 = (void *) ptr;
651 else
652 {
653 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_2_5\n");
654 err = COL_ERROR_SYNCINIT;
655 }
656 ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.2");
657 if (ptr)
658 __real_pthread_cond_timedwait_2_2 = (void *) ptr;
659 else
660 {
661 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait_2_2\n");
662 err = COL_ERROR_SYNCINIT;
663 }
664 #endif /* ARCH() */
665 #endif /* WSIZE(64) */
666 /* the pointers that are common to 32- and 64-bits, and to SPARC and Intel */
667
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");
671 if (ptr)
672 __real_strtol = (void *) ptr;
673 else
674 {
675 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT strtol\n");
676 err = COL_ERROR_SYNCINIT;
677 }
678 init_thread_intf_finished++;
679 TprintfT (0, "synctrace init_thread_intf complete\n");
680 return err;
681 }
682
683 /* These next two routines are used from jprofile to record Java synctrace data */
684 void
685 __collector_jsync_begin ()
686 {
687 int *guard;
688 if (CHCK_JREENTRANCE (guard))
689 {
690 Tprintf (DBG_LT1, "__collector_jsync_begin: skipped\n");
691 return;
692 }
693 Tprintf (DBG_LT1, "__collector_jsync_begin: start event\n");
694 PUSH_REENTRANCE (guard);
695 }
696
697 void
698 __collector_jsync_end (hrtime_t reqt, void *object)
699 {
700 int *guard;
701 if (RECHCK_JREENTRANCE (guard))
702 {
703 Tprintf (DBG_LT1, "__collector_jsync_end: skipped\n");
704 return;
705 }
706 hrtime_t grnt = gethrtime ();
707 if (grnt - reqt >= sync_threshold)
708 {
709 Sync_packet spacket;
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);
717 }
718 Tprintf (DBG_LT1, "__collector_jsync_begin: end event\n");
719 POP_REENTRANCE (guard);
720 }
721
722 /*-------------------------------------------------------- pthread_mutex_lock */
723 int
724 pthread_mutex_lock (pthread_mutex_t *mp)
725 {
726 int *guard;
727 if (NULL_PTR (pthread_mutex_lock))
728 init_thread_intf ();
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))
735 {
736 POP_REENTRANCE (guard);
737 return ret;
738 }
739 hrtime_t grnt = gethrtime ();
740 if (grnt - reqt >= sync_threshold)
741 {
742 Sync_packet spacket;
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);
750 }
751 POP_REENTRANCE (guard);
752 return ret;
753 }
754
755
756 /*------------------------------------------------------------- pthread_cond_wait */
757 // map interposed symbol versions
758 static int
759 __collector_pthread_cond_wait_symver (int(real_pthread_cond_wait) (), pthread_cond_t *cond, pthread_mutex_t *mutex);
760
761 #if ARCH(Intel) || ARCH(SPARC)
762 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_3_2,
763 pthread_cond_wait@@GLIBC_2.3.2)
764 #endif
765 int
766 __collector_pthread_cond_wait_2_3_2 (pthread_cond_t *cond, pthread_mutex_t *mutex)
767 {
768 if (NULL_PTR (pthread_cond_wait))
769 init_thread_intf ();
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);
772 }
773
774 #if WSIZE(32)
775
776 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_0,
777 pthread_cond_wait@GLIBC_2.0)
778 int
779 __collector_pthread_cond_wait_2_0 (pthread_cond_t *cond, pthread_mutex_t *mutex)
780 {
781 if (NULL_PTR (pthread_cond_wait))
782 init_thread_intf ();
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);
785 }
786 #else // WSIZE(64)
787 #if ARCH(Intel)
788 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2_5,
789 pthread_cond_wait@GLIBC_2.2.5)
790 int
791 __collector_pthread_cond_wait_2_2_5 (pthread_cond_t *cond, pthread_mutex_t *mutex)
792 {
793 if (NULL_PTR (pthread_cond_wait))
794 init_thread_intf ();
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);
797 }
798 #elif ARCH(SPARC)
799
800 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2,
801 pthread_cond_wait@GLIBC_2.2)
802 int
803 __collector_pthread_cond_wait_2_2 (pthread_cond_t *cond, pthread_mutex_t *mutex)
804 {
805 if (NULL_PTR (pthread_cond_wait))
806 init_thread_intf ();
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);
809 }
810 #endif // ARCH()
811 #endif // WSIZE()
812
813 static int
814 __collector_pthread_cond_wait_symver (int(real_pthread_cond_wait) (), pthread_cond_t *cond, pthread_mutex_t *mutex)
815 {
816 int *guard;
817 if (NULL_PTR (pthread_cond_wait))
818 init_thread_intf ();
819 if (CHCK_NREENTRANCE (guard))
820 return (real_pthread_cond_wait) (cond, mutex);
821 PUSH_REENTRANCE (guard);
822 hrtime_t reqt = gethrtime ();
823 int ret = -1;
824 ret = (real_pthread_cond_wait) (cond, mutex);
825 if (RECHCK_NREENTRANCE (guard))
826 {
827 POP_REENTRANCE (guard);
828 return ret;
829 }
830 hrtime_t grnt = gethrtime ();
831 if (grnt - reqt >= sync_threshold)
832 {
833 Sync_packet spacket;
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);
841 }
842 POP_REENTRANCE (guard);
843 return ret;
844 }
845
846 /*---------------------------------------------------- pthread_cond_timedwait */
847 // map interposed symbol versions
848 static int
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);
853
854 #if ARCH(Intel) || ARCH(SPARC)
855 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_3_2,
856 pthread_cond_timedwait@@GLIBC_2.3.2)
857 #endif // ARCH()
858 int
859 __collector_pthread_cond_timedwait_2_3_2 (pthread_cond_t *cond,
860 pthread_mutex_t *mutex,
861 const struct timespec *abstime)
862 {
863 if (NULL_PTR (pthread_cond_timedwait))
864 init_thread_intf ();
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);
867 }
868
869 #if WSIZE(32)
870 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_0,
871 pthread_cond_timedwait@GLIBC_2.0)
872 int
873 __collector_pthread_cond_timedwait_2_0 (pthread_cond_t *cond,
874 pthread_mutex_t *mutex,
875 const struct timespec *abstime)
876 {
877 if (NULL_PTR (pthread_cond_timedwait))
878 init_thread_intf ();
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);
881 }
882 #else // WSIZE(64)
883 #if ARCH(Intel)
884 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2_5,
885 pthread_cond_timedwait@GLIBC_2.2.5)
886 int
887 __collector_pthread_cond_timedwait_2_2_5 (pthread_cond_t *cond,
888 pthread_mutex_t *mutex,
889 const struct timespec *abstime)
890 {
891 if (NULL_PTR (pthread_cond_timedwait))
892 init_thread_intf ();
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);
895 }
896 #elif ARCH(SPARC)
897
898 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2,
899 pthread_cond_timedwait@GLIBC_2.2)
900 int
901 __collector_pthread_cond_timedwait_2_2 (pthread_cond_t *cond,
902 pthread_mutex_t *mutex,
903 const struct timespec *abstime)
904 {
905 if (NULL_PTR (pthread_cond_timedwait))
906 init_thread_intf ();
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);
909 }
910 #endif // ARCH()
911 #endif // WSIZE()
912
913 static int
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)
918 {
919 int *guard;
920 if (NULL_PTR (pthread_cond_timedwait))
921 init_thread_intf ();
922 if (CHCK_NREENTRANCE (guard))
923 return (real_pthread_cond_timedwait) (cond, mutex, abstime);
924 PUSH_REENTRANCE (guard);
925 hrtime_t reqt = gethrtime ();
926 int ret = -1;
927 ret = (real_pthread_cond_timedwait) (cond, mutex, abstime);
928 if (RECHCK_NREENTRANCE (guard))
929 {
930 POP_REENTRANCE (guard);
931 return ret;
932 }
933 hrtime_t grnt = gethrtime ();
934 if (grnt - reqt >= sync_threshold)
935 {
936 Sync_packet spacket;
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);
944 }
945 POP_REENTRANCE (guard);
946 return ret;
947 }
948
949 /*------------------------------------------------------------- pthread_join */
950 int
951 pthread_join (pthread_t target_thread, void **status)
952 {
953 int *guard;
954 if (NULL_PTR (pthread_join))
955 init_thread_intf ();
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))
962 {
963 POP_REENTRANCE (guard);
964 return ret;
965 }
966 hrtime_t grnt = gethrtime ();
967 if (grnt - reqt >= sync_threshold)
968 {
969 Sync_packet spacket;
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);
977 }
978 POP_REENTRANCE (guard);
979 return ret;
980 }
981
982 /*------------------------------------------------------------- sem_wait */
983 // map interposed symbol versions
984 #if ARCH(Intel) && WSIZE(32)
985 static int
986 __collector_sem_wait_symver (int(real_sem_wait) (), sem_t *sp);
987
988 SYMVER_ATTRIBUTE (__collector_sem_wait_2_1, sem_wait@@GLIBC_2.1)
989 int
990 __collector_sem_wait_2_1 (sem_t *sp)
991 {
992 if (NULL_PTR (sem_wait))
993 init_thread_intf ();
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);
996 }
997
998 SYMVER_ATTRIBUTE (__collector_sem_wait_2_0, sem_wait@GLIBC_2.0)
999 int
1000 __collector_sem_wait_2_0 (sem_t *sp)
1001 {
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);
1006 }
1007 #endif
1008
1009 #if ARCH(Intel) && WSIZE(32)
1010 static int
1011 __collector_sem_wait_symver (int(real_sem_wait) (), sem_t *sp)
1012 {
1013 #else
1014 int
1015 sem_wait (sem_t *sp)
1016 {
1017 #endif
1018 int *guard;
1019 if (NULL_PTR (sem_wait))
1020 init_thread_intf ();
1021 if (CHCK_NREENTRANCE (guard))
1022 {
1023 #if ARCH(Intel) && WSIZE(32)
1024 return (real_sem_wait) (sp);
1025 #else
1026 return CALL_REAL (sem_wait)(sp);
1027 #endif
1028 }
1029 PUSH_REENTRANCE (guard);
1030 hrtime_t reqt = gethrtime ();
1031 int ret = -1;
1032 #if ARCH(Intel) && WSIZE(32)
1033 ret = (real_sem_wait) (sp);
1034 #else
1035 ret = CALL_REAL (sem_wait)(sp);
1036 #endif
1037 if (RECHCK_NREENTRANCE (guard))
1038 {
1039 POP_REENTRANCE (guard);
1040 return ret;
1041 }
1042 hrtime_t grnt = gethrtime ();
1043 if (grnt - reqt >= sync_threshold)
1044 {
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;
1051
1052 #if ARCH(Intel) && WSIZE(32)
1053 spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
1054 #else
1055 spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK, &spacket);
1056 #endif
1057 collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
1058 }
1059 POP_REENTRANCE (guard);
1060 return ret;
1061 }