timer_stats.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*
  2. * kernel/time/timer_stats.c
  3. *
  4. * Collect timer usage statistics.
  5. *
  6. * Copyright(C) 2006, Red Hat, Inc., Ingo Molnar
  7. * Copyright(C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
  8. *
  9. * timer_stats is based on timer_top, a similar functionality which was part of
  10. * Con Kolivas dyntick patch set. It was developed by Daniel Petrini at the
  11. * Instituto Nokia de Tecnologia - INdT - Manaus. timer_top's design was based
  12. * on dynamic allocation of the statistics entries and linear search based
  13. * lookup combined with a global lock, rather than the static array, hash
  14. * and per-CPU locking which is used by timer_stats. It was written for the
  15. * pre hrtimer kernel code and therefore did not take hrtimers into account.
  16. * Nevertheless it provided the base for the timer_stats implementation and
  17. * was a helpful source of inspiration. Kudos to Daniel and the Nokia folks
  18. * for this effort.
  19. *
  20. * timer_top.c is
  21. * Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus
  22. * Written by Daniel Petrini <d.pensator@gmail.com>
  23. * timer_top.c was released under the GNU General Public License version 2
  24. *
  25. * We export the addresses and counting of timer functions being called,
  26. * the pid and cmdline from the owner process if applicable.
  27. *
  28. * Start/stop data collection:
  29. * # echo 1[0] >/proc/timer_stats
  30. *
  31. * Display the information collected so far:
  32. * # cat /proc/timer_stats
  33. *
  34. * This program is free software; you can redistribute it and/or modify
  35. * it under the terms of the GNU General Public License version 2 as
  36. * published by the Free Software Foundation.
  37. */
  38. #include <linux/proc_fs.h>
  39. #include <linux/module.h>
  40. #include <linux/spinlock.h>
  41. #include <linux/sched.h>
  42. #include <linux/seq_file.h>
  43. #include <linux/kallsyms.h>
  44. #include <asm/uaccess.h>
  45. /*
  46. * This is our basic unit of interest: a timer expiry event identified
  47. * by the timer, its start/expire functions and the PID of the task that
  48. * started the timer. We count the number of times an event happens:
  49. */
  50. struct entry {
  51. /*
  52. * Hash list:
  53. */
  54. struct entry *next;
  55. /*
  56. * Hash keys:
  57. */
  58. void *timer;
  59. void *start_func;
  60. void *expire_func;
  61. pid_t pid;
  62. /*
  63. * Number of timeout events:
  64. */
  65. unsigned long count;
  66. /*
  67. * We save the command-line string to preserve
  68. * this information past task exit:
  69. */
  70. char comm[TASK_COMM_LEN + 1];
  71. } ____cacheline_aligned_in_smp;
  72. /*
  73. * Spinlock protecting the tables - not taken during lookup:
  74. */
  75. static DEFINE_SPINLOCK(table_lock);
  76. /*
  77. * Per-CPU lookup locks for fast hash lookup:
  78. */
  79. static DEFINE_PER_CPU(spinlock_t, lookup_lock);
  80. /*
  81. * Mutex to serialize state changes with show-stats activities:
  82. */
  83. static DEFINE_MUTEX(show_mutex);
  84. /*
  85. * Collection status, active/inactive:
  86. */
  87. static int __read_mostly active;
  88. /*
  89. * Beginning/end timestamps of measurement:
  90. */
  91. static ktime_t time_start, time_stop;
  92. /*
  93. * tstat entry structs only get allocated while collection is
  94. * active and never freed during that time - this simplifies
  95. * things quite a bit.
  96. *
  97. * They get freed when a new collection period is started.
  98. */
  99. #define MAX_ENTRIES_BITS 10
  100. #define MAX_ENTRIES (1UL << MAX_ENTRIES_BITS)
  101. static unsigned long nr_entries;
  102. static struct entry entries[MAX_ENTRIES];
  103. static atomic_t overflow_count;
  104. /*
  105. * The entries are in a hash-table, for fast lookup:
  106. */
  107. #define TSTAT_HASH_BITS (MAX_ENTRIES_BITS - 1)
  108. #define TSTAT_HASH_SIZE (1UL << TSTAT_HASH_BITS)
  109. #define TSTAT_HASH_MASK (TSTAT_HASH_SIZE - 1)
  110. #define __tstat_hashfn(entry) \
  111. (((unsigned long)(entry)->timer ^ \
  112. (unsigned long)(entry)->start_func ^ \
  113. (unsigned long)(entry)->expire_func ^ \
  114. (unsigned long)(entry)->pid ) & TSTAT_HASH_MASK)
  115. #define tstat_hashentry(entry) (tstat_hash_table + __tstat_hashfn(entry))
  116. static struct entry *tstat_hash_table[TSTAT_HASH_SIZE] __read_mostly;
  117. static void reset_entries(void)
  118. {
  119. nr_entries = 0;
  120. memset(entries, 0, sizeof(entries));
  121. memset(tstat_hash_table, 0, sizeof(tstat_hash_table));
  122. atomic_set(&overflow_count, 0);
  123. }
  124. static struct entry *alloc_entry(void)
  125. {
  126. if (nr_entries >= MAX_ENTRIES)
  127. return NULL;
  128. return entries + nr_entries++;
  129. }
  130. static int match_entries(struct entry *entry1, struct entry *entry2)
  131. {
  132. return entry1->timer == entry2->timer &&
  133. entry1->start_func == entry2->start_func &&
  134. entry1->expire_func == entry2->expire_func &&
  135. entry1->pid == entry2->pid;
  136. }
  137. /*
  138. * Look up whether an entry matching this item is present
  139. * in the hash already. Must be called with irqs off and the
  140. * lookup lock held:
  141. */
  142. static struct entry *tstat_lookup(struct entry *entry, char *comm)
  143. {
  144. struct entry **head, *curr, *prev;
  145. head = tstat_hashentry(entry);
  146. curr = *head;
  147. /*
  148. * The fastpath is when the entry is already hashed,
  149. * we do this with the lookup lock held, but with the
  150. * table lock not held:
  151. */
  152. while (curr) {
  153. if (match_entries(curr, entry))
  154. return curr;
  155. curr = curr->next;
  156. }
  157. /*
  158. * Slowpath: allocate, set up and link a new hash entry:
  159. */
  160. prev = NULL;
  161. curr = *head;
  162. spin_lock(&table_lock);
  163. /*
  164. * Make sure we have not raced with another CPU:
  165. */
  166. while (curr) {
  167. if (match_entries(curr, entry))
  168. goto out_unlock;
  169. prev = curr;
  170. curr = curr->next;
  171. }
  172. curr = alloc_entry();
  173. if (curr) {
  174. *curr = *entry;
  175. curr->count = 0;
  176. curr->next = NULL;
  177. memcpy(curr->comm, comm, TASK_COMM_LEN);
  178. smp_mb(); /* Ensure that curr is initialized before insert */
  179. if (prev)
  180. prev->next = curr;
  181. else
  182. *head = curr;
  183. }
  184. out_unlock:
  185. spin_unlock(&table_lock);
  186. return curr;
  187. }
  188. /**
  189. * timer_stats_update_stats - Update the statistics for a timer.
  190. * @timer: pointer to either a timer_list or a hrtimer
  191. * @pid: the pid of the task which set up the timer
  192. * @startf: pointer to the function which did the timer setup
  193. * @timerf: pointer to the timer callback function of the timer
  194. * @comm: name of the process which set up the timer
  195. *
  196. * When the timer is already registered, then the event counter is
  197. * incremented. Otherwise the timer is registered in a free slot.
  198. */
  199. void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
  200. void *timerf, char * comm)
  201. {
  202. /*
  203. * It doesnt matter which lock we take:
  204. */
  205. spinlock_t *lock;
  206. struct entry *entry, input;
  207. unsigned long flags;
  208. if (likely(!active))
  209. return;
  210. lock = &per_cpu(lookup_lock, raw_smp_processor_id());
  211. input.timer = timer;
  212. input.start_func = startf;
  213. input.expire_func = timerf;
  214. input.pid = pid;
  215. spin_lock_irqsave(lock, flags);
  216. if (!active)
  217. goto out_unlock;
  218. entry = tstat_lookup(&input, comm);
  219. if (likely(entry))
  220. entry->count++;
  221. else
  222. atomic_inc(&overflow_count);
  223. out_unlock:
  224. spin_unlock_irqrestore(lock, flags);
  225. }
  226. static void print_name_offset(struct seq_file *m, unsigned long addr)
  227. {
  228. char symname[KSYM_NAME_LEN+1];
  229. if (lookup_symbol_name(addr, symname) < 0)
  230. seq_printf(m, "<%p>", (void *)addr);
  231. else
  232. seq_printf(m, "%s", symname);
  233. }
  234. static int tstats_show(struct seq_file *m, void *v)
  235. {
  236. struct timespec period;
  237. struct entry *entry;
  238. unsigned long ms;
  239. long events = 0;
  240. ktime_t time;
  241. int i;
  242. mutex_lock(&show_mutex);
  243. /*
  244. * If still active then calculate up to now:
  245. */
  246. if (active)
  247. time_stop = ktime_get();
  248. time = ktime_sub(time_stop, time_start);
  249. period = ktime_to_timespec(time);
  250. ms = period.tv_nsec / 1000000;
  251. seq_puts(m, "Timer Stats Version: v0.1\n");
  252. seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms);
  253. if (atomic_read(&overflow_count))
  254. seq_printf(m, "Overflow: %d entries\n",
  255. atomic_read(&overflow_count));
  256. for (i = 0; i < nr_entries; i++) {
  257. entry = entries + i;
  258. seq_printf(m, "%4lu, %5d %-16s ",
  259. entry->count, entry->pid, entry->comm);
  260. print_name_offset(m, (unsigned long)entry->start_func);
  261. seq_puts(m, " (");
  262. print_name_offset(m, (unsigned long)entry->expire_func);
  263. seq_puts(m, ")\n");
  264. events += entry->count;
  265. }
  266. ms += period.tv_sec * 1000;
  267. if (!ms)
  268. ms = 1;
  269. if (events && period.tv_sec)
  270. seq_printf(m, "%ld total events, %ld.%ld events/sec\n", events,
  271. events / period.tv_sec, events * 1000 / ms);
  272. else
  273. seq_printf(m, "%ld total events\n", events);
  274. mutex_unlock(&show_mutex);
  275. return 0;
  276. }
  277. /*
  278. * After a state change, make sure all concurrent lookup/update
  279. * activities have stopped:
  280. */
  281. static void sync_access(void)
  282. {
  283. unsigned long flags;
  284. int cpu;
  285. for_each_online_cpu(cpu) {
  286. spin_lock_irqsave(&per_cpu(lookup_lock, cpu), flags);
  287. /* nothing */
  288. spin_unlock_irqrestore(&per_cpu(lookup_lock, cpu), flags);
  289. }
  290. }
  291. static ssize_t tstats_write(struct file *file, const char __user *buf,
  292. size_t count, loff_t *offs)
  293. {
  294. char ctl[2];
  295. if (count != 2 || *offs)
  296. return -EINVAL;
  297. if (copy_from_user(ctl, buf, count))
  298. return -EFAULT;
  299. mutex_lock(&show_mutex);
  300. switch (ctl[0]) {
  301. case '0':
  302. if (active) {
  303. active = 0;
  304. time_stop = ktime_get();
  305. sync_access();
  306. }
  307. break;
  308. case '1':
  309. if (!active) {
  310. reset_entries();
  311. time_start = ktime_get();
  312. smp_mb();
  313. active = 1;
  314. }
  315. break;
  316. default:
  317. count = -EINVAL;
  318. }
  319. mutex_unlock(&show_mutex);
  320. return count;
  321. }
  322. static int tstats_open(struct inode *inode, struct file *filp)
  323. {
  324. return single_open(filp, tstats_show, NULL);
  325. }
  326. static struct file_operations tstats_fops = {
  327. .open = tstats_open,
  328. .read = seq_read,
  329. .write = tstats_write,
  330. .llseek = seq_lseek,
  331. .release = seq_release,
  332. };
  333. void __init init_timer_stats(void)
  334. {
  335. int cpu;
  336. for_each_possible_cpu(cpu)
  337. spin_lock_init(&per_cpu(lookup_lock, cpu));
  338. }
  339. static int __init init_tstats_procfs(void)
  340. {
  341. struct proc_dir_entry *pe;
  342. pe = create_proc_entry("timer_stats", 0644, NULL);
  343. if (!pe)
  344. return -ENOMEM;
  345. pe->proc_fops = &tstats_fops;
  346. return 0;
  347. }
  348. __initcall(init_tstats_procfs);