sort.c 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219
  1. #include <sys/mman.h>
  2. #include "sort.h"
  3. #include "hist.h"
  4. #include "comm.h"
  5. #include "symbol.h"
  6. #include "evsel.h"
  7. #include "evlist.h"
  8. #include <traceevent/event-parse.h>
  9. regex_t parent_regex;
  10. const char default_parent_pattern[] = "^sys_|^do_page_fault";
  11. const char *parent_pattern = default_parent_pattern;
  12. const char default_sort_order[] = "comm,dso,symbol";
  13. const char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles";
  14. const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
  15. const char default_top_sort_order[] = "dso,symbol";
  16. const char default_diff_sort_order[] = "dso,symbol";
  17. const char *sort_order;
  18. const char *field_order;
  19. regex_t ignore_callees_regex;
  20. int have_ignore_callees = 0;
  21. int sort__need_collapse = 0;
  22. int sort__has_parent = 0;
  23. int sort__has_sym = 0;
  24. int sort__has_dso = 0;
  25. int sort__has_socket = 0;
  26. enum sort_mode sort__mode = SORT_MODE__NORMAL;
  27. static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
  28. {
  29. int n;
  30. va_list ap;
  31. va_start(ap, fmt);
  32. n = vsnprintf(bf, size, fmt, ap);
  33. if (symbol_conf.field_sep && n > 0) {
  34. char *sep = bf;
  35. while (1) {
  36. sep = strchr(sep, *symbol_conf.field_sep);
  37. if (sep == NULL)
  38. break;
  39. *sep = '.';
  40. }
  41. }
  42. va_end(ap);
  43. if (n >= (int)size)
  44. return size - 1;
  45. return n;
  46. }
  47. static int64_t cmp_null(const void *l, const void *r)
  48. {
  49. if (!l && !r)
  50. return 0;
  51. else if (!l)
  52. return -1;
  53. else
  54. return 1;
  55. }
  56. /* --sort pid */
  57. static int64_t
  58. sort__thread_cmp(struct hist_entry *left, struct hist_entry *right)
  59. {
  60. return right->thread->tid - left->thread->tid;
  61. }
  62. static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
  63. size_t size, unsigned int width)
  64. {
  65. const char *comm = thread__comm_str(he->thread);
  66. width = max(7U, width) - 6;
  67. return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid,
  68. width, width, comm ?: "");
  69. }
  70. struct sort_entry sort_thread = {
  71. .se_header = " Pid:Command",
  72. .se_cmp = sort__thread_cmp,
  73. .se_snprintf = hist_entry__thread_snprintf,
  74. .se_width_idx = HISTC_THREAD,
  75. };
  76. /* --sort comm */
  77. static int64_t
  78. sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
  79. {
  80. /* Compare the addr that should be unique among comm */
  81. return strcmp(comm__str(right->comm), comm__str(left->comm));
  82. }
  83. static int64_t
  84. sort__comm_collapse(struct hist_entry *left, struct hist_entry *right)
  85. {
  86. /* Compare the addr that should be unique among comm */
  87. return strcmp(comm__str(right->comm), comm__str(left->comm));
  88. }
  89. static int64_t
  90. sort__comm_sort(struct hist_entry *left, struct hist_entry *right)
  91. {
  92. return strcmp(comm__str(right->comm), comm__str(left->comm));
  93. }
  94. static int hist_entry__comm_snprintf(struct hist_entry *he, char *bf,
  95. size_t size, unsigned int width)
  96. {
  97. return repsep_snprintf(bf, size, "%-*.*s", width, width, comm__str(he->comm));
  98. }
  99. struct sort_entry sort_comm = {
  100. .se_header = "Command",
  101. .se_cmp = sort__comm_cmp,
  102. .se_collapse = sort__comm_collapse,
  103. .se_sort = sort__comm_sort,
  104. .se_snprintf = hist_entry__comm_snprintf,
  105. .se_width_idx = HISTC_COMM,
  106. };
  107. /* --sort dso */
  108. static int64_t _sort__dso_cmp(struct map *map_l, struct map *map_r)
  109. {
  110. struct dso *dso_l = map_l ? map_l->dso : NULL;
  111. struct dso *dso_r = map_r ? map_r->dso : NULL;
  112. const char *dso_name_l, *dso_name_r;
  113. if (!dso_l || !dso_r)
  114. return cmp_null(dso_r, dso_l);
  115. if (verbose) {
  116. dso_name_l = dso_l->long_name;
  117. dso_name_r = dso_r->long_name;
  118. } else {
  119. dso_name_l = dso_l->short_name;
  120. dso_name_r = dso_r->short_name;
  121. }
  122. return strcmp(dso_name_l, dso_name_r);
  123. }
  124. static int64_t
  125. sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
  126. {
  127. return _sort__dso_cmp(right->ms.map, left->ms.map);
  128. }
  129. static int _hist_entry__dso_snprintf(struct map *map, char *bf,
  130. size_t size, unsigned int width)
  131. {
  132. if (map && map->dso) {
  133. const char *dso_name = !verbose ? map->dso->short_name :
  134. map->dso->long_name;
  135. return repsep_snprintf(bf, size, "%-*.*s", width, width, dso_name);
  136. }
  137. return repsep_snprintf(bf, size, "%-*.*s", width, width, "[unknown]");
  138. }
  139. static int hist_entry__dso_snprintf(struct hist_entry *he, char *bf,
  140. size_t size, unsigned int width)
  141. {
  142. return _hist_entry__dso_snprintf(he->ms.map, bf, size, width);
  143. }
  144. struct sort_entry sort_dso = {
  145. .se_header = "Shared Object",
  146. .se_cmp = sort__dso_cmp,
  147. .se_snprintf = hist_entry__dso_snprintf,
  148. .se_width_idx = HISTC_DSO,
  149. };
  150. /* --sort symbol */
  151. static int64_t _sort__addr_cmp(u64 left_ip, u64 right_ip)
  152. {
  153. return (int64_t)(right_ip - left_ip);
  154. }
  155. static int64_t _sort__sym_cmp(struct symbol *sym_l, struct symbol *sym_r)
  156. {
  157. if (!sym_l || !sym_r)
  158. return cmp_null(sym_l, sym_r);
  159. if (sym_l == sym_r)
  160. return 0;
  161. if (sym_l->start != sym_r->start)
  162. return (int64_t)(sym_r->start - sym_l->start);
  163. return (int64_t)(sym_r->end - sym_l->end);
  164. }
  165. static int64_t
  166. sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
  167. {
  168. int64_t ret;
  169. if (!left->ms.sym && !right->ms.sym)
  170. return _sort__addr_cmp(left->ip, right->ip);
  171. /*
  172. * comparing symbol address alone is not enough since it's a
  173. * relative address within a dso.
  174. */
  175. if (!sort__has_dso) {
  176. ret = sort__dso_cmp(left, right);
  177. if (ret != 0)
  178. return ret;
  179. }
  180. return _sort__sym_cmp(left->ms.sym, right->ms.sym);
  181. }
  182. static int64_t
  183. sort__sym_sort(struct hist_entry *left, struct hist_entry *right)
  184. {
  185. if (!left->ms.sym || !right->ms.sym)
  186. return cmp_null(left->ms.sym, right->ms.sym);
  187. return strcmp(right->ms.sym->name, left->ms.sym->name);
  188. }
  189. static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
  190. u64 ip, char level, char *bf, size_t size,
  191. unsigned int width)
  192. {
  193. size_t ret = 0;
  194. if (verbose) {
  195. char o = map ? dso__symtab_origin(map->dso) : '!';
  196. ret += repsep_snprintf(bf, size, "%-#*llx %c ",
  197. BITS_PER_LONG / 4 + 2, ip, o);
  198. }
  199. ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
  200. if (sym && map) {
  201. if (map->type == MAP__VARIABLE) {
  202. ret += repsep_snprintf(bf + ret, size - ret, "%s", sym->name);
  203. ret += repsep_snprintf(bf + ret, size - ret, "+0x%llx",
  204. ip - map->unmap_ip(map, sym->start));
  205. ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
  206. width - ret, "");
  207. } else {
  208. ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
  209. width - ret,
  210. sym->name);
  211. }
  212. } else {
  213. size_t len = BITS_PER_LONG / 4;
  214. ret += repsep_snprintf(bf + ret, size - ret, "%-#.*llx",
  215. len, ip);
  216. ret += repsep_snprintf(bf + ret, size - ret, "%-*s",
  217. width - ret, "");
  218. }
  219. if (ret > width)
  220. bf[width] = '\0';
  221. return width;
  222. }
  223. static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
  224. size_t size, unsigned int width)
  225. {
  226. return _hist_entry__sym_snprintf(he->ms.map, he->ms.sym, he->ip,
  227. he->level, bf, size, width);
  228. }
  229. struct sort_entry sort_sym = {
  230. .se_header = "Symbol",
  231. .se_cmp = sort__sym_cmp,
  232. .se_sort = sort__sym_sort,
  233. .se_snprintf = hist_entry__sym_snprintf,
  234. .se_width_idx = HISTC_SYMBOL,
  235. };
  236. /* --sort srcline */
  237. static int64_t
  238. sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
  239. {
  240. if (!left->srcline) {
  241. if (!left->ms.map)
  242. left->srcline = SRCLINE_UNKNOWN;
  243. else {
  244. struct map *map = left->ms.map;
  245. left->srcline = get_srcline(map->dso,
  246. map__rip_2objdump(map, left->ip),
  247. left->ms.sym, true);
  248. }
  249. }
  250. if (!right->srcline) {
  251. if (!right->ms.map)
  252. right->srcline = SRCLINE_UNKNOWN;
  253. else {
  254. struct map *map = right->ms.map;
  255. right->srcline = get_srcline(map->dso,
  256. map__rip_2objdump(map, right->ip),
  257. right->ms.sym, true);
  258. }
  259. }
  260. return strcmp(right->srcline, left->srcline);
  261. }
  262. static int hist_entry__srcline_snprintf(struct hist_entry *he, char *bf,
  263. size_t size, unsigned int width)
  264. {
  265. return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcline);
  266. }
  267. struct sort_entry sort_srcline = {
  268. .se_header = "Source:Line",
  269. .se_cmp = sort__srcline_cmp,
  270. .se_snprintf = hist_entry__srcline_snprintf,
  271. .se_width_idx = HISTC_SRCLINE,
  272. };
  273. /* --sort srcfile */
  274. static char no_srcfile[1];
  275. static char *get_srcfile(struct hist_entry *e)
  276. {
  277. char *sf, *p;
  278. struct map *map = e->ms.map;
  279. sf = __get_srcline(map->dso, map__rip_2objdump(map, e->ip),
  280. e->ms.sym, false, true);
  281. if (!strcmp(sf, SRCLINE_UNKNOWN))
  282. return no_srcfile;
  283. p = strchr(sf, ':');
  284. if (p && *sf) {
  285. *p = 0;
  286. return sf;
  287. }
  288. free(sf);
  289. return no_srcfile;
  290. }
  291. static int64_t
  292. sort__srcfile_cmp(struct hist_entry *left, struct hist_entry *right)
  293. {
  294. if (!left->srcfile) {
  295. if (!left->ms.map)
  296. left->srcfile = no_srcfile;
  297. else
  298. left->srcfile = get_srcfile(left);
  299. }
  300. if (!right->srcfile) {
  301. if (!right->ms.map)
  302. right->srcfile = no_srcfile;
  303. else
  304. right->srcfile = get_srcfile(right);
  305. }
  306. return strcmp(right->srcfile, left->srcfile);
  307. }
  308. static int hist_entry__srcfile_snprintf(struct hist_entry *he, char *bf,
  309. size_t size, unsigned int width)
  310. {
  311. return repsep_snprintf(bf, size, "%-*.*s", width, width, he->srcfile);
  312. }
  313. struct sort_entry sort_srcfile = {
  314. .se_header = "Source File",
  315. .se_cmp = sort__srcfile_cmp,
  316. .se_snprintf = hist_entry__srcfile_snprintf,
  317. .se_width_idx = HISTC_SRCFILE,
  318. };
  319. /* --sort parent */
  320. static int64_t
  321. sort__parent_cmp(struct hist_entry *left, struct hist_entry *right)
  322. {
  323. struct symbol *sym_l = left->parent;
  324. struct symbol *sym_r = right->parent;
  325. if (!sym_l || !sym_r)
  326. return cmp_null(sym_l, sym_r);
  327. return strcmp(sym_r->name, sym_l->name);
  328. }
  329. static int hist_entry__parent_snprintf(struct hist_entry *he, char *bf,
  330. size_t size, unsigned int width)
  331. {
  332. return repsep_snprintf(bf, size, "%-*.*s", width, width,
  333. he->parent ? he->parent->name : "[other]");
  334. }
  335. struct sort_entry sort_parent = {
  336. .se_header = "Parent symbol",
  337. .se_cmp = sort__parent_cmp,
  338. .se_snprintf = hist_entry__parent_snprintf,
  339. .se_width_idx = HISTC_PARENT,
  340. };
  341. /* --sort cpu */
  342. static int64_t
  343. sort__cpu_cmp(struct hist_entry *left, struct hist_entry *right)
  344. {
  345. return right->cpu - left->cpu;
  346. }
  347. static int hist_entry__cpu_snprintf(struct hist_entry *he, char *bf,
  348. size_t size, unsigned int width)
  349. {
  350. return repsep_snprintf(bf, size, "%*.*d", width, width, he->cpu);
  351. }
  352. struct sort_entry sort_cpu = {
  353. .se_header = "CPU",
  354. .se_cmp = sort__cpu_cmp,
  355. .se_snprintf = hist_entry__cpu_snprintf,
  356. .se_width_idx = HISTC_CPU,
  357. };
  358. /* --sort socket */
  359. static int64_t
  360. sort__socket_cmp(struct hist_entry *left, struct hist_entry *right)
  361. {
  362. return right->socket - left->socket;
  363. }
  364. static int hist_entry__socket_snprintf(struct hist_entry *he, char *bf,
  365. size_t size, unsigned int width)
  366. {
  367. return repsep_snprintf(bf, size, "%*.*d", width, width-3, he->socket);
  368. }
  369. struct sort_entry sort_socket = {
  370. .se_header = "Socket",
  371. .se_cmp = sort__socket_cmp,
  372. .se_snprintf = hist_entry__socket_snprintf,
  373. .se_width_idx = HISTC_SOCKET,
  374. };
  375. /* sort keys for branch stacks */
  376. static int64_t
  377. sort__dso_from_cmp(struct hist_entry *left, struct hist_entry *right)
  378. {
  379. if (!left->branch_info || !right->branch_info)
  380. return cmp_null(left->branch_info, right->branch_info);
  381. return _sort__dso_cmp(left->branch_info->from.map,
  382. right->branch_info->from.map);
  383. }
  384. static int hist_entry__dso_from_snprintf(struct hist_entry *he, char *bf,
  385. size_t size, unsigned int width)
  386. {
  387. if (he->branch_info)
  388. return _hist_entry__dso_snprintf(he->branch_info->from.map,
  389. bf, size, width);
  390. else
  391. return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
  392. }
  393. static int64_t
  394. sort__dso_to_cmp(struct hist_entry *left, struct hist_entry *right)
  395. {
  396. if (!left->branch_info || !right->branch_info)
  397. return cmp_null(left->branch_info, right->branch_info);
  398. return _sort__dso_cmp(left->branch_info->to.map,
  399. right->branch_info->to.map);
  400. }
  401. static int hist_entry__dso_to_snprintf(struct hist_entry *he, char *bf,
  402. size_t size, unsigned int width)
  403. {
  404. if (he->branch_info)
  405. return _hist_entry__dso_snprintf(he->branch_info->to.map,
  406. bf, size, width);
  407. else
  408. return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
  409. }
  410. static int64_t
  411. sort__sym_from_cmp(struct hist_entry *left, struct hist_entry *right)
  412. {
  413. struct addr_map_symbol *from_l = &left->branch_info->from;
  414. struct addr_map_symbol *from_r = &right->branch_info->from;
  415. if (!left->branch_info || !right->branch_info)
  416. return cmp_null(left->branch_info, right->branch_info);
  417. from_l = &left->branch_info->from;
  418. from_r = &right->branch_info->from;
  419. if (!from_l->sym && !from_r->sym)
  420. return _sort__addr_cmp(from_l->addr, from_r->addr);
  421. return _sort__sym_cmp(from_l->sym, from_r->sym);
  422. }
  423. static int64_t
  424. sort__sym_to_cmp(struct hist_entry *left, struct hist_entry *right)
  425. {
  426. struct addr_map_symbol *to_l, *to_r;
  427. if (!left->branch_info || !right->branch_info)
  428. return cmp_null(left->branch_info, right->branch_info);
  429. to_l = &left->branch_info->to;
  430. to_r = &right->branch_info->to;
  431. if (!to_l->sym && !to_r->sym)
  432. return _sort__addr_cmp(to_l->addr, to_r->addr);
  433. return _sort__sym_cmp(to_l->sym, to_r->sym);
  434. }
  435. static int hist_entry__sym_from_snprintf(struct hist_entry *he, char *bf,
  436. size_t size, unsigned int width)
  437. {
  438. if (he->branch_info) {
  439. struct addr_map_symbol *from = &he->branch_info->from;
  440. return _hist_entry__sym_snprintf(from->map, from->sym, from->addr,
  441. he->level, bf, size, width);
  442. }
  443. return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
  444. }
  445. static int hist_entry__sym_to_snprintf(struct hist_entry *he, char *bf,
  446. size_t size, unsigned int width)
  447. {
  448. if (he->branch_info) {
  449. struct addr_map_symbol *to = &he->branch_info->to;
  450. return _hist_entry__sym_snprintf(to->map, to->sym, to->addr,
  451. he->level, bf, size, width);
  452. }
  453. return repsep_snprintf(bf, size, "%-*.*s", width, width, "N/A");
  454. }
  455. struct sort_entry sort_dso_from = {
  456. .se_header = "Source Shared Object",
  457. .se_cmp = sort__dso_from_cmp,
  458. .se_snprintf = hist_entry__dso_from_snprintf,
  459. .se_width_idx = HISTC_DSO_FROM,
  460. };
  461. struct sort_entry sort_dso_to = {
  462. .se_header = "Target Shared Object",
  463. .se_cmp = sort__dso_to_cmp,
  464. .se_snprintf = hist_entry__dso_to_snprintf,
  465. .se_width_idx = HISTC_DSO_TO,
  466. };
  467. struct sort_entry sort_sym_from = {
  468. .se_header = "Source Symbol",
  469. .se_cmp = sort__sym_from_cmp,
  470. .se_snprintf = hist_entry__sym_from_snprintf,
  471. .se_width_idx = HISTC_SYMBOL_FROM,
  472. };
  473. struct sort_entry sort_sym_to = {
  474. .se_header = "Target Symbol",
  475. .se_cmp = sort__sym_to_cmp,
  476. .se_snprintf = hist_entry__sym_to_snprintf,
  477. .se_width_idx = HISTC_SYMBOL_TO,
  478. };
  479. static int64_t
  480. sort__mispredict_cmp(struct hist_entry *left, struct hist_entry *right)
  481. {
  482. unsigned char mp, p;
  483. if (!left->branch_info || !right->branch_info)
  484. return cmp_null(left->branch_info, right->branch_info);
  485. mp = left->branch_info->flags.mispred != right->branch_info->flags.mispred;
  486. p = left->branch_info->flags.predicted != right->branch_info->flags.predicted;
  487. return mp || p;
  488. }
  489. static int hist_entry__mispredict_snprintf(struct hist_entry *he, char *bf,
  490. size_t size, unsigned int width){
  491. static const char *out = "N/A";
  492. if (he->branch_info) {
  493. if (he->branch_info->flags.predicted)
  494. out = "N";
  495. else if (he->branch_info->flags.mispred)
  496. out = "Y";
  497. }
  498. return repsep_snprintf(bf, size, "%-*.*s", width, width, out);
  499. }
  500. static int64_t
  501. sort__cycles_cmp(struct hist_entry *left, struct hist_entry *right)
  502. {
  503. return left->branch_info->flags.cycles -
  504. right->branch_info->flags.cycles;
  505. }
  506. static int hist_entry__cycles_snprintf(struct hist_entry *he, char *bf,
  507. size_t size, unsigned int width)
  508. {
  509. if (he->branch_info->flags.cycles == 0)
  510. return repsep_snprintf(bf, size, "%-*s", width, "-");
  511. return repsep_snprintf(bf, size, "%-*hd", width,
  512. he->branch_info->flags.cycles);
  513. }
  514. struct sort_entry sort_cycles = {
  515. .se_header = "Basic Block Cycles",
  516. .se_cmp = sort__cycles_cmp,
  517. .se_snprintf = hist_entry__cycles_snprintf,
  518. .se_width_idx = HISTC_CYCLES,
  519. };
  520. /* --sort daddr_sym */
  521. static int64_t
  522. sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
  523. {
  524. uint64_t l = 0, r = 0;
  525. if (left->mem_info)
  526. l = left->mem_info->daddr.addr;
  527. if (right->mem_info)
  528. r = right->mem_info->daddr.addr;
  529. return (int64_t)(r - l);
  530. }
  531. static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
  532. size_t size, unsigned int width)
  533. {
  534. uint64_t addr = 0;
  535. struct map *map = NULL;
  536. struct symbol *sym = NULL;
  537. if (he->mem_info) {
  538. addr = he->mem_info->daddr.addr;
  539. map = he->mem_info->daddr.map;
  540. sym = he->mem_info->daddr.sym;
  541. }
  542. return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
  543. width);
  544. }
  545. static int64_t
  546. sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right)
  547. {
  548. uint64_t l = 0, r = 0;
  549. if (left->mem_info)
  550. l = left->mem_info->iaddr.addr;
  551. if (right->mem_info)
  552. r = right->mem_info->iaddr.addr;
  553. return (int64_t)(r - l);
  554. }
  555. static int hist_entry__iaddr_snprintf(struct hist_entry *he, char *bf,
  556. size_t size, unsigned int width)
  557. {
  558. uint64_t addr = 0;
  559. struct map *map = NULL;
  560. struct symbol *sym = NULL;
  561. if (he->mem_info) {
  562. addr = he->mem_info->iaddr.addr;
  563. map = he->mem_info->iaddr.map;
  564. sym = he->mem_info->iaddr.sym;
  565. }
  566. return _hist_entry__sym_snprintf(map, sym, addr, he->level, bf, size,
  567. width);
  568. }
  569. static int64_t
  570. sort__dso_daddr_cmp(struct hist_entry *left, struct hist_entry *right)
  571. {
  572. struct map *map_l = NULL;
  573. struct map *map_r = NULL;
  574. if (left->mem_info)
  575. map_l = left->mem_info->daddr.map;
  576. if (right->mem_info)
  577. map_r = right->mem_info->daddr.map;
  578. return _sort__dso_cmp(map_l, map_r);
  579. }
  580. static int hist_entry__dso_daddr_snprintf(struct hist_entry *he, char *bf,
  581. size_t size, unsigned int width)
  582. {
  583. struct map *map = NULL;
  584. if (he->mem_info)
  585. map = he->mem_info->daddr.map;
  586. return _hist_entry__dso_snprintf(map, bf, size, width);
  587. }
  588. static int64_t
  589. sort__locked_cmp(struct hist_entry *left, struct hist_entry *right)
  590. {
  591. union perf_mem_data_src data_src_l;
  592. union perf_mem_data_src data_src_r;
  593. if (left->mem_info)
  594. data_src_l = left->mem_info->data_src;
  595. else
  596. data_src_l.mem_lock = PERF_MEM_LOCK_NA;
  597. if (right->mem_info)
  598. data_src_r = right->mem_info->data_src;
  599. else
  600. data_src_r.mem_lock = PERF_MEM_LOCK_NA;
  601. return (int64_t)(data_src_r.mem_lock - data_src_l.mem_lock);
  602. }
  603. static int hist_entry__locked_snprintf(struct hist_entry *he, char *bf,
  604. size_t size, unsigned int width)
  605. {
  606. const char *out;
  607. u64 mask = PERF_MEM_LOCK_NA;
  608. if (he->mem_info)
  609. mask = he->mem_info->data_src.mem_lock;
  610. if (mask & PERF_MEM_LOCK_NA)
  611. out = "N/A";
  612. else if (mask & PERF_MEM_LOCK_LOCKED)
  613. out = "Yes";
  614. else
  615. out = "No";
  616. return repsep_snprintf(bf, size, "%-*s", width, out);
  617. }
  618. static int64_t
  619. sort__tlb_cmp(struct hist_entry *left, struct hist_entry *right)
  620. {
  621. union perf_mem_data_src data_src_l;
  622. union perf_mem_data_src data_src_r;
  623. if (left->mem_info)
  624. data_src_l = left->mem_info->data_src;
  625. else
  626. data_src_l.mem_dtlb = PERF_MEM_TLB_NA;
  627. if (right->mem_info)
  628. data_src_r = right->mem_info->data_src;
  629. else
  630. data_src_r.mem_dtlb = PERF_MEM_TLB_NA;
  631. return (int64_t)(data_src_r.mem_dtlb - data_src_l.mem_dtlb);
  632. }
  633. static const char * const tlb_access[] = {
  634. "N/A",
  635. "HIT",
  636. "MISS",
  637. "L1",
  638. "L2",
  639. "Walker",
  640. "Fault",
  641. };
  642. #define NUM_TLB_ACCESS (sizeof(tlb_access)/sizeof(const char *))
  643. static int hist_entry__tlb_snprintf(struct hist_entry *he, char *bf,
  644. size_t size, unsigned int width)
  645. {
  646. char out[64];
  647. size_t sz = sizeof(out) - 1; /* -1 for null termination */
  648. size_t l = 0, i;
  649. u64 m = PERF_MEM_TLB_NA;
  650. u64 hit, miss;
  651. out[0] = '\0';
  652. if (he->mem_info)
  653. m = he->mem_info->data_src.mem_dtlb;
  654. hit = m & PERF_MEM_TLB_HIT;
  655. miss = m & PERF_MEM_TLB_MISS;
  656. /* already taken care of */
  657. m &= ~(PERF_MEM_TLB_HIT|PERF_MEM_TLB_MISS);
  658. for (i = 0; m && i < NUM_TLB_ACCESS; i++, m >>= 1) {
  659. if (!(m & 0x1))
  660. continue;
  661. if (l) {
  662. strcat(out, " or ");
  663. l += 4;
  664. }
  665. strncat(out, tlb_access[i], sz - l);
  666. l += strlen(tlb_access[i]);
  667. }
  668. if (*out == '\0')
  669. strcpy(out, "N/A");
  670. if (hit)
  671. strncat(out, " hit", sz - l);
  672. if (miss)
  673. strncat(out, " miss", sz - l);
  674. return repsep_snprintf(bf, size, "%-*s", width, out);
  675. }
  676. static int64_t
  677. sort__lvl_cmp(struct hist_entry *left, struct hist_entry *right)
  678. {
  679. union perf_mem_data_src data_src_l;
  680. union perf_mem_data_src data_src_r;
  681. if (left->mem_info)
  682. data_src_l = left->mem_info->data_src;
  683. else
  684. data_src_l.mem_lvl = PERF_MEM_LVL_NA;
  685. if (right->mem_info)
  686. data_src_r = right->mem_info->data_src;
  687. else
  688. data_src_r.mem_lvl = PERF_MEM_LVL_NA;
  689. return (int64_t)(data_src_r.mem_lvl - data_src_l.mem_lvl);
  690. }
  691. static const char * const mem_lvl[] = {
  692. "N/A",
  693. "HIT",
  694. "MISS",
  695. "L1",
  696. "LFB",
  697. "L2",
  698. "L3",
  699. "Local RAM",
  700. "Remote RAM (1 hop)",
  701. "Remote RAM (2 hops)",
  702. "Remote Cache (1 hop)",
  703. "Remote Cache (2 hops)",
  704. "I/O",
  705. "Uncached",
  706. };
  707. #define NUM_MEM_LVL (sizeof(mem_lvl)/sizeof(const char *))
  708. static int hist_entry__lvl_snprintf(struct hist_entry *he, char *bf,
  709. size_t size, unsigned int width)
  710. {
  711. char out[64];
  712. size_t sz = sizeof(out) - 1; /* -1 for null termination */
  713. size_t i, l = 0;
  714. u64 m = PERF_MEM_LVL_NA;
  715. u64 hit, miss;
  716. if (he->mem_info)
  717. m = he->mem_info->data_src.mem_lvl;
  718. out[0] = '\0';
  719. hit = m & PERF_MEM_LVL_HIT;
  720. miss = m & PERF_MEM_LVL_MISS;
  721. /* already taken care of */
  722. m &= ~(PERF_MEM_LVL_HIT|PERF_MEM_LVL_MISS);
  723. for (i = 0; m && i < NUM_MEM_LVL; i++, m >>= 1) {
  724. if (!(m & 0x1))
  725. continue;
  726. if (l) {
  727. strcat(out, " or ");
  728. l += 4;
  729. }
  730. strncat(out, mem_lvl[i], sz - l);
  731. l += strlen(mem_lvl[i]);
  732. }
  733. if (*out == '\0')
  734. strcpy(out, "N/A");
  735. if (hit)
  736. strncat(out, " hit", sz - l);
  737. if (miss)
  738. strncat(out, " miss", sz - l);
  739. return repsep_snprintf(bf, size, "%-*s", width, out);
  740. }
  741. static int64_t
  742. sort__snoop_cmp(struct hist_entry *left, struct hist_entry *right)
  743. {
  744. union perf_mem_data_src data_src_l;
  745. union perf_mem_data_src data_src_r;
  746. if (left->mem_info)
  747. data_src_l = left->mem_info->data_src;
  748. else
  749. data_src_l.mem_snoop = PERF_MEM_SNOOP_NA;
  750. if (right->mem_info)
  751. data_src_r = right->mem_info->data_src;
  752. else
  753. data_src_r.mem_snoop = PERF_MEM_SNOOP_NA;
  754. return (int64_t)(data_src_r.mem_snoop - data_src_l.mem_snoop);
  755. }
  756. static const char * const snoop_access[] = {
  757. "N/A",
  758. "None",
  759. "Miss",
  760. "Hit",
  761. "HitM",
  762. };
  763. #define NUM_SNOOP_ACCESS (sizeof(snoop_access)/sizeof(const char *))
  764. static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
  765. size_t size, unsigned int width)
  766. {
  767. char out[64];
  768. size_t sz = sizeof(out) - 1; /* -1 for null termination */
  769. size_t i, l = 0;
  770. u64 m = PERF_MEM_SNOOP_NA;
  771. out[0] = '\0';
  772. if (he->mem_info)
  773. m = he->mem_info->data_src.mem_snoop;
  774. for (i = 0; m && i < NUM_SNOOP_ACCESS; i++, m >>= 1) {
  775. if (!(m & 0x1))
  776. continue;
  777. if (l) {
  778. strcat(out, " or ");
  779. l += 4;
  780. }
  781. strncat(out, snoop_access[i], sz - l);
  782. l += strlen(snoop_access[i]);
  783. }
  784. if (*out == '\0')
  785. strcpy(out, "N/A");
  786. return repsep_snprintf(bf, size, "%-*s", width, out);
  787. }
  788. static inline u64 cl_address(u64 address)
  789. {
  790. /* return the cacheline of the address */
  791. return (address & ~(cacheline_size - 1));
  792. }
  793. static int64_t
  794. sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
  795. {
  796. u64 l, r;
  797. struct map *l_map, *r_map;
  798. if (!left->mem_info) return -1;
  799. if (!right->mem_info) return 1;
  800. /* group event types together */
  801. if (left->cpumode > right->cpumode) return -1;
  802. if (left->cpumode < right->cpumode) return 1;
  803. l_map = left->mem_info->daddr.map;
  804. r_map = right->mem_info->daddr.map;
  805. /* if both are NULL, jump to sort on al_addr instead */
  806. if (!l_map && !r_map)
  807. goto addr;
  808. if (!l_map) return -1;
  809. if (!r_map) return 1;
  810. if (l_map->maj > r_map->maj) return -1;
  811. if (l_map->maj < r_map->maj) return 1;
  812. if (l_map->min > r_map->min) return -1;
  813. if (l_map->min < r_map->min) return 1;
  814. if (l_map->ino > r_map->ino) return -1;
  815. if (l_map->ino < r_map->ino) return 1;
  816. if (l_map->ino_generation > r_map->ino_generation) return -1;
  817. if (l_map->ino_generation < r_map->ino_generation) return 1;
  818. /*
  819. * Addresses with no major/minor numbers are assumed to be
  820. * anonymous in userspace. Sort those on pid then address.
  821. *
  822. * The kernel and non-zero major/minor mapped areas are
  823. * assumed to be unity mapped. Sort those on address.
  824. */
  825. if ((left->cpumode != PERF_RECORD_MISC_KERNEL) &&
  826. (!(l_map->flags & MAP_SHARED)) &&
  827. !l_map->maj && !l_map->min && !l_map->ino &&
  828. !l_map->ino_generation) {
  829. /* userspace anonymous */
  830. if (left->thread->pid_ > right->thread->pid_) return -1;
  831. if (left->thread->pid_ < right->thread->pid_) return 1;
  832. }
  833. addr:
  834. /* al_addr does all the right addr - start + offset calculations */
  835. l = cl_address(left->mem_info->daddr.al_addr);
  836. r = cl_address(right->mem_info->daddr.al_addr);
  837. if (l > r) return -1;
  838. if (l < r) return 1;
  839. return 0;
  840. }
  841. static int hist_entry__dcacheline_snprintf(struct hist_entry *he, char *bf,
  842. size_t size, unsigned int width)
  843. {
  844. uint64_t addr = 0;
  845. struct map *map = NULL;
  846. struct symbol *sym = NULL;
  847. char level = he->level;
  848. if (he->mem_info) {
  849. addr = cl_address(he->mem_info->daddr.al_addr);
  850. map = he->mem_info->daddr.map;
  851. sym = he->mem_info->daddr.sym;
  852. /* print [s] for shared data mmaps */
  853. if ((he->cpumode != PERF_RECORD_MISC_KERNEL) &&
  854. map && (map->type == MAP__VARIABLE) &&
  855. (map->flags & MAP_SHARED) &&
  856. (map->maj || map->min || map->ino ||
  857. map->ino_generation))
  858. level = 's';
  859. else if (!map)
  860. level = 'X';
  861. }
  862. return _hist_entry__sym_snprintf(map, sym, addr, level, bf, size,
  863. width);
  864. }
  865. struct sort_entry sort_mispredict = {
  866. .se_header = "Branch Mispredicted",
  867. .se_cmp = sort__mispredict_cmp,
  868. .se_snprintf = hist_entry__mispredict_snprintf,
  869. .se_width_idx = HISTC_MISPREDICT,
  870. };
  871. static u64 he_weight(struct hist_entry *he)
  872. {
  873. return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
  874. }
  875. static int64_t
  876. sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
  877. {
  878. return he_weight(left) - he_weight(right);
  879. }
  880. static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
  881. size_t size, unsigned int width)
  882. {
  883. return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he));
  884. }
  885. struct sort_entry sort_local_weight = {
  886. .se_header = "Local Weight",
  887. .se_cmp = sort__local_weight_cmp,
  888. .se_snprintf = hist_entry__local_weight_snprintf,
  889. .se_width_idx = HISTC_LOCAL_WEIGHT,
  890. };
  891. static int64_t
  892. sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
  893. {
  894. return left->stat.weight - right->stat.weight;
  895. }
  896. static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
  897. size_t size, unsigned int width)
  898. {
  899. return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight);
  900. }
  901. struct sort_entry sort_global_weight = {
  902. .se_header = "Weight",
  903. .se_cmp = sort__global_weight_cmp,
  904. .se_snprintf = hist_entry__global_weight_snprintf,
  905. .se_width_idx = HISTC_GLOBAL_WEIGHT,
  906. };
  907. struct sort_entry sort_mem_daddr_sym = {
  908. .se_header = "Data Symbol",
  909. .se_cmp = sort__daddr_cmp,
  910. .se_snprintf = hist_entry__daddr_snprintf,
  911. .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
  912. };
  913. struct sort_entry sort_mem_iaddr_sym = {
  914. .se_header = "Code Symbol",
  915. .se_cmp = sort__iaddr_cmp,
  916. .se_snprintf = hist_entry__iaddr_snprintf,
  917. .se_width_idx = HISTC_MEM_IADDR_SYMBOL,
  918. };
  919. struct sort_entry sort_mem_daddr_dso = {
  920. .se_header = "Data Object",
  921. .se_cmp = sort__dso_daddr_cmp,
  922. .se_snprintf = hist_entry__dso_daddr_snprintf,
  923. .se_width_idx = HISTC_MEM_DADDR_SYMBOL,
  924. };
  925. struct sort_entry sort_mem_locked = {
  926. .se_header = "Locked",
  927. .se_cmp = sort__locked_cmp,
  928. .se_snprintf = hist_entry__locked_snprintf,
  929. .se_width_idx = HISTC_MEM_LOCKED,
  930. };
  931. struct sort_entry sort_mem_tlb = {
  932. .se_header = "TLB access",
  933. .se_cmp = sort__tlb_cmp,
  934. .se_snprintf = hist_entry__tlb_snprintf,
  935. .se_width_idx = HISTC_MEM_TLB,
  936. };
  937. struct sort_entry sort_mem_lvl = {
  938. .se_header = "Memory access",
  939. .se_cmp = sort__lvl_cmp,
  940. .se_snprintf = hist_entry__lvl_snprintf,
  941. .se_width_idx = HISTC_MEM_LVL,
  942. };
  943. struct sort_entry sort_mem_snoop = {
  944. .se_header = "Snoop",
  945. .se_cmp = sort__snoop_cmp,
  946. .se_snprintf = hist_entry__snoop_snprintf,
  947. .se_width_idx = HISTC_MEM_SNOOP,
  948. };
  949. struct sort_entry sort_mem_dcacheline = {
  950. .se_header = "Data Cacheline",
  951. .se_cmp = sort__dcacheline_cmp,
  952. .se_snprintf = hist_entry__dcacheline_snprintf,
  953. .se_width_idx = HISTC_MEM_DCACHELINE,
  954. };
  955. static int64_t
  956. sort__abort_cmp(struct hist_entry *left, struct hist_entry *right)
  957. {
  958. if (!left->branch_info || !right->branch_info)
  959. return cmp_null(left->branch_info, right->branch_info);
  960. return left->branch_info->flags.abort !=
  961. right->branch_info->flags.abort;
  962. }
  963. static int hist_entry__abort_snprintf(struct hist_entry *he, char *bf,
  964. size_t size, unsigned int width)
  965. {
  966. static const char *out = "N/A";
  967. if (he->branch_info) {
  968. if (he->branch_info->flags.abort)
  969. out = "A";
  970. else
  971. out = ".";
  972. }
  973. return repsep_snprintf(bf, size, "%-*s", width, out);
  974. }
  975. struct sort_entry sort_abort = {
  976. .se_header = "Transaction abort",
  977. .se_cmp = sort__abort_cmp,
  978. .se_snprintf = hist_entry__abort_snprintf,
  979. .se_width_idx = HISTC_ABORT,
  980. };
  981. static int64_t
  982. sort__in_tx_cmp(struct hist_entry *left, struct hist_entry *right)
  983. {
  984. if (!left->branch_info || !right->branch_info)
  985. return cmp_null(left->branch_info, right->branch_info);
  986. return left->branch_info->flags.in_tx !=
  987. right->branch_info->flags.in_tx;
  988. }
  989. static int hist_entry__in_tx_snprintf(struct hist_entry *he, char *bf,
  990. size_t size, unsigned int width)
  991. {
  992. static const char *out = "N/A";
  993. if (he->branch_info) {
  994. if (he->branch_info->flags.in_tx)
  995. out = "T";
  996. else
  997. out = ".";
  998. }
  999. return repsep_snprintf(bf, size, "%-*s", width, out);
  1000. }
  1001. struct sort_entry sort_in_tx = {
  1002. .se_header = "Branch in transaction",
  1003. .se_cmp = sort__in_tx_cmp,
  1004. .se_snprintf = hist_entry__in_tx_snprintf,
  1005. .se_width_idx = HISTC_IN_TX,
  1006. };
  1007. static int64_t
  1008. sort__transaction_cmp(struct hist_entry *left, struct hist_entry *right)
  1009. {
  1010. return left->transaction - right->transaction;
  1011. }
  1012. static inline char *add_str(char *p, const char *str)
  1013. {
  1014. strcpy(p, str);
  1015. return p + strlen(str);
  1016. }
  1017. static struct txbit {
  1018. unsigned flag;
  1019. const char *name;
  1020. int skip_for_len;
  1021. } txbits[] = {
  1022. { PERF_TXN_ELISION, "EL ", 0 },
  1023. { PERF_TXN_TRANSACTION, "TX ", 1 },
  1024. { PERF_TXN_SYNC, "SYNC ", 1 },
  1025. { PERF_TXN_ASYNC, "ASYNC ", 0 },
  1026. { PERF_TXN_RETRY, "RETRY ", 0 },
  1027. { PERF_TXN_CONFLICT, "CON ", 0 },
  1028. { PERF_TXN_CAPACITY_WRITE, "CAP-WRITE ", 1 },
  1029. { PERF_TXN_CAPACITY_READ, "CAP-READ ", 0 },
  1030. { 0, NULL, 0 }
  1031. };
  1032. int hist_entry__transaction_len(void)
  1033. {
  1034. int i;
  1035. int len = 0;
  1036. for (i = 0; txbits[i].name; i++) {
  1037. if (!txbits[i].skip_for_len)
  1038. len += strlen(txbits[i].name);
  1039. }
  1040. len += 4; /* :XX<space> */
  1041. return len;
  1042. }
  1043. static int hist_entry__transaction_snprintf(struct hist_entry *he, char *bf,
  1044. size_t size, unsigned int width)
  1045. {
  1046. u64 t = he->transaction;
  1047. char buf[128];
  1048. char *p = buf;
  1049. int i;
  1050. buf[0] = 0;
  1051. for (i = 0; txbits[i].name; i++)
  1052. if (txbits[i].flag & t)
  1053. p = add_str(p, txbits[i].name);
  1054. if (t && !(t & (PERF_TXN_SYNC|PERF_TXN_ASYNC)))
  1055. p = add_str(p, "NEITHER ");
  1056. if (t & PERF_TXN_ABORT_MASK) {
  1057. sprintf(p, ":%" PRIx64,
  1058. (t & PERF_TXN_ABORT_MASK) >>
  1059. PERF_TXN_ABORT_SHIFT);
  1060. p += strlen(p);
  1061. }
  1062. return repsep_snprintf(bf, size, "%-*s", width, buf);
  1063. }
  1064. struct sort_entry sort_transaction = {
  1065. .se_header = "Transaction ",
  1066. .se_cmp = sort__transaction_cmp,
  1067. .se_snprintf = hist_entry__transaction_snprintf,
  1068. .se_width_idx = HISTC_TRANSACTION,
  1069. };
  1070. struct sort_dimension {
  1071. const char *name;
  1072. struct sort_entry *entry;
  1073. int taken;
  1074. };
  1075. #define DIM(d, n, func) [d] = { .name = n, .entry = &(func) }
  1076. static struct sort_dimension common_sort_dimensions[] = {
  1077. DIM(SORT_PID, "pid", sort_thread),
  1078. DIM(SORT_COMM, "comm", sort_comm),
  1079. DIM(SORT_DSO, "dso", sort_dso),
  1080. DIM(SORT_SYM, "symbol", sort_sym),
  1081. DIM(SORT_PARENT, "parent", sort_parent),
  1082. DIM(SORT_CPU, "cpu", sort_cpu),
  1083. DIM(SORT_SOCKET, "socket", sort_socket),
  1084. DIM(SORT_SRCLINE, "srcline", sort_srcline),
  1085. DIM(SORT_SRCFILE, "srcfile", sort_srcfile),
  1086. DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
  1087. DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
  1088. DIM(SORT_TRANSACTION, "transaction", sort_transaction),
  1089. };
  1090. #undef DIM
  1091. #define DIM(d, n, func) [d - __SORT_BRANCH_STACK] = { .name = n, .entry = &(func) }
  1092. static struct sort_dimension bstack_sort_dimensions[] = {
  1093. DIM(SORT_DSO_FROM, "dso_from", sort_dso_from),
  1094. DIM(SORT_DSO_TO, "dso_to", sort_dso_to),
  1095. DIM(SORT_SYM_FROM, "symbol_from", sort_sym_from),
  1096. DIM(SORT_SYM_TO, "symbol_to", sort_sym_to),
  1097. DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
  1098. DIM(SORT_IN_TX, "in_tx", sort_in_tx),
  1099. DIM(SORT_ABORT, "abort", sort_abort),
  1100. DIM(SORT_CYCLES, "cycles", sort_cycles),
  1101. };
  1102. #undef DIM
  1103. #define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) }
  1104. static struct sort_dimension memory_sort_dimensions[] = {
  1105. DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
  1106. DIM(SORT_MEM_IADDR_SYMBOL, "symbol_iaddr", sort_mem_iaddr_sym),
  1107. DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
  1108. DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
  1109. DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
  1110. DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
  1111. DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
  1112. DIM(SORT_MEM_DCACHELINE, "dcacheline", sort_mem_dcacheline),
  1113. };
  1114. #undef DIM
  1115. struct hpp_dimension {
  1116. const char *name;
  1117. struct perf_hpp_fmt *fmt;
  1118. int taken;
  1119. };
  1120. #define DIM(d, n) { .name = n, .fmt = &perf_hpp__format[d], }
  1121. static struct hpp_dimension hpp_sort_dimensions[] = {
  1122. DIM(PERF_HPP__OVERHEAD, "overhead"),
  1123. DIM(PERF_HPP__OVERHEAD_SYS, "overhead_sys"),
  1124. DIM(PERF_HPP__OVERHEAD_US, "overhead_us"),
  1125. DIM(PERF_HPP__OVERHEAD_GUEST_SYS, "overhead_guest_sys"),
  1126. DIM(PERF_HPP__OVERHEAD_GUEST_US, "overhead_guest_us"),
  1127. DIM(PERF_HPP__OVERHEAD_ACC, "overhead_children"),
  1128. DIM(PERF_HPP__SAMPLES, "sample"),
  1129. DIM(PERF_HPP__PERIOD, "period"),
  1130. };
  1131. #undef DIM
  1132. struct hpp_sort_entry {
  1133. struct perf_hpp_fmt hpp;
  1134. struct sort_entry *se;
  1135. };
  1136. bool perf_hpp__same_sort_entry(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
  1137. {
  1138. struct hpp_sort_entry *hse_a;
  1139. struct hpp_sort_entry *hse_b;
  1140. if (!perf_hpp__is_sort_entry(a) || !perf_hpp__is_sort_entry(b))
  1141. return false;
  1142. hse_a = container_of(a, struct hpp_sort_entry, hpp);
  1143. hse_b = container_of(b, struct hpp_sort_entry, hpp);
  1144. return hse_a->se == hse_b->se;
  1145. }
  1146. void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
  1147. {
  1148. struct hpp_sort_entry *hse;
  1149. if (!perf_hpp__is_sort_entry(fmt))
  1150. return;
  1151. hse = container_of(fmt, struct hpp_sort_entry, hpp);
  1152. hists__new_col_len(hists, hse->se->se_width_idx, strlen(fmt->name));
  1153. }
  1154. static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  1155. struct perf_evsel *evsel)
  1156. {
  1157. struct hpp_sort_entry *hse;
  1158. size_t len = fmt->user_len;
  1159. hse = container_of(fmt, struct hpp_sort_entry, hpp);
  1160. if (!len)
  1161. len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
  1162. return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
  1163. }
  1164. static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
  1165. struct perf_hpp *hpp __maybe_unused,
  1166. struct perf_evsel *evsel)
  1167. {
  1168. struct hpp_sort_entry *hse;
  1169. size_t len = fmt->user_len;
  1170. hse = container_of(fmt, struct hpp_sort_entry, hpp);
  1171. if (!len)
  1172. len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx);
  1173. return len;
  1174. }
  1175. static int __sort__hpp_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  1176. struct hist_entry *he)
  1177. {
  1178. struct hpp_sort_entry *hse;
  1179. size_t len = fmt->user_len;
  1180. hse = container_of(fmt, struct hpp_sort_entry, hpp);
  1181. if (!len)
  1182. len = hists__col_len(he->hists, hse->se->se_width_idx);
  1183. return hse->se->se_snprintf(he, hpp->buf, hpp->size, len);
  1184. }
  1185. static int64_t __sort__hpp_cmp(struct perf_hpp_fmt *fmt,
  1186. struct hist_entry *a, struct hist_entry *b)
  1187. {
  1188. struct hpp_sort_entry *hse;
  1189. hse = container_of(fmt, struct hpp_sort_entry, hpp);
  1190. return hse->se->se_cmp(a, b);
  1191. }
  1192. static int64_t __sort__hpp_collapse(struct perf_hpp_fmt *fmt,
  1193. struct hist_entry *a, struct hist_entry *b)
  1194. {
  1195. struct hpp_sort_entry *hse;
  1196. int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *);
  1197. hse = container_of(fmt, struct hpp_sort_entry, hpp);
  1198. collapse_fn = hse->se->se_collapse ?: hse->se->se_cmp;
  1199. return collapse_fn(a, b);
  1200. }
  1201. static int64_t __sort__hpp_sort(struct perf_hpp_fmt *fmt,
  1202. struct hist_entry *a, struct hist_entry *b)
  1203. {
  1204. struct hpp_sort_entry *hse;
  1205. int64_t (*sort_fn)(struct hist_entry *, struct hist_entry *);
  1206. hse = container_of(fmt, struct hpp_sort_entry, hpp);
  1207. sort_fn = hse->se->se_sort ?: hse->se->se_cmp;
  1208. return sort_fn(a, b);
  1209. }
  1210. static struct hpp_sort_entry *
  1211. __sort_dimension__alloc_hpp(struct sort_dimension *sd)
  1212. {
  1213. struct hpp_sort_entry *hse;
  1214. hse = malloc(sizeof(*hse));
  1215. if (hse == NULL) {
  1216. pr_err("Memory allocation failed\n");
  1217. return NULL;
  1218. }
  1219. hse->se = sd->entry;
  1220. hse->hpp.name = sd->entry->se_header;
  1221. hse->hpp.header = __sort__hpp_header;
  1222. hse->hpp.width = __sort__hpp_width;
  1223. hse->hpp.entry = __sort__hpp_entry;
  1224. hse->hpp.color = NULL;
  1225. hse->hpp.cmp = __sort__hpp_cmp;
  1226. hse->hpp.collapse = __sort__hpp_collapse;
  1227. hse->hpp.sort = __sort__hpp_sort;
  1228. INIT_LIST_HEAD(&hse->hpp.list);
  1229. INIT_LIST_HEAD(&hse->hpp.sort_list);
  1230. hse->hpp.elide = false;
  1231. hse->hpp.len = 0;
  1232. hse->hpp.user_len = 0;
  1233. return hse;
  1234. }
  1235. bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format)
  1236. {
  1237. return format->header == __sort__hpp_header;
  1238. }
  1239. static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd)
  1240. {
  1241. struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
  1242. if (hse == NULL)
  1243. return -1;
  1244. perf_hpp__register_sort_field(&hse->hpp);
  1245. return 0;
  1246. }
  1247. static int __sort_dimension__add_hpp_output(struct sort_dimension *sd)
  1248. {
  1249. struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd);
  1250. if (hse == NULL)
  1251. return -1;
  1252. perf_hpp__column_register(&hse->hpp);
  1253. return 0;
  1254. }
  1255. struct hpp_dynamic_entry {
  1256. struct perf_hpp_fmt hpp;
  1257. struct perf_evsel *evsel;
  1258. struct format_field *field;
  1259. unsigned dynamic_len;
  1260. };
  1261. static int hde_width(struct hpp_dynamic_entry *hde)
  1262. {
  1263. if (!hde->hpp.len) {
  1264. int len = hde->dynamic_len;
  1265. int namelen = strlen(hde->field->name);
  1266. int fieldlen = hde->field->size;
  1267. if (namelen > len)
  1268. len = namelen;
  1269. if (!(hde->field->flags & FIELD_IS_STRING)) {
  1270. /* length for print hex numbers */
  1271. fieldlen = hde->field->size * 2 + 2;
  1272. }
  1273. if (fieldlen > len)
  1274. len = fieldlen;
  1275. hde->hpp.len = len;
  1276. }
  1277. return hde->hpp.len;
  1278. }
  1279. static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  1280. struct perf_evsel *evsel __maybe_unused)
  1281. {
  1282. struct hpp_dynamic_entry *hde;
  1283. size_t len = fmt->user_len;
  1284. hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
  1285. if (!len)
  1286. len = hde_width(hde);
  1287. return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, hde->field->name);
  1288. }
  1289. static int __sort__hde_width(struct perf_hpp_fmt *fmt,
  1290. struct perf_hpp *hpp __maybe_unused,
  1291. struct perf_evsel *evsel __maybe_unused)
  1292. {
  1293. struct hpp_dynamic_entry *hde;
  1294. size_t len = fmt->user_len;
  1295. hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
  1296. if (!len)
  1297. len = hde_width(hde);
  1298. return len;
  1299. }
  1300. static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  1301. struct hist_entry *he)
  1302. {
  1303. struct hpp_dynamic_entry *hde;
  1304. size_t len = fmt->user_len;
  1305. struct trace_seq seq;
  1306. int ret;
  1307. hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
  1308. if (!len)
  1309. len = hde_width(hde);
  1310. if (hists_to_evsel(he->hists) != hde->evsel)
  1311. return scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, "N/A");
  1312. trace_seq_init(&seq);
  1313. pevent_print_field(&seq, he->raw_data, hde->field);
  1314. ret = scnprintf(hpp->buf, hpp->size, "%*.*s", len, len, seq.buffer);
  1315. trace_seq_destroy(&seq);
  1316. return ret;
  1317. }
  1318. static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
  1319. struct hist_entry *a, struct hist_entry *b)
  1320. {
  1321. struct hpp_dynamic_entry *hde;
  1322. struct format_field *field;
  1323. unsigned offset, size;
  1324. hde = container_of(fmt, struct hpp_dynamic_entry, hpp);
  1325. if (hists_to_evsel(a->hists) != hde->evsel)
  1326. return 0;
  1327. field = hde->field;
  1328. if (field->flags & FIELD_IS_DYNAMIC) {
  1329. unsigned long long dyn;
  1330. pevent_read_number_field(field, a->raw_data, &dyn);
  1331. offset = dyn & 0xffff;
  1332. size = (dyn >> 16) & 0xffff;
  1333. /* record max width for output */
  1334. if (size > hde->dynamic_len)
  1335. hde->dynamic_len = size;
  1336. } else {
  1337. offset = field->offset;
  1338. size = field->size;
  1339. }
  1340. return memcmp(a->raw_data + offset, b->raw_data + offset, size);
  1341. }
  1342. static struct hpp_dynamic_entry *
  1343. __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field)
  1344. {
  1345. struct hpp_dynamic_entry *hde;
  1346. hde = malloc(sizeof(*hde));
  1347. if (hde == NULL) {
  1348. pr_debug("Memory allocation failed\n");
  1349. return NULL;
  1350. }
  1351. hde->evsel = evsel;
  1352. hde->field = field;
  1353. hde->dynamic_len = 0;
  1354. hde->hpp.name = field->name;
  1355. hde->hpp.header = __sort__hde_header;
  1356. hde->hpp.width = __sort__hde_width;
  1357. hde->hpp.entry = __sort__hde_entry;
  1358. hde->hpp.color = NULL;
  1359. hde->hpp.cmp = __sort__hde_cmp;
  1360. hde->hpp.collapse = __sort__hde_cmp;
  1361. hde->hpp.sort = __sort__hde_cmp;
  1362. INIT_LIST_HEAD(&hde->hpp.list);
  1363. INIT_LIST_HEAD(&hde->hpp.sort_list);
  1364. hde->hpp.elide = false;
  1365. hde->hpp.len = 0;
  1366. hde->hpp.user_len = 0;
  1367. return hde;
  1368. }
  1369. static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok)
  1370. {
  1371. char *str, *event_name, *field_name;
  1372. struct perf_evsel *evsel, *pos;
  1373. struct format_field *field;
  1374. struct hpp_dynamic_entry *hde;
  1375. int ret = 0;
  1376. if (evlist == NULL)
  1377. return -ENOENT;
  1378. str = strdup(tok);
  1379. if (str == NULL)
  1380. return -ENOMEM;
  1381. event_name = str;
  1382. field_name = strchr(str, '.');
  1383. if (field_name == NULL) {
  1384. ret = -EINVAL;
  1385. goto out;
  1386. }
  1387. *field_name++ = '\0';
  1388. evsel = NULL;
  1389. evlist__for_each(evlist, pos) {
  1390. if (!strcmp(pos->name, event_name)) {
  1391. evsel = pos;
  1392. break;
  1393. }
  1394. }
  1395. if (evsel == NULL) {
  1396. pr_debug("Cannot find event: %s\n", event_name);
  1397. ret = -ENOENT;
  1398. goto out;
  1399. }
  1400. if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
  1401. pr_debug("%s is not a tracepoint event\n", event_name);
  1402. ret = -EINVAL;
  1403. goto out;
  1404. }
  1405. field = pevent_find_any_field(evsel->tp_format, field_name);
  1406. if (field == NULL) {
  1407. pr_debug("Cannot find event field for %s.%s\n",
  1408. event_name, field_name);
  1409. ret = -ENOENT;
  1410. goto out;
  1411. }
  1412. hde = __alloc_dynamic_entry(evsel, field);
  1413. if (hde == NULL) {
  1414. ret = -ENOMEM;
  1415. goto out;
  1416. }
  1417. perf_hpp__register_sort_field(&hde->hpp);
  1418. out:
  1419. free(str);
  1420. return ret;
  1421. }
  1422. static int __sort_dimension__add(struct sort_dimension *sd)
  1423. {
  1424. if (sd->taken)
  1425. return 0;
  1426. if (__sort_dimension__add_hpp_sort(sd) < 0)
  1427. return -1;
  1428. if (sd->entry->se_collapse)
  1429. sort__need_collapse = 1;
  1430. sd->taken = 1;
  1431. return 0;
  1432. }
  1433. static int __hpp_dimension__add(struct hpp_dimension *hd)
  1434. {
  1435. if (!hd->taken) {
  1436. hd->taken = 1;
  1437. perf_hpp__register_sort_field(hd->fmt);
  1438. }
  1439. return 0;
  1440. }
  1441. static int __sort_dimension__add_output(struct sort_dimension *sd)
  1442. {
  1443. if (sd->taken)
  1444. return 0;
  1445. if (__sort_dimension__add_hpp_output(sd) < 0)
  1446. return -1;
  1447. sd->taken = 1;
  1448. return 0;
  1449. }
  1450. static int __hpp_dimension__add_output(struct hpp_dimension *hd)
  1451. {
  1452. if (!hd->taken) {
  1453. hd->taken = 1;
  1454. perf_hpp__column_register(hd->fmt);
  1455. }
  1456. return 0;
  1457. }
  1458. int hpp_dimension__add_output(unsigned col)
  1459. {
  1460. BUG_ON(col >= PERF_HPP__MAX_INDEX);
  1461. return __hpp_dimension__add_output(&hpp_sort_dimensions[col]);
  1462. }
  1463. static int sort_dimension__add(const char *tok,
  1464. struct perf_evlist *evlist __maybe_unused)
  1465. {
  1466. unsigned int i;
  1467. for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
  1468. struct sort_dimension *sd = &common_sort_dimensions[i];
  1469. if (strncasecmp(tok, sd->name, strlen(tok)))
  1470. continue;
  1471. if (sd->entry == &sort_parent) {
  1472. int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED);
  1473. if (ret) {
  1474. char err[BUFSIZ];
  1475. regerror(ret, &parent_regex, err, sizeof(err));
  1476. pr_err("Invalid regex: %s\n%s", parent_pattern, err);
  1477. return -EINVAL;
  1478. }
  1479. sort__has_parent = 1;
  1480. } else if (sd->entry == &sort_sym) {
  1481. sort__has_sym = 1;
  1482. /*
  1483. * perf diff displays the performance difference amongst
  1484. * two or more perf.data files. Those files could come
  1485. * from different binaries. So we should not compare
  1486. * their ips, but the name of symbol.
  1487. */
  1488. if (sort__mode == SORT_MODE__DIFF)
  1489. sd->entry->se_collapse = sort__sym_sort;
  1490. } else if (sd->entry == &sort_dso) {
  1491. sort__has_dso = 1;
  1492. } else if (sd->entry == &sort_socket) {
  1493. sort__has_socket = 1;
  1494. }
  1495. return __sort_dimension__add(sd);
  1496. }
  1497. for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
  1498. struct hpp_dimension *hd = &hpp_sort_dimensions[i];
  1499. if (strncasecmp(tok, hd->name, strlen(tok)))
  1500. continue;
  1501. return __hpp_dimension__add(hd);
  1502. }
  1503. for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
  1504. struct sort_dimension *sd = &bstack_sort_dimensions[i];
  1505. if (strncasecmp(tok, sd->name, strlen(tok)))
  1506. continue;
  1507. if (sort__mode != SORT_MODE__BRANCH)
  1508. return -EINVAL;
  1509. if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
  1510. sort__has_sym = 1;
  1511. __sort_dimension__add(sd);
  1512. return 0;
  1513. }
  1514. for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
  1515. struct sort_dimension *sd = &memory_sort_dimensions[i];
  1516. if (strncasecmp(tok, sd->name, strlen(tok)))
  1517. continue;
  1518. if (sort__mode != SORT_MODE__MEMORY)
  1519. return -EINVAL;
  1520. if (sd->entry == &sort_mem_daddr_sym)
  1521. sort__has_sym = 1;
  1522. __sort_dimension__add(sd);
  1523. return 0;
  1524. }
  1525. if (!add_dynamic_entry(evlist, tok))
  1526. return 0;
  1527. return -ESRCH;
  1528. }
  1529. static const char *get_default_sort_order(void)
  1530. {
  1531. const char *default_sort_orders[] = {
  1532. default_sort_order,
  1533. default_branch_sort_order,
  1534. default_mem_sort_order,
  1535. default_top_sort_order,
  1536. default_diff_sort_order,
  1537. };
  1538. BUG_ON(sort__mode >= ARRAY_SIZE(default_sort_orders));
  1539. return default_sort_orders[sort__mode];
  1540. }
  1541. static int setup_sort_order(void)
  1542. {
  1543. char *new_sort_order;
  1544. /*
  1545. * Append '+'-prefixed sort order to the default sort
  1546. * order string.
  1547. */
  1548. if (!sort_order || is_strict_order(sort_order))
  1549. return 0;
  1550. if (sort_order[1] == '\0') {
  1551. error("Invalid --sort key: `+'");
  1552. return -EINVAL;
  1553. }
  1554. /*
  1555. * We allocate new sort_order string, but we never free it,
  1556. * because it's checked over the rest of the code.
  1557. */
  1558. if (asprintf(&new_sort_order, "%s,%s",
  1559. get_default_sort_order(), sort_order + 1) < 0) {
  1560. error("Not enough memory to set up --sort");
  1561. return -ENOMEM;
  1562. }
  1563. sort_order = new_sort_order;
  1564. return 0;
  1565. }
  1566. static int __setup_sorting(struct perf_evlist *evlist)
  1567. {
  1568. char *tmp, *tok, *str;
  1569. const char *sort_keys;
  1570. int ret = 0;
  1571. ret = setup_sort_order();
  1572. if (ret)
  1573. return ret;
  1574. sort_keys = sort_order;
  1575. if (sort_keys == NULL) {
  1576. if (is_strict_order(field_order)) {
  1577. /*
  1578. * If user specified field order but no sort order,
  1579. * we'll honor it and not add default sort orders.
  1580. */
  1581. return 0;
  1582. }
  1583. sort_keys = get_default_sort_order();
  1584. }
  1585. str = strdup(sort_keys);
  1586. if (str == NULL) {
  1587. error("Not enough memory to setup sort keys");
  1588. return -ENOMEM;
  1589. }
  1590. for (tok = strtok_r(str, ", ", &tmp);
  1591. tok; tok = strtok_r(NULL, ", ", &tmp)) {
  1592. ret = sort_dimension__add(tok, evlist);
  1593. if (ret == -EINVAL) {
  1594. error("Invalid --sort key: `%s'", tok);
  1595. break;
  1596. } else if (ret == -ESRCH) {
  1597. error("Unknown --sort key: `%s'", tok);
  1598. break;
  1599. }
  1600. }
  1601. free(str);
  1602. return ret;
  1603. }
  1604. void perf_hpp__set_elide(int idx, bool elide)
  1605. {
  1606. struct perf_hpp_fmt *fmt;
  1607. struct hpp_sort_entry *hse;
  1608. perf_hpp__for_each_format(fmt) {
  1609. if (!perf_hpp__is_sort_entry(fmt))
  1610. continue;
  1611. hse = container_of(fmt, struct hpp_sort_entry, hpp);
  1612. if (hse->se->se_width_idx == idx) {
  1613. fmt->elide = elide;
  1614. break;
  1615. }
  1616. }
  1617. }
  1618. static bool __get_elide(struct strlist *list, const char *list_name, FILE *fp)
  1619. {
  1620. if (list && strlist__nr_entries(list) == 1) {
  1621. if (fp != NULL)
  1622. fprintf(fp, "# %s: %s\n", list_name,
  1623. strlist__entry(list, 0)->s);
  1624. return true;
  1625. }
  1626. return false;
  1627. }
  1628. static bool get_elide(int idx, FILE *output)
  1629. {
  1630. switch (idx) {
  1631. case HISTC_SYMBOL:
  1632. return __get_elide(symbol_conf.sym_list, "symbol", output);
  1633. case HISTC_DSO:
  1634. return __get_elide(symbol_conf.dso_list, "dso", output);
  1635. case HISTC_COMM:
  1636. return __get_elide(symbol_conf.comm_list, "comm", output);
  1637. default:
  1638. break;
  1639. }
  1640. if (sort__mode != SORT_MODE__BRANCH)
  1641. return false;
  1642. switch (idx) {
  1643. case HISTC_SYMBOL_FROM:
  1644. return __get_elide(symbol_conf.sym_from_list, "sym_from", output);
  1645. case HISTC_SYMBOL_TO:
  1646. return __get_elide(symbol_conf.sym_to_list, "sym_to", output);
  1647. case HISTC_DSO_FROM:
  1648. return __get_elide(symbol_conf.dso_from_list, "dso_from", output);
  1649. case HISTC_DSO_TO:
  1650. return __get_elide(symbol_conf.dso_to_list, "dso_to", output);
  1651. default:
  1652. break;
  1653. }
  1654. return false;
  1655. }
  1656. void sort__setup_elide(FILE *output)
  1657. {
  1658. struct perf_hpp_fmt *fmt;
  1659. struct hpp_sort_entry *hse;
  1660. perf_hpp__for_each_format(fmt) {
  1661. if (!perf_hpp__is_sort_entry(fmt))
  1662. continue;
  1663. hse = container_of(fmt, struct hpp_sort_entry, hpp);
  1664. fmt->elide = get_elide(hse->se->se_width_idx, output);
  1665. }
  1666. /*
  1667. * It makes no sense to elide all of sort entries.
  1668. * Just revert them to show up again.
  1669. */
  1670. perf_hpp__for_each_format(fmt) {
  1671. if (!perf_hpp__is_sort_entry(fmt))
  1672. continue;
  1673. if (!fmt->elide)
  1674. return;
  1675. }
  1676. perf_hpp__for_each_format(fmt) {
  1677. if (!perf_hpp__is_sort_entry(fmt))
  1678. continue;
  1679. fmt->elide = false;
  1680. }
  1681. }
  1682. static int output_field_add(char *tok)
  1683. {
  1684. unsigned int i;
  1685. for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++) {
  1686. struct sort_dimension *sd = &common_sort_dimensions[i];
  1687. if (strncasecmp(tok, sd->name, strlen(tok)))
  1688. continue;
  1689. return __sort_dimension__add_output(sd);
  1690. }
  1691. for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) {
  1692. struct hpp_dimension *hd = &hpp_sort_dimensions[i];
  1693. if (strncasecmp(tok, hd->name, strlen(tok)))
  1694. continue;
  1695. return __hpp_dimension__add_output(hd);
  1696. }
  1697. for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) {
  1698. struct sort_dimension *sd = &bstack_sort_dimensions[i];
  1699. if (strncasecmp(tok, sd->name, strlen(tok)))
  1700. continue;
  1701. return __sort_dimension__add_output(sd);
  1702. }
  1703. for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
  1704. struct sort_dimension *sd = &memory_sort_dimensions[i];
  1705. if (strncasecmp(tok, sd->name, strlen(tok)))
  1706. continue;
  1707. return __sort_dimension__add_output(sd);
  1708. }
  1709. return -ESRCH;
  1710. }
  1711. static void reset_dimensions(void)
  1712. {
  1713. unsigned int i;
  1714. for (i = 0; i < ARRAY_SIZE(common_sort_dimensions); i++)
  1715. common_sort_dimensions[i].taken = 0;
  1716. for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++)
  1717. hpp_sort_dimensions[i].taken = 0;
  1718. for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++)
  1719. bstack_sort_dimensions[i].taken = 0;
  1720. for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++)
  1721. memory_sort_dimensions[i].taken = 0;
  1722. }
  1723. bool is_strict_order(const char *order)
  1724. {
  1725. return order && (*order != '+');
  1726. }
  1727. static int __setup_output_field(void)
  1728. {
  1729. char *tmp, *tok, *str, *strp;
  1730. int ret = -EINVAL;
  1731. if (field_order == NULL)
  1732. return 0;
  1733. strp = str = strdup(field_order);
  1734. if (str == NULL) {
  1735. error("Not enough memory to setup output fields");
  1736. return -ENOMEM;
  1737. }
  1738. if (!is_strict_order(field_order))
  1739. strp++;
  1740. if (!strlen(strp)) {
  1741. error("Invalid --fields key: `+'");
  1742. goto out;
  1743. }
  1744. for (tok = strtok_r(strp, ", ", &tmp);
  1745. tok; tok = strtok_r(NULL, ", ", &tmp)) {
  1746. ret = output_field_add(tok);
  1747. if (ret == -EINVAL) {
  1748. error("Invalid --fields key: `%s'", tok);
  1749. break;
  1750. } else if (ret == -ESRCH) {
  1751. error("Unknown --fields key: `%s'", tok);
  1752. break;
  1753. }
  1754. }
  1755. out:
  1756. free(str);
  1757. return ret;
  1758. }
  1759. int setup_sorting(struct perf_evlist *evlist)
  1760. {
  1761. int err;
  1762. err = __setup_sorting(evlist);
  1763. if (err < 0)
  1764. return err;
  1765. if (parent_pattern != default_parent_pattern) {
  1766. err = sort_dimension__add("parent", evlist);
  1767. if (err < 0)
  1768. return err;
  1769. }
  1770. reset_dimensions();
  1771. /*
  1772. * perf diff doesn't use default hpp output fields.
  1773. */
  1774. if (sort__mode != SORT_MODE__DIFF)
  1775. perf_hpp__init();
  1776. err = __setup_output_field();
  1777. if (err < 0)
  1778. return err;
  1779. /* copy sort keys to output fields */
  1780. perf_hpp__setup_output_field();
  1781. /* and then copy output fields to sort keys */
  1782. perf_hpp__append_sort_keys();
  1783. return 0;
  1784. }
  1785. void reset_output_field(void)
  1786. {
  1787. sort__need_collapse = 0;
  1788. sort__has_parent = 0;
  1789. sort__has_sym = 0;
  1790. sort__has_dso = 0;
  1791. field_order = NULL;
  1792. sort_order = NULL;
  1793. reset_dimensions();
  1794. perf_hpp__reset_output_field();
  1795. }