aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/hrtimer/timer_stats.txt4
-rw-r--r--include/linux/hrtimer.h5
-rw-r--r--include/linux/timer.h15
-rw-r--r--kernel/time/timer_stats.c14
-rw-r--r--kernel/timer.c14
5 files changed, 36 insertions, 16 deletions
diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt
index 22b0814d0ad0..20d368c59814 100644
--- a/Documentation/hrtimer/timer_stats.txt
+++ b/Documentation/hrtimer/timer_stats.txt
@@ -67,3 +67,7 @@ executed on expiry.
67 67
68 Thomas, Ingo 68 Thomas, Ingo
69 69
70Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable
71timer will appear as follows
72 10D, 1 swapper queue_delayed_work_on (delayed_work_timer_fn)
73
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 17c29dca8354..540799bc85f8 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -329,12 +329,13 @@ extern void sysrq_timer_list_show(void);
329#ifdef CONFIG_TIMER_STATS 329#ifdef CONFIG_TIMER_STATS
330 330
331extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf, 331extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
332 void *timerf, char * comm); 332 void *timerf, char *comm,
333 unsigned int timer_flag);
333 334
334static inline void timer_stats_account_hrtimer(struct hrtimer *timer) 335static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
335{ 336{
336 timer_stats_update_stats(timer, timer->start_pid, timer->start_site, 337 timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
337 timer->function, timer->start_comm); 338 timer->function, timer->start_comm, 0);
338} 339}
339 340
340extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer, 341extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer,
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 2b59e6d4219c..78cf899b4409 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -90,16 +90,13 @@ extern unsigned long get_next_timer_interrupt(unsigned long now);
90 */ 90 */
91#ifdef CONFIG_TIMER_STATS 91#ifdef CONFIG_TIMER_STATS
92 92
93#define TIMER_STATS_FLAG_DEFERRABLE 0x1
94
93extern void init_timer_stats(void); 95extern void init_timer_stats(void);
94 96
95extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf, 97extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
96 void *timerf, char * comm); 98 void *timerf, char *comm,
97 99 unsigned int timer_flag);
98static inline void timer_stats_account_timer(struct timer_list *timer)
99{
100 timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
101 timer->function, timer->start_comm);
102}
103 100
104extern void __timer_stats_timer_set_start_info(struct timer_list *timer, 101extern void __timer_stats_timer_set_start_info(struct timer_list *timer,
105 void *addr); 102 void *addr);
@@ -118,10 +115,6 @@ static inline void init_timer_stats(void)
118{ 115{
119} 116}
120 117
121static inline void timer_stats_account_timer(struct timer_list *timer)
122{
123}
124
125static inline void timer_stats_timer_set_start_info(struct timer_list *timer) 118static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
126{ 119{
127} 120}
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
index 321693724ad7..9b8a826236dd 100644
--- a/kernel/time/timer_stats.c
+++ b/kernel/time/timer_stats.c
@@ -68,6 +68,7 @@ struct entry {
68 * Number of timeout events: 68 * Number of timeout events:
69 */ 69 */
70 unsigned long count; 70 unsigned long count;
71 unsigned int timer_flag;
71 72
72 /* 73 /*
73 * We save the command-line string to preserve 74 * We save the command-line string to preserve
@@ -231,7 +232,8 @@ static struct entry *tstat_lookup(struct entry *entry, char *comm)
231 * incremented. Otherwise the timer is registered in a free slot. 232 * incremented. Otherwise the timer is registered in a free slot.
232 */ 233 */
233void timer_stats_update_stats(void *timer, pid_t pid, void *startf, 234void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
234 void *timerf, char * comm) 235 void *timerf, char *comm,
236 unsigned int timer_flag)
235{ 237{
236 /* 238 /*
237 * It doesnt matter which lock we take: 239 * It doesnt matter which lock we take:
@@ -249,6 +251,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
249 input.start_func = startf; 251 input.start_func = startf;
250 input.expire_func = timerf; 252 input.expire_func = timerf;
251 input.pid = pid; 253 input.pid = pid;
254 input.timer_flag = timer_flag;
252 255
253 spin_lock_irqsave(lock, flags); 256 spin_lock_irqsave(lock, flags);
254 if (!active) 257 if (!active)
@@ -295,7 +298,7 @@ static int tstats_show(struct seq_file *m, void *v)
295 period = ktime_to_timespec(time); 298 period = ktime_to_timespec(time);
296 ms = period.tv_nsec / 1000000; 299 ms = period.tv_nsec / 1000000;
297 300
298 seq_puts(m, "Timer Stats Version: v0.1\n"); 301 seq_puts(m, "Timer Stats Version: v0.2\n");
299 seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms); 302 seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms);
300 if (atomic_read(&overflow_count)) 303 if (atomic_read(&overflow_count))
301 seq_printf(m, "Overflow: %d entries\n", 304 seq_printf(m, "Overflow: %d entries\n",
@@ -303,8 +306,13 @@ static int tstats_show(struct seq_file *m, void *v)
303 306
304 for (i = 0; i < nr_entries; i++) { 307 for (i = 0; i < nr_entries; i++) {
305 entry = entries + i; 308 entry = entries + i;
306 seq_printf(m, "%4lu, %5d %-16s ", 309 if (entry->timer_flag & TIMER_STATS_FLAG_DEFERRABLE) {
310 seq_printf(m, "%4luD, %5d %-16s ",
307 entry->count, entry->pid, entry->comm); 311 entry->count, entry->pid, entry->comm);
312 } else {
313 seq_printf(m, " %4lu, %5d %-16s ",
314 entry->count, entry->pid, entry->comm);
315 }
308 316
309 print_name_offset(m, (unsigned long)entry->start_func); 317 print_name_offset(m, (unsigned long)entry->start_func);
310 seq_puts(m, " ("); 318 seq_puts(m, " (");
diff --git a/kernel/timer.c b/kernel/timer.c
index 1ab3106a2b5d..1258371e0d2b 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -305,6 +305,20 @@ void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
305 memcpy(timer->start_comm, current->comm, TASK_COMM_LEN); 305 memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
306 timer->start_pid = current->pid; 306 timer->start_pid = current->pid;
307} 307}
308
309static void timer_stats_account_timer(struct timer_list *timer)
310{
311 unsigned int flag = 0;
312
313 if (unlikely(tbase_get_deferrable(timer->base)))
314 flag |= TIMER_STATS_FLAG_DEFERRABLE;
315
316 timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
317 timer->function, timer->start_comm, flag);
318}
319
320#else
321static void timer_stats_account_timer(struct timer_list *timer) {}
308#endif 322#endif
309 323
310/** 324/**