Loading Documentation/timers/timer_stats.txtdeleted 100644 → 0 +0 −73 Original line number Diff line number Diff line timer_stats - timer usage statistics ------------------------------------ timer_stats is a debugging facility to make the timer (ab)usage in a Linux system visible to kernel and userspace developers. If enabled in the config but not used it has almost zero runtime overhead, and a relatively small data structure overhead. Even if collection is enabled runtime all the locking is per-CPU and lookup is hashed. timer_stats should be used by kernel and userspace developers to verify that their code does not make unduly use of timers. This helps to avoid unnecessary wakeups, which should be avoided to optimize power consumption. It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration section. timer_stats collects information about the timer events which are fired in a Linux system over a sample period: - the pid of the task(process) which initialized the timer - the name of the process which initialized the timer - the function where the timer was initialized - the callback function which is associated to the timer - the number of events (callbacks) timer_stats adds an entry to /proc: /proc/timer_stats This entry is used to control the statistics functionality and to read out the sampled information. The timer_stats functionality is inactive on bootup. To activate a sample period issue: # echo 1 >/proc/timer_stats To stop a sample period issue: # echo 0 >/proc/timer_stats The statistics can be retrieved by: # cat /proc/timer_stats While sampling is enabled, each readout from /proc/timer_stats will see newly updated statistics. Once sampling is disabled, the sampled information is kept until a new sample period is started. This allows multiple readouts. Sample output of /proc/timer_stats: Timerstats sample period: 3.888770 s 12, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick) 15, 1 swapper hcd_submit_urb (rh_timer_func) 4, 959 kedac schedule_timeout (process_timeout) 1, 0 swapper page_writeback_init (wb_timer_fn) 28, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick) 22, 2948 IRQ 4 tty_flip_buffer_push (delayed_work_timer_fn) 3, 3100 bash schedule_timeout (process_timeout) 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) 1, 1 swapper neigh_table_init_no_netlink (neigh_periodic_timer) 1, 2292 ip __netdev_watchdog_up (dev_watchdog) 1, 23 events/1 do_cache_clean (delayed_work_timer_fn) 90 total events, 30.0 events/sec The first column is the number of events, the second column the pid, the third column is the name of the process. The forth column shows the function which initialized the timer and in parenthesis the callback function which was 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) include/linux/hrtimer.h +0 −11 Original line number Diff line number Diff line Loading @@ -91,12 +91,6 @@ enum hrtimer_restart { * @base: pointer to the timer base (per cpu and per clock) * @state: state information (See bit values above) * @is_rel: Set if the timer was armed relative * @start_pid: timer statistics field to store the pid of the task which * started the timer * @start_site: timer statistics field to store the site where the timer * was started * @start_comm: timer statistics field to store the name of the process which * started the timer * * The hrtimer structure must be initialized by hrtimer_init() */ Loading @@ -107,11 +101,6 @@ struct hrtimer { struct hrtimer_clock_base *base; u8 state; u8 is_rel; #ifdef CONFIG_TIMER_STATS int start_pid; void *start_site; char start_comm[16]; #endif }; /** Loading include/linux/timer.h +0 −45 Original line number Diff line number Diff line Loading @@ -20,11 +20,6 @@ struct timer_list { unsigned long data; u32 flags; #ifdef CONFIG_TIMER_STATS int start_pid; void *start_site; char start_comm[16]; #endif #ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map; #endif Loading Loading @@ -200,46 +195,6 @@ extern int mod_timer_pending(struct timer_list *timer, unsigned long expires); /* To be used from cpusets, only */ extern void timer_quiesce_cpu(void *cpup); /* * Timer-statistics info: */ #ifdef CONFIG_TIMER_STATS extern int timer_stats_active; extern void init_timer_stats(void); extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf, void *timerf, char *comm, u32 flags); extern void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr); static inline void timer_stats_timer_set_start_info(struct timer_list *timer) { if (likely(!timer_stats_active)) return; __timer_stats_timer_set_start_info(timer, __builtin_return_address(0)); } static inline void timer_stats_timer_clear_start_info(struct timer_list *timer) { timer->start_site = NULL; } #else static inline void init_timer_stats(void) { } static inline void timer_stats_timer_set_start_info(struct timer_list *timer) { } static inline void timer_stats_timer_clear_start_info(struct timer_list *timer) { } #endif extern void add_timer(struct timer_list *timer); extern int try_to_del_timer_sync(struct timer_list *timer); Loading kernel/kthread.c +0 −1 Original line number Diff line number Diff line Loading @@ -854,7 +854,6 @@ void __kthread_queue_delayed_work(struct kthread_worker *worker, list_add(&work->node, &worker->delayed_work_list); work->worker = worker; timer_stats_timer_set_start_info(&dwork->timer); timer->expires = jiffies + delay; add_timer(timer); } Loading kernel/time/Makefile +0 −1 Original line number Diff line number Diff line Loading @@ -9,7 +9,6 @@ ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y) endif obj-$(CONFIG_GENERIC_SCHED_CLOCK) += sched_clock.o obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o tick-sched.o obj-$(CONFIG_TIMER_STATS) += timer_stats.o obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o obj-$(CONFIG_TEST_UDELAY) += test_udelay.o Loading Loading
Documentation/timers/timer_stats.txtdeleted 100644 → 0 +0 −73 Original line number Diff line number Diff line timer_stats - timer usage statistics ------------------------------------ timer_stats is a debugging facility to make the timer (ab)usage in a Linux system visible to kernel and userspace developers. If enabled in the config but not used it has almost zero runtime overhead, and a relatively small data structure overhead. Even if collection is enabled runtime all the locking is per-CPU and lookup is hashed. timer_stats should be used by kernel and userspace developers to verify that their code does not make unduly use of timers. This helps to avoid unnecessary wakeups, which should be avoided to optimize power consumption. It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration section. timer_stats collects information about the timer events which are fired in a Linux system over a sample period: - the pid of the task(process) which initialized the timer - the name of the process which initialized the timer - the function where the timer was initialized - the callback function which is associated to the timer - the number of events (callbacks) timer_stats adds an entry to /proc: /proc/timer_stats This entry is used to control the statistics functionality and to read out the sampled information. The timer_stats functionality is inactive on bootup. To activate a sample period issue: # echo 1 >/proc/timer_stats To stop a sample period issue: # echo 0 >/proc/timer_stats The statistics can be retrieved by: # cat /proc/timer_stats While sampling is enabled, each readout from /proc/timer_stats will see newly updated statistics. Once sampling is disabled, the sampled information is kept until a new sample period is started. This allows multiple readouts. Sample output of /proc/timer_stats: Timerstats sample period: 3.888770 s 12, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick) 15, 1 swapper hcd_submit_urb (rh_timer_func) 4, 959 kedac schedule_timeout (process_timeout) 1, 0 swapper page_writeback_init (wb_timer_fn) 28, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick) 22, 2948 IRQ 4 tty_flip_buffer_push (delayed_work_timer_fn) 3, 3100 bash schedule_timeout (process_timeout) 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) 1, 1 swapper neigh_table_init_no_netlink (neigh_periodic_timer) 1, 2292 ip __netdev_watchdog_up (dev_watchdog) 1, 23 events/1 do_cache_clean (delayed_work_timer_fn) 90 total events, 30.0 events/sec The first column is the number of events, the second column the pid, the third column is the name of the process. The forth column shows the function which initialized the timer and in parenthesis the callback function which was 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)
include/linux/hrtimer.h +0 −11 Original line number Diff line number Diff line Loading @@ -91,12 +91,6 @@ enum hrtimer_restart { * @base: pointer to the timer base (per cpu and per clock) * @state: state information (See bit values above) * @is_rel: Set if the timer was armed relative * @start_pid: timer statistics field to store the pid of the task which * started the timer * @start_site: timer statistics field to store the site where the timer * was started * @start_comm: timer statistics field to store the name of the process which * started the timer * * The hrtimer structure must be initialized by hrtimer_init() */ Loading @@ -107,11 +101,6 @@ struct hrtimer { struct hrtimer_clock_base *base; u8 state; u8 is_rel; #ifdef CONFIG_TIMER_STATS int start_pid; void *start_site; char start_comm[16]; #endif }; /** Loading
include/linux/timer.h +0 −45 Original line number Diff line number Diff line Loading @@ -20,11 +20,6 @@ struct timer_list { unsigned long data; u32 flags; #ifdef CONFIG_TIMER_STATS int start_pid; void *start_site; char start_comm[16]; #endif #ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map; #endif Loading Loading @@ -200,46 +195,6 @@ extern int mod_timer_pending(struct timer_list *timer, unsigned long expires); /* To be used from cpusets, only */ extern void timer_quiesce_cpu(void *cpup); /* * Timer-statistics info: */ #ifdef CONFIG_TIMER_STATS extern int timer_stats_active; extern void init_timer_stats(void); extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf, void *timerf, char *comm, u32 flags); extern void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr); static inline void timer_stats_timer_set_start_info(struct timer_list *timer) { if (likely(!timer_stats_active)) return; __timer_stats_timer_set_start_info(timer, __builtin_return_address(0)); } static inline void timer_stats_timer_clear_start_info(struct timer_list *timer) { timer->start_site = NULL; } #else static inline void init_timer_stats(void) { } static inline void timer_stats_timer_set_start_info(struct timer_list *timer) { } static inline void timer_stats_timer_clear_start_info(struct timer_list *timer) { } #endif extern void add_timer(struct timer_list *timer); extern int try_to_del_timer_sync(struct timer_list *timer); Loading
kernel/kthread.c +0 −1 Original line number Diff line number Diff line Loading @@ -854,7 +854,6 @@ void __kthread_queue_delayed_work(struct kthread_worker *worker, list_add(&work->node, &worker->delayed_work_list); work->worker = worker; timer_stats_timer_set_start_info(&dwork->timer); timer->expires = jiffies + delay; add_timer(timer); } Loading
kernel/time/Makefile +0 −1 Original line number Diff line number Diff line Loading @@ -9,7 +9,6 @@ ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y) endif obj-$(CONFIG_GENERIC_SCHED_CLOCK) += sched_clock.o obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o tick-sched.o obj-$(CONFIG_TIMER_STATS) += timer_stats.o obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o obj-$(CONFIG_TEST_UDELAY) += test_udelay.o Loading