callchain.c 23 KB

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