callchain.c 24 KB

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