2005-04-08 17:40:24

by jdavis

[permalink] [raw]
Subject: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)



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


2005-04-08 22:23:37

by Steven Rostedt

[permalink] [raw]
Subject: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)

On Fri, 2005-04-08 at 10:39 -0700, [email protected] 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


2005-04-21 02:58:51

by Steven Rostedt

[permalink] [raw]
Subject: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)]

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, [email protected] 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
> -

2005-04-21 03:42:22

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)]

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


Attachments:
jiffies.c (13.03 kB)

2005-04-21 08:53:10

by Russell King

[permalink] [raw]
Subject: Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)]

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

2005-04-21 10:52:22

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)]

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


2005-04-21 14:57:05

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)]



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

2005-04-21 15:35:22

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)]

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

2005-04-21 15:54:57

by Chris Friesen

[permalink] [raw]
Subject: Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)]

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

2005-04-21 16:13:36

by Linus Torvalds

[permalink] [raw]
Subject: Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)]



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

2005-04-22 02:55:08

by Edgar Toernig

[permalink] [raw]
Subject: Re: [PATCH] Bad rounding in timeval_to_jiffies [was: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)]

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.

2005-04-29 21:30:01

by Nish Aravamudan

[permalink] [raw]
Subject: Re: Odd Timer behavior in 2.6 vs 2.4 (1 extra tick)

On 4/8/05, [email protected] <[email protected]> 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