public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
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);
+	}
 }
 
 /*

  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