Re: 2.2.8 gettimeofday() still doesn't work on Alpha

Thorsten Kranzkowski (th@Marvin.DL8BCU.ampr.org)
Wed, 12 May 1999 18:42:49 +0000 (UTC)


> Just booted 2.2.8 on my PC164 and the timetest program (included below)
> produces negative deltas with high frequency.
>

Hello Tom!
I wasn't aware of that other patch (I'm quite new to alpha :-)) - It is
essentially right! I was tracking down the same effect where do_gettimeofday()
was called from interrupt context (drivers/net/hamradio/baycom_ser_fdx.c)
so I didn't notice it effected userspace also.
Thanks for pointing that out!

So please try if the attached patch works for you - I will send it to Linus
then.

Bye
Thorsten

--- linux-2.2.8/arch/alpha/kernel/time.c.orig Fri Apr 30 23:44:19 1999
+++ linux/arch/alpha/kernel/time.c Wed May 12 17:06:53 1999
@@ -21,6 +21,9 @@
* 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net)
* fixed algorithm in do_gettimeofday() for calculating the precise time
* from processor cycle counter (now taking lost_ticks into account)
+ * 1999-05-12 Thorsten Kranzkowski (dl8bcu@gmx.net)
+ * fixed do_gettimeofday() even more
+ * based on a patch from Bruce Elliott <bde@nwlink.com>
*/
#include <linux/config.h>
#include <linux/errno.h>
@@ -330,15 +333,17 @@
{
unsigned long flags, delta_cycles, delta_usec;
unsigned long sec, usec;
- __u32 now;
+ unsigned long lost ;
+ unsigned long partial_tick ;
extern volatile unsigned long lost_ticks; /*kernel/sched.c*/

- now = rpcc();
- save_and_cli(flags);
+ read_lock_irqsave(&xtime.lock, flags);
+ delta_cycles = rpcc() - state.last_time;
sec = xtime.tv_sec;
usec = xtime.tv_usec;
- delta_cycles = now - state.last_time;
- restore_flags(flags);
+ partial_tick = state.partial_tick;
+ lost = lost_ticks;
+ read_unlock_irqrestore(&xtime_lock, flags);

/*
* usec = cycles * ticks_per_cycle * 2**48 * 1e6 / (2**48 * ticks)
@@ -354,12 +359,12 @@
*/

delta_usec = (delta_cycles * state.scaled_ticks_per_cycle
- + state.partial_tick
- + (lost_ticks << FIX_SHIFT) ) * 15625;
+ + partial_tick
+ + (lost << FIX_SHIFT) ) * 15625;
delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;

/* the 'lost_tics' term above implements this:
- * delta_usec += lost_ticks * (1000000 / HZ);
+ * delta_usec += lost * (1000000 / HZ);
*/

usec += delta_usec;
@@ -375,13 +380,31 @@
void
do_settimeofday(struct timeval *tv)
{
- cli();
+ unsigned long delta_usec;
+ extern volatile unsigned long lost_ticks; /*kernel/sched.c*/
+
+ /* The offset that is added into time in do_gettimeofday above must
+ * be subtracted here to keep a coherent view of the time. Without
+ * this, a full-tick error is possible.
+ */
+
+ write_lock_irq(&xtime_lock);
+ delta_usec = ((rpcc() - state.last_time) * state.scaled_ticks_per_cycle
+ + state.partial_tick
+ + (lost_ticks << FIX_SHIFT) ) * 15625;
+ delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
+
xtime = *tv;
+ xtime.tv_usec -= delta_usec ;
+ if (xtime.tv_usec <0) {
+ xtime.tv_usec += 1000000 ;
+ xtime.tv_sec-- ;
+ }
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
- sti();
+ write_unlock_irq(&xtime_lock);
}


-- 
| Thorsten Kranzkowski            Snail: Niemannsweg 30, 49201 Dissen, Germany |
| Mobile: ++49 161 7210230         Inet: dl8bcu@gmx.net                        |
| Ampr: dl8bcu@db0nei.#nrw.deu.eu, dl8bcu@marvin.dl8bcu.ampr.org [44.130.8.19] |

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/