xref: /netbsd-src/external/gpl3/binutils.old/dist/gprofng/libcollector/synctrace.c (revision c42dbd0ed2e61fe6eda8590caa852ccf34719964)
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
collector_memset(void * s,int c,size_t n)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
__collector_module_init(CollectorInterface * _collector_interface)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
open_experiment(const char * exp)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
start_data_collection(void)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
stop_data_collection(void)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
close_experiment(void)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
detach_experiment(void)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
sync_calibrate()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
init_thread_intf()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
__collector_jsync_begin()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
__collector_jsync_end(hrtime_t reqt,void * object)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
pthread_mutex_lock(pthread_mutex_t * mp)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
__collector_pthread_cond_wait_2_3_2(pthread_cond_t * cond,pthread_mutex_t * mutex)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
__collector_pthread_cond_wait_2_0(pthread_cond_t * cond,pthread_mutex_t * mutex)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
__collector_pthread_cond_wait_2_2_5(pthread_cond_t * cond,pthread_mutex_t * mutex)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
__collector_pthread_cond_wait_2_2(pthread_cond_t * cond,pthread_mutex_t * mutex)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
__collector_pthread_cond_wait_symver(int (real_pthread_cond_wait)(),pthread_cond_t * cond,pthread_mutex_t * mutex)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
__collector_pthread_cond_timedwait_2_3_2(pthread_cond_t * cond,pthread_mutex_t * mutex,const struct timespec * abstime)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
__collector_pthread_cond_timedwait_2_0(pthread_cond_t * cond,pthread_mutex_t * mutex,const struct timespec * abstime)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
__collector_pthread_cond_timedwait_2_2_5(pthread_cond_t * cond,pthread_mutex_t * mutex,const struct timespec * abstime)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
__collector_pthread_cond_timedwait_2_2(pthread_cond_t * cond,pthread_mutex_t * mutex,const struct timespec * abstime)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
__collector_pthread_cond_timedwait_symver(int (real_pthread_cond_timedwait)(),pthread_cond_t * cond,pthread_mutex_t * mutex,const struct timespec * abstime)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
pthread_join(pthread_t target_thread,void ** status)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
__collector_sem_wait_2_1(sem_t * sp)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
__collector_sem_wait_2_0(sem_t * sp)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
__collector_sem_wait_symver(int (real_sem_wait)(),sem_t * sp)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