Remove path name from test case
[binutils-gdb.git] / gprofng / libcollector / synctrace.c
1 /* Copyright (C) 2021-2023 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 <stddef.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/param.h>
33 #include <pthread.h>
34
35 #include "gp-defs.h"
36 #include "collector.h"
37 #include "gp-experiment.h"
38 #include "data_pckts.h"
39 #include "tsd.h"
40 #include "cc_libcollector.h"
41
42 /* define the packet that will be written out */
43 typedef struct Sync_packet
44 { /* Synchronization delay tracing packet */
45 Common_packet comm;
46 hrtime_t requested; /* time of synchronization request */
47 Vaddr_type objp; /* vaddr of synchronization object */
48 } Sync_packet;
49
50 static int open_experiment (const char *);
51 static int start_data_collection (void);
52 static int stop_data_collection (void);
53 static int close_experiment (void);
54 static int detach_experiment (void);
55 static int init_thread_intf ();
56 static int sync_calibrate ();
57
58 static ModuleInterface module_interface ={
59 SP_SYNCTRACE_FILE, /* description */
60 NULL, /* initInterface */
61 open_experiment, /* openExperiment */
62 start_data_collection, /* startDataCollection */
63 stop_data_collection, /* stopDataCollection */
64 close_experiment, /* closeExperiment */
65 detach_experiment /* detachExperiment (fork child) */
66 };
67
68 static CollectorInterface *collector_interface = NULL;
69 static int sync_mode = 0;
70 static long sync_scope = 0;
71 static int sync_native = 0;
72 static int sync_java = 0;
73 static CollectorModule sync_hndl = COLLECTOR_MODULE_ERR;
74 static unsigned sync_key = COLLECTOR_TSD_INVALID_KEY;
75 static long sync_threshold = -1; /* calibrate the value */
76 static int init_thread_intf_started = 0;
77 static int init_thread_intf_finished = 0;
78
79 #define CHCK_NREENTRANCE(x) (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
80 #define RECHCK_NREENTRANCE(x) (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
81 #define CHCK_JREENTRANCE(x) (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
82 #define RECHCK_JREENTRANCE(x) (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
83 #define PUSH_REENTRANCE(x) ((*(x))++)
84 #define POP_REENTRANCE(x) ((*(x))--)
85 #define gethrtime collector_interface->getHiResTime
86
87 /*
88 * In most cases, the functions which require interposition are implemented as
89 * weak symbols corresponding to an associated internal function named with a
90 * leading underscore: e.g., mutex_lock() is simply an alias for _mutex_lock().
91 * For the wait functions, however, the published version (used by applications)
92 * is distinct from the internal version (used by system libraries), i.e.,
93 * cond_wait() is an alias for _cond_wait_cancel() rather than _cond_wait().
94 */
95 static long int (*__real_strtol)(const char *nptr, char **endptr, int base) = NULL;
96 static int (*__real_fprintf) (FILE *stream, const char *format, ...) = NULL;
97 static void (*__real___collector_jprofile_enable_synctrace) (void) = NULL;
98 static int (*__real_pthread_mutex_lock) (pthread_mutex_t *mutex) = NULL;
99 static int (*__real_pthread_mutex_lock_2_17) (pthread_mutex_t *mutex) = NULL;
100 static int (*__real_pthread_mutex_lock_2_2_5) (pthread_mutex_t *mutex) = NULL;
101 static int (*__real_pthread_mutex_lock_2_0) (pthread_mutex_t *mutex) = NULL;
102 static int (*__real_pthread_mutex_unlock) (pthread_mutex_t *mutex) = NULL;
103 static int (*__real_pthread_cond_wait) (pthread_cond_t *restrict cond,
104 pthread_mutex_t *restrict mutex) = NULL;
105 static int (*__real_pthread_cond_timedwait) (pthread_cond_t *restrict cond,
106 pthread_mutex_t *restrict mutex,
107 const struct timespec *restrict abstime) = NULL;
108 static int (*__real_pthread_join) (pthread_t thread, void **retval) = NULL;
109 static int (*__real_pthread_join_2_34) (pthread_t thread, void **retval) = NULL;
110 static int (*__real_pthread_join_2_17) (pthread_t thread, void **retval) = NULL;
111 static int (*__real_pthread_join_2_2_5) (pthread_t thread, void **retval) = NULL;
112 static int (*__real_pthread_join_2_0) (pthread_t thread, void **retval) = NULL;
113 static int (*__real_sem_wait) (sem_t *sem) = NULL;
114 static int (*__real_sem_wait_2_34) (sem_t *sem) = NULL;
115 static int (*__real_sem_wait_2_17) (sem_t *sem) = NULL;
116 static int (*__real_sem_wait_2_2_5) (sem_t *sem) = NULL;
117 static int (*__real_sem_wait_2_1) (sem_t *sem) = NULL;
118 static int (*__real_sem_wait_2_0) (sem_t *sem) = NULL;
119 static int (*__real_pthread_cond_wait_2_17) (pthread_cond_t *restrict cond,
120 pthread_mutex_t *restrict mutex) = NULL;
121 static int (*__real_pthread_cond_wait_2_3_2) (pthread_cond_t *restrict cond,
122 pthread_mutex_t *restrict mutex) = NULL;
123 static int (*__real_pthread_cond_wait_2_2_5) (pthread_cond_t *restrict cond,
124 pthread_mutex_t *restrict mutex) = NULL;
125 static int (*__real_pthread_cond_wait_2_0) (pthread_cond_t *restrict cond,
126 pthread_mutex_t *restrict mutex) = NULL;
127 static int (*__real_pthread_cond_timedwait_2_17) (pthread_cond_t *restrict cond,
128 pthread_mutex_t *restrict mutex,
129 const struct timespec *restrict abstime) = NULL;
130 static int (*__real_pthread_cond_timedwait_2_3_2) (pthread_cond_t *restrict cond,
131 pthread_mutex_t *restrict mutex,
132 const struct timespec *restrict abstime) = NULL;
133 static int (*__real_pthread_cond_timedwait_2_2_5) (pthread_cond_t *restrict cond,
134 pthread_mutex_t *restrict mutex,
135 const struct timespec *restrict abstime) = NULL;
136 static int (*__real_pthread_cond_timedwait_2_0) (pthread_cond_t *restrict cond,
137 pthread_mutex_t *restrict mutex,
138 const struct timespec *restrict abstime) = NULL;
139
140
141 static void
142 collector_memset (void *s, int c, size_t n)
143 {
144 unsigned char *s1 = s;
145 while (n--)
146 *s1++ = (unsigned char) c;
147 }
148
149 void
150 __collector_module_init (CollectorInterface *_collector_interface)
151 {
152 if (_collector_interface == NULL)
153 return;
154 collector_interface = _collector_interface;
155 TprintfT (0, "synctrace: __collector_module_init\n");
156 sync_hndl = collector_interface->registerModule (&module_interface);
157
158 /* Initialize next module */
159 ModuleInitFunc next_init = (ModuleInitFunc) dlsym (RTLD_NEXT, "__collector_module_init");
160 if (next_init != NULL)
161 next_init (_collector_interface);
162 }
163
164 static int
165 open_experiment (const char *exp)
166 {
167 long thresh = 0;
168 if (init_thread_intf_finished == 0)
169 init_thread_intf ();
170 if (collector_interface == NULL)
171 {
172 Tprintf (0, "synctrace: collector_interface is null.\n");
173 return COL_ERROR_SYNCINIT;
174 }
175 if (sync_hndl == COLLECTOR_MODULE_ERR)
176 {
177 Tprintf (0, "synctrace: handle create failed.\n");
178 collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">data handle not created</event>\n",
179 SP_JCMD_CERROR, COL_ERROR_SYNCINIT);
180 return COL_ERROR_SYNCINIT;
181 }
182 TprintfT (0, "synctrace: open_experiment %s\n", exp);
183
184 char *params = (char *) collector_interface->getParams ();
185 while (params)
186 {
187 if ((params[0] == 's') && (params[1] == ':'))
188 {
189 char *ptr = params + 2;
190 Tprintf (DBG_LT1, "synctrace: open_experiment s: parameter = %s\n", ptr);
191 while (*ptr != ',' && *ptr != ';')
192 ptr++;
193 sync_scope = 0;
194 if (*ptr == ',')
195 {
196 sync_scope = CALL_REAL (strtol) (ptr + 1, NULL, 0);
197 switch (sync_scope)
198 {
199 case 1:
200 sync_java = 0;
201 sync_native = 1;
202 break;
203 case 2:
204 sync_java = 1;
205 sync_native = 0;
206 break;
207 default:
208 case 3:
209 sync_native = 1;
210 sync_java = 1;
211 break;
212 }
213 Tprintf (0, "\tsynctrace: sync_scope found as %ld\n", sync_scope);
214 }
215 else
216 {
217 /* the old-style descriptor, without scope */
218 /* if there was no comma, use the old default */
219 sync_scope = 3;
220 sync_java = 1;
221 sync_native = 1;
222 Tprintf (0, "\tsynctrace: sync_scope not found set to %ld\n", sync_scope);
223 }
224 if (__real___collector_jprofile_enable_synctrace == NULL)
225 sync_java = 0;
226 thresh = CALL_REAL (strtol)(params + 2, NULL, 0);
227 break; /* from the loop to find the "s:thresh,scope" entry */
228 }
229 else
230 params++;
231 }
232 if (params == NULL) /* Sync data collection not specified */
233 return COL_ERROR_SYNCINIT;
234 if (thresh < 0) /* calibrate the threshold, keep it as a negative number */
235 thresh = -sync_calibrate ();
236
237 sync_key = collector_interface->createKey (sizeof ( int), NULL, NULL);
238 if (sync_key == (unsigned) - 1)
239 {
240 Tprintf (0, "synctrace: TSD key create failed.\n");
241 collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">TSD key not created</event>\n",
242 SP_JCMD_CERROR, COL_ERROR_SYNCINIT);
243 return COL_ERROR_SYNCINIT;
244 }
245 /* if Java synctrace was requested, tell the jprofile module */
246 if (sync_java)
247 {
248 TprintfT (0, "synctrace: enabling Java synctrace\n");
249 CALL_REAL (__collector_jprofile_enable_synctrace)();
250 }
251 collector_interface->writeLog ("<profile name=\"%s\" threshold=\"%ld\" scope=\"%ld\">\n",
252 SP_JCMD_SYNCTRACE, thresh, sync_scope);
253 collector_interface->writeLog (" <profdata fname=\"%s\"/>\n",
254 module_interface.description);
255 /* Record Sync_packet description */
256 collector_interface->writeLog (" <profpckt kind=\"%d\" uname=\"Synchronization tracing data\">\n", SYNC_PCKT);
257 collector_interface->writeLog (" <field name=\"LWPID\" uname=\"Lightweight process id\" offset=\"%d\" type=\"%s\"/>\n",
258 (int) offsetof (Sync_packet, comm.lwp_id),
259 fld_sizeof (Sync_packet, comm.lwp_id) == 4 ? "INT32" : "INT64");
260 collector_interface->writeLog (" <field name=\"THRID\" uname=\"Thread number\" offset=\"%d\" type=\"%s\"/>\n",
261 (int) offsetof (Sync_packet, comm.thr_id),
262 fld_sizeof (Sync_packet, comm.thr_id) == 4 ? "INT32" : "INT64");
263 collector_interface->writeLog (" <field name=\"CPUID\" uname=\"CPU id\" offset=\"%d\" type=\"%s\"/>\n",
264 (int) offsetof (Sync_packet, comm.cpu_id),
265 fld_sizeof (Sync_packet, comm.cpu_id) == 4 ? "INT32" : "INT64");
266 collector_interface->writeLog (" <field name=\"TSTAMP\" uname=\"High resolution timestamp\" offset=\"%d\" type=\"%s\"/>\n",
267 (int) offsetof (Sync_packet, comm.tstamp),
268 fld_sizeof (Sync_packet, comm.tstamp) == 4 ? "INT32" : "INT64");
269 collector_interface->writeLog (" <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
270 (int) offsetof (Sync_packet, comm.frinfo),
271 fld_sizeof (Sync_packet, comm.frinfo) == 4 ? "INT32" : "INT64");
272 collector_interface->writeLog (" <field name=\"SRQST\" uname=\"Synchronization start time\" offset=\"%d\" type=\"%s\"/>\n",
273 (int) offsetof (Sync_packet, requested),
274 fld_sizeof (Sync_packet, requested) == 4 ? "INT32" : "INT64");
275 collector_interface->writeLog (" <field name=\"SOBJ\" uname=\"Synchronization object address\" offset=\"%d\" type=\"%s\"/>\n",
276 (int) offsetof (Sync_packet, objp),
277 fld_sizeof (Sync_packet, objp) == 4 ? "INT32" : "INT64");
278 collector_interface->writeLog (" </profpckt>\n");
279 collector_interface->writeLog ("</profile>\n");
280
281 /* Convert threshold from microsec to nanosec */
282 sync_threshold = (thresh > 0 ? thresh : -thresh) * 1000;
283 TprintfT (0, "synctrace: open_experiment complete %ld\n", sync_threshold);
284 return COL_ERROR_NONE;
285 }
286
287 static int
288 start_data_collection (void)
289 {
290 sync_mode = 1;
291 TprintfT (0, "synctrace: start_data_collection\n");
292 return 0;
293 }
294
295 static int
296 stop_data_collection (void)
297 {
298 sync_mode = 0;
299 TprintfT (0, "synctrace: stop_data_collection\n");
300 return 0;
301 }
302
303 static int
304 close_experiment (void)
305 {
306 sync_mode = 0;
307 sync_threshold = -1;
308 sync_key = COLLECTOR_TSD_INVALID_KEY;
309 TprintfT (0, "synctrace: close_experiment\n");
310 return 0;
311 }
312
313 /* fork child. Clean up state but don't write to experiment */
314 static int
315 detach_experiment (void)
316 {
317 sync_mode = 0;
318 sync_threshold = -1;
319 sync_key = COLLECTOR_TSD_INVALID_KEY;
320 TprintfT (0, "synctrace: detach_experiment\n");
321 return 0;
322 }
323
324 #define NUM_ITER 100 /* number of iterations in calibration */
325 #define NUM_WARMUP 3 /* number of warm up iterations */
326
327 static int
328 sync_calibrate ()
329 {
330 pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER;
331 hrtime_t bt, at, delta;
332 hrtime_t avg, max, min;
333 int i;
334 int ret;
335 avg = (hrtime_t) 0;
336 min = max = (hrtime_t) 0;
337 for (i = 0; i < NUM_ITER + NUM_WARMUP; i++)
338 {
339 /* Here we simulate a real call */
340 bt = gethrtime ();
341 ret = CALL_REAL (pthread_mutex_lock)(&mt);
342 at = gethrtime ();
343 CALL_REAL (pthread_mutex_unlock)(&mt);
344 if (i < NUM_WARMUP) /* skip these iterations */
345 continue;
346 /* add the time of this one */
347 delta = at - bt;
348 avg += delta;
349 if (min == 0)
350 min = delta;
351 if (delta < min)
352 min = delta;
353 if (delta > max)
354 max = delta;
355 }
356 /* compute average time */
357 avg = avg / NUM_ITER;
358
359 /* pretty simple, let's see how it works */
360 if (max < 6 * avg)
361 max = 6 * avg;
362 /* round up to the nearest microsecond */
363 ret = (int) ((max + 999) / 1000);
364 return ret;
365 }
366
367 static int
368 init_pthread_mutex_lock (void *dlflag)
369 {
370 __real_pthread_mutex_lock_2_17 = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.17");
371 __real_pthread_mutex_lock_2_2_5 = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2.5");
372 __real_pthread_mutex_lock_2_0 = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.0");
373 if (__real_pthread_mutex_lock_2_17)
374 __real_pthread_mutex_lock = __real_pthread_mutex_lock_2_17;
375 else if (__real_pthread_mutex_lock_2_2_5)
376 __real_pthread_mutex_lock = __real_pthread_mutex_lock_2_2_5;
377 else if (__real_pthread_mutex_lock_2_0)
378 __real_pthread_mutex_lock = __real_pthread_mutex_lock_2_0;
379 else
380 __real_pthread_mutex_lock = dlsym (dlflag, "pthread_mutex_lock");
381 return __real_pthread_mutex_lock ? 1 : 0;
382 }
383
384 static int
385 init_thread_intf ()
386 {
387 void *dlflag = RTLD_NEXT;
388 int err = 0;
389 /* if we detect recursion/reentrance, SEGV so we can get a stack */
390 init_thread_intf_started++;
391 if (!init_thread_intf_finished && init_thread_intf_started >= 3)
392 {
393 /* pull the plug if recursion occurs... */
394 abort ();
395 }
396 /* lookup fprint to print fatal error message */
397 void *ptr = dlsym (RTLD_DEFAULT, "fprintf");
398 if (ptr)
399 {
400 __real_fprintf = (void *) ptr;
401 }
402 else
403 {
404 abort ();
405 }
406
407 /* find the __collector_jprofile_enable_synctrace routine in jprofile module */
408 ptr = dlsym (RTLD_DEFAULT, "__collector_jprofile_enable_synctrace");
409 if (ptr)
410 __real___collector_jprofile_enable_synctrace = (void *) ptr;
411 else
412 {
413 #if defined(GPROFNG_JAVA_PROFILING)
414 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT __collector_jprofile_enable_synctrace\n");
415 err = COL_ERROR_SYNCINIT;
416 #endif
417 sync_java = 0;
418 }
419
420 dlflag = RTLD_NEXT;
421 if (init_pthread_mutex_lock (dlflag) == 0)
422 {
423 /* We are probably dlopened after libthread/libc,
424 * try to search in the previously loaded objects
425 */
426 dlflag = RTLD_DEFAULT;
427 if (init_pthread_mutex_lock (dlflag) == 0)
428 {
429 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
430 err = COL_ERROR_SYNCINIT;
431 }
432 }
433
434 if ((ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.17")) != NULL)
435 __real_pthread_mutex_unlock = ptr;
436 else if ((ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.2.5")) != NULL)
437 __real_pthread_mutex_unlock = ptr;
438 else if ((ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.0")) != NULL)
439 __real_pthread_mutex_unlock = ptr;
440 else
441 __real_pthread_mutex_unlock = dlsym (dlflag, "pthread_mutex_unlock");
442 if (__real_pthread_mutex_unlock == NULL)
443 {
444 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
445 err = COL_ERROR_SYNCINIT;
446 }
447
448 __real_pthread_cond_wait_2_17 = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.17");
449 __real_pthread_cond_wait_2_3_2 = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.3.2");
450 __real_pthread_cond_wait_2_2_5 = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.2.5");
451 __real_pthread_cond_wait_2_0 = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.0");
452 if (__real_pthread_cond_wait_2_17)
453 __real_pthread_cond_wait = __real_pthread_cond_wait_2_17;
454 else if (__real_pthread_cond_wait_2_3_2)
455 __real_pthread_cond_wait = __real_pthread_cond_wait_2_3_2;
456 else if (__real_pthread_cond_wait_2_2_5)
457 __real_pthread_cond_wait = __real_pthread_cond_wait_2_2_5;
458 else if (__real_pthread_cond_wait_2_0)
459 __real_pthread_cond_wait = __real_pthread_cond_wait_2_0;
460 else
461 __real_pthread_cond_wait = dlsym (dlflag, "pthread_cond_wait");
462 if (__real_pthread_cond_wait == NULL)
463 {
464 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
465 err = COL_ERROR_SYNCINIT;
466 }
467
468 __real_pthread_cond_timedwait_2_17 = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.17");
469 __real_pthread_cond_timedwait_2_3_2 = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.3.2");
470 __real_pthread_cond_timedwait_2_2_5 = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.2.5");
471 __real_pthread_cond_timedwait_2_0 = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.0");
472 if (__real_pthread_cond_timedwait_2_17)
473 __real_pthread_cond_timedwait = __real_pthread_cond_timedwait_2_17;
474 else if (__real_pthread_cond_timedwait_2_3_2)
475 __real_pthread_cond_timedwait = __real_pthread_cond_timedwait_2_3_2;
476 else if (__real_pthread_cond_timedwait_2_2_5)
477 __real_pthread_cond_timedwait = __real_pthread_cond_timedwait_2_2_5;
478 else if (__real_pthread_cond_timedwait_2_0)
479 __real_pthread_cond_timedwait = __real_pthread_cond_timedwait_2_0;
480 else
481 __real_pthread_cond_timedwait = dlsym (dlflag, "pthread_cond_timedwait");
482 if (__real_pthread_cond_timedwait == NULL)
483 {
484 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
485 err = COL_ERROR_SYNCINIT;
486 }
487
488 __real_pthread_join_2_34 = dlvsym (dlflag, "pthread_join", "GLIBC_2.34");
489 __real_pthread_join_2_17 = dlvsym (dlflag, "pthread_join", "GLIBC_2.17");
490 __real_pthread_join_2_2_5 = dlvsym (dlflag, "pthread_join", "GLIBC_2.2.5");
491 __real_pthread_join_2_0 = dlvsym (dlflag, "pthread_join", "GLIBC_2.0");
492 if (__real_pthread_join_2_34)
493 __real_pthread_join = __real_pthread_join_2_34;
494 else if (__real_pthread_join_2_17)
495 __real_pthread_join = __real_pthread_join_2_17;
496 else if (__real_pthread_join_2_2_5)
497 __real_pthread_join = __real_pthread_join_2_2_5;
498 else if (__real_pthread_join_2_0)
499 __real_pthread_join = __real_pthread_join_2_0;
500 else
501 __real_pthread_join = dlsym (dlflag, "pthread_join");
502 if (__real_pthread_join == NULL)
503 {
504 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
505 err = COL_ERROR_SYNCINIT;
506 }
507
508 __real_sem_wait_2_34 = dlvsym (dlflag, "sem_wait", "GLIBC_2.34");
509 __real_sem_wait_2_17 = dlvsym (dlflag, "sem_wait", "GLIBC_2.17");
510 __real_sem_wait_2_2_5 = dlvsym (dlflag, "sem_wait", "GLIBC_2.2.5");
511 __real_sem_wait_2_1 = dlvsym (dlflag, "sem_wait", "GLIBC_2.1");
512 __real_sem_wait_2_0 = dlvsym (dlflag, "sem_wait", "GLIBC_2.0");
513 if (__real_sem_wait_2_34)
514 __real_sem_wait = __real_sem_wait_2_34;
515 else if (__real_sem_wait_2_17)
516 __real_sem_wait = __real_sem_wait_2_17;
517 else if (__real_sem_wait_2_2_5)
518 __real_sem_wait = __real_sem_wait_2_2_5;
519 else if (__real_sem_wait_2_1)
520 __real_sem_wait = __real_sem_wait_2_1;
521 else if (__real_sem_wait_2_0)
522 __real_sem_wait = __real_sem_wait_2_0;
523 else
524 __real_sem_wait = dlsym (dlflag, "sem_wait");
525 if (__real_sem_wait == NULL)
526 {
527 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
528 err = COL_ERROR_SYNCINIT;
529 }
530
531
532 ptr = dlsym (dlflag, "strtol");
533 if (ptr)
534 __real_strtol = (void *) ptr;
535 else
536 {
537 CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT strtol\n");
538 err = COL_ERROR_SYNCINIT;
539 }
540 init_thread_intf_finished++;
541 TprintfT (0, "synctrace init_thread_intf complete\n");
542 return err;
543 }
544
545 /* These next two routines are used from jprofile to record Java synctrace data */
546 void
547 __collector_jsync_begin ()
548 {
549 int *guard;
550 if (CHCK_JREENTRANCE (guard))
551 {
552 Tprintf (DBG_LT1, "__collector_jsync_begin: skipped\n");
553 return;
554 }
555 Tprintf (DBG_LT1, "__collector_jsync_begin: start event\n");
556 PUSH_REENTRANCE (guard);
557 }
558
559 void
560 __collector_jsync_end (hrtime_t reqt, void *object)
561 {
562 int *guard;
563 if (RECHCK_JREENTRANCE (guard))
564 {
565 Tprintf (DBG_LT1, "__collector_jsync_end: skipped\n");
566 return;
567 }
568 hrtime_t grnt = gethrtime ();
569 if (grnt - reqt >= sync_threshold)
570 {
571 Sync_packet spacket;
572 collector_memset (&spacket, 0, sizeof (Sync_packet));
573 spacket.comm.tsize = sizeof (Sync_packet);
574 spacket.comm.tstamp = grnt;
575 spacket.requested = reqt;
576 spacket.objp = (intptr_t) object;
577 spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl,
578 spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
579 collector_interface->writeDataRecord (sync_hndl, (Common_packet*) &spacket);
580 }
581 Tprintf (DBG_LT1, "__collector_jsync_begin: end event\n");
582 POP_REENTRANCE (guard);
583 }
584 /*-------------------------------------------------------- pthread_mutex_lock */
585 static int
586 gprofng_pthread_mutex_lock (int (real_func) (pthread_mutex_t *),
587 pthread_mutex_t *mp)
588 {
589 int *guard;
590 if (CHCK_NREENTRANCE (guard))
591 return (real_func) (mp);
592 PUSH_REENTRANCE (guard);
593 hrtime_t reqt = gethrtime ();
594 int ret = (real_func) (mp);
595 if (RECHCK_NREENTRANCE (guard))
596 {
597 POP_REENTRANCE (guard);
598 return ret;
599 }
600 hrtime_t grnt = gethrtime ();
601 if (grnt - reqt >= sync_threshold)
602 {
603 Sync_packet spacket;
604 collector_memset (&spacket, 0, sizeof (Sync_packet));
605 spacket.comm.tsize = sizeof (Sync_packet);
606 spacket.comm.tstamp = grnt;
607 spacket.requested = reqt;
608 spacket.objp = (intptr_t) mp;
609 spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl,
610 spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
611 collector_interface->writeDataRecord (sync_hndl, (Common_packet*) &spacket);
612 }
613 POP_REENTRANCE (guard);
614 return ret;
615 }
616
617 #define DCL_PTHREAD_MUTEX_LOCK(dcl_f) \
618 int dcl_f (pthread_mutex_t *mp) \
619 { \
620 if (__real_pthread_mutex_lock == NULL) \
621 init_thread_intf (); \
622 return gprofng_pthread_mutex_lock (__real_pthread_mutex_lock, mp); \
623 }
624
625 DCL_FUNC_VER (DCL_PTHREAD_MUTEX_LOCK, pthread_mutex_lock_2_17, pthread_mutex_lock@GLIBC_2.17)
626 DCL_FUNC_VER (DCL_PTHREAD_MUTEX_LOCK, pthread_mutex_lock_2_2_5, pthread_mutex_lock@GLIBC_2.2.5)
627 DCL_FUNC_VER (DCL_PTHREAD_MUTEX_LOCK, pthread_mutex_lock_2_0, pthread_mutex_lock@GLIBC_2.0)
628 DCL_PTHREAD_MUTEX_LOCK (pthread_mutex_lock)
629
630 /*------------------------------------------------------------- pthread_cond_wait */
631 static int
632 gprofng_pthread_cond_wait (int(real_func) (pthread_cond_t *, pthread_mutex_t *),
633 pthread_cond_t *cond, pthread_mutex_t *mutex)
634 {
635 int *guard;
636 if (CHCK_NREENTRANCE (guard))
637 return (real_func) (cond, mutex);
638 PUSH_REENTRANCE (guard);
639 hrtime_t reqt = gethrtime ();
640 int ret = -1;
641 ret = (real_func) (cond, mutex);
642 if (RECHCK_NREENTRANCE (guard))
643 {
644 POP_REENTRANCE (guard);
645 return ret;
646 }
647 hrtime_t grnt = gethrtime ();
648 if (grnt - reqt >= sync_threshold)
649 {
650 Sync_packet spacket;
651 collector_memset (&spacket, 0, sizeof (Sync_packet));
652 spacket.comm.tsize = sizeof (Sync_packet);
653 spacket.comm.tstamp = grnt;
654 spacket.requested = reqt;
655 spacket.objp = (intptr_t) mutex;
656 spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl,
657 spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
658 collector_interface->writeDataRecord (sync_hndl, (Common_packet*) &spacket);
659 }
660 POP_REENTRANCE (guard);
661 return ret;
662 }
663
664 #define DCL_PTHREAD_COND_WAIT(dcl_f) \
665 int dcl_f (pthread_cond_t *cond, pthread_mutex_t *mutex) \
666 { \
667 if (__real_pthread_cond_wait == NULL) \
668 init_thread_intf (); \
669 return gprofng_pthread_cond_wait (__real_pthread_cond_wait, cond, mutex); \
670 }
671
672 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT, pthread_cond_wait_2_17, pthread_cond_wait@GLIBC_2.17)
673 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT, pthread_cond_wait_2_3_2, pthread_cond_wait@GLIBC_2.3.2)
674 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT, pthread_cond_wait_2_2_5, pthread_cond_wait@GLIBC_2.2.5)
675 DCL_FUNC_VER (DCL_PTHREAD_COND_WAIT, pthread_cond_wait_2_0, pthread_cond_wait@GLIBC_2.0)
676 DCL_PTHREAD_COND_WAIT (pthread_cond_wait)
677
678 /*---------------------------------------------------- pthread_cond_timedwait */
679 static int
680 gprofng_pthread_cond_timedwait (int(real_func) (pthread_cond_t *,
681 pthread_mutex_t*, const struct timespec *),
682 pthread_cond_t *cond, pthread_mutex_t *mutex,
683 const struct timespec *abstime)
684 {
685 int *guard;
686 if (CHCK_NREENTRANCE (guard))
687 return (real_func) (cond, mutex, abstime);
688 PUSH_REENTRANCE (guard);
689 hrtime_t reqt = gethrtime ();
690 int ret = -1;
691 ret = (real_func) (cond, mutex, abstime);
692 if (RECHCK_NREENTRANCE (guard))
693 {
694 POP_REENTRANCE (guard);
695 return ret;
696 }
697 hrtime_t grnt = gethrtime ();
698 if (grnt - reqt >= sync_threshold)
699 {
700 Sync_packet spacket;
701 collector_memset (&spacket, 0, sizeof (Sync_packet));
702 spacket.comm.tsize = sizeof (Sync_packet);
703 spacket.comm.tstamp = grnt;
704 spacket.requested = reqt;
705 spacket.objp = (intptr_t) mutex;
706 spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl,
707 spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
708 collector_interface->writeDataRecord (sync_hndl, (Common_packet*) &spacket);
709 }
710 POP_REENTRANCE (guard);
711 return ret;
712 }
713
714 #define DCL_PTHREAD_COND_TIMEDWAIT(dcl_f) \
715 int dcl_f (pthread_cond_t *cond, pthread_mutex_t *mutex, \
716 const struct timespec *abstime) \
717 { \
718 if (__real_pthread_cond_timedwait == NULL) \
719 init_thread_intf (); \
720 return gprofng_pthread_cond_timedwait (__real_pthread_cond_timedwait, cond, mutex, abstime); \
721 }
722
723 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT, pthread_cond_timedwait_2_17, pthread_cond_timedwait@GLIBC_2.17)
724 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT, pthread_cond_timedwait_2_3_2, pthread_cond_timedwait@GLIBC_2.3.2)
725 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT, pthread_cond_timedwait_2_2_5, pthread_cond_timedwait@GLIBC_2.2.5)
726 DCL_FUNC_VER (DCL_PTHREAD_COND_TIMEDWAIT, pthread_cond_timedwait_2_0, pthread_cond_timedwait@GLIBC_2.0)
727 DCL_PTHREAD_COND_TIMEDWAIT (pthread_cond_timedwait)
728
729
730 /*------------------------------------------------------------- pthread_join */
731 static int
732 gprofng_pthread_join (int(real_func) (pthread_t, void **),
733 pthread_t target_thread, void **status)
734 {
735 int *guard;
736 if (CHCK_NREENTRANCE (guard))
737 return real_func (target_thread, status);
738 PUSH_REENTRANCE (guard);
739 hrtime_t reqt = gethrtime ();
740 int ret = real_func(target_thread, status);
741 if (RECHCK_NREENTRANCE (guard))
742 {
743 POP_REENTRANCE (guard);
744 return ret;
745 }
746 hrtime_t grnt = gethrtime ();
747 if (grnt - reqt >= sync_threshold)
748 {
749 Sync_packet spacket;
750 collector_memset (&spacket, 0, sizeof (Sync_packet));
751 spacket.comm.tsize = sizeof (Sync_packet);
752 spacket.comm.tstamp = grnt;
753 spacket.requested = reqt;
754 spacket.objp = (Vaddr_type) target_thread;
755 spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl,
756 spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
757 collector_interface->writeDataRecord (sync_hndl, (Common_packet*) &spacket);
758 }
759 POP_REENTRANCE (guard);
760 return ret;
761 }
762
763 #define DCL_PTHREAD_JOIN(dcl_f) \
764 int dcl_f (pthread_t target_thread, void **status) \
765 { \
766 if (__real_pthread_join == NULL) \
767 init_thread_intf (); \
768 return gprofng_pthread_join (__real_pthread_join, target_thread, status); \
769 }
770
771 DCL_FUNC_VER (DCL_PTHREAD_JOIN, pthread_join_2_34, pthread_join@GLIBC_2.34)
772 DCL_FUNC_VER (DCL_PTHREAD_JOIN, pthread_join_2_17, pthread_join@GLIBC_2.17)
773 DCL_FUNC_VER (DCL_PTHREAD_JOIN, pthread_join_2_2_5, pthread_join@GLIBC_2.2.5)
774 DCL_FUNC_VER (DCL_PTHREAD_JOIN, pthread_join_2_0, pthread_join@GLIBC_2.0)
775 DCL_PTHREAD_JOIN (pthread_join)
776
777 /*------------------------------------------------------------- sem_wait */
778 static int
779 gprofng_sem_wait (int (real_func) (sem_t *), sem_t *sp)
780 {
781 int *guard;
782 if (CHCK_NREENTRANCE (guard))
783 return real_func (sp);
784 PUSH_REENTRANCE (guard);
785 hrtime_t reqt = gethrtime ();
786 int ret = -1;
787 ret = real_func (sp);
788 if (RECHCK_NREENTRANCE (guard))
789 {
790 POP_REENTRANCE (guard);
791 return ret;
792 }
793 hrtime_t grnt = gethrtime ();
794 if (grnt - reqt >= sync_threshold)
795 {
796 Sync_packet spacket;
797 collector_memset (&spacket, 0, sizeof (Sync_packet));
798 spacket.comm.tsize = sizeof (Sync_packet);
799 spacket.comm.tstamp = grnt;
800 spacket.requested = reqt;
801 spacket.objp = (intptr_t) sp;
802 spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl,
803 spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
804 collector_interface->writeDataRecord (sync_hndl, (Common_packet*) &spacket);
805 }
806 POP_REENTRANCE (guard);
807 return ret;
808 }
809
810 #define DCL_SEM_WAIT(dcl_f) \
811 int dcl_f (sem_t *sp) \
812 { \
813 if (__real_sem_wait == NULL) \
814 init_thread_intf (); \
815 return gprofng_sem_wait (__real_sem_wait, sp); \
816 }
817
818 DCL_FUNC_VER (DCL_SEM_WAIT, sem_wait_2_34, sem_wait@GLIBC_2.34)
819 DCL_FUNC_VER (DCL_SEM_WAIT, sem_wait_2_17, sem_wait@GLIBC_2.17)
820 DCL_FUNC_VER (DCL_SEM_WAIT, sem_wait_2_2_5, sem_wait@GLIBC_2.2.5)
821 DCL_FUNC_VER (DCL_SEM_WAIT, sem_wait_2_0, sem_wait@GLIBC_2.0)
822 DCL_FUNC_VER (DCL_SEM_WAIT, sem_wait_2_1, sem_wait@GLIBC_2.1)
823 DCL_SEM_WAIT (sem_wait)