Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull timer updates from Thomas Gleixner: "The timer departement provides: - More y2038 work in the area of ntp and pps. - Optimization of posix cpu timers - New time related selftests - Some new clocksource drivers - The usual pile of fixes, cleanups and improvements" * 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (25 commits) timeconst: Update path in comment timers/x86/hpet: Type adjustments clocksource/drivers/armada-370-xp: Implement ARM delay timer clocksource/drivers/tango_xtal: Add new timer for Tango SoCs clocksource/drivers/imx: Allow timer irq affinity change clocksource/drivers/exynos_mct: Use container_of() instead of this_cpu_ptr() clocksource/drivers/h8300_*: Remove unneeded memset()s clocksource/drivers/sh_cmt: Remove unneeded memset() in sh_cmt_setup() clocksource/drivers/em_sti: Remove unneeded memset()s clocksource/drivers/mediatek: Use GPT as sched clock source clockevents/drivers/mtk: Fix spurious interrupt leading to crash posix_cpu_timer: Reduce unnecessary sighand lock contention posix_cpu_timer: Convert cputimer->running to bool posix_cpu_timer: Check thread timers only when there are active thread timers posix_cpu_timer: Optimize fastpath_timer_check() timers, kselftest: Add 'adjtick' test to validate adjtimex() tick adjustments timers: Use __fls in apply_slack() clocksource: Remove return statement from void functions net: sfc: avoid using timespec ntp/pps: use y2038 safe types in pps_event_time ...
This commit is contained in:
@@ -479,7 +479,7 @@ static u32 clocksource_max_adjustment(struct clocksource *cs)
|
||||
* return half the number of nanoseconds the hardware counter can technically
|
||||
* cover. This is done so that we can potentially detect problems caused by
|
||||
* delayed timers or bad hardware, which might result in time intervals that
|
||||
* are larger then what the math used can handle without overflows.
|
||||
* are larger than what the math used can handle without overflows.
|
||||
*/
|
||||
u64 clocks_calc_max_nsecs(u32 mult, u32 shift, u32 maxadj, u64 mask, u64 *max_cyc)
|
||||
{
|
||||
@@ -595,16 +595,15 @@ static void __clocksource_select(bool skipcur)
|
||||
*/
|
||||
static void clocksource_select(void)
|
||||
{
|
||||
return __clocksource_select(false);
|
||||
__clocksource_select(false);
|
||||
}
|
||||
|
||||
static void clocksource_select_fallback(void)
|
||||
{
|
||||
return __clocksource_select(true);
|
||||
__clocksource_select(true);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_ARCH_USES_GETTIMEOFFSET */
|
||||
|
||||
static inline void clocksource_select(void) { }
|
||||
static inline void clocksource_select_fallback(void) { }
|
||||
|
||||
|
@@ -59,7 +59,7 @@
|
||||
/*
|
||||
* The timer bases:
|
||||
*
|
||||
* There are more clockids then hrtimer bases. Thus, we index
|
||||
* There are more clockids than hrtimer bases. Thus, we index
|
||||
* into the timer bases by the hrtimer_base_type enum. When trying
|
||||
* to reach a base using a clockid, hrtimer_clockid_to_base()
|
||||
* is used to convert from clockid to the proper hrtimer_base_type.
|
||||
|
@@ -99,7 +99,7 @@ static time64_t ntp_next_leap_sec = TIME64_MAX;
|
||||
static int pps_valid; /* signal watchdog counter */
|
||||
static long pps_tf[3]; /* phase median filter */
|
||||
static long pps_jitter; /* current jitter (ns) */
|
||||
static struct timespec pps_fbase; /* beginning of the last freq interval */
|
||||
static struct timespec64 pps_fbase; /* beginning of the last freq interval */
|
||||
static int pps_shift; /* current interval duration (s) (shift) */
|
||||
static int pps_intcnt; /* interval counter */
|
||||
static s64 pps_freq; /* frequency offset (scaled ns/s) */
|
||||
@@ -509,7 +509,7 @@ static DECLARE_DELAYED_WORK(sync_cmos_work, sync_cmos_clock);
|
||||
static void sync_cmos_clock(struct work_struct *work)
|
||||
{
|
||||
struct timespec64 now;
|
||||
struct timespec next;
|
||||
struct timespec64 next;
|
||||
int fail = 1;
|
||||
|
||||
/*
|
||||
@@ -559,7 +559,7 @@ static void sync_cmos_clock(struct work_struct *work)
|
||||
next.tv_nsec -= NSEC_PER_SEC;
|
||||
}
|
||||
queue_delayed_work(system_power_efficient_wq,
|
||||
&sync_cmos_work, timespec_to_jiffies(&next));
|
||||
&sync_cmos_work, timespec64_to_jiffies(&next));
|
||||
}
|
||||
|
||||
void ntp_notify_cmos_timer(void)
|
||||
@@ -773,13 +773,13 @@ int __do_adjtimex(struct timex *txc, struct timespec64 *ts, s32 *time_tai)
|
||||
* pps_normtime.nsec has a range of ( -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ]
|
||||
* while timespec.tv_nsec has a range of [0, NSEC_PER_SEC) */
|
||||
struct pps_normtime {
|
||||
__kernel_time_t sec; /* seconds */
|
||||
s64 sec; /* seconds */
|
||||
long nsec; /* nanoseconds */
|
||||
};
|
||||
|
||||
/* normalize the timestamp so that nsec is in the
|
||||
( -NSEC_PER_SEC / 2, NSEC_PER_SEC / 2 ] interval */
|
||||
static inline struct pps_normtime pps_normalize_ts(struct timespec ts)
|
||||
static inline struct pps_normtime pps_normalize_ts(struct timespec64 ts)
|
||||
{
|
||||
struct pps_normtime norm = {
|
||||
.sec = ts.tv_sec,
|
||||
@@ -861,7 +861,7 @@ static long hardpps_update_freq(struct pps_normtime freq_norm)
|
||||
pps_errcnt++;
|
||||
pps_dec_freq_interval();
|
||||
printk_deferred(KERN_ERR
|
||||
"hardpps: PPSERROR: interval too long - %ld s\n",
|
||||
"hardpps: PPSERROR: interval too long - %lld s\n",
|
||||
freq_norm.sec);
|
||||
return 0;
|
||||
}
|
||||
@@ -948,7 +948,7 @@ static void hardpps_update_phase(long error)
|
||||
* This code is based on David Mills's reference nanokernel
|
||||
* implementation. It was mostly rewritten but keeps the same idea.
|
||||
*/
|
||||
void __hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
|
||||
void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
|
||||
{
|
||||
struct pps_normtime pts_norm, freq_norm;
|
||||
|
||||
@@ -969,7 +969,7 @@ void __hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
|
||||
}
|
||||
|
||||
/* ok, now we have a base for frequency calculation */
|
||||
freq_norm = pps_normalize_ts(timespec_sub(*raw_ts, pps_fbase));
|
||||
freq_norm = pps_normalize_ts(timespec64_sub(*raw_ts, pps_fbase));
|
||||
|
||||
/* check that the signal is in the range
|
||||
* [1s - MAXFREQ us, 1s + MAXFREQ us], otherwise reject it */
|
||||
|
@@ -9,5 +9,5 @@ extern ktime_t ntp_get_next_leap(void);
|
||||
extern int second_overflow(unsigned long secs);
|
||||
extern int ntp_validate_timex(struct timex *);
|
||||
extern int __do_adjtimex(struct timex *, struct timespec64 *, s32 *);
|
||||
extern void __hardpps(const struct timespec *, const struct timespec *);
|
||||
extern void __hardpps(const struct timespec64 *, const struct timespec64 *);
|
||||
#endif /* _LINUX_NTP_INTERNAL_H */
|
||||
|
@@ -249,7 +249,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
|
||||
* but barriers are not required because update_gt_cputime()
|
||||
* can handle concurrent updates.
|
||||
*/
|
||||
WRITE_ONCE(cputimer->running, 1);
|
||||
WRITE_ONCE(cputimer->running, true);
|
||||
}
|
||||
sample_cputime_atomic(times, &cputimer->cputime_atomic);
|
||||
}
|
||||
@@ -864,6 +864,13 @@ static void check_thread_timers(struct task_struct *tsk,
|
||||
unsigned long long expires;
|
||||
unsigned long soft;
|
||||
|
||||
/*
|
||||
* If cputime_expires is zero, then there are no active
|
||||
* per thread CPU timers.
|
||||
*/
|
||||
if (task_cputime_zero(&tsk->cputime_expires))
|
||||
return;
|
||||
|
||||
expires = check_timers_list(timers, firing, prof_ticks(tsk));
|
||||
tsk_expires->prof_exp = expires_to_cputime(expires);
|
||||
|
||||
@@ -911,7 +918,7 @@ static inline void stop_process_timers(struct signal_struct *sig)
|
||||
struct thread_group_cputimer *cputimer = &sig->cputimer;
|
||||
|
||||
/* Turn off cputimer->running. This is done without locking. */
|
||||
WRITE_ONCE(cputimer->running, 0);
|
||||
WRITE_ONCE(cputimer->running, false);
|
||||
}
|
||||
|
||||
static u32 onecputick;
|
||||
@@ -961,6 +968,19 @@ static void check_process_timers(struct task_struct *tsk,
|
||||
struct task_cputime cputime;
|
||||
unsigned long soft;
|
||||
|
||||
/*
|
||||
* If cputimer is not running, then there are no active
|
||||
* process wide timers (POSIX 1.b, itimers, RLIMIT_CPU).
|
||||
*/
|
||||
if (!READ_ONCE(tsk->signal->cputimer.running))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Signify that a thread is checking for process timers.
|
||||
* Write access to this field is protected by the sighand lock.
|
||||
*/
|
||||
sig->cputimer.checking_timer = true;
|
||||
|
||||
/*
|
||||
* Collect the current process totals.
|
||||
*/
|
||||
@@ -1015,6 +1035,8 @@ static void check_process_timers(struct task_struct *tsk,
|
||||
sig->cputime_expires.sched_exp = sched_expires;
|
||||
if (task_cputime_zero(&sig->cputime_expires))
|
||||
stop_process_timers(sig);
|
||||
|
||||
sig->cputimer.checking_timer = false;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1117,24 +1139,33 @@ static inline int task_cputime_expired(const struct task_cputime *sample,
|
||||
static inline int fastpath_timer_check(struct task_struct *tsk)
|
||||
{
|
||||
struct signal_struct *sig;
|
||||
cputime_t utime, stime;
|
||||
|
||||
task_cputime(tsk, &utime, &stime);
|
||||
|
||||
if (!task_cputime_zero(&tsk->cputime_expires)) {
|
||||
struct task_cputime task_sample = {
|
||||
.utime = utime,
|
||||
.stime = stime,
|
||||
.sum_exec_runtime = tsk->se.sum_exec_runtime
|
||||
};
|
||||
struct task_cputime task_sample;
|
||||
|
||||
task_cputime(tsk, &task_sample.utime, &task_sample.stime);
|
||||
task_sample.sum_exec_runtime = tsk->se.sum_exec_runtime;
|
||||
if (task_cputime_expired(&task_sample, &tsk->cputime_expires))
|
||||
return 1;
|
||||
}
|
||||
|
||||
sig = tsk->signal;
|
||||
/* Check if cputimer is running. This is accessed without locking. */
|
||||
if (READ_ONCE(sig->cputimer.running)) {
|
||||
/*
|
||||
* Check if thread group timers expired when the cputimer is
|
||||
* running and no other thread in the group is already checking
|
||||
* for thread group cputimers. These fields are read without the
|
||||
* sighand lock. However, this is fine because this is meant to
|
||||
* be a fastpath heuristic to determine whether we should try to
|
||||
* acquire the sighand lock to check/handle timers.
|
||||
*
|
||||
* In the worst case scenario, if 'running' or 'checking_timer' gets
|
||||
* set but the current thread doesn't see the change yet, we'll wait
|
||||
* until the next thread in the group gets a scheduler interrupt to
|
||||
* handle the timer. This isn't an issue in practice because these
|
||||
* types of delays with signals actually getting sent are expected.
|
||||
*/
|
||||
if (READ_ONCE(sig->cputimer.running) &&
|
||||
!READ_ONCE(sig->cputimer.checking_timer)) {
|
||||
struct task_cputime group_sample;
|
||||
|
||||
sample_cputime_atomic(&group_sample, &sig->cputimer.cputime_atomic);
|
||||
@@ -1174,12 +1205,8 @@ void run_posix_cpu_timers(struct task_struct *tsk)
|
||||
* put them on the firing list.
|
||||
*/
|
||||
check_thread_timers(tsk, &firing);
|
||||
/*
|
||||
* If there are any active process wide timers (POSIX 1.b, itimers,
|
||||
* RLIMIT_CPU) cputimer must be running.
|
||||
*/
|
||||
if (READ_ONCE(tsk->signal->cputimer.running))
|
||||
check_process_timers(tsk, &firing);
|
||||
|
||||
check_process_timers(tsk, &firing);
|
||||
|
||||
/*
|
||||
* We must release these locks before taking any timer's lock.
|
||||
|
@@ -39,7 +39,7 @@ define fmuls(b,n,d) {
|
||||
}
|
||||
|
||||
define timeconst(hz) {
|
||||
print "/* Automatically generated by kernel/timeconst.bc */\n"
|
||||
print "/* Automatically generated by kernel/time/timeconst.bc */\n"
|
||||
print "/* Time conversion constants for HZ == ", hz, " */\n"
|
||||
print "\n"
|
||||
|
||||
|
@@ -849,7 +849,7 @@ EXPORT_SYMBOL_GPL(ktime_get_real_seconds);
|
||||
#ifdef CONFIG_NTP_PPS
|
||||
|
||||
/**
|
||||
* getnstime_raw_and_real - get day and raw monotonic time in timespec format
|
||||
* ktime_get_raw_and_real_ts64 - get day and raw monotonic time in timespec format
|
||||
* @ts_raw: pointer to the timespec to be set to raw monotonic time
|
||||
* @ts_real: pointer to the timespec to be set to the time of day
|
||||
*
|
||||
@@ -857,7 +857,7 @@ EXPORT_SYMBOL_GPL(ktime_get_real_seconds);
|
||||
* same time atomically and stores the resulting timestamps in timespec
|
||||
* format.
|
||||
*/
|
||||
void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real)
|
||||
void ktime_get_raw_and_real_ts64(struct timespec64 *ts_raw, struct timespec64 *ts_real)
|
||||
{
|
||||
struct timekeeper *tk = &tk_core.timekeeper;
|
||||
unsigned long seq;
|
||||
@@ -868,7 +868,7 @@ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real)
|
||||
do {
|
||||
seq = read_seqcount_begin(&tk_core.seq);
|
||||
|
||||
*ts_raw = timespec64_to_timespec(tk->raw_time);
|
||||
*ts_raw = tk->raw_time;
|
||||
ts_real->tv_sec = tk->xtime_sec;
|
||||
ts_real->tv_nsec = 0;
|
||||
|
||||
@@ -877,10 +877,10 @@ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real)
|
||||
|
||||
} while (read_seqcount_retry(&tk_core.seq, seq));
|
||||
|
||||
timespec_add_ns(ts_raw, nsecs_raw);
|
||||
timespec_add_ns(ts_real, nsecs_real);
|
||||
timespec64_add_ns(ts_raw, nsecs_raw);
|
||||
timespec64_add_ns(ts_real, nsecs_real);
|
||||
}
|
||||
EXPORT_SYMBOL(getnstime_raw_and_real);
|
||||
EXPORT_SYMBOL(ktime_get_raw_and_real_ts64);
|
||||
|
||||
#endif /* CONFIG_NTP_PPS */
|
||||
|
||||
@@ -1674,7 +1674,7 @@ static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
|
||||
/**
|
||||
* accumulate_nsecs_to_secs - Accumulates nsecs into secs
|
||||
*
|
||||
* Helper function that accumulates a the nsecs greater then a second
|
||||
* Helper function that accumulates the nsecs greater than a second
|
||||
* from the xtime_nsec field to the xtime_secs field.
|
||||
* It also calls into the NTP code to handle leapsecond processing.
|
||||
*
|
||||
@@ -1726,7 +1726,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
|
||||
cycle_t interval = tk->cycle_interval << shift;
|
||||
u64 raw_nsecs;
|
||||
|
||||
/* If the offset is smaller then a shifted interval, do nothing */
|
||||
/* If the offset is smaller than a shifted interval, do nothing */
|
||||
if (offset < interval)
|
||||
return offset;
|
||||
|
||||
@@ -2025,7 +2025,7 @@ int do_adjtimex(struct timex *txc)
|
||||
/**
|
||||
* hardpps() - Accessor function to NTP __hardpps function
|
||||
*/
|
||||
void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
|
||||
void hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
@@ -461,10 +461,17 @@ void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
|
||||
|
||||
static void timer_stats_account_timer(struct timer_list *timer)
|
||||
{
|
||||
if (likely(!timer->start_site))
|
||||
void *site;
|
||||
|
||||
/*
|
||||
* start_site can be concurrently reset by
|
||||
* timer_stats_timer_clear_start_info()
|
||||
*/
|
||||
site = READ_ONCE(timer->start_site);
|
||||
if (likely(!site))
|
||||
return;
|
||||
|
||||
timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
|
||||
timer_stats_update_stats(timer, timer->start_pid, site,
|
||||
timer->function, timer->start_comm,
|
||||
timer->flags);
|
||||
}
|
||||
@@ -867,7 +874,7 @@ unsigned long apply_slack(struct timer_list *timer, unsigned long expires)
|
||||
if (mask == 0)
|
||||
return expires;
|
||||
|
||||
bit = find_last_bit(&mask, BITS_PER_LONG);
|
||||
bit = __fls(mask);
|
||||
|
||||
mask = (1UL << bit) - 1;
|
||||
|
||||
|
Reference in New Issue
Block a user