builtin-lock.c 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <errno.h>
  3. #include <inttypes.h>
  4. #include "builtin.h"
  5. #include "perf.h"
  6. #include "util/evlist.h" // for struct evsel_str_handler
  7. #include "util/evsel.h"
  8. #include "util/symbol.h"
  9. #include "util/thread.h"
  10. #include "util/header.h"
  11. #include "util/target.h"
  12. #include "util/cgroup.h"
  13. #include "util/callchain.h"
  14. #include "util/lock-contention.h"
  15. #include "util/bpf_skel/lock_data.h"
  16. #include <subcmd/pager.h>
  17. #include <subcmd/parse-options.h>
  18. #include "util/trace-event.h"
  19. #include "util/tracepoint.h"
  20. #include "util/debug.h"
  21. #include "util/session.h"
  22. #include "util/tool.h"
  23. #include "util/data.h"
  24. #include "util/string2.h"
  25. #include "util/map.h"
  26. #include "util/util.h"
  27. #include <stdio.h>
  28. #include <sys/types.h>
  29. #include <sys/prctl.h>
  30. #include <semaphore.h>
  31. #include <math.h>
  32. #include <limits.h>
  33. #include <ctype.h>
  34. #include <linux/list.h>
  35. #include <linux/hash.h>
  36. #include <linux/kernel.h>
  37. #include <linux/zalloc.h>
  38. #include <linux/err.h>
  39. #include <linux/stringify.h>
  40. static struct perf_session *session;
  41. static struct target target;
  42. /* based on kernel/lockdep.c */
  43. #define LOCKHASH_BITS 12
  44. #define LOCKHASH_SIZE (1UL << LOCKHASH_BITS)
  45. static struct hlist_head *lockhash_table;
  46. #define __lockhashfn(key) hash_long((unsigned long)key, LOCKHASH_BITS)
  47. #define lockhashentry(key) (lockhash_table + __lockhashfn((key)))
  48. static struct rb_root thread_stats;
  49. static bool combine_locks;
  50. static bool show_thread_stats;
  51. static bool show_lock_addrs;
  52. static bool show_lock_owner;
  53. static bool show_lock_cgroups;
  54. static bool use_bpf;
  55. static unsigned long bpf_map_entries = MAX_ENTRIES;
  56. static int max_stack_depth = CONTENTION_STACK_DEPTH;
  57. static int stack_skip = CONTENTION_STACK_SKIP;
  58. static int print_nr_entries = INT_MAX / 2;
  59. static LIST_HEAD(callstack_filters);
  60. static const char *output_name = NULL;
  61. static FILE *lock_output;
  62. struct callstack_filter {
  63. struct list_head list;
  64. char name[];
  65. };
  66. static struct lock_filter filters;
  67. static enum lock_aggr_mode aggr_mode = LOCK_AGGR_ADDR;
  68. static bool needs_callstack(void)
  69. {
  70. return !list_empty(&callstack_filters);
  71. }
  72. static struct thread_stat *thread_stat_find(u32 tid)
  73. {
  74. struct rb_node *node;
  75. struct thread_stat *st;
  76. node = thread_stats.rb_node;
  77. while (node) {
  78. st = container_of(node, struct thread_stat, rb);
  79. if (st->tid == tid)
  80. return st;
  81. else if (tid < st->tid)
  82. node = node->rb_left;
  83. else
  84. node = node->rb_right;
  85. }
  86. return NULL;
  87. }
  88. static void thread_stat_insert(struct thread_stat *new)
  89. {
  90. struct rb_node **rb = &thread_stats.rb_node;
  91. struct rb_node *parent = NULL;
  92. struct thread_stat *p;
  93. while (*rb) {
  94. p = container_of(*rb, struct thread_stat, rb);
  95. parent = *rb;
  96. if (new->tid < p->tid)
  97. rb = &(*rb)->rb_left;
  98. else if (new->tid > p->tid)
  99. rb = &(*rb)->rb_right;
  100. else
  101. BUG_ON("inserting invalid thread_stat\n");
  102. }
  103. rb_link_node(&new->rb, parent, rb);
  104. rb_insert_color(&new->rb, &thread_stats);
  105. }
  106. static struct thread_stat *thread_stat_findnew_after_first(u32 tid)
  107. {
  108. struct thread_stat *st;
  109. st = thread_stat_find(tid);
  110. if (st)
  111. return st;
  112. st = zalloc(sizeof(struct thread_stat));
  113. if (!st) {
  114. pr_err("memory allocation failed\n");
  115. return NULL;
  116. }
  117. st->tid = tid;
  118. INIT_LIST_HEAD(&st->seq_list);
  119. thread_stat_insert(st);
  120. return st;
  121. }
  122. static struct thread_stat *thread_stat_findnew_first(u32 tid);
  123. static struct thread_stat *(*thread_stat_findnew)(u32 tid) =
  124. thread_stat_findnew_first;
  125. static struct thread_stat *thread_stat_findnew_first(u32 tid)
  126. {
  127. struct thread_stat *st;
  128. st = zalloc(sizeof(struct thread_stat));
  129. if (!st) {
  130. pr_err("memory allocation failed\n");
  131. return NULL;
  132. }
  133. st->tid = tid;
  134. INIT_LIST_HEAD(&st->seq_list);
  135. rb_link_node(&st->rb, NULL, &thread_stats.rb_node);
  136. rb_insert_color(&st->rb, &thread_stats);
  137. thread_stat_findnew = thread_stat_findnew_after_first;
  138. return st;
  139. }
  140. /* build simple key function one is bigger than two */
  141. #define SINGLE_KEY(member) \
  142. static int lock_stat_key_ ## member(struct lock_stat *one, \
  143. struct lock_stat *two) \
  144. { \
  145. return one->member > two->member; \
  146. }
  147. SINGLE_KEY(nr_acquired)
  148. SINGLE_KEY(nr_contended)
  149. SINGLE_KEY(avg_wait_time)
  150. SINGLE_KEY(wait_time_total)
  151. SINGLE_KEY(wait_time_max)
  152. static int lock_stat_key_wait_time_min(struct lock_stat *one,
  153. struct lock_stat *two)
  154. {
  155. u64 s1 = one->wait_time_min;
  156. u64 s2 = two->wait_time_min;
  157. if (s1 == ULLONG_MAX)
  158. s1 = 0;
  159. if (s2 == ULLONG_MAX)
  160. s2 = 0;
  161. return s1 > s2;
  162. }
  163. struct lock_key {
  164. /*
  165. * name: the value for specify by user
  166. * this should be simpler than raw name of member
  167. * e.g. nr_acquired -> acquired, wait_time_total -> wait_total
  168. */
  169. const char *name;
  170. /* header: the string printed on the header line */
  171. const char *header;
  172. /* len: the printing width of the field */
  173. int len;
  174. /* key: a pointer to function to compare two lock stats for sorting */
  175. int (*key)(struct lock_stat*, struct lock_stat*);
  176. /* print: a pointer to function to print a given lock stats */
  177. void (*print)(struct lock_key*, struct lock_stat*);
  178. /* list: list entry to link this */
  179. struct list_head list;
  180. };
  181. static void lock_stat_key_print_time(unsigned long long nsec, int len)
  182. {
  183. static const struct {
  184. float base;
  185. const char *unit;
  186. } table[] = {
  187. { 1e9 * 3600, "h " },
  188. { 1e9 * 60, "m " },
  189. { 1e9, "s " },
  190. { 1e6, "ms" },
  191. { 1e3, "us" },
  192. { 0, NULL },
  193. };
  194. /* for CSV output */
  195. if (len == 0) {
  196. fprintf(lock_output, "%llu", nsec);
  197. return;
  198. }
  199. for (int i = 0; table[i].unit; i++) {
  200. if (nsec < table[i].base)
  201. continue;
  202. fprintf(lock_output, "%*.2f %s", len - 3, nsec / table[i].base, table[i].unit);
  203. return;
  204. }
  205. fprintf(lock_output, "%*llu %s", len - 3, nsec, "ns");
  206. }
  207. #define PRINT_KEY(member) \
  208. static void lock_stat_key_print_ ## member(struct lock_key *key, \
  209. struct lock_stat *ls) \
  210. { \
  211. fprintf(lock_output, "%*llu", key->len, (unsigned long long)ls->member);\
  212. }
  213. #define PRINT_TIME(member) \
  214. static void lock_stat_key_print_ ## member(struct lock_key *key, \
  215. struct lock_stat *ls) \
  216. { \
  217. lock_stat_key_print_time((unsigned long long)ls->member, key->len); \
  218. }
  219. PRINT_KEY(nr_acquired)
  220. PRINT_KEY(nr_contended)
  221. PRINT_TIME(avg_wait_time)
  222. PRINT_TIME(wait_time_total)
  223. PRINT_TIME(wait_time_max)
  224. static void lock_stat_key_print_wait_time_min(struct lock_key *key,
  225. struct lock_stat *ls)
  226. {
  227. u64 wait_time = ls->wait_time_min;
  228. if (wait_time == ULLONG_MAX)
  229. wait_time = 0;
  230. lock_stat_key_print_time(wait_time, key->len);
  231. }
  232. static const char *sort_key = "acquired";
  233. static int (*compare)(struct lock_stat *, struct lock_stat *);
  234. static struct rb_root sorted; /* place to store intermediate data */
  235. static struct rb_root result; /* place to store sorted data */
  236. static LIST_HEAD(lock_keys);
  237. static const char *output_fields;
  238. #define DEF_KEY_LOCK(name, header, fn_suffix, len) \
  239. { #name, header, len, lock_stat_key_ ## fn_suffix, lock_stat_key_print_ ## fn_suffix, {} }
  240. static struct lock_key report_keys[] = {
  241. DEF_KEY_LOCK(acquired, "acquired", nr_acquired, 10),
  242. DEF_KEY_LOCK(contended, "contended", nr_contended, 10),
  243. DEF_KEY_LOCK(avg_wait, "avg wait", avg_wait_time, 12),
  244. DEF_KEY_LOCK(wait_total, "total wait", wait_time_total, 12),
  245. DEF_KEY_LOCK(wait_max, "max wait", wait_time_max, 12),
  246. DEF_KEY_LOCK(wait_min, "min wait", wait_time_min, 12),
  247. /* extra comparisons much complicated should be here */
  248. { }
  249. };
  250. static struct lock_key contention_keys[] = {
  251. DEF_KEY_LOCK(contended, "contended", nr_contended, 10),
  252. DEF_KEY_LOCK(wait_total, "total wait", wait_time_total, 12),
  253. DEF_KEY_LOCK(wait_max, "max wait", wait_time_max, 12),
  254. DEF_KEY_LOCK(wait_min, "min wait", wait_time_min, 12),
  255. DEF_KEY_LOCK(avg_wait, "avg wait", avg_wait_time, 12),
  256. /* extra comparisons much complicated should be here */
  257. { }
  258. };
  259. static int select_key(bool contention)
  260. {
  261. int i;
  262. struct lock_key *keys = report_keys;
  263. if (contention)
  264. keys = contention_keys;
  265. for (i = 0; keys[i].name; i++) {
  266. if (!strcmp(keys[i].name, sort_key)) {
  267. compare = keys[i].key;
  268. /* selected key should be in the output fields */
  269. if (list_empty(&keys[i].list))
  270. list_add_tail(&keys[i].list, &lock_keys);
  271. return 0;
  272. }
  273. }
  274. pr_err("Unknown compare key: %s\n", sort_key);
  275. return -1;
  276. }
  277. static int add_output_field(bool contention, char *name)
  278. {
  279. int i;
  280. struct lock_key *keys = report_keys;
  281. if (contention)
  282. keys = contention_keys;
  283. for (i = 0; keys[i].name; i++) {
  284. if (strcmp(keys[i].name, name))
  285. continue;
  286. /* prevent double link */
  287. if (list_empty(&keys[i].list))
  288. list_add_tail(&keys[i].list, &lock_keys);
  289. return 0;
  290. }
  291. pr_err("Unknown output field: %s\n", name);
  292. return -1;
  293. }
  294. static int setup_output_field(bool contention, const char *str)
  295. {
  296. char *tok, *tmp, *orig;
  297. int i, ret = 0;
  298. struct lock_key *keys = report_keys;
  299. if (contention)
  300. keys = contention_keys;
  301. /* no output field given: use all of them */
  302. if (str == NULL) {
  303. for (i = 0; keys[i].name; i++)
  304. list_add_tail(&keys[i].list, &lock_keys);
  305. return 0;
  306. }
  307. for (i = 0; keys[i].name; i++)
  308. INIT_LIST_HEAD(&keys[i].list);
  309. orig = tmp = strdup(str);
  310. if (orig == NULL)
  311. return -ENOMEM;
  312. while ((tok = strsep(&tmp, ",")) != NULL){
  313. ret = add_output_field(contention, tok);
  314. if (ret < 0)
  315. break;
  316. }
  317. free(orig);
  318. return ret;
  319. }
  320. static void combine_lock_stats(struct lock_stat *st)
  321. {
  322. struct rb_node **rb = &sorted.rb_node;
  323. struct rb_node *parent = NULL;
  324. struct lock_stat *p;
  325. int ret;
  326. while (*rb) {
  327. p = container_of(*rb, struct lock_stat, rb);
  328. parent = *rb;
  329. if (st->name && p->name)
  330. ret = strcmp(st->name, p->name);
  331. else
  332. ret = !!st->name - !!p->name;
  333. if (ret == 0) {
  334. p->nr_acquired += st->nr_acquired;
  335. p->nr_contended += st->nr_contended;
  336. p->wait_time_total += st->wait_time_total;
  337. if (p->nr_contended)
  338. p->avg_wait_time = p->wait_time_total / p->nr_contended;
  339. if (p->wait_time_min > st->wait_time_min)
  340. p->wait_time_min = st->wait_time_min;
  341. if (p->wait_time_max < st->wait_time_max)
  342. p->wait_time_max = st->wait_time_max;
  343. p->broken |= st->broken;
  344. st->combined = 1;
  345. return;
  346. }
  347. if (ret < 0)
  348. rb = &(*rb)->rb_left;
  349. else
  350. rb = &(*rb)->rb_right;
  351. }
  352. rb_link_node(&st->rb, parent, rb);
  353. rb_insert_color(&st->rb, &sorted);
  354. }
  355. static void insert_to_result(struct lock_stat *st,
  356. int (*bigger)(struct lock_stat *, struct lock_stat *))
  357. {
  358. struct rb_node **rb = &result.rb_node;
  359. struct rb_node *parent = NULL;
  360. struct lock_stat *p;
  361. if (combine_locks && st->combined)
  362. return;
  363. while (*rb) {
  364. p = container_of(*rb, struct lock_stat, rb);
  365. parent = *rb;
  366. if (bigger(st, p))
  367. rb = &(*rb)->rb_left;
  368. else
  369. rb = &(*rb)->rb_right;
  370. }
  371. rb_link_node(&st->rb, parent, rb);
  372. rb_insert_color(&st->rb, &result);
  373. }
  374. /* returns left most element of result, and erase it */
  375. static struct lock_stat *pop_from_result(void)
  376. {
  377. struct rb_node *node = result.rb_node;
  378. if (!node)
  379. return NULL;
  380. while (node->rb_left)
  381. node = node->rb_left;
  382. rb_erase(node, &result);
  383. return container_of(node, struct lock_stat, rb);
  384. }
  385. struct lock_stat *lock_stat_find(u64 addr)
  386. {
  387. struct hlist_head *entry = lockhashentry(addr);
  388. struct lock_stat *ret;
  389. hlist_for_each_entry(ret, entry, hash_entry) {
  390. if (ret->addr == addr)
  391. return ret;
  392. }
  393. return NULL;
  394. }
  395. struct lock_stat *lock_stat_findnew(u64 addr, const char *name, int flags)
  396. {
  397. struct hlist_head *entry = lockhashentry(addr);
  398. struct lock_stat *ret, *new;
  399. hlist_for_each_entry(ret, entry, hash_entry) {
  400. if (ret->addr == addr)
  401. return ret;
  402. }
  403. new = zalloc(sizeof(struct lock_stat));
  404. if (!new)
  405. goto alloc_failed;
  406. new->addr = addr;
  407. new->name = strdup(name);
  408. if (!new->name) {
  409. free(new);
  410. goto alloc_failed;
  411. }
  412. new->flags = flags;
  413. new->wait_time_min = ULLONG_MAX;
  414. hlist_add_head(&new->hash_entry, entry);
  415. return new;
  416. alloc_failed:
  417. pr_err("memory allocation failed\n");
  418. return NULL;
  419. }
  420. bool match_callstack_filter(struct machine *machine, u64 *callstack)
  421. {
  422. struct map *kmap;
  423. struct symbol *sym;
  424. u64 ip;
  425. const char *arch = perf_env__arch(machine->env);
  426. if (list_empty(&callstack_filters))
  427. return true;
  428. for (int i = 0; i < max_stack_depth; i++) {
  429. struct callstack_filter *filter;
  430. /*
  431. * In powerpc, the callchain saved by kernel always includes
  432. * first three entries as the NIP (next instruction pointer),
  433. * LR (link register), and the contents of LR save area in the
  434. * second stack frame. In certain scenarios its possible to have
  435. * invalid kernel instruction addresses in either LR or the second
  436. * stack frame's LR. In that case, kernel will store that address as
  437. * zero.
  438. *
  439. * The below check will continue to look into callstack,
  440. * incase first or second callstack index entry has 0
  441. * address for powerpc.
  442. */
  443. if (!callstack || (!callstack[i] && (strcmp(arch, "powerpc") ||
  444. (i != 1 && i != 2))))
  445. break;
  446. ip = callstack[i];
  447. sym = machine__find_kernel_symbol(machine, ip, &kmap);
  448. if (sym == NULL)
  449. continue;
  450. list_for_each_entry(filter, &callstack_filters, list) {
  451. if (strstr(sym->name, filter->name))
  452. return true;
  453. }
  454. }
  455. return false;
  456. }
  457. struct trace_lock_handler {
  458. /* it's used on CONFIG_LOCKDEP */
  459. int (*acquire_event)(struct evsel *evsel,
  460. struct perf_sample *sample);
  461. /* it's used on CONFIG_LOCKDEP && CONFIG_LOCK_STAT */
  462. int (*acquired_event)(struct evsel *evsel,
  463. struct perf_sample *sample);
  464. /* it's used on CONFIG_LOCKDEP && CONFIG_LOCK_STAT */
  465. int (*contended_event)(struct evsel *evsel,
  466. struct perf_sample *sample);
  467. /* it's used on CONFIG_LOCKDEP */
  468. int (*release_event)(struct evsel *evsel,
  469. struct perf_sample *sample);
  470. /* it's used when CONFIG_LOCKDEP is off */
  471. int (*contention_begin_event)(struct evsel *evsel,
  472. struct perf_sample *sample);
  473. /* it's used when CONFIG_LOCKDEP is off */
  474. int (*contention_end_event)(struct evsel *evsel,
  475. struct perf_sample *sample);
  476. };
  477. static struct lock_seq_stat *get_seq(struct thread_stat *ts, u64 addr)
  478. {
  479. struct lock_seq_stat *seq;
  480. list_for_each_entry(seq, &ts->seq_list, list) {
  481. if (seq->addr == addr)
  482. return seq;
  483. }
  484. seq = zalloc(sizeof(struct lock_seq_stat));
  485. if (!seq) {
  486. pr_err("memory allocation failed\n");
  487. return NULL;
  488. }
  489. seq->state = SEQ_STATE_UNINITIALIZED;
  490. seq->addr = addr;
  491. list_add(&seq->list, &ts->seq_list);
  492. return seq;
  493. }
  494. enum broken_state {
  495. BROKEN_ACQUIRE,
  496. BROKEN_ACQUIRED,
  497. BROKEN_CONTENDED,
  498. BROKEN_RELEASE,
  499. BROKEN_MAX,
  500. };
  501. static int bad_hist[BROKEN_MAX];
  502. enum acquire_flags {
  503. TRY_LOCK = 1,
  504. READ_LOCK = 2,
  505. };
  506. static int get_key_by_aggr_mode_simple(u64 *key, u64 addr, u32 tid)
  507. {
  508. switch (aggr_mode) {
  509. case LOCK_AGGR_ADDR:
  510. *key = addr;
  511. break;
  512. case LOCK_AGGR_TASK:
  513. *key = tid;
  514. break;
  515. case LOCK_AGGR_CALLER:
  516. case LOCK_AGGR_CGROUP:
  517. default:
  518. pr_err("Invalid aggregation mode: %d\n", aggr_mode);
  519. return -EINVAL;
  520. }
  521. return 0;
  522. }
  523. static u64 callchain_id(struct evsel *evsel, struct perf_sample *sample);
  524. static int get_key_by_aggr_mode(u64 *key, u64 addr, struct evsel *evsel,
  525. struct perf_sample *sample)
  526. {
  527. if (aggr_mode == LOCK_AGGR_CALLER) {
  528. *key = callchain_id(evsel, sample);
  529. return 0;
  530. }
  531. return get_key_by_aggr_mode_simple(key, addr, sample->tid);
  532. }
  533. static int report_lock_acquire_event(struct evsel *evsel,
  534. struct perf_sample *sample)
  535. {
  536. struct lock_stat *ls;
  537. struct thread_stat *ts;
  538. struct lock_seq_stat *seq;
  539. const char *name = evsel__strval(evsel, sample, "name");
  540. u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
  541. int flag = evsel__intval(evsel, sample, "flags");
  542. u64 key;
  543. int ret;
  544. ret = get_key_by_aggr_mode_simple(&key, addr, sample->tid);
  545. if (ret < 0)
  546. return ret;
  547. ls = lock_stat_findnew(key, name, 0);
  548. if (!ls)
  549. return -ENOMEM;
  550. ts = thread_stat_findnew(sample->tid);
  551. if (!ts)
  552. return -ENOMEM;
  553. seq = get_seq(ts, addr);
  554. if (!seq)
  555. return -ENOMEM;
  556. switch (seq->state) {
  557. case SEQ_STATE_UNINITIALIZED:
  558. case SEQ_STATE_RELEASED:
  559. if (!flag) {
  560. seq->state = SEQ_STATE_ACQUIRING;
  561. } else {
  562. if (flag & TRY_LOCK)
  563. ls->nr_trylock++;
  564. if (flag & READ_LOCK)
  565. ls->nr_readlock++;
  566. seq->state = SEQ_STATE_READ_ACQUIRED;
  567. seq->read_count = 1;
  568. ls->nr_acquired++;
  569. }
  570. break;
  571. case SEQ_STATE_READ_ACQUIRED:
  572. if (flag & READ_LOCK) {
  573. seq->read_count++;
  574. ls->nr_acquired++;
  575. goto end;
  576. } else {
  577. goto broken;
  578. }
  579. break;
  580. case SEQ_STATE_ACQUIRED:
  581. case SEQ_STATE_ACQUIRING:
  582. case SEQ_STATE_CONTENDED:
  583. broken:
  584. /* broken lock sequence */
  585. if (!ls->broken) {
  586. ls->broken = 1;
  587. bad_hist[BROKEN_ACQUIRE]++;
  588. }
  589. list_del_init(&seq->list);
  590. free(seq);
  591. goto end;
  592. default:
  593. BUG_ON("Unknown state of lock sequence found!\n");
  594. break;
  595. }
  596. ls->nr_acquire++;
  597. seq->prev_event_time = sample->time;
  598. end:
  599. return 0;
  600. }
  601. static int report_lock_acquired_event(struct evsel *evsel,
  602. struct perf_sample *sample)
  603. {
  604. struct lock_stat *ls;
  605. struct thread_stat *ts;
  606. struct lock_seq_stat *seq;
  607. u64 contended_term;
  608. const char *name = evsel__strval(evsel, sample, "name");
  609. u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
  610. u64 key;
  611. int ret;
  612. ret = get_key_by_aggr_mode_simple(&key, addr, sample->tid);
  613. if (ret < 0)
  614. return ret;
  615. ls = lock_stat_findnew(key, name, 0);
  616. if (!ls)
  617. return -ENOMEM;
  618. ts = thread_stat_findnew(sample->tid);
  619. if (!ts)
  620. return -ENOMEM;
  621. seq = get_seq(ts, addr);
  622. if (!seq)
  623. return -ENOMEM;
  624. switch (seq->state) {
  625. case SEQ_STATE_UNINITIALIZED:
  626. /* orphan event, do nothing */
  627. return 0;
  628. case SEQ_STATE_ACQUIRING:
  629. break;
  630. case SEQ_STATE_CONTENDED:
  631. contended_term = sample->time - seq->prev_event_time;
  632. ls->wait_time_total += contended_term;
  633. if (contended_term < ls->wait_time_min)
  634. ls->wait_time_min = contended_term;
  635. if (ls->wait_time_max < contended_term)
  636. ls->wait_time_max = contended_term;
  637. break;
  638. case SEQ_STATE_RELEASED:
  639. case SEQ_STATE_ACQUIRED:
  640. case SEQ_STATE_READ_ACQUIRED:
  641. /* broken lock sequence */
  642. if (!ls->broken) {
  643. ls->broken = 1;
  644. bad_hist[BROKEN_ACQUIRED]++;
  645. }
  646. list_del_init(&seq->list);
  647. free(seq);
  648. goto end;
  649. default:
  650. BUG_ON("Unknown state of lock sequence found!\n");
  651. break;
  652. }
  653. seq->state = SEQ_STATE_ACQUIRED;
  654. ls->nr_acquired++;
  655. ls->avg_wait_time = ls->nr_contended ? ls->wait_time_total/ls->nr_contended : 0;
  656. seq->prev_event_time = sample->time;
  657. end:
  658. return 0;
  659. }
  660. static int report_lock_contended_event(struct evsel *evsel,
  661. struct perf_sample *sample)
  662. {
  663. struct lock_stat *ls;
  664. struct thread_stat *ts;
  665. struct lock_seq_stat *seq;
  666. const char *name = evsel__strval(evsel, sample, "name");
  667. u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
  668. u64 key;
  669. int ret;
  670. ret = get_key_by_aggr_mode_simple(&key, addr, sample->tid);
  671. if (ret < 0)
  672. return ret;
  673. ls = lock_stat_findnew(key, name, 0);
  674. if (!ls)
  675. return -ENOMEM;
  676. ts = thread_stat_findnew(sample->tid);
  677. if (!ts)
  678. return -ENOMEM;
  679. seq = get_seq(ts, addr);
  680. if (!seq)
  681. return -ENOMEM;
  682. switch (seq->state) {
  683. case SEQ_STATE_UNINITIALIZED:
  684. /* orphan event, do nothing */
  685. return 0;
  686. case SEQ_STATE_ACQUIRING:
  687. break;
  688. case SEQ_STATE_RELEASED:
  689. case SEQ_STATE_ACQUIRED:
  690. case SEQ_STATE_READ_ACQUIRED:
  691. case SEQ_STATE_CONTENDED:
  692. /* broken lock sequence */
  693. if (!ls->broken) {
  694. ls->broken = 1;
  695. bad_hist[BROKEN_CONTENDED]++;
  696. }
  697. list_del_init(&seq->list);
  698. free(seq);
  699. goto end;
  700. default:
  701. BUG_ON("Unknown state of lock sequence found!\n");
  702. break;
  703. }
  704. seq->state = SEQ_STATE_CONTENDED;
  705. ls->nr_contended++;
  706. ls->avg_wait_time = ls->wait_time_total/ls->nr_contended;
  707. seq->prev_event_time = sample->time;
  708. end:
  709. return 0;
  710. }
  711. static int report_lock_release_event(struct evsel *evsel,
  712. struct perf_sample *sample)
  713. {
  714. struct lock_stat *ls;
  715. struct thread_stat *ts;
  716. struct lock_seq_stat *seq;
  717. const char *name = evsel__strval(evsel, sample, "name");
  718. u64 addr = evsel__intval(evsel, sample, "lockdep_addr");
  719. u64 key;
  720. int ret;
  721. ret = get_key_by_aggr_mode_simple(&key, addr, sample->tid);
  722. if (ret < 0)
  723. return ret;
  724. ls = lock_stat_findnew(key, name, 0);
  725. if (!ls)
  726. return -ENOMEM;
  727. ts = thread_stat_findnew(sample->tid);
  728. if (!ts)
  729. return -ENOMEM;
  730. seq = get_seq(ts, addr);
  731. if (!seq)
  732. return -ENOMEM;
  733. switch (seq->state) {
  734. case SEQ_STATE_UNINITIALIZED:
  735. goto end;
  736. case SEQ_STATE_ACQUIRED:
  737. break;
  738. case SEQ_STATE_READ_ACQUIRED:
  739. seq->read_count--;
  740. BUG_ON(seq->read_count < 0);
  741. if (seq->read_count) {
  742. ls->nr_release++;
  743. goto end;
  744. }
  745. break;
  746. case SEQ_STATE_ACQUIRING:
  747. case SEQ_STATE_CONTENDED:
  748. case SEQ_STATE_RELEASED:
  749. /* broken lock sequence */
  750. if (!ls->broken) {
  751. ls->broken = 1;
  752. bad_hist[BROKEN_RELEASE]++;
  753. }
  754. goto free_seq;
  755. default:
  756. BUG_ON("Unknown state of lock sequence found!\n");
  757. break;
  758. }
  759. ls->nr_release++;
  760. free_seq:
  761. list_del_init(&seq->list);
  762. free(seq);
  763. end:
  764. return 0;
  765. }
  766. static int get_symbol_name_offset(struct map *map, struct symbol *sym, u64 ip,
  767. char *buf, int size)
  768. {
  769. u64 offset;
  770. if (map == NULL || sym == NULL) {
  771. buf[0] = '\0';
  772. return 0;
  773. }
  774. offset = map__map_ip(map, ip) - sym->start;
  775. if (offset)
  776. return scnprintf(buf, size, "%s+%#lx", sym->name, offset);
  777. else
  778. return strlcpy(buf, sym->name, size);
  779. }
  780. static int lock_contention_caller(struct evsel *evsel, struct perf_sample *sample,
  781. char *buf, int size)
  782. {
  783. struct thread *thread;
  784. struct callchain_cursor *cursor;
  785. struct machine *machine = &session->machines.host;
  786. struct symbol *sym;
  787. int skip = 0;
  788. int ret;
  789. /* lock names will be replaced to task name later */
  790. if (show_thread_stats)
  791. return -1;
  792. thread = machine__findnew_thread(machine, -1, sample->pid);
  793. if (thread == NULL)
  794. return -1;
  795. cursor = get_tls_callchain_cursor();
  796. /* use caller function name from the callchain */
  797. ret = thread__resolve_callchain(thread, cursor, evsel, sample,
  798. NULL, NULL, max_stack_depth);
  799. if (ret != 0) {
  800. thread__put(thread);
  801. return -1;
  802. }
  803. callchain_cursor_commit(cursor);
  804. thread__put(thread);
  805. while (true) {
  806. struct callchain_cursor_node *node;
  807. node = callchain_cursor_current(cursor);
  808. if (node == NULL)
  809. break;
  810. /* skip first few entries - for lock functions */
  811. if (++skip <= stack_skip)
  812. goto next;
  813. sym = node->ms.sym;
  814. if (sym && !machine__is_lock_function(machine, node->ip)) {
  815. get_symbol_name_offset(node->ms.map, sym, node->ip,
  816. buf, size);
  817. return 0;
  818. }
  819. next:
  820. callchain_cursor_advance(cursor);
  821. }
  822. return -1;
  823. }
  824. static u64 callchain_id(struct evsel *evsel, struct perf_sample *sample)
  825. {
  826. struct callchain_cursor *cursor;
  827. struct machine *machine = &session->machines.host;
  828. struct thread *thread;
  829. u64 hash = 0;
  830. int skip = 0;
  831. int ret;
  832. thread = machine__findnew_thread(machine, -1, sample->pid);
  833. if (thread == NULL)
  834. return -1;
  835. cursor = get_tls_callchain_cursor();
  836. /* use caller function name from the callchain */
  837. ret = thread__resolve_callchain(thread, cursor, evsel, sample,
  838. NULL, NULL, max_stack_depth);
  839. thread__put(thread);
  840. if (ret != 0)
  841. return -1;
  842. callchain_cursor_commit(cursor);
  843. while (true) {
  844. struct callchain_cursor_node *node;
  845. node = callchain_cursor_current(cursor);
  846. if (node == NULL)
  847. break;
  848. /* skip first few entries - for lock functions */
  849. if (++skip <= stack_skip)
  850. goto next;
  851. if (node->ms.sym && machine__is_lock_function(machine, node->ip))
  852. goto next;
  853. hash ^= hash_long((unsigned long)node->ip, 64);
  854. next:
  855. callchain_cursor_advance(cursor);
  856. }
  857. return hash;
  858. }
  859. static u64 *get_callstack(struct perf_sample *sample, int max_stack)
  860. {
  861. u64 *callstack;
  862. u64 i;
  863. int c;
  864. callstack = calloc(max_stack, sizeof(*callstack));
  865. if (callstack == NULL)
  866. return NULL;
  867. for (i = 0, c = 0; i < sample->callchain->nr && c < max_stack; i++) {
  868. u64 ip = sample->callchain->ips[i];
  869. if (ip >= PERF_CONTEXT_MAX)
  870. continue;
  871. callstack[c++] = ip;
  872. }
  873. return callstack;
  874. }
  875. static int report_lock_contention_begin_event(struct evsel *evsel,
  876. struct perf_sample *sample)
  877. {
  878. struct lock_stat *ls;
  879. struct thread_stat *ts;
  880. struct lock_seq_stat *seq;
  881. u64 addr = evsel__intval(evsel, sample, "lock_addr");
  882. unsigned int flags = evsel__intval(evsel, sample, "flags");
  883. u64 key;
  884. int i, ret;
  885. static bool kmap_loaded;
  886. struct machine *machine = &session->machines.host;
  887. struct map *kmap;
  888. struct symbol *sym;
  889. ret = get_key_by_aggr_mode(&key, addr, evsel, sample);
  890. if (ret < 0)
  891. return ret;
  892. if (!kmap_loaded) {
  893. unsigned long *addrs;
  894. /* make sure it loads the kernel map to find lock symbols */
  895. map__load(machine__kernel_map(machine));
  896. kmap_loaded = true;
  897. /* convert (kernel) symbols to addresses */
  898. for (i = 0; i < filters.nr_syms; i++) {
  899. sym = machine__find_kernel_symbol_by_name(machine,
  900. filters.syms[i],
  901. &kmap);
  902. if (sym == NULL) {
  903. pr_warning("ignore unknown symbol: %s\n",
  904. filters.syms[i]);
  905. continue;
  906. }
  907. addrs = realloc(filters.addrs,
  908. (filters.nr_addrs + 1) * sizeof(*addrs));
  909. if (addrs == NULL) {
  910. pr_warning("memory allocation failure\n");
  911. return -ENOMEM;
  912. }
  913. addrs[filters.nr_addrs++] = map__unmap_ip(kmap, sym->start);
  914. filters.addrs = addrs;
  915. }
  916. }
  917. ls = lock_stat_find(key);
  918. if (!ls) {
  919. char buf[128];
  920. const char *name = "";
  921. switch (aggr_mode) {
  922. case LOCK_AGGR_ADDR:
  923. sym = machine__find_kernel_symbol(machine, key, &kmap);
  924. if (sym)
  925. name = sym->name;
  926. break;
  927. case LOCK_AGGR_CALLER:
  928. name = buf;
  929. if (lock_contention_caller(evsel, sample, buf, sizeof(buf)) < 0)
  930. name = "Unknown";
  931. break;
  932. case LOCK_AGGR_CGROUP:
  933. case LOCK_AGGR_TASK:
  934. default:
  935. break;
  936. }
  937. ls = lock_stat_findnew(key, name, flags);
  938. if (!ls)
  939. return -ENOMEM;
  940. }
  941. if (filters.nr_types) {
  942. bool found = false;
  943. for (i = 0; i < filters.nr_types; i++) {
  944. if (flags == filters.types[i]) {
  945. found = true;
  946. break;
  947. }
  948. }
  949. if (!found)
  950. return 0;
  951. }
  952. if (filters.nr_addrs) {
  953. bool found = false;
  954. for (i = 0; i < filters.nr_addrs; i++) {
  955. if (addr == filters.addrs[i]) {
  956. found = true;
  957. break;
  958. }
  959. }
  960. if (!found)
  961. return 0;
  962. }
  963. if (needs_callstack()) {
  964. u64 *callstack = get_callstack(sample, max_stack_depth);
  965. if (callstack == NULL)
  966. return -ENOMEM;
  967. if (!match_callstack_filter(machine, callstack)) {
  968. free(callstack);
  969. return 0;
  970. }
  971. if (ls->callstack == NULL)
  972. ls->callstack = callstack;
  973. else
  974. free(callstack);
  975. }
  976. ts = thread_stat_findnew(sample->tid);
  977. if (!ts)
  978. return -ENOMEM;
  979. seq = get_seq(ts, addr);
  980. if (!seq)
  981. return -ENOMEM;
  982. switch (seq->state) {
  983. case SEQ_STATE_UNINITIALIZED:
  984. case SEQ_STATE_ACQUIRED:
  985. break;
  986. case SEQ_STATE_CONTENDED:
  987. /*
  988. * It can have nested contention begin with mutex spinning,
  989. * then we would use the original contention begin event and
  990. * ignore the second one.
  991. */
  992. goto end;
  993. case SEQ_STATE_ACQUIRING:
  994. case SEQ_STATE_READ_ACQUIRED:
  995. case SEQ_STATE_RELEASED:
  996. /* broken lock sequence */
  997. if (!ls->broken) {
  998. ls->broken = 1;
  999. bad_hist[BROKEN_CONTENDED]++;
  1000. }
  1001. list_del_init(&seq->list);
  1002. free(seq);
  1003. goto end;
  1004. default:
  1005. BUG_ON("Unknown state of lock sequence found!\n");
  1006. break;
  1007. }
  1008. if (seq->state != SEQ_STATE_CONTENDED) {
  1009. seq->state = SEQ_STATE_CONTENDED;
  1010. seq->prev_event_time = sample->time;
  1011. ls->nr_contended++;
  1012. }
  1013. end:
  1014. return 0;
  1015. }
  1016. static int report_lock_contention_end_event(struct evsel *evsel,
  1017. struct perf_sample *sample)
  1018. {
  1019. struct lock_stat *ls;
  1020. struct thread_stat *ts;
  1021. struct lock_seq_stat *seq;
  1022. u64 contended_term;
  1023. u64 addr = evsel__intval(evsel, sample, "lock_addr");
  1024. u64 key;
  1025. int ret;
  1026. ret = get_key_by_aggr_mode(&key, addr, evsel, sample);
  1027. if (ret < 0)
  1028. return ret;
  1029. ls = lock_stat_find(key);
  1030. if (!ls)
  1031. return 0;
  1032. ts = thread_stat_find(sample->tid);
  1033. if (!ts)
  1034. return 0;
  1035. seq = get_seq(ts, addr);
  1036. if (!seq)
  1037. return -ENOMEM;
  1038. switch (seq->state) {
  1039. case SEQ_STATE_UNINITIALIZED:
  1040. goto end;
  1041. case SEQ_STATE_CONTENDED:
  1042. contended_term = sample->time - seq->prev_event_time;
  1043. ls->wait_time_total += contended_term;
  1044. if (contended_term < ls->wait_time_min)
  1045. ls->wait_time_min = contended_term;
  1046. if (ls->wait_time_max < contended_term)
  1047. ls->wait_time_max = contended_term;
  1048. break;
  1049. case SEQ_STATE_ACQUIRING:
  1050. case SEQ_STATE_ACQUIRED:
  1051. case SEQ_STATE_READ_ACQUIRED:
  1052. case SEQ_STATE_RELEASED:
  1053. /* broken lock sequence */
  1054. if (!ls->broken) {
  1055. ls->broken = 1;
  1056. bad_hist[BROKEN_ACQUIRED]++;
  1057. }
  1058. list_del_init(&seq->list);
  1059. free(seq);
  1060. goto end;
  1061. default:
  1062. BUG_ON("Unknown state of lock sequence found!\n");
  1063. break;
  1064. }
  1065. seq->state = SEQ_STATE_ACQUIRED;
  1066. ls->nr_acquired++;
  1067. ls->avg_wait_time = ls->wait_time_total/ls->nr_acquired;
  1068. end:
  1069. return 0;
  1070. }
  1071. /* lock oriented handlers */
  1072. /* TODO: handlers for CPU oriented, thread oriented */
  1073. static struct trace_lock_handler report_lock_ops = {
  1074. .acquire_event = report_lock_acquire_event,
  1075. .acquired_event = report_lock_acquired_event,
  1076. .contended_event = report_lock_contended_event,
  1077. .release_event = report_lock_release_event,
  1078. .contention_begin_event = report_lock_contention_begin_event,
  1079. .contention_end_event = report_lock_contention_end_event,
  1080. };
  1081. static struct trace_lock_handler contention_lock_ops = {
  1082. .contention_begin_event = report_lock_contention_begin_event,
  1083. .contention_end_event = report_lock_contention_end_event,
  1084. };
  1085. static struct trace_lock_handler *trace_handler;
  1086. static int evsel__process_lock_acquire(struct evsel *evsel, struct perf_sample *sample)
  1087. {
  1088. if (trace_handler->acquire_event)
  1089. return trace_handler->acquire_event(evsel, sample);
  1090. return 0;
  1091. }
  1092. static int evsel__process_lock_acquired(struct evsel *evsel, struct perf_sample *sample)
  1093. {
  1094. if (trace_handler->acquired_event)
  1095. return trace_handler->acquired_event(evsel, sample);
  1096. return 0;
  1097. }
  1098. static int evsel__process_lock_contended(struct evsel *evsel, struct perf_sample *sample)
  1099. {
  1100. if (trace_handler->contended_event)
  1101. return trace_handler->contended_event(evsel, sample);
  1102. return 0;
  1103. }
  1104. static int evsel__process_lock_release(struct evsel *evsel, struct perf_sample *sample)
  1105. {
  1106. if (trace_handler->release_event)
  1107. return trace_handler->release_event(evsel, sample);
  1108. return 0;
  1109. }
  1110. static int evsel__process_contention_begin(struct evsel *evsel, struct perf_sample *sample)
  1111. {
  1112. if (trace_handler->contention_begin_event)
  1113. return trace_handler->contention_begin_event(evsel, sample);
  1114. return 0;
  1115. }
  1116. static int evsel__process_contention_end(struct evsel *evsel, struct perf_sample *sample)
  1117. {
  1118. if (trace_handler->contention_end_event)
  1119. return trace_handler->contention_end_event(evsel, sample);
  1120. return 0;
  1121. }
  1122. static void print_bad_events(int bad, int total)
  1123. {
  1124. /* Output for debug, this have to be removed */
  1125. int i;
  1126. int broken = 0;
  1127. const char *name[4] =
  1128. { "acquire", "acquired", "contended", "release" };
  1129. for (i = 0; i < BROKEN_MAX; i++)
  1130. broken += bad_hist[i];
  1131. if (quiet || total == 0 || (broken == 0 && verbose <= 0))
  1132. return;
  1133. fprintf(lock_output, "\n=== output for debug ===\n\n");
  1134. fprintf(lock_output, "bad: %d, total: %d\n", bad, total);
  1135. fprintf(lock_output, "bad rate: %.2f %%\n", (double)bad / (double)total * 100);
  1136. fprintf(lock_output, "histogram of events caused bad sequence\n");
  1137. for (i = 0; i < BROKEN_MAX; i++)
  1138. fprintf(lock_output, " %10s: %d\n", name[i], bad_hist[i]);
  1139. }
  1140. /* TODO: various way to print, coloring, nano or milli sec */
  1141. static void print_result(void)
  1142. {
  1143. struct lock_stat *st;
  1144. struct lock_key *key;
  1145. char cut_name[20];
  1146. int bad, total, printed;
  1147. if (!quiet) {
  1148. fprintf(lock_output, "%20s ", "Name");
  1149. list_for_each_entry(key, &lock_keys, list)
  1150. fprintf(lock_output, "%*s ", key->len, key->header);
  1151. fprintf(lock_output, "\n\n");
  1152. }
  1153. bad = total = printed = 0;
  1154. while ((st = pop_from_result())) {
  1155. total++;
  1156. if (st->broken)
  1157. bad++;
  1158. if (!st->nr_acquired)
  1159. continue;
  1160. bzero(cut_name, 20);
  1161. if (strlen(st->name) < 20) {
  1162. /* output raw name */
  1163. const char *name = st->name;
  1164. if (show_thread_stats) {
  1165. struct thread *t;
  1166. /* st->addr contains tid of thread */
  1167. t = perf_session__findnew(session, st->addr);
  1168. name = thread__comm_str(t);
  1169. }
  1170. fprintf(lock_output, "%20s ", name);
  1171. } else {
  1172. strncpy(cut_name, st->name, 16);
  1173. cut_name[16] = '.';
  1174. cut_name[17] = '.';
  1175. cut_name[18] = '.';
  1176. cut_name[19] = '\0';
  1177. /* cut off name for saving output style */
  1178. fprintf(lock_output, "%20s ", cut_name);
  1179. }
  1180. list_for_each_entry(key, &lock_keys, list) {
  1181. key->print(key, st);
  1182. fprintf(lock_output, " ");
  1183. }
  1184. fprintf(lock_output, "\n");
  1185. if (++printed >= print_nr_entries)
  1186. break;
  1187. }
  1188. print_bad_events(bad, total);
  1189. }
  1190. static bool info_threads, info_map;
  1191. static void dump_threads(void)
  1192. {
  1193. struct thread_stat *st;
  1194. struct rb_node *node;
  1195. struct thread *t;
  1196. fprintf(lock_output, "%10s: comm\n", "Thread ID");
  1197. node = rb_first(&thread_stats);
  1198. while (node) {
  1199. st = container_of(node, struct thread_stat, rb);
  1200. t = perf_session__findnew(session, st->tid);
  1201. fprintf(lock_output, "%10d: %s\n", st->tid, thread__comm_str(t));
  1202. node = rb_next(node);
  1203. thread__put(t);
  1204. }
  1205. }
  1206. static int compare_maps(struct lock_stat *a, struct lock_stat *b)
  1207. {
  1208. int ret;
  1209. if (a->name && b->name)
  1210. ret = strcmp(a->name, b->name);
  1211. else
  1212. ret = !!a->name - !!b->name;
  1213. if (!ret)
  1214. return a->addr < b->addr;
  1215. else
  1216. return ret < 0;
  1217. }
  1218. static void dump_map(void)
  1219. {
  1220. unsigned int i;
  1221. struct lock_stat *st;
  1222. fprintf(lock_output, "Address of instance: name of class\n");
  1223. for (i = 0; i < LOCKHASH_SIZE; i++) {
  1224. hlist_for_each_entry(st, &lockhash_table[i], hash_entry) {
  1225. insert_to_result(st, compare_maps);
  1226. }
  1227. }
  1228. while ((st = pop_from_result()))
  1229. fprintf(lock_output, " %#llx: %s\n", (unsigned long long)st->addr, st->name);
  1230. }
  1231. static void dump_info(void)
  1232. {
  1233. if (info_threads)
  1234. dump_threads();
  1235. if (info_map) {
  1236. if (info_threads)
  1237. fputc('\n', lock_output);
  1238. dump_map();
  1239. }
  1240. }
  1241. static const struct evsel_str_handler lock_tracepoints[] = {
  1242. { "lock:lock_acquire", evsel__process_lock_acquire, }, /* CONFIG_LOCKDEP */
  1243. { "lock:lock_acquired", evsel__process_lock_acquired, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
  1244. { "lock:lock_contended", evsel__process_lock_contended, }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
  1245. { "lock:lock_release", evsel__process_lock_release, }, /* CONFIG_LOCKDEP */
  1246. };
  1247. static const struct evsel_str_handler contention_tracepoints[] = {
  1248. { "lock:contention_begin", evsel__process_contention_begin, },
  1249. { "lock:contention_end", evsel__process_contention_end, },
  1250. };
  1251. static int process_event_update(const struct perf_tool *tool,
  1252. union perf_event *event,
  1253. struct evlist **pevlist)
  1254. {
  1255. int ret;
  1256. ret = perf_event__process_event_update(tool, event, pevlist);
  1257. if (ret < 0)
  1258. return ret;
  1259. /* this can return -EEXIST since we call it for each evsel */
  1260. perf_session__set_tracepoints_handlers(session, lock_tracepoints);
  1261. perf_session__set_tracepoints_handlers(session, contention_tracepoints);
  1262. return 0;
  1263. }
  1264. typedef int (*tracepoint_handler)(struct evsel *evsel,
  1265. struct perf_sample *sample);
  1266. static int process_sample_event(const struct perf_tool *tool __maybe_unused,
  1267. union perf_event *event,
  1268. struct perf_sample *sample,
  1269. struct evsel *evsel,
  1270. struct machine *machine)
  1271. {
  1272. int err = 0;
  1273. struct thread *thread = machine__findnew_thread(machine, sample->pid,
  1274. sample->tid);
  1275. if (thread == NULL) {
  1276. pr_debug("problem processing %d event, skipping it.\n",
  1277. event->header.type);
  1278. return -1;
  1279. }
  1280. if (evsel->handler != NULL) {
  1281. tracepoint_handler f = evsel->handler;
  1282. err = f(evsel, sample);
  1283. }
  1284. thread__put(thread);
  1285. return err;
  1286. }
  1287. static void combine_result(void)
  1288. {
  1289. unsigned int i;
  1290. struct lock_stat *st;
  1291. if (!combine_locks)
  1292. return;
  1293. for (i = 0; i < LOCKHASH_SIZE; i++) {
  1294. hlist_for_each_entry(st, &lockhash_table[i], hash_entry) {
  1295. combine_lock_stats(st);
  1296. }
  1297. }
  1298. }
  1299. static void sort_result(void)
  1300. {
  1301. unsigned int i;
  1302. struct lock_stat *st;
  1303. for (i = 0; i < LOCKHASH_SIZE; i++) {
  1304. hlist_for_each_entry(st, &lockhash_table[i], hash_entry) {
  1305. insert_to_result(st, compare);
  1306. }
  1307. }
  1308. }
  1309. static const struct {
  1310. unsigned int flags;
  1311. const char *str;
  1312. const char *name;
  1313. } lock_type_table[] = {
  1314. { 0, "semaphore", "semaphore" },
  1315. { LCB_F_SPIN, "spinlock", "spinlock" },
  1316. { LCB_F_SPIN | LCB_F_READ, "rwlock:R", "rwlock" },
  1317. { LCB_F_SPIN | LCB_F_WRITE, "rwlock:W", "rwlock" },
  1318. { LCB_F_READ, "rwsem:R", "rwsem" },
  1319. { LCB_F_WRITE, "rwsem:W", "rwsem" },
  1320. { LCB_F_RT, "rt-mutex", "rt-mutex" },
  1321. { LCB_F_RT | LCB_F_READ, "rwlock-rt:R", "rwlock-rt" },
  1322. { LCB_F_RT | LCB_F_WRITE, "rwlock-rt:W", "rwlock-rt" },
  1323. { LCB_F_PERCPU | LCB_F_READ, "pcpu-sem:R", "percpu-rwsem" },
  1324. { LCB_F_PERCPU | LCB_F_WRITE, "pcpu-sem:W", "percpu-rwsem" },
  1325. { LCB_F_MUTEX, "mutex", "mutex" },
  1326. { LCB_F_MUTEX | LCB_F_SPIN, "mutex", "mutex" },
  1327. /* alias for optimistic spinning only */
  1328. { LCB_F_MUTEX | LCB_F_SPIN, "mutex:spin", "mutex-spin" },
  1329. };
  1330. static const char *get_type_str(unsigned int flags)
  1331. {
  1332. flags &= LCB_F_MAX_FLAGS - 1;
  1333. for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
  1334. if (lock_type_table[i].flags == flags)
  1335. return lock_type_table[i].str;
  1336. }
  1337. return "unknown";
  1338. }
  1339. static const char *get_type_name(unsigned int flags)
  1340. {
  1341. flags &= LCB_F_MAX_FLAGS - 1;
  1342. for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
  1343. if (lock_type_table[i].flags == flags)
  1344. return lock_type_table[i].name;
  1345. }
  1346. return "unknown";
  1347. }
  1348. static void lock_filter_finish(void)
  1349. {
  1350. zfree(&filters.types);
  1351. filters.nr_types = 0;
  1352. zfree(&filters.addrs);
  1353. filters.nr_addrs = 0;
  1354. for (int i = 0; i < filters.nr_syms; i++)
  1355. free(filters.syms[i]);
  1356. zfree(&filters.syms);
  1357. filters.nr_syms = 0;
  1358. zfree(&filters.cgrps);
  1359. filters.nr_cgrps = 0;
  1360. }
  1361. static void sort_contention_result(void)
  1362. {
  1363. sort_result();
  1364. }
  1365. static void print_header_stdio(void)
  1366. {
  1367. struct lock_key *key;
  1368. list_for_each_entry(key, &lock_keys, list)
  1369. fprintf(lock_output, "%*s ", key->len, key->header);
  1370. switch (aggr_mode) {
  1371. case LOCK_AGGR_TASK:
  1372. fprintf(lock_output, " %10s %s\n\n", "pid",
  1373. show_lock_owner ? "owner" : "comm");
  1374. break;
  1375. case LOCK_AGGR_CALLER:
  1376. fprintf(lock_output, " %10s %s\n\n", "type", "caller");
  1377. break;
  1378. case LOCK_AGGR_ADDR:
  1379. fprintf(lock_output, " %16s %s\n\n", "address", "symbol");
  1380. break;
  1381. case LOCK_AGGR_CGROUP:
  1382. fprintf(lock_output, " %s\n\n", "cgroup");
  1383. break;
  1384. default:
  1385. break;
  1386. }
  1387. }
  1388. static void print_header_csv(const char *sep)
  1389. {
  1390. struct lock_key *key;
  1391. fprintf(lock_output, "# output: ");
  1392. list_for_each_entry(key, &lock_keys, list)
  1393. fprintf(lock_output, "%s%s ", key->header, sep);
  1394. switch (aggr_mode) {
  1395. case LOCK_AGGR_TASK:
  1396. fprintf(lock_output, "%s%s %s\n", "pid", sep,
  1397. show_lock_owner ? "owner" : "comm");
  1398. break;
  1399. case LOCK_AGGR_CALLER:
  1400. fprintf(lock_output, "%s%s %s", "type", sep, "caller");
  1401. if (verbose > 0)
  1402. fprintf(lock_output, "%s %s", sep, "stacktrace");
  1403. fprintf(lock_output, "\n");
  1404. break;
  1405. case LOCK_AGGR_ADDR:
  1406. fprintf(lock_output, "%s%s %s%s %s\n", "address", sep, "symbol", sep, "type");
  1407. break;
  1408. case LOCK_AGGR_CGROUP:
  1409. fprintf(lock_output, "%s\n", "cgroup");
  1410. break;
  1411. default:
  1412. break;
  1413. }
  1414. }
  1415. static void print_header(void)
  1416. {
  1417. if (!quiet) {
  1418. if (symbol_conf.field_sep)
  1419. print_header_csv(symbol_conf.field_sep);
  1420. else
  1421. print_header_stdio();
  1422. }
  1423. }
  1424. static void print_lock_stat_stdio(struct lock_contention *con, struct lock_stat *st)
  1425. {
  1426. struct lock_key *key;
  1427. struct thread *t;
  1428. int pid;
  1429. list_for_each_entry(key, &lock_keys, list) {
  1430. key->print(key, st);
  1431. fprintf(lock_output, " ");
  1432. }
  1433. switch (aggr_mode) {
  1434. case LOCK_AGGR_CALLER:
  1435. fprintf(lock_output, " %10s %s\n", get_type_str(st->flags), st->name);
  1436. break;
  1437. case LOCK_AGGR_TASK:
  1438. pid = st->addr;
  1439. t = perf_session__findnew(session, pid);
  1440. fprintf(lock_output, " %10d %s\n",
  1441. pid, pid == -1 ? "Unknown" : thread__comm_str(t));
  1442. break;
  1443. case LOCK_AGGR_ADDR:
  1444. fprintf(lock_output, " %016llx %s (%s)\n", (unsigned long long)st->addr,
  1445. st->name, get_type_name(st->flags));
  1446. break;
  1447. case LOCK_AGGR_CGROUP:
  1448. fprintf(lock_output, " %s\n", st->name);
  1449. break;
  1450. default:
  1451. break;
  1452. }
  1453. if (aggr_mode == LOCK_AGGR_CALLER && verbose > 0) {
  1454. struct map *kmap;
  1455. struct symbol *sym;
  1456. char buf[128];
  1457. u64 ip;
  1458. for (int i = 0; i < max_stack_depth; i++) {
  1459. if (!st->callstack || !st->callstack[i])
  1460. break;
  1461. ip = st->callstack[i];
  1462. sym = machine__find_kernel_symbol(con->machine, ip, &kmap);
  1463. get_symbol_name_offset(kmap, sym, ip, buf, sizeof(buf));
  1464. fprintf(lock_output, "\t\t\t%#lx %s\n", (unsigned long)ip, buf);
  1465. }
  1466. }
  1467. }
  1468. static void print_lock_stat_csv(struct lock_contention *con, struct lock_stat *st,
  1469. const char *sep)
  1470. {
  1471. struct lock_key *key;
  1472. struct thread *t;
  1473. int pid;
  1474. list_for_each_entry(key, &lock_keys, list) {
  1475. key->print(key, st);
  1476. fprintf(lock_output, "%s ", sep);
  1477. }
  1478. switch (aggr_mode) {
  1479. case LOCK_AGGR_CALLER:
  1480. fprintf(lock_output, "%s%s %s", get_type_str(st->flags), sep, st->name);
  1481. if (verbose <= 0)
  1482. fprintf(lock_output, "\n");
  1483. break;
  1484. case LOCK_AGGR_TASK:
  1485. pid = st->addr;
  1486. t = perf_session__findnew(session, pid);
  1487. fprintf(lock_output, "%d%s %s\n", pid, sep,
  1488. pid == -1 ? "Unknown" : thread__comm_str(t));
  1489. break;
  1490. case LOCK_AGGR_ADDR:
  1491. fprintf(lock_output, "%llx%s %s%s %s\n", (unsigned long long)st->addr, sep,
  1492. st->name, sep, get_type_name(st->flags));
  1493. break;
  1494. case LOCK_AGGR_CGROUP:
  1495. fprintf(lock_output, "%s\n",st->name);
  1496. break;
  1497. default:
  1498. break;
  1499. }
  1500. if (aggr_mode == LOCK_AGGR_CALLER && verbose > 0) {
  1501. struct map *kmap;
  1502. struct symbol *sym;
  1503. char buf[128];
  1504. u64 ip;
  1505. for (int i = 0; i < max_stack_depth; i++) {
  1506. if (!st->callstack || !st->callstack[i])
  1507. break;
  1508. ip = st->callstack[i];
  1509. sym = machine__find_kernel_symbol(con->machine, ip, &kmap);
  1510. get_symbol_name_offset(kmap, sym, ip, buf, sizeof(buf));
  1511. fprintf(lock_output, "%s %#lx %s", i ? ":" : sep, (unsigned long) ip, buf);
  1512. }
  1513. fprintf(lock_output, "\n");
  1514. }
  1515. }
  1516. static void print_lock_stat(struct lock_contention *con, struct lock_stat *st)
  1517. {
  1518. if (symbol_conf.field_sep)
  1519. print_lock_stat_csv(con, st, symbol_conf.field_sep);
  1520. else
  1521. print_lock_stat_stdio(con, st);
  1522. }
  1523. static void print_footer_stdio(int total, int bad, struct lock_contention_fails *fails)
  1524. {
  1525. /* Output for debug, this have to be removed */
  1526. int broken = fails->task + fails->stack + fails->time + fails->data;
  1527. if (!use_bpf)
  1528. print_bad_events(bad, total);
  1529. if (quiet || total == 0 || (broken == 0 && verbose <= 0))
  1530. return;
  1531. total += broken;
  1532. fprintf(lock_output, "\n=== output for debug ===\n\n");
  1533. fprintf(lock_output, "bad: %d, total: %d\n", broken, total);
  1534. fprintf(lock_output, "bad rate: %.2f %%\n", 100.0 * broken / total);
  1535. fprintf(lock_output, "histogram of failure reasons\n");
  1536. fprintf(lock_output, " %10s: %d\n", "task", fails->task);
  1537. fprintf(lock_output, " %10s: %d\n", "stack", fails->stack);
  1538. fprintf(lock_output, " %10s: %d\n", "time", fails->time);
  1539. fprintf(lock_output, " %10s: %d\n", "data", fails->data);
  1540. }
  1541. static void print_footer_csv(int total, int bad, struct lock_contention_fails *fails,
  1542. const char *sep)
  1543. {
  1544. /* Output for debug, this have to be removed */
  1545. if (use_bpf)
  1546. bad = fails->task + fails->stack + fails->time + fails->data;
  1547. if (quiet || total == 0 || (bad == 0 && verbose <= 0))
  1548. return;
  1549. total += bad;
  1550. fprintf(lock_output, "# debug: total=%d%s bad=%d", total, sep, bad);
  1551. if (use_bpf) {
  1552. fprintf(lock_output, "%s bad_%s=%d", sep, "task", fails->task);
  1553. fprintf(lock_output, "%s bad_%s=%d", sep, "stack", fails->stack);
  1554. fprintf(lock_output, "%s bad_%s=%d", sep, "time", fails->time);
  1555. fprintf(lock_output, "%s bad_%s=%d", sep, "data", fails->data);
  1556. } else {
  1557. int i;
  1558. const char *name[4] = { "acquire", "acquired", "contended", "release" };
  1559. for (i = 0; i < BROKEN_MAX; i++)
  1560. fprintf(lock_output, "%s bad_%s=%d", sep, name[i], bad_hist[i]);
  1561. }
  1562. fprintf(lock_output, "\n");
  1563. }
  1564. static void print_footer(int total, int bad, struct lock_contention_fails *fails)
  1565. {
  1566. if (symbol_conf.field_sep)
  1567. print_footer_csv(total, bad, fails, symbol_conf.field_sep);
  1568. else
  1569. print_footer_stdio(total, bad, fails);
  1570. }
  1571. static void print_contention_result(struct lock_contention *con)
  1572. {
  1573. struct lock_stat *st;
  1574. int bad, total, printed;
  1575. if (!quiet)
  1576. print_header();
  1577. bad = total = printed = 0;
  1578. while ((st = pop_from_result())) {
  1579. total += use_bpf ? st->nr_contended : 1;
  1580. if (st->broken)
  1581. bad++;
  1582. if (!st->wait_time_total)
  1583. continue;
  1584. print_lock_stat(con, st);
  1585. if (++printed >= print_nr_entries)
  1586. break;
  1587. }
  1588. if (print_nr_entries) {
  1589. /* update the total/bad stats */
  1590. while ((st = pop_from_result())) {
  1591. total += use_bpf ? st->nr_contended : 1;
  1592. if (st->broken)
  1593. bad++;
  1594. }
  1595. }
  1596. /* some entries are collected but hidden by the callstack filter */
  1597. total += con->nr_filtered;
  1598. print_footer(total, bad, &con->fails);
  1599. }
  1600. static bool force;
  1601. static int __cmd_report(bool display_info)
  1602. {
  1603. int err = -EINVAL;
  1604. struct perf_tool eops;
  1605. struct perf_data data = {
  1606. .path = input_name,
  1607. .mode = PERF_DATA_MODE_READ,
  1608. .force = force,
  1609. };
  1610. perf_tool__init(&eops, /*ordered_events=*/true);
  1611. eops.attr = perf_event__process_attr;
  1612. eops.event_update = process_event_update;
  1613. eops.sample = process_sample_event;
  1614. eops.comm = perf_event__process_comm;
  1615. eops.mmap = perf_event__process_mmap;
  1616. eops.namespaces = perf_event__process_namespaces;
  1617. eops.tracing_data = perf_event__process_tracing_data;
  1618. session = perf_session__new(&data, &eops);
  1619. if (IS_ERR(session)) {
  1620. pr_err("Initializing perf session failed\n");
  1621. return PTR_ERR(session);
  1622. }
  1623. symbol_conf.allow_aliases = true;
  1624. symbol__init(&session->header.env);
  1625. if (!data.is_pipe) {
  1626. if (!perf_session__has_traces(session, "lock record"))
  1627. goto out_delete;
  1628. if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) {
  1629. pr_err("Initializing perf session tracepoint handlers failed\n");
  1630. goto out_delete;
  1631. }
  1632. if (perf_session__set_tracepoints_handlers(session, contention_tracepoints)) {
  1633. pr_err("Initializing perf session tracepoint handlers failed\n");
  1634. goto out_delete;
  1635. }
  1636. }
  1637. if (setup_output_field(false, output_fields))
  1638. goto out_delete;
  1639. if (select_key(false))
  1640. goto out_delete;
  1641. if (show_thread_stats)
  1642. aggr_mode = LOCK_AGGR_TASK;
  1643. err = perf_session__process_events(session);
  1644. if (err)
  1645. goto out_delete;
  1646. setup_pager();
  1647. if (display_info) /* used for info subcommand */
  1648. dump_info();
  1649. else {
  1650. combine_result();
  1651. sort_result();
  1652. print_result();
  1653. }
  1654. out_delete:
  1655. perf_session__delete(session);
  1656. return err;
  1657. }
  1658. static void sighandler(int sig __maybe_unused)
  1659. {
  1660. }
  1661. static int check_lock_contention_options(const struct option *options,
  1662. const char * const *usage)
  1663. {
  1664. if (show_thread_stats && show_lock_addrs) {
  1665. pr_err("Cannot use thread and addr mode together\n");
  1666. parse_options_usage(usage, options, "threads", 0);
  1667. parse_options_usage(NULL, options, "lock-addr", 0);
  1668. return -1;
  1669. }
  1670. if (show_lock_owner && !use_bpf) {
  1671. pr_err("Lock owners are available only with BPF\n");
  1672. parse_options_usage(usage, options, "lock-owner", 0);
  1673. parse_options_usage(NULL, options, "use-bpf", 0);
  1674. return -1;
  1675. }
  1676. if (show_lock_owner && show_lock_addrs) {
  1677. pr_err("Cannot use owner and addr mode together\n");
  1678. parse_options_usage(usage, options, "lock-owner", 0);
  1679. parse_options_usage(NULL, options, "lock-addr", 0);
  1680. return -1;
  1681. }
  1682. if (show_lock_cgroups && !use_bpf) {
  1683. pr_err("Cgroups are available only with BPF\n");
  1684. parse_options_usage(usage, options, "lock-cgroup", 0);
  1685. parse_options_usage(NULL, options, "use-bpf", 0);
  1686. return -1;
  1687. }
  1688. if (show_lock_cgroups && show_lock_addrs) {
  1689. pr_err("Cannot use cgroup and addr mode together\n");
  1690. parse_options_usage(usage, options, "lock-cgroup", 0);
  1691. parse_options_usage(NULL, options, "lock-addr", 0);
  1692. return -1;
  1693. }
  1694. if (show_lock_cgroups && show_thread_stats) {
  1695. pr_err("Cannot use cgroup and thread mode together\n");
  1696. parse_options_usage(usage, options, "lock-cgroup", 0);
  1697. parse_options_usage(NULL, options, "threads", 0);
  1698. return -1;
  1699. }
  1700. if (symbol_conf.field_sep) {
  1701. if (strstr(symbol_conf.field_sep, ":") || /* part of type flags */
  1702. strstr(symbol_conf.field_sep, "+") || /* part of caller offset */
  1703. strstr(symbol_conf.field_sep, ".")) { /* can be in a symbol name */
  1704. pr_err("Cannot use the separator that is already used\n");
  1705. parse_options_usage(usage, options, "x", 1);
  1706. return -1;
  1707. }
  1708. }
  1709. if (show_lock_owner)
  1710. show_thread_stats = true;
  1711. return 0;
  1712. }
  1713. static int __cmd_contention(int argc, const char **argv)
  1714. {
  1715. int err = -EINVAL;
  1716. struct perf_tool eops;
  1717. struct perf_data data = {
  1718. .path = input_name,
  1719. .mode = PERF_DATA_MODE_READ,
  1720. .force = force,
  1721. };
  1722. struct lock_contention con = {
  1723. .target = &target,
  1724. .map_nr_entries = bpf_map_entries,
  1725. .max_stack = max_stack_depth,
  1726. .stack_skip = stack_skip,
  1727. .filters = &filters,
  1728. .save_callstack = needs_callstack(),
  1729. .owner = show_lock_owner,
  1730. .cgroups = RB_ROOT,
  1731. };
  1732. lockhash_table = calloc(LOCKHASH_SIZE, sizeof(*lockhash_table));
  1733. if (!lockhash_table)
  1734. return -ENOMEM;
  1735. con.result = &lockhash_table[0];
  1736. perf_tool__init(&eops, /*ordered_events=*/true);
  1737. eops.attr = perf_event__process_attr;
  1738. eops.event_update = process_event_update;
  1739. eops.sample = process_sample_event;
  1740. eops.comm = perf_event__process_comm;
  1741. eops.mmap = perf_event__process_mmap;
  1742. eops.tracing_data = perf_event__process_tracing_data;
  1743. session = perf_session__new(use_bpf ? NULL : &data, &eops);
  1744. if (IS_ERR(session)) {
  1745. pr_err("Initializing perf session failed\n");
  1746. err = PTR_ERR(session);
  1747. session = NULL;
  1748. goto out_delete;
  1749. }
  1750. con.machine = &session->machines.host;
  1751. con.aggr_mode = aggr_mode = show_thread_stats ? LOCK_AGGR_TASK :
  1752. show_lock_addrs ? LOCK_AGGR_ADDR :
  1753. show_lock_cgroups ? LOCK_AGGR_CGROUP : LOCK_AGGR_CALLER;
  1754. if (con.aggr_mode == LOCK_AGGR_CALLER)
  1755. con.save_callstack = true;
  1756. symbol_conf.allow_aliases = true;
  1757. symbol__init(&session->header.env);
  1758. if (use_bpf) {
  1759. err = target__validate(&target);
  1760. if (err) {
  1761. char errbuf[512];
  1762. target__strerror(&target, err, errbuf, 512);
  1763. pr_err("%s\n", errbuf);
  1764. goto out_delete;
  1765. }
  1766. signal(SIGINT, sighandler);
  1767. signal(SIGCHLD, sighandler);
  1768. signal(SIGTERM, sighandler);
  1769. con.evlist = evlist__new();
  1770. if (con.evlist == NULL) {
  1771. err = -ENOMEM;
  1772. goto out_delete;
  1773. }
  1774. err = evlist__create_maps(con.evlist, &target);
  1775. if (err < 0)
  1776. goto out_delete;
  1777. if (argc) {
  1778. err = evlist__prepare_workload(con.evlist, &target,
  1779. argv, false, NULL);
  1780. if (err < 0)
  1781. goto out_delete;
  1782. }
  1783. if (lock_contention_prepare(&con) < 0) {
  1784. pr_err("lock contention BPF setup failed\n");
  1785. goto out_delete;
  1786. }
  1787. } else if (!data.is_pipe) {
  1788. if (!perf_session__has_traces(session, "lock record"))
  1789. goto out_delete;
  1790. if (!evlist__find_evsel_by_str(session->evlist,
  1791. "lock:contention_begin")) {
  1792. pr_err("lock contention evsel not found\n");
  1793. goto out_delete;
  1794. }
  1795. if (perf_session__set_tracepoints_handlers(session,
  1796. contention_tracepoints)) {
  1797. pr_err("Initializing perf session tracepoint handlers failed\n");
  1798. goto out_delete;
  1799. }
  1800. }
  1801. if (setup_output_field(true, output_fields))
  1802. goto out_delete;
  1803. if (select_key(true))
  1804. goto out_delete;
  1805. if (symbol_conf.field_sep) {
  1806. int i;
  1807. struct lock_key *keys = contention_keys;
  1808. /* do not align output in CSV format */
  1809. for (i = 0; keys[i].name; i++)
  1810. keys[i].len = 0;
  1811. }
  1812. if (use_bpf) {
  1813. lock_contention_start();
  1814. if (argc)
  1815. evlist__start_workload(con.evlist);
  1816. /* wait for signal */
  1817. pause();
  1818. lock_contention_stop();
  1819. lock_contention_read(&con);
  1820. } else {
  1821. err = perf_session__process_events(session);
  1822. if (err)
  1823. goto out_delete;
  1824. }
  1825. setup_pager();
  1826. sort_contention_result();
  1827. print_contention_result(&con);
  1828. out_delete:
  1829. lock_filter_finish();
  1830. evlist__delete(con.evlist);
  1831. lock_contention_finish(&con);
  1832. perf_session__delete(session);
  1833. zfree(&lockhash_table);
  1834. return err;
  1835. }
  1836. static int __cmd_record(int argc, const char **argv)
  1837. {
  1838. const char *record_args[] = {
  1839. "record", "-R", "-m", "1024", "-c", "1", "--synth", "task",
  1840. };
  1841. const char *callgraph_args[] = {
  1842. "--call-graph", "fp," __stringify(CONTENTION_STACK_DEPTH),
  1843. };
  1844. unsigned int rec_argc, i, j, ret;
  1845. unsigned int nr_tracepoints;
  1846. unsigned int nr_callgraph_args = 0;
  1847. const char **rec_argv;
  1848. bool has_lock_stat = true;
  1849. for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) {
  1850. if (!is_valid_tracepoint(lock_tracepoints[i].name)) {
  1851. pr_debug("tracepoint %s is not enabled. "
  1852. "Are CONFIG_LOCKDEP and CONFIG_LOCK_STAT enabled?\n",
  1853. lock_tracepoints[i].name);
  1854. has_lock_stat = false;
  1855. break;
  1856. }
  1857. }
  1858. if (has_lock_stat)
  1859. goto setup_args;
  1860. for (i = 0; i < ARRAY_SIZE(contention_tracepoints); i++) {
  1861. if (!is_valid_tracepoint(contention_tracepoints[i].name)) {
  1862. pr_err("tracepoint %s is not enabled.\n",
  1863. contention_tracepoints[i].name);
  1864. return 1;
  1865. }
  1866. }
  1867. nr_callgraph_args = ARRAY_SIZE(callgraph_args);
  1868. setup_args:
  1869. rec_argc = ARRAY_SIZE(record_args) + nr_callgraph_args + argc - 1;
  1870. if (has_lock_stat)
  1871. nr_tracepoints = ARRAY_SIZE(lock_tracepoints);
  1872. else
  1873. nr_tracepoints = ARRAY_SIZE(contention_tracepoints);
  1874. /* factor of 2 is for -e in front of each tracepoint */
  1875. rec_argc += 2 * nr_tracepoints;
  1876. rec_argv = calloc(rec_argc + 1, sizeof(char *));
  1877. if (!rec_argv)
  1878. return -ENOMEM;
  1879. for (i = 0; i < ARRAY_SIZE(record_args); i++)
  1880. rec_argv[i] = record_args[i];
  1881. for (j = 0; j < nr_tracepoints; j++) {
  1882. rec_argv[i++] = "-e";
  1883. rec_argv[i++] = has_lock_stat
  1884. ? lock_tracepoints[j].name
  1885. : contention_tracepoints[j].name;
  1886. }
  1887. for (j = 0; j < nr_callgraph_args; j++, i++)
  1888. rec_argv[i] = callgraph_args[j];
  1889. for (j = 1; j < (unsigned int)argc; j++, i++)
  1890. rec_argv[i] = argv[j];
  1891. BUG_ON(i != rec_argc);
  1892. ret = cmd_record(i, rec_argv);
  1893. free(rec_argv);
  1894. return ret;
  1895. }
  1896. static int parse_map_entry(const struct option *opt, const char *str,
  1897. int unset __maybe_unused)
  1898. {
  1899. unsigned long *len = (unsigned long *)opt->value;
  1900. unsigned long val;
  1901. char *endptr;
  1902. errno = 0;
  1903. val = strtoul(str, &endptr, 0);
  1904. if (*endptr != '\0' || errno != 0) {
  1905. pr_err("invalid BPF map length: %s\n", str);
  1906. return -1;
  1907. }
  1908. *len = val;
  1909. return 0;
  1910. }
  1911. static int parse_max_stack(const struct option *opt, const char *str,
  1912. int unset __maybe_unused)
  1913. {
  1914. unsigned long *len = (unsigned long *)opt->value;
  1915. long val;
  1916. char *endptr;
  1917. errno = 0;
  1918. val = strtol(str, &endptr, 0);
  1919. if (*endptr != '\0' || errno != 0) {
  1920. pr_err("invalid max stack depth: %s\n", str);
  1921. return -1;
  1922. }
  1923. if (val < 0 || val > sysctl__max_stack()) {
  1924. pr_err("invalid max stack depth: %ld\n", val);
  1925. return -1;
  1926. }
  1927. *len = val;
  1928. return 0;
  1929. }
  1930. static bool add_lock_type(unsigned int flags)
  1931. {
  1932. unsigned int *tmp;
  1933. tmp = realloc(filters.types, (filters.nr_types + 1) * sizeof(*filters.types));
  1934. if (tmp == NULL)
  1935. return false;
  1936. tmp[filters.nr_types++] = flags;
  1937. filters.types = tmp;
  1938. return true;
  1939. }
  1940. static int parse_lock_type(const struct option *opt __maybe_unused, const char *str,
  1941. int unset __maybe_unused)
  1942. {
  1943. char *s, *tmp, *tok;
  1944. s = strdup(str);
  1945. if (s == NULL)
  1946. return -1;
  1947. for (tok = strtok_r(s, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) {
  1948. bool found = false;
  1949. /* `tok` is `str` in `lock_type_table` if it contains ':'. */
  1950. if (strchr(tok, ':')) {
  1951. for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
  1952. if (!strcmp(lock_type_table[i].str, tok) &&
  1953. add_lock_type(lock_type_table[i].flags)) {
  1954. found = true;
  1955. break;
  1956. }
  1957. }
  1958. if (!found) {
  1959. pr_err("Unknown lock flags name: %s\n", tok);
  1960. free(s);
  1961. return -1;
  1962. }
  1963. continue;
  1964. }
  1965. /*
  1966. * Otherwise `tok` is `name` in `lock_type_table`.
  1967. * Single lock name could contain multiple flags.
  1968. */
  1969. for (unsigned int i = 0; i < ARRAY_SIZE(lock_type_table); i++) {
  1970. if (!strcmp(lock_type_table[i].name, tok)) {
  1971. if (add_lock_type(lock_type_table[i].flags)) {
  1972. found = true;
  1973. } else {
  1974. free(s);
  1975. return -1;
  1976. }
  1977. }
  1978. }
  1979. if (!found) {
  1980. pr_err("Unknown lock name: %s\n", tok);
  1981. free(s);
  1982. return -1;
  1983. }
  1984. }
  1985. free(s);
  1986. return 0;
  1987. }
  1988. static bool add_lock_addr(unsigned long addr)
  1989. {
  1990. unsigned long *tmp;
  1991. tmp = realloc(filters.addrs, (filters.nr_addrs + 1) * sizeof(*filters.addrs));
  1992. if (tmp == NULL) {
  1993. pr_err("Memory allocation failure\n");
  1994. return false;
  1995. }
  1996. tmp[filters.nr_addrs++] = addr;
  1997. filters.addrs = tmp;
  1998. return true;
  1999. }
  2000. static bool add_lock_sym(char *name)
  2001. {
  2002. char **tmp;
  2003. char *sym = strdup(name);
  2004. if (sym == NULL) {
  2005. pr_err("Memory allocation failure\n");
  2006. return false;
  2007. }
  2008. tmp = realloc(filters.syms, (filters.nr_syms + 1) * sizeof(*filters.syms));
  2009. if (tmp == NULL) {
  2010. pr_err("Memory allocation failure\n");
  2011. free(sym);
  2012. return false;
  2013. }
  2014. tmp[filters.nr_syms++] = sym;
  2015. filters.syms = tmp;
  2016. return true;
  2017. }
  2018. static int parse_lock_addr(const struct option *opt __maybe_unused, const char *str,
  2019. int unset __maybe_unused)
  2020. {
  2021. char *s, *tmp, *tok;
  2022. int ret = 0;
  2023. u64 addr;
  2024. s = strdup(str);
  2025. if (s == NULL)
  2026. return -1;
  2027. for (tok = strtok_r(s, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) {
  2028. char *end;
  2029. addr = strtoul(tok, &end, 16);
  2030. if (*end == '\0') {
  2031. if (!add_lock_addr(addr)) {
  2032. ret = -1;
  2033. break;
  2034. }
  2035. continue;
  2036. }
  2037. /*
  2038. * At this moment, we don't have kernel symbols. Save the symbols
  2039. * in a separate list and resolve them to addresses later.
  2040. */
  2041. if (!add_lock_sym(tok)) {
  2042. ret = -1;
  2043. break;
  2044. }
  2045. }
  2046. free(s);
  2047. return ret;
  2048. }
  2049. static int parse_call_stack(const struct option *opt __maybe_unused, const char *str,
  2050. int unset __maybe_unused)
  2051. {
  2052. char *s, *tmp, *tok;
  2053. int ret = 0;
  2054. s = strdup(str);
  2055. if (s == NULL)
  2056. return -1;
  2057. for (tok = strtok_r(s, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) {
  2058. struct callstack_filter *entry;
  2059. entry = malloc(sizeof(*entry) + strlen(tok) + 1);
  2060. if (entry == NULL) {
  2061. pr_err("Memory allocation failure\n");
  2062. free(s);
  2063. return -1;
  2064. }
  2065. strcpy(entry->name, tok);
  2066. list_add_tail(&entry->list, &callstack_filters);
  2067. }
  2068. free(s);
  2069. return ret;
  2070. }
  2071. static int parse_output(const struct option *opt __maybe_unused, const char *str,
  2072. int unset __maybe_unused)
  2073. {
  2074. const char **name = (const char **)opt->value;
  2075. if (str == NULL)
  2076. return -1;
  2077. lock_output = fopen(str, "w");
  2078. if (lock_output == NULL) {
  2079. pr_err("Cannot open %s\n", str);
  2080. return -1;
  2081. }
  2082. *name = str;
  2083. return 0;
  2084. }
  2085. static bool add_lock_cgroup(char *name)
  2086. {
  2087. u64 *tmp;
  2088. struct cgroup *cgrp;
  2089. cgrp = cgroup__new(name, /*do_open=*/false);
  2090. if (cgrp == NULL) {
  2091. pr_err("Failed to create cgroup: %s\n", name);
  2092. return false;
  2093. }
  2094. if (read_cgroup_id(cgrp) < 0) {
  2095. pr_err("Failed to read cgroup id for %s\n", name);
  2096. cgroup__put(cgrp);
  2097. return false;
  2098. }
  2099. tmp = realloc(filters.cgrps, (filters.nr_cgrps + 1) * sizeof(*filters.cgrps));
  2100. if (tmp == NULL) {
  2101. pr_err("Memory allocation failure\n");
  2102. return false;
  2103. }
  2104. tmp[filters.nr_cgrps++] = cgrp->id;
  2105. filters.cgrps = tmp;
  2106. cgroup__put(cgrp);
  2107. return true;
  2108. }
  2109. static int parse_cgroup_filter(const struct option *opt __maybe_unused, const char *str,
  2110. int unset __maybe_unused)
  2111. {
  2112. char *s, *tmp, *tok;
  2113. int ret = 0;
  2114. s = strdup(str);
  2115. if (s == NULL)
  2116. return -1;
  2117. for (tok = strtok_r(s, ", ", &tmp); tok; tok = strtok_r(NULL, ", ", &tmp)) {
  2118. if (!add_lock_cgroup(tok)) {
  2119. ret = -1;
  2120. break;
  2121. }
  2122. }
  2123. free(s);
  2124. return ret;
  2125. }
  2126. int cmd_lock(int argc, const char **argv)
  2127. {
  2128. const struct option lock_options[] = {
  2129. OPT_STRING('i', "input", &input_name, "file", "input file name"),
  2130. OPT_CALLBACK(0, "output", &output_name, "file", "output file name", parse_output),
  2131. OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
  2132. OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
  2133. OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
  2134. OPT_STRING(0, "vmlinux", &symbol_conf.vmlinux_name,
  2135. "file", "vmlinux pathname"),
  2136. OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
  2137. "file", "kallsyms pathname"),
  2138. OPT_BOOLEAN('q', "quiet", &quiet, "Do not show any warnings or messages"),
  2139. OPT_END()
  2140. };
  2141. const struct option info_options[] = {
  2142. OPT_BOOLEAN('t', "threads", &info_threads,
  2143. "dump the thread list in perf.data"),
  2144. OPT_BOOLEAN('m', "map", &info_map,
  2145. "dump the map of lock instances (address:name table)"),
  2146. OPT_PARENT(lock_options)
  2147. };
  2148. const struct option report_options[] = {
  2149. OPT_STRING('k', "key", &sort_key, "acquired",
  2150. "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
  2151. OPT_STRING('F', "field", &output_fields, NULL,
  2152. "output fields (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
  2153. /* TODO: type */
  2154. OPT_BOOLEAN('c', "combine-locks", &combine_locks,
  2155. "combine locks in the same class"),
  2156. OPT_BOOLEAN('t', "threads", &show_thread_stats,
  2157. "show per-thread lock stats"),
  2158. OPT_INTEGER('E', "entries", &print_nr_entries, "display this many functions"),
  2159. OPT_PARENT(lock_options)
  2160. };
  2161. struct option contention_options[] = {
  2162. OPT_STRING('k', "key", &sort_key, "wait_total",
  2163. "key for sorting (contended / wait_total / wait_max / wait_min / avg_wait)"),
  2164. OPT_STRING('F', "field", &output_fields, "contended,wait_total,wait_max,avg_wait",
  2165. "output fields (contended / wait_total / wait_max / wait_min / avg_wait)"),
  2166. OPT_BOOLEAN('t', "threads", &show_thread_stats,
  2167. "show per-thread lock stats"),
  2168. OPT_BOOLEAN('b', "use-bpf", &use_bpf, "use BPF program to collect lock contention stats"),
  2169. OPT_BOOLEAN('a', "all-cpus", &target.system_wide,
  2170. "System-wide collection from all CPUs"),
  2171. OPT_STRING('C', "cpu", &target.cpu_list, "cpu",
  2172. "List of cpus to monitor"),
  2173. OPT_STRING('p', "pid", &target.pid, "pid",
  2174. "Trace on existing process id"),
  2175. OPT_STRING(0, "tid", &target.tid, "tid",
  2176. "Trace on existing thread id (exclusive to --pid)"),
  2177. OPT_CALLBACK('M', "map-nr-entries", &bpf_map_entries, "num",
  2178. "Max number of BPF map entries", parse_map_entry),
  2179. OPT_CALLBACK(0, "max-stack", &max_stack_depth, "num",
  2180. "Set the maximum stack depth when collecting lock contention, "
  2181. "Default: " __stringify(CONTENTION_STACK_DEPTH), parse_max_stack),
  2182. OPT_INTEGER(0, "stack-skip", &stack_skip,
  2183. "Set the number of stack depth to skip when finding a lock caller, "
  2184. "Default: " __stringify(CONTENTION_STACK_SKIP)),
  2185. OPT_INTEGER('E', "entries", &print_nr_entries, "display this many functions"),
  2186. OPT_BOOLEAN('l', "lock-addr", &show_lock_addrs, "show lock stats by address"),
  2187. OPT_CALLBACK('Y', "type-filter", NULL, "FLAGS",
  2188. "Filter specific type of locks", parse_lock_type),
  2189. OPT_CALLBACK('L', "lock-filter", NULL, "ADDRS/NAMES",
  2190. "Filter specific address/symbol of locks", parse_lock_addr),
  2191. OPT_CALLBACK('S', "callstack-filter", NULL, "NAMES",
  2192. "Filter specific function in the callstack", parse_call_stack),
  2193. OPT_BOOLEAN('o', "lock-owner", &show_lock_owner, "show lock owners instead of waiters"),
  2194. OPT_STRING_NOEMPTY('x', "field-separator", &symbol_conf.field_sep, "separator",
  2195. "print result in CSV format with custom separator"),
  2196. OPT_BOOLEAN(0, "lock-cgroup", &show_lock_cgroups, "show lock stats by cgroup"),
  2197. OPT_CALLBACK('G', "cgroup-filter", NULL, "CGROUPS",
  2198. "Filter specific cgroups", parse_cgroup_filter),
  2199. OPT_PARENT(lock_options)
  2200. };
  2201. const char * const info_usage[] = {
  2202. "perf lock info [<options>]",
  2203. NULL
  2204. };
  2205. const char *const lock_subcommands[] = { "record", "report", "script",
  2206. "info", "contention", NULL };
  2207. const char *lock_usage[] = {
  2208. NULL,
  2209. NULL
  2210. };
  2211. const char * const report_usage[] = {
  2212. "perf lock report [<options>]",
  2213. NULL
  2214. };
  2215. const char * const contention_usage[] = {
  2216. "perf lock contention [<options>]",
  2217. NULL
  2218. };
  2219. unsigned int i;
  2220. int rc = 0;
  2221. lockhash_table = calloc(LOCKHASH_SIZE, sizeof(*lockhash_table));
  2222. if (!lockhash_table)
  2223. return -ENOMEM;
  2224. for (i = 0; i < LOCKHASH_SIZE; i++)
  2225. INIT_HLIST_HEAD(lockhash_table + i);
  2226. lock_output = stderr;
  2227. argc = parse_options_subcommand(argc, argv, lock_options, lock_subcommands,
  2228. lock_usage, PARSE_OPT_STOP_AT_NON_OPTION);
  2229. if (!argc)
  2230. usage_with_options(lock_usage, lock_options);
  2231. if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) {
  2232. return __cmd_record(argc, argv);
  2233. } else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) {
  2234. trace_handler = &report_lock_ops;
  2235. if (argc) {
  2236. argc = parse_options(argc, argv,
  2237. report_options, report_usage, 0);
  2238. if (argc)
  2239. usage_with_options(report_usage, report_options);
  2240. }
  2241. rc = __cmd_report(false);
  2242. } else if (!strcmp(argv[0], "script")) {
  2243. /* Aliased to 'perf script' */
  2244. rc = cmd_script(argc, argv);
  2245. } else if (!strcmp(argv[0], "info")) {
  2246. if (argc) {
  2247. argc = parse_options(argc, argv,
  2248. info_options, info_usage, 0);
  2249. if (argc)
  2250. usage_with_options(info_usage, info_options);
  2251. }
  2252. /* If neither threads nor map requested, display both */
  2253. if (!info_threads && !info_map) {
  2254. info_threads = true;
  2255. info_map = true;
  2256. }
  2257. /* recycling report_lock_ops */
  2258. trace_handler = &report_lock_ops;
  2259. rc = __cmd_report(true);
  2260. } else if (strlen(argv[0]) > 2 && strstarts("contention", argv[0])) {
  2261. trace_handler = &contention_lock_ops;
  2262. sort_key = "wait_total";
  2263. output_fields = "contended,wait_total,wait_max,avg_wait";
  2264. #ifndef HAVE_BPF_SKEL
  2265. set_option_nobuild(contention_options, 'b', "use-bpf",
  2266. "no BUILD_BPF_SKEL=1", false);
  2267. #endif
  2268. if (argc) {
  2269. argc = parse_options(argc, argv, contention_options,
  2270. contention_usage, 0);
  2271. }
  2272. if (check_lock_contention_options(contention_options,
  2273. contention_usage) < 0)
  2274. return -1;
  2275. rc = __cmd_contention(argc, argv);
  2276. } else {
  2277. usage_with_options(lock_usage, lock_options);
  2278. }
  2279. /* free usage string allocated by parse_options_subcommand */
  2280. free((void *)lock_usage[0]);
  2281. zfree(&lockhash_table);
  2282. return rc;
  2283. }