callchain.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263
  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 = cursor_node->map;
  380. if (cursor_node->branch) {
  381. call->branch_count = 1;
  382. if (cursor_node->branch_flags.predicted)
  383. call->predicted_count = 1;
  384. if (cursor_node->branch_flags.abort)
  385. call->abort_count = 1;
  386. call->cycles_count = cursor_node->branch_flags.cycles;
  387. call->iter_count = cursor_node->nr_loop_iter;
  388. call->samples_count = cursor_node->samples;
  389. }
  390. list_add_tail(&call->list, &node->val);
  391. callchain_cursor_advance(cursor);
  392. cursor_node = callchain_cursor_current(cursor);
  393. }
  394. return 0;
  395. }
  396. static struct callchain_node *
  397. add_child(struct callchain_node *parent,
  398. struct callchain_cursor *cursor,
  399. u64 period)
  400. {
  401. struct callchain_node *new;
  402. new = create_child(parent, false);
  403. if (new == NULL)
  404. return NULL;
  405. if (fill_node(new, cursor) < 0) {
  406. struct callchain_list *call, *tmp;
  407. list_for_each_entry_safe(call, tmp, &new->val, list) {
  408. list_del(&call->list);
  409. free(call);
  410. }
  411. free(new);
  412. return NULL;
  413. }
  414. new->children_hit = 0;
  415. new->hit = period;
  416. new->children_count = 0;
  417. new->count = 1;
  418. return new;
  419. }
  420. enum match_result {
  421. MATCH_ERROR = -1,
  422. MATCH_EQ,
  423. MATCH_LT,
  424. MATCH_GT,
  425. };
  426. static enum match_result match_chain(struct callchain_cursor_node *node,
  427. struct callchain_list *cnode)
  428. {
  429. struct symbol *sym = node->sym;
  430. u64 left, right;
  431. if (cnode->ms.sym && sym &&
  432. callchain_param.key == CCKEY_FUNCTION) {
  433. left = cnode->ms.sym->start;
  434. right = sym->start;
  435. } else {
  436. left = cnode->ip;
  437. right = node->ip;
  438. }
  439. if (left == right) {
  440. if (node->branch) {
  441. cnode->branch_count++;
  442. if (node->branch_flags.predicted)
  443. cnode->predicted_count++;
  444. if (node->branch_flags.abort)
  445. cnode->abort_count++;
  446. cnode->cycles_count += node->branch_flags.cycles;
  447. cnode->iter_count += node->nr_loop_iter;
  448. cnode->samples_count += node->samples;
  449. }
  450. return MATCH_EQ;
  451. }
  452. return left > right ? MATCH_GT : MATCH_LT;
  453. }
  454. /*
  455. * Split the parent in two parts (a new child is created) and
  456. * give a part of its callchain to the created child.
  457. * Then create another child to host the given callchain of new branch
  458. */
  459. static int
  460. split_add_child(struct callchain_node *parent,
  461. struct callchain_cursor *cursor,
  462. struct callchain_list *to_split,
  463. u64 idx_parents, u64 idx_local, u64 period)
  464. {
  465. struct callchain_node *new;
  466. struct list_head *old_tail;
  467. unsigned int idx_total = idx_parents + idx_local;
  468. /* split */
  469. new = create_child(parent, true);
  470. if (new == NULL)
  471. return -1;
  472. /* split the callchain and move a part to the new child */
  473. old_tail = parent->val.prev;
  474. list_del_range(&to_split->list, old_tail);
  475. new->val.next = &to_split->list;
  476. new->val.prev = old_tail;
  477. to_split->list.prev = &new->val;
  478. old_tail->next = &new->val;
  479. /* split the hits */
  480. new->hit = parent->hit;
  481. new->children_hit = parent->children_hit;
  482. parent->children_hit = callchain_cumul_hits(new);
  483. new->val_nr = parent->val_nr - idx_local;
  484. parent->val_nr = idx_local;
  485. new->count = parent->count;
  486. new->children_count = parent->children_count;
  487. parent->children_count = callchain_cumul_counts(new);
  488. /* create a new child for the new branch if any */
  489. if (idx_total < cursor->nr) {
  490. struct callchain_node *first;
  491. struct callchain_list *cnode;
  492. struct callchain_cursor_node *node;
  493. struct rb_node *p, **pp;
  494. parent->hit = 0;
  495. parent->children_hit += period;
  496. parent->count = 0;
  497. parent->children_count += 1;
  498. node = callchain_cursor_current(cursor);
  499. new = add_child(parent, cursor, period);
  500. if (new == NULL)
  501. return -1;
  502. /*
  503. * This is second child since we moved parent's children
  504. * to new (first) child above.
  505. */
  506. p = parent->rb_root_in.rb_node;
  507. first = rb_entry(p, struct callchain_node, rb_node_in);
  508. cnode = list_first_entry(&first->val, struct callchain_list,
  509. list);
  510. if (match_chain(node, cnode) == MATCH_LT)
  511. pp = &p->rb_left;
  512. else
  513. pp = &p->rb_right;
  514. rb_link_node(&new->rb_node_in, p, pp);
  515. rb_insert_color(&new->rb_node_in, &parent->rb_root_in);
  516. } else {
  517. parent->hit = period;
  518. parent->count = 1;
  519. }
  520. return 0;
  521. }
  522. static enum match_result
  523. append_chain(struct callchain_node *root,
  524. struct callchain_cursor *cursor,
  525. u64 period);
  526. static int
  527. append_chain_children(struct callchain_node *root,
  528. struct callchain_cursor *cursor,
  529. u64 period)
  530. {
  531. struct callchain_node *rnode;
  532. struct callchain_cursor_node *node;
  533. struct rb_node **p = &root->rb_root_in.rb_node;
  534. struct rb_node *parent = NULL;
  535. node = callchain_cursor_current(cursor);
  536. if (!node)
  537. return -1;
  538. /* lookup in childrens */
  539. while (*p) {
  540. enum match_result ret;
  541. parent = *p;
  542. rnode = rb_entry(parent, struct callchain_node, rb_node_in);
  543. /* If at least first entry matches, rely to children */
  544. ret = append_chain(rnode, cursor, period);
  545. if (ret == MATCH_EQ)
  546. goto inc_children_hit;
  547. if (ret == MATCH_ERROR)
  548. return -1;
  549. if (ret == MATCH_LT)
  550. p = &parent->rb_left;
  551. else
  552. p = &parent->rb_right;
  553. }
  554. /* nothing in children, add to the current node */
  555. rnode = add_child(root, cursor, period);
  556. if (rnode == NULL)
  557. return -1;
  558. rb_link_node(&rnode->rb_node_in, parent, p);
  559. rb_insert_color(&rnode->rb_node_in, &root->rb_root_in);
  560. inc_children_hit:
  561. root->children_hit += period;
  562. root->children_count++;
  563. return 0;
  564. }
  565. static enum match_result
  566. append_chain(struct callchain_node *root,
  567. struct callchain_cursor *cursor,
  568. u64 period)
  569. {
  570. struct callchain_list *cnode;
  571. u64 start = cursor->pos;
  572. bool found = false;
  573. u64 matches;
  574. enum match_result cmp = MATCH_ERROR;
  575. /*
  576. * Lookup in the current node
  577. * If we have a symbol, then compare the start to match
  578. * anywhere inside a function, unless function
  579. * mode is disabled.
  580. */
  581. list_for_each_entry(cnode, &root->val, list) {
  582. struct callchain_cursor_node *node;
  583. node = callchain_cursor_current(cursor);
  584. if (!node)
  585. break;
  586. cmp = match_chain(node, cnode);
  587. if (cmp != MATCH_EQ)
  588. break;
  589. found = true;
  590. callchain_cursor_advance(cursor);
  591. }
  592. /* matches not, relay no the parent */
  593. if (!found) {
  594. WARN_ONCE(cmp == MATCH_ERROR, "Chain comparison error\n");
  595. return cmp;
  596. }
  597. matches = cursor->pos - start;
  598. /* we match only a part of the node. Split it and add the new chain */
  599. if (matches < root->val_nr) {
  600. if (split_add_child(root, cursor, cnode, start, matches,
  601. period) < 0)
  602. return MATCH_ERROR;
  603. return MATCH_EQ;
  604. }
  605. /* we match 100% of the path, increment the hit */
  606. if (matches == root->val_nr && cursor->pos == cursor->nr) {
  607. root->hit += period;
  608. root->count++;
  609. return MATCH_EQ;
  610. }
  611. /* We match the node and still have a part remaining */
  612. if (append_chain_children(root, cursor, period) < 0)
  613. return MATCH_ERROR;
  614. return MATCH_EQ;
  615. }
  616. int callchain_append(struct callchain_root *root,
  617. struct callchain_cursor *cursor,
  618. u64 period)
  619. {
  620. if (!cursor->nr)
  621. return 0;
  622. callchain_cursor_commit(cursor);
  623. if (append_chain_children(&root->node, cursor, period) < 0)
  624. return -1;
  625. if (cursor->nr > root->max_depth)
  626. root->max_depth = cursor->nr;
  627. return 0;
  628. }
  629. static int
  630. merge_chain_branch(struct callchain_cursor *cursor,
  631. struct callchain_node *dst, struct callchain_node *src)
  632. {
  633. struct callchain_cursor_node **old_last = cursor->last;
  634. struct callchain_node *child;
  635. struct callchain_list *list, *next_list;
  636. struct rb_node *n;
  637. int old_pos = cursor->nr;
  638. int err = 0;
  639. list_for_each_entry_safe(list, next_list, &src->val, list) {
  640. callchain_cursor_append(cursor, list->ip,
  641. list->ms.map, list->ms.sym,
  642. false, NULL, 0, 0);
  643. list_del(&list->list);
  644. free(list);
  645. }
  646. if (src->hit) {
  647. callchain_cursor_commit(cursor);
  648. if (append_chain_children(dst, cursor, src->hit) < 0)
  649. return -1;
  650. }
  651. n = rb_first(&src->rb_root_in);
  652. while (n) {
  653. child = container_of(n, struct callchain_node, rb_node_in);
  654. n = rb_next(n);
  655. rb_erase(&child->rb_node_in, &src->rb_root_in);
  656. err = merge_chain_branch(cursor, dst, child);
  657. if (err)
  658. break;
  659. free(child);
  660. }
  661. cursor->nr = old_pos;
  662. cursor->last = old_last;
  663. return err;
  664. }
  665. int callchain_merge(struct callchain_cursor *cursor,
  666. struct callchain_root *dst, struct callchain_root *src)
  667. {
  668. return merge_chain_branch(cursor, &dst->node, &src->node);
  669. }
  670. int callchain_cursor_append(struct callchain_cursor *cursor,
  671. u64 ip, struct map *map, struct symbol *sym,
  672. bool branch, struct branch_flags *flags,
  673. int nr_loop_iter, int samples)
  674. {
  675. struct callchain_cursor_node *node = *cursor->last;
  676. if (!node) {
  677. node = calloc(1, sizeof(*node));
  678. if (!node)
  679. return -ENOMEM;
  680. *cursor->last = node;
  681. }
  682. node->ip = ip;
  683. node->map = map;
  684. node->sym = sym;
  685. node->branch = branch;
  686. node->nr_loop_iter = nr_loop_iter;
  687. node->samples = samples;
  688. if (flags)
  689. memcpy(&node->branch_flags, flags,
  690. sizeof(struct branch_flags));
  691. cursor->nr++;
  692. cursor->last = &node->next;
  693. return 0;
  694. }
  695. int sample__resolve_callchain(struct perf_sample *sample,
  696. struct callchain_cursor *cursor, struct symbol **parent,
  697. struct perf_evsel *evsel, struct addr_location *al,
  698. int max_stack)
  699. {
  700. if (sample->callchain == NULL)
  701. return 0;
  702. if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
  703. perf_hpp_list.parent) {
  704. return thread__resolve_callchain(al->thread, cursor, evsel, sample,
  705. parent, al, max_stack);
  706. }
  707. return 0;
  708. }
  709. int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample)
  710. {
  711. if (!symbol_conf.use_callchain || sample->callchain == NULL)
  712. return 0;
  713. return callchain_append(he->callchain, &callchain_cursor, sample->period);
  714. }
  715. int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *node,
  716. bool hide_unresolved)
  717. {
  718. al->map = node->map;
  719. al->sym = node->sym;
  720. if (node->map)
  721. al->addr = node->map->map_ip(node->map, node->ip);
  722. else
  723. al->addr = node->ip;
  724. if (al->sym == NULL) {
  725. if (hide_unresolved)
  726. return 0;
  727. if (al->map == NULL)
  728. goto out;
  729. }
  730. if (al->map->groups == &al->machine->kmaps) {
  731. if (machine__is_host(al->machine)) {
  732. al->cpumode = PERF_RECORD_MISC_KERNEL;
  733. al->level = 'k';
  734. } else {
  735. al->cpumode = PERF_RECORD_MISC_GUEST_KERNEL;
  736. al->level = 'g';
  737. }
  738. } else {
  739. if (machine__is_host(al->machine)) {
  740. al->cpumode = PERF_RECORD_MISC_USER;
  741. al->level = '.';
  742. } else if (perf_guest) {
  743. al->cpumode = PERF_RECORD_MISC_GUEST_USER;
  744. al->level = 'u';
  745. } else {
  746. al->cpumode = PERF_RECORD_MISC_HYPERVISOR;
  747. al->level = 'H';
  748. }
  749. }
  750. out:
  751. return 1;
  752. }
  753. char *callchain_list__sym_name(struct callchain_list *cl,
  754. char *bf, size_t bfsize, bool show_dso)
  755. {
  756. int printed;
  757. if (cl->ms.sym) {
  758. if (callchain_param.key == CCKEY_ADDRESS &&
  759. cl->ms.map && !cl->srcline)
  760. cl->srcline = get_srcline(cl->ms.map->dso,
  761. map__rip_2objdump(cl->ms.map,
  762. cl->ip),
  763. cl->ms.sym, false);
  764. if (cl->srcline)
  765. printed = scnprintf(bf, bfsize, "%s %s",
  766. cl->ms.sym->name, cl->srcline);
  767. else
  768. printed = scnprintf(bf, bfsize, "%s", cl->ms.sym->name);
  769. } else
  770. printed = scnprintf(bf, bfsize, "%#" PRIx64, cl->ip);
  771. if (show_dso)
  772. scnprintf(bf + printed, bfsize - printed, " %s",
  773. cl->ms.map ?
  774. cl->ms.map->dso->short_name :
  775. "unknown");
  776. return bf;
  777. }
  778. char *callchain_node__scnprintf_value(struct callchain_node *node,
  779. char *bf, size_t bfsize, u64 total)
  780. {
  781. double percent = 0.0;
  782. u64 period = callchain_cumul_hits(node);
  783. unsigned count = callchain_cumul_counts(node);
  784. if (callchain_param.mode == CHAIN_FOLDED) {
  785. period = node->hit;
  786. count = node->count;
  787. }
  788. switch (callchain_param.value) {
  789. case CCVAL_PERIOD:
  790. scnprintf(bf, bfsize, "%"PRIu64, period);
  791. break;
  792. case CCVAL_COUNT:
  793. scnprintf(bf, bfsize, "%u", count);
  794. break;
  795. case CCVAL_PERCENT:
  796. default:
  797. if (total)
  798. percent = period * 100.0 / total;
  799. scnprintf(bf, bfsize, "%.2f%%", percent);
  800. break;
  801. }
  802. return bf;
  803. }
  804. int callchain_node__fprintf_value(struct callchain_node *node,
  805. FILE *fp, u64 total)
  806. {
  807. double percent = 0.0;
  808. u64 period = callchain_cumul_hits(node);
  809. unsigned count = callchain_cumul_counts(node);
  810. if (callchain_param.mode == CHAIN_FOLDED) {
  811. period = node->hit;
  812. count = node->count;
  813. }
  814. switch (callchain_param.value) {
  815. case CCVAL_PERIOD:
  816. return fprintf(fp, "%"PRIu64, period);
  817. case CCVAL_COUNT:
  818. return fprintf(fp, "%u", count);
  819. case CCVAL_PERCENT:
  820. default:
  821. if (total)
  822. percent = period * 100.0 / total;
  823. return percent_color_fprintf(fp, "%.2f%%", percent);
  824. }
  825. return 0;
  826. }
  827. static void callchain_counts_value(struct callchain_node *node,
  828. u64 *branch_count, u64 *predicted_count,
  829. u64 *abort_count, u64 *cycles_count)
  830. {
  831. struct callchain_list *clist;
  832. list_for_each_entry(clist, &node->val, list) {
  833. if (branch_count)
  834. *branch_count += clist->branch_count;
  835. if (predicted_count)
  836. *predicted_count += clist->predicted_count;
  837. if (abort_count)
  838. *abort_count += clist->abort_count;
  839. if (cycles_count)
  840. *cycles_count += clist->cycles_count;
  841. }
  842. }
  843. static int callchain_node_branch_counts_cumul(struct callchain_node *node,
  844. u64 *branch_count,
  845. u64 *predicted_count,
  846. u64 *abort_count,
  847. u64 *cycles_count)
  848. {
  849. struct callchain_node *child;
  850. struct rb_node *n;
  851. n = rb_first(&node->rb_root_in);
  852. while (n) {
  853. child = rb_entry(n, struct callchain_node, rb_node_in);
  854. n = rb_next(n);
  855. callchain_node_branch_counts_cumul(child, branch_count,
  856. predicted_count,
  857. abort_count,
  858. cycles_count);
  859. callchain_counts_value(child, branch_count,
  860. predicted_count, abort_count,
  861. cycles_count);
  862. }
  863. return 0;
  864. }
  865. int callchain_branch_counts(struct callchain_root *root,
  866. u64 *branch_count, u64 *predicted_count,
  867. u64 *abort_count, u64 *cycles_count)
  868. {
  869. if (branch_count)
  870. *branch_count = 0;
  871. if (predicted_count)
  872. *predicted_count = 0;
  873. if (abort_count)
  874. *abort_count = 0;
  875. if (cycles_count)
  876. *cycles_count = 0;
  877. return callchain_node_branch_counts_cumul(&root->node,
  878. branch_count,
  879. predicted_count,
  880. abort_count,
  881. cycles_count);
  882. }
  883. static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
  884. u64 branch_count, u64 predicted_count,
  885. u64 abort_count, u64 cycles_count,
  886. u64 iter_count, u64 samples_count)
  887. {
  888. double predicted_percent = 0.0;
  889. const char *null_str = "";
  890. char iter_str[32];
  891. char *str;
  892. u64 cycles = 0;
  893. if (branch_count == 0) {
  894. if (fp)
  895. return fprintf(fp, " (calltrace)");
  896. return scnprintf(bf, bfsize, " (calltrace)");
  897. }
  898. if (iter_count && samples_count) {
  899. scnprintf(iter_str, sizeof(iter_str),
  900. ", iterations:%" PRId64 "",
  901. iter_count / samples_count);
  902. str = iter_str;
  903. } else
  904. str = (char *)null_str;
  905. predicted_percent = predicted_count * 100.0 / branch_count;
  906. cycles = cycles_count / branch_count;
  907. if ((predicted_percent >= 100.0) && (abort_count == 0)) {
  908. if (fp)
  909. return fprintf(fp, " (cycles:%" PRId64 "%s)",
  910. cycles, str);
  911. return scnprintf(bf, bfsize, " (cycles:%" PRId64 "%s)",
  912. cycles, str);
  913. }
  914. if ((predicted_percent < 100.0) && (abort_count == 0)) {
  915. if (fp)
  916. return fprintf(fp,
  917. " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
  918. predicted_percent, cycles, str);
  919. return scnprintf(bf, bfsize,
  920. " (predicted:%.1f%%, cycles:%" PRId64 "%s)",
  921. predicted_percent, cycles, str);
  922. }
  923. if (fp)
  924. return fprintf(fp,
  925. " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
  926. predicted_percent, abort_count, cycles, str);
  927. return scnprintf(bf, bfsize,
  928. " (predicted:%.1f%%, abort:%" PRId64 ", cycles:%" PRId64 "%s)",
  929. predicted_percent, abort_count, cycles, str);
  930. }
  931. int callchain_list_counts__printf_value(struct callchain_node *node,
  932. struct callchain_list *clist,
  933. FILE *fp, char *bf, int bfsize)
  934. {
  935. u64 branch_count, predicted_count;
  936. u64 abort_count, cycles_count;
  937. u64 iter_count = 0, samples_count = 0;
  938. branch_count = clist->branch_count;
  939. predicted_count = clist->predicted_count;
  940. abort_count = clist->abort_count;
  941. cycles_count = clist->cycles_count;
  942. if (node) {
  943. struct callchain_list *call;
  944. list_for_each_entry(call, &node->val, list) {
  945. iter_count += call->iter_count;
  946. samples_count += call->samples_count;
  947. }
  948. }
  949. return callchain_counts_printf(fp, bf, bfsize, branch_count,
  950. predicted_count, abort_count,
  951. cycles_count, iter_count, samples_count);
  952. }
  953. static void free_callchain_node(struct callchain_node *node)
  954. {
  955. struct callchain_list *list, *tmp;
  956. struct callchain_node *child;
  957. struct rb_node *n;
  958. list_for_each_entry_safe(list, tmp, &node->parent_val, list) {
  959. list_del(&list->list);
  960. free(list);
  961. }
  962. list_for_each_entry_safe(list, tmp, &node->val, list) {
  963. list_del(&list->list);
  964. free(list);
  965. }
  966. n = rb_first(&node->rb_root_in);
  967. while (n) {
  968. child = container_of(n, struct callchain_node, rb_node_in);
  969. n = rb_next(n);
  970. rb_erase(&child->rb_node_in, &node->rb_root_in);
  971. free_callchain_node(child);
  972. free(child);
  973. }
  974. }
  975. void free_callchain(struct callchain_root *root)
  976. {
  977. if (!symbol_conf.use_callchain)
  978. return;
  979. free_callchain_node(&root->node);
  980. }
  981. static u64 decay_callchain_node(struct callchain_node *node)
  982. {
  983. struct callchain_node *child;
  984. struct rb_node *n;
  985. u64 child_hits = 0;
  986. n = rb_first(&node->rb_root_in);
  987. while (n) {
  988. child = container_of(n, struct callchain_node, rb_node_in);
  989. child_hits += decay_callchain_node(child);
  990. n = rb_next(n);
  991. }
  992. node->hit = (node->hit * 7) / 8;
  993. node->children_hit = child_hits;
  994. return node->hit;
  995. }
  996. void decay_callchain(struct callchain_root *root)
  997. {
  998. if (!symbol_conf.use_callchain)
  999. return;
  1000. decay_callchain_node(&root->node);
  1001. }
  1002. int callchain_node__make_parent_list(struct callchain_node *node)
  1003. {
  1004. struct callchain_node *parent = node->parent;
  1005. struct callchain_list *chain, *new;
  1006. LIST_HEAD(head);
  1007. while (parent) {
  1008. list_for_each_entry_reverse(chain, &parent->val, list) {
  1009. new = malloc(sizeof(*new));
  1010. if (new == NULL)
  1011. goto out;
  1012. *new = *chain;
  1013. new->has_children = false;
  1014. list_add_tail(&new->list, &head);
  1015. }
  1016. parent = parent->parent;
  1017. }
  1018. list_for_each_entry_safe_reverse(chain, new, &head, list)
  1019. list_move_tail(&chain->list, &node->parent_val);
  1020. if (!list_empty(&node->parent_val)) {
  1021. chain = list_first_entry(&node->parent_val, struct callchain_list, list);
  1022. chain->has_children = rb_prev(&node->rb_node) || rb_next(&node->rb_node);
  1023. chain = list_first_entry(&node->val, struct callchain_list, list);
  1024. chain->has_children = false;
  1025. }
  1026. return 0;
  1027. out:
  1028. list_for_each_entry_safe(chain, new, &head, list) {
  1029. list_del(&chain->list);
  1030. free(chain);
  1031. }
  1032. return -ENOMEM;
  1033. }
  1034. int callchain_cursor__copy(struct callchain_cursor *dst,
  1035. struct callchain_cursor *src)
  1036. {
  1037. int rc = 0;
  1038. callchain_cursor_reset(dst);
  1039. callchain_cursor_commit(src);
  1040. while (true) {
  1041. struct callchain_cursor_node *node;
  1042. node = callchain_cursor_current(src);
  1043. if (node == NULL)
  1044. break;
  1045. rc = callchain_cursor_append(dst, node->ip, node->map, node->sym,
  1046. node->branch, &node->branch_flags,
  1047. node->nr_loop_iter, node->samples);
  1048. if (rc)
  1049. break;
  1050. callchain_cursor_advance(src);
  1051. }
  1052. return rc;
  1053. }