Merge tag 'v4.0-rc2' into timers/core, to refresh the tree before pulling more changes
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
obj-y += time.o timer.o hrtimer.o itimer.o posix-timers.o posix-cpu-timers.o
|
||||
obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
|
||||
obj-y += timeconv.o posix-clock.o alarmtimer.o
|
||||
obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o
|
||||
|
||||
obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD) += clockevents.o
|
||||
obj-$(CONFIG_GENERIC_CLOCKEVENTS) += tick-common.o
|
||||
|
||||
@@ -788,7 +788,7 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
|
||||
goto out;
|
||||
}
|
||||
|
||||
restart = ¤t_thread_info()->restart_block;
|
||||
restart = ¤t->restart_block;
|
||||
restart->fn = alarm_timer_nsleep_restart;
|
||||
restart->nanosleep.clockid = type;
|
||||
restart->nanosleep.expires = exp.tv64;
|
||||
|
||||
@@ -34,82 +34,6 @@
|
||||
#include "tick-internal.h"
|
||||
#include "timekeeping_internal.h"
|
||||
|
||||
void timecounter_init(struct timecounter *tc,
|
||||
const struct cyclecounter *cc,
|
||||
u64 start_tstamp)
|
||||
{
|
||||
tc->cc = cc;
|
||||
tc->cycle_last = cc->read(cc);
|
||||
tc->nsec = start_tstamp;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timecounter_init);
|
||||
|
||||
/**
|
||||
* timecounter_read_delta - get nanoseconds since last call of this function
|
||||
* @tc: Pointer to time counter
|
||||
*
|
||||
* When the underlying cycle counter runs over, this will be handled
|
||||
* correctly as long as it does not run over more than once between
|
||||
* calls.
|
||||
*
|
||||
* The first call to this function for a new time counter initializes
|
||||
* the time tracking and returns an undefined result.
|
||||
*/
|
||||
static u64 timecounter_read_delta(struct timecounter *tc)
|
||||
{
|
||||
cycle_t cycle_now, cycle_delta;
|
||||
u64 ns_offset;
|
||||
|
||||
/* read cycle counter: */
|
||||
cycle_now = tc->cc->read(tc->cc);
|
||||
|
||||
/* calculate the delta since the last timecounter_read_delta(): */
|
||||
cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask;
|
||||
|
||||
/* convert to nanoseconds: */
|
||||
ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta);
|
||||
|
||||
/* update time stamp of timecounter_read_delta() call: */
|
||||
tc->cycle_last = cycle_now;
|
||||
|
||||
return ns_offset;
|
||||
}
|
||||
|
||||
u64 timecounter_read(struct timecounter *tc)
|
||||
{
|
||||
u64 nsec;
|
||||
|
||||
/* increment time by nanoseconds since last call */
|
||||
nsec = timecounter_read_delta(tc);
|
||||
nsec += tc->nsec;
|
||||
tc->nsec = nsec;
|
||||
|
||||
return nsec;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timecounter_read);
|
||||
|
||||
u64 timecounter_cyc2time(struct timecounter *tc,
|
||||
cycle_t cycle_tstamp)
|
||||
{
|
||||
u64 cycle_delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
|
||||
u64 nsec;
|
||||
|
||||
/*
|
||||
* Instead of always treating cycle_tstamp as more recent
|
||||
* than tc->cycle_last, detect when it is too far in the
|
||||
* future and treat it as old time stamp instead.
|
||||
*/
|
||||
if (cycle_delta > tc->cc->mask / 2) {
|
||||
cycle_delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
|
||||
nsec = tc->nsec - cyclecounter_cyc2ns(tc->cc, cycle_delta);
|
||||
} else {
|
||||
nsec = cyclecounter_cyc2ns(tc->cc, cycle_delta) + tc->nsec;
|
||||
}
|
||||
|
||||
return nsec;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timecounter_cyc2time);
|
||||
|
||||
/**
|
||||
* clocks_calc_mult_shift - calculate mult/shift factors for scaled math of clocks
|
||||
* @mult: pointer to mult variable
|
||||
|
||||
@@ -122,7 +122,7 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
|
||||
mono = ktime_get_update_offsets_tick(&off_real, &off_boot, &off_tai);
|
||||
boot = ktime_add(mono, off_boot);
|
||||
xtim = ktime_add(mono, off_real);
|
||||
tai = ktime_add(xtim, off_tai);
|
||||
tai = ktime_add(mono, off_tai);
|
||||
|
||||
base->clock_base[HRTIMER_BASE_REALTIME].softirq_time = xtim;
|
||||
base->clock_base[HRTIMER_BASE_MONOTONIC].softirq_time = mono;
|
||||
@@ -1583,7 +1583,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
|
||||
goto out;
|
||||
}
|
||||
|
||||
restart = ¤t_thread_info()->restart_block;
|
||||
restart = ¤t->restart_block;
|
||||
restart->fn = hrtimer_nanosleep_restart;
|
||||
restart->nanosleep.clockid = t.timer.base->clockid;
|
||||
restart->nanosleep.rmtp = rmtp;
|
||||
|
||||
@@ -633,6 +633,17 @@ int ntp_validate_timex(struct timex *txc)
|
||||
if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME)))
|
||||
return -EPERM;
|
||||
|
||||
/*
|
||||
* Check for potential multiplication overflows that can
|
||||
* only happen on 64-bit systems:
|
||||
*/
|
||||
if ((txc->modes & ADJ_FREQUENCY) && (BITS_PER_LONG == 64)) {
|
||||
if (LLONG_MIN / PPM_SCALE > txc->freq)
|
||||
return -EINVAL;
|
||||
if (LLONG_MAX / PPM_SCALE < txc->freq)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1334,8 +1334,7 @@ static long posix_cpu_nsleep_restart(struct restart_block *restart_block);
|
||||
static int posix_cpu_nsleep(const clockid_t which_clock, int flags,
|
||||
struct timespec *rqtp, struct timespec __user *rmtp)
|
||||
{
|
||||
struct restart_block *restart_block =
|
||||
¤t_thread_info()->restart_block;
|
||||
struct restart_block *restart_block = ¤t->restart_block;
|
||||
struct itimerspec it;
|
||||
int error;
|
||||
|
||||
|
||||
@@ -394,6 +394,56 @@ void tick_resume(void)
|
||||
}
|
||||
}
|
||||
|
||||
static DEFINE_RAW_SPINLOCK(tick_freeze_lock);
|
||||
static unsigned int tick_freeze_depth;
|
||||
|
||||
/**
|
||||
* tick_freeze - Suspend the local tick and (possibly) timekeeping.
|
||||
*
|
||||
* Check if this is the last online CPU executing the function and if so,
|
||||
* suspend timekeeping. Otherwise suspend the local tick.
|
||||
*
|
||||
* Call with interrupts disabled. Must be balanced with %tick_unfreeze().
|
||||
* Interrupts must not be enabled before the subsequent %tick_unfreeze().
|
||||
*/
|
||||
void tick_freeze(void)
|
||||
{
|
||||
raw_spin_lock(&tick_freeze_lock);
|
||||
|
||||
tick_freeze_depth++;
|
||||
if (tick_freeze_depth == num_online_cpus()) {
|
||||
timekeeping_suspend();
|
||||
} else {
|
||||
tick_suspend();
|
||||
tick_suspend_broadcast();
|
||||
}
|
||||
|
||||
raw_spin_unlock(&tick_freeze_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* tick_unfreeze - Resume the local tick and (possibly) timekeeping.
|
||||
*
|
||||
* Check if this is the first CPU executing the function and if so, resume
|
||||
* timekeeping. Otherwise resume the local tick.
|
||||
*
|
||||
* Call with interrupts disabled. Must be balanced with %tick_freeze().
|
||||
* Interrupts must not be enabled after the preceding %tick_freeze().
|
||||
*/
|
||||
void tick_unfreeze(void)
|
||||
{
|
||||
raw_spin_lock(&tick_freeze_lock);
|
||||
|
||||
if (tick_freeze_depth == num_online_cpus())
|
||||
timekeeping_resume();
|
||||
else
|
||||
tick_resume();
|
||||
|
||||
tick_freeze_depth--;
|
||||
|
||||
raw_spin_unlock(&tick_freeze_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* tick_init - initialize the tick control
|
||||
*/
|
||||
|
||||
@@ -326,13 +326,6 @@ static int tick_nohz_cpu_down_callback(struct notifier_block *nfb,
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Worst case string length in chunks of CPU range seems 2 steps
|
||||
* separations: 0,2,4,6,...
|
||||
* This is NR_CPUS + sizeof('\0')
|
||||
*/
|
||||
static char __initdata nohz_full_buf[NR_CPUS + 1];
|
||||
|
||||
static int tick_nohz_init_all(void)
|
||||
{
|
||||
int err = -1;
|
||||
@@ -393,8 +386,8 @@ void __init tick_nohz_init(void)
|
||||
context_tracking_cpu_set(cpu);
|
||||
|
||||
cpu_notifier(tick_nohz_cpu_down_callback, 0);
|
||||
cpulist_scnprintf(nohz_full_buf, sizeof(nohz_full_buf), tick_nohz_full_mask);
|
||||
pr_info("NO_HZ: Full dynticks CPUs: %s.\n", nohz_full_buf);
|
||||
pr_info("NO_HZ: Full dynticks CPUs: %*pbl.\n",
|
||||
cpumask_pr_args(tick_nohz_full_mask));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -196,6 +196,10 @@ SYSCALL_DEFINE2(settimeofday, struct timeval __user *, tv,
|
||||
if (tv) {
|
||||
if (copy_from_user(&user_tv, tv, sizeof(*tv)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!timeval_valid(&user_tv))
|
||||
return -EINVAL;
|
||||
|
||||
new_ts.tv_sec = user_tv.tv_sec;
|
||||
new_ts.tv_nsec = user_tv.tv_usec * NSEC_PER_USEC;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* linux/kernel/time/timecounter.c
|
||||
*
|
||||
* based on code that migrated away from
|
||||
* linux/kernel/time/clocksource.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/timecounter.h>
|
||||
|
||||
void timecounter_init(struct timecounter *tc,
|
||||
const struct cyclecounter *cc,
|
||||
u64 start_tstamp)
|
||||
{
|
||||
tc->cc = cc;
|
||||
tc->cycle_last = cc->read(cc);
|
||||
tc->nsec = start_tstamp;
|
||||
tc->mask = (1ULL << cc->shift) - 1;
|
||||
tc->frac = 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timecounter_init);
|
||||
|
||||
/**
|
||||
* timecounter_read_delta - get nanoseconds since last call of this function
|
||||
* @tc: Pointer to time counter
|
||||
*
|
||||
* When the underlying cycle counter runs over, this will be handled
|
||||
* correctly as long as it does not run over more than once between
|
||||
* calls.
|
||||
*
|
||||
* The first call to this function for a new time counter initializes
|
||||
* the time tracking and returns an undefined result.
|
||||
*/
|
||||
static u64 timecounter_read_delta(struct timecounter *tc)
|
||||
{
|
||||
cycle_t cycle_now, cycle_delta;
|
||||
u64 ns_offset;
|
||||
|
||||
/* read cycle counter: */
|
||||
cycle_now = tc->cc->read(tc->cc);
|
||||
|
||||
/* calculate the delta since the last timecounter_read_delta(): */
|
||||
cycle_delta = (cycle_now - tc->cycle_last) & tc->cc->mask;
|
||||
|
||||
/* convert to nanoseconds: */
|
||||
ns_offset = cyclecounter_cyc2ns(tc->cc, cycle_delta,
|
||||
tc->mask, &tc->frac);
|
||||
|
||||
/* update time stamp of timecounter_read_delta() call: */
|
||||
tc->cycle_last = cycle_now;
|
||||
|
||||
return ns_offset;
|
||||
}
|
||||
|
||||
u64 timecounter_read(struct timecounter *tc)
|
||||
{
|
||||
u64 nsec;
|
||||
|
||||
/* increment time by nanoseconds since last call */
|
||||
nsec = timecounter_read_delta(tc);
|
||||
nsec += tc->nsec;
|
||||
tc->nsec = nsec;
|
||||
|
||||
return nsec;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timecounter_read);
|
||||
|
||||
/*
|
||||
* This is like cyclecounter_cyc2ns(), but it is used for computing a
|
||||
* time previous to the time stored in the cycle counter.
|
||||
*/
|
||||
static u64 cc_cyc2ns_backwards(const struct cyclecounter *cc,
|
||||
cycle_t cycles, u64 mask, u64 frac)
|
||||
{
|
||||
u64 ns = (u64) cycles;
|
||||
|
||||
ns = ((ns * cc->mult) - frac) >> cc->shift;
|
||||
|
||||
return ns;
|
||||
}
|
||||
|
||||
u64 timecounter_cyc2time(struct timecounter *tc,
|
||||
cycle_t cycle_tstamp)
|
||||
{
|
||||
u64 delta = (cycle_tstamp - tc->cycle_last) & tc->cc->mask;
|
||||
u64 nsec = tc->nsec, frac = tc->frac;
|
||||
|
||||
/*
|
||||
* Instead of always treating cycle_tstamp as more recent
|
||||
* than tc->cycle_last, detect when it is too far in the
|
||||
* future and treat it as old time stamp instead.
|
||||
*/
|
||||
if (delta > tc->cc->mask / 2) {
|
||||
delta = (tc->cycle_last - cycle_tstamp) & tc->cc->mask;
|
||||
nsec -= cc_cyc2ns_backwards(tc->cc, delta, tc->mask, frac);
|
||||
} else {
|
||||
nsec += cyclecounter_cyc2ns(tc->cc, delta, tc->mask, &frac);
|
||||
}
|
||||
|
||||
return nsec;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timecounter_cyc2time);
|
||||
+38
-10
@@ -230,9 +230,7 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
|
||||
|
||||
/**
|
||||
* update_fast_timekeeper - Update the fast and NMI safe monotonic timekeeper.
|
||||
* @tk: The timekeeper from which we take the update
|
||||
* @tkf: The fast timekeeper to update
|
||||
* @tbase: The time base for the fast timekeeper (mono/raw)
|
||||
* @tkr: Timekeeping readout base from which we take the update
|
||||
*
|
||||
* We want to use this from any context including NMI and tracing /
|
||||
* instrumenting the timekeeping code itself.
|
||||
@@ -244,11 +242,11 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
|
||||
* smp_wmb(); <- Ensure that the last base[1] update is visible
|
||||
* tkf->seq++;
|
||||
* smp_wmb(); <- Ensure that the seqcount update is visible
|
||||
* update(tkf->base[0], tk);
|
||||
* update(tkf->base[0], tkr);
|
||||
* smp_wmb(); <- Ensure that the base[0] update is visible
|
||||
* tkf->seq++;
|
||||
* smp_wmb(); <- Ensure that the seqcount update is visible
|
||||
* update(tkf->base[1], tk);
|
||||
* update(tkf->base[1], tkr);
|
||||
*
|
||||
* The reader side does:
|
||||
*
|
||||
@@ -269,7 +267,7 @@ static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
|
||||
* slightly wrong timestamp (a few nanoseconds). See
|
||||
* @ktime_get_mono_fast_ns.
|
||||
*/
|
||||
static void update_fast_timekeeper(struct timekeeper *tk)
|
||||
static void update_fast_timekeeper(struct tk_read_base *tkr)
|
||||
{
|
||||
struct tk_read_base *base = tk_fast_mono.base;
|
||||
|
||||
@@ -277,7 +275,7 @@ static void update_fast_timekeeper(struct timekeeper *tk)
|
||||
raw_write_seqcount_latch(&tk_fast_mono.seq);
|
||||
|
||||
/* Update base[0] */
|
||||
memcpy(base, &tk->tkr, sizeof(*base));
|
||||
memcpy(base, tkr, sizeof(*base));
|
||||
|
||||
/* Force readers back to base[0] */
|
||||
raw_write_seqcount_latch(&tk_fast_mono.seq);
|
||||
@@ -334,6 +332,35 @@ u64 notrace ktime_get_mono_fast_ns(void)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ktime_get_mono_fast_ns);
|
||||
|
||||
/* Suspend-time cycles value for halted fast timekeeper. */
|
||||
static cycle_t cycles_at_suspend;
|
||||
|
||||
static cycle_t dummy_clock_read(struct clocksource *cs)
|
||||
{
|
||||
return cycles_at_suspend;
|
||||
}
|
||||
|
||||
/**
|
||||
* halt_fast_timekeeper - Prevent fast timekeeper from accessing clocksource.
|
||||
* @tk: Timekeeper to snapshot.
|
||||
*
|
||||
* It generally is unsafe to access the clocksource after timekeeping has been
|
||||
* suspended, so take a snapshot of the readout base of @tk and use it as the
|
||||
* fast timekeeper's readout base while suspended. It will return the same
|
||||
* number of cycles every time until timekeeping is resumed at which time the
|
||||
* proper readout base for the fast timekeeper will be restored automatically.
|
||||
*/
|
||||
static void halt_fast_timekeeper(struct timekeeper *tk)
|
||||
{
|
||||
static struct tk_read_base tkr_dummy;
|
||||
struct tk_read_base *tkr = &tk->tkr;
|
||||
|
||||
memcpy(&tkr_dummy, tkr, sizeof(tkr_dummy));
|
||||
cycles_at_suspend = tkr->read(tkr->clock);
|
||||
tkr_dummy.read = dummy_clock_read;
|
||||
update_fast_timekeeper(&tkr_dummy);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GENERIC_TIME_VSYSCALL_OLD
|
||||
|
||||
static inline void update_vsyscall(struct timekeeper *tk)
|
||||
@@ -462,7 +489,7 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
|
||||
memcpy(&shadow_timekeeper, &tk_core.timekeeper,
|
||||
sizeof(tk_core.timekeeper));
|
||||
|
||||
update_fast_timekeeper(tk);
|
||||
update_fast_timekeeper(&tk->tkr);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1170,7 +1197,7 @@ void timekeeping_inject_sleeptime64(struct timespec64 *delta)
|
||||
* xtime/wall_to_monotonic/jiffies/etc are
|
||||
* still managed by arch specific suspend/resume code.
|
||||
*/
|
||||
static void timekeeping_resume(void)
|
||||
void timekeeping_resume(void)
|
||||
{
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
struct clocksource *clock = tk->tkr.clock;
|
||||
@@ -1251,7 +1278,7 @@ static void timekeeping_resume(void)
|
||||
hrtimers_resume();
|
||||
}
|
||||
|
||||
static int timekeeping_suspend(void)
|
||||
int timekeeping_suspend(void)
|
||||
{
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
unsigned long flags;
|
||||
@@ -1296,6 +1323,7 @@ static int timekeeping_suspend(void)
|
||||
}
|
||||
|
||||
timekeeping_update(tk, TK_MIRROR);
|
||||
halt_fast_timekeeper(tk);
|
||||
write_seqcount_end(&tk_core.seq);
|
||||
raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
|
||||
|
||||
|
||||
@@ -16,5 +16,7 @@ extern int timekeeping_inject_offset(struct timespec *ts);
|
||||
extern s32 timekeeping_get_tai_offset(void);
|
||||
extern void timekeeping_set_tai_offset(s32 tai_offset);
|
||||
extern void timekeeping_clocktai(struct timespec *ts);
|
||||
extern int timekeeping_suspend(void);
|
||||
extern void timekeeping_resume(void);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user