hwprofile.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  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. /* Hardware counter profiling */
  17. #include "config.h"
  18. #include <alloca.h>
  19. #include <dlfcn.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <unistd.h>
  23. #include <errno.h>
  24. #include <sys/syscall.h>
  25. #include <signal.h>
  26. #include <ucontext.h>
  27. #include "gp-defs.h"
  28. #define _STRING_H 1 /* XXX MEZ: temporary workaround */
  29. #include "hwcdrv.h"
  30. #include "collector_module.h"
  31. #include "gp-experiment.h"
  32. #include "libcol_util.h"
  33. #include "hwprofile.h"
  34. #include "ABS.h"
  35. #include "tsd.h"
  36. /* TprintfT(<level>,...) definitions. Adjust per module as needed */
  37. #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings
  38. #define DBG_LT1 1 // for configuration details, warnings
  39. #define DBG_LT2 2
  40. #define DBG_LT3 3
  41. #define DBG_LT4 4
  42. #define DBG_LT5 5
  43. #define SD_OFF 0 /* before start or after close she shut down process */
  44. #define SD_PENDING 1 /* before running real_detach_experiment() */
  45. #define SD_COMPLETE 2 /* after running real_detach_experiment() */
  46. static int init_interface (CollectorInterface*);
  47. static int open_experiment (const char *);
  48. static int start_data_collection (void);
  49. static int stop_data_collection (void);
  50. static int close_experiment (void);
  51. static int detach_experiment (void);
  52. static int real_detach_experiment (void);
  53. static ModuleInterface module_interface ={
  54. SP_HWCNTR_FILE, /* description */
  55. init_interface, /* initInterface */
  56. open_experiment, /* openExperiment */
  57. start_data_collection, /* startDataCollection */
  58. stop_data_collection, /* stopDataCollection */
  59. close_experiment, /* closeExperiment */
  60. detach_experiment /* detachExperiment (fork child) */
  61. };
  62. static CollectorInterface *collector_interface = NULL;
  63. /*---------------------------------------------------------------------------*/
  64. /* compile options and workarounds */
  65. /* Solaris: We set ITIMER_REALPROF to ensure that counters get started on
  66. * LWPs that existed before the collector initialization.
  67. *
  68. * In addition, if the appropriate #define's are set, we check for:
  69. * lost-hw-overflow -- the HW counters rollover, but the overflow
  70. * interrupt is not generated (counters keep running)
  71. * lost-sigemt -- the interrupt is received by the kernel,
  72. * which stops the counters, but the kernel fails
  73. * to deliver the signal.
  74. */
  75. /*---------------------------------------------------------------------------*/
  76. /* typedefs */
  77. typedef enum {
  78. HWCMODE_OFF, /* before start or after close */
  79. HWCMODE_SUSPEND, /* stop_data_collection called */
  80. HWCMODE_ACTIVE, /* counters are defined and after start_data_collection() */
  81. HWCMODE_ABORT /* fatal error occured. Log a message, stop recording */
  82. } hwc_mode_t;
  83. /*---------------------------------------------------------------------------*/
  84. /* prototypes */
  85. static void init_ucontexts (void);
  86. static int hwc_initialize_handlers (void);
  87. static void collector_record_counter (ucontext_t*,
  88. int timecvt,
  89. ABST_type, hrtime_t,
  90. unsigned, uint64_t);
  91. static void collector_hwc_ABORT (int errnum, const char *msg);
  92. static void hwclogwrite0 ();
  93. static void hwclogwrite (Hwcentry *);
  94. static void set_hwc_mode (hwc_mode_t);
  95. static void collector_sigemt_handler (int sig, siginfo_t *si, void *puc);
  96. /*---------------------------------------------------------------------------*/
  97. /* static variables */
  98. /* --- user counter selections and options */
  99. static int hwcdef_has_memspace; /* true to indicate use of extened packets */
  100. static unsigned hwcdef_cnt; /* number of *active* hardware counters */
  101. static unsigned hwcdef_num_sampling_ctrdefs; /* ctrs that use sampling */
  102. static unsigned hwcdef_num_overflow_ctrdefs; /* ctrs that use overflow */
  103. static Hwcentry **hwcdef; /* HWC definitions */
  104. static int cpcN_cpuver = CPUVER_UNDEFINED;
  105. static int hwcdrv_inited; /* Don't call hwcdrv_init() in fork_child */
  106. static hwcdrv_api_t *hwc_driver = NULL;
  107. static unsigned hwprofile_tsd_key = COLLECTOR_TSD_INVALID_KEY;
  108. static int hwprofile_tsd_sz = 0;
  109. static volatile hwc_mode_t hwc_mode = HWCMODE_OFF;
  110. static volatile unsigned int nthreads_in_sighandler = 0;
  111. static volatile unsigned int sd_state = SD_OFF;
  112. /* --- experiment logging state */
  113. static CollectorModule expr_hndl = COLLECTOR_MODULE_ERR;
  114. static ucontext_t expr_dummy_uc; // used for hacked "collector" frames
  115. static ucontext_t expr_out_of_range_uc; // used for "out-of-range" frames
  116. static ucontext_t expr_frozen_uc; // used for "frozen" frames
  117. static ucontext_t expr_nopc_uc; // used for not-program-related frames
  118. static ucontext_t expr_lostcounts_uc; // used for lost_counts frames
  119. /* --- signal handler state */
  120. static struct sigaction old_sigemt_handler; //overwritten in fork-child
  121. /*---------------------------------------------------------------------------*/
  122. /* macros */
  123. #define COUNTERS_ENABLED() (hwcdef_cnt)
  124. #define gethrtime collector_interface->getHiResTime
  125. #ifdef DEBUG
  126. #define Tprintf(...) if (collector_interface) collector_interface->writeDebugInfo( 0, __VA_ARGS__ )
  127. #define TprintfT(...) if (collector_interface) collector_interface->writeDebugInfo( 1, __VA_ARGS__ )
  128. #else
  129. #define Tprintf(...)
  130. #define TprintfT(...)
  131. #endif
  132. /*---------------------------------------------------------------------------*/
  133. /* Initialization routines */
  134. static hwcdrv_api_t *
  135. get_hwc_driver ()
  136. {
  137. if (hwc_driver == NULL)
  138. hwc_driver = __collector_get_hwcdrv ();
  139. return hwc_driver;
  140. }
  141. static void init_module () __attribute__ ((constructor));
  142. static void
  143. init_module ()
  144. {
  145. __collector_dlsym_guard = 1;
  146. RegModuleFunc reg_module = (RegModuleFunc) dlsym (RTLD_DEFAULT, "__collector_register_module");
  147. __collector_dlsym_guard = 0;
  148. if (reg_module == NULL)
  149. {
  150. TprintfT (0, "hwprofile: init_module FAILED - reg_module = NULL\n");
  151. return;
  152. }
  153. expr_hndl = reg_module (&module_interface);
  154. if (expr_hndl == COLLECTOR_MODULE_ERR)
  155. {
  156. TprintfT (0, "hwprofile: ERROR: handle not created.\n");
  157. if (collector_interface)
  158. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">data handle not created</event>\n",
  159. SP_JCMD_CERROR, COL_ERROR_HWCINIT);
  160. }
  161. }
  162. static int
  163. init_interface (CollectorInterface *_collector_interface)
  164. {
  165. collector_interface = _collector_interface;
  166. return COL_ERROR_NONE;
  167. }
  168. static void *
  169. hwprofile_get_tsd ()
  170. {
  171. return collector_interface->getKey (hwprofile_tsd_key);
  172. }
  173. static int
  174. open_experiment (const char *exp)
  175. {
  176. if (collector_interface == NULL)
  177. {
  178. TprintfT (0, "hwprofile: ERROR: collector_interface is null.\n");
  179. return COL_ERROR_HWCINIT;
  180. }
  181. const char *params = collector_interface->getParams ();
  182. while (params)
  183. {
  184. if (__collector_strStartWith (params, "h:*") == 0)
  185. {
  186. /* HWC counters set by default */
  187. collector_interface->writeLog ("<%s %s=\"1\"/>\n",
  188. SP_TAG_SETTING, SP_JCMD_HWC_DEFAULT);
  189. params += 3;
  190. break;
  191. }
  192. else if (__collector_strStartWith (params, "h:") == 0)
  193. {
  194. params += 2;
  195. break;
  196. }
  197. params = CALL_UTIL (strchr)(params, ';');
  198. if (params)
  199. params++;
  200. }
  201. if (params == NULL) /* HWC profiling not specified */
  202. return COL_ERROR_HWCINIT;
  203. char *s = CALL_UTIL (strchr)(params, (int) ';');
  204. int sz = s ? s - params : CALL_UTIL (strlen)(params);
  205. char *defstring = (char*) alloca (sz + 1);
  206. CALL_UTIL (strlcpy)(defstring, params, sz + 1);
  207. TprintfT (0, "hwprofile: open_experiment %s -- %s\n", exp, defstring);
  208. int err = COL_ERROR_NONE;
  209. /* init counter library */
  210. if (!hwcdrv_inited)
  211. { /* do not call hwcdrv_init() from fork-child */
  212. hwcdrv_inited = 1;
  213. get_hwc_driver ();
  214. if (hwc_driver->hwcdrv_init (collector_hwc_ABORT, &hwprofile_tsd_sz) == 0)
  215. {
  216. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
  217. SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
  218. TprintfT (0, "hwprofile: ERROR: hwcfuncs_init() failed\n");
  219. return COL_ERROR_HWCINIT;
  220. }
  221. if (hwc_driver->hwcdrv_enable_mt (hwprofile_get_tsd))
  222. {
  223. // It is OK to call hwcdrv_enable_mt() before tsd key is created
  224. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
  225. SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
  226. TprintfT (0, "hwprofile: ERROR: hwcdrv_enable_mt() failed\n");
  227. return COL_ERROR_HWCINIT;
  228. }
  229. hwc_driver->hwcdrv_get_info (&cpcN_cpuver, NULL, NULL, NULL, NULL);
  230. if (cpcN_cpuver < 0)
  231. {
  232. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
  233. SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
  234. TprintfT (0, "hwprofile: ERROR: hwcdrv_get_info() failed\n");
  235. return COL_ERROR_HWCINIT;
  236. }
  237. }
  238. if (hwprofile_tsd_sz)
  239. {
  240. hwprofile_tsd_key = collector_interface->createKey (hwprofile_tsd_sz, NULL, NULL);
  241. if (hwprofile_tsd_key == COLLECTOR_TSD_INVALID_KEY)
  242. {
  243. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
  244. SP_JCMD_CERROR, COL_ERROR_HWCINIT, defstring);
  245. TprintfT (0, "hwprofile: ERROR: TSD createKey failed\n");
  246. return COL_ERROR_HWCINIT;
  247. }
  248. }
  249. hwcdef_cnt = 0;
  250. hwcdef_has_memspace = 0;
  251. /* create counters based on hwcdef[] */
  252. err = __collector_hwcfuncs_bind_descriptor (defstring);
  253. if (err)
  254. {
  255. err = err == HWCFUNCS_ERROR_HWCINIT ? COL_ERROR_HWCINIT : COL_ERROR_HWCARGS;
  256. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s</event>\n",
  257. SP_JCMD_CERROR, err, defstring);
  258. TprintfT (0, "hwprofile: ERROR: open_experiment() failed, RC=%d \n", err);
  259. return err;
  260. }
  261. /* generate an array of counter structures for each requested counter */
  262. hwcdef = __collector_hwcfuncs_get_ctrs (&hwcdef_cnt);
  263. hwcdef_num_sampling_ctrdefs = hwcdef_num_overflow_ctrdefs = 0;
  264. int idx;
  265. for (idx = 0; idx < hwcdef_cnt; idx++)
  266. {
  267. if (HWCENTRY_USES_SAMPLING (hwcdef[idx]))
  268. {
  269. hwcdef_num_sampling_ctrdefs++;
  270. }
  271. else
  272. {
  273. hwcdef_num_overflow_ctrdefs++;
  274. }
  275. }
  276. init_ucontexts ();
  277. /* initialize the SIGEMT handler, and the periodic HWC checker */
  278. err = hwc_initialize_handlers ();
  279. if (err != COL_ERROR_NONE)
  280. {
  281. hwcdef_cnt = 0;
  282. TprintfT (0, "hwprofile: ERROR: open_experiment() failed, RC=%d \n", err);
  283. /* log written by hwc_initialize_handlers() */
  284. return err;
  285. }
  286. for (idx = 0; idx < hwcdef_cnt; idx++)
  287. if (ABST_BACKTRACK_ENABLED (hwcdef[idx]->memop))
  288. hwcdef_has_memspace = 1;
  289. /* record the hwc definitions in the log, based on the counter array */
  290. hwclogwrite0 ();
  291. for (idx = 0; idx < hwcdef_cnt; idx++)
  292. hwclogwrite (hwcdef[idx]);
  293. return COL_ERROR_NONE;
  294. }
  295. int
  296. __collector_ext_hwc_lwp_init ()
  297. {
  298. return get_hwc_driver ()->hwcdrv_lwp_init ();
  299. }
  300. void
  301. __collector_ext_hwc_lwp_fini ()
  302. {
  303. get_hwc_driver ()->hwcdrv_lwp_fini ();
  304. }
  305. int
  306. __collector_ext_hwc_lwp_suspend ()
  307. {
  308. return get_hwc_driver ()->hwcdrv_lwp_suspend ();
  309. }
  310. int
  311. __collector_ext_hwc_lwp_resume ()
  312. {
  313. return get_hwc_driver ()->hwcdrv_lwp_resume ();
  314. }
  315. /* Dummy routine, used to provide a context for non-program related profiles */
  316. void
  317. __collector_not_program_related () { }
  318. /* Dummy routine, used to provide a context for lost counts (perf_events) */
  319. void
  320. __collector_hwc_samples_lost () { }
  321. /* Dummy routine, used to provide a context */
  322. void
  323. __collector_hwcs_frozen () { }
  324. /* Dummy routine, used to provide a context */
  325. void
  326. __collector_hwcs_out_of_range () { }
  327. /* initialize some structures */
  328. static void
  329. init_ucontexts (void)
  330. {
  331. /* initialize dummy context for "collector" frames */
  332. getcontext (&expr_dummy_uc);
  333. SETFUNCTIONCONTEXT (&expr_dummy_uc, NULL);
  334. /* initialize dummy context for "out-of-range" frames */
  335. getcontext (&expr_out_of_range_uc);
  336. SETFUNCTIONCONTEXT (&expr_out_of_range_uc, &__collector_hwcs_out_of_range);
  337. /* initialize dummy context for "frozen" frames */
  338. getcontext (&expr_frozen_uc);
  339. SETFUNCTIONCONTEXT (&expr_frozen_uc, &__collector_hwcs_frozen);
  340. /* initialize dummy context for non-program-related frames */
  341. getcontext (&expr_nopc_uc);
  342. SETFUNCTIONCONTEXT (&expr_nopc_uc, &__collector_not_program_related);
  343. /* initialize dummy context for lost-counts-related frames */
  344. getcontext (&expr_lostcounts_uc);
  345. SETFUNCTIONCONTEXT (&expr_lostcounts_uc, &__collector_hwc_samples_lost);
  346. }
  347. /* initialize the signal handler */
  348. static int
  349. hwc_initialize_handlers (void)
  350. {
  351. /* install the signal handler for SIGEMT */
  352. struct sigaction oact;
  353. if (__collector_sigaction (HWCFUNCS_SIGNAL, NULL, &oact) != 0)
  354. {
  355. TprintfT (0, "hwc_initialize_handlers(): ERROR: hwc_initialize_handlers(): __collector_sigaction() failed to get oact\n");
  356. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">old handler could not be determined</event>\n", SP_JCMD_CERROR, COL_ERROR_HWCINIT);
  357. return COL_ERROR_HWCINIT;
  358. }
  359. if (oact.sa_sigaction == collector_sigemt_handler)
  360. {
  361. /* signal handler is already in place; we are probably in a fork-child */
  362. TprintfT (DBG_LT1, "hwc_initialize_handlers(): hwc_initialize_handlers() collector_sigemt_handler already installed\n");
  363. }
  364. else
  365. {
  366. /* set our signal handler */
  367. struct sigaction c_act;
  368. CALL_UTIL (memset)(&c_act, 0, sizeof c_act);
  369. sigemptyset (&c_act.sa_mask);
  370. sigaddset (&c_act.sa_mask, SIGPROF); /* block SIGPROF delivery in handler */
  371. /* XXXX should probably also block sample_sig & pause_sig */
  372. c_act.sa_sigaction = collector_sigemt_handler; /* note: used to set sa_handler instead */
  373. c_act.sa_flags = SA_RESTART | SA_SIGINFO;
  374. if (__collector_sigaction (HWCFUNCS_SIGNAL, &c_act, &old_sigemt_handler) != 0)
  375. {
  376. TprintfT (0, "hwc_initialize_handlers(): ERROR: hwc_initialize_handlers(): __collector_sigaction() failed to set cact\n");
  377. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">event handler could not be installed</event>\n", SP_JCMD_CERROR, COL_ERROR_HWCINIT);
  378. return COL_ERROR_HWCINIT;
  379. }
  380. }
  381. return COL_ERROR_NONE;
  382. }
  383. static int
  384. close_experiment (void)
  385. {
  386. /* note: stop_data_collection() should have already been called by
  387. * collector_close_experiment()
  388. */
  389. if (!COUNTERS_ENABLED ())
  390. return COL_ERROR_NONE;
  391. detach_experiment ();
  392. /* cpc or libperfctr may still generate sigemts for a while */
  393. /* verify that SIGEMT handler is still installed */
  394. /* (still required with sigaction interposition and management,
  395. since interposition is not done for attach experiments)
  396. */
  397. struct sigaction curr;
  398. if (__collector_sigaction (HWCFUNCS_SIGNAL, NULL, &curr) == -1)
  399. {
  400. TprintfT (0, "hwprofile close_experiment: ERROR: hwc sigaction check failed: errno=%d\n", errno);
  401. }
  402. else if (curr.sa_sigaction != collector_sigemt_handler)
  403. {
  404. TprintfT (DBG_LT1, "hwprofile close_experiment: WARNING: collector sigemt handler replaced by 0x%p!\n", curr.sa_handler);
  405. (void) collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">0x%p</event>\n",
  406. SP_JCMD_CWARN, COL_WARN_SIGEMT, curr.sa_handler);
  407. }
  408. else
  409. TprintfT (DBG_LT1, "hwprofile close_experiment: collector sigemt handler integrity verified!\n");
  410. TprintfT (0, "hwprofile: close_experiment\n");
  411. return 0;
  412. }
  413. static int
  414. detach_experiment (void)
  415. {
  416. /* fork child. Clean up state but don't write to experiment */
  417. /* note: stop_data_collection() has already been called by the fork_prologue */
  418. // detach_experiment() can be called asynchronously
  419. // from anywhere, even from within a sigemt handler
  420. // via DBX detach.
  421. // Important: stop_data_collection() _must_ be called
  422. // before detach_experiment() is called.
  423. if (!COUNTERS_ENABLED ())
  424. return COL_ERROR_NONE;
  425. TprintfT (0, "hwprofile: detach_experiment()\n");
  426. if (SD_OFF != __collector_cas_32 (&sd_state, SD_OFF, SD_PENDING))
  427. return 0;
  428. // one and only one call should ever make it here here.
  429. if (hwc_mode == HWCMODE_ACTIVE)
  430. {
  431. TprintfT (0, "hwprofile: ERROR: stop_data_collection() should have been called before detach_experiment()\n");
  432. stop_data_collection ();
  433. }
  434. // Assumption: The only calls to sigemt_handler
  435. // we should see at this point
  436. // will be those that were already in-flight before
  437. // stop_new_sigemts() was called.
  438. if (nthreads_in_sighandler > 0)
  439. {
  440. // sigemt handlers should see
  441. // SD_PENDING and should call real_detach_experiment()
  442. // when the last handler is finished.
  443. TprintfT (DBG_LT1, "hwprofile: detach in the middle of signal handler.\n");
  444. return 0;
  445. }
  446. // If we get here, there should be no remaining
  447. // sigemt handlers. However, we don't really know
  448. // if there were ever any in flight, so call
  449. // real_detach_experiment() here:
  450. return real_detach_experiment (); // multiple calls to this OK
  451. }
  452. static int
  453. real_detach_experiment (void)
  454. {
  455. /*multiple calls to this routine are OK.*/
  456. if (SD_PENDING != __collector_cas_32 (&sd_state, SD_PENDING, SD_COMPLETE))
  457. return 0;
  458. // only the first caller to this routine should get here.
  459. hwcdef_cnt = 0; /* since now deinstalled */
  460. hwcdef = NULL;
  461. set_hwc_mode (HWCMODE_OFF);
  462. if (SD_COMPLETE != __collector_cas_32 (&sd_state, SD_COMPLETE, SD_OFF))
  463. {
  464. TprintfT (0, "hwprofile: ERROR: unexpected sd_state in real_detach_experiment()\n");
  465. sd_state = SD_OFF;
  466. }
  467. hwprofile_tsd_key = COLLECTOR_TSD_INVALID_KEY;
  468. TprintfT (DBG_LT0, "hwprofile: real_detach_experiment() detached from experiment.\n");
  469. return 0;
  470. }
  471. /*---------------------------------------------------------------------------*/
  472. /* Record counter values. */
  473. /* <value> should already be adjusted to be "zero-based" (counting up from 0).*/
  474. static void
  475. collector_record_counter_internal (ucontext_t *ucp, int timecvt,
  476. ABST_type ABS_memop, hrtime_t time,
  477. unsigned tag, uint64_t value, uint64_t pc,
  478. uint64_t va, uint64_t latency,
  479. uint64_t data_source)
  480. {
  481. MHwcntr_packet pckt;
  482. CALL_UTIL (memset)(&pckt, 0, sizeof ( MHwcntr_packet));
  483. pckt.comm.tstamp = time;
  484. pckt.tag = tag;
  485. if (timecvt > 1)
  486. {
  487. if (HWCVAL_HAS_ERR (value))
  488. {
  489. value = HWCVAL_CLR_ERR (value);
  490. value *= timecvt;
  491. value = HWCVAL_SET_ERR (value);
  492. }
  493. else
  494. value *= timecvt;
  495. }
  496. pckt.interval = value;
  497. pckt.comm.type = HW_PCKT;
  498. pckt.comm.tsize = sizeof (Hwcntr_packet);
  499. TprintfT (DBG_LT4, "hwprofile: %llu sample %lld tag %u recorded\n",
  500. (unsigned long long) time, (long long) value, tag);
  501. if (ABS_memop == ABST_NOPC)
  502. ucp = &expr_nopc_uc;
  503. pckt.comm.frinfo = collector_interface->getFrameInfo (expr_hndl, pckt.comm.tstamp, FRINFO_FROM_UC, ucp);
  504. collector_interface->writeDataRecord (expr_hndl, (Common_packet*) & pckt);
  505. }
  506. static void
  507. collector_record_counter (ucontext_t *ucp, int timecvt, ABST_type ABS_memop,
  508. hrtime_t time, unsigned tag, uint64_t value)
  509. {
  510. collector_record_counter_internal (ucp, timecvt, ABS_memop, time, tag, value,
  511. HWCFUNCS_INVALID_U64, HWCFUNCS_INVALID_U64,
  512. HWCFUNCS_INVALID_U64, HWCFUNCS_INVALID_U64);
  513. }
  514. /*---------------------------------------------------------------------------*/
  515. /* Signal handlers */
  516. /* SIGEMT -- relayed from libcpc, when the counter overflows */
  517. /* Generates the appropriate event or events, and resets the counters */
  518. static void
  519. collector_sigemt_handler (int sig, siginfo_t *si, void *puc)
  520. {
  521. int rc;
  522. hwc_event_t sample, lost_samples;
  523. if (sig != HWCFUNCS_SIGNAL)
  524. {
  525. TprintfT (0, "hwprofile: ERROR: %s: unexpected signal %d\n", "collector_sigemt_handler", sig);
  526. return;
  527. }
  528. if (!COUNTERS_ENABLED ())
  529. { /* apparently deinstalled */
  530. TprintfT (0, "hwprofile: WARNING: SIGEMT detected after close_experiment()\n");
  531. /* kills future sigemts since hwcdrv_sighlr_restart() not called */
  532. return;
  533. }
  534. /* Typically, we expect HWC overflow signals to come from the kernel: si_code > 0.
  535. * On Linux, however, dbx might be "forwarding" a signal using tkill()/tgkill().
  536. * For more information on what si_code values can be expected on Linux, check:
  537. * cmn_components/Collector_Interface/hwcdrv_pcl.c hwcdrv_overflow()
  538. * cmn_components/Collector_Interface/hwcdrv_perfctr.c hdrv_perfctr_overflow()
  539. */
  540. if (puc == NULL || si == NULL || (si->si_code <= 0 && si->si_code != SI_TKILL))
  541. {
  542. TprintfT (DBG_LT3, "hwprofile: collector_sigemt_handler SIG%02d\n", sig);
  543. if (old_sigemt_handler.sa_handler == SIG_DFL)
  544. __collector_SIGDFL_handler (HWCFUNCS_SIGNAL);
  545. else if (old_sigemt_handler.sa_handler != SIG_IGN &&
  546. old_sigemt_handler.sa_sigaction != &collector_sigemt_handler)
  547. {
  548. /* Redirect the signal to the previous signal handler */
  549. (old_sigemt_handler.sa_sigaction)(sig, si, puc);
  550. TprintfT (DBG_LT1, "hwprofile: collector_sigemt_handler SIG%02d redirected to original handler\n", sig);
  551. }
  552. return;
  553. }
  554. rc = get_hwc_driver ()->hwcdrv_overflow (si, &sample, &lost_samples);
  555. if (rc)
  556. {
  557. /* hwcdrv_sighlr_restart() should not be called */
  558. TprintfT (0, "hwprofile: ERROR: collector_sigemt_handler: hwcdrv_overflow() failed\n");
  559. return;
  560. }
  561. if (hwc_mode == HWCMODE_ACTIVE)
  562. {
  563. /* record the event only if counters are active */
  564. /* The following has been copied from dispatcher.c */
  565. #if ARCH(SPARC)
  566. /* 23340823 signal handler third argument should point to a ucontext_t */
  567. /* Convert sigcontext to ucontext_t on sparc-Linux */
  568. ucontext_t uctxmem;
  569. struct sigcontext *sctx = (struct sigcontext*) puc;
  570. ucontext_t *uctx = &uctxmem;
  571. uctx->uc_link = NULL;
  572. #if WSIZE(32)
  573. uctx->uc_mcontext.gregs[REG_PC] = sctx->si_regs.pc;
  574. __collector_memcpy (&uctx->uc_mcontext.gregs[3],
  575. sctx->si_regs.u_regs,
  576. sizeof (sctx->si_regs.u_regs));
  577. #else
  578. uctx->uc_mcontext.mc_gregs[MC_PC] = sctx->sigc_regs.tpc;
  579. __collector_memcpy (&uctx->uc_mcontext.mc_gregs[3],
  580. sctx->sigc_regs.u_regs,
  581. sizeof (sctx->sigc_regs.u_regs));
  582. #endif /* WSIZE() */
  583. #else
  584. ucontext_t *uctx = (ucontext_t*) puc;
  585. #endif /* ARCH() */
  586. for (int ii = 0; ii < hwcdef_cnt; ii++)
  587. if (lost_samples.ce_pic[ii])
  588. collector_record_counter (&expr_lostcounts_uc, hwcdef[ii]->timecvt,
  589. hwcdef[ii]->memop, lost_samples.ce_hrt,
  590. hwcdef[ii]->sort_order, lost_samples.ce_pic[ii]);
  591. for (int ii = 0; ii < hwcdef_cnt; ii++)
  592. if (sample.ce_pic[ii])
  593. collector_record_counter (uctx, hwcdef[ii]->timecvt,
  594. hwcdef[ii]->memop, sample.ce_hrt,
  595. hwcdef[ii]->sort_order, sample.ce_pic[ii]);
  596. }
  597. rc = get_hwc_driver ()->hwcdrv_sighlr_restart (NULL);
  598. }
  599. /* SIGPROF -- not installed as handler, but
  600. * __collector_ext_hwc_check: called by (SIGPROF) dispatcher.
  601. * Periodical check of integrity of HWC count/signal mechanism,
  602. * as required for various chip/system bugs/workarounds.
  603. */
  604. void
  605. __collector_ext_hwc_check (siginfo_t *info, ucontext_t *vcontext) { }
  606. /*---------------------------------------------------------------------------*/
  607. int
  608. collector_sigemt_sigaction (const struct sigaction *nact,
  609. struct sigaction *oact)
  610. {
  611. struct sigaction oact_check;
  612. /* Error codes and messages that refer to HWC are tricky.
  613. * E.g., HWC profiling might not even be on; we might
  614. * encounter an error here simply because the user is
  615. * trying to set a handler for a signal that happens to
  616. * be HWCFUNCS_SIGNAL, which we aren't even using.
  617. */
  618. if (__collector_sigaction (HWCFUNCS_SIGNAL, NULL, &oact_check) != 0)
  619. {
  620. TprintfT (0, "hwprofile: ERROR: collector_sigemt_sigaction(): request to set handler for signal %d, but check on existing handler failed\n", HWCFUNCS_SIGNAL);
  621. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">old handler for signal %d could not be determined</event>\n", SP_JCMD_CERROR, COL_ERROR_HWCINIT, HWCFUNCS_SIGNAL);
  622. return COL_ERROR_HWCINIT;
  623. }
  624. if (oact_check.sa_sigaction == collector_sigemt_handler)
  625. {
  626. /* dispatcher is in place, so nact/oact apply to old_sigemt_handler */
  627. if (oact != NULL)
  628. {
  629. oact->sa_handler = old_sigemt_handler.sa_handler;
  630. oact->sa_mask = old_sigemt_handler.sa_mask;
  631. oact->sa_flags = old_sigemt_handler.sa_flags;
  632. }
  633. if (nact != NULL)
  634. {
  635. old_sigemt_handler.sa_handler = nact->sa_handler;
  636. old_sigemt_handler.sa_mask = nact->sa_mask;
  637. old_sigemt_handler.sa_flags = nact->sa_flags;
  638. }
  639. return COL_ERROR_NONE;
  640. }
  641. else /* no dispatcher in place, so just act like normal sigaction() */
  642. return __collector_sigaction (HWCFUNCS_SIGNAL, nact, oact);
  643. }
  644. static void
  645. collector_hwc_ABORT (int errnum, const char *msg)
  646. {
  647. TprintfT (0, "hwprofile: collector_hwc_ABORT: [%d] %s\n", errnum, msg);
  648. if (hwc_mode == HWCMODE_ABORT) /* HWC collection already aborted! */
  649. return;
  650. set_hwc_mode (HWCMODE_ABORT); /* set global flag to disable handlers and indicate abort */
  651. /* Write the error message to the experiment */
  652. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s: errno=%d</event>\n",
  653. SP_JCMD_CERROR, COL_ERROR_HWCFAIL, msg, errnum);
  654. #ifdef REAL_DEBUG
  655. abort ();
  656. #else
  657. TprintfT (0, "hwprofile: Continuing without HWC collection...\n");
  658. #endif
  659. }
  660. static int
  661. start_data_collection (void)
  662. {
  663. hwc_mode_t old_mode = hwc_mode;
  664. if (!COUNTERS_ENABLED ())
  665. return COL_ERROR_NONE;
  666. TprintfT (0, "hwprofile: start_data_collection (hwc_mode=%d)\n", old_mode);
  667. switch (old_mode)
  668. {
  669. case HWCMODE_OFF:
  670. if (get_hwc_driver ()->hwcdrv_start ())
  671. {
  672. TprintfT (0, "hwprofile: ERROR: start_data_collection() failed in hwcdrv_start()\n");
  673. collector_interface->writeLog ("<event kind=\"%s\" id=\"%d\">%s: errno=%d</event>\n",
  674. SP_JCMD_CERROR, COL_ERROR_HWCFAIL,
  675. "start_data_collection()", errno);
  676. return COL_ERROR_HWCINIT;
  677. }
  678. set_hwc_mode (HWCMODE_ACTIVE); /* start handling events on signals */
  679. break;
  680. case HWCMODE_SUSPEND:
  681. if (get_hwc_driver ()->hwcdrv_lwp_resume ())
  682. {
  683. TprintfT (0, "hwprofile: ERROR: start_data_collection() failed in hwcdrv_lwp_resume()\n");
  684. /* ignore errors from lwp_resume() */
  685. }
  686. set_hwc_mode (HWCMODE_ACTIVE); /* start handling events on signals */
  687. break;
  688. default:
  689. TprintfT (0, "hwprofile: ERROR: start_data_collection() invalid mode\n");
  690. return COL_ERROR_HWCINIT;
  691. }
  692. return COL_ERROR_NONE;
  693. }
  694. static int
  695. stop_data_collection (void)
  696. {
  697. hwc_mode_t old_mode = hwc_mode;
  698. if (!COUNTERS_ENABLED ())
  699. return COL_ERROR_NONE;
  700. TprintfT (0, "hwprofile: stop_data_collection (hwc_mode=%d)\n", old_mode);
  701. switch (old_mode)
  702. {
  703. case HWCMODE_SUSPEND:
  704. return COL_ERROR_NONE;
  705. case HWCMODE_ACTIVE:
  706. set_hwc_mode (HWCMODE_SUSPEND); /* stop handling signals */
  707. break;
  708. default:
  709. /* Don't change the mode, but attempt to suspend anyway... */
  710. break;
  711. }
  712. if (get_hwc_driver ()->hwcdrv_lwp_suspend ())
  713. /* ignore errors from lwp_suspend() */
  714. TprintfT (0, "hwprofile: ERROR: stop_data_collection() failed in hwcdrv_lwp_suspend()\n");
  715. /*
  716. * hwcdrv_lwp_suspend() cannot guarantee that all SIGEMTs will stop
  717. * but hwc_mode will prevent logging and counters will overflow once
  718. * then stay frozen.
  719. */
  720. /* There may still be pending SIGEMTs so don't reset the SIG_DFL handler.
  721. */
  722. /* see comment in dispatcher.c */
  723. /* ret = __collector_sigaction( SIGEMT, &old_sigemt_handler, NULL ); */
  724. return COL_ERROR_NONE;
  725. }
  726. /*---------------------------------------------------------------------------*/
  727. /* utilities */
  728. static void
  729. set_hwc_mode (hwc_mode_t md)
  730. {
  731. TprintfT (DBG_LT1, "hwprofile: set_hwc_mode(%d)\n", md);
  732. hwc_mode = md;
  733. }
  734. int
  735. __collector_ext_hwc_active ()
  736. {
  737. return (hwc_mode == HWCMODE_ACTIVE);
  738. }
  739. static void
  740. hwclogwrite0 ()
  741. {
  742. collector_interface->writeLog ("<profdata fname=\"%s\"/>\n",
  743. module_interface.description);
  744. /* Record Hwcntr_packet description */
  745. Hwcntr_packet *pp = NULL;
  746. collector_interface->writeLog ("<profpckt kind=\"%d\" uname=\"" STXT ("Hardware counter profiling data") "\">\n", HW_PCKT);
  747. collector_interface->writeLog (" <field name=\"LWPID\" uname=\"" STXT ("Lightweight process id") "\" offset=\"%d\" type=\"%s\"/>\n",
  748. &pp->comm.lwp_id, sizeof (pp->comm.lwp_id) == 4 ? "INT32" : "INT64");
  749. collector_interface->writeLog (" <field name=\"THRID\" uname=\"" STXT ("Thread number") "\" offset=\"%d\" type=\"%s\"/>\n",
  750. &pp->comm.thr_id, sizeof (pp->comm.thr_id) == 4 ? "INT32" : "INT64");
  751. collector_interface->writeLog (" <field name=\"CPUID\" uname=\"" STXT ("CPU id") "\" offset=\"%d\" type=\"%s\"/>\n",
  752. &pp->comm.cpu_id, sizeof (pp->comm.cpu_id) == 4 ? "INT32" : "INT64");
  753. collector_interface->writeLog (" <field name=\"TSTAMP\" uname=\"" STXT ("High resolution timestamp") "\" offset=\"%d\" type=\"%s\"/>\n",
  754. &pp->comm.tstamp, sizeof (pp->comm.tstamp) == 4 ? "INT32" : "INT64");
  755. collector_interface->writeLog (" <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
  756. &pp->comm.frinfo, sizeof (pp->comm.frinfo) == 4 ? "INT32" : "INT64");
  757. collector_interface->writeLog (" <field name=\"HWCTAG\" uname=\"" STXT ("Hardware counter index") "\" offset=\"%d\" type=\"%s\"/>\n",
  758. &pp->tag, sizeof (pp->tag) == 4 ? "INT32" : "INT64");
  759. collector_interface->writeLog (" <field name=\"HWCINT\" uname=\"" STXT ("Hardware counter interval") "\" offset=\"%d\" type=\"%s\"/>\n",
  760. &pp->interval, sizeof (pp->interval) == 4 ? "INT32" : "INT64");
  761. collector_interface->writeLog ("</profpckt>\n");
  762. if (hwcdef_has_memspace)
  763. {
  764. /* Record MHwcntr_packet description */
  765. MHwcntr_packet *xpp = NULL;
  766. collector_interface->writeLog ("<profpckt kind=\"%d\" uname=\"" STXT ("Hardware counter profiling data") "\">\n", MHWC_PCKT);
  767. collector_interface->writeLog (" <field name=\"LWPID\" uname=\"" STXT ("Lightweight process id") "\" offset=\"%d\" type=\"%s\"/>\n",
  768. &xpp->comm.lwp_id, sizeof (xpp->comm.lwp_id) == 4 ? "INT32" : "INT64");
  769. collector_interface->writeLog (" <field name=\"THRID\" uname=\"" STXT ("Thread number") "\" offset=\"%d\" type=\"%s\"/>\n",
  770. &xpp->comm.thr_id, sizeof (xpp->comm.thr_id) == 4 ? "INT32" : "INT64");
  771. collector_interface->writeLog (" <field name=\"CPUID\" uname=\"" STXT ("CPU id") "\" offset=\"%d\" type=\"%s\"/>\n",
  772. &xpp->comm.cpu_id, sizeof (xpp->comm.cpu_id) == 4 ? "INT32" : "INT64");
  773. collector_interface->writeLog (" <field name=\"TSTAMP\" uname=\"" STXT ("High resolution timestamp") "\" offset=\"%d\" type=\"%s\"/>\n",
  774. &xpp->comm.tstamp, sizeof (xpp->comm.tstamp) == 4 ? "INT32" : "INT64");
  775. collector_interface->writeLog (" <field name=\"FRINFO\" offset=\"%d\" type=\"%s\"/>\n",
  776. &xpp->comm.frinfo, sizeof (xpp->comm.frinfo) == 4 ? "INT32" : "INT64");
  777. collector_interface->writeLog (" <field name=\"HWCTAG\" uname=\"" STXT ("Hardware counter index") "\" offset=\"%d\" type=\"%s\"/>\n",
  778. &xpp->tag, sizeof (xpp->tag) == 4 ? "INT32" : "INT64");
  779. collector_interface->writeLog (" <field name=\"HWCINT\" uname=\"" STXT ("Hardware counter interval") "\" offset=\"%d\" type=\"%s\"/>\n",
  780. &xpp->interval, sizeof (xpp->interval) == 4 ? "INT32" : "INT64");
  781. collector_interface->writeLog (" <field name=\"VADDR\" uname=\"" STXT ("Virtual address (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
  782. &xpp->ea_vaddr, sizeof (xpp->ea_vaddr) == 4 ? "UINT32" : "UINT64");
  783. collector_interface->writeLog (" <field name=\"PADDR\" uname=\"" STXT ("Physical address (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
  784. &xpp->ea_paddr, sizeof (xpp->ea_paddr) == 4 ? "UINT32" : "UINT64");
  785. collector_interface->writeLog (" <field name=\"VIRTPC\" uname=\"" STXT ("Virtual address (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
  786. &xpp->pc_vaddr, sizeof (xpp->pc_vaddr) == 4 ? "UINT32" : "UINT64");
  787. collector_interface->writeLog (" <field name=\"PHYSPC\" uname=\"" STXT ("Physical address (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
  788. &xpp->pc_paddr, sizeof (xpp->pc_paddr) == 4 ? "UINT32" : "UINT64");
  789. collector_interface->writeLog (" <field name=\"EA_PAGESIZE\" uname=\"" STXT ("Page size (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
  790. &xpp->ea_pagesz, sizeof (xpp->ea_pagesz) == 4 ? "INT32" : "INT64");
  791. collector_interface->writeLog (" <field name=\"PC_PAGESIZE\" uname=\"" STXT ("Page size (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
  792. &xpp->pc_pagesz, sizeof (xpp->pc_pagesz) == 4 ? "INT32" : "INT64");
  793. collector_interface->writeLog (" <field name=\"EA_LGRP\" uname=\"" STXT ("Page locality group (data)") "\" offset=\"%d\" type=\"%s\"/>\n",
  794. &xpp->ea_lgrp, sizeof (xpp->ea_lgrp) == 4 ? "INT32" : "INT64");
  795. collector_interface->writeLog (" <field name=\"PC_LGRP\" uname=\"" STXT ("Page locality group (instruction)") "\" offset=\"%d\" type=\"%s\"/>\n",
  796. &xpp->pc_lgrp, sizeof (xpp->pc_lgrp) == 4 ? "INT32" : "INT64");
  797. collector_interface->writeLog (" <field name=\"LWP_LGRP_HOME\" uname=\"" STXT ("LWP home lgroup id") "\" offset=\"%d\" type=\"%s\"/>\n",
  798. &xpp->lgrp_lwp, sizeof (xpp->lgrp_lwp) == 4 ? "INT32" : "INT64");
  799. collector_interface->writeLog (" <field name=\"PS_LGRP_HOME\" uname=\"" STXT ("Process home lgroup id") "\" offset=\"%d\" type=\"%s\"/>\n",
  800. &xpp->lgrp_ps, sizeof (xpp->lgrp_ps) == 4 ? "INT32" : "INT64");
  801. collector_interface->writeLog (" <field name=\"MEM_LAT\" uname=\"" STXT ("Memory Latency Cycles") "\" offset=\"%d\" type=\"%s\"/>\n",
  802. &xpp->latency, sizeof (xpp->latency) == 4 ? "INT32" : "INT64");
  803. collector_interface->writeLog (" <field name=\"MEM_SRC\" uname=\"" STXT ("Memory Data Source") "\" offset=\"%d\" type=\"%s\"/>\n",
  804. &xpp->data_source, sizeof (xpp->data_source) == 4 ? "INT32" : "INT64");
  805. collector_interface->writeLog ("</profpckt>\n");
  806. }
  807. }
  808. static void
  809. hwclogwrite (Hwcentry * ctr)
  810. {
  811. TprintfT (DBG_LT1, "hwprofile: writeLog(%s %u %s %d %u %d)\n",
  812. SP_JCMD_HW_COUNTER, cpcN_cpuver, ctr->name ? ctr->name : "NULL",
  813. ctr->val, ctr->sort_order, ctr->memop);
  814. collector_interface->writeLog ("<profile name=\"%s\"", SP_JCMD_HW_COUNTER);
  815. collector_interface->writeLog (" cpuver=\"%u\"", cpcN_cpuver);
  816. collector_interface->writeLog (" hwcname=\"%s\"", ctr->name);
  817. collector_interface->writeLog (" int_name=\"%s\"", ctr->int_name);
  818. collector_interface->writeLog (" interval=\"%d\"", ctr->val);
  819. collector_interface->writeLog (" tag=\"%u\"", ctr->sort_order);
  820. collector_interface->writeLog (" memop=\"%d\"", ctr->memop);
  821. collector_interface->writeLog ("/>\n");
  822. }