synctrace.c 35 KB

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