aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.davemloft.net>2004-08-06 08:59:59 -0700
committerDavid S. Miller <davem@nuts.davemloft.net>2004-08-06 08:59:59 -0700
commit2ae23d292eecae72577b26b13356becdf257cdb7 (patch)
treeefab52be37352e6d73596f29c0dc91e361cc3092 /arch
parente7bf20316397771071fead8fa59169a9ce90d804 (diff)
downloadhistory-2ae23d292eecae72577b26b13356becdf257cdb7.tar.gz
[SPARC64]: Eliminate costly sdivx from gettimeofday.
Also use non-irq read seqlocking on xtime_lock. Signed-off-by: David S. Miller <davem@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/time.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 06e1579f061436..11625cce4891f6 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -423,7 +423,7 @@ static unsigned long timer_ticks_per_nsec_quotient;
#define TICK_SIZE (tick_nsec / 1000)
-static __inline__ void timer_check_rtc(void)
+static inline void timer_check_rtc(void)
{
/* last time the cmos clock got updated */
static long last_rtc_update;
@@ -1139,7 +1139,6 @@ EXPORT_SYMBOL(do_settimeofday);
*/
void do_gettimeofday(struct timeval *tv)
{
- unsigned long flags;
unsigned long seq;
unsigned long usec, sec;
unsigned long max_ntp_tick = tick_usec - tickadj;
@@ -1147,7 +1146,7 @@ void do_gettimeofday(struct timeval *tv)
do {
unsigned long lost;
- seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ seq = read_seqbegin(&xtime_lock);
usec = do_gettimeoffset();
lost = jiffies - wall_jiffies;
@@ -1166,8 +1165,18 @@ void do_gettimeofday(struct timeval *tv)
usec += lost * tick_usec;
sec = xtime.tv_sec;
- usec += (xtime.tv_nsec / 1000);
- } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+
+ /* Believe it or not, this divide shows up on
+ * kernel profiles. The problem is that it is
+ * both 64-bit and signed. Happily, 32-bits
+ * of precision is all we really need and in
+ * doing so gcc ends up emitting a cheap multiply.
+ *
+ * XXX Why is tv_nsec 'long' and 'signed' in
+ * XXX the first place, can it even be negative?
+ */
+ usec += ((unsigned int) xtime.tv_nsec / 1000U);
+ } while (read_seqretry(&xtime_lock, seq));
while (usec >= 1000000) {
usec -= 1000000;