@ -8,15 +8,17 @@
# include <linux/clocksource.h>
# include <linux/init.h>
# include <linux/jiffies.h>
# include <linux/ktime.h>
# include <linux/kernel.h>
# include <linux/moduleparam.h>
# include <linux/sched.h>
# include <linux/syscore_ops.h>
# include <linux/timer.h>
# include <linux/hr timer.h>
# include <linux/sched_clock.h>
# include <linux/seqlock.h>
struct clock_data {
ktime_t wrap_kt ;
u64 epoch_ns ;
u32 epoch_cyc ;
seqcount_t seq ;
@ -26,8 +28,7 @@ struct clock_data {
bool suspended ;
} ;
static void sched_clock_poll ( unsigned long wrap_ticks ) ;
static DEFINE_TIMER ( sched_clock_timer , sched_clock_poll , 0 , 0 ) ;
static struct hrtimer sched_clock_timer ;
static int irqtime = - 1 ;
core_param ( irqtime , irqtime , int , 0400 ) ;
@ -93,15 +94,16 @@ static void notrace update_sched_clock(void)
raw_local_irq_restore ( flags ) ;
}
static void sched_clock_poll ( unsigned long wrap_ticks )
static enum hrtimer_restart sched_clock_poll ( struct hrtimer * hrt )
{
mod_timer ( & sched_clock_timer , round_jiffies ( jiffies + wrap_ticks ) ) ;
update_sched_clock ( ) ;
hrtimer_forward_now ( hrt , cd . wrap_kt ) ;
return HRTIMER_RESTART ;
}
void __init setup_sched_clock ( u32 ( * read ) ( void ) , int bits , unsigned long rate )
{
unsigned long r , w ;
unsigned long r ;
u64 res , wrap ;
char r_unit ;
@ -129,19 +131,13 @@ void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
/* calculate how many ns until we wrap */
wrap = cyc_to_ns ( ( 1ULL < < bits ) - 1 , cd . mult , cd . shift ) ;
do_div ( wrap , NSEC_PER_MSEC ) ;
w = wrap ;
cd . wrap_kt = ns_to_ktime ( wrap - ( wrap > > 3 ) ) ;
/* calculate the ns resolution of this counter */
res = cyc_to_ns ( 1ULL , cd . mult , cd . shift ) ;
pr_info ( " sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lum s \n " ,
bits , r , r_unit , res , w ) ;
pr_info ( " sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %llun s \n " ,
bits , r , r_unit , res , wrap ) ;
/*
* Start the timer to keep sched_clock ( ) properly updated and
* sets the initial epoch .
*/
sched_clock_timer . data = msecs_to_jiffies ( w - ( w / 10 ) ) ;
update_sched_clock ( ) ;
/*
@ -172,12 +168,20 @@ void __init sched_clock_postinit(void)
if ( read_sched_clock = = jiffy_sched_clock_read )
setup_sched_clock ( jiffy_sched_clock_read , 32 , HZ ) ;
sched_clock_poll ( sched_clock_timer . data ) ;
update_sched_clock ( ) ;
/*
* Start the timer to keep sched_clock ( ) properly updated and
* sets the initial epoch .
*/
hrtimer_init ( & sched_clock_timer , CLOCK_MONOTONIC , HRTIMER_MODE_REL ) ;
sched_clock_timer . function = sched_clock_poll ;
hrtimer_start ( & sched_clock_timer , cd . wrap_kt , HRTIMER_MODE_REL ) ;
}
static int sched_clock_suspend ( void )
{
sched_clock_poll ( sched_clock_timer . data ) ;
sched_clock_poll ( & sched_clock_timer ) ;
cd . suspended = true ;
return 0 ;
}