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 */ 50typedef 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 57static int open_experiment (const char *); 58static int start_data_collection (void); 59static int stop_data_collection (void); 60static int close_experiment (void); 61static int detach_experiment (void); 62static int init_thread_intf (); 63static int sync_calibrate (); 64 65static 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 75static CollectorInterface *collector_interface = NULL; 76static int sync_mode = 0; 77static long sync_scope = 0; 78static int sync_native = 0; 79static int sync_java = 0; 80static CollectorModule sync_hndl = COLLECTOR_MODULE_ERR; 81static unsigned sync_key = COLLECTOR_TSD_INVALID_KEY; 82static long sync_threshold = -1; /* calibrate the value */ 83static int init_thread_intf_started = 0; 84static 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 */ 113static void *__real_strtol = NULL; 114static void *__real_fprintf = NULL; 115static void *__real___collector_jprofile_enable_synctrace = NULL; 116static void *__real_pthread_mutex_lock = NULL; 117static void *__real_pthread_mutex_unlock = NULL; /* not interposed, used in calibrate */ 118static void *__real_pthread_cond_wait = NULL; 119static void *__real_pthread_cond_timedwait = NULL; 120static void *__real_pthread_join = NULL; 121static void *__real_sem_wait = NULL; 122static void *__real_pthread_cond_wait_2_3_2 = NULL; 123static void *__real_pthread_cond_timedwait_2_3_2 = NULL; 124 125#if WSIZE(32) 126static void *__real_sem_wait_2_1 = NULL; 127static void *__real_sem_wait_2_0 = NULL; 128static void *__real_pthread_cond_wait_2_0 = NULL; 129static void *__real_pthread_cond_timedwait_2_0 = NULL; 130#elif WSIZE(64) 131#if ARCH(Intel) 132static void *__real_pthread_cond_wait_2_2_5 = NULL; 133static void *__real_pthread_cond_timedwait_2_2_5 = NULL; 134#elif ARCH(SPARC) 135static void *__real_pthread_cond_wait_2_2 = NULL; 136static void *__real_pthread_cond_timedwait_2_2 = NULL; 137#endif /* ARCH() */ 138#endif /* WSIZE() */ 139 140static void 141collector_memset (void *s, int c, size_t n) 142{ 143 unsigned char *s1 = s; 144 while (n--) 145 *s1++ = (unsigned char) c; 146} 147 148void 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 163static int 164open_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 280static int 281start_data_collection (void) 282{ 283 sync_mode = 1; 284 TprintfT (0, "synctrace: start_data_collection\n"); 285 return 0; 286} 287 288static int 289stop_data_collection (void) 290{ 291 sync_mode = 0; 292 TprintfT (0, "synctrace: stop_data_collection\n"); 293 return 0; 294} 295 296static int 297close_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 */ 307static int 308detach_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 320static int 321sync_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 360static int 361init_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 */ 684void 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 697void 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 */ 723int 724pthread_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 758static 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) 762SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_3_2, 763 pthread_cond_wait@@GLIBC_2.3.2) 764#endif 765int 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 776SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_0, 777 pthread_cond_wait@GLIBC_2.0) 778int 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) 788SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2_5, 789 pthread_cond_wait@GLIBC_2.2.5) 790int 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 800SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2, 801 pthread_cond_wait@GLIBC_2.2) 802int 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 813static 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 848static 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) 855SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_3_2, 856 pthread_cond_timedwait@@GLIBC_2.3.2) 857#endif // ARCH() 858int 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) 870SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_0, 871 pthread_cond_timedwait@GLIBC_2.0) 872int 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) 884SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2_5, 885 pthread_cond_timedwait@GLIBC_2.2.5) 886int 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 898SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2, 899 pthread_cond_timedwait@GLIBC_2.2) 900int 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 913static 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 */ 950int 951pthread_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) 985static int 986__collector_sem_wait_symver (int(real_sem_wait) (), sem_t *sp); 987 988SYMVER_ATTRIBUTE (__collector_sem_wait_2_1, sem_wait@@GLIBC_2.1) 989int 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 998SYMVER_ATTRIBUTE (__collector_sem_wait_2_0, sem_wait@GLIBC_2.0) 999int 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) 1010static int 1011__collector_sem_wait_symver (int(real_sem_wait) (), sem_t *sp) 1012{ 1013#else 1014int 1015sem_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} 1062