lkml.org 
[lkml]   [1999]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: [Patch] Re: usleep granularity
    Oops, I forgot one assignment for the Alpha code (lost = lost_ticks). This
    is the fixed patch.

    Bernd Paysan
    "If you want it done right, you have to do it yourself"
    http://www.jwdt.com/~paysan/
    --- linux-2.3.9/arch/alpha/kernel/time.c.orig Sat Jul 10 13:49:32 1999
    +++ linux-2.3.9/arch/alpha/kernel/time.c Sat Jul 10 13:57:57 1999
    @@ -323,6 +323,44 @@
    panic("Could not allocate timer IRQ!");
    }

    +unsigned long gettimeoffset(void)
    +{
    + unsigned long lost, delta_cycles, delta_usec, partial_tick;
    +
    +#ifdef __SMP__
    + /* Until and unless we figure out how to get cpu cycle counters
    + in sync and keep them there, we can't use the rpcc tricks. */
    + delta_usec = 1000000L / HZ - 1;
    +#else
    + /*
    + * usec = cycles * ticks_per_cycle * 2**48 * 1e6 / (2**48 * ticks)
    + * = cycles * (s_t_p_c) * 1e6 / (2**48 * ticks)
    + * = cycles * (s_t_p_c) * 15625 / (2**42 * ticks)
    + *
    + * which, given a 600MHz cycle and a 1024Hz tick, has a
    + * dynamic range of about 1.7e17, which is less than the
    + * 1.8e19 in an unsigned long, so we are safe from overflow.
    + *
    + * Round, but with .5 up always, since .5 to even is harder
    + * with no clear gain.
    + */
    +
    + delta_cycles = rpcc() - state.last_time;
    + partial_tick = state.partial_tick;
    + lost = lost_ticks;
    +
    + delta_usec = (delta_cycles * state.scaled_ticks_per_cycle
    + + partial_tick
    + + (lost << FIX_SHIFT)) * 15625;
    + delta_usec = ((delta_usec / ((1UL << (FIX_SHIFT-6-1)) * HZ)) + 1) / 2;
    +#endif
    +
    + return delta_usec;
    +}
    +
    /*
    * Use the cycle counter to estimate an displacement from the last time
    * tick. Unfortunately the Alpha designers made only the low 32-bits of
    --- linux-2.3.9/arch/sparc/kernel/time.c.orig Sat Jul 10 13:49:32 1999
    +++ linux-2.3.9/arch/sparc/kernel/time.c Sat Jul 10 13:52:28 1999
    @@ -441,6 +441,11 @@
    return offset + count;
    }

    +unsigned long gettimeoffset(void)
    +{
    + return do_gettimeoffset();
    +}
    +
    /* This need not obtain the xtime_lock as it is coded in
    * an implicitly SMP safe way already.
    */
    --- linux-2.3.9/arch/mips/kernel/time.c.orig Sat Jul 10 13:49:32 1999
    +++ linux-2.3.9/arch/mips/kernel/time.c Sat Jul 10 14:01:00 1999
    @@ -212,6 +212,15 @@
    static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;

    /*
    + * This is the exported gettimeoffset() function -- Bernd Paysan
    + */
    +
    +unsigned long gettimeoffset(void)
    +{
    + return do_gettimeoffset();
    +}
    +
    +/*
    * This version of gettimeofday has near microsecond resolution.
    */
    void do_gettimeofday(struct timeval *tv)
    --- linux-2.3.9/arch/ppc/kernel/time.c.orig Sat Jul 10 13:49:32 1999
    +++ linux-2.3.9/arch/ppc/kernel/time.c Sat Jul 10 14:00:22 1999
    @@ -132,6 +132,16 @@
    hardirq_exit(cpu);
    }

    +unsigned long gettimeoffset(void)
    +{
    +#ifndef __SMP__
    + return (decrementer_count - get_dec())
    + * count_period_num / count_period_den;
    +#else
    + return 1000000L / HZ - 1;
    +#endif
    +}
    +
    /*
    * This version of gettimeofday has microsecond resolution.
    */
    --- linux-2.3.9/arch/m68k/kernel/time.c.orig Sat Jul 10 13:49:32 1999
    +++ linux-2.3.9/arch/m68k/kernel/time.c Sat Jul 10 14:02:44 1999
    @@ -153,6 +153,22 @@
    extern rwlock_t xtime_lock;

    /*
    + * This is the exported gettimeoffset() function -- Bernd Paysan
    + */
    +
    +unsigned long gettimeoffset(void)
    +{
    + unsigned long usec, lost;
    +
    + usec = mach_gettimeoffset();
    + lost = lost_ticks;
    + if (lost)
    + usec += lost * (1000000/HZ);
    +
    + return usec;
    +}
    +
    +/*
    * This version of gettimeofday has near microsecond resolution.
    */
    void do_gettimeofday(struct timeval *tv)
    --- linux-2.3.9/arch/sparc64/kernel/time.c.orig Sat Jul 10 13:49:32 1999
    +++ linux-2.3.9/arch/sparc64/kernel/time.c Sat Jul 10 13:52:43 1999
    @@ -411,6 +411,11 @@
    return ticks / timer_ticks_per_usec;
    }

    +unsigned long gettimeoffset(void)
    +{
    + return do_gettimeoffset();
    +}
    +
    /* This need not obtain the xtime_lock as it is coded in
    * an implicitly SMP safe way already.
    */
    --- linux-2.3.9/fs/select.c.orig Thu Jul 8 21:12:43 1999
    +++ linux-2.3.9/fs/select.c Thu Jul 8 22:16:33 1999
    @@ -14,6 +14,7 @@
    #include <linux/smp_lock.h>
    #include <linux/poll.h>
    #include <linux/file.h>
    +#include <linux/time.h>

    #include <asm/uaccess.h>

    @@ -231,6 +232,17 @@
    *
    * Update: ERESTARTSYS breaks at least the xview clock binary, so
    * I'm trying ERESTARTNOHAND which restart only when you want to.
    + *
    + * Update: the previous code had a sleep time between 10 and 20 ms
    + * at least - it wasn't possible to sleep between 0 and 10 ms. The
    + * new code doesn't consider worst-case szenarios, and instead
    + * uses gettimeoffset() to compensate for the time to the current
    + * jiffie's schedule time.
    + *
    + * I also want to use the same code for nanosleep() as for select().
    + *
    + * -- Bernd Paysan <bernd.paysan@gmx.de>
    + *
    */
    #define MAX_SELECT_SECONDS \
    ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
    @@ -257,8 +269,12 @@
    goto out_nofds;

    if ((unsigned long) sec < MAX_SELECT_SECONDS) {
    - timeout = ROUND_UP(usec, 1000000/HZ);
    - timeout += sec * (unsigned long) HZ;
    + struct timespec tspec;
    +
    + tspec.tv_sec = sec;
    + tspec.tv_nsec = usec * 1000;
    +
    + timeout = timespec_to_jiffies(&tspec);
    }
    }

    --- linux-2.3.9/include/linux/time.h.orig Thu Jul 8 21:34:34 1999
    +++ linux-2.3.9/include/linux/time.h Sat Jul 10 14:15:30 1999
    @@ -23,20 +23,60 @@
    * to wait "jiffies+1" in order to guarantee that we wait
    * at _least_ "jiffies" - so "jiffies+1" had better still
    * be positive.
    + *
    + * Update: timespec_to_jiffies used to round up worst case,
    + * instead of just adding the current offset to the ns delay.
    + * CAVEAT: this really should include jiffies in the calculation,
    + * since jiffies could overflow between the call off gettimeoffset()
    + * and the addition of jiffies in the underlying code.
    + *
    + * The timer code in arch/<machine>/kernel/time.c must export gettimeoffset(),
    + * which should return 1000000L / HZ - 1 (worst case) if unknown.
    + * -- Bernd Paysan <bernd.paysan@gmx.de>
    */
    #define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)

    +#ifdef __KERNEL__
    +#ifdef CONFIG_ARM
    +#include <asm/arch/time.h>
    +#else
    +extern unsigned long gettimeoffset(void);
    +#endif
    +#endif
    +
    static __inline__ unsigned long
    timespec_to_jiffies(struct timespec *value)
    {
    unsigned long sec = value->tv_sec;
    long nsec = value->tv_nsec;
    + long offset;
    +#ifdef T2J_WITH_JIFFIES
    + long jiffies1;
    +#endif

    if (sec >= (MAX_JIFFY_OFFSET / HZ))
    +#ifdef T2J_WITH_JIFFIES
    + return jiffies + MAX_JIFFY_OFFSET;
    +#else
    return MAX_JIFFY_OFFSET;
    - nsec += 1000000000L / HZ - 1;
    +#endif
    +
    +#ifdef T2J_WITH_JIFFIES
    + do {
    + jiffies1 = jiffies;
    +#endif
    + offset = gettimeoffset();
    +#ifdef T2J_WITH_JIFFIES
    + } while (jiffies1 != jiffies);
    +#endif
    +
    + nsec += offset * 1000;
    nsec /= 1000000000L / HZ;
    - return HZ * sec + nsec;
    + return HZ * sec + nsec
    +#ifdef T2J_WITH_JIFFIES
    + + jiffies
    +#endif
    + ;
    }

    static __inline__ void
    \
     
     \ /
      Last update: 2005-03-22 13:52    [W:0.032 / U:29.232 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site