callchain.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  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. return -1;
  46. }
  47. static int parse_callchain_order(const char *value)
  48. {
  49. if (!strncmp(value, "caller", strlen(value))) {
  50. callchain_param.order = ORDER_CALLER;
  51. callchain_param.order_set = true;
  52. return 0;
  53. }
  54. if (!strncmp(value, "callee", strlen(value))) {
  55. callchain_param.order = ORDER_CALLEE;
  56. callchain_param.order_set = true;
  57. return 0;
  58. }
  59. return -1;
  60. }
  61. static int parse_callchain_sort_key(const char *value)
  62. {
  63. if (!strncmp(value, "function", strlen(value))) {
  64. callchain_param.key = CCKEY_FUNCTION;
  65. return 0;
  66. }
  67. if (!strncmp(value, "address", strlen(value))) {
  68. callchain_param.key = CCKEY_ADDRESS;
  69. return 0;
  70. }
  71. if (!strncmp(value, "branch", strlen(value))) {
  72. callchain_param.branch_callstack = 1;
  73. return 0;
  74. }
  75. return -1;
  76. }
  77. static int parse_callchain_value(const char *value)
  78. {
  79. if (!strncmp(value, "percent", strlen(value))) {
  80. callchain_param.value = CCVAL_PERCENT;
  81. return 0;
  82. }
  83. if (!strncmp(value, "period", strlen(value))) {
  84. callchain_param.value = CCVAL_PERIOD;
  85. return 0;
  86. }
  87. if (!strncmp(value, "count", strlen(value))) {
  88. callchain_param.value = CCVAL_COUNT;
  89. return 0;
  90. }
  91. return -1;
  92. }
  93. static int
  94. __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
  95. {
  96. char *tok;
  97. char *endptr;
  98. bool minpcnt_set = false;
  99. bool record_opt_set = false;
  100. bool try_stack_size = false;
  101. symbol_conf.use_callchain = true;
  102. if (!arg)
  103. return 0;
  104. while ((tok = strtok((char *)arg, ",")) != NULL) {
  105. if (!strncmp(tok, "none", strlen(tok))) {
  106. callchain_param.mode = CHAIN_NONE;
  107. symbol_conf.use_callchain = false;
  108. return 0;
  109. }
  110. if (!parse_callchain_mode(tok) ||
  111. !parse_callchain_order(tok) ||
  112. !parse_callchain_sort_key(tok) ||
  113. !parse_callchain_value(tok)) {
  114. /* parsing ok - move on to the next */
  115. try_stack_size = false;
  116. goto next;
  117. } else if (allow_record_opt && !record_opt_set) {
  118. if (parse_callchain_record(tok, &callchain_param))
  119. goto try_numbers;
  120. /* assume that number followed by 'dwarf' is stack size */
  121. if (callchain_param.record_mode == CALLCHAIN_DWARF)
  122. try_stack_size = true;
  123. record_opt_set = true;
  124. goto next;
  125. }
  126. try_numbers:
  127. if (try_stack_size) {
  128. unsigned long size = 0;
  129. if (get_stack_size(tok, &size) < 0)
  130. return -1;
  131. callchain_param.dump_size = size;
  132. try_stack_size = false;
  133. } else if (!minpcnt_set) {
  134. /* try to get the min percent */
  135. callchain_param.min_percent = strtod(tok, &endptr);
  136. if (tok == endptr)
  137. return -1;
  138. minpcnt_set = true;
  139. } else {
  140. /* try print limit at last */
  141. callchain_param.print_limit = strtoul(tok, &endptr, 0);
  142. if (tok == endptr)
  143. return -1;
  144. }
  145. next:
  146. arg = NULL;
  147. }
  148. if (callchain_register_param(&callchain_param) < 0) {
  149. pr_err("Can't register callchain params\n");
  150. return -1;
  151. }
  152. return 0;
  153. }
  154. int parse_callchain_report_opt(const char *arg)
  155. {
  156. return __parse_callchain_report_opt(arg, false);
  157. }
  158. int parse_callchain_top_opt(const char *arg)
  159. {
  160. return __parse_callchain_report_opt(arg, true);
  161. }
  162. int perf_callchain_config(const char *var, const char *value)
  163. {
  164. char *endptr;
  165. if (prefixcmp(var, "call-graph."))
  166. return 0;
  167. var += sizeof("call-graph.") - 1;
  168. if (!strcmp(var, "record-mode"))
  169. return parse_callchain_record_opt(value, &callchain_param);
  170. #ifdef HAVE_DWARF_UNWIND_SUPPORT
  171. if (!strcmp(var, "dump-size")) {
  172. unsigned long size = 0;
  173. int ret;
  174. ret = get_stack_size(value, &size);
  175. callchain_param.dump_size = size;
  176. return ret;
  177. }
  178. #endif
  179. if (!strcmp(var, "print-type"))
  180. return parse_callchain_mode(value);
  181. if (!strcmp(var, "order"))
  182. return parse_callchain_order(value);
  183. if (!strcmp(var, "sort-key"))
  184. return parse_callchain_sort_key(value);
  185. if (!strcmp(var, "threshold")) {
  186. callchain_param.min_percent = strtod(value, &endptr);
  187. if (value == endptr)
  188. return -1;
  189. }
  190. if (!strcmp(var, "print-limit")) {
  191. callchain_param.print_limit = strtod(value, &endptr);
  192. if (value == endptr)
  193. return -1;
  194. }
  195. return 0;
  196. }
  197. static void
  198. rb_insert_callchain(struct rb_root *root, struct callchain_node *chain,
  199. enum chain_mode mode)
  200. {
  201. struct rb_node **p = &root->rb_node;
  202. struct rb_node *parent = NULL;
  203. struct callchain_node *rnode;
  204. u64 chain_cumul = callchain_cumul_hits(chain);
  205. while (*p) {
  206. u64 rnode_cumul;
  207. parent = *p;
  208. rnode = rb_entry(parent, struct callchain_node, rb_node);
  209. rnode_cumul = callchain_cumul_hits(rnode);
  210. switch (mode) {
  211. case CHAIN_FLAT:
  212. case CHAIN_FOLDED:
  213. if (rnode->hit < chain->hit)
  214. p = &(*p)->rb_left;
  215. else
  216. p = &(*p)->rb_right;
  217. break;
  218. case CHAIN_GRAPH_ABS: /* Falldown */
  219. case CHAIN_GRAPH_REL:
  220. if (rnode_cumul < chain_cumul)
  221. p = &(*p)->rb_left;
  222. else
  223. p = &(*p)->rb_right;
  224. break;
  225. case CHAIN_NONE:
  226. default:
  227. break;
  228. }
  229. }
  230. rb_link_node(&chain->rb_node, parent, p);
  231. rb_insert_color(&chain->rb_node, root);
  232. }
  233. static void
  234. __sort_chain_flat(struct rb_root *rb_root, struct callchain_node *node,
  235. u64 min_hit)
  236. {
  237. struct rb_node *n;
  238. struct callchain_node *child;
  239. n = rb_first(&node->rb_root_in);
  240. while (n) {
  241. child = rb_entry(n, struct callchain_node, rb_node_in);
  242. n = rb_next(n);
  243. __sort_chain_flat(rb_root, child, min_hit);
  244. }
  245. if (node->hit && node->hit >= min_hit)
  246. rb_insert_callchain(rb_root, node, CHAIN_FLAT);
  247. }
  248. /*
  249. * Once we get every callchains from the stream, we can now
  250. * sort them by hit
  251. */
  252. static void
  253. sort_chain_flat(struct rb_root *rb_root, struct callchain_root *root,
  254. u64 min_hit, struct callchain_param *param __maybe_unused)
  255. {
  256. *rb_root = RB_ROOT;
  257. __sort_chain_flat(rb_root, &root->node, min_hit);
  258. }
  259. static void __sort_chain_graph_abs(struct callchain_node *node,
  260. u64 min_hit)
  261. {
  262. struct rb_node *n;
  263. struct callchain_node *child;
  264. node->rb_root = RB_ROOT;
  265. n = rb_first(&node->rb_root_in);
  266. while (n) {
  267. child = rb_entry(n, struct callchain_node, rb_node_in);
  268. n = rb_next(n);
  269. __sort_chain_graph_abs(child, min_hit);
  270. if (callchain_cumul_hits(child) >= min_hit)
  271. rb_insert_callchain(&node->rb_root, child,
  272. CHAIN_GRAPH_ABS);
  273. }
  274. }
  275. static void
  276. sort_chain_graph_abs(struct rb_root *rb_root, struct callchain_root *chain_root,
  277. u64 min_hit, struct callchain_param *param __maybe_unused)
  278. {
  279. __sort_chain_graph_abs(&chain_root->node, min_hit);
  280. rb_root->rb_node = chain_root->node.rb_root.rb_node;
  281. }
  282. static void __sort_chain_graph_rel(struct callchain_node *node,
  283. double min_percent)
  284. {
  285. struct rb_node *n;
  286. struct callchain_node *child;
  287. u64 min_hit;
  288. node->rb_root = RB_ROOT;
  289. min_hit = ceil(node->children_hit * min_percent);
  290. n = rb_first(&node->rb_root_in);
  291. while (n) {
  292. child = rb_entry(n, struct callchain_node, rb_node_in);
  293. n = rb_next(n);
  294. __sort_chain_graph_rel(child, min_percent);
  295. if (callchain_cumul_hits(child) >= min_hit)
  296. rb_insert_callchain(&node->rb_root, child,
  297. CHAIN_GRAPH_REL);
  298. }
  299. }
  300. static void
  301. sort_chain_graph_rel(struct rb_root *rb_root, struct callchain_root *chain_root,
  302. u64 min_hit __maybe_unused, struct callchain_param *param)
  303. {
  304. __sort_chain_graph_rel(&chain_root->node, param->min_percent / 100.0);
  305. rb_root->rb_node = chain_root->node.rb_root.rb_node;
  306. }
  307. int callchain_register_param(struct callchain_param *param)
  308. {
  309. switch (param->mode) {
  310. case CHAIN_GRAPH_ABS:
  311. param->sort = sort_chain_graph_abs;
  312. break;
  313. case CHAIN_GRAPH_REL:
  314. param->sort = sort_chain_graph_rel;
  315. break;
  316. case CHAIN_FLAT:
  317. case CHAIN_FOLDED:
  318. param->sort = sort_chain_flat;
  319. break;
  320. case CHAIN_NONE:
  321. default:
  322. return -1;
  323. }
  324. return 0;
  325. }
  326. /*
  327. * Create a child for a parent. If inherit_children, then the new child
  328. * will become the new parent of it's parent children
  329. */
  330. static struct callchain_node *
  331. create_child(struct callchain_node *parent, bool inherit_children)
  332. {
  333. struct callchain_node *new;
  334. new = zalloc(sizeof(*new));
  335. if (!new) {
  336. perror("not enough memory to create child for code path tree");
  337. return NULL;
  338. }
  339. new->parent = parent;
  340. INIT_LIST_HEAD(&new->val);
  341. INIT_LIST_HEAD(&new->parent_val);
  342. if (inherit_children) {
  343. struct rb_node *n;
  344. struct callchain_node *child;
  345. new->rb_root_in = parent->rb_root_in;
  346. parent->rb_root_in = RB_ROOT;
  347. n = rb_first(&new->rb_root_in);
  348. while (n) {
  349. child = rb_entry(n, struct callchain_node, rb_node_in);
  350. child->parent = new;
  351. n = rb_next(n);
  352. }
  353. /* make it the first child */
  354. rb_link_node(&new->rb_node_in, NULL, &parent->rb_root_in.rb_node);
  355. rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
  356. }
  357. return new;
  358. }
  359. /*
  360. * Fill the node with callchain values
  361. */
  362. static void
  363. fill_node(struct callchain_node *node, struct callchain_cursor *cursor)
  364. {
  365. struct callchain_cursor_node *cursor_node;
  366. node->val_nr = cursor->nr - cursor->pos;
  367. if (!node->val_nr)
  368. pr_warning("Warning: empty node in callchain tree\n");
  369. cursor_node = callchain_cursor_current(cursor);
  370. while (cursor_node) {
  371. struct callchain_list *call;
  372. call = zalloc(sizeof(*call));
  373. if (!call) {
  374. perror("not enough memory for the code path tree");
  375. return;
  376. }
  377. call->ip = cursor_node->ip;
  378. call->ms.sym = cursor_node->sym;
  379. call->ms.map = cursor_node->map;
  380. list_add_tail(&call->list, &node->val);
  381. callchain_cursor_advance(cursor);
  382. cursor_node = callchain_cursor_current(cursor);
  383. }
  384. }
  385. static struct callchain_node *
  386. add_child(struct callchain_node *parent,
  387. struct callchain_cursor *cursor,
  388. u64 period)
  389. {
  390. struct callchain_node *new;
  391. new = create_child(parent, false);
  392. fill_node(new, cursor);
  393. new->children_hit = 0;
  394. new->hit = period;
  395. new->children_count = 0;
  396. new->count = 1;
  397. return new;
  398. }
  399. static s64 match_chain(struct callchain_cursor_node *node,
  400. struct callchain_list *cnode)
  401. {
  402. struct symbol *sym = node->sym;
  403. if (cnode->ms.sym && sym &&
  404. callchain_param.key == CCKEY_FUNCTION)
  405. return cnode->ms.sym->start - sym->start;
  406. else
  407. return cnode->ip - node->ip;
  408. }
  409. /*
  410. * Split the parent in two parts (a new child is created) and
  411. * give a part of its callchain to the created child.
  412. * Then create another child to host the given callchain of new branch
  413. */
  414. static void
  415. split_add_child(struct callchain_node *parent,
  416. struct callchain_cursor *cursor,
  417. struct callchain_list *to_split,
  418. u64 idx_parents, u64 idx_local, u64 period)
  419. {
  420. struct callchain_node *new;
  421. struct list_head *old_tail;
  422. unsigned int idx_total = idx_parents + idx_local;
  423. /* split */
  424. new = create_child(parent, true);
  425. /* split the callchain and move a part to the new child */
  426. old_tail = parent->val.prev;
  427. list_del_range(&to_split->list, old_tail);
  428. new->val.next = &to_split->list;
  429. new->val.prev = old_tail;
  430. to_split->list.prev = &new->val;
  431. old_tail->next = &new->val;
  432. /* split the hits */
  433. new->hit = parent->hit;
  434. new->children_hit = parent->children_hit;
  435. parent->children_hit = callchain_cumul_hits(new);
  436. new->val_nr = parent->val_nr - idx_local;
  437. parent->val_nr = idx_local;
  438. new->count = parent->count;
  439. new->children_count = parent->children_count;
  440. parent->children_count = callchain_cumul_counts(new);
  441. /* create a new child for the new branch if any */
  442. if (idx_total < cursor->nr) {
  443. struct callchain_node *first;
  444. struct callchain_list *cnode;
  445. struct callchain_cursor_node *node;
  446. struct rb_node *p, **pp;
  447. parent->hit = 0;
  448. parent->children_hit += period;
  449. parent->count = 0;
  450. parent->children_count += 1;
  451. node = callchain_cursor_current(cursor);
  452. new = add_child(parent, cursor, period);
  453. /*
  454. * This is second child since we moved parent's children
  455. * to new (first) child above.
  456. */
  457. p = parent->rb_root_in.rb_node;
  458. first = rb_entry(p, struct callchain_node, rb_node_in);
  459. cnode = list_first_entry(&first->val, struct callchain_list,
  460. list);
  461. if (match_chain(node, cnode) < 0)
  462. pp = &p->rb_left;
  463. else
  464. pp = &p->rb_right;
  465. rb_link_node(&new->rb_node_in, p, pp);
  466. rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
  467. } else {
  468. parent->hit = period;
  469. parent->count = 1;
  470. }
  471. }
  472. static int
  473. append_chain(struct callchain_node *root,
  474. struct callchain_cursor *cursor,
  475. u64 period);
  476. static void
  477. append_chain_children(struct callchain_node *root,
  478. struct callchain_cursor *cursor,
  479. u64 period)
  480. {
  481. struct callchain_node *rnode;
  482. struct callchain_cursor_node *node;
  483. struct rb_node **p = &root->rb_root_in.rb_node;
  484. struct rb_node *parent = NULL;
  485. node = callchain_cursor_current(cursor);
  486. if (!node)
  487. return;
  488. /* lookup in childrens */
  489. while (*p) {
  490. s64 ret;
  491. parent = *p;
  492. rnode = rb_entry(parent, struct callchain_node, rb_node_in);
  493. /* If at least first entry matches, rely to children */
  494. ret = append_chain(rnode, cursor, period);
  495. if (ret == 0)
  496. goto inc_children_hit;
  497. if (ret < 0)
  498. p = &parent->rb_left;
  499. else
  500. p = &parent->rb_right;
  501. }
  502. /* nothing in children, add to the current node */
  503. rnode = add_child(root, cursor, period);
  504. rb_link_node(&rnode->rb_node_in, parent, p);
  505. rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
  506. inc_children_hit:
  507. root->children_hit += period;
  508. root->children_count++;
  509. }
  510. static int
  511. append_chain(struct callchain_node *root,
  512. struct callchain_cursor *cursor,
  513. u64 period)
  514. {
  515. struct callchain_list *cnode;
  516. u64 start = cursor->pos;
  517. bool found = false;
  518. u64 matches;
  519. int cmp = 0;
  520. /*
  521. * Lookup in the current node
  522. * If we have a symbol, then compare the start to match
  523. * anywhere inside a function, unless function
  524. * mode is disabled.
  525. */
  526. list_for_each_entry(cnode, &root->val, list) {
  527. struct callchain_cursor_node *node;
  528. node = callchain_cursor_current(cursor);
  529. if (!node)
  530. break;
  531. cmp = match_chain(node, cnode);
  532. if (cmp)
  533. break;
  534. found = true;
  535. callchain_cursor_advance(cursor);
  536. }
  537. /* matches not, relay no the parent */
  538. if (!found) {
  539. WARN_ONCE(!cmp, "Chain comparison error\n");
  540. return cmp;
  541. }
  542. matches = cursor->pos - start;
  543. /* we match only a part of the node. Split it and add the new chain */
  544. if (matches < root->val_nr) {
  545. split_add_child(root, cursor, cnode, start, matches, period);
  546. return 0;
  547. }
  548. /* we match 100% of the path, increment the hit */
  549. if (matches == root->val_nr && cursor->pos == cursor->nr) {
  550. root->hit += period;
  551. root->count++;
  552. return 0;
  553. }
  554. /* We match the node and still have a part remaining */
  555. append_chain_children(root, cursor, period);
  556. return 0;
  557. }
  558. int callchain_append(struct callchain_root *root,
  559. struct callchain_cursor *cursor,
  560. u64 period)
  561. {
  562. if (!cursor->nr)
  563. return 0;
  564. callchain_cursor_commit(cursor);
  565. append_chain_children(&root->node, cursor, period);
  566. if (cursor->nr > root->max_depth)
  567. root->max_depth = cursor->nr;
  568. return 0;
  569. }
  570. static int
  571. merge_chain_branch(struct callchain_cursor *cursor,
  572. struct callchain_node *dst, struct callchain_node *src)
  573. {
  574. struct callchain_cursor_node **old_last = cursor->last;
  575. struct callchain_node *child;
  576. struct callchain_list *list, *next_list;
  577. struct rb_node *n;
  578. int old_pos = cursor->nr;
  579. int err = 0;
  580. list_for_each_entry_safe(list, next_list, &src->val, list) {
  581. callchain_cursor_append(cursor, list->ip,
  582. list->ms.map, list->ms.sym);
  583. list_del(&list->list);
  584. free(list);
  585. }
  586. if (src->hit) {
  587. callchain_cursor_commit(cursor);
  588. append_chain_children(dst, cursor, src->hit);
  589. }
  590. n = rb_first(&src->rb_root_in);
  591. while (n) {
  592. child = container_of(n, struct callchain_node, rb_node_in);
  593. n = rb_next(n);
  594. rb_erase(&child->rb_node_in, &src->rb_root_in);
  595. err = merge_chain_branch(cursor, dst, child);
  596. if (err)
  597. break;
  598. free(child);
  599. }
  600. cursor->nr = old_pos;
  601. cursor->last = old_last;
  602. return err;
  603. }
  604. int callchain_merge(struct callchain_cursor *cursor,
  605. struct callchain_root *dst, struct callchain_root *src)
  606. {
  607. return merge_chain_branch(cursor, &dst->node, &src->node);
  608. }
  609. int callchain_cursor_append(struct callchain_cursor *cursor,
  610. u64 ip, struct map *map, struct symbol *sym)
  611. {
  612. struct callchain_cursor_node *node = *cursor->last;
  613. if (!node) {
  614. node = calloc(1, sizeof(*node));
  615. if (!node)
  616. return -ENOMEM;
  617. *cursor->last = node;
  618. }
  619. node->ip = ip;
  620. node->map = map;
  621. node->sym = sym;
  622. cursor->nr++;
  623. cursor->last = &node->next;
  624. return 0;
  625. }
  626. int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
  627. struct perf_evsel *evsel, struct addr_location *al,
  628. int max_stack)
  629. {
  630. if (sample->callchain == NULL)
  631. return 0;
  632. if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
  633. sort__has_parent) {
  634. return thread__resolve_callchain(al->thread, evsel, sample,
  635. parent, al, max_stack);
  636. }
  637. return 0;
  638. }
  639. int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
  640. {
  641. if (!symbol_conf.use_callchain || sample->callchain == NULL)
  642. return 0;
  643. return callchain_append(he->callchain, &callchain_cursor, sample->period);
  644. }
  645. int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
  646. bool hide_unresolved)
  647. {
  648. al->map = node->map;
  649. al->sym = node->sym;
  650. if (node->map)
  651. al->addr = node->map->map_ip(node->map, node->ip);
  652. else
  653. al->addr = node->ip;
  654. if (al->sym == NULL) {
  655. if (hide_unresolved)
  656. return 0;
  657. if (al->map == NULL)
  658. goto out;
  659. }
  660. if (al->map->groups == &al->machine->kmaps) {
  661. if (machine__is_host(al->machine)) {
  662. al->cpumode = PERF_RECORD_MISC_KERNEL;
  663. al->level = 'k';
  664. } else {
  665. al->cpumode = PERF_RECORD_MISC_GUEST_KERNEL;
  666. al->level = 'g';
  667. }
  668. } else {
  669. if (machine__is_host(al->machine)) {
  670. al->cpumode = PERF_RECORD_MISC_USER;
  671. al->level = '.';
  672. } else if (perf_guest) {
  673. al->cpumode = PERF_RECORD_MISC_GUEST_USER;
  674. al->level = 'u';
  675. } else {
  676. al->cpumode = PERF_RECORD_MISC_HYPERVISOR;
  677. al->level = 'H';
  678. }
  679. }
  680. out:
  681. return 1;
  682. }
  683. char *callchain_list__sym_name(struct callchain_list *cl,
  684. char *bf, size_t bfsize, bool show_dso)
  685. {
  686. int printed;
  687. if (cl->ms.sym) {
  688. if (callchain_param.key == CCKEY_ADDRESS &&
  689. cl->ms.map && !cl->srcline)
  690. cl->srcline = get_srcline(cl->ms.map->dso,
  691. map__rip_2objdump(cl->ms.map,
  692. cl->ip),
  693. cl->ms.sym, false);
  694. if (cl->srcline)
  695. printed = scnprintf(bf, bfsize, "%s %s",
  696. cl->ms.sym->name, cl->srcline);
  697. else
  698. printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
  699. } else
  700. printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
  701. if (show_dso)
  702. scnprintf(bf + printed, bfsize - printed, " %s",
  703. cl->ms.map ?
  704. cl->ms.map->dso->short_name :
  705. "unknown");
  706. return bf;
  707. }
  708. char *callchain_node__scnprintf_value(struct callchain_node *node,
  709. char *bf, size_t bfsize, u64 total)
  710. {
  711. double percent = 0.0;
  712. u64 period = callchain_cumul_hits(node);
  713. unsigned count = callchain_cumul_counts(node);
  714. if (callchain_param.mode == CHAIN_FOLDED) {
  715. period = node->hit;
  716. count = node->count;
  717. }
  718. switch (callchain_param.value) {
  719. case CCVAL_PERIOD:
  720. scnprintf(bf, bfsize, "%"PRIu64, period);
  721. break;
  722. case CCVAL_COUNT:
  723. scnprintf(bf, bfsize, "%u", count);
  724. break;
  725. case CCVAL_PERCENT:
  726. default:
  727. if (total)
  728. percent = period * 100.0 / total;
  729. scnprintf(bf, bfsize, "%.2f%%", percent);
  730. break;
  731. }
  732. return bf;
  733. }
  734. int callchain_node__fprintf_value(struct callchain_node *node,
  735. FILE *fp, u64 total)
  736. {
  737. double percent = 0.0;
  738. u64 period = callchain_cumul_hits(node);
  739. unsigned count = callchain_cumul_counts(node);
  740. if (callchain_param.mode == CHAIN_FOLDED) {
  741. period = node->hit;
  742. count = node->count;
  743. }
  744. switch (callchain_param.value) {
  745. case CCVAL_PERIOD:
  746. return fprintf(fp, "%"PRIu64, period);
  747. case CCVAL_COUNT:
  748. return fprintf(fp, "%u", count);
  749. case CCVAL_PERCENT:
  750. default:
  751. if (total)
  752. percent = period * 100.0 / total;
  753. return percent_color_fprintf(fp, "%.2f%%", percent);
  754. }
  755. return 0;
  756. }
  757. static void free_callchain_node(struct callchain_node *node)
  758. {
  759. struct callchain_list *list, *tmp;
  760. struct callchain_node *child;
  761. struct rb_node *n;
  762. list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
  763. list_del(&list->list);
  764. free(list);
  765. }
  766. list_for_each_entry_safe(list, tmp, &node->val, list) {
  767. list_del(&list->list);
  768. free(list);
  769. }
  770. n = rb_first(&node->rb_root_in);
  771. while (n) {
  772. child = container_of(n, struct callchain_node, rb_node_in);
  773. n = rb_next(n);
  774. rb_erase(&child->rb_node_in, &node->rb_root_in);
  775. free_callchain_node(child);
  776. free(child);
  777. }
  778. }
  779. void free_callchain(struct callchain_root *root)
  780. {
  781. if (!symbol_conf.use_callchain)
  782. return;
  783. free_callchain_node(&root->node);
  784. }
  785. static u64 decay_callchain_node(struct callchain_node *node)
  786. {
  787. struct callchain_node *child;
  788. struct rb_node *n;
  789. u64 child_hits = 0;
  790. n = rb_first(&node->rb_root_in);
  791. while (n) {
  792. child = container_of(n, struct callchain_node, rb_node_in);
  793. child_hits += decay_callchain_node(child);
  794. n = rb_next(n);
  795. }
  796. node->hit = (node->hit * 7) / 8;
  797. node->children_hit = child_hits;
  798. return node->hit;
  799. }
  800. void decay_callchain(struct callchain_root *root)
  801. {
  802. if (!symbol_conf.use_callchain)
  803. return;
  804. decay_callchain_node(&root->node);
  805. }
  806. int callchain_node__make_parent_list(struct callchain_node *node)
  807. {
  808. struct callchain_node *parent = node->parent;
  809. struct callchain_list *chain, *new;
  810. LIST_HEAD(head);
  811. while (parent) {
  812. list_for_each_entry_reverse(chain, &parent->val, list) {
  813. new = malloc(sizeof(*new));
  814. if (new == NULL)
  815. goto out;
  816. *new = *chain;
  817. new->has_children = false;
  818. list_add_tail(&new->list, &head);
  819. }
  820. parent = parent->parent;
  821. }
  822. list_for_each_entry_safe_reverse(chain, new, &head, list)
  823. list_move_tail(&chain->list, &node->parent_val);
  824. if (!list_empty(&node->parent_val)) {
  825. chain = list_first_entry(&node->parent_val, struct callchain_list, list);
  826. chain->has_children = rb_prev(&node->rb_node) || rb_next(&node->rb_node);
  827. chain = list_first_entry(&node->val, struct callchain_list, list);
  828. chain->has_children = false;
  829. }
  830. return 0;
  831. out:
  832. list_for_each_entry_safe(chain, new, &head, list) {
  833. list_del(&chain->list);
  834. free(chain);
  835. }
  836. return -ENOMEM;
  837. }