Home | History | Annotate | Line # | Download | only in libcollector
synctrace.c revision 1.1.1.1
      1 /* Copyright (C) 2021 Free Software Foundation, Inc.
      2    Contributed by Oracle.
      3 
      4    This file is part of GNU Binutils.
      5 
      6    This program is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3, or (at your option)
      9    any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program; if not, write to the Free Software
     18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
     19    MA 02110-1301, USA.  */
     20 
     21 /*
     22  *	Synchronization events
     23  */
     24 #include "config.h"
     25 #include <alloca.h>
     26 #include <dlfcn.h>
     27 #include <unistd.h>
     28 #include <semaphore.h>		/* sem_wait() */
     29 #include <stdlib.h>
     30 #include <string.h>
     31 #include <sys/param.h>
     32 #include <pthread.h>
     33 
     34 #include "gp-defs.h"
     35 #include "collector_module.h"
     36 #include "gp-experiment.h"
     37 #include "data_pckts.h"
     38 #include "i18n.h"
     39 #include "tsd.h"
     40 #include "cc_libcollector.h"
     41 
     42 /* TprintfT(<level>,...) definitions.  Adjust per module as needed */
     43 #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
     44 #define DBG_LTT 0 // for interposition on GLIBC functions
     45 #define DBG_LT1 1 // for configuration details, warnings
     46 #define DBG_LT2 2
     47 #define DBG_LT3 3
     48 
     49 /* define the packet that will be written out */
     50 typedef struct Sync_packet
     51 { /* Synchronization delay tracing packet */
     52   Common_packet comm;
     53   hrtime_t requested;       /* time of synchronization request */
     54   Vaddr_type objp;          /* vaddr of synchronization object */
     55 } Sync_packet;
     56 
     57 static int open_experiment (const char *);
     58 static int start_data_collection (void);
     59 static int stop_data_collection (void);
     60 static int close_experiment (void);
     61 static int detach_experiment (void);
     62 static int init_thread_intf ();
     63 static int sync_calibrate ();
     64 
     65 static ModuleInterface module_interface ={
     66   SP_SYNCTRACE_FILE,        /* description */
     67   NULL,                     /* initInterface */
     68   open_experiment,          /* openExperiment */
     69   start_data_collection,    /* startDataCollection */
     70   stop_data_collection,     /* stopDataCollection */
     71   close_experiment,         /* closeExperiment */
     72   detach_experiment         /* detachExperiment (fork child) */
     73 };
     74 
     75 static CollectorInterface *collector_interface = NULL;
     76 static int sync_mode = 0;
     77 static long sync_scope = 0;
     78 static int sync_native = 0;
     79 static int sync_java = 0;
     80 static CollectorModule sync_hndl = COLLECTOR_MODULE_ERR;
     81 static unsigned sync_key = COLLECTOR_TSD_INVALID_KEY;
     82 static long sync_threshold = -1; /* calibrate the value */
     83 static int init_thread_intf_started = 0;
     84 static int init_thread_intf_finished = 0;
     85 
     86 #define CHCK_NREENTRANCE(x)     (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
     87 #define RECHCK_NREENTRANCE(x)   (!sync_native || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
     88 #define CHCK_JREENTRANCE(x)     (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) != 0))
     89 #define RECHCK_JREENTRANCE(x)   (!sync_java || !sync_mode || ((x) = collector_interface->getKey( sync_key )) == NULL || (*(x) == 0))
     90 #define PUSH_REENTRANCE(x)      ((*(x))++)
     91 #define POP_REENTRANCE(x)       ((*(x))--)
     92 
     93 #define CALL_REAL(x)            (*(int(*)())__real_##x)
     94 #define NULL_PTR(x)             ( __real_##x == NULL )
     95 #define gethrtime	collector_interface->getHiResTime
     96 
     97 #ifdef DEBUG
     98 #define Tprintf(...)   if (collector_interface) collector_interface->writeDebugInfo( 0, __VA_ARGS__ )
     99 #define TprintfT(...)  if (collector_interface) collector_interface->writeDebugInfo( 1, __VA_ARGS__ )
    100 #else
    101 #define Tprintf(...)
    102 #define TprintfT(...)
    103 #endif
    104 
    105 /*
    106  * In most cases, the functions which require interposition are implemented as
    107  * weak symbols corresponding to an associated internal function named with a
    108  * leading underscore: e.g., mutex_lock() is simply an alias for _mutex_lock().
    109  * For the wait functions, however, the published version (used by applications)
    110  * is distinct from the internal version (used by system libraries), i.e.,
    111  * cond_wait() is an alias for _cond_wait_cancel() rather than _cond_wait().
    112  */
    113 static void *__real_strtol = NULL;
    114 static void *__real_fprintf = NULL;
    115 static void *__real___collector_jprofile_enable_synctrace = NULL;
    116 static void *__real_pthread_mutex_lock = NULL;
    117 static void *__real_pthread_mutex_unlock = NULL; /* not interposed, used in calibrate */
    118 static void *__real_pthread_cond_wait = NULL;
    119 static void *__real_pthread_cond_timedwait = NULL;
    120 static void *__real_pthread_join = NULL;
    121 static void *__real_sem_wait = NULL;
    122 static void *__real_pthread_cond_wait_2_3_2 = NULL;
    123 static void *__real_pthread_cond_timedwait_2_3_2 = NULL;
    124 
    125 #if WSIZE(32)
    126 static void *__real_sem_wait_2_1 = NULL;
    127 static void *__real_sem_wait_2_0 = NULL;
    128 static void *__real_pthread_cond_wait_2_0 = NULL;
    129 static void *__real_pthread_cond_timedwait_2_0 = NULL;
    130 #elif WSIZE(64)
    131 #if ARCH(Intel)
    132 static void *__real_pthread_cond_wait_2_2_5 = NULL;
    133 static void *__real_pthread_cond_timedwait_2_2_5 = NULL;
    134 #elif ARCH(SPARC)
    135 static void *__real_pthread_cond_wait_2_2 = NULL;
    136 static void *__real_pthread_cond_timedwait_2_2 = NULL;
    137 #endif  /* ARCH() */
    138 #endif /* WSIZE() */
    139 
    140 static void
    141 collector_memset (void *s, int c, size_t n)
    142 {
    143   unsigned char *s1 = s;
    144   while (n--)
    145     *s1++ = (unsigned char) c;
    146 }
    147 
    148 void
    149 __collector_module_init (CollectorInterface *_collector_interface)
    150 {
    151   if (_collector_interface == NULL)
    152     return;
    153   collector_interface = _collector_interface;
    154   TprintfT (0, "synctrace: __collector_module_init\n");
    155   sync_hndl = collector_interface->registerModule (&module_interface);
    156 
    157   /* Initialize next module */
    158   ModuleInitFunc next_init = (ModuleInitFunc) dlsym (RTLD_NEXT, "__collector_module_init");
    159   if (next_init != NULL)
    160     next_init (_collector_interface);
    161 }
    162 
    163 static int
    164 open_experiment (const char *exp)
    165 {
    166   long thresh = 0;
    167   if (init_thread_intf_finished == 0)
    168     init_thread_intf ();
    169   if (collector_interface == NULL)
    170     {
    171       Tprintf (0, "synctrace: collector_interface is null.\n");
    172       return COL_ERROR_SYNCINIT;
    173     }
    174   if (sync_hndl == COLLECTOR_MODULE_ERR)
    175     {
    176       Tprintf (0, "synctrace: handle create failed.\n");
    177       collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">data handle not created</event>\n",
    178 				     SP_JCMD_CERROR, COL_ERROR_SYNCINIT);
    179       return COL_ERROR_SYNCINIT;
    180     }
    181   TprintfT (0, "synctrace: open_experiment %s\n", exp);
    182 
    183   char *params = (char *) collector_interface->getParams ();
    184   while (params)
    185     {
    186       if ((params[0] == 's') && (params[1] == ':'))
    187 	{
    188 	  char *ptr = params + 2;
    189 	  Tprintf (DBG_LT1, "synctrace: open_experiment s: parameter = %s\n", ptr);
    190 	  while (*ptr != ',' && *ptr != ';')
    191 	    ptr++;
    192 	  sync_scope = 0;
    193 	  if (*ptr == ',')
    194 	    {
    195 	      sync_scope = CALL_REAL (strtol) (ptr + 1, NULL, 0);
    196 	      switch (sync_scope)
    197 		{
    198 		case 1:
    199 		  sync_java = 0;
    200 		  sync_native = 1;
    201 		  break;
    202 		case 2:
    203 		  sync_java = 1;
    204 		  sync_native = 0;
    205 		  break;
    206 		default:
    207 		case 3:
    208 		  sync_native = 1;
    209 		  sync_java = 1;
    210 		  break;
    211 		}
    212 	      Tprintf (0, "\tsynctrace: sync_scope found as %ld\n", sync_scope);
    213 	    }
    214 	  else
    215 	    {
    216 	      /* the old-style descriptor, without scope */
    217 	      /* if there was no comma, use the old default */
    218 	      sync_scope = 3;
    219 	      sync_java = 1;
    220 	      sync_native = 1;
    221 	      Tprintf (0, "\tsynctrace: sync_scope not found set to %ld\n", sync_scope);
    222 	    }
    223 	  if (__real___collector_jprofile_enable_synctrace == NULL)
    224 	    sync_java = 0;
    225 	  thresh = CALL_REAL (strtol)(params + 2, NULL, 0);
    226 	  break; /* from the loop to find the "s:thresh,scope" entry */
    227 	}
    228       else
    229 	params++;
    230     }
    231   if (params == NULL)  /* Sync data collection not specified */
    232     return COL_ERROR_SYNCINIT;
    233   if (thresh < 0)  /* calibrate the threshold, keep it as a negative number */
    234     thresh = -sync_calibrate ();
    235 
    236   sync_key = collector_interface->createKey (sizeof ( int), NULL, NULL);
    237   if (sync_key == (unsigned) - 1)
    238     {
    239       Tprintf (0, "synctrace: TSD key create failed.\n");
    240       collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">TSD key not created</event>\n",
    241 				     SP_JCMD_CERROR, COL_ERROR_SYNCINIT);
    242       return COL_ERROR_SYNCINIT;
    243     }
    244   /* if Java synctrace was requested, tell the jprofile module */
    245   if (sync_java)
    246     {
    247       TprintfT (0, "synctrace: enabling Java synctrace\n");
    248       CALL_REAL (__collector_jprofile_enable_synctrace)();
    249     }
    250   collector_interface->writeLog ("<profile name=\"%s\" threshold=\"%ld\" scope=\"%ld\">\n",
    251 				 SP_JCMD_SYNCTRACE, thresh, sync_scope);
    252   collector_interface->writeLog ("  <profdata fname=\"%s\"/>\n",
    253 				 module_interface.description);
    254   /* Record Sync_packet description */
    255   Sync_packet *pp = NULL;
    256   collector_interface->writeLog ("  <profpckt kind=\"%d\" uname=\"Synchronization tracing data\">\n", SYNC_PCKT);
    257   collector_interface->writeLog ("    <field name=\"LWPID\" uname=\"Lightweight process id\" offset=\"%d\" type=\"%s\"/>\n",
    258 				 &pp->comm.lwp_id, sizeof (pp->comm.lwp_id) == 4 ? "INT32" : "INT64");
    259   collector_interface->writeLog ("    <field name=\"THRID\" uname=\"Thread number\" offset=\"%d\" type=\"%s\"/>\n",
    260 				 &pp->comm.thr_id, sizeof (pp->comm.thr_id) == 4 ? "INT32" : "INT64");
    261   collector_interface->writeLog ("    <field name=\"CPUID\" uname=\"CPU id\" offset=\"%d\" type=\"%s\"/>\n",
    262 				 &pp->comm.cpu_id, sizeof (pp->comm.cpu_id) == 4 ? "INT32" : "INT64");
    263   collector_interface->writeLog ("    <field name=\"TSTAMP\" uname=\"High resolution timestamp\" offset=\"%d\" type=\"%s\"/>\n",
    264 				 &pp->comm.tstamp, sizeof (pp->comm.tstamp) == 4 ? "INT32" : "INT64");
    265   collector_interface->writeLog ("    <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
    266 				 &pp->comm.frinfo, sizeof (pp->comm.frinfo) == 4 ? "INT32" : "INT64");
    267   collector_interface->writeLog ("    <field name=\"SRQST\" uname=\"Synchronization start time\" offset=\"%d\" type=\"%s\"/>\n",
    268 				 &pp->requested, sizeof (pp->requested) == 4 ? "INT32" : "INT64");
    269   collector_interface->writeLog ("    <field name=\"SOBJ\" uname=\"Synchronization object address\" offset=\"%d\" type=\"%s\"/>\n",
    270 				 &pp->objp, sizeof (pp->objp) == 4 ? "INT32" : "INT64");
    271   collector_interface->writeLog ("  </profpckt>\n");
    272   collector_interface->writeLog ("</profile>\n");
    273 
    274   /* Convert threshold from microsec to nanosec */
    275   sync_threshold = (thresh > 0 ? thresh : -thresh) * 1000;
    276   TprintfT (0, "synctrace: open_experiment complete %ld\n", sync_threshold);
    277   return COL_ERROR_NONE;
    278 }
    279 
    280 static int
    281 start_data_collection (void)
    282 {
    283   sync_mode = 1;
    284   TprintfT (0, "synctrace: start_data_collection\n");
    285   return 0;
    286 }
    287 
    288 static int
    289 stop_data_collection (void)
    290 {
    291   sync_mode = 0;
    292   TprintfT (0, "synctrace: stop_data_collection\n");
    293   return 0;
    294 }
    295 
    296 static int
    297 close_experiment (void)
    298 {
    299   sync_mode = 0;
    300   sync_threshold = -1;
    301   sync_key = COLLECTOR_TSD_INVALID_KEY;
    302   TprintfT (0, "synctrace: close_experiment\n");
    303   return 0;
    304 }
    305 
    306 /* fork child.  Clean up state but don't write to experiment */
    307 static int
    308 detach_experiment (void)
    309 {
    310   sync_mode = 0;
    311   sync_threshold = -1;
    312   sync_key = COLLECTOR_TSD_INVALID_KEY;
    313   TprintfT (0, "synctrace: detach_experiment\n");
    314   return 0;
    315 }
    316 
    317 #define NUM_ITER    100     /* number of iterations in calibration */
    318 #define NUM_WARMUP    3     /* number of warm up iterations */
    319 
    320 static int
    321 sync_calibrate ()
    322 {
    323   pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER;
    324   hrtime_t bt, at, delta;
    325   hrtime_t avg, max, min;
    326   int i;
    327   int ret;
    328   avg = (hrtime_t) 0;
    329   min = max = (hrtime_t) 0;
    330   for (i = 0; i < NUM_ITER + NUM_WARMUP; i++)
    331     {
    332       /* Here we simulate a real call */
    333       bt = gethrtime ();
    334       ret = CALL_REAL (pthread_mutex_lock)(&mt);
    335       at = gethrtime ();
    336       CALL_REAL (pthread_mutex_unlock)(&mt);
    337       if (i < NUM_WARMUP)   /* skip these iterations */
    338 	continue;
    339       /* add the time of this one */
    340       delta = at - bt;
    341       avg += delta;
    342       if (min == 0)
    343 	min = delta;
    344       if (delta < min)
    345 	min = delta;
    346       if (delta > max)
    347 	max = delta;
    348     }
    349   /* compute average time */
    350   avg = avg / NUM_ITER;
    351 
    352   /* pretty simple, let's see how it works */
    353   if (max < 6 * avg)
    354     max = 6 * avg;
    355   /* round up to the nearest microsecond */
    356   ret = (int) ((max + 999) / 1000);
    357   return ret;
    358 }
    359 
    360 static int
    361 init_thread_intf ()
    362 {
    363   void *dlflag = RTLD_NEXT;
    364   int err = 0;
    365   /* if we detect recursion/reentrance, SEGV so we can get a stack */
    366   init_thread_intf_started++;
    367   if (!init_thread_intf_finished && init_thread_intf_started >= 3)
    368     {
    369       /* pull the plug if recursion occurs... */
    370       abort ();
    371     }
    372   /* lookup fprint to print fatal error message */
    373   void *ptr = dlsym (RTLD_DEFAULT, "fprintf");
    374   if (ptr)
    375     {
    376       __real_fprintf = (void *) ptr;
    377     }
    378   else
    379     {
    380       abort ();
    381     }
    382 
    383   /* find the __collector_jprofile_enable_synctrace routine in jprofile module */
    384   ptr = dlsym (RTLD_DEFAULT, "__collector_jprofile_enable_synctrace");
    385   if (ptr)
    386     __real___collector_jprofile_enable_synctrace = (void *) ptr;
    387   else
    388     {
    389 #if defined(GPROFNG_JAVA_PROFILING)
    390       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT __collector_jprofile_enable_synctrace\n");
    391       err = COL_ERROR_SYNCINIT;
    392 #endif
    393       sync_java = 0;
    394     }
    395 
    396 #if WSIZE(32)
    397   /* ########################################## begin WSIZE(32) */
    398   /* IMPORTANT!!  The GLIBC_* versions below must match those in the er_sync.*.mapfile ! */
    399   dlflag = RTLD_NEXT;
    400   ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.0");
    401   if (ptr == NULL)
    402     {
    403       /* We are probably dlopened after libthread/libc,
    404        * try to search in the previously loaded objects
    405        */
    406       dlflag = RTLD_DEFAULT;
    407       ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.0");
    408       if (ptr != NULL)
    409 	{
    410 	  __real_pthread_mutex_lock = ptr;
    411 	  Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for OS sync routines\n");
    412 	}
    413       else
    414 	{
    415 	  CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
    416 	  err = COL_ERROR_SYNCINIT;
    417 	}
    418     }
    419   else
    420     __real_pthread_mutex_lock = ptr;
    421 
    422   ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.0");
    423   if (ptr)
    424     __real_pthread_mutex_unlock = (void *) ptr;
    425   else
    426     {
    427       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
    428       err = COL_ERROR_SYNCINIT;
    429     }
    430   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.3.2");
    431   if (ptr)
    432     __real_pthread_cond_wait = (void *) ptr;
    433   else
    434     {
    435       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
    436       err = COL_ERROR_SYNCINIT;
    437     }
    438   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.3.2");
    439   if (ptr)
    440     __real_pthread_cond_timedwait = (void *) ptr;
    441   else
    442     {
    443       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
    444       err = COL_ERROR_SYNCINIT;
    445     }
    446   ptr = dlvsym (dlflag, "pthread_join", "GLIBC_2.0");
    447   if (ptr)
    448     __real_pthread_join = (void *) ptr;
    449   else
    450     {
    451       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
    452       err = COL_ERROR_SYNCINIT;
    453     }
    454   ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.1");
    455   if (ptr)
    456     __real_sem_wait = (void *) ptr;
    457   else
    458     {
    459       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
    460       err = COL_ERROR_SYNCINIT;
    461     }
    462 
    463 #if ARCH(Intel)
    464   /* ############## Intel specific additional pointers for 32-bits */
    465   ptr = __real_sem_wait_2_1 = __real_sem_wait;
    466   ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.0");
    467   if (ptr)
    468     __real_sem_wait_2_0 = (void *) ptr;
    469   else
    470     {
    471       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait_2_0\n");
    472       err = COL_ERROR_SYNCINIT;
    473     }
    474   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.0");
    475   if (ptr)
    476     __real_pthread_cond_wait_2_0 = (void *) ptr;
    477   else
    478     {
    479       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_0\n");
    480       err = COL_ERROR_SYNCINIT;
    481     }
    482   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.0");
    483   if (ptr)
    484     __real_pthread_cond_timedwait_2_0 = (void *) ptr;
    485   else
    486     {
    487       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT __real_pthread_cond_timedwait_2_0\n");
    488       err = COL_ERROR_SYNCINIT;
    489     }
    490 #endif /* ARCH(Intel) */
    491 
    492 #else /* WSIZE(64) */
    493   /* # most versions are different between platforms	*/
    494   /* # the few that are common are set after the ARCH ifdef */
    495 #if ARCH(Aarch64)
    496   dlflag = RTLD_NEXT;
    497 #define GLIBC_N    "GLIBC_2.17"
    498   __real_pthread_mutex_lock = dlvsym(dlflag, "pthread_mutex_lock", GLIBC_N);
    499   __real_pthread_mutex_unlock = dlvsym(dlflag, "pthread_mutex_unlock", GLIBC_N);
    500   __real_pthread_cond_wait = dlvsym(dlflag, "pthread_cond_wait", GLIBC_N);
    501   __real_pthread_cond_timedwait = dlvsym(dlflag, "pthread_cond_timedwait", GLIBC_N);
    502   __real_pthread_join = dlvsym(dlflag, "pthread_join", GLIBC_N);
    503   __real_sem_wait = dlvsym(dlflag, "sem_wait", GLIBC_N);
    504 
    505 #elif ARCH(Intel)
    506   dlflag = RTLD_NEXT;
    507   ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2.5");
    508   if (ptr == NULL)
    509     {
    510       /* We are probably dlopened after libthread/libc,
    511        * try to search in the previously loaded objects
    512        */
    513       dlflag = RTLD_DEFAULT;
    514       ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2.5");
    515       if (ptr != NULL)
    516 	{
    517 	  __real_pthread_mutex_lock = ptr;
    518 	  Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for Solaris sync routines\n");
    519 	}
    520       else
    521 	{
    522 	  CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_lock\n");
    523 	  err = COL_ERROR_SYNCINIT;
    524 	}
    525     }
    526   else
    527     __real_pthread_mutex_lock = ptr;
    528   ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.2.5");
    529   if (ptr)
    530     __real_pthread_mutex_unlock = (void *) ptr;
    531   else
    532     {
    533       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
    534       err = COL_ERROR_SYNCINIT;
    535     }
    536   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.3.2");
    537   if (ptr)
    538     __real_pthread_cond_wait = (void *) ptr;
    539   else
    540     {
    541       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
    542       err = COL_ERROR_SYNCINIT;
    543     }
    544   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.3.2");
    545   if (ptr)
    546     __real_pthread_cond_timedwait = (void *) ptr;
    547   else
    548     {
    549       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
    550       err = COL_ERROR_SYNCINIT;
    551     }
    552   ptr = dlvsym (dlflag, "pthread_join", "GLIBC_2.2.5");
    553   if (ptr)
    554     __real_pthread_join = (void *) ptr;
    555   else
    556     {
    557       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
    558       err = COL_ERROR_SYNCINIT;
    559     }
    560   ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.2.5");
    561   if (ptr)
    562     __real_sem_wait = (void *) ptr;
    563   else
    564     {
    565       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
    566       err = COL_ERROR_SYNCINIT;
    567     }
    568   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.2.5");
    569   if (ptr)
    570     __real_pthread_cond_wait_2_2_5 = (void *) ptr;
    571   else
    572     {
    573       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_2_5\n");
    574       err = COL_ERROR_SYNCINIT;
    575     }
    576   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.2.5");
    577   if (ptr)
    578     __real_pthread_cond_timedwait_2_2_5 = (void *) ptr;
    579   else
    580     {
    581       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait_2_2_5\n");
    582       err = COL_ERROR_SYNCINIT;
    583     }
    584 
    585 #elif ARCH(SPARC)
    586   dlflag = RTLD_NEXT;
    587   ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2");
    588   if (ptr == NULL)
    589     {
    590       /* We are probably dlopened after libthread/libc,
    591        * try to search in the previously loaded objects
    592        */
    593       dlflag = RTLD_DEFAULT;
    594       ptr = dlvsym (dlflag, "pthread_mutex_lock", "GLIBC_2.2");
    595       if (ptr != NULL)
    596 	{
    597 	  __real_pthread_mutex_lock = ptr;
    598 	  Tprintf (0, "synctrace: WARNING: init_thread_intf() using RTLD_DEFAULT for Solaris sync routines\n");
    599 	}
    600       else
    601 	{
    602 	  CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT mutex_lock\n");
    603 	  err = COL_ERROR_SYNCINIT;
    604 	}
    605     }
    606   else
    607     __real_pthread_mutex_lock = ptr;
    608   ptr = dlvsym (dlflag, "pthread_mutex_unlock", "GLIBC_2.2");
    609   if (ptr)
    610     __real_pthread_mutex_unlock = (void *) ptr;
    611   else
    612     {
    613       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_mutex_unlock\n");
    614       err = COL_ERROR_SYNCINIT;
    615     }
    616   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.3.2");
    617   if (ptr)
    618     __real_pthread_cond_wait = (void *) ptr;
    619   else
    620     {
    621       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait\n");
    622       err = COL_ERROR_SYNCINIT;
    623     }
    624   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.3.2");
    625   if (ptr)
    626     __real_pthread_cond_timedwait = (void *) ptr;
    627   else
    628     {
    629       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait\n");
    630       err = COL_ERROR_SYNCINIT;
    631     }
    632   ptr = dlvsym (dlflag, "pthread_join", "GLIBC_2.2");
    633   if (ptr)
    634     __real_pthread_join = (void *) ptr;
    635   else
    636     {
    637       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_join\n");
    638       err = COL_ERROR_SYNCINIT;
    639     }
    640   ptr = dlvsym (dlflag, "sem_wait", "GLIBC_2.2");
    641   if (ptr)
    642     __real_sem_wait = (void *) ptr;
    643   else
    644     {
    645       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT sem_wait\n");
    646       err = COL_ERROR_SYNCINIT;
    647     }
    648   ptr = dlvsym (dlflag, "pthread_cond_wait", "GLIBC_2.2");
    649   if (ptr)
    650     __real_pthread_cond_wait_2_2 = (void *) ptr;
    651   else
    652     {
    653       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_wait_2_2_5\n");
    654       err = COL_ERROR_SYNCINIT;
    655     }
    656   ptr = dlvsym (dlflag, "pthread_cond_timedwait", "GLIBC_2.2");
    657   if (ptr)
    658     __real_pthread_cond_timedwait_2_2 = (void *) ptr;
    659   else
    660     {
    661       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT pthread_cond_timedwait_2_2\n");
    662       err = COL_ERROR_SYNCINIT;
    663     }
    664 #endif /* ARCH() */
    665 #endif /* WSIZE(64) */
    666   /*  the pointers that are common to 32- and 64-bits, and to SPARC and Intel */
    667 
    668   __real_pthread_cond_wait_2_3_2 = __real_pthread_cond_wait;
    669   __real_pthread_cond_timedwait_2_3_2 = __real_pthread_cond_timedwait;
    670   ptr = dlsym (dlflag, "strtol");
    671   if (ptr)
    672     __real_strtol = (void *) ptr;
    673   else
    674     {
    675       CALL_REAL (fprintf)(stderr, "synctrace_init COL_ERROR_SYNCINIT strtol\n");
    676       err = COL_ERROR_SYNCINIT;
    677     }
    678   init_thread_intf_finished++;
    679   TprintfT (0, "synctrace init_thread_intf complete\n");
    680   return err;
    681 }
    682 
    683 /* These next two routines are used from jprofile to record Java synctrace data */
    684 void
    685 __collector_jsync_begin ()
    686 {
    687   int *guard;
    688   if (CHCK_JREENTRANCE (guard))
    689     {
    690       Tprintf (DBG_LT1, "__collector_jsync_begin: skipped\n");
    691       return;
    692     }
    693   Tprintf (DBG_LT1, "__collector_jsync_begin: start event\n");
    694   PUSH_REENTRANCE (guard);
    695 }
    696 
    697 void
    698 __collector_jsync_end (hrtime_t reqt, void *object)
    699 {
    700   int *guard;
    701   if (RECHCK_JREENTRANCE (guard))
    702     {
    703       Tprintf (DBG_LT1, "__collector_jsync_end: skipped\n");
    704       return;
    705     }
    706   hrtime_t grnt = gethrtime ();
    707   if (grnt - reqt >= sync_threshold)
    708     {
    709       Sync_packet spacket;
    710       collector_memset (&spacket, 0, sizeof (Sync_packet));
    711       spacket.comm.tsize = sizeof (Sync_packet);
    712       spacket.comm.tstamp = grnt;
    713       spacket.requested = reqt;
    714       spacket.objp = (intptr_t) object;
    715       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
    716       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
    717     }
    718   Tprintf (DBG_LT1, "__collector_jsync_begin: end event\n");
    719   POP_REENTRANCE (guard);
    720 }
    721 
    722 /*-------------------------------------------------------- pthread_mutex_lock */
    723 int
    724 pthread_mutex_lock (pthread_mutex_t *mp)
    725 {
    726   int *guard;
    727   if (NULL_PTR (pthread_mutex_lock))
    728     init_thread_intf ();
    729   if (CHCK_NREENTRANCE (guard))
    730     return CALL_REAL (pthread_mutex_lock)(mp);
    731   PUSH_REENTRANCE (guard);
    732   hrtime_t reqt = gethrtime ();
    733   int ret = CALL_REAL (pthread_mutex_lock)(mp);
    734   if (RECHCK_NREENTRANCE (guard))
    735     {
    736       POP_REENTRANCE (guard);
    737       return ret;
    738     }
    739   hrtime_t grnt = gethrtime ();
    740   if (grnt - reqt >= sync_threshold)
    741     {
    742       Sync_packet spacket;
    743       collector_memset (&spacket, 0, sizeof (Sync_packet));
    744       spacket.comm.tsize = sizeof (Sync_packet);
    745       spacket.comm.tstamp = grnt;
    746       spacket.requested = reqt;
    747       spacket.objp = (intptr_t) mp;
    748       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK, &spacket);
    749       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
    750     }
    751   POP_REENTRANCE (guard);
    752   return ret;
    753 }
    754 
    755 
    756 /*------------------------------------------------------------- pthread_cond_wait */
    757 // map interposed symbol versions
    758 static int
    759 __collector_pthread_cond_wait_symver (int(real_pthread_cond_wait) (), pthread_cond_t *cond, pthread_mutex_t *mutex);
    760 
    761 #if ARCH(Intel) || ARCH(SPARC)
    762 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_3_2,
    763 		  pthread_cond_wait@@GLIBC_2.3.2)
    764 #endif
    765 int
    766 __collector_pthread_cond_wait_2_3_2 (pthread_cond_t *cond, pthread_mutex_t *mutex)
    767 {
    768   if (NULL_PTR (pthread_cond_wait))
    769     init_thread_intf ();
    770   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_wait_2_3_2@%p\n", CALL_REAL (pthread_cond_wait_2_3_2));
    771   return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_3_2), cond, mutex);
    772 }
    773 
    774 #if WSIZE(32)
    775 
    776 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_0,
    777 		  pthread_cond_wait@GLIBC_2.0)
    778 int
    779 __collector_pthread_cond_wait_2_0 (pthread_cond_t *cond, pthread_mutex_t *mutex)
    780 {
    781   if (NULL_PTR (pthread_cond_wait))
    782     init_thread_intf ();
    783   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_wait_2_0@%p\n", CALL_REAL (pthread_cond_wait_2_0));
    784   return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_0), cond, mutex);
    785 }
    786 #else // WSIZE(64)
    787 #if ARCH(Intel)
    788 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2_5,
    789 		  pthread_cond_wait@GLIBC_2.2.5)
    790 int
    791 __collector_pthread_cond_wait_2_2_5 (pthread_cond_t *cond, pthread_mutex_t *mutex)
    792 {
    793   if (NULL_PTR (pthread_cond_wait))
    794     init_thread_intf ();
    795   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_wait_2_2_5@%p\n", CALL_REAL (pthread_cond_wait_2_2_5));
    796   return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_2_5), cond, mutex);
    797 }
    798 #elif ARCH(SPARC)
    799 
    800 SYMVER_ATTRIBUTE (__collector_pthread_cond_wait_2_2,
    801 		  pthread_cond_wait@GLIBC_2.2)
    802 int
    803 __collector_pthread_cond_wait_2_2 (pthread_cond_t *cond, pthread_mutex_t *mutex)
    804 {
    805   if (NULL_PTR (pthread_cond_wait))
    806     init_thread_intf ();
    807   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_wait_2_2@%p\n", CALL_REAL (pthread_cond_wait_2_2));
    808   return __collector_pthread_cond_wait_symver (CALL_REAL (pthread_cond_wait_2_2), cond, mutex);
    809 }
    810 #endif  // ARCH()
    811 #endif  // WSIZE()
    812 
    813 static int
    814 __collector_pthread_cond_wait_symver (int(real_pthread_cond_wait) (), pthread_cond_t *cond, pthread_mutex_t *mutex)
    815 {
    816   int *guard;
    817   if (NULL_PTR (pthread_cond_wait))
    818     init_thread_intf ();
    819   if (CHCK_NREENTRANCE (guard))
    820     return (real_pthread_cond_wait) (cond, mutex);
    821   PUSH_REENTRANCE (guard);
    822   hrtime_t reqt = gethrtime ();
    823   int ret = -1;
    824   ret = (real_pthread_cond_wait) (cond, mutex);
    825   if (RECHCK_NREENTRANCE (guard))
    826     {
    827       POP_REENTRANCE (guard);
    828       return ret;
    829     }
    830   hrtime_t grnt = gethrtime ();
    831   if (grnt - reqt >= sync_threshold)
    832     {
    833       Sync_packet spacket;
    834       collector_memset (&spacket, 0, sizeof (Sync_packet));
    835       spacket.comm.tsize = sizeof (Sync_packet);
    836       spacket.comm.tstamp = grnt;
    837       spacket.requested = reqt;
    838       spacket.objp = (intptr_t) mutex;
    839       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
    840       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
    841     }
    842   POP_REENTRANCE (guard);
    843   return ret;
    844 }
    845 
    846 /*---------------------------------------------------- pthread_cond_timedwait */
    847 // map interposed symbol versions
    848 static int
    849 __collector_pthread_cond_timedwait_symver (int(real_pthread_cond_timedwait) (),
    850 					   pthread_cond_t *cond,
    851 					   pthread_mutex_t *mutex,
    852 					   const struct timespec *abstime);
    853 
    854 #if ARCH(Intel) || ARCH(SPARC)
    855 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_3_2,
    856 		  pthread_cond_timedwait@@GLIBC_2.3.2)
    857 #endif  // ARCH()
    858 int
    859 __collector_pthread_cond_timedwait_2_3_2 (pthread_cond_t *cond,
    860 					  pthread_mutex_t *mutex,
    861 					  const struct timespec *abstime)
    862 {
    863   if (NULL_PTR (pthread_cond_timedwait))
    864     init_thread_intf ();
    865   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_3_2@%p\n", CALL_REAL (pthread_cond_timedwait_2_3_2));
    866   return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_3_2), cond, mutex, abstime);
    867 }
    868 
    869 #if WSIZE(32)
    870 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_0,
    871 		  pthread_cond_timedwait@GLIBC_2.0)
    872 int
    873 __collector_pthread_cond_timedwait_2_0 (pthread_cond_t *cond,
    874 					pthread_mutex_t *mutex,
    875 					const struct timespec *abstime)
    876 {
    877   if (NULL_PTR (pthread_cond_timedwait))
    878     init_thread_intf ();
    879   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_0@%p\n", CALL_REAL (pthread_cond_timedwait_2_0));
    880   return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_0), cond, mutex, abstime);
    881 }
    882 #else // WSIZE(64)
    883 #if ARCH(Intel)
    884 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2_5,
    885 		  pthread_cond_timedwait@GLIBC_2.2.5)
    886 int
    887 __collector_pthread_cond_timedwait_2_2_5 (pthread_cond_t *cond,
    888 					  pthread_mutex_t *mutex,
    889 					  const struct timespec *abstime)
    890 {
    891   if (NULL_PTR (pthread_cond_timedwait))
    892     init_thread_intf ();
    893   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_2_5@%p\n", CALL_REAL (pthread_cond_timedwait_2_2_5));
    894   return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_2_5), cond, mutex, abstime);
    895 }
    896 #elif ARCH(SPARC)
    897 
    898 SYMVER_ATTRIBUTE (__collector_pthread_cond_timedwait_2_2,
    899 		  pthread_cond_timedwait@GLIBC_2.2)
    900 int
    901 __collector_pthread_cond_timedwait_2_2 (pthread_cond_t *cond,
    902 					pthread_mutex_t *mutex,
    903 					const struct timespec *abstime)
    904 {
    905   if (NULL_PTR (pthread_cond_timedwait))
    906     init_thread_intf ();
    907   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_pthread_cond_timedwait_2_2@%p\n", CALL_REAL (pthread_cond_timedwait_2_2));
    908   return __collector_pthread_cond_timedwait_symver (CALL_REAL (pthread_cond_timedwait_2_2), cond, mutex, abstime);
    909 }
    910 #endif  // ARCH()
    911 #endif  // WSIZE()
    912 
    913 static int
    914 __collector_pthread_cond_timedwait_symver (int(real_pthread_cond_timedwait) (),
    915 					   pthread_cond_t *cond,
    916 					   pthread_mutex_t *mutex,
    917 					   const struct timespec *abstime)
    918 {
    919   int *guard;
    920   if (NULL_PTR (pthread_cond_timedwait))
    921     init_thread_intf ();
    922   if (CHCK_NREENTRANCE (guard))
    923     return (real_pthread_cond_timedwait) (cond, mutex, abstime);
    924   PUSH_REENTRANCE (guard);
    925   hrtime_t reqt = gethrtime ();
    926   int ret = -1;
    927   ret = (real_pthread_cond_timedwait) (cond, mutex, abstime);
    928   if (RECHCK_NREENTRANCE (guard))
    929     {
    930       POP_REENTRANCE (guard);
    931       return ret;
    932     }
    933   hrtime_t grnt = gethrtime ();
    934   if (grnt - reqt >= sync_threshold)
    935     {
    936       Sync_packet spacket;
    937       collector_memset (&spacket, 0, sizeof ( Sync_packet));
    938       spacket.comm.tsize = sizeof ( Sync_packet);
    939       spacket.comm.tstamp = grnt;
    940       spacket.requested = reqt;
    941       spacket.objp = (intptr_t) mutex;
    942       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
    943       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
    944     }
    945   POP_REENTRANCE (guard);
    946   return ret;
    947 }
    948 
    949 /*------------------------------------------------------------- pthread_join */
    950 int
    951 pthread_join (pthread_t target_thread, void **status)
    952 {
    953   int *guard;
    954   if (NULL_PTR (pthread_join))
    955     init_thread_intf ();
    956   if (CHCK_NREENTRANCE (guard))
    957     return CALL_REAL (pthread_join)(target_thread, status);
    958   PUSH_REENTRANCE (guard);
    959   hrtime_t reqt = gethrtime ();
    960   int ret = CALL_REAL (pthread_join)(target_thread, status);
    961   if (RECHCK_NREENTRANCE (guard))
    962     {
    963       POP_REENTRANCE (guard);
    964       return ret;
    965     }
    966   hrtime_t grnt = gethrtime ();
    967   if (grnt - reqt >= sync_threshold)
    968     {
    969       Sync_packet spacket;
    970       collector_memset (&spacket, 0, sizeof ( Sync_packet));
    971       spacket.comm.tsize = sizeof ( Sync_packet);
    972       spacket.comm.tstamp = grnt;
    973       spacket.requested = reqt;
    974       spacket.objp = (Vaddr_type) target_thread;
    975       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK, &spacket);
    976       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
    977     }
    978   POP_REENTRANCE (guard);
    979   return ret;
    980 }
    981 
    982 /*------------------------------------------------------------- sem_wait */
    983 // map interposed symbol versions
    984 #if ARCH(Intel) && WSIZE(32)
    985 static int
    986 __collector_sem_wait_symver (int(real_sem_wait) (), sem_t *sp);
    987 
    988 SYMVER_ATTRIBUTE (__collector_sem_wait_2_1, sem_wait@@GLIBC_2.1)
    989 int
    990 __collector_sem_wait_2_1 (sem_t *sp)
    991 {
    992   if (NULL_PTR (sem_wait))
    993     init_thread_intf ();
    994   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_sem_wait_2_1@%p\n", CALL_REAL (sem_wait_2_1));
    995   return __collector_sem_wait_symver (CALL_REAL (sem_wait_2_1), sp);
    996 }
    997 
    998 SYMVER_ATTRIBUTE (__collector_sem_wait_2_0, sem_wait@GLIBC_2.0)
    999 int
   1000 __collector_sem_wait_2_0 (sem_t *sp)
   1001 {
   1002   if (NULL_PTR (sem_wait))
   1003     init_thread_intf ();
   1004   TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_sem_wait_2_0@%p\n", CALL_REAL (sem_wait_2_0));
   1005   return __collector_sem_wait_symver (CALL_REAL (sem_wait_2_0), sp);
   1006 }
   1007 #endif
   1008 
   1009 #if ARCH(Intel) && WSIZE(32)
   1010 static int
   1011 __collector_sem_wait_symver (int(real_sem_wait) (), sem_t *sp)
   1012 {
   1013 #else
   1014 int
   1015 sem_wait (sem_t *sp)
   1016 {
   1017 #endif
   1018   int *guard;
   1019   if (NULL_PTR (sem_wait))
   1020     init_thread_intf ();
   1021   if (CHCK_NREENTRANCE (guard))
   1022     {
   1023 #if ARCH(Intel) && WSIZE(32)
   1024       return (real_sem_wait) (sp);
   1025 #else
   1026       return CALL_REAL (sem_wait)(sp);
   1027 #endif
   1028     }
   1029   PUSH_REENTRANCE (guard);
   1030   hrtime_t reqt = gethrtime ();
   1031   int ret = -1;
   1032 #if ARCH(Intel) && WSIZE(32)
   1033   ret = (real_sem_wait) (sp);
   1034 #else
   1035   ret = CALL_REAL (sem_wait)(sp);
   1036 #endif
   1037   if (RECHCK_NREENTRANCE (guard))
   1038     {
   1039       POP_REENTRANCE (guard);
   1040       return ret;
   1041     }
   1042   hrtime_t grnt = gethrtime ();
   1043   if (grnt - reqt >= sync_threshold)
   1044     {
   1045       Sync_packet spacket;
   1046       collector_memset (&spacket, 0, sizeof ( Sync_packet));
   1047       spacket.comm.tsize = sizeof ( Sync_packet);
   1048       spacket.comm.tstamp = grnt;
   1049       spacket.requested = reqt;
   1050       spacket.objp = (intptr_t) sp;
   1051 
   1052 #if ARCH(Intel) && WSIZE(32)
   1053       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK_ARG, &spacket);
   1054 #else
   1055       spacket.comm.frinfo = collector_interface->getFrameInfo (sync_hndl, spacket.comm.tstamp, FRINFO_FROM_STACK, &spacket);
   1056 #endif
   1057       collector_interface->writeDataRecord (sync_hndl, (Common_packet*) & spacket);
   1058     }
   1059   POP_REENTRANCE (guard);
   1060   return ret;
   1061 }
   1062