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