[IA64] remove time interpolator
Remove time_interpolator code (This is generic code, but only user was ia64. It has been superseded by the CONFIG_GENERIC_TIME code). Signed-off-by: Bob Picco <bob.picco@hp.com> Signed-off-by: John Stultz <johnstul@us.ibm.com> Signed-off-by: Peter Keilty <peter.keilty@hp.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
This commit is contained in:
parent
0aa366f351
commit
1f564ad6d4
6 changed files with 0 additions and 391 deletions
|
@ -1,41 +0,0 @@
|
||||||
Time Interpolators
|
|
||||||
------------------
|
|
||||||
|
|
||||||
Time interpolators are a base of time calculation between timer ticks and
|
|
||||||
allow an accurate determination of time down to the accuracy of the time
|
|
||||||
source in nanoseconds.
|
|
||||||
|
|
||||||
The architecture specific code typically provides gettimeofday and
|
|
||||||
settimeofday under Linux. The time interpolator provides both if an arch
|
|
||||||
defines CONFIG_TIME_INTERPOLATION. The arch still must set up timer tick
|
|
||||||
operations and call the necessary functions to advance the clock.
|
|
||||||
|
|
||||||
With the time interpolator a standardized interface exists for time
|
|
||||||
interpolation between ticks. The provided logic is highly scalable
|
|
||||||
and has been tested in SMP situations of up to 512 CPUs.
|
|
||||||
|
|
||||||
If CONFIG_TIME_INTERPOLATION is defined then the architecture specific code
|
|
||||||
(or the device drivers - like HPET) may register time interpolators.
|
|
||||||
These are typically defined in the following way:
|
|
||||||
|
|
||||||
static struct time_interpolator my_interpolator {
|
|
||||||
.frequency = MY_FREQUENCY,
|
|
||||||
.source = TIME_SOURCE_MMIO32,
|
|
||||||
.shift = 8, /* scaling for higher accuracy */
|
|
||||||
.drift = -1, /* Unknown drift */
|
|
||||||
.jitter = 0 /* time source is stable */
|
|
||||||
};
|
|
||||||
|
|
||||||
void time_init(void)
|
|
||||||
{
|
|
||||||
....
|
|
||||||
/* Initialization of the timer *.
|
|
||||||
my_interpolator.address = &my_timer;
|
|
||||||
register_time_interpolator(&my_interpolator);
|
|
||||||
....
|
|
||||||
}
|
|
||||||
|
|
||||||
For more details see include/linux/timex.h and kernel/timer.c.
|
|
||||||
|
|
||||||
Christoph Lameter <christoph@lameter.com>, October 31, 2004
|
|
||||||
|
|
|
@ -224,66 +224,6 @@ static inline int ntp_synced(void)
|
||||||
__x < 0 ? -(-__x >> __s) : __x >> __s; \
|
__x < 0 ? -(-__x >> __s) : __x >> __s; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_TIME_INTERPOLATION
|
|
||||||
|
|
||||||
#define TIME_SOURCE_CPU 0
|
|
||||||
#define TIME_SOURCE_MMIO64 1
|
|
||||||
#define TIME_SOURCE_MMIO32 2
|
|
||||||
#define TIME_SOURCE_FUNCTION 3
|
|
||||||
|
|
||||||
/* For proper operations time_interpolator clocks must run slightly slower
|
|
||||||
* than the standard clock since the interpolator may only correct by having
|
|
||||||
* time jump forward during a tick. A slower clock is usually a side effect
|
|
||||||
* of the integer divide of the nanoseconds in a second by the frequency.
|
|
||||||
* The accuracy of the division can be increased by specifying a shift.
|
|
||||||
* However, this may cause the clock not to be slow enough.
|
|
||||||
* The interpolator will self-tune the clock by slowing down if no
|
|
||||||
* resets occur or speeding up if the time jumps per analysis cycle
|
|
||||||
* become too high.
|
|
||||||
*
|
|
||||||
* Setting jitter compensates for a fluctuating timesource by comparing
|
|
||||||
* to the last value read from the timesource to insure that an earlier value
|
|
||||||
* is not returned by a later call. The price to pay
|
|
||||||
* for the compensation is that the timer routines are not as scalable anymore.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct time_interpolator {
|
|
||||||
u16 source; /* time source flags */
|
|
||||||
u8 shift; /* increases accuracy of multiply by shifting. */
|
|
||||||
/* Note that bits may be lost if shift is set too high */
|
|
||||||
u8 jitter; /* if set compensate for fluctuations */
|
|
||||||
u32 nsec_per_cyc; /* set by register_time_interpolator() */
|
|
||||||
void *addr; /* address of counter or function */
|
|
||||||
cycles_t mask; /* mask the valid bits of the counter */
|
|
||||||
unsigned long offset; /* nsec offset at last update of interpolator */
|
|
||||||
u64 last_counter; /* counter value in units of the counter at last update */
|
|
||||||
cycles_t last_cycle; /* Last timer value if TIME_SOURCE_JITTER is set */
|
|
||||||
u64 frequency; /* frequency in counts/second */
|
|
||||||
long drift; /* drift in parts-per-million (or -1) */
|
|
||||||
unsigned long skips; /* skips forward */
|
|
||||||
unsigned long ns_skipped; /* nanoseconds skipped */
|
|
||||||
struct time_interpolator *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern void register_time_interpolator(struct time_interpolator *);
|
|
||||||
extern void unregister_time_interpolator(struct time_interpolator *);
|
|
||||||
extern void time_interpolator_reset(void);
|
|
||||||
extern unsigned long time_interpolator_get_offset(void);
|
|
||||||
extern void time_interpolator_update(long delta_nsec);
|
|
||||||
|
|
||||||
#else /* !CONFIG_TIME_INTERPOLATION */
|
|
||||||
|
|
||||||
static inline void time_interpolator_reset(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void time_interpolator_update(long delta_nsec)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* !CONFIG_TIME_INTERPOLATION */
|
|
||||||
|
|
||||||
#define TICK_LENGTH_SHIFT 32
|
#define TICK_LENGTH_SHIFT 32
|
||||||
|
|
||||||
#ifdef CONFIG_NO_HZ
|
#ifdef CONFIG_NO_HZ
|
||||||
|
|
|
@ -136,7 +136,6 @@ static inline void warp_clock(void)
|
||||||
write_seqlock_irq(&xtime_lock);
|
write_seqlock_irq(&xtime_lock);
|
||||||
wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60;
|
wall_to_monotonic.tv_sec -= sys_tz.tz_minuteswest * 60;
|
||||||
xtime.tv_sec += sys_tz.tz_minuteswest * 60;
|
xtime.tv_sec += sys_tz.tz_minuteswest * 60;
|
||||||
time_interpolator_reset();
|
|
||||||
write_sequnlock_irq(&xtime_lock);
|
write_sequnlock_irq(&xtime_lock);
|
||||||
clock_was_set();
|
clock_was_set();
|
||||||
}
|
}
|
||||||
|
@ -309,92 +308,6 @@ struct timespec timespec_trunc(struct timespec t, unsigned gran)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(timespec_trunc);
|
EXPORT_SYMBOL(timespec_trunc);
|
||||||
|
|
||||||
#ifdef CONFIG_TIME_INTERPOLATION
|
|
||||||
void getnstimeofday (struct timespec *tv)
|
|
||||||
{
|
|
||||||
unsigned long seq,sec,nsec;
|
|
||||||
|
|
||||||
do {
|
|
||||||
seq = read_seqbegin(&xtime_lock);
|
|
||||||
sec = xtime.tv_sec;
|
|
||||||
nsec = xtime.tv_nsec+time_interpolator_get_offset();
|
|
||||||
} while (unlikely(read_seqretry(&xtime_lock, seq)));
|
|
||||||
|
|
||||||
while (unlikely(nsec >= NSEC_PER_SEC)) {
|
|
||||||
nsec -= NSEC_PER_SEC;
|
|
||||||
++sec;
|
|
||||||
}
|
|
||||||
tv->tv_sec = sec;
|
|
||||||
tv->tv_nsec = nsec;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(getnstimeofday);
|
|
||||||
|
|
||||||
int do_settimeofday (struct timespec *tv)
|
|
||||||
{
|
|
||||||
time_t wtm_sec, sec = tv->tv_sec;
|
|
||||||
long wtm_nsec, nsec = tv->tv_nsec;
|
|
||||||
|
|
||||||
if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
write_seqlock_irq(&xtime_lock);
|
|
||||||
{
|
|
||||||
wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
|
|
||||||
wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
|
|
||||||
|
|
||||||
set_normalized_timespec(&xtime, sec, nsec);
|
|
||||||
set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
|
|
||||||
|
|
||||||
time_adjust = 0; /* stop active adjtime() */
|
|
||||||
time_status |= STA_UNSYNC;
|
|
||||||
time_maxerror = NTP_PHASE_LIMIT;
|
|
||||||
time_esterror = NTP_PHASE_LIMIT;
|
|
||||||
time_interpolator_reset();
|
|
||||||
}
|
|
||||||
write_sequnlock_irq(&xtime_lock);
|
|
||||||
clock_was_set();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(do_settimeofday);
|
|
||||||
|
|
||||||
void do_gettimeofday (struct timeval *tv)
|
|
||||||
{
|
|
||||||
unsigned long seq, nsec, usec, sec, offset;
|
|
||||||
do {
|
|
||||||
seq = read_seqbegin(&xtime_lock);
|
|
||||||
offset = time_interpolator_get_offset();
|
|
||||||
sec = xtime.tv_sec;
|
|
||||||
nsec = xtime.tv_nsec;
|
|
||||||
} while (unlikely(read_seqretry(&xtime_lock, seq)));
|
|
||||||
|
|
||||||
usec = (nsec + offset) / 1000;
|
|
||||||
|
|
||||||
while (unlikely(usec >= USEC_PER_SEC)) {
|
|
||||||
usec -= USEC_PER_SEC;
|
|
||||||
++sec;
|
|
||||||
}
|
|
||||||
|
|
||||||
tv->tv_sec = sec;
|
|
||||||
tv->tv_usec = usec;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure xtime.tv_sec [returned by sys_time()] always
|
|
||||||
* follows the gettimeofday() result precisely. This
|
|
||||||
* condition is extremely unlikely, it can hit at most
|
|
||||||
* once per second:
|
|
||||||
*/
|
|
||||||
if (unlikely(xtime.tv_sec != tv->tv_sec)) {
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
write_seqlock_irqsave(&xtime_lock, flags);
|
|
||||||
update_wall_time();
|
|
||||||
write_sequnlock_irqrestore(&xtime_lock, flags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(do_gettimeofday);
|
|
||||||
|
|
||||||
#else /* CONFIG_TIME_INTERPOLATION */
|
|
||||||
|
|
||||||
#ifndef CONFIG_GENERIC_TIME
|
#ifndef CONFIG_GENERIC_TIME
|
||||||
/*
|
/*
|
||||||
* Simulate gettimeofday using do_gettimeofday which only allows a timeval
|
* Simulate gettimeofday using do_gettimeofday which only allows a timeval
|
||||||
|
@ -410,7 +323,6 @@ void getnstimeofday(struct timespec *tv)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(getnstimeofday);
|
EXPORT_SYMBOL_GPL(getnstimeofday);
|
||||||
#endif
|
#endif
|
||||||
#endif /* CONFIG_TIME_INTERPOLATION */
|
|
||||||
|
|
||||||
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
|
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
|
||||||
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
|
* Assumes input in normal date format, i.e. 1980-12-31 23:59:59
|
||||||
|
|
|
@ -116,11 +116,6 @@ void second_overflow(void)
|
||||||
if (xtime.tv_sec % 86400 == 0) {
|
if (xtime.tv_sec % 86400 == 0) {
|
||||||
xtime.tv_sec--;
|
xtime.tv_sec--;
|
||||||
wall_to_monotonic.tv_sec++;
|
wall_to_monotonic.tv_sec++;
|
||||||
/*
|
|
||||||
* The timer interpolator will make time change
|
|
||||||
* gradually instead of an immediate jump by one second
|
|
||||||
*/
|
|
||||||
time_interpolator_update(-NSEC_PER_SEC);
|
|
||||||
time_state = TIME_OOP;
|
time_state = TIME_OOP;
|
||||||
printk(KERN_NOTICE "Clock: inserting leap second "
|
printk(KERN_NOTICE "Clock: inserting leap second "
|
||||||
"23:59:60 UTC\n");
|
"23:59:60 UTC\n");
|
||||||
|
@ -130,11 +125,6 @@ void second_overflow(void)
|
||||||
if ((xtime.tv_sec + 1) % 86400 == 0) {
|
if ((xtime.tv_sec + 1) % 86400 == 0) {
|
||||||
xtime.tv_sec++;
|
xtime.tv_sec++;
|
||||||
wall_to_monotonic.tv_sec--;
|
wall_to_monotonic.tv_sec--;
|
||||||
/*
|
|
||||||
* Use of time interpolator for a gradual change of
|
|
||||||
* time
|
|
||||||
*/
|
|
||||||
time_interpolator_update(NSEC_PER_SEC);
|
|
||||||
time_state = TIME_WAIT;
|
time_state = TIME_WAIT;
|
||||||
printk(KERN_NOTICE "Clock: deleting leap second "
|
printk(KERN_NOTICE "Clock: deleting leap second "
|
||||||
"23:59:59 UTC\n");
|
"23:59:59 UTC\n");
|
||||||
|
|
|
@ -466,10 +466,6 @@ void update_wall_time(void)
|
||||||
second_overflow();
|
second_overflow();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* interpolator bits */
|
|
||||||
time_interpolator_update(clock->xtime_interval
|
|
||||||
>> clock->shift);
|
|
||||||
|
|
||||||
/* accumulate error between NTP and clock interval */
|
/* accumulate error between NTP and clock interval */
|
||||||
clock->error += current_tick_length();
|
clock->error += current_tick_length();
|
||||||
clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
|
clock->error -= clock->xtime_interval << (TICK_LENGTH_SHIFT - clock->shift);
|
||||||
|
|
188
kernel/timer.c
188
kernel/timer.c
|
@ -1349,194 +1349,6 @@ void __init init_timers(void)
|
||||||
open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
|
open_softirq(TIMER_SOFTIRQ, run_timer_softirq, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TIME_INTERPOLATION
|
|
||||||
|
|
||||||
struct time_interpolator *time_interpolator __read_mostly;
|
|
||||||
static struct time_interpolator *time_interpolator_list __read_mostly;
|
|
||||||
static DEFINE_SPINLOCK(time_interpolator_lock);
|
|
||||||
|
|
||||||
static inline cycles_t time_interpolator_get_cycles(unsigned int src)
|
|
||||||
{
|
|
||||||
unsigned long (*x)(void);
|
|
||||||
|
|
||||||
switch (src)
|
|
||||||
{
|
|
||||||
case TIME_SOURCE_FUNCTION:
|
|
||||||
x = time_interpolator->addr;
|
|
||||||
return x();
|
|
||||||
|
|
||||||
case TIME_SOURCE_MMIO64 :
|
|
||||||
return readq_relaxed((void __iomem *)time_interpolator->addr);
|
|
||||||
|
|
||||||
case TIME_SOURCE_MMIO32 :
|
|
||||||
return readl_relaxed((void __iomem *)time_interpolator->addr);
|
|
||||||
|
|
||||||
default: return get_cycles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline u64 time_interpolator_get_counter(int writelock)
|
|
||||||
{
|
|
||||||
unsigned int src = time_interpolator->source;
|
|
||||||
|
|
||||||
if (time_interpolator->jitter)
|
|
||||||
{
|
|
||||||
cycles_t lcycle;
|
|
||||||
cycles_t now;
|
|
||||||
|
|
||||||
do {
|
|
||||||
lcycle = time_interpolator->last_cycle;
|
|
||||||
now = time_interpolator_get_cycles(src);
|
|
||||||
if (lcycle && time_after(lcycle, now))
|
|
||||||
return lcycle;
|
|
||||||
|
|
||||||
/* When holding the xtime write lock, there's no need
|
|
||||||
* to add the overhead of the cmpxchg. Readers are
|
|
||||||
* force to retry until the write lock is released.
|
|
||||||
*/
|
|
||||||
if (writelock) {
|
|
||||||
time_interpolator->last_cycle = now;
|
|
||||||
return now;
|
|
||||||
}
|
|
||||||
/* Keep track of the last timer value returned. The use of cmpxchg here
|
|
||||||
* will cause contention in an SMP environment.
|
|
||||||
*/
|
|
||||||
} while (unlikely(cmpxchg(&time_interpolator->last_cycle, lcycle, now) != lcycle));
|
|
||||||
return now;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return time_interpolator_get_cycles(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
void time_interpolator_reset(void)
|
|
||||||
{
|
|
||||||
time_interpolator->offset = 0;
|
|
||||||
time_interpolator->last_counter = time_interpolator_get_counter(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define GET_TI_NSECS(count,i) (((((count) - i->last_counter) & (i)->mask) * (i)->nsec_per_cyc) >> (i)->shift)
|
|
||||||
|
|
||||||
unsigned long time_interpolator_get_offset(void)
|
|
||||||
{
|
|
||||||
/* If we do not have a time interpolator set up then just return zero */
|
|
||||||
if (!time_interpolator)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return time_interpolator->offset +
|
|
||||||
GET_TI_NSECS(time_interpolator_get_counter(0), time_interpolator);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define INTERPOLATOR_ADJUST 65536
|
|
||||||
#define INTERPOLATOR_MAX_SKIP 10*INTERPOLATOR_ADJUST
|
|
||||||
|
|
||||||
void time_interpolator_update(long delta_nsec)
|
|
||||||
{
|
|
||||||
u64 counter;
|
|
||||||
unsigned long offset;
|
|
||||||
|
|
||||||
/* If there is no time interpolator set up then do nothing */
|
|
||||||
if (!time_interpolator)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The interpolator compensates for late ticks by accumulating the late
|
|
||||||
* time in time_interpolator->offset. A tick earlier than expected will
|
|
||||||
* lead to a reset of the offset and a corresponding jump of the clock
|
|
||||||
* forward. Again this only works if the interpolator clock is running
|
|
||||||
* slightly slower than the regular clock and the tuning logic insures
|
|
||||||
* that.
|
|
||||||
*/
|
|
||||||
|
|
||||||
counter = time_interpolator_get_counter(1);
|
|
||||||
offset = time_interpolator->offset +
|
|
||||||
GET_TI_NSECS(counter, time_interpolator);
|
|
||||||
|
|
||||||
if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
|
|
||||||
time_interpolator->offset = offset - delta_nsec;
|
|
||||||
else {
|
|
||||||
time_interpolator->skips++;
|
|
||||||
time_interpolator->ns_skipped += delta_nsec - offset;
|
|
||||||
time_interpolator->offset = 0;
|
|
||||||
}
|
|
||||||
time_interpolator->last_counter = counter;
|
|
||||||
|
|
||||||
/* Tuning logic for time interpolator invoked every minute or so.
|
|
||||||
* Decrease interpolator clock speed if no skips occurred and an offset is carried.
|
|
||||||
* Increase interpolator clock speed if we skip too much time.
|
|
||||||
*/
|
|
||||||
if (jiffies % INTERPOLATOR_ADJUST == 0)
|
|
||||||
{
|
|
||||||
if (time_interpolator->skips == 0 && time_interpolator->offset > tick_nsec)
|
|
||||||
time_interpolator->nsec_per_cyc--;
|
|
||||||
if (time_interpolator->ns_skipped > INTERPOLATOR_MAX_SKIP && time_interpolator->offset == 0)
|
|
||||||
time_interpolator->nsec_per_cyc++;
|
|
||||||
time_interpolator->skips = 0;
|
|
||||||
time_interpolator->ns_skipped = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int
|
|
||||||
is_better_time_interpolator(struct time_interpolator *new)
|
|
||||||
{
|
|
||||||
if (!time_interpolator)
|
|
||||||
return 1;
|
|
||||||
return new->frequency > 2*time_interpolator->frequency ||
|
|
||||||
(unsigned long)new->drift < (unsigned long)time_interpolator->drift;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
register_time_interpolator(struct time_interpolator *ti)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
/* Sanity check */
|
|
||||||
BUG_ON(ti->frequency == 0 || ti->mask == 0);
|
|
||||||
|
|
||||||
ti->nsec_per_cyc = ((u64)NSEC_PER_SEC << ti->shift) / ti->frequency;
|
|
||||||
spin_lock(&time_interpolator_lock);
|
|
||||||
write_seqlock_irqsave(&xtime_lock, flags);
|
|
||||||
if (is_better_time_interpolator(ti)) {
|
|
||||||
time_interpolator = ti;
|
|
||||||
time_interpolator_reset();
|
|
||||||
}
|
|
||||||
write_sequnlock_irqrestore(&xtime_lock, flags);
|
|
||||||
|
|
||||||
ti->next = time_interpolator_list;
|
|
||||||
time_interpolator_list = ti;
|
|
||||||
spin_unlock(&time_interpolator_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
unregister_time_interpolator(struct time_interpolator *ti)
|
|
||||||
{
|
|
||||||
struct time_interpolator *curr, **prev;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock(&time_interpolator_lock);
|
|
||||||
prev = &time_interpolator_list;
|
|
||||||
for (curr = *prev; curr; curr = curr->next) {
|
|
||||||
if (curr == ti) {
|
|
||||||
*prev = curr->next;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prev = &curr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_seqlock_irqsave(&xtime_lock, flags);
|
|
||||||
if (ti == time_interpolator) {
|
|
||||||
/* we lost the best time-interpolator: */
|
|
||||||
time_interpolator = NULL;
|
|
||||||
/* find the next-best interpolator */
|
|
||||||
for (curr = time_interpolator_list; curr; curr = curr->next)
|
|
||||||
if (is_better_time_interpolator(curr))
|
|
||||||
time_interpolator = curr;
|
|
||||||
time_interpolator_reset();
|
|
||||||
}
|
|
||||||
write_sequnlock_irqrestore(&xtime_lock, flags);
|
|
||||||
spin_unlock(&time_interpolator_lock);
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_TIME_INTERPOLATION */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* msleep - sleep safely even with waitqueue interruptions
|
* msleep - sleep safely even with waitqueue interruptions
|
||||||
* @msecs: Time in milliseconds to sleep for
|
* @msecs: Time in milliseconds to sleep for
|
||||||
|
|
Loading…
Reference in a new issue