builtin-lock.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. #include "builtin.h"
  2. #include "perf.h"
  3. #include "util/util.h"
  4. #include "util/cache.h"
  5. #include "util/symbol.h"
  6. #include "util/thread.h"
  7. #include "util/header.h"
  8. #include "util/parse-options.h"
  9. #include "util/trace-event.h"
  10. #include "util/debug.h"
  11. #include "util/session.h"
  12. #include <sys/types.h>
  13. #include <sys/prctl.h>
  14. #include <semaphore.h>
  15. #include <pthread.h>
  16. #include <math.h>
  17. #include <limits.h>
  18. #include <linux/list.h>
  19. #include <linux/hash.h>
  20. static struct perf_session *session;
  21. /* based on kernel/lockdep.c */
  22. #define LOCKHASH_BITS 12
  23. #define LOCKHASH_SIZE (1UL << LOCKHASH_BITS)
  24. static struct list_head lockhash_table[LOCKHASH_SIZE];
  25. #define __lockhashfn(key) hash_long((unsigned long)key, LOCKHASH_BITS)
  26. #define lockhashentry(key) (lockhash_table + __lockhashfn((key)))
  27. struct lock_stat {
  28. struct list_head hash_entry;
  29. struct rb_node rb; /* used for sorting */
  30. /*
  31. * FIXME: raw_field_value() returns unsigned long long,
  32. * so address of lockdep_map should be dealed as 64bit.
  33. * Is there more better solution?
  34. */
  35. void *addr; /* address of lockdep_map, used as ID */
  36. char *name; /* for strcpy(), we cannot use const */
  37. unsigned int nr_acquire;
  38. unsigned int nr_acquired;
  39. unsigned int nr_contended;
  40. unsigned int nr_release;
  41. unsigned int nr_readlock;
  42. unsigned int nr_trylock;
  43. /* these times are in nano sec. */
  44. u64 wait_time_total;
  45. u64 wait_time_min;
  46. u64 wait_time_max;
  47. int discard; /* flag of blacklist */
  48. };
  49. /*
  50. * States of lock_seq_stat
  51. *
  52. * UNINITIALIZED is required for detecting first event of acquire.
  53. * As the nature of lock events, there is no guarantee
  54. * that the first event for the locks are acquire,
  55. * it can be acquired, contended or release.
  56. */
  57. #define SEQ_STATE_UNINITIALIZED 0 /* initial state */
  58. #define SEQ_STATE_RELEASED 1
  59. #define SEQ_STATE_ACQUIRING 2
  60. #define SEQ_STATE_ACQUIRED 3
  61. #define SEQ_STATE_READ_ACQUIRED 4
  62. #define SEQ_STATE_CONTENDED 5
  63. /*
  64. * MAX_LOCK_DEPTH
  65. * Imported from include/linux/sched.h.
  66. * Should this be synchronized?
  67. */
  68. #define MAX_LOCK_DEPTH 48
  69. /*
  70. * struct lock_seq_stat:
  71. * Place to put on state of one lock sequence
  72. * 1) acquire -> acquired -> release
  73. * 2) acquire -> contended -> acquired -> release
  74. * 3) acquire (with read or try) -> release
  75. * 4) Are there other patterns?
  76. */
  77. struct lock_seq_stat {
  78. struct list_head list;
  79. int state;
  80. u64 prev_event_time;
  81. void *addr;
  82. int read_count;
  83. };
  84. struct thread_stat {
  85. struct rb_node rb;
  86. u32 tid;
  87. struct list_head seq_list;
  88. };
  89. static struct rb_root thread_stats;
  90. static struct thread_stat *thread_stat_find(u32 tid)
  91. {
  92. struct rb_node *node;
  93. struct thread_stat *st;
  94. node = thread_stats.rb_node;
  95. while (node) {
  96. st = container_of(node, struct thread_stat, rb);
  97. if (st->tid == tid)
  98. return st;
  99. else if (tid < st->tid)
  100. node = node->rb_left;
  101. else
  102. node = node->rb_right;
  103. }
  104. return NULL;
  105. }
  106. static void thread_stat_insert(struct thread_stat *new)
  107. {
  108. struct rb_node **rb = &thread_stats.rb_node;
  109. struct rb_node *parent = NULL;
  110. struct thread_stat *p;
  111. while (*rb) {
  112. p = container_of(*rb, struct thread_stat, rb);
  113. parent = *rb;
  114. if (new->tid < p->tid)
  115. rb = &(*rb)->rb_left;
  116. else if (new->tid > p->tid)
  117. rb = &(*rb)->rb_right;
  118. else
  119. BUG_ON("inserting invalid thread_stat\n");
  120. }
  121. rb_link_node(&new->rb, parent, rb);
  122. rb_insert_color(&new->rb, &thread_stats);
  123. }
  124. static struct thread_stat *thread_stat_findnew_after_first(u32 tid)
  125. {
  126. struct thread_stat *st;
  127. st = thread_stat_find(tid);
  128. if (st)
  129. return st;
  130. st = zalloc(sizeof(struct thread_stat));
  131. if (!st)
  132. die("memory allocation failed\n");
  133. st->tid = tid;
  134. INIT_LIST_HEAD(&st->seq_list);
  135. thread_stat_insert(st);
  136. return st;
  137. }
  138. static struct thread_stat *thread_stat_findnew_first(u32 tid);
  139. static struct thread_stat *(*thread_stat_findnew)(u32 tid) =
  140. thread_stat_findnew_first;
  141. static struct thread_stat *thread_stat_findnew_first(u32 tid)
  142. {
  143. struct thread_stat *st;
  144. st = zalloc(sizeof(struct thread_stat));
  145. if (!st)
  146. die("memory allocation failed\n");
  147. st->tid = tid;
  148. INIT_LIST_HEAD(&st->seq_list);
  149. rb_link_node(&st->rb, NULL, &thread_stats.rb_node);
  150. rb_insert_color(&st->rb, &thread_stats);
  151. thread_stat_findnew = thread_stat_findnew_after_first;
  152. return st;
  153. }
  154. /* build simple key function one is bigger than two */
  155. #define SINGLE_KEY(member) \
  156. static int lock_stat_key_ ## member(struct lock_stat *one, \
  157. struct lock_stat *two) \
  158. { \
  159. return one->member > two->member; \
  160. }
  161. SINGLE_KEY(nr_acquired)
  162. SINGLE_KEY(nr_contended)
  163. SINGLE_KEY(wait_time_total)
  164. SINGLE_KEY(wait_time_min)
  165. SINGLE_KEY(wait_time_max)
  166. struct lock_key {
  167. /*
  168. * name: the value for specify by user
  169. * this should be simpler than raw name of member
  170. * e.g. nr_acquired -> acquired, wait_time_total -> wait_total
  171. */
  172. const char *name;
  173. int (*key)(struct lock_stat*, struct lock_stat*);
  174. };
  175. static const char *sort_key = "acquired";
  176. static int (*compare)(struct lock_stat *, struct lock_stat *);
  177. static struct rb_root result; /* place to store sorted data */
  178. #define DEF_KEY_LOCK(name, fn_suffix) \
  179. { #name, lock_stat_key_ ## fn_suffix }
  180. struct lock_key keys[] = {
  181. DEF_KEY_LOCK(acquired, nr_acquired),
  182. DEF_KEY_LOCK(contended, nr_contended),
  183. DEF_KEY_LOCK(wait_total, wait_time_total),
  184. DEF_KEY_LOCK(wait_min, wait_time_min),
  185. DEF_KEY_LOCK(wait_max, wait_time_max),
  186. /* extra comparisons much complicated should be here */
  187. { NULL, NULL }
  188. };
  189. static void select_key(void)
  190. {
  191. int i;
  192. for (i = 0; keys[i].name; i++) {
  193. if (!strcmp(keys[i].name, sort_key)) {
  194. compare = keys[i].key;
  195. return;
  196. }
  197. }
  198. die("Unknown compare key:%s\n", sort_key);
  199. }
  200. static void insert_to_result(struct lock_stat *st,
  201. int (*bigger)(struct lock_stat *, struct lock_stat *))
  202. {
  203. struct rb_node **rb = &result.rb_node;
  204. struct rb_node *parent = NULL;
  205. struct lock_stat *p;
  206. while (*rb) {
  207. p = container_of(*rb, struct lock_stat, rb);
  208. parent = *rb;
  209. if (bigger(st, p))
  210. rb = &(*rb)->rb_left;
  211. else
  212. rb = &(*rb)->rb_right;
  213. }
  214. rb_link_node(&st->rb, parent, rb);
  215. rb_insert_color(&st->rb, &result);
  216. }
  217. /* returns left most element of result, and erase it */
  218. static struct lock_stat *pop_from_result(void)
  219. {
  220. struct rb_node *node = result.rb_node;
  221. if (!node)
  222. return NULL;
  223. while (node->rb_left)
  224. node = node->rb_left;
  225. rb_erase(node, &result);
  226. return container_of(node, struct lock_stat, rb);
  227. }
  228. static struct lock_stat *lock_stat_findnew(void *addr, const char *name)
  229. {
  230. struct list_head *entry = lockhashentry(addr);
  231. struct lock_stat *ret, *new;
  232. list_for_each_entry(ret, entry, hash_entry) {
  233. if (ret->addr == addr)
  234. return ret;
  235. }
  236. new = zalloc(sizeof(struct lock_stat));
  237. if (!new)
  238. goto alloc_failed;
  239. new->addr = addr;
  240. new->name = zalloc(sizeof(char) * strlen(name) + 1);
  241. if (!new->name)
  242. goto alloc_failed;
  243. strcpy(new->name, name);
  244. new->wait_time_min = ULLONG_MAX;
  245. list_add(&new->hash_entry, entry);
  246. return new;
  247. alloc_failed:
  248. die("memory allocation failed\n");
  249. }
  250. static char const *input_name = "perf.data";
  251. static int profile_cpu = -1;
  252. struct raw_event_sample {
  253. u32 size;
  254. char data[0];
  255. };
  256. struct trace_acquire_event {
  257. void *addr;
  258. const char *name;
  259. int flag;
  260. };
  261. struct trace_acquired_event {
  262. void *addr;
  263. const char *name;
  264. };
  265. struct trace_contended_event {
  266. void *addr;
  267. const char *name;
  268. };
  269. struct trace_release_event {
  270. void *addr;
  271. const char *name;
  272. };
  273. struct trace_lock_handler {
  274. void (*acquire_event)(struct trace_acquire_event *,
  275. struct event *,
  276. int cpu,
  277. u64 timestamp,
  278. struct thread *thread);
  279. void (*acquired_event)(struct trace_acquired_event *,
  280. struct event *,
  281. int cpu,
  282. u64 timestamp,
  283. struct thread *thread);
  284. void (*contended_event)(struct trace_contended_event *,
  285. struct event *,
  286. int cpu,
  287. u64 timestamp,
  288. struct thread *thread);
  289. void (*release_event)(struct trace_release_event *,
  290. struct event *,
  291. int cpu,
  292. u64 timestamp,
  293. struct thread *thread);
  294. };
  295. static struct lock_seq_stat *get_seq(struct thread_stat *ts, void *addr)
  296. {
  297. struct lock_seq_stat *seq;
  298. list_for_each_entry(seq, &ts->seq_list, list) {
  299. if (seq->addr == addr)
  300. return seq;
  301. }
  302. seq = zalloc(sizeof(struct lock_seq_stat));
  303. if (!seq)
  304. die("Not enough memory\n");
  305. seq->state = SEQ_STATE_UNINITIALIZED;
  306. seq->addr = addr;
  307. list_add(&seq->list, &ts->seq_list);
  308. return seq;
  309. }
  310. static int bad_hist[4];
  311. static void
  312. report_lock_acquire_event(struct trace_acquire_event *acquire_event,
  313. struct event *__event __used,
  314. int cpu __used,
  315. u64 timestamp __used,
  316. struct thread *thread __used)
  317. {
  318. struct lock_stat *ls;
  319. struct thread_stat *ts;
  320. struct lock_seq_stat *seq;
  321. ls = lock_stat_findnew(acquire_event->addr, acquire_event->name);
  322. if (ls->discard)
  323. return;
  324. ts = thread_stat_findnew(thread->pid);
  325. seq = get_seq(ts, acquire_event->addr);
  326. switch (seq->state) {
  327. case SEQ_STATE_UNINITIALIZED:
  328. case SEQ_STATE_RELEASED:
  329. if (!acquire_event->flag) {
  330. seq->state = SEQ_STATE_ACQUIRING;
  331. } else {
  332. if (acquire_event->flag & 1)
  333. ls->nr_trylock++;
  334. if (acquire_event->flag & 2)
  335. ls->nr_readlock++;
  336. seq->state = SEQ_STATE_READ_ACQUIRED;
  337. seq->read_count = 1;
  338. ls->nr_acquired++;
  339. }
  340. break;
  341. case SEQ_STATE_READ_ACQUIRED:
  342. if (acquire_event->flag & 2) {
  343. seq->read_count++;
  344. ls->nr_acquired++;
  345. goto end;
  346. } else {
  347. goto broken;
  348. }
  349. break;
  350. case SEQ_STATE_ACQUIRED:
  351. case SEQ_STATE_ACQUIRING:
  352. case SEQ_STATE_CONTENDED:
  353. broken:
  354. /* broken lock sequence, discard it */
  355. ls->discard = 1;
  356. bad_hist[0]++;
  357. list_del(&seq->list);
  358. free(seq);
  359. goto end;
  360. break;
  361. default:
  362. BUG_ON("Unknown state of lock sequence found!\n");
  363. break;
  364. }
  365. ls->nr_acquire++;
  366. seq->prev_event_time = timestamp;
  367. end:
  368. return;
  369. }
  370. static void
  371. report_lock_acquired_event(struct trace_acquired_event *acquired_event,
  372. struct event *__event __used,
  373. int cpu __used,
  374. u64 timestamp __used,
  375. struct thread *thread __used)
  376. {
  377. struct lock_stat *ls;
  378. struct thread_stat *ts;
  379. struct lock_seq_stat *seq;
  380. u64 contended_term;
  381. ls = lock_stat_findnew(acquired_event->addr, acquired_event->name);
  382. if (ls->discard)
  383. return;
  384. ts = thread_stat_findnew(thread->pid);
  385. seq = get_seq(ts, acquired_event->addr);
  386. switch (seq->state) {
  387. case SEQ_STATE_UNINITIALIZED:
  388. /* orphan event, do nothing */
  389. return;
  390. case SEQ_STATE_ACQUIRING:
  391. break;
  392. case SEQ_STATE_CONTENDED:
  393. contended_term = timestamp - seq->prev_event_time;
  394. ls->wait_time_total += contended_term;
  395. if (contended_term < ls->wait_time_min)
  396. ls->wait_time_min = contended_term;
  397. else if (ls->wait_time_max < contended_term)
  398. ls->wait_time_max = contended_term;
  399. break;
  400. case SEQ_STATE_RELEASED:
  401. case SEQ_STATE_ACQUIRED:
  402. case SEQ_STATE_READ_ACQUIRED:
  403. /* broken lock sequence, discard it */
  404. ls->discard = 1;
  405. bad_hist[1]++;
  406. list_del(&seq->list);
  407. free(seq);
  408. goto end;
  409. break;
  410. default:
  411. BUG_ON("Unknown state of lock sequence found!\n");
  412. break;
  413. }
  414. seq->state = SEQ_STATE_ACQUIRED;
  415. ls->nr_acquired++;
  416. seq->prev_event_time = timestamp;
  417. end:
  418. return;
  419. }
  420. static void
  421. report_lock_contended_event(struct trace_contended_event *contended_event,
  422. struct event *__event __used,
  423. int cpu __used,
  424. u64 timestamp __used,
  425. struct thread *thread __used)
  426. {
  427. struct lock_stat *ls;
  428. struct thread_stat *ts;
  429. struct lock_seq_stat *seq;
  430. ls = lock_stat_findnew(contended_event->addr, contended_event->name);
  431. if (ls->discard)
  432. return;
  433. ts = thread_stat_findnew(thread->pid);
  434. seq = get_seq(ts, contended_event->addr);
  435. switch (seq->state) {
  436. case SEQ_STATE_UNINITIALIZED:
  437. /* orphan event, do nothing */
  438. return;
  439. case SEQ_STATE_ACQUIRING:
  440. break;
  441. case SEQ_STATE_RELEASED:
  442. case SEQ_STATE_ACQUIRED:
  443. case SEQ_STATE_READ_ACQUIRED:
  444. case SEQ_STATE_CONTENDED:
  445. /* broken lock sequence, discard it */
  446. ls->discard = 1;
  447. bad_hist[2]++;
  448. list_del(&seq->list);
  449. free(seq);
  450. goto end;
  451. break;
  452. default:
  453. BUG_ON("Unknown state of lock sequence found!\n");
  454. break;
  455. }
  456. seq->state = SEQ_STATE_CONTENDED;
  457. ls->nr_contended++;
  458. seq->prev_event_time = timestamp;
  459. end:
  460. return;
  461. }
  462. static void
  463. report_lock_release_event(struct trace_release_event *release_event,
  464. struct event *__event __used,
  465. int cpu __used,
  466. u64 timestamp __used,
  467. struct thread *thread __used)
  468. {
  469. struct lock_stat *ls;
  470. struct thread_stat *ts;
  471. struct lock_seq_stat *seq;
  472. ls = lock_stat_findnew(release_event->addr, release_event->name);
  473. if (ls->discard)
  474. return;
  475. ts = thread_stat_findnew(thread->pid);
  476. seq = get_seq(ts, release_event->addr);
  477. switch (seq->state) {
  478. case SEQ_STATE_UNINITIALIZED:
  479. goto end;
  480. break;
  481. case SEQ_STATE_ACQUIRED:
  482. break;
  483. case SEQ_STATE_READ_ACQUIRED:
  484. seq->read_count--;
  485. BUG_ON(seq->read_count < 0);
  486. if (!seq->read_count) {
  487. ls->nr_release++;
  488. goto end;
  489. }
  490. break;
  491. case SEQ_STATE_ACQUIRING:
  492. case SEQ_STATE_CONTENDED:
  493. case SEQ_STATE_RELEASED:
  494. /* broken lock sequence, discard it */
  495. ls->discard = 1;
  496. bad_hist[3]++;
  497. goto free_seq;
  498. break;
  499. default:
  500. BUG_ON("Unknown state of lock sequence found!\n");
  501. break;
  502. }
  503. ls->nr_release++;
  504. free_seq:
  505. list_del(&seq->list);
  506. free(seq);
  507. end:
  508. return;
  509. }
  510. /* lock oriented handlers */
  511. /* TODO: handlers for CPU oriented, thread oriented */
  512. static struct trace_lock_handler report_lock_ops = {
  513. .acquire_event = report_lock_acquire_event,
  514. .acquired_event = report_lock_acquired_event,
  515. .contended_event = report_lock_contended_event,
  516. .release_event = report_lock_release_event,
  517. };
  518. static struct trace_lock_handler *trace_handler;
  519. static void
  520. process_lock_acquire_event(void *data,
  521. struct event *event __used,
  522. int cpu __used,
  523. u64 timestamp __used,
  524. struct thread *thread __used)
  525. {
  526. struct trace_acquire_event acquire_event;
  527. u64 tmp; /* this is required for casting... */
  528. tmp = raw_field_value(event, "lockdep_addr", data);
  529. memcpy(&acquire_event.addr, &tmp, sizeof(void *));
  530. acquire_event.name = (char *)raw_field_ptr(event, "name", data);
  531. acquire_event.flag = (int)raw_field_value(event, "flag", data);
  532. if (trace_handler->acquire_event)
  533. trace_handler->acquire_event(&acquire_event, event, cpu, timestamp, thread);
  534. }
  535. static void
  536. process_lock_acquired_event(void *data,
  537. struct event *event __used,
  538. int cpu __used,
  539. u64 timestamp __used,
  540. struct thread *thread __used)
  541. {
  542. struct trace_acquired_event acquired_event;
  543. u64 tmp; /* this is required for casting... */
  544. tmp = raw_field_value(event, "lockdep_addr", data);
  545. memcpy(&acquired_event.addr, &tmp, sizeof(void *));
  546. acquired_event.name = (char *)raw_field_ptr(event, "name", data);
  547. if (trace_handler->acquire_event)
  548. trace_handler->acquired_event(&acquired_event, event, cpu, timestamp, thread);
  549. }
  550. static void
  551. process_lock_contended_event(void *data,
  552. struct event *event __used,
  553. int cpu __used,
  554. u64 timestamp __used,
  555. struct thread *thread __used)
  556. {
  557. struct trace_contended_event contended_event;
  558. u64 tmp; /* this is required for casting... */
  559. tmp = raw_field_value(event, "lockdep_addr", data);
  560. memcpy(&contended_event.addr, &tmp, sizeof(void *));
  561. contended_event.name = (char *)raw_field_ptr(event, "name", data);
  562. if (trace_handler->acquire_event)
  563. trace_handler->contended_event(&contended_event, event, cpu, timestamp, thread);
  564. }
  565. static void
  566. process_lock_release_event(void *data,
  567. struct event *event __used,
  568. int cpu __used,
  569. u64 timestamp __used,
  570. struct thread *thread __used)
  571. {
  572. struct trace_release_event release_event;
  573. u64 tmp; /* this is required for casting... */
  574. tmp = raw_field_value(event, "lockdep_addr", data);
  575. memcpy(&release_event.addr, &tmp, sizeof(void *));
  576. release_event.name = (char *)raw_field_ptr(event, "name", data);
  577. if (trace_handler->acquire_event)
  578. trace_handler->release_event(&release_event, event, cpu, timestamp, thread);
  579. }
  580. static void
  581. process_raw_event(void *data, int cpu __used,
  582. u64 timestamp __used, struct thread *thread __used)
  583. {
  584. struct event *event;
  585. int type;
  586. type = trace_parse_common_type(data);
  587. event = trace_find_event(type);
  588. if (!strcmp(event->name, "lock_acquire"))
  589. process_lock_acquire_event(data, event, cpu, timestamp, thread);
  590. if (!strcmp(event->name, "lock_acquired"))
  591. process_lock_acquired_event(data, event, cpu, timestamp, thread);
  592. if (!strcmp(event->name, "lock_contended"))
  593. process_lock_contended_event(data, event, cpu, timestamp, thread);
  594. if (!strcmp(event->name, "lock_release"))
  595. process_lock_release_event(data, event, cpu, timestamp, thread);
  596. }
  597. struct raw_event_queue {
  598. u64 timestamp;
  599. int cpu;
  600. void *data;
  601. struct thread *thread;
  602. struct list_head list;
  603. };
  604. static LIST_HEAD(raw_event_head);
  605. #define FLUSH_PERIOD (5 * NSEC_PER_SEC)
  606. static u64 flush_limit = ULLONG_MAX;
  607. static u64 last_flush = 0;
  608. struct raw_event_queue *last_inserted;
  609. static void flush_raw_event_queue(u64 limit)
  610. {
  611. struct raw_event_queue *tmp, *iter;
  612. list_for_each_entry_safe(iter, tmp, &raw_event_head, list) {
  613. if (iter->timestamp > limit)
  614. return;
  615. if (iter == last_inserted)
  616. last_inserted = NULL;
  617. process_raw_event(iter->data, iter->cpu, iter->timestamp,
  618. iter->thread);
  619. last_flush = iter->timestamp;
  620. list_del(&iter->list);
  621. free(iter->data);
  622. free(iter);
  623. }
  624. }
  625. static void __queue_raw_event_end(struct raw_event_queue *new)
  626. {
  627. struct raw_event_queue *iter;
  628. list_for_each_entry_reverse(iter, &raw_event_head, list) {
  629. if (iter->timestamp < new->timestamp) {
  630. list_add(&new->list, &iter->list);
  631. return;
  632. }
  633. }
  634. list_add(&new->list, &raw_event_head);
  635. }
  636. static void __queue_raw_event_before(struct raw_event_queue *new,
  637. struct raw_event_queue *iter)
  638. {
  639. list_for_each_entry_continue_reverse(iter, &raw_event_head, list) {
  640. if (iter->timestamp < new->timestamp) {
  641. list_add(&new->list, &iter->list);
  642. return;
  643. }
  644. }
  645. list_add(&new->list, &raw_event_head);
  646. }
  647. static void __queue_raw_event_after(struct raw_event_queue *new,
  648. struct raw_event_queue *iter)
  649. {
  650. list_for_each_entry_continue(iter, &raw_event_head, list) {
  651. if (iter->timestamp > new->timestamp) {
  652. list_add_tail(&new->list, &iter->list);
  653. return;
  654. }
  655. }
  656. list_add_tail(&new->list, &raw_event_head);
  657. }
  658. /* The queue is ordered by time */
  659. static void __queue_raw_event(struct raw_event_queue *new)
  660. {
  661. if (!last_inserted) {
  662. __queue_raw_event_end(new);
  663. return;
  664. }
  665. /*
  666. * Most of the time the current event has a timestamp
  667. * very close to the last event inserted, unless we just switched
  668. * to another event buffer. Having a sorting based on a list and
  669. * on the last inserted event that is close to the current one is
  670. * probably more efficient than an rbtree based sorting.
  671. */
  672. if (last_inserted->timestamp >= new->timestamp)
  673. __queue_raw_event_before(new, last_inserted);
  674. else
  675. __queue_raw_event_after(new, last_inserted);
  676. }
  677. static void queue_raw_event(void *data, int raw_size, int cpu,
  678. u64 timestamp, struct thread *thread)
  679. {
  680. struct raw_event_queue *new;
  681. if (flush_limit == ULLONG_MAX)
  682. flush_limit = timestamp + FLUSH_PERIOD;
  683. if (timestamp < last_flush) {
  684. printf("Warning: Timestamp below last timeslice flush\n");
  685. return;
  686. }
  687. new = malloc(sizeof(*new));
  688. if (!new)
  689. die("Not enough memory\n");
  690. new->timestamp = timestamp;
  691. new->cpu = cpu;
  692. new->thread = thread;
  693. new->data = malloc(raw_size);
  694. if (!new->data)
  695. die("Not enough memory\n");
  696. memcpy(new->data, data, raw_size);
  697. __queue_raw_event(new);
  698. last_inserted = new;
  699. /*
  700. * We want to have a slice of events covering 2 * FLUSH_PERIOD
  701. * If FLUSH_PERIOD is big enough, it ensures every events that occured
  702. * in the first half of the timeslice have all been buffered and there
  703. * are none remaining (we need that because of the weakly ordered
  704. * event recording we have). Then once we reach the 2 * FLUSH_PERIOD
  705. * timeslice, we flush the first half to be gentle with the memory
  706. * (the second half can still get new events in the middle, so wait
  707. * another period to flush it)
  708. */
  709. if (new->timestamp > flush_limit &&
  710. new->timestamp - flush_limit > FLUSH_PERIOD) {
  711. flush_limit += FLUSH_PERIOD;
  712. flush_raw_event_queue(flush_limit);
  713. }
  714. }
  715. static int process_sample_event(event_t *event, struct perf_session *s)
  716. {
  717. struct thread *thread;
  718. struct sample_data data;
  719. bzero(&data, sizeof(struct sample_data));
  720. event__parse_sample(event, s->sample_type, &data);
  721. /* CAUTION: using tid as thread.pid */
  722. thread = perf_session__findnew(s, data.tid);
  723. if (thread == NULL) {
  724. pr_debug("problem processing %d event, skipping it.\n",
  725. event->header.type);
  726. return -1;
  727. }
  728. dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
  729. if (profile_cpu != -1 && profile_cpu != (int) data.cpu)
  730. return 0;
  731. queue_raw_event(data.raw_data, data.raw_size, data.cpu, data.time, thread);
  732. return 0;
  733. }
  734. /* TODO: various way to print, coloring, nano or milli sec */
  735. static void print_result(void)
  736. {
  737. struct lock_stat *st;
  738. char cut_name[20];
  739. int bad, total;
  740. printf("%20s ", "Name");
  741. printf("%10s ", "acquired");
  742. printf("%10s ", "contended");
  743. printf("%15s ", "total wait (ns)");
  744. printf("%15s ", "max wait (ns)");
  745. printf("%15s ", "min wait (ns)");
  746. printf("\n\n");
  747. bad = total = 0;
  748. while ((st = pop_from_result())) {
  749. total++;
  750. if (st->discard) {
  751. bad++;
  752. continue;
  753. }
  754. bzero(cut_name, 20);
  755. if (strlen(st->name) < 16) {
  756. /* output raw name */
  757. printf("%20s ", st->name);
  758. } else {
  759. strncpy(cut_name, st->name, 16);
  760. cut_name[16] = '.';
  761. cut_name[17] = '.';
  762. cut_name[18] = '.';
  763. cut_name[19] = '\0';
  764. /* cut off name for saving output style */
  765. printf("%20s ", cut_name);
  766. }
  767. printf("%10u ", st->nr_acquired);
  768. printf("%10u ", st->nr_contended);
  769. printf("%15llu ", st->wait_time_total);
  770. printf("%15llu ", st->wait_time_max);
  771. printf("%15llu ", st->wait_time_min == ULLONG_MAX ?
  772. 0 : st->wait_time_min);
  773. printf("\n");
  774. }
  775. {
  776. /* Output for debug, this have to be removed */
  777. int i;
  778. const char *name[4] =
  779. { "acquire", "acquired", "contended", "release" };
  780. printf("\n=== output for debug===\n\n");
  781. printf("bad:%d, total:%d\n", bad, total);
  782. printf("bad rate:%f\n", (double)(bad / total));
  783. printf("histogram of events caused bad sequence\n");
  784. for (i = 0; i < 4; i++)
  785. printf(" %10s: %d\n", name[i], bad_hist[i]);
  786. }
  787. }
  788. static void dump_map(void)
  789. {
  790. unsigned int i;
  791. struct lock_stat *st;
  792. for (i = 0; i < LOCKHASH_SIZE; i++) {
  793. list_for_each_entry(st, &lockhash_table[i], hash_entry) {
  794. printf("%p: %s\n", st->addr, st->name);
  795. }
  796. }
  797. }
  798. static struct perf_event_ops eops = {
  799. .sample = process_sample_event,
  800. .comm = event__process_comm,
  801. };
  802. static int read_events(void)
  803. {
  804. session = perf_session__new(input_name, O_RDONLY, 0);
  805. if (!session)
  806. die("Initializing perf session failed\n");
  807. return perf_session__process_events(session, &eops);
  808. }
  809. static void sort_result(void)
  810. {
  811. unsigned int i;
  812. struct lock_stat *st;
  813. for (i = 0; i < LOCKHASH_SIZE; i++) {
  814. list_for_each_entry(st, &lockhash_table[i], hash_entry) {
  815. insert_to_result(st, compare);
  816. }
  817. }
  818. }
  819. static void __cmd_report(void)
  820. {
  821. setup_pager();
  822. select_key();
  823. read_events();
  824. flush_raw_event_queue(ULLONG_MAX);
  825. sort_result();
  826. print_result();
  827. }
  828. static const char * const report_usage[] = {
  829. "perf lock report [<options>]",
  830. NULL
  831. };
  832. static const struct option report_options[] = {
  833. OPT_STRING('k', "key", &sort_key, "acquired",
  834. "key for sorting"),
  835. /* TODO: type */
  836. OPT_END()
  837. };
  838. static const char * const lock_usage[] = {
  839. "perf lock [<options>] {record|trace|report}",
  840. NULL
  841. };
  842. static const struct option lock_options[] = {
  843. OPT_STRING('i', "input", &input_name, "file", "input file name"),
  844. OPT_INCR('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"),
  845. OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"),
  846. OPT_END()
  847. };
  848. static const char *record_args[] = {
  849. "record",
  850. "-a",
  851. "-R",
  852. "-f",
  853. "-m", "1024",
  854. "-c", "1",
  855. "-e", "lock:lock_acquire:r",
  856. "-e", "lock:lock_acquired:r",
  857. "-e", "lock:lock_contended:r",
  858. "-e", "lock:lock_release:r",
  859. };
  860. static int __cmd_record(int argc, const char **argv)
  861. {
  862. unsigned int rec_argc, i, j;
  863. const char **rec_argv;
  864. rec_argc = ARRAY_SIZE(record_args) + argc - 1;
  865. rec_argv = calloc(rec_argc + 1, sizeof(char *));
  866. for (i = 0; i < ARRAY_SIZE(record_args); i++)
  867. rec_argv[i] = strdup(record_args[i]);
  868. for (j = 1; j < (unsigned int)argc; j++, i++)
  869. rec_argv[i] = argv[j];
  870. BUG_ON(i != rec_argc);
  871. return cmd_record(i, rec_argv, NULL);
  872. }
  873. int cmd_lock(int argc, const char **argv, const char *prefix __used)
  874. {
  875. unsigned int i;
  876. symbol__init();
  877. for (i = 0; i < LOCKHASH_SIZE; i++)
  878. INIT_LIST_HEAD(lockhash_table + i);
  879. argc = parse_options(argc, argv, lock_options, lock_usage,
  880. PARSE_OPT_STOP_AT_NON_OPTION);
  881. if (!argc)
  882. usage_with_options(lock_usage, lock_options);
  883. if (!strncmp(argv[0], "rec", 3)) {
  884. return __cmd_record(argc, argv);
  885. } else if (!strncmp(argv[0], "report", 6)) {
  886. trace_handler = &report_lock_ops;
  887. if (argc) {
  888. argc = parse_options(argc, argv,
  889. report_options, report_usage, 0);
  890. if (argc)
  891. usage_with_options(report_usage, report_options);
  892. }
  893. __cmd_report();
  894. } else if (!strcmp(argv[0], "trace")) {
  895. /* Aliased to 'perf trace' */
  896. return cmd_trace(argc, argv, prefix);
  897. } else if (!strcmp(argv[0], "map")) {
  898. /* recycling report_lock_ops */
  899. trace_handler = &report_lock_ops;
  900. setup_pager();
  901. read_events();
  902. dump_map();
  903. } else {
  904. usage_with_options(lock_usage, lock_options);
  905. }
  906. return 0;
  907. }