callchain.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282
  1. /*
  2. * Copyright (C) 2009-2011, Frederic Weisbecker <fweisbec@gmail.com>
  3. *
  4. * Handle the callchains from the stream in an ad-hoc radix tree and then
  5. * sort them in an rbtree.
  6. *
  7. * Using a radix for code path provides a fast retrieval and factorizes
  8. * memory use. Also that lets us use the paths in a hierarchical graph view.
  9. *
  10. */
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <stdbool.h>
  14. #include <errno.h>
  15. #include <math.h>
  16. #include "asm/bug.h"
  17. #include "hist.h"
  18. #include "util.h"
  19. #include "sort.h"
  20. #include "machine.h"
  21. #include "callchain.h"
  22. __thread struct callchain_cursor callchain_cursor;
  23. int parse_callchain_record_opt(const char *arg, struct callchain_param *param)
  24. {
  25. return parse_callchain_record(arg, param);
  26. }
  27. static int parse_callchain_mode(const char *value)
  28. {
  29. if (!strncmp(value, "graph", strlen(value))) {
  30. callchain_param.mode = CHAIN_GRAPH_ABS;
  31. return 0;
  32. }
  33. if (!strncmp(value, "flat", strlen(value))) {
  34. callchain_param.mode = CHAIN_FLAT;
  35. return 0;
  36. }
  37. if (!strncmp(value, "fractal", strlen(value))) {
  38. callchain_param.mode = CHAIN_GRAPH_REL;
  39. return 0;
  40. }
  41. if (!strncmp(value, "folded", strlen(value))) {
  42. callchain_param.mode = CHAIN_FOLDED;
  43. return 0;
  44. }
  45. pr_err("Invalid callchain mode: %s\n", value);
  46. return -1;
  47. }
  48. static int parse_callchain_order(const char *value)
  49. {
  50. if (!strncmp(value, "caller", strlen(value))) {
  51. callchain_param.order = ORDER_CALLER;
  52. callchain_param.order_set = true;
  53. return 0;
  54. }
  55. if (!strncmp(value, "callee", strlen(value))) {
  56. callchain_param.order = ORDER_CALLEE;
  57. callchain_param.order_set = true;
  58. return 0;
  59. }
  60. pr_err("Invalid callchain order: %s\n", value);
  61. return -1;
  62. }
  63. static int parse_callchain_sort_key(const char *value)
  64. {
  65. if (!strncmp(value, "function", strlen(value))) {
  66. callchain_param.key = CCKEY_FUNCTION;
  67. return 0;
  68. }
  69. if (!strncmp(value, "address", strlen(value))) {
  70. callchain_param.key = CCKEY_ADDRESS;
  71. return 0;
  72. }
  73. if (!strncmp(value, "branch", strlen(value))) {
  74. callchain_param.branch_callstack = 1;
  75. return 0;
  76. }
  77. pr_err("Invalid callchain sort key: %s\n", value);
  78. return -1;
  79. }
  80. static int parse_callchain_value(const char *value)
  81. {
  82. if (!strncmp(value, "percent", strlen(value))) {
  83. callchain_param.value = CCVAL_PERCENT;
  84. return 0;
  85. }
  86. if (!strncmp(value, "period", strlen(value))) {
  87. callchain_param.value = CCVAL_PERIOD;
  88. return 0;
  89. }
  90. if (!strncmp(value, "count", strlen(value))) {
  91. callchain_param.value = CCVAL_COUNT;
  92. return 0;
  93. }
  94. pr_err("Invalid callchain config key: %s\n", value);
  95. return -1;
  96. }
  97. static int
  98. __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
  99. {
  100. char *tok;
  101. char *endptr;
  102. bool minpcnt_set = false;
  103. bool record_opt_set = false;
  104. bool try_stack_size = false;
  105. callchain_param.enabled = true;
  106. symbol_conf.use_callchain = true;
  107. if (!arg)
  108. return 0;
  109. while ((tok = strtok((char *)arg, ",")) != NULL) {
  110. if (!strncmp(tok, "none", strlen(tok))) {
  111. callchain_param.mode = CHAIN_NONE;
  112. callchain_param.enabled = false;
  113. symbol_conf.use_callchain = false;
  114. return 0;
  115. }
  116. if (!parse_callchain_mode(tok) ||
  117. !parse_callchain_order(tok) ||
  118. !parse_callchain_sort_key(tok) ||
  119. !parse_callchain_value(tok)) {
  120. /* parsing ok - move on to the next */
  121. try_stack_size = false;
  122. goto next;
  123. } else if (allow_record_opt && !record_opt_set) {
  124. if (parse_callchain_record(tok, &callchain_param))
  125. goto try_numbers;
  126. /* assume that number followed by 'dwarf' is stack size */
  127. if (callchain_param.record_mode == CALLCHAIN_DWARF)
  128. try_stack_size = true;
  129. record_opt_set = true;
  130. goto next;
  131. }
  132. try_numbers:
  133. if (try_stack_size) {
  134. unsigned long size = 0;
  135. if (get_stack_size(tok, &size) < 0)
  136. return -1;
  137. callchain_param.dump_size = size;
  138. try_stack_size = false;
  139. } else if (!minpcnt_set) {
  140. /* try to get the min percent */
  141. callchain_param.min_percent = strtod(tok, &endptr);
  142. if (tok == endptr)
  143. return -1;
  144. minpcnt_set = true;
  145. } else {
  146. /* try print limit at last */
  147. callchain_param.print_limit = strtoul(tok, &endptr, 0);
  148. if (tok == endptr)
  149. return -1;
  150. }
  151. next:
  152. arg = NULL;
  153. }
  154. if (callchain_register_param(&callchain_param) < 0) {
  155. pr_err("Can't register callchain params\n");
  156. return -1;
  157. }
  158. return 0;
  159. }
  160. int parse_callchain_report_opt(const char *arg)
  161. {
  162. return __parse_callchain_report_opt(arg, false);
  163. }
  164. int parse_callchain_top_opt(const char *arg)
  165. {
  166. return __parse_callchain_report_opt(arg, true);
  167. }
  168. int perf_callchain_config(const char *var, const char *value)
  169. {
  170. char *endptr;
  171. if (prefixcmp(var, "call-graph."))
  172. return 0;
  173. var += sizeof("call-graph.") - 1;
  174. if (!strcmp(var, "record-mode"))
  175. return parse_callchain_record_opt(value, &callchain_param);
  176. if (!strcmp(var, "dump-size")) {
  177. unsigned long size = 0;
  178. int ret;
  179. ret = get_stack_size(value, &size);
  180. callchain_param.dump_size = size;
  181. return ret;
  182. }
  183. if (!strcmp(var, "print-type"))
  184. return parse_callchain_mode(value);
  185. if (!strcmp(var, "order"))
  186. return parse_callchain_order(value);
  187. if (!strcmp(var, "sort-key"))
  188. return parse_callchain_sort_key(value);
  189. if (!strcmp(var, "threshold")) {
  190. callchain_param.min_percent = strtod(value, &endptr);
  191. if (value == endptr) {
  192. pr_err("Invalid callchain threshold: %s\n", value);
  193. return -1;
  194. }
  195. }
  196. if (!strcmp(var, "print-limit")) {
  197. callchain_param.print_limit = strtod(value, &endptr);
  198. if (value == endptr) {
  199. pr_err("Invalid callchain print limit: %s\n", value);
  200. return -1;
  201. }
  202. }
  203. return 0;
  204. }
  205. static void
  206. rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
  207. enum chain_mode mode)
  208. {
  209. struct rb_node **p = &root->rb_node;
  210. struct rb_node *parent = NULL;
  211. struct callchain_node *rnode;
  212. u64 chain_cumul = callchain_cumul_hits(chain);
  213. while (*p) {
  214. u64 rnode_cumul;
  215. parent = *p;
  216. rnode = rb_entry(parent, struct callchain_node, rb_node);
  217. rnode_cumul = callchain_cumul_hits(rnode);
  218. switch (mode) {
  219. case CHAIN_FLAT:
  220. case CHAIN_FOLDED:
  221. if (rnode->hit < chain->hit)
  222. p = &(*p)->rb_left;
  223. else
  224. p = &(*p)->rb_right;
  225. break;
  226. case CHAIN_GRAPH_ABS: /* Falldown */
  227. case CHAIN_GRAPH_REL:
  228. if (rnode_cumul < chain_cumul)
  229. p = &(*p)->rb_left;
  230. else
  231. p = &(*p)->rb_right;
  232. break;
  233. case CHAIN_NONE:
  234. default:
  235. break;
  236. }
  237. }
  238. rb_link_node(&chain->rb_node, parent, p);
  239. rb_insert_color(&chain->rb_node, root);
  240. }
  241. static void
  242. __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
  243. u64 min_hit)
  244. {
  245. struct rb_node *n;
  246. struct callchain_node *child;
  247. n = rb_first(&node->rb_root_in);
  248. while (n) {
  249. child = rb_entry(n, struct callchain_node, rb_node_in);
  250. n = rb_next(n);
  251. __sort_chain_flat(rb_root, child, min_hit);
  252. }
  253. if (node->hit && node->hit >= min_hit)
  254. rb_insert_callchain(rb_root, node, CHAIN_FLAT);
  255. }
  256. /*
  257. * Once we get every callchains from the stream, we can now
  258. * sort them by hit
  259. */
  260. static void
  261. sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
  262. u64 min_hit, struct callchain_param *param __maybe_unused)
  263. {
  264. *rb_root = RB_ROOT;
  265. __sort_chain_flat(rb_root, &root->node, min_hit);
  266. }
  267. static void __sort_chain_graph_abs(struct callchain_node *node,
  268. u64 min_hit)
  269. {
  270. struct rb_node *n;
  271. struct callchain_node *child;
  272. node->rb_root = RB_ROOT;
  273. n = rb_first(&node->rb_root_in);
  274. while (n) {
  275. child = rb_entry(n, struct callchain_node, rb_node_in);
  276. n = rb_next(n);
  277. __sort_chain_graph_abs(child, min_hit);
  278. if (callchain_cumul_hits(child) >= min_hit)
  279. rb_insert_callchain(&node->rb_root, child,
  280. CHAIN_GRAPH_ABS);
  281. }
  282. }
  283. static void
  284. sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
  285. u64 min_hit, struct callchain_param *param __maybe_unused)
  286. {
  287. __sort_chain_graph_abs(&chain_root->node, min_hit);
  288. rb_root->rb_node = chain_root->node.rb_root.rb_node;
  289. }
  290. static void __sort_chain_graph_rel(struct callchain_node *node,
  291. double min_percent)
  292. {
  293. struct rb_node *n;
  294. struct callchain_node *child;
  295. u64 min_hit;
  296. node->rb_root = RB_ROOT;
  297. min_hit = ceil(node->children_hit * min_percent);
  298. n = rb_first(&node->rb_root_in);
  299. while (n) {
  300. child = rb_entry(n, struct callchain_node, rb_node_in);
  301. n = rb_next(n);
  302. __sort_chain_graph_rel(child, min_percent);
  303. if (callchain_cumul_hits(child) >= min_hit)
  304. rb_insert_callchain(&node->rb_root, child,
  305. CHAIN_GRAPH_REL);
  306. }
  307. }
  308. static void
  309. sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
  310. u64 min_hit __maybe_unused, struct callchain_param *param)
  311. {
  312. __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
  313. rb_root->rb_node = chain_root->node.rb_root.rb_node;
  314. }
  315. int callchain_register_param(struct callchain_param *param)
  316. {
  317. switch (param->mode) {
  318. case CHAIN_GRAPH_ABS:
  319. param->sort = sort_chain_graph_abs;
  320. break;
  321. case CHAIN_GRAPH_REL:
  322. param->sort = sort_chain_graph_rel;
  323. break;
  324. case CHAIN_FLAT:
  325. case CHAIN_FOLDED:
  326. param->sort = sort_chain_flat;
  327. break;
  328. case CHAIN_NONE:
  329. default:
  330. return -1;
  331. }
  332. return 0;
  333. }
  334. /*
  335. * Create a child for a parent. If inherit_children, then the new child
  336. * will become the new parent of it's parent children
  337. */
  338. static struct callchain_node *
  339. create_child(struct callchain_node *parent, bool inherit_children)
  340. {
  341. struct callchain_node *new;
  342. new = zalloc(sizeof(*new));
  343. if (!new) {
  344. perror("not enough memory to create child for code path tree");
  345. return NULL;
  346. }
  347. new->parent = parent;
  348. INIT_LIST_HEAD(&new->val);
  349. INIT_LIST_HEAD(&new->parent_val);
  350. if (inherit_children) {
  351. struct rb_node *n;
  352. struct callchain_node *child;
  353. new->rb_root_in = parent->rb_root_in;
  354. parent->rb_root_in = RB_ROOT;
  355. n = rb_first(&new->rb_root_in);
  356. while (n) {
  357. child = rb_entry(n, struct callchain_node, rb_node_in);
  358. child->parent = new;
  359. n = rb_next(n);
  360. }
  361. /* make it the first child */
  362. rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node);
  363. rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
  364. }
  365. return new;
  366. }
  367. /*
  368. * Fill the node with callchain values
  369. */
  370. static int
  371. fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
  372. {
  373. struct callchain_cursor_node *cursor_node;
  374. node->val_nr = cursor->nr - cursor->pos;
  375. if (!node->val_nr)
  376. pr_warning("Warning: empty node in callchain tree\n");
  377. cursor_node = callchain_cursor_current(cursor);
  378. while (cursor_node) {
  379. struct callchain_list *call;
  380. call = zalloc(sizeof(*call));
  381. if (!call) {
  382. perror("not enough memory for the code path tree");
  383. return -1;
  384. }
  385. call->ip = cursor_node->ip;
  386. call->ms.sym = cursor_node->sym;
  387. call->ms.map = map__get(cursor_node->map);
  388. if (cursor_node->branch) {
  389. call->branch_count = 1;
  390. if (cursor_node->branch_flags.predicted)
  391. call->predicted_count = 1;
  392. if (cursor_node->branch_flags.abort)
  393. call->abort_count = 1;
  394. call->cycles_count = cursor_node->branch_flags.cycles;
  395. call->iter_count = cursor_node->nr_loop_iter;
  396. call->samples_count = cursor_node->samples;
  397. }
  398. list_add_tail(&call->list, &node->val);
  399. callchain_cursor_advance(cursor);
  400. cursor_node = callchain_cursor_current(cursor);
  401. }
  402. return 0;
  403. }
  404. static struct callchain_node *
  405. add_child(struct callchain_node *parent,
  406. struct callchain_cursor *cursor,
  407. u64 period)
  408. {
  409. struct callchain_node *new;
  410. new = create_child(parent, false);
  411. if (new == NULL)
  412. return NULL;
  413. if (fill_node(new, cursor) < 0) {
  414. struct callchain_list *call, *tmp;
  415. list_for_each_entry_safe(call, tmp, &new->val, list) {
  416. list_del(&call->list);
  417. map__zput(call->ms.map);
  418. free(call);
  419. }
  420. free(new);
  421. return NULL;
  422. }
  423. new->children_hit = 0;
  424. new->hit = period;
  425. new->children_count = 0;
  426. new->count = 1;
  427. return new;
  428. }
  429. enum match_result {
  430. MATCH_ERROR = -1,
  431. MATCH_EQ,
  432. MATCH_LT,
  433. MATCH_GT,
  434. };
  435. static enum match_result match_chain(struct callchain_cursor_node *node,
  436. struct callchain_list *cnode)
  437. {
  438. struct symbol *sym = node->sym;
  439. u64 left, right;
  440. if (cnode->ms.sym && sym &&
  441. callchain_param.key == CCKEY_FUNCTION) {
  442. left = cnode->ms.sym->start;
  443. right = sym->start;
  444. } else {
  445. left = cnode->ip;
  446. right = node->ip;
  447. }
  448. if (left == right) {
  449. if (node->branch) {
  450. cnode->branch_count++;
  451. if (node->branch_flags.predicted)
  452. cnode->predicted_count++;
  453. if (node->branch_flags.abort)
  454. cnode->abort_count++;
  455. cnode->cycles_count += node->branch_flags.cycles;
  456. cnode->iter_count += node->nr_loop_iter;
  457. cnode->samples_count += node->samples;
  458. }
  459. return MATCH_EQ;
  460. }
  461. return left > right ? MATCH_GT : MATCH_LT;
  462. }
  463. /*
  464. * Split the parent in two parts (a new child is created) and
  465. * give a part of its callchain to the created child.
  466. * Then create another child to host the given callchain of new branch
  467. */
  468. static int
  469. split_add_child(struct callchain_node *parent,
  470. struct callchain_cursor *cursor,
  471. struct callchain_list *to_split,
  472. u64 idx_parents, u64 idx_local, u64 period)
  473. {
  474. struct callchain_node *new;
  475. struct list_head *old_tail;
  476. unsigned int idx_total = idx_parents + idx_local;
  477. /* split */
  478. new = create_child(parent, true);
  479. if (new == NULL)
  480. return -1;
  481. /* split the callchain and move a part to the new child */
  482. old_tail = parent->val.prev;
  483. list_del_range(&to_split->list, old_tail);
  484. new->val.next = &to_split->list;
  485. new->val.prev = old_tail;
  486. to_split->list.prev = &new->val;
  487. old_tail->next = &new->val;
  488. /* split the hits */
  489. new->hit = parent->hit;
  490. new->children_hit = parent->children_hit;
  491. parent->children_hit = callchain_cumul_hits(new);
  492. new->val_nr = parent->val_nr - idx_local;
  493. parent->val_nr = idx_local;
  494. new->count = parent->count;
  495. new->children_count = parent->children_count;
  496. parent->children_count = callchain_cumul_counts(new);
  497. /* create a new child for the new branch if any */
  498. if (idx_total < cursor->nr) {
  499. struct callchain_node *first;
  500. struct callchain_list *cnode;
  501. struct callchain_cursor_node *node;
  502. struct rb_node *p, **pp;
  503. parent->hit = 0;
  504. parent->children_hit += period;
  505. parent->count = 0;
  506. parent->children_count += 1;
  507. node = callchain_cursor_current(cursor);
  508. new = add_child(parent, cursor, period);
  509. if (new == NULL)
  510. return -1;
  511. /*
  512. * This is second child since we moved parent's children
  513. * to new (first) child above.
  514. */
  515. p = parent->rb_root_in.rb_node;
  516. first = rb_entry(p, struct callchain_node, rb_node_in);
  517. cnode = list_first_entry(&first->val, struct callchain_list,
  518. list);
  519. if (match_chain(node, cnode) == MATCH_LT)
  520. pp = &p->rb_left;
  521. else
  522. pp = &p->rb_right;
  523. rb_link_node(&new->rb_node_in, p, pp);
  524. rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
  525. } else {
  526. parent->hit = period;
  527. parent->count = 1;
  528. }
  529. return 0;
  530. }
  531. static enum match_result
  532. append_chain(struct callchain_node *root,
  533. struct callchain_cursor *cursor,
  534. u64 period);
  535. static int
  536. append_chain_children(struct callchain_node *root,
  537. struct callchain_cursor *cursor,
  538. u64 period)
  539. {
  540. struct callchain_node *rnode;
  541. struct callchain_cursor_node *node;
  542. struct rb_node **p = &root->rb_root_in.rb_node;
  543. struct rb_node *parent = NULL;
  544. node = callchain_cursor_current(cursor);
  545. if (!node)
  546. return -1;
  547. /* lookup in childrens */
  548. while (*p) {
  549. enum match_result ret;
  550. parent = *p;
  551. rnode = rb_entry(parent, struct callchain_node, rb_node_in);
  552. /* If at least first entry matches, rely to children */
  553. ret = append_chain(rnode, cursor, period);
  554. if (ret == MATCH_EQ)
  555. goto inc_children_hit;
  556. if (ret == MATCH_ERROR)
  557. return -1;
  558. if (ret == MATCH_LT)
  559. p = &parent->rb_left;
  560. else
  561. p = &parent->rb_right;
  562. }
  563. /* nothing in children, add to the current node */
  564. rnode = add_child(root, cursor, period);
  565. if (rnode == NULL)
  566. return -1;
  567. rb_link_node(&rnode->rb_node_in, parent, p);
  568. rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
  569. inc_children_hit:
  570. root->children_hit += period;
  571. root->children_count++;
  572. return 0;
  573. }
  574. static enum match_result
  575. append_chain(struct callchain_node *root,
  576. struct callchain_cursor *cursor,
  577. u64 period)
  578. {
  579. struct callchain_list *cnode;
  580. u64 start = cursor->pos;
  581. bool found = false;
  582. u64 matches;
  583. enum match_result cmp = MATCH_ERROR;
  584. /*
  585. * Lookup in the current node
  586. * If we have a symbol, then compare the start to match
  587. * anywhere inside a function, unless function
  588. * mode is disabled.
  589. */
  590. list_for_each_entry(cnode, &root->val, list) {
  591. struct callchain_cursor_node *node;
  592. node = callchain_cursor_current(cursor);
  593. if (!node)
  594. break;
  595. cmp = match_chain(node, cnode);
  596. if (cmp != MATCH_EQ)
  597. break;
  598. found = true;
  599. callchain_cursor_advance(cursor);
  600. }
  601. /* matches not, relay no the parent */
  602. if (!found) {
  603. WARN_ONCE(cmp == MATCH_ERROR, "Chain comparison error\n");
  604. return cmp;
  605. }
  606. matches = cursor->pos - start;
  607. /* we match only a part of the node. Split it and add the new chain */
  608. if (matches < root->val_nr) {
  609. if (split_add_child(root, cursor, cnode, start, matches,
  610. period) < 0)
  611. return MATCH_ERROR;
  612. return MATCH_EQ;
  613. }
  614. /* we match 100% of the path, increment the hit */
  615. if (matches == root->val_nr && cursor->pos == cursor->nr) {
  616. root->hit += period;
  617. root->count++;
  618. return MATCH_EQ;
  619. }
  620. /* We match the node and still have a part remaining */
  621. if (append_chain_children(root, cursor, period) < 0)
  622. return MATCH_ERROR;
  623. return MATCH_EQ;
  624. }
  625. int callchain_append(struct callchain_root *root,
  626. struct callchain_cursor *cursor,
  627. u64 period)
  628. {
  629. if (!cursor->nr)
  630. return 0;
  631. callchain_cursor_commit(cursor);
  632. if (append_chain_children(&root->node, cursor, period) < 0)
  633. return -1;
  634. if (cursor->nr > root->max_depth)
  635. root->max_depth = cursor->nr;
  636. return 0;
  637. }
  638. static int
  639. merge_chain_branch(struct callchain_cursor *cursor,
  640. struct callchain_node *dst, struct callchain_node *src)
  641. {
  642. struct callchain_cursor_node **old_last = cursor->last;
  643. struct callchain_node *child;
  644. struct callchain_list *list, *next_list;
  645. struct rb_node *n;
  646. int old_pos = cursor->nr;
  647. int err = 0;
  648. list_for_each_entry_safe(list, next_list, &src->val, list) {
  649. callchain_cursor_append(cursor, list->ip,
  650. list->ms.map, list->ms.sym,
  651. false, NULL, 0, 0);
  652. list_del(&list->list);
  653. map__zput(list->ms.map);
  654. free(list);
  655. }
  656. if (src->hit) {
  657. callchain_cursor_commit(cursor);
  658. if (append_chain_children(dst, cursor, src->hit) < 0)
  659. return -1;
  660. }
  661. n = rb_first(&src->rb_root_in);
  662. while (n) {
  663. child = container_of(n, struct callchain_node, rb_node_in);
  664. n = rb_next(n);
  665. rb_erase(&child->rb_node_in, &src->rb_root_in);
  666. err = merge_chain_branch(cursor, dst, child);
  667. if (err)
  668. break;
  669. free(child);
  670. }
  671. cursor->nr = old_pos;
  672. cursor->last = old_last;
  673. return err;
  674. }
  675. int callchain_merge(struct callchain_cursor *cursor,
  676. struct callchain_root *dst, struct callchain_root *src)
  677. {
  678. return merge_chain_branch(cursor, &dst->node, &src->node);
  679. }
  680. int callchain_cursor_append(struct callchain_cursor *cursor,
  681. u64 ip, struct map *map, struct symbol *sym,
  682. bool branch, struct branch_flags *flags,
  683. int nr_loop_iter, int samples)
  684. {
  685. struct callchain_cursor_node *node = *cursor->last;
  686. if (!node) {
  687. node = calloc(1, sizeof(*node));
  688. if (!node)
  689. return -ENOMEM;
  690. *cursor->last = node;
  691. }
  692. node->ip = ip;
  693. map__zput(node->map);
  694. node->map = map__get(map);
  695. node->sym = sym;
  696. node->branch = branch;
  697. node->nr_loop_iter = nr_loop_iter;
  698. node->samples = samples;
  699. if (flags)
  700. memcpy(&node->branch_flags, flags,
  701. sizeof(struct branch_flags));
  702. cursor->nr++;
  703. cursor->last = &node->next;
  704. return 0;
  705. }
  706. int sample__resolve_callchain(struct perf_sample *sample,
  707. struct callchain_cursor *cursor, struct symbol **parent,
  708. struct perf_evsel *evsel, struct addr_location *al,
  709. int max_stack)
  710. {
  711. if (sample->callchain == NULL)
  712. return 0;
  713. if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
  714. perf_hpp_list.parent) {
  715. return thread__resolve_callchain(al->thread, cursor, evsel, sample,
  716. parent, al, max_stack);
  717. }
  718. return 0;
  719. }
  720. int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
  721. {
  722. if (!symbol_conf.use_callchain || sample->callchain == NULL)
  723. return 0;
  724. return callchain_append(he->callchain, &callchain_cursor, sample->period);
  725. }
  726. int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
  727. bool hide_unresolved)
  728. {
  729. al->map = node->map;
  730. al->sym = node->sym;
  731. if (node->map)
  732. al->addr = node->map->map_ip(node->map, node->ip);
  733. else
  734. al->addr = node->ip;
  735. if (al->sym == NULL) {
  736. if (hide_unresolved)
  737. return 0;
  738. if (al->map == NULL)
  739. goto out;
  740. }
  741. if (al->map->groups == &al->machine->kmaps) {
  742. if (machine__is_host(al->machine)) {
  743. al->cpumode = PERF_RECORD_MISC_KERNEL;
  744. al->level = 'k';
  745. } else {
  746. al->cpumode = PERF_RECORD_MISC_GUEST_KERNEL;
  747. al->level = 'g';
  748. }
  749. } else {
  750. if (machine__is_host(al->machine)) {
  751. al->cpumode = PERF_RECORD_MISC_USER;
  752. al->level = '.';
  753. } else if (perf_guest) {
  754. al->cpumode = PERF_RECORD_MISC_GUEST_USER;
  755. al->level = 'u';
  756. } else {
  757. al->cpumode = PERF_RECORD_MISC_HYPERVISOR;
  758. al->level = 'H';
  759. }
  760. }
  761. out:
  762. return 1;
  763. }
  764. char *callchain_list__sym_name(struct callchain_list *cl,
  765. char *bf, size_t bfsize, bool show_dso)
  766. {
  767. int printed;
  768. if (cl->ms.sym) {
  769. if (callchain_param.key == CCKEY_ADDRESS &&
  770. cl->ms.map && !cl->srcline)
  771. cl->srcline = get_srcline(cl->ms.map->dso,
  772. map__rip_2objdump(cl->ms.map,
  773. cl->ip),
  774. cl->ms.sym, false);
  775. if (cl->srcline)
  776. printed = scnprintf(bf, bfsize, "%s %s",
  777. cl->ms.sym->name, cl->srcline);
  778. else
  779. printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
  780. } else
  781. printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
  782. if (show_dso)
  783. scnprintf(bf + printed, bfsize - printed, " %s",
  784. cl->ms.map ?
  785. cl->ms.map->dso->short_name :
  786. "unknown");
  787. return bf;
  788. }
  789. char *callchain_node__scnprintf_value(struct callchain_node *node,
  790. char *bf, size_t bfsize, u64 total)
  791. {
  792. double percent = 0.0;
  793. u64 period = callchain_cumul_hits(node);
  794. unsigned count = callchain_cumul_counts(node);
  795. if (callchain_param.mode == CHAIN_FOLDED) {
  796. period = node->hit;
  797. count = node->count;
  798. }
  799. switch (callchain_param.value) {
  800. case CCVAL_PERIOD:
  801. scnprintf(bf, bfsize, "%"PRIu64, period);
  802. break;
  803. case CCVAL_COUNT:
  804. scnprintf(bf, bfsize, "%u", count);
  805. break;
  806. case CCVAL_PERCENT:
  807. default:
  808. if (total)
  809. percent = period * 100.0 / total;
  810. scnprintf(bf, bfsize, "%.2f%%", percent);
  811. break;
  812. }
  813. return bf;
  814. }
  815. int callchain_node__fprintf_value(struct callchain_node *node,
  816. FILE *fp, u64 total)
  817. {
  818. double percent = 0.0;
  819. u64 period = callchain_cumul_hits(node);
  820. unsigned count = callchain_cumul_counts(node);
  821. if (callchain_param.mode == CHAIN_FOLDED) {
  822. period = node->hit;
  823. count = node->count;
  824. }
  825. switch (callchain_param.value) {
  826. case CCVAL_PERIOD:
  827. return fprintf(fp, "%"PRIu64, period);
  828. case CCVAL_COUNT:
  829. return fprintf(fp, "%u", count);
  830. case CCVAL_PERCENT:
  831. default:
  832. if (total)
  833. percent = period * 100.0 / total;
  834. return percent_color_fprintf(fp, "%.2f%%", percent);
  835. }
  836. return 0;
  837. }
  838. static void callchain_counts_value(struct callchain_node *node,
  839. u64 *branch_count, u64 *predicted_count,
  840. u64 *abort_count, u64 *cycles_count)
  841. {
  842. struct callchain_list *clist;
  843. list_for_each_entry(clist, &node->val, list) {
  844. if (branch_count)
  845. *branch_count += clist->branch_count;
  846. if (predicted_count)
  847. *predicted_count += clist->predicted_count;
  848. if (abort_count)
  849. *abort_count += clist->abort_count;
  850. if (cycles_count)
  851. *cycles_count += clist->cycles_count;
  852. }
  853. }
  854. static int callchain_node_branch_counts_cumul(struct callchain_node *node,
  855. u64 *branch_count,
  856. u64 *predicted_count,
  857. u64 *abort_count,
  858. u64 *cycles_count)
  859. {
  860. struct callchain_node *child;
  861. struct rb_node *n;
  862. n = rb_first(&node->rb_root_in);
  863. while (n) {
  864. child = rb_entry(n, struct callchain_node, rb_node_in);
  865. n = rb_next(n);
  866. callchain_node_branch_counts_cumul(child, branch_count,
  867. predicted_count,
  868. abort_count,
  869. cycles_count);
  870. callchain_counts_value(child, branch_count,
  871. predicted_count, abort_count,
  872. cycles_count);
  873. }
  874. return 0;
  875. }
  876. int callchain_branch_counts(struct callchain_root *root,
  877. u64 *branch_count, u64 *predicted_count,
  878. u64 *abort_count, u64 *cycles_count)
  879. {
  880. if (branch_count)
  881. *branch_count = 0;
  882. if (predicted_count)
  883. *predicted_count = 0;
  884. if (abort_count)
  885. *abort_count = 0;
  886. if (cycles_count)
  887. *cycles_count = 0;
  888. return callchain_node_branch_counts_cumul(&root->node,
  889. branch_count,
  890. predicted_count,
  891. abort_count,
  892. cycles_count);
  893. }
  894. static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
  895. u64 branch_count, u64 predicted_count,
  896. u64 abort_count, u64 cycles_count,
  897. u64 iter_count, u64 samples_count)
  898. {
  899. double predicted_percent = 0.0;
  900. const char *null_str = "";
  901. char iter_str[32];
  902. char *str;
  903. u64 cycles = 0;
  904. if (branch_count == 0) {
  905. if (fp)
  906. return fprintf(fp, " (calltrace)");
  907. return scnprintf(bf, bfsize, " (calltrace)");
  908. }
  909. if (iter_count && samples_count) {
  910. scnprintf(iter_str, sizeof(iter_str),
  911. ", iterations:%" PRId64 "",
  912. iter_count / samples_count);
  913. str = iter_str;
  914. } else
  915. str = (char *)null_str;
  916. predicted_percent = predicted_count * 100.0 / branch_count;
  917. cycles = cycles_count / branch_count;
  918. if ((predicted_percent >= 100.0) && (abort_count == 0)) {
  919. if (fp)
  920. return fprintf(fp, " (cycles:%" PRId64 "%s)",
  921. cycles, str);
  922. return scnprintf(bf, bfsize, " (cycles:%" PRId64 "%s)",
  923. cycles, str);
  924. }
  925. if ((predicted_percent < 100.0) && (abort_count == 0)) {
  926. if (fp)
  927. return fprintf(fp,
  928. " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
  929. predicted_percent, cycles, str);
  930. return scnprintf(bf, bfsize,
  931. " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
  932. predicted_percent, cycles, str);
  933. }
  934. if (fp)
  935. return fprintf(fp,
  936. " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
  937. predicted_percent, abort_count, cycles, str);
  938. return scnprintf(bf, bfsize,
  939. " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
  940. predicted_percent, abort_count, cycles, str);
  941. }
  942. int callchain_list_counts__printf_value(struct callchain_node *node,
  943. struct callchain_list *clist,
  944. FILE *fp, char *bf, int bfsize)
  945. {
  946. u64 branch_count, predicted_count;
  947. u64 abort_count, cycles_count;
  948. u64 iter_count = 0, samples_count = 0;
  949. branch_count = clist->branch_count;
  950. predicted_count = clist->predicted_count;
  951. abort_count = clist->abort_count;
  952. cycles_count = clist->cycles_count;
  953. if (node) {
  954. struct callchain_list *call;
  955. list_for_each_entry(call, &node->val, list) {
  956. iter_count += call->iter_count;
  957. samples_count += call->samples_count;
  958. }
  959. }
  960. return callchain_counts_printf(fp, bf, bfsize, branch_count,
  961. predicted_count, abort_count,
  962. cycles_count, iter_count, samples_count);
  963. }
  964. static void free_callchain_node(struct callchain_node *node)
  965. {
  966. struct callchain_list *list, *tmp;
  967. struct callchain_node *child;
  968. struct rb_node *n;
  969. list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
  970. list_del(&list->list);
  971. map__zput(list->ms.map);
  972. free(list);
  973. }
  974. list_for_each_entry_safe(list, tmp, &node->val, list) {
  975. list_del(&list->list);
  976. map__zput(list->ms.map);
  977. free(list);
  978. }
  979. n = rb_first(&node->rb_root_in);
  980. while (n) {
  981. child = container_of(n, struct callchain_node, rb_node_in);
  982. n = rb_next(n);
  983. rb_erase(&child->rb_node_in, &node->rb_root_in);
  984. free_callchain_node(child);
  985. free(child);
  986. }
  987. }
  988. void free_callchain(struct callchain_root *root)
  989. {
  990. if (!symbol_conf.use_callchain)
  991. return;
  992. free_callchain_node(&root->node);
  993. }
  994. static u64 decay_callchain_node(struct callchain_node *node)
  995. {
  996. struct callchain_node *child;
  997. struct rb_node *n;
  998. u64 child_hits = 0;
  999. n = rb_first(&node->rb_root_in);
  1000. while (n) {
  1001. child = container_of(n, struct callchain_node, rb_node_in);
  1002. child_hits += decay_callchain_node(child);
  1003. n = rb_next(n);
  1004. }
  1005. node->hit = (node->hit * 7) / 8;
  1006. node->children_hit = child_hits;
  1007. return node->hit;
  1008. }
  1009. void decay_callchain(struct callchain_root *root)
  1010. {
  1011. if (!symbol_conf.use_callchain)
  1012. return;
  1013. decay_callchain_node(&root->node);
  1014. }
  1015. int callchain_node__make_parent_list(struct callchain_node *node)
  1016. {
  1017. struct callchain_node *parent = node->parent;
  1018. struct callchain_list *chain, *new;
  1019. LIST_HEAD(head);
  1020. while (parent) {
  1021. list_for_each_entry_reverse(chain, &parent->val, list) {
  1022. new = malloc(sizeof(*new));
  1023. if (new == NULL)
  1024. goto out;
  1025. *new = *chain;
  1026. new->has_children = false;
  1027. map__get(new->ms.map);
  1028. list_add_tail(&new->list, &head);
  1029. }
  1030. parent = parent->parent;
  1031. }
  1032. list_for_each_entry_safe_reverse(chain, new, &head, list)
  1033. list_move_tail(&chain->list, &node->parent_val);
  1034. if (!list_empty(&node->parent_val)) {
  1035. chain = list_first_entry(&node->parent_val, struct callchain_list, list);
  1036. chain->has_children = rb_prev(&node->rb_node) || rb_next(&node->rb_node);
  1037. chain = list_first_entry(&node->val, struct callchain_list, list);
  1038. chain->has_children = false;
  1039. }
  1040. return 0;
  1041. out:
  1042. list_for_each_entry_safe(chain, new, &head, list) {
  1043. list_del(&chain->list);
  1044. map__zput(chain->ms.map);
  1045. free(chain);
  1046. }
  1047. return -ENOMEM;
  1048. }
  1049. int callchain_cursor__copy(struct callchain_cursor *dst,
  1050. struct callchain_cursor *src)
  1051. {
  1052. int rc = 0;
  1053. callchain_cursor_reset(dst);
  1054. callchain_cursor_commit(src);
  1055. while (true) {
  1056. struct callchain_cursor_node *node;
  1057. node = callchain_cursor_current(src);
  1058. if (node == NULL)
  1059. break;
  1060. rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
  1061. node->branch, &node->branch_flags,
  1062. node->nr_loop_iter, node->samples);
  1063. if (rc)
  1064. break;
  1065. callchain_cursor_advance(src);
  1066. }
  1067. return rc;
  1068. }