From: john stultz <johnstul@us.ibm.com>
To: akpm@osdl.org
Cc: john stultz <johnstul@us.ibm.com>,
linux-kernel@vger.kernel.org, george@wildturkeyranch.net,
Steven Rostedt <rostedt@goodmis.org>,
Thomas Gleixner <tglx@linutronix.de>,
Ulrich Windl <ulrich.windl@rz.uni-regensburg.de>,
Roman Zippel <zippel@linux-m68k.org>, Ingo Molnar <mingo@elte.hu>,
Paul Mackerras <paulus@samba.org>
Subject: [PATCH 5/10] Time: Introduce arch generic time accessors
Date: Wed, 22 Mar 2006 20:06:20 -0700 [thread overview]
Message-ID: <20060323030619.19338.49583.sendpatchset@cog.beaverton.ibm.com> (raw)
In-Reply-To: <20060323030547.19338.95102.sendpatchset@cog.beaverton.ibm.com>
Introduces clocksource switching code and the arch generic time
accessor functions that use the clocksource infrastructure.
Signed-off-by: John Stultz <johnstul@us.ibm.com>
include/linux/time.h | 15 ++++
kernel/time.c | 2
kernel/timer.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 187 insertions(+)
linux-2.6.16_timeofday-core4_C1.patch
============================================
diff --git a/include/linux/time.h b/include/linux/time.h
index 84cfa7b..fc06884 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -107,6 +107,7 @@ extern int do_getitimer(int which, struc
extern void getnstimeofday(struct timespec *tv);
extern struct timespec timespec_trunc(struct timespec t, unsigned gran);
+extern int timekeeping_is_continuous(void);
/**
* timespec_to_ns - Convert timespec to nanoseconds
@@ -149,6 +150,20 @@ extern struct timespec ns_to_timespec(co
*/
extern struct timeval ns_to_timeval(const nsec_t nsec);
+/**
+ * timespec_add_ns - Adds nanoseconds to a timespec
+ * @a: pointer to timespec to be incremented
+ * @ns: unsigned nanoseconds value to be added
+ */
+static inline void timespec_add_ns(struct timespec *a, u64 ns)
+{
+ ns += a->tv_nsec;
+ while(unlikely(ns >= NSEC_PER_SEC)) {
+ ns -= NSEC_PER_SEC;
+ a->tv_sec++;
+ }
+ a->tv_nsec = ns;
+}
#endif /* __KERNEL__ */
#define NFDBITS __NFDBITS
diff --git a/kernel/time.c b/kernel/time.c
index 8045391..526fbdb 100644
--- a/kernel/time.c
+++ b/kernel/time.c
@@ -550,6 +550,7 @@ EXPORT_SYMBOL(do_gettimeofday);
#else
+#ifndef CONFIG_GENERIC_TIME
/*
* Simulate gettimeofday using do_gettimeofday which only allows a timeval
* and therefore only yields usec accuracy
@@ -564,6 +565,7 @@ void getnstimeofday(struct timespec *tv)
}
EXPORT_SYMBOL_GPL(getnstimeofday);
#endif
+#endif
/* 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
diff --git a/kernel/timer.c b/kernel/timer.c
index 339d52f..0c1e184 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -806,6 +806,169 @@ u64 current_tick_length(long shift)
#include <linux/clocksource.h>
static struct clocksource *clock; /* pointer to current clocksource */
static cycle_t last_clock_cycle; /* cycle value at last update_wall_time */
+
+#ifdef CONFIG_GENERIC_TIME
+/**
+ * __get_nsec_offset - Returns nanoseconds since last call to periodic_hook
+ *
+ * private function, must hold xtime_lock lock when being
+ * called. Returns the number of nanoseconds since the
+ * last call to update_wall_time() (adjusted by NTP scaling)
+ */
+static inline s64 __get_nsec_offset(void)
+{
+ cycle_t cycle_now, cycle_delta;
+ s64 ns_offset;
+
+ /* read clocksource: */
+ cycle_now = read_clocksource(clock);
+
+ /* calculate the delta since the last update_wall_time: */
+ cycle_delta = (cycle_now - last_clock_cycle) & clock->mask;
+
+ /* convert to nanoseconds: */
+ ns_offset = cyc2ns(clock, cycle_delta);
+
+ return ns_offset;
+}
+
+/**
+ * __get_realtime_clock_ts - Returns the time of day in a timespec
+ * @ts: pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec. Used by
+ * do_gettimeofday() and get_realtime_clock_ts().
+ */
+static inline void __get_realtime_clock_ts(struct timespec *ts)
+{
+ unsigned long seq;
+ s64 nsecs;
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+
+ *ts = xtime;
+ nsecs = __get_nsec_offset();
+
+ } while (read_seqretry(&xtime_lock, seq));
+
+ timespec_add_ns(ts, nsecs);
+}
+
+/**
+ * get_realtime_clock_ts - Returns the time of day in a timespec
+ * @ts: pointer to the timespec to be set
+ *
+ * Returns the time of day in a timespec.
+ */
+void getnstimeofday(struct timespec *ts)
+{
+ __get_realtime_clock_ts(ts);
+}
+
+EXPORT_SYMBOL(getnstimeofday);
+
+/**
+ * do_gettimeofday - Returns the time of day in a timeval
+ * @tv: pointer to the timeval to be set
+ *
+ * NOTE: Users should be converted to using get_realtime_clock_ts()
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+ struct timespec now;
+
+ __get_realtime_clock_ts(&now);
+ tv->tv_sec = now.tv_sec;
+ tv->tv_usec = now.tv_nsec/1000;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+/**
+ * do_settimeofday - Sets the time of day
+ * @tv: pointer to the timespec variable containing the new time
+ *
+ * Sets the time of day to the new time and update NTP and notify hrtimers
+ */
+int do_settimeofday(struct timespec *tv)
+{
+ unsigned long flags;
+ 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_irqsave(&xtime_lock, flags);
+
+ nsec -= __get_nsec_offset();
+
+ 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);
+
+ ntp_clear();
+
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+
+ /* signal hrtimers about time change */
+ clock_was_set();
+
+ return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+/**
+ * change_clocksource - Swaps clocksources if a new one is available
+ *
+ * Accumulates current time interval and initializes new clocksource
+ */
+static int change_clocksource(void)
+{
+ struct clocksource *new;
+ cycle_t now;
+ u64 nsec;
+ new = get_next_clocksource();
+ if (clock != new) {
+ now = read_clocksource(new);
+ nsec = __get_nsec_offset();
+ timespec_add_ns(&xtime, nsec);
+
+ clock = new;
+ last_clock_cycle = now;
+ printk(KERN_INFO "Time: %s clocksource has been installed.\n",
+ clock->name);
+ return 1;
+ } else if (clock->update_callback) {
+ return clock->update_callback();
+ }
+ return 0;
+}
+#else
+#define change_clocksource() (0)
+#endif
+
+/**
+ * timeofday_is_continuous - check to see if timekeeping is free running
+ */
+int timekeeping_is_continuous(void)
+{
+ unsigned long seq;
+ int ret;
+
+ do {
+ seq = read_seqbegin(&xtime_lock);
+
+ ret = clock->is_continuous;
+
+ } while (read_seqretry(&xtime_lock, seq));
+
+ return ret;
+}
+
/*
* timekeeping_init - Initializes the clocksource and common timekeeping values
*/
@@ -912,6 +1075,13 @@ static void update_wall_time(void)
/* store full nanoseconds into xtime */
xtime.tv_nsec = remainder_snsecs >> clock->shift;
remainder_snsecs -= (s64)xtime.tv_nsec << clock->shift;
+
+ /* check to see if there is a new clocksource to use */
+ if (change_clocksource()) {
+ error = 0;
+ remainder_snsecs = 0;
+ calculate_clocksource_interval(clock, tick_nsec);
+ }
}
/*
next prev parent reply other threads:[~2006-03-23 3:06 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-03-23 3:05 [PATCHSET 0/10] Time: Generic Timekeeping (v.C1) john stultz
2006-03-23 3:05 ` [PATCH 1/10] Time: Clocksource Infrastructure john stultz
2006-03-23 3:06 ` [PATCH 2/10] Time: Use clocksource infrastructure for update_wall_time john stultz
2006-03-23 3:06 ` [PATCH 3/10] Time: Let user request precision from current_tick_length() john stultz
2006-03-23 3:06 ` [PATCH 4/10] Time: Use clocksource abstraction for NTP adjustments john stultz
2006-03-23 3:06 ` john stultz [this message]
2006-03-23 3:06 ` [PATCH 6/10] Time: i386 Conversion - part 1: Move timer_pit.c to i8253.c john stultz
2006-03-23 3:06 ` [PATCH 7/10] Time: i386 Conversion - part 2: Rework TSC Support john stultz
2006-03-23 3:06 ` [PATCH 8/10] Time: i386 Conversion - part 3: Enable Generic Timekeeping john stultz
2006-03-23 3:06 ` [PATCH 9/10] Time: i386 Conversion - part 4: Remove Old timer_opts Code john stultz
2006-03-23 3:06 ` [PATCH 10/10] Time: i386 Clocksource Drivers john stultz
2006-03-23 12:48 ` [PATCHSET 0/10] Time: Generic Timekeeping (v.C1) Roman Zippel
2006-03-23 14:20 ` Thomas Gleixner
2006-03-23 13:45 ` Roman Zippel
2006-03-23 19:40 ` john stultz
-- strict thread matches above, loose matches on Subject: below --
2006-03-18 0:39 [PATCHSET 0/10] Time: Generic Timekeeping (v.C0) john stultz
2006-03-18 0:40 ` [PATCH 5/10] Time: Introduce arch generic time accessors john stultz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060323030619.19338.49583.sendpatchset@cog.beaverton.ibm.com \
--to=johnstul@us.ibm.com \
--cc=akpm@osdl.org \
--cc=george@wildturkeyranch.net \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=paulus@samba.org \
--cc=rostedt@goodmis.org \
--cc=tglx@linutronix.de \
--cc=ulrich.windl@rz.uni-regensburg.de \
--cc=zippel@linux-m68k.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox