Skip to content

Commit

Permalink
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…linux/kernel/git/tip/tip

Pull timer core update from Thomas Gleixner:
 - Bug fixes (one for a longstanding dead loop issue)
 - Rework of time related vsyscalls
 - Alarm timer updates
 - Jiffies updates to remove compile time dependencies

* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  timekeeping: Cast raw_interval to u64 to avoid shift overflow
  timers: Fix endless looping between cascade() and internal_add_timer()
  time/jiffies: bring back unconditional LATCH definition
  time: Convert x86_64 to using new update_vsyscall
  time: Only do nanosecond rounding on GENERIC_TIME_VSYSCALL_OLD systems
  time: Introduce new GENERIC_TIME_VSYSCALL
  time: Convert CONFIG_GENERIC_TIME_VSYSCALL to CONFIG_GENERIC_TIME_VSYSCALL_OLD
  time: Move update_vsyscall definitions to timekeeper_internal.h
  time: Move timekeeper structure to timekeeper_internal.h for vsyscall changes
  jiffies: Remove compile time assumptions about CLOCK_TICK_RATE
  jiffies: Kill unused TICK_USEC_TO_NSEC
  alarmtimer: Rename alarmtimer_remove to alarmtimer_dequeue
  alarmtimer: Remove unused helpers & defines
  alarmtimer: Use hrtimer per-alarm instead of per-base
  alarmtimer: Implement minimum alarm interval for allowing suspend
  • Loading branch information
torvalds committed Oct 12, 2012
2 parents 0588f1f + 5b3900c commit 03d3602
Show file tree
Hide file tree
Showing 20 changed files with 289 additions and 265 deletions.
2 changes: 1 addition & 1 deletion arch/ia64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ config IA64
select ARCH_TASK_STRUCT_ALLOCATOR
select ARCH_THREAD_INFO_ALLOCATOR
select ARCH_CLOCKSOURCE_DATA
select GENERIC_TIME_VSYSCALL
select GENERIC_TIME_VSYSCALL_OLD
default y
help
The Itanium Processor Family is Intel's 64-bit successor to
Expand Down
4 changes: 2 additions & 2 deletions arch/ia64/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include <linux/interrupt.h>
#include <linux/efi.h>
#include <linux/timex.h>
#include <linux/clocksource.h>
#include <linux/timekeeper_internal.h>
#include <linux/platform_device.h>

#include <asm/machvec.h>
Expand Down Expand Up @@ -454,7 +454,7 @@ void update_vsyscall_tz(void)
{
}

void update_vsyscall(struct timespec *wall, struct timespec *wtm,
void update_vsyscall_old(struct timespec *wall, struct timespec *wtm,
struct clocksource *c, u32 mult)
{
write_seqcount_begin(&fsyscall_gtod_data.seq);
Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ config PPC
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select GENERIC_SMP_IDLE_THREAD
select GENERIC_CMOS_UPDATE
select GENERIC_TIME_VSYSCALL
select GENERIC_TIME_VSYSCALL_OLD
select GENERIC_CLOCKEVENTS
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
/* powerpc clocksource/clockevent code */

#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/timekeeper_internal.h>

static cycle_t rtc_read(struct clocksource *);
static struct clocksource clocksource_rtc = {
Expand Down Expand Up @@ -727,7 +727,7 @@ static cycle_t timebase_read(struct clocksource *cs)
return (cycle_t)get_tb();
}

void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
struct clocksource *clock, u32 mult)
{
u64 new_tb_to_xs, new_stamp_xsec;
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ config S390
select HAVE_UID16 if 32BIT
select ARCH_WANT_IPC_PARSE_VERSION
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select GENERIC_TIME_VSYSCALL_OLD
select GENERIC_CLOCKEVENTS
select KTIME_SCALAR if 32BIT
select HAVE_ARCH_SECCOMP_FILTER
Expand Down
4 changes: 2 additions & 2 deletions arch/s390/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#include <linux/profile.h>
#include <linux/timex.h>
#include <linux/notifier.h>
#include <linux/clocksource.h>
#include <linux/timekeeper_internal.h>
#include <linux/clockchips.h>
#include <linux/gfp.h>
#include <linux/kprobes.h>
Expand Down Expand Up @@ -219,7 +219,7 @@ struct clocksource * __init clocksource_default_clock(void)
return &clocksource_tod;
}

void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
void update_vsyscall_old(struct timespec *wall_time, struct timespec *wtm,
struct clocksource *clock, u32 mult)
{
if (clock != &clocksource_tod)
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/include/asm/vgtod.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ struct vsyscall_gtod_data {

/* open coded 'struct timespec' */
time_t wall_time_sec;
u32 wall_time_nsec;
u32 monotonic_time_nsec;
u64 wall_time_snsec;
u64 monotonic_time_snsec;
time_t monotonic_time_sec;

struct timezone sys_tz;
Expand Down
3 changes: 3 additions & 0 deletions arch/x86/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
#include <linux/percpu.h>
#include <linux/crash_dump.h>
#include <linux/tboot.h>
#include <linux/jiffies.h>

#include <video/edid.h>

Expand Down Expand Up @@ -1032,6 +1033,8 @@ void __init setup_arch(char **cmdline_p)
mcheck_init();

arch_init_ideal_nops();

register_refined_jiffies(CLOCK_TICK_RATE);
}

#ifdef CONFIG_X86_32
Expand Down
49 changes: 29 additions & 20 deletions arch/x86/kernel/vsyscall_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include <linux/jiffies.h>
#include <linux/sysctl.h>
#include <linux/topology.h>
#include <linux/clocksource.h>
#include <linux/timekeeper_internal.h>
#include <linux/getcpu.h>
#include <linux/cpu.h>
#include <linux/smp.h>
Expand Down Expand Up @@ -82,32 +82,41 @@ void update_vsyscall_tz(void)
vsyscall_gtod_data.sys_tz = sys_tz;
}

void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
struct clocksource *clock, u32 mult)
void update_vsyscall(struct timekeeper *tk)
{
struct timespec monotonic;
struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data;

write_seqcount_begin(&vsyscall_gtod_data.seq);
write_seqcount_begin(&vdata->seq);

/* copy vsyscall data */
vsyscall_gtod_data.clock.vclock_mode = clock->archdata.vclock_mode;
vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
vsyscall_gtod_data.clock.mask = clock->mask;
vsyscall_gtod_data.clock.mult = mult;
vsyscall_gtod_data.clock.shift = clock->shift;

vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
vdata->clock.vclock_mode = tk->clock->archdata.vclock_mode;
vdata->clock.cycle_last = tk->clock->cycle_last;
vdata->clock.mask = tk->clock->mask;
vdata->clock.mult = tk->mult;
vdata->clock.shift = tk->shift;

vdata->wall_time_sec = tk->xtime_sec;
vdata->wall_time_snsec = tk->xtime_nsec;

vdata->monotonic_time_sec = tk->xtime_sec
+ tk->wall_to_monotonic.tv_sec;
vdata->monotonic_time_snsec = tk->xtime_nsec
+ (tk->wall_to_monotonic.tv_nsec
<< tk->shift);
while (vdata->monotonic_time_snsec >=
(((u64)NSEC_PER_SEC) << tk->shift)) {
vdata->monotonic_time_snsec -=
((u64)NSEC_PER_SEC) << tk->shift;
vdata->monotonic_time_sec++;
}

monotonic = timespec_add(*wall_time, *wtm);
vsyscall_gtod_data.monotonic_time_sec = monotonic.tv_sec;
vsyscall_gtod_data.monotonic_time_nsec = monotonic.tv_nsec;
vdata->wall_time_coarse.tv_sec = tk->xtime_sec;
vdata->wall_time_coarse.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);

vsyscall_gtod_data.wall_time_coarse = __current_kernel_time();
vsyscall_gtod_data.monotonic_time_coarse =
timespec_add(vsyscall_gtod_data.wall_time_coarse, *wtm);
vdata->monotonic_time_coarse = timespec_add(vdata->wall_time_coarse,
tk->wall_to_monotonic);

write_seqcount_end(&vsyscall_gtod_data.seq);
write_seqcount_end(&vdata->seq);
}

static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
Expand Down
22 changes: 14 additions & 8 deletions arch/x86/vdso/vclock_gettime.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ notrace static long vdso_fallback_gtod(struct timeval *tv, struct timezone *tz)
}


notrace static inline long vgetns(void)
notrace static inline u64 vgetsns(void)
{
long v;
cycles_t cycles;
Expand All @@ -91,21 +91,24 @@ notrace static inline long vgetns(void)
else
return 0;
v = (cycles - gtod->clock.cycle_last) & gtod->clock.mask;
return (v * gtod->clock.mult) >> gtod->clock.shift;
return v * gtod->clock.mult;
}

/* Code size doesn't matter (vdso is 4k anyway) and this is faster. */
notrace static int __always_inline do_realtime(struct timespec *ts)
{
unsigned long seq, ns;
unsigned long seq;
u64 ns;
int mode;

ts->tv_nsec = 0;
do {
seq = read_seqcount_begin(&gtod->seq);
mode = gtod->clock.vclock_mode;
ts->tv_sec = gtod->wall_time_sec;
ts->tv_nsec = gtod->wall_time_nsec;
ns = vgetns();
ns = gtod->wall_time_snsec;
ns += vgetsns();
ns >>= gtod->clock.shift;
} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));

timespec_add_ns(ts, ns);
Expand All @@ -114,15 +117,18 @@ notrace static int __always_inline do_realtime(struct timespec *ts)

notrace static int do_monotonic(struct timespec *ts)
{
unsigned long seq, ns;
unsigned long seq;
u64 ns;
int mode;

ts->tv_nsec = 0;
do {
seq = read_seqcount_begin(&gtod->seq);
mode = gtod->clock.vclock_mode;
ts->tv_sec = gtod->monotonic_time_sec;
ts->tv_nsec = gtod->monotonic_time_nsec;
ns = vgetns();
ns = gtod->monotonic_time_snsec;
ns += vgetsns();
ns >>= gtod->clock.shift;
} while (unlikely(read_seqcount_retry(&gtod->seq, seq)));
timespec_add_ns(ts, ns);

Expand Down
31 changes: 2 additions & 29 deletions include/linux/alarmtimer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ enum alarmtimer_restart {

#define ALARMTIMER_STATE_INACTIVE 0x00
#define ALARMTIMER_STATE_ENQUEUED 0x01
#define ALARMTIMER_STATE_CALLBACK 0x02

/**
* struct alarm - Alarm timer structure
Expand All @@ -35,6 +34,7 @@ enum alarmtimer_restart {
*/
struct alarm {
struct timerqueue_node node;
struct hrtimer timer;
enum alarmtimer_restart (*function)(struct alarm *, ktime_t now);
enum alarmtimer_type type;
int state;
Expand All @@ -43,39 +43,12 @@ struct alarm {

void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
enum alarmtimer_restart (*function)(struct alarm *, ktime_t));
void alarm_start(struct alarm *alarm, ktime_t start);
int alarm_start(struct alarm *alarm, ktime_t start);
int alarm_try_to_cancel(struct alarm *alarm);
int alarm_cancel(struct alarm *alarm);

u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval);

/*
* A alarmtimer is active, when it is enqueued into timerqueue or the
* callback function is running.
*/
static inline int alarmtimer_active(const struct alarm *timer)
{
return timer->state != ALARMTIMER_STATE_INACTIVE;
}

/*
* Helper function to check, whether the timer is on one of the queues
*/
static inline int alarmtimer_is_queued(struct alarm *timer)
{
return timer->state & ALARMTIMER_STATE_ENQUEUED;
}

/*
* Helper function to check, whether the timer is running the callback
* function
*/
static inline int alarmtimer_callback_running(struct alarm *timer)
{
return timer->state & ALARMTIMER_STATE_CALLBACK;
}


/* Provide way to access the rtc device being used by alarmtimers */
struct rtc_device *alarmtimer_get_rtcdev(void);

Expand Down
16 changes: 0 additions & 16 deletions include/linux/clocksource.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,22 +319,6 @@ static inline void __clocksource_updatefreq_khz(struct clocksource *cs, u32 khz)
__clocksource_updatefreq_scale(cs, 1000, khz);
}

#ifdef CONFIG_GENERIC_TIME_VSYSCALL
extern void
update_vsyscall(struct timespec *ts, struct timespec *wtm,
struct clocksource *c, u32 mult);
extern void update_vsyscall_tz(void);
#else
static inline void
update_vsyscall(struct timespec *ts, struct timespec *wtm,
struct clocksource *c, u32 mult)
{
}

static inline void update_vsyscall_tz(void)
{
}
#endif

extern void timekeeping_notify(struct clocksource *clock);

Expand Down
20 changes: 3 additions & 17 deletions include/linux/jiffies.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,31 +51,17 @@
#define SH_DIV(NOM,DEN,LSH) ( (((NOM) / (DEN)) << (LSH)) \
+ ((((NOM) % (DEN)) << (LSH)) + (DEN) / 2) / (DEN))

#ifdef CLOCK_TICK_RATE
/* LATCH is used in the interval timer and ftape setup. */
# define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ) /* For divider */

/*
* HZ is the requested value. However the CLOCK_TICK_RATE may not allow
* for exactly HZ. So SHIFTED_HZ is high res HZ ("<< 8" is for accuracy)
*/
# define SHIFTED_HZ (SH_DIV(CLOCK_TICK_RATE, LATCH, 8))
#else
# define SHIFTED_HZ (HZ << 8)
#endif
extern int register_refined_jiffies(long clock_tick_rate);

/* TICK_NSEC is the time between ticks in nsec assuming SHIFTED_HZ */
#define TICK_NSEC (SH_DIV(1000000UL * 1000, SHIFTED_HZ, 8))
#define TICK_NSEC ((NSEC_PER_SEC+HZ/2)/HZ)

/* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
#define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ)

/*
* TICK_USEC_TO_NSEC is the time between ticks in nsec assuming SHIFTED_HZ and
* a value TUSEC for TICK_USEC (can be set bij adjtimex)
*/
#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV(TUSEC * USER_HZ * 1000, SHIFTED_HZ, 8))

/* some arch's have a small-data section that can be accessed register-relative
* but that can only take up to, say, 4-byte variables. jiffies being part of
* an 8-byte variable may not be correctly accessed unless we force the issue
Expand Down
Loading

0 comments on commit 03d3602

Please sign in to comment.