callchain.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  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 int
  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 -1;
  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. return 0;
  385. }
  386. static struct callchain_node *
  387. add_child(struct callchain_node *parent,
  388. struct callchain_cursor *cursor,
  389. u64 period)
  390. {
  391. struct callchain_node *new;
  392. new = create_child(parent, false);
  393. if (new == NULL)
  394. return NULL;
  395. if (fill_node(new, cursor) < 0) {
  396. struct callchain_list *call, *tmp;
  397. list_for_each_entry_safe(call, tmp, &new->val, list) {
  398. list_del(&call->list);
  399. free(call);
  400. }
  401. free(new);
  402. return NULL;
  403. }
  404. new->children_hit = 0;
  405. new->hit = period;
  406. new->children_count = 0;
  407. new->count = 1;
  408. return new;
  409. }
  410. enum match_result {
  411. MATCH_ERROR = -1,
  412. MATCH_EQ,
  413. MATCH_LT,
  414. MATCH_GT,
  415. };
  416. static enum match_result match_chain(struct callchain_cursor_node *node,
  417. struct callchain_list *cnode)
  418. {
  419. struct symbol *sym = node->sym;
  420. u64 left, right;
  421. if (cnode->ms.sym && sym &&
  422. callchain_param.key == CCKEY_FUNCTION) {
  423. left = cnode->ms.sym->start;
  424. right = sym->start;
  425. } else {
  426. left = cnode->ip;
  427. right = node->ip;
  428. }
  429. if (left == right)
  430. return MATCH_EQ;
  431. return left > right ? MATCH_GT : MATCH_LT;
  432. }
  433. /*
  434. * Split the parent in two parts (a new child is created) and
  435. * give a part of its callchain to the created child.
  436. * Then create another child to host the given callchain of new branch
  437. */
  438. static int
  439. split_add_child(struct callchain_node *parent,
  440. struct callchain_cursor *cursor,
  441. struct callchain_list *to_split,
  442. u64 idx_parents, u64 idx_local, u64 period)
  443. {
  444. struct callchain_node *new;
  445. struct list_head *old_tail;
  446. unsigned int idx_total = idx_parents + idx_local;
  447. /* split */
  448. new = create_child(parent, true);
  449. if (new == NULL)
  450. return -1;
  451. /* split the callchain and move a part to the new child */
  452. old_tail = parent->val.prev;
  453. list_del_range(&to_split->list, old_tail);
  454. new->val.next = &to_split->list;
  455. new->val.prev = old_tail;
  456. to_split->list.prev = &new->val;
  457. old_tail->next = &new->val;
  458. /* split the hits */
  459. new->hit = parent->hit;
  460. new->children_hit = parent->children_hit;
  461. parent->children_hit = callchain_cumul_hits(new);
  462. new->val_nr = parent->val_nr - idx_local;
  463. parent->val_nr = idx_local;
  464. new->count = parent->count;
  465. new->children_count = parent->children_count;
  466. parent->children_count = callchain_cumul_counts(new);
  467. /* create a new child for the new branch if any */
  468. if (idx_total < cursor->nr) {
  469. struct callchain_node *first;
  470. struct callchain_list *cnode;
  471. struct callchain_cursor_node *node;
  472. struct rb_node *p, **pp;
  473. parent->hit = 0;
  474. parent->children_hit += period;
  475. parent->count = 0;
  476. parent->children_count += 1;
  477. node = callchain_cursor_current(cursor);
  478. new = add_child(parent, cursor, period);
  479. if (new == NULL)
  480. return -1;
  481. /*
  482. * This is second child since we moved parent's children
  483. * to new (first) child above.
  484. */
  485. p = parent->rb_root_in.rb_node;
  486. first = rb_entry(p, struct callchain_node, rb_node_in);
  487. cnode = list_first_entry(&first->val, struct callchain_list,
  488. list);
  489. if (match_chain(node, cnode) == MATCH_LT)
  490. pp = &p->rb_left;
  491. else
  492. pp = &p->rb_right;
  493. rb_link_node(&new->rb_node_in, p, pp);
  494. rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
  495. } else {
  496. parent->hit = period;
  497. parent->count = 1;
  498. }
  499. return 0;
  500. }
  501. static enum match_result
  502. append_chain(struct callchain_node *root,
  503. struct callchain_cursor *cursor,
  504. u64 period);
  505. static int
  506. append_chain_children(struct callchain_node *root,
  507. struct callchain_cursor *cursor,
  508. u64 period)
  509. {
  510. struct callchain_node *rnode;
  511. struct callchain_cursor_node *node;
  512. struct rb_node **p = &root->rb_root_in.rb_node;
  513. struct rb_node *parent = NULL;
  514. node = callchain_cursor_current(cursor);
  515. if (!node)
  516. return -1;
  517. /* lookup in childrens */
  518. while (*p) {
  519. enum match_result ret;
  520. parent = *p;
  521. rnode = rb_entry(parent, struct callchain_node, rb_node_in);
  522. /* If at least first entry matches, rely to children */
  523. ret = append_chain(rnode, cursor, period);
  524. if (ret == MATCH_EQ)
  525. goto inc_children_hit;
  526. if (ret == MATCH_ERROR)
  527. return -1;
  528. if (ret == MATCH_LT)
  529. p = &parent->rb_left;
  530. else
  531. p = &parent->rb_right;
  532. }
  533. /* nothing in children, add to the current node */
  534. rnode = add_child(root, cursor, period);
  535. if (rnode == NULL)
  536. return -1;
  537. rb_link_node(&rnode->rb_node_in, parent, p);
  538. rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
  539. inc_children_hit:
  540. root->children_hit += period;
  541. root->children_count++;
  542. return 0;
  543. }
  544. static enum match_result
  545. append_chain(struct callchain_node *root,
  546. struct callchain_cursor *cursor,
  547. u64 period)
  548. {
  549. struct callchain_list *cnode;
  550. u64 start = cursor->pos;
  551. bool found = false;
  552. u64 matches;
  553. enum match_result cmp = MATCH_ERROR;
  554. /*
  555. * Lookup in the current node
  556. * If we have a symbol, then compare the start to match
  557. * anywhere inside a function, unless function
  558. * mode is disabled.
  559. */
  560. list_for_each_entry(cnode, &root->val, list) {
  561. struct callchain_cursor_node *node;
  562. node = callchain_cursor_current(cursor);
  563. if (!node)
  564. break;
  565. cmp = match_chain(node, cnode);
  566. if (cmp != MATCH_EQ)
  567. break;
  568. found = true;
  569. callchain_cursor_advance(cursor);
  570. }
  571. /* matches not, relay no the parent */
  572. if (!found) {
  573. WARN_ONCE(cmp == MATCH_ERROR, "Chain comparison error\n");
  574. return cmp;
  575. }
  576. matches = cursor->pos - start;
  577. /* we match only a part of the node. Split it and add the new chain */
  578. if (matches < root->val_nr) {
  579. if (split_add_child(root, cursor, cnode, start, matches,
  580. period) < 0)
  581. return MATCH_ERROR;
  582. return MATCH_EQ;
  583. }
  584. /* we match 100% of the path, increment the hit */
  585. if (matches == root->val_nr && cursor->pos == cursor->nr) {
  586. root->hit += period;
  587. root->count++;
  588. return MATCH_EQ;
  589. }
  590. /* We match the node and still have a part remaining */
  591. if (append_chain_children(root, cursor, period) < 0)
  592. return MATCH_ERROR;
  593. return MATCH_EQ;
  594. }
  595. int callchain_append(struct callchain_root *root,
  596. struct callchain_cursor *cursor,
  597. u64 period)
  598. {
  599. if (!cursor->nr)
  600. return 0;
  601. callchain_cursor_commit(cursor);
  602. if (append_chain_children(&root->node, cursor, period) < 0)
  603. return -1;
  604. if (cursor->nr > root->max_depth)
  605. root->max_depth = cursor->nr;
  606. return 0;
  607. }
  608. static int
  609. merge_chain_branch(struct callchain_cursor *cursor,
  610. struct callchain_node *dst, struct callchain_node *src)
  611. {
  612. struct callchain_cursor_node **old_last = cursor->last;
  613. struct callchain_node *child;
  614. struct callchain_list *list, *next_list;
  615. struct rb_node *n;
  616. int old_pos = cursor->nr;
  617. int err = 0;
  618. list_for_each_entry_safe(list, next_list, &src->val, list) {
  619. callchain_cursor_append(cursor, list->ip,
  620. list->ms.map, list->ms.sym);
  621. list_del(&list->list);
  622. free(list);
  623. }
  624. if (src->hit) {
  625. callchain_cursor_commit(cursor);
  626. if (append_chain_children(dst, cursor, src->hit) < 0)
  627. return -1;
  628. }
  629. n = rb_first(&src->rb_root_in);
  630. while (n) {
  631. child = container_of(n, struct callchain_node, rb_node_in);
  632. n = rb_next(n);
  633. rb_erase(&child->rb_node_in, &src->rb_root_in);
  634. err = merge_chain_branch(cursor, dst, child);
  635. if (err)
  636. break;
  637. free(child);
  638. }
  639. cursor->nr = old_pos;
  640. cursor->last = old_last;
  641. return err;
  642. }
  643. int callchain_merge(struct callchain_cursor *cursor,
  644. struct callchain_root *dst, struct callchain_root *src)
  645. {
  646. return merge_chain_branch(cursor, &dst->node, &src->node);
  647. }
  648. int callchain_cursor_append(struct callchain_cursor *cursor,
  649. u64 ip, struct map *map, struct symbol *sym)
  650. {
  651. struct callchain_cursor_node *node = *cursor->last;
  652. if (!node) {
  653. node = calloc(1, sizeof(*node));
  654. if (!node)
  655. return -ENOMEM;
  656. *cursor->last = node;
  657. }
  658. node->ip = ip;
  659. node->map = map;
  660. node->sym = sym;
  661. cursor->nr++;
  662. cursor->last = &node->next;
  663. return 0;
  664. }
  665. int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,
  666. struct perf_evsel *evsel, struct addr_location *al,
  667. int max_stack)
  668. {
  669. if (sample->callchain == NULL)
  670. return 0;
  671. if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
  672. sort__has_parent) {
  673. return thread__resolve_callchain(al->thread, evsel, sample,
  674. parent, al, max_stack);
  675. }
  676. return 0;
  677. }
  678. int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
  679. {
  680. if (!symbol_conf.use_callchain || sample->callchain == NULL)
  681. return 0;
  682. return callchain_append(he->callchain, &callchain_cursor, sample->period);
  683. }
  684. int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
  685. bool hide_unresolved)
  686. {
  687. al->map = node->map;
  688. al->sym = node->sym;
  689. if (node->map)
  690. al->addr = node->map->map_ip(node->map, node->ip);
  691. else
  692. al->addr = node->ip;
  693. if (al->sym == NULL) {
  694. if (hide_unresolved)
  695. return 0;
  696. if (al->map == NULL)
  697. goto out;
  698. }
  699. if (al->map->groups == &al->machine->kmaps) {
  700. if (machine__is_host(al->machine)) {
  701. al->cpumode = PERF_RECORD_MISC_KERNEL;
  702. al->level = 'k';
  703. } else {
  704. al->cpumode = PERF_RECORD_MISC_GUEST_KERNEL;
  705. al->level = 'g';
  706. }
  707. } else {
  708. if (machine__is_host(al->machine)) {
  709. al->cpumode = PERF_RECORD_MISC_USER;
  710. al->level = '.';
  711. } else if (perf_guest) {
  712. al->cpumode = PERF_RECORD_MISC_GUEST_USER;
  713. al->level = 'u';
  714. } else {
  715. al->cpumode = PERF_RECORD_MISC_HYPERVISOR;
  716. al->level = 'H';
  717. }
  718. }
  719. out:
  720. return 1;
  721. }
  722. char *callchain_list__sym_name(struct callchain_list *cl,
  723. char *bf, size_t bfsize, bool show_dso)
  724. {
  725. int printed;
  726. if (cl->ms.sym) {
  727. if (callchain_param.key == CCKEY_ADDRESS &&
  728. cl->ms.map && !cl->srcline)
  729. cl->srcline = get_srcline(cl->ms.map->dso,
  730. map__rip_2objdump(cl->ms.map,
  731. cl->ip),
  732. cl->ms.sym, false);
  733. if (cl->srcline)
  734. printed = scnprintf(bf, bfsize, "%s %s",
  735. cl->ms.sym->name, cl->srcline);
  736. else
  737. printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
  738. } else
  739. printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
  740. if (show_dso)
  741. scnprintf(bf + printed, bfsize - printed, " %s",
  742. cl->ms.map ?
  743. cl->ms.map->dso->short_name :
  744. "unknown");
  745. return bf;
  746. }
  747. char *callchain_node__scnprintf_value(struct callchain_node *node,
  748. char *bf, size_t bfsize, u64 total)
  749. {
  750. double percent = 0.0;
  751. u64 period = callchain_cumul_hits(node);
  752. unsigned count = callchain_cumul_counts(node);
  753. if (callchain_param.mode == CHAIN_FOLDED) {
  754. period = node->hit;
  755. count = node->count;
  756. }
  757. switch (callchain_param.value) {
  758. case CCVAL_PERIOD:
  759. scnprintf(bf, bfsize, "%"PRIu64, period);
  760. break;
  761. case CCVAL_COUNT:
  762. scnprintf(bf, bfsize, "%u", count);
  763. break;
  764. case CCVAL_PERCENT:
  765. default:
  766. if (total)
  767. percent = period * 100.0 / total;
  768. scnprintf(bf, bfsize, "%.2f%%", percent);
  769. break;
  770. }
  771. return bf;
  772. }
  773. int callchain_node__fprintf_value(struct callchain_node *node,
  774. FILE *fp, u64 total)
  775. {
  776. double percent = 0.0;
  777. u64 period = callchain_cumul_hits(node);
  778. unsigned count = callchain_cumul_counts(node);
  779. if (callchain_param.mode == CHAIN_FOLDED) {
  780. period = node->hit;
  781. count = node->count;
  782. }
  783. switch (callchain_param.value) {
  784. case CCVAL_PERIOD:
  785. return fprintf(fp, "%"PRIu64, period);
  786. case CCVAL_COUNT:
  787. return fprintf(fp, "%u", count);
  788. case CCVAL_PERCENT:
  789. default:
  790. if (total)
  791. percent = period * 100.0 / total;
  792. return percent_color_fprintf(fp, "%.2f%%", percent);
  793. }
  794. return 0;
  795. }
  796. static void free_callchain_node(struct callchain_node *node)
  797. {
  798. struct callchain_list *list, *tmp;
  799. struct callchain_node *child;
  800. struct rb_node *n;
  801. list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
  802. list_del(&list->list);
  803. free(list);
  804. }
  805. list_for_each_entry_safe(list, tmp, &node->val, list) {
  806. list_del(&list->list);
  807. free(list);
  808. }
  809. n = rb_first(&node->rb_root_in);
  810. while (n) {
  811. child = container_of(n, struct callchain_node, rb_node_in);
  812. n = rb_next(n);
  813. rb_erase(&child->rb_node_in, &node->rb_root_in);
  814. free_callchain_node(child);
  815. free(child);
  816. }
  817. }
  818. void free_callchain(struct callchain_root *root)
  819. {
  820. if (!symbol_conf.use_callchain)
  821. return;
  822. free_callchain_node(&root->node);
  823. }
  824. static u64 decay_callchain_node(struct callchain_node *node)
  825. {
  826. struct callchain_node *child;
  827. struct rb_node *n;
  828. u64 child_hits = 0;
  829. n = rb_first(&node->rb_root_in);
  830. while (n) {
  831. child = container_of(n, struct callchain_node, rb_node_in);
  832. child_hits += decay_callchain_node(child);
  833. n = rb_next(n);
  834. }
  835. node->hit = (node->hit * 7) / 8;
  836. node->children_hit = child_hits;
  837. return node->hit;
  838. }
  839. void decay_callchain(struct callchain_root *root)
  840. {
  841. if (!symbol_conf.use_callchain)
  842. return;
  843. decay_callchain_node(&root->node);
  844. }
  845. int callchain_node__make_parent_list(struct callchain_node *node)
  846. {
  847. struct callchain_node *parent = node->parent;
  848. struct callchain_list *chain, *new;
  849. LIST_HEAD(head);
  850. while (parent) {
  851. list_for_each_entry_reverse(chain, &parent->val, list) {
  852. new = malloc(sizeof(*new));
  853. if (new == NULL)
  854. goto out;
  855. *new = *chain;
  856. new->has_children = false;
  857. list_add_tail(&new->list, &head);
  858. }
  859. parent = parent->parent;
  860. }
  861. list_for_each_entry_safe_reverse(chain, new, &head, list)
  862. list_move_tail(&chain->list, &node->parent_val);
  863. if (!list_empty(&node->parent_val)) {
  864. chain = list_first_entry(&node->parent_val, struct callchain_list, list);
  865. chain->has_children = rb_prev(&node->rb_node) || rb_next(&node->rb_node);
  866. chain = list_first_entry(&node->val, struct callchain_list, list);
  867. chain->has_children = false;
  868. }
  869. return 0;
  870. out:
  871. list_for_each_entry_safe(chain, new, &head, list) {
  872. list_del(&chain->list);
  873. free(chain);
  874. }
  875. return -ENOMEM;
  876. }