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    [from the cache]
©2003-2011 Jasper Spaans