Add a flag to indicate deferrable timers in /proc/timer_stats
Add a flag in /proc/timer_stats to indicate deferrable timers. This will let developers/users to differentiate between types of tiemrs in /proc/timer_stats. Deferrable timer and normal timer will appear in /proc/timer_stats as below. 10D, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) 10, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) Also version of timer_stats changes from v0.1 to v0.2 Signed-off-by: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> Acked-by: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: john stultz <johnstul@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
e080706190
commit
c5c061b8f9
5 changed files with 36 additions and 16 deletions
|
@ -67,3 +67,7 @@ executed on expiry.
|
|||
|
||||
Thomas, Ingo
|
||||
|
||||
Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable
|
||||
timer will appear as follows
|
||||
10D, 1 swapper queue_delayed_work_on (delayed_work_timer_fn)
|
||||
|
||||
|
|
|
@ -329,12 +329,13 @@ extern void sysrq_timer_list_show(void);
|
|||
#ifdef CONFIG_TIMER_STATS
|
||||
|
||||
extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
|
||||
void *timerf, char * comm);
|
||||
void *timerf, char *comm,
|
||||
unsigned int timer_flag);
|
||||
|
||||
static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
|
||||
{
|
||||
timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
|
||||
timer->function, timer->start_comm);
|
||||
timer->function, timer->start_comm, 0);
|
||||
}
|
||||
|
||||
extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer,
|
||||
|
|
|
@ -90,16 +90,13 @@ extern unsigned long get_next_timer_interrupt(unsigned long now);
|
|||
*/
|
||||
#ifdef CONFIG_TIMER_STATS
|
||||
|
||||
#define TIMER_STATS_FLAG_DEFERRABLE 0x1
|
||||
|
||||
extern void init_timer_stats(void);
|
||||
|
||||
extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
|
||||
void *timerf, char * comm);
|
||||
|
||||
static inline void timer_stats_account_timer(struct timer_list *timer)
|
||||
{
|
||||
timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
|
||||
timer->function, timer->start_comm);
|
||||
}
|
||||
void *timerf, char *comm,
|
||||
unsigned int timer_flag);
|
||||
|
||||
extern void __timer_stats_timer_set_start_info(struct timer_list *timer,
|
||||
void *addr);
|
||||
|
@ -118,10 +115,6 @@ static inline void init_timer_stats(void)
|
|||
{
|
||||
}
|
||||
|
||||
static inline void timer_stats_account_timer(struct timer_list *timer)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ struct entry {
|
|||
* Number of timeout events:
|
||||
*/
|
||||
unsigned long count;
|
||||
unsigned int timer_flag;
|
||||
|
||||
/*
|
||||
* We save the command-line string to preserve
|
||||
|
@ -231,7 +232,8 @@ static struct entry *tstat_lookup(struct entry *entry, char *comm)
|
|||
* incremented. Otherwise the timer is registered in a free slot.
|
||||
*/
|
||||
void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
|
||||
void *timerf, char * comm)
|
||||
void *timerf, char *comm,
|
||||
unsigned int timer_flag)
|
||||
{
|
||||
/*
|
||||
* It doesnt matter which lock we take:
|
||||
|
@ -249,6 +251,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
|
|||
input.start_func = startf;
|
||||
input.expire_func = timerf;
|
||||
input.pid = pid;
|
||||
input.timer_flag = timer_flag;
|
||||
|
||||
spin_lock_irqsave(lock, flags);
|
||||
if (!active)
|
||||
|
@ -295,7 +298,7 @@ static int tstats_show(struct seq_file *m, void *v)
|
|||
period = ktime_to_timespec(time);
|
||||
ms = period.tv_nsec / 1000000;
|
||||
|
||||
seq_puts(m, "Timer Stats Version: v0.1\n");
|
||||
seq_puts(m, "Timer Stats Version: v0.2\n");
|
||||
seq_printf(m, "Sample period: %ld.%03ld s\n", period.tv_sec, ms);
|
||||
if (atomic_read(&overflow_count))
|
||||
seq_printf(m, "Overflow: %d entries\n",
|
||||
|
@ -303,8 +306,13 @@ static int tstats_show(struct seq_file *m, void *v)
|
|||
|
||||
for (i = 0; i < nr_entries; i++) {
|
||||
entry = entries + i;
|
||||
seq_printf(m, "%4lu, %5d %-16s ",
|
||||
if (entry->timer_flag & TIMER_STATS_FLAG_DEFERRABLE) {
|
||||
seq_printf(m, "%4luD, %5d %-16s ",
|
||||
entry->count, entry->pid, entry->comm);
|
||||
} else {
|
||||
seq_printf(m, " %4lu, %5d %-16s ",
|
||||
entry->count, entry->pid, entry->comm);
|
||||
}
|
||||
|
||||
print_name_offset(m, (unsigned long)entry->start_func);
|
||||
seq_puts(m, " (");
|
||||
|
|
|
@ -305,6 +305,20 @@ void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
|
|||
memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
|
||||
timer->start_pid = current->pid;
|
||||
}
|
||||
|
||||
static void timer_stats_account_timer(struct timer_list *timer)
|
||||
{
|
||||
unsigned int flag = 0;
|
||||
|
||||
if (unlikely(tbase_get_deferrable(timer->base)))
|
||||
flag |= TIMER_STATS_FLAG_DEFERRABLE;
|
||||
|
||||
timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
|
||||
timer->function, timer->start_comm, flag);
|
||||
}
|
||||
|
||||
#else
|
||||
static void timer_stats_account_timer(struct timer_list *timer) {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue