public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)
@ 2005-04-08 17:39 jdavis
  2005-04-08 22:19 ` Steven Rostedt
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: jdavis @ 2005-04-08 17:39 UTC (permalink / raw)
  To: linux-kernel



Hello, 

I've created a pretty straight forward timer using setitimer, and noticed
some odd differences between 2.4 and 2.6, I wonder if I could get a
clarification if this is the way it should work, or if I should continue to
try to "fix" it.

I create a RealTime Thread( SCHED_FIFO, maxPriority-1 ) (also tried
SCHED_RR) ...

that creates a timer ...setitimer( ITIMER_REAL, SIGALRM) with a 10 milli
period. (I've also tried timer_create with CLOCK_REALTIME and SIGRTMIN)

and then the thread does a sem_wait() on a semaphore. 

the signal handler does a sem_post() .


on 2.4.X the (idle) worst case latency is ~40 microseconds, 
on 2.6.X the (idle) latency is about the same plus 1 tick of the scheduler
~1000 micro seconds... Always.. Every time.
So to work around this on 2.6 I simply subtract 1 millisecond from my timer
as a fudge factor and everything works as expected.

I've tried compiling various kernels (2.6.9, 2.6.11) with kernel pre-empting
on, etc..

Is this the correct behavior? If so I'm curious who is using up the extra
Tick?
Does the asynch signal handler use up the whole tick even though it only has
to sem_post()?

I am not subscribed to the list, so I would appreciate a CC.
Thanks,
-JD

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)
  2005-04-08 17:39 Odd Timer behavior in 2.6 vs 2.4 (1 extra tick) jdavis
@ 2005-04-08 22:19 ` Steven Rostedt
  2005-04-21  2:58 ` [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)] Steven Rostedt
  2005-04-29 21:28 ` Odd Timer behavior in 2.6 vs 2.4 (1 extra tick) Nish Aravamudan
  2 siblings, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2005-04-08 22:19 UTC (permalink / raw)
  To: jdavis; +Cc: linux-kernel

On Fri, 2005-04-08 at 10:39 -0700, jdavis@accessline.com wrote:
> 
> Hello, 
> 
> I've created a pretty straight forward timer using setitimer, and noticed
> some odd differences between 2.4 and 2.6, I wonder if I could get a
> clarification if this is the way it should work, or if I should continue to
> try to "fix" it.

Hi, could you send me a simple program that shows the latency, then I'll
be able to analysis exactly where the problem (if there is a problem)
is.

-- Steve



^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)]
  2005-04-08 17:39 Odd Timer behavior in 2.6 vs 2.4 (1 extra tick) jdavis
  2005-04-08 22:19 ` Steven Rostedt
@ 2005-04-21  2:58 ` Steven Rostedt
  2005-04-21  3:40   ` Steven Rostedt
  2005-04-29 21:28 ` Odd Timer behavior in 2.6 vs 2.4 (1 extra tick) Nish Aravamudan
  2 siblings, 1 reply; 12+ messages in thread
From: Steven Rostedt @ 2005-04-21  2:58 UTC (permalink / raw)
  To: jdavis; +Cc: linux-kernel, Andrew Morton, Linus Torvalds

I looked into the problem that jdavis had and found that the conversion
of the timeval_to_jiffies was off by one. 

To convert tv.tv_sec = 0, tv.tv_usec = 10000 to jiffies, you come up
with an answer of 11 (assuming 1000 HZ).  

Here's the patch:

--- ./include/linux/jiffies.h.orig	2005-04-20 22:30:34.000000000 -0400
+++ ./include/linux/jiffies.h	2005-04-20 22:39:42.000000000 -0400
@@ -231,7 +231,7 @@
  * in jiffies (albit scaled), it is nothing but the bits we will shift
  * off.
  */
-#define USEC_ROUND (u64)(((u64)1 << USEC_JIFFIE_SC) - 1)
+#define USEC_ROUND (u64)(((u64)1 << (USEC_JIFFIE_SC - 1)))
 /*
  * The maximum jiffie value is (MAX_INT >> 1).  Here we translate that
  * into seconds.  The 64-bit case will overflow if we are not careful,


I wrote a user program that copies all of the jiffies.h and shows the
output of the conversion.  Without this patch you get:

usec=10000  jiffies = 11
usec=10010  jiffies = 11
usec=10020  jiffies = 11
   .
   .
   .
usec=10980  jiffies = 11
usec=10990  jiffies = 11
usec=11000  jiffies = 12


With the patch, you get:

usec=10000  jiffies = 10
usec=10010  jiffies = 10
usec=10020  jiffies = 10
   .
   .
   .
usec=10480  jiffies = 10
usec=10490  jiffies = 10
usec=10500  jiffies = 11
usec=10510  jiffies = 11
   .
   .
   .
usec=10990  jiffies = 11
usec=11000  jiffies = 11

Which I believe is the more desired result.

I've kept jdavis original email to show where this was discovered.

-- Steve



On Fri, 2005-04-08 at 10:39 -0700, jdavis@accessline.com wrote:
> 
> Hello, 
> 
> I've created a pretty straight forward timer using setitimer, and noticed
> some odd differences between 2.4 and 2.6, I wonder if I could get a
> clarification if this is the way it should work, or if I should continue to
> try to "fix" it.
> 
> I create a RealTime Thread( SCHED_FIFO, maxPriority-1 ) (also tried
> SCHED_RR) ...
> 
> that creates a timer ...setitimer( ITIMER_REAL, SIGALRM) with a 10 milli
> period. (I've also tried timer_create with CLOCK_REALTIME and SIGRTMIN)
> 
> and then the thread does a sem_wait() on a semaphore. 
> 
> the signal handler does a sem_post() .
> 
> 
> on 2.4.X the (idle) worst case latency is ~40 microseconds, 
> on 2.6.X the (idle) latency is about the same plus 1 tick of the scheduler
> ~1000 micro seconds... Always.. Every time.
> So to work around this on 2.6 I simply subtract 1 millisecond from my timer
> as a fudge factor and everything works as expected.
> 
> I've tried compiling various kernels (2.6.9, 2.6.11) with kernel pre-empting
> on, etc..
> 
> Is this the correct behavior? If so I'm curious who is using up the extra
> Tick?
> Does the asynch signal handler use up the whole tick even though it only has
> to sem_post()?
> 
> I am not subscribed to the list, so I would appreciate a CC.
> Thanks,
> -JD
> -


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)]
  2005-04-21  2:58 ` [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)] Steven Rostedt
@ 2005-04-21  3:40   ` Steven Rostedt
  2005-04-21  8:51     ` Russell King
  0 siblings, 1 reply; 12+ messages in thread
From: Steven Rostedt @ 2005-04-21  3:40 UTC (permalink / raw)
  To: jdavis; +Cc: Linus Torvalds, Andrew Morton, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1613 bytes --]

On Wed, 2005-04-20 at 22:58 -0400, Steven Rostedt wrote:
> I looked into the problem that jdavis had and found that the conversion
> of the timeval_to_jiffies was off by one. 
> 
> To convert tv.tv_sec = 0, tv.tv_usec = 10000 to jiffies, you come up
> with an answer of 11 (assuming 1000 HZ).  
> 

OK, this bothered me that this patch seems to work, since the comments
around the USEC_ROUND seem to make sense. So I looked more closely into
this.

Is 11 jiffies correct for 10ms?  Since the the USEC_CONVERSION contains
a TICK_NSEC which is suppose to (I believe) convert the number of CPU
ticks to nanoseconds.  Since ticks don't map nicely to nanoseconds there
can be a discrepancy for the actual time.  But this doesn't explain why
the patch changes everything into the desired result, assuming that
 10 ms == 10 jiffies.  

Maybe there's too much rounding going on.  I'll have to take a deeper
look into this, but feel free to look yourselves! I'm going to bed.

I've attached my userland program if you want to play around with the
numbers.

> Here's the patch:
> 
> --- ./include/linux/jiffies.h.orig	2005-04-20 22:30:34.000000000 -0400
> +++ ./include/linux/jiffies.h	2005-04-20 22:39:42.000000000 -0400
> @@ -231,7 +231,7 @@
>   * in jiffies (albit scaled), it is nothing but the bits we will shift
>   * off.
>   */
> -#define USEC_ROUND (u64)(((u64)1 << USEC_JIFFIE_SC) - 1)
> +#define USEC_ROUND (u64)(((u64)1 << (USEC_JIFFIE_SC - 1)))
>  /*
>   * The maximum jiffie value is (MAX_INT >> 1).  Here we translate that
>   * into seconds.  The 64-bit case will overflow if we are not careful,

-- Steve


[-- Attachment #2: jiffies.c --]
[-- Type: text/x-csrc, Size: 13346 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef unsigned long long u64;

#define HZ 1000

#ifndef div_long_long_rem
#define div_long_long_rem(dividend,divisor,remainder) \
({							\
	u64 result = dividend;				\
	*remainder = do_div(result,divisor);		\
	result;						\
})
#endif

#  define CLOCK_TICK_RATE 1193182 /* Underlying HZ */
#define NSEC_PER_SEC (1000000000L)
#define NSEC_PER_USEC (1000L)

/*
 * The following defines establish the engineering parameters of the PLL
 * model. The HZ variable establishes the timer interrupt frequency, 100 Hz
 * for the SunOS kernel, 256 Hz for the Ultrix kernel and 1024 Hz for the
 * OSF/1 kernel. The SHIFT_HZ define expresses the same value as the
 * nearest power of two in order to avoid hardware multiply operations.
 */
#if HZ >= 12 && HZ < 24
# define SHIFT_HZ	4
#elif HZ >= 24 && HZ < 48
# define SHIFT_HZ	5
#elif HZ >= 48 && HZ < 96
# define SHIFT_HZ	6
#elif HZ >= 96 && HZ < 192
# define SHIFT_HZ	7
#elif HZ >= 192 && HZ < 384
# define SHIFT_HZ	8
#elif HZ >= 384 && HZ < 768
# define SHIFT_HZ	9
#elif HZ >= 768 && HZ < 1536
# define SHIFT_HZ	10
#else
# error You lose.
#endif

/* LATCH is used in the interval timer and ftape setup. */
#define LATCH  ((CLOCK_TICK_RATE + HZ/2) / HZ)	/* For divider */

/* Suppose we want to devide two numbers NOM and DEN: NOM/DEN, the we can
 * improve accuracy by shifting LSH bits, hence calculating:
 *     (NOM << LSH) / DEN
 * This however means trouble for large NOM, because (NOM << LSH) may no
 * longer fit in 32 bits. The following way of calculating this gives us
 * some slack, under the following conditions:
 *   - (NOM / DEN) fits in (32 - LSH) bits.
 *   - (NOM % DEN) fits in (32 - LSH) bits.
 */
#define SH_DIV(NOM,DEN,LSH) (   ((NOM / DEN) << LSH)                    \
                             + (((NOM % DEN) << LSH) + DEN / 2) / DEN)

/* HZ is the requested value. ACTHZ is actual HZ ("<< 8" is for accuracy) */
#define ACTHZ (SH_DIV (CLOCK_TICK_RATE, LATCH, 8))

/* TICK_NSEC is the time between ticks in nsec assuming real ACTHZ */
#define TICK_NSEC (SH_DIV (1000000UL * 1000, ACTHZ, 8))

/* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
#define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ)

/* TICK_USEC_TO_NSEC is the time between ticks in nsec assuming real ACTHZ and	*/
/* a value TUSEC for TICK_USEC (can be set bij adjtimex)		*/
#define TICK_USEC_TO_NSEC(TUSEC) (SH_DIV (TUSEC * USER_HZ * 1000, ACTHZ, 8))

/* some arch's have a small-data section that can be accessed register-relative
 * but that can only take up to, say, 4-byte variables. jiffies being part of
 * an 8-byte variable may not be correctly accessed unless we force the issue
 */
#define __jiffy_data  __attribute__((section(".data")))

/*
 * The 64-bit value is not volatile - you MUST NOT read it
 * without sampling the sequence number in xtime_lock.
 * get_jiffies_64() will do this for you as appropriate.
 */
extern u64 __jiffy_data jiffies_64;
extern unsigned long volatile __jiffy_data jiffies;

#if (BITS_PER_LONG < 64)
u64 get_jiffies_64(void);
#else
static inline u64 get_jiffies_64(void)
{
	return (u64)jiffies;
}
#endif

/*
 *	These inlines deal with timer wrapping correctly. You are 
 *	strongly encouraged to use them
 *	1. Because people otherwise forget
 *	2. Because if the timer wrap changes in future you won't have to
 *	   alter your driver code.
 *
 * time_after(a,b) returns true if the time a is after time b.
 *
 * Do this with "<0" and ">=0" to only test the sign of the result. A
 * good compiler would generate better code (and a really good compiler
 * wouldn't care). Gcc is currently neither.
 */
#define time_after(a,b)		\
	(typecheck(unsigned long, a) && \
	 typecheck(unsigned long, b) && \
	 ((long)(b) - (long)(a) < 0))
#define time_before(a,b)	time_after(b,a)

#define time_after_eq(a,b)	\
	(typecheck(unsigned long, a) && \
	 typecheck(unsigned long, b) && \
	 ((long)(a) - (long)(b) >= 0))
#define time_before_eq(a,b)	time_after_eq(b,a)

/*
 * Have the 32 bit jiffies value wrap 5 minutes after boot
 * so jiffies wrap bugs show up earlier.
 */
#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))

/*
 * Change timeval to jiffies, trying to avoid the
 * most obvious overflows..
 *
 * And some not so obvious.
 *
 * Note that we don't want to return MAX_LONG, because
 * for various timeout reasons we often end up having
 * to wait "jiffies+1" in order to guarantee that we wait
 * at _least_ "jiffies" - so "jiffies+1" had better still
 * be positive.
 */
#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1)

/*
 * We want to do realistic conversions of time so we need to use the same
 * values the update wall clock code uses as the jiffies size.  This value
 * is: TICK_NSEC (which is defined in timex.h).  This
 * is a constant and is in nanoseconds.  We will used scaled math
 * with a set of scales defined here as SEC_JIFFIE_SC,  USEC_JIFFIE_SC and
 * NSEC_JIFFIE_SC.  Note that these defines contain nothing but
 * constants and so are computed at compile time.  SHIFT_HZ (computed in
 * timex.h) adjusts the scaling for different HZ values.

 * Scaled math???  What is that?
 *
 * Scaled math is a way to do integer math on values that would,
 * otherwise, either overflow, underflow, or cause undesired div
 * instructions to appear in the execution path.  In short, we "scale"
 * up the operands so they take more bits (more precision, less
 * underflow), do the desired operation and then "scale" the result back
 * by the same amount.  If we do the scaling by shifting we avoid the
 * costly mpy and the dastardly div instructions.

 * Suppose, for example, we want to convert from seconds to jiffies
 * where jiffies is defined in nanoseconds as NSEC_PER_JIFFIE.  The
 * simple math is: jiff = (sec * NSEC_PER_SEC) / NSEC_PER_JIFFIE; We
 * observe that (NSEC_PER_SEC / NSEC_PER_JIFFIE) is a constant which we
 * might calculate at compile time, however, the result will only have
 * about 3-4 bits of precision (less for smaller values of HZ).
 *
 * So, we scale as follows:
 * jiff = (sec) * (NSEC_PER_SEC / NSEC_PER_JIFFIE);
 * jiff = ((sec) * ((NSEC_PER_SEC * SCALE)/ NSEC_PER_JIFFIE)) / SCALE;
 * Then we make SCALE a power of two so:
 * jiff = ((sec) * ((NSEC_PER_SEC << SCALE)/ NSEC_PER_JIFFIE)) >> SCALE;
 * Now we define:
 * #define SEC_CONV = ((NSEC_PER_SEC << SCALE)/ NSEC_PER_JIFFIE))
 * jiff = (sec * SEC_CONV) >> SCALE;
 *
 * Often the math we use will expand beyond 32-bits so we tell C how to
 * do this and pass the 64-bit result of the mpy through the ">> SCALE"
 * which should take the result back to 32-bits.  We want this expansion
 * to capture as much precision as possible.  At the same time we don't
 * want to overflow so we pick the SCALE to avoid this.  In this file,
 * that means using a different scale for each range of HZ values (as
 * defined in timex.h).
 *
 * For those who want to know, gcc will give a 64-bit result from a "*"
 * operator if the result is a long long AND at least one of the
 * operands is cast to long long (usually just prior to the "*" so as
 * not to confuse it into thinking it really has a 64-bit operand,
 * which, buy the way, it can do, but it take more code and at least 2
 * mpys).

 * We also need to be aware that one second in nanoseconds is only a
 * couple of bits away from overflowing a 32-bit word, so we MUST use
 * 64-bits to get the full range time in nanoseconds.

 */

/*
 * Here are the scales we will use.  One for seconds, nanoseconds and
 * microseconds.
 *
 * Within the limits of cpp we do a rough cut at the SEC_JIFFIE_SC and
 * check if the sign bit is set.  If not, we bump the shift count by 1.
 * (Gets an extra bit of precision where we can use it.)
 * We know it is set for HZ = 1024 and HZ = 100 not for 1000.
 * Haven't tested others.

 * Limits of cpp (for #if expressions) only long (no long long), but
 * then we only need the most signicant bit.
 */

#define SEC_JIFFIE_SC (31 - SHIFT_HZ)
#if !((((NSEC_PER_SEC << 2) / TICK_NSEC) << (SEC_JIFFIE_SC - 2)) & 0x80000000)
#undef SEC_JIFFIE_SC
#define SEC_JIFFIE_SC (32 - SHIFT_HZ)
#endif
#define NSEC_JIFFIE_SC (SEC_JIFFIE_SC + 29)
#define USEC_JIFFIE_SC (SEC_JIFFIE_SC + 19)
#define SEC_CONVERSION ((unsigned long)((((u64)NSEC_PER_SEC << SEC_JIFFIE_SC) +\
                                TICK_NSEC -1) / (u64)TICK_NSEC))

#define NSEC_CONVERSION ((unsigned long)((((u64)1 << NSEC_JIFFIE_SC) +\
                                        TICK_NSEC -1) / (u64)TICK_NSEC))
#define USEC_CONVERSION  \
                    ((unsigned long)((((u64)NSEC_PER_USEC << USEC_JIFFIE_SC) +\
                                        TICK_NSEC -1) / (u64)TICK_NSEC))
/*
 * USEC_ROUND is used in the timeval to jiffie conversion.  See there
 * for more details.  It is the scaled resolution rounding value.  Note
 * that it is a 64-bit value.  Since, when it is applied, we are already
 * in jiffies (albit scaled), it is nothing but the bits we will shift
 * off.
 */
#define USEC_ROUND (u64)(((u64)1 << USEC_JIFFIE_SC) - 1)
#define USEC_ROUND2 (u64)(((u64)1 << (USEC_JIFFIE_SC - 1)))
/*
 * The maximum jiffie value is (MAX_INT >> 1).  Here we translate that
 * into seconds.  The 64-bit case will overflow if we are not careful,
 * so use the messy SH_DIV macro to do it.  Still all constants.
 */
#if BITS_PER_LONG < 64
# define MAX_SEC_IN_JIFFIES \
	(long)((u64)((u64)MAX_JIFFY_OFFSET * TICK_NSEC) / NSEC_PER_SEC)
#else	/* take care of overflow on 64 bits machines */
# define MAX_SEC_IN_JIFFIES \
	(SH_DIV((MAX_JIFFY_OFFSET >> SEC_JIFFIE_SC) * TICK_NSEC, NSEC_PER_SEC, 1) - 1)

#endif

/*
 * Convert jiffies to milliseconds and back.
 *
 * Avoid unnecessary multiplications/divisions in the
 * two most common HZ cases:
 */
static inline unsigned int jiffies_to_msecs(const unsigned long j)
{
#if HZ <= 1000 && !(1000 % HZ)
	return (1000 / HZ) * j;
#elif HZ > 1000 && !(HZ % 1000)
	return (j + (HZ / 1000) - 1)/(HZ / 1000);
#else
	return (j * 1000) / HZ;
#endif
}

static inline unsigned int jiffies_to_usecs(const unsigned long j)
{
#if HZ <= 1000 && !(1000 % HZ)
	return (1000000 / HZ) * j;
#elif HZ > 1000 && !(HZ % 1000)
	return (j*1000 + (HZ - 1000))/(HZ / 1000);
#else
	return (j * 1000000) / HZ;
#endif
}

static inline unsigned long msecs_to_jiffies(const unsigned int m)
{
	if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET))
		return MAX_JIFFY_OFFSET;
#if HZ <= 1000 && !(1000 % HZ)
	return (m + (1000 / HZ) - 1) / (1000 / HZ);
#elif HZ > 1000 && !(HZ % 1000)
	return m * (HZ / 1000);
#else
	return (m * HZ + 999) / 1000;
#endif
}

static inline unsigned long usecs_to_jiffies(const unsigned int u)
{
	if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET))
		return MAX_JIFFY_OFFSET;
#if HZ <= 1000 && !(1000 % HZ)
	return (u + (1000000 / HZ) - 1000) / (1000000 / HZ);
#elif HZ > 1000 && !(HZ % 1000)
	return u * (HZ / 1000000);
#else
	return (u * HZ + 999999) / 1000000;
#endif
}

/*
 * The TICK_NSEC - 1 rounds up the value to the next resolution.  Note
 * that a remainder subtract here would not do the right thing as the
 * resolution values don't fall on second boundries.  I.e. the line:
 * nsec -= nsec % TICK_NSEC; is NOT a correct resolution rounding.
 *
 * Rather, we just shift the bits off the right.
 *
 * The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec
 * value to a scaled second value.
 */


/* Same for "timeval"
 *
 * Well, almost.  The problem here is that the real system resolution is
 * in nanoseconds and the value being converted is in micro seconds.
 * Also for some machines (those that use HZ = 1024, in-particular),
 * there is a LARGE error in the tick size in microseconds.

 * The solution we use is to do the rounding AFTER we convert the
 * microsecond part.  Thus the USEC_ROUND, the bits to be shifted off.
 * Instruction wise, this should cost only an additional add with carry
 * instruction above the way it was done above.
 */
static __inline__ unsigned long
timeval_to_jiffies(const struct timeval *value)
{
	unsigned long sec = value->tv_sec;
	long usec = value->tv_usec;

	if (sec >= MAX_SEC_IN_JIFFIES){
		sec = MAX_SEC_IN_JIFFIES;
		usec = 0;
	}
#if 0
	printf("usec * USEC_CONVERSION = %llx\n",
			(u64)usec * USEC_CONVERSION);
	printf("usec * USEC_CONVERSION + USEC_ROUND = %llx  >> %llx\n",
			(u64)usec * USEC_CONVERSION + USEC_ROUND,
			((u64)usec * USEC_CONVERSION + USEC_ROUND) >> USEC_JIFFIE_SC
			);
	printf("usec * USEC_CONVERSION + USEC_ROUND2 = %llx  "
			">> %llx  = %ld jiffies\n",
			(u64)usec * USEC_CONVERSION + USEC_ROUND2,
			((u64)usec * USEC_CONVERSION + USEC_ROUND2) >> USEC_JIFFIE_SC,
		(((u64)sec * SEC_CONVERSION) +
			(((u64)usec * USEC_CONVERSION + USEC_ROUND2) >>
			 (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC
			);
#endif

#define USE_PATCH 0
#if USE_PATCH
	return (((u64)sec * SEC_CONVERSION) +
		(((u64)usec * USEC_CONVERSION + USEC_ROUND2) >>
		 (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
#else
	return (((u64)sec * SEC_CONVERSION) +
		(((u64)usec * USEC_CONVERSION + USEC_ROUND) >>
		 (USEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC;
#endif
}
int main(int argc, char **argv)
{
	unsigned long jiffies;
	struct timeval tv;
	int i;

	tv.tv_sec = 0;
	for (i=0; i <= 100; i++) {
		tv.tv_usec = 10000 + i*10;

		jiffies = timeval_to_jiffies(&tv);
		printf("usec=%ld  jiffies = %lu\n",tv.tv_usec,jiffies);
	}
	return 0;
}

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)]
  2005-04-21  3:40   ` Steven Rostedt
@ 2005-04-21  8:51     ` Russell King
  2005-04-21 10:51       ` Steven Rostedt
  0 siblings, 1 reply; 12+ messages in thread
From: Russell King @ 2005-04-21  8:51 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: jdavis, Linus Torvalds, Andrew Morton, linux-kernel

On Wed, Apr 20, 2005 at 11:40:16PM -0400, Steven Rostedt wrote:
> Is 11 jiffies correct for 10ms?

Consider the 1 jiffy case.  How long does waiting one jiffy actually wait?

j=0            1              2
+--------------+--------------+--> t
 A     B      C D

If you start timing one jiffy from A, you're looking for j=1, so your
timer expires close to D and you have waited one jiffy.

If you start timing one jiffy from B, you're still looking for j=1.
Your timer expires at the same point (D) but you've waited less than
one jiffy.

If you start timing one jiffy from C, it's the same - expires at D.
This time, you've waited virtually no time at all.

The problem is that when you add a timer, you don't have any idea
which point you're going to be starting your timer at.

This is why we always round up to the next jiffy when we convert
times to jiffies - this ensures that you will get at _least_ the
timeout you requested, which is in itself a very important
guarantee.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)]
  2005-04-21  8:51     ` Russell King
@ 2005-04-21 10:51       ` Steven Rostedt
  2005-04-21 14:58         ` Linus Torvalds
  0 siblings, 1 reply; 12+ messages in thread
From: Steven Rostedt @ 2005-04-21 10:51 UTC (permalink / raw)
  To: Russell King; +Cc: jdavis, Linus Torvalds, Andrew Morton, linux-kernel

On Thu, 2005-04-21 at 09:51 +0100, Russell King wrote:
[...]
> The problem is that when you add a timer, you don't have any idea
> which point you're going to be starting your timer at.
> 
> This is why we always round up to the next jiffy when we convert
> times to jiffies - this ensures that you will get at _least_ the
> timeout you requested, which is in itself a very important
> guarantee.
> 

Thanks, I forgot about the guarantee of "at least" the time requested.
I took this on because I noticed this in a driver I wrote. With the user
passing in a timeval for a periodic condition. I noticed that this would
drift quite a bit. I guess I need to write my own timeval_to_jiffies
conversion so that i remove the added jiffy. For this case, I actually
want a true rounded value to the closest jiffy.

Thanks again,

-- Steve



^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)]
  2005-04-21 10:51       ` Steven Rostedt
@ 2005-04-21 14:58         ` Linus Torvalds
  2005-04-21 15:34           ` Steven Rostedt
  2005-04-21 15:53           ` Chris Friesen
  0 siblings, 2 replies; 12+ messages in thread
From: Linus Torvalds @ 2005-04-21 14:58 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: Russell King, jdavis, Andrew Morton, linux-kernel



On Thu, 21 Apr 2005, Steven Rostedt wrote:
> 
> Thanks, I forgot about the guarantee of "at least" the time requested.
> I took this on because I noticed this in a driver I wrote. With the user
> passing in a timeval for a periodic condition. I noticed that this would
> drift quite a bit.

Your user is doing things wrong. If he wants a non-drifting clock, he 
should look at _realtime_ and then always re-calculate the "how long do I 
want to sleep" from that. Because even if the kernel was able to do all 
offsets with nanosecond precision and wake you up _exactly_, you'd still 
be drifting because of the time spent in between calls (and scheduling 
events etc).

>	 I guess I need to write my own timeval_to_jiffies
> conversion so that i remove the added jiffy. For this case, I actually
> want a true rounded value to the closest jiffy.

No, if you're looking at reliable wall-clock time, you really need to use
wall-clock, not successive time offsets. The time offsets will always
drift: you can make the drift small enough that your particular
application doesn't happen to care (or, quite often - make it drift in a
_direction_ you don't happen to care about), but it's still wrong.

If you calculate the expected timeout from the time-of-day in the caller,
your drift not only goes away, but you'll actually be able to handle 
things like "oops, the machine is under load so I missed an event".

Yes, it gets slightly more complicated (and a _lot_ more complicated if
your app needs to do something special for the missed case, like dropping
data and re-syncing, which is common in things like video or sound
streaming), but the fact is, it's just the right thing to do.

		Linus

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)]
  2005-04-21 14:58         ` Linus Torvalds
@ 2005-04-21 15:34           ` Steven Rostedt
  2005-04-21 15:53           ` Chris Friesen
  1 sibling, 0 replies; 12+ messages in thread
From: Steven Rostedt @ 2005-04-21 15:34 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Russell King, jdavis, Andrew Morton, linux-kernel

On Thu, 2005-04-21 at 07:58 -0700, Linus Torvalds wrote:
> 
> On Thu, 21 Apr 2005, Steven Rostedt wrote:
> > 
> > Thanks, I forgot about the guarantee of "at least" the time requested.
> > I took this on because I noticed this in a driver I wrote. With the user
> > passing in a timeval for a periodic condition. I noticed that this would
> > drift quite a bit.
> 
> Your user is doing things wrong. If he wants a non-drifting clock, he 
> should look at _realtime_ and then always re-calculate the "how long do I 
> want to sleep" from that. Because even if the kernel was able to do all 
> offsets with nanosecond precision and wake you up _exactly_, you'd still 
> be drifting because of the time spent in between calls (and scheduling 
> events etc).
> 

It's even stranger than this.  I'm working on a custom kernel for a
customer based off of Ingo's RT patches. They want to be able to make a
process run for a percentage of the CPU. So you can make a process run
10 jiffies out of every 100. Using Ingo's RT patch helps to keep the
latencies down from interrupts.


> >	 I guess I need to write my own timeval_to_jiffies
> > conversion so that i remove the added jiffy. For this case, I actually
> > want a true rounded value to the closest jiffy.
> 
> No, if you're looking at reliable wall-clock time, you really need to use
> wall-clock, not successive time offsets. The time offsets will always
> drift: you can make the drift small enough that your particular
> application doesn't happen to care (or, quite often - make it drift in a
> _direction_ you don't happen to care about), but it's still wrong.
> 

The customer understands that the precision would be in jiffies, and
hopefully better, when/if I can get the high res timers patch working
with this as well.  The problem arises with the API using timeval to
determine the percentage and period. With the added jiffy, the
calculations are wrong.
  
> If you calculate the expected timeout from the time-of-day in the caller,
> your drift not only goes away, but you'll actually be able to handle 
> things like "oops, the machine is under load so I missed an event".
> 

Hopefully there is never a missed event (this is checked for though),
since the process would be running at the highest priority. It's OK for
the process to come in late, as long as it runs the required amount
within the given period.

> Yes, it gets slightly more complicated (and a _lot_ more complicated if
> your app needs to do something special for the missed case, like dropping
> data and re-syncing, which is common in things like video or sound
> streaming), but the fact is, it's just the right thing to do.

This project is much more complicated than what I've mentioned here, but
it shows what I need. Currently we are using jiffies as the timer, but
eventually we will be using a better source and the whole
timeval_to_jiffies conversion wouldn't matter.

-- Steve


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)]
  2005-04-21 14:58         ` Linus Torvalds
  2005-04-21 15:34           ` Steven Rostedt
@ 2005-04-21 15:53           ` Chris Friesen
  2005-04-21 16:13             ` Linus Torvalds
  1 sibling, 1 reply; 12+ messages in thread
From: Chris Friesen @ 2005-04-21 15:53 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Steven Rostedt, Russell King, jdavis, Andrew Morton, linux-kernel

Linus Torvalds wrote:

> If you calculate the expected timeout from the time-of-day in the caller,
> your drift not only goes away, but you'll actually be able to handle 
> things like "oops, the machine is under load so I missed an event".

Does mainline have a high precision monotonic wallclock that is not 
affected by time-of-day changes?  Something like "nano/mico seconds 
since boot"?

Chris

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)]
  2005-04-21 15:53           ` Chris Friesen
@ 2005-04-21 16:13             ` Linus Torvalds
  2005-04-22  2:54               ` Edgar Toernig
  0 siblings, 1 reply; 12+ messages in thread
From: Linus Torvalds @ 2005-04-21 16:13 UTC (permalink / raw)
  To: Chris Friesen
  Cc: Steven Rostedt, Russell King, jdavis, Andrew Morton, linux-kernel



On Thu, 21 Apr 2005, Chris Friesen wrote:
> 
> Does mainline have a high precision monotonic wallclock that is not 
> affected by time-of-day changes?  Something like "nano/mico seconds 
> since boot"?

High precision? No. We do have "jiffies since boot". We don't actually
expose it anywhere, although you _can_ get it's "standardized version",
aka "centi-seconds per boot" from things like /proc/uptime.

(Not high-performance, but such an interface _could_ be. It's one of the
few things we could trivially map into the "system call page", and have
accessible to user space with just a simple read - faster even than the
"fast gettimeofday" implementations).

The thing is, most people who want the time of day want a real time with
some precision. Getting "approximate uptime" really really _really_ fast
might be useful for some things, but I don't know how many.

			Linus

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4  (1 extra tick)]
  2005-04-21 16:13             ` Linus Torvalds
@ 2005-04-22  2:54               ` Edgar Toernig
  0 siblings, 0 replies; 12+ messages in thread
From: Edgar Toernig @ 2005-04-22  2:54 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Chris Friesen, Steven Rostedt, Russell King, jdavis,
	Andrew Morton, linux-kernel

On Thu, 21 Apr 2005, Chris Friesen wrote:
>
> Does mainline have a high precision monotonic wallclock that is not 
> affected by time-of-day changes?  Something like "nano/mico seconds 
> since boot"?

On newer kernels with the posix timers (I think 2.6 - not sure though)
there's clock_gettime(CLOCK_MONOTONIC, ...).

Linus Torvalds wrote:
>
> Getting "approximate uptime" really really _really_ fast
> might be useful for some things, but I don't know how many.

I bet most users of gettimeofday actually want a strictly monotonic
increasing clock where the actual base time is irrelevant.  Just strace
some apps - those issuing hundreds and thousands of gettimeofday calls
are most likely in this class.  Those who only call gettimeofday once
or twice or the ones that really want the wall clock time.

How often does the kernel use jiffies (the monotonic clock) and how often
xtime (the wall clock)?

Ciao, ET.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)
  2005-04-08 17:39 Odd Timer behavior in 2.6 vs 2.4 (1 extra tick) jdavis
  2005-04-08 22:19 ` Steven Rostedt
  2005-04-21  2:58 ` [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)] Steven Rostedt
@ 2005-04-29 21:28 ` Nish Aravamudan
  2 siblings, 0 replies; 12+ messages in thread
From: Nish Aravamudan @ 2005-04-29 21:28 UTC (permalink / raw)
  To: jdavis@accessline.com; +Cc: linux-kernel

On 4/8/05, jdavis@accessline.com <jdavis@accessline.com> wrote:
> 
> 
> Hello,
> 
> I've created a pretty straight forward timer using setitimer, and noticed
> some odd differences between 2.4 and 2.6, I wonder if I could get a
> clarification if this is the way it should work, or if I should continue to
> try to "fix" it.
> 
> I create a RealTime Thread( SCHED_FIFO, maxPriority-1 ) (also tried
> SCHED_RR) ...
> 
> that creates a timer ...setitimer( ITIMER_REAL, SIGALRM) with a 10 milli
> period. (I've also tried timer_create with CLOCK_REALTIME and SIGRTMIN)
> 
> and then the thread does a sem_wait() on a semaphore.
> 
> the signal handler does a sem_post() .
> 
> on 2.4.X the (idle) worst case latency is ~40 microseconds,
> on 2.6.X the (idle) latency is about the same plus 1 tick of the scheduler
> ~1000 micro seconds... Always.. Every time.
> So to work around this on 2.6 I simply subtract 1 millisecond from my timer
> as a fudge factor and everything works as expected.

There are several problems with the current soft-timer subsystem in
this area. Basically, the actual tick rate is slightly more than once
per millisecond, which requires adding one jiffy to compensate.
Additionally, one can't be sure ``where'' one is within a tick, so
another jiffy has to be added, to make sure the timer does not go off
early. sys_nanosleep() does something similar.

I will be submitting an RFC based on John Stultz's timeofday rework
which tries to resolve these issues.

Thanks,
Nish

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2005-04-29 21:30 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-04-08 17:39 Odd Timer behavior in 2.6 vs 2.4 (1 extra tick) jdavis
2005-04-08 22:19 ` Steven Rostedt
2005-04-21  2:58 ` [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)] Steven Rostedt
2005-04-21  3:40   ` Steven Rostedt
2005-04-21  8:51     ` Russell King
2005-04-21 10:51       ` Steven Rostedt
2005-04-21 14:58         ` Linus Torvalds
2005-04-21 15:34           ` Steven Rostedt
2005-04-21 15:53           ` Chris Friesen
2005-04-21 16:13             ` Linus Torvalds
2005-04-22  2:54               ` Edgar Toernig
2005-04-29 21:28 ` Odd Timer behavior in 2.6 vs 2.4 (1 extra tick) Nish Aravamudan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox