Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

nanosleep() resolution

491 views
Skip to first unread message

Rahul Sood

unread,
Jan 28, 2003, 8:47:32 PM1/28/03
to
the nanosleep() call supposedly makes the caller sleep for the
specified time interval in nanoseconds. However I tried it on solaris
5.8 and Linux 2.2 and found that if nanosleep() is called with time
interval < 10 millisec (10^7 ns) it still sleeps for 10ms. Is this the
maximum sleep resolution ? Are there other ways of sleeping for
smaller intervals, while having minimal CPU overhead ? I also tried
the select() call, passing it different timeouts < 10ms but it
returned only after 10ms had elapsed. Is this a system hard limit on
the minimum sleep time ? I understood that the limit is determined
only by the machine clock, which was 330 MHz (3ns) on these systems.

-Rahul Sood
rs...@panix.com

Alex Pavloff

unread,
Jan 28, 2003, 9:04:37 PM1/28/03
to

Check in (I think for 2.2) linux/sched.h

#define HZ 100

The linux scheduler runs at a 10ms interval. This means that when you
sleep, the soonest that you be scheduled to run again is, as you see,
10ms.

Now, you can increase this number, but the more that timer interrupt
is called, the more cpu time the kernel will get and the less time
your processes will get (among other things).
--
Alex Pavloff - remove BLAH to email
Software Engineer, Eason Technology

Shaun Clowes

unread,
Jan 28, 2003, 9:40:33 PM1/28/03
to

> Check in (I think for 2.2) linux/sched.h
>
> #define HZ 100
>
> The linux scheduler runs at a 10ms interval. This means that when you
> sleep, the soonest that you be scheduled to run again is, as you see,
> 10ms.
>
> Now, you can increase this number, but the more that timer interrupt
> is called, the more cpu time the kernel will get and the less time
> your processes will get (among other things).

The more recent 2.4 kernels have the timer running at 512Hz so this should
help. Basically the only way you'll get sleep times of the length you want
is to busy loop, though obviously you could well be pre-empted and end up
having to cop the 10ms whether you like it or not.

Cheers,
Shaun

Roland Mainz

unread,
Jan 28, 2003, 11:31:21 PM1/28/03
to
Rahul Sood wrote:

> the nanosleep() call supposedly makes the caller sleep for the
> specified time interval in nanoseconds. However I tried it on solaris
> 5.8 and Linux 2.2 and found that if nanosleep() is called with time
> interval < 10 millisec (10^7 ns) it still sleeps for 10ms. Is this the
> maximum sleep resolution ?

In Solaris it depends on the kernel configuration. You can either have
10ms resolution or ~~1ms resolution - see URL below...

> Are there other ways of sleeping for
> smaller intervals, while having minimal CPU overhead ? I also tried
> the select() call, passing it different timeouts < 10ms but it
> returned only after 10ms had elapsed. Is this a system hard limit on
> the minimum sleep time ? I understood that the limit is determined
> only by the machine clock, which was 330 MHz (3ns) on these systems.

If I recall it correctly setting the Solaris kernel tuneable
"hires_tick" (see
http://docs.sun.com/db/doc/816-0607/6m735r5f9?q=hires_tick&a=view)
should give you want you want... :)

----

Bye,
Roland

--
__ . . __
(o.\ \/ /.o) Roland...@informatik.med.uni-giessen.de
\__\/\/__/ gis...@informatik.med.uni-giessen.de
/O /==\ O\ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
(;O/ \/ \O;) TEL +49 641 99-41370 FAX +49 641 99-41359

Casper H.S. Dik

unread,
Jan 29, 2003, 3:56:37 AM1/29/03
to
rs...@panix.com (Rahul Sood) writes:

The Solaris kernel has a tunable which allows you to set the kernel
clock frequency to 1000Hz (this effects naosleep, interval timers, poll
[and therefor select] and such). Since select() is implemented in
terms of poll() in Solaris, its resolution can never be better than
1ms.

Privileged process can use arbitrary precision timers (if the hardware
supports them).


The solaris FAQ says:

7.5) How can I have a clock resolution better than 10ms?

Starting with Solaris 2.6, this can be achieved with the following
entry in /etc/system:

set hires_tick = 1

This will set the system hz value to 1000.

In principle, you can also set "hz" directly, but that is not supported
nor recommended:

* Get 0.1 ms clock resolution/timer granularity
set hz = 10000

Solaris 8 introduces the cyclic subsystem; this allows for timers
of much better granularity without burdening the system with a high
interrupt rate. High resolution timers are available to root
only using timer_create(3rt) with a clock_id of CLOCK_HIGHRES.

--- end of excerpt from the FAQ

The most recently posted version of the FAQ is available from
<http://www.science.uva.nl/pub/solaris/solaris2/>
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

Jonathan Adams

unread,
Jan 29, 2003, 5:26:40 AM1/29/03
to
rs...@panix.com (Rahul Sood) wrote in message news:<25edd3c2.03012...@posting.google.com>...

On both Linux and Solaris, the resolution of nanosleep(2) is limited
by the system "tick", which defaults to 100HZ (10ms) on Solaris (and
also on the Linux kernel you are running). On Solaris, the same
mechanism handles select()/poll() timeouts.

This is a design decision left over from the earliest implementations
of Unix.

However, in Solaris 8 and above, you can get timers of much higher
accuracy and resolution by using timer_create(3RT) with a clock_id
of CLOCK_HIGHRES. This allows for arbitrary resolution timers that
are both low-latency and low-jitter, (both are easily <100
microseconds) without significant processor overhead (for reasonable
frequencies, at least)

There are caveats, however:

1. You need to be running as root to create CLOCK_HIGHRES timers.
2. They are *timers*, which means they fire periodically (as
opposed to nanosleep(), which sleeps for a period, then returns).
3. They fire by sending a signal to your process, which means that
using them is much more complicated than just calling
nanosleep() (your handler can only use async-signal-safe
routines, etc.)
4. Remember that processing these timers takes time -- if you use
too high of a frequency, the CPU will spend all of its time
processing your timer, and you won't be able to get any actual
work done.
5. CLOCK_HIGHRES only has accurate timing on Ultrasparc processors.
On x86, you will get the correct *number* of firings, but they
will be clumped at 10ms intervals.
6. To *really* achieve the supported latency and jitter, your
process will need to be in the real-time scheduling class, and
will have to be designed with that in mind. You'll probably
also want to be in a processor set of your own, with interrupts
disabled. (For most applications, of course, this is overkill)

- jonathan

Alex Pavloff

unread,
Jan 29, 2003, 1:24:01 PM1/29/03
to
On Wed, 29 Jan 2003 02:40:33 GMT, "Shaun Clowes"
<del...@zero.spam.progsoc.org> wrote:

>The more recent 2.4 kernels have the timer running at 512Hz so this should
>help. Basically the only way you'll get sleep times of the length you want
>is to busy loop, though obviously you could well be pre-empted and end up
>having to cop the 10ms whether you like it or not.

My 2.4.20 has in param.h

#define HZ 100

for most architectures (including i386).

Is this not the timer or is it 2.6 that the HZ value changed in?

Neil Zanella

unread,
Jan 29, 2003, 2:20:45 PM1/29/03
to

On Wed, 29 Jan 2003, Alex Pavloff wrote:

> On Wed, 29 Jan 2003 02:40:33 GMT, "Shaun Clowes"
> <del...@zero.spam.progsoc.org> wrote:
>
> >The more recent 2.4 kernels have the timer running at 512Hz so this should
> >help. Basically the only way you'll get sleep times of the length you want
> >is to busy loop, though obviously you could well be pre-empted and end up
> >having to cop the 10ms whether you like it or not.
>
> My 2.4.20 has in param.h
>
> #define HZ 100

Does this mean that on a processor running at 1GHz the least amount of
time a process can sleep for is 10 nanoseconds?

BTW, I think the proper way to determine the number of clock ticks per
second from a POSIX program is to use sysconf(3) as follows:

#include <stdio.h>
#include <unistd.h>

int main()
{
printf("%d\n", sysconf(_SC_CLK_TCK));
}

Regards,

Neil

Brett E. Dufault

unread,
Jan 29, 2003, 4:48:10 PM1/29/03
to
On Wednesday 29 January 2003 1:24 pm, Alex Pavloff wrote:

> On Wed, 29 Jan 2003 02:40:33 GMT, "Shaun Clowes"
> <del...@zero.spam.progsoc.org> wrote:
>
>>The more recent 2.4 kernels have the timer running at 512Hz so this should
>>help. Basically the only way you'll get sleep times of the length you want
>>is to busy loop, though obviously you could well be pre-empted and end up
>>having to cop the 10ms whether you like it or not.
>
> My 2.4.20 has in param.h
>
> #define HZ 100
>
> for most architectures (including i386).
>
> Is this not the timer or is it 2.6 that the HZ value changed in?

It's a feature of the 2.5 Linux kernels, but Red Hat back-ported this into
some of their 2.4 kernel releases. Possibly Shaun was looking at the source
for a Red Hat Linux 2.4 kernel. (RH kernels are usually heavily modified
from the "vanilla" Linux kernel sources.)

HTH,
--Brett

--
There are no fnords in my email address...

Message has been deleted

Alex Pavloff

unread,
Jan 29, 2003, 5:28:14 PM1/29/03
to
On Wed, 29 Jan 2003 21:48:10 GMT, "Brett E. Dufault"
<bduf...@FNORD.ehugin.FNORD.com> wrote:

>It's a feature of the 2.5 Linux kernels, but Red Hat back-ported this into
>some of their 2.4 kernel releases. Possibly Shaun was looking at the source
>for a Red Hat Linux 2.4 kernel. (RH kernels are usually heavily modified
>from the "vanilla" Linux kernel sources.)

Ahh, thats it. In my Redhat 8.0 sources, the HZ value is configurable
during kernel configuration and is coud be set to some other value.
Interestingly, _SC_CLK_TCK still reports "100", but various people
have posted that the HZ value has been set to 512.

Shaun Clowes

unread,
Jan 29, 2003, 10:09:02 PM1/29/03
to
> >It's a feature of the 2.5 Linux kernels, but Red Hat back-ported this
into
> >some of their 2.4 kernel releases. Possibly Shaun was looking at the
source
> >for a Red Hat Linux 2.4 kernel. (RH kernels are usually heavily modified
> >from the "vanilla" Linux kernel sources.)

I was indeed, apologies on that one.

> Ahh, thats it. In my Redhat 8.0 sources, the HZ value is configurable
> during kernel configuration and is coud be set to some other value.
> Interestingly, _SC_CLK_TCK still reports "100", but various people
> have posted that the HZ value has been set to 512.

Yeah, I suspect this is a deliberate move to try to retain compatibility
with userland apps that expect the timer to be 100Hz. However it can be very
annoying since it results in the ticks returned by the times() routine
looping on a value much smaller than it should (it's still calculated from
the 32 bit version of the kernel hz counter unfortunately).

Cheers,
Shaun


David Schwartz

unread,
Jan 30, 2003, 1:25:07 AM1/30/03
to

Depending upon *which* "param.h" file you're talking about, this is the
user space value of HZ, not the kernel's timer version.

DS

Valentin Nechayev

unread,
Jan 30, 2003, 3:58:43 AM1/30/03
to
>>> Neil Zanella wrote:

> >>The more recent 2.4 kernels have the timer running at 512Hz so this should
> >>help. Basically the only way you'll get sleep times of the length you want
> >>is to busy loop, though obviously you could well be pre-empted and end up
> >>having to cop the 10ms whether you like it or not.
>> My 2.4.20 has in param.h
>> #define HZ 100

NZ> Does this mean that on a processor running at 1GHz the least amount of
NZ> time a process can sleep for is 10 nanoseconds?

No, of course. For 10 ns, you have to get timer hardware which can issue
next interrupt in speficied moment with granulation up to a few nanoseconds.
(Not every K nanoseconds! This will simply paralyse the work.)
None PC, at least, has such hardware; the fastest timer which can generate
interrupts in required moments is i8254 with 1193181.81/3 == 397727 Hz,
i.e. in 2.5us (2.5 microseconds) intervals. Possibly, another architectures
can have features for this.
But none time-sharing OS without realtime features can do this.

NZ> BTW, I think the proper way to determine the number of clock ticks per
NZ> second from a POSIX program is to use sysconf(3) as follows:

Of course. But this is the proper way for program which is already compiled.
System admin has no strong reason to get this data such portable way.


-netch-

Casper H.S. Dik

unread,
Jan 30, 2003, 4:18:15 AM1/30/03
to
"Shaun Clowes" <del...@zero.spam.progsoc.org> writes:

>Yeah, I suspect this is a deliberate move to try to retain compatibility
>with userland apps that expect the timer to be 100Hz. However it can be very
>annoying since it results in the ticks returned by the times() routine
>looping on a value much smaller than it should (it's still calculated from
>the 32 bit version of the kernel hz counter unfortunately).


And what is the value of the CLK_TCK #define?

If you can't do clock_t * CLK_TCK to get an actual time, I'd say
that's a bug.

Casper

Alex Pavloff

unread,
Jan 30, 2003, 1:17:35 PM1/30/03
to

the linux kernel include/asm/param.h,

Even the include/linux/param.h just goes and includes the asm/param.h,
and the remaining param.h files appear to be driver specific. Linux
2.4.20 and the Redhat-patched 2.4.18 are the same this time.

Which param.h are you talking about that has "userspace" value?

Shaun Clowes

unread,
Feb 2, 2003, 5:32:06 PM2/2/03
to
> >Yeah, I suspect this is a deliberate move to try to retain compatibility
> >with userland apps that expect the timer to be 100Hz. However it can be
very
> >annoying since it results in the ticks returned by the times() routine
> >looping on a value much smaller than it should (it's still calculated
from
> >the 32 bit version of the kernel hz counter unfortunately).
>
> And what is the value of the CLK_TCK #define?

Always 100Hz, though personally I don't use that define, sysconf() makes
more sense.

> If you can't do clock_t * CLK_TCK to get an actual time, I'd say
> that's a bug.

You can, but that value will loop after some short amount of time (and thus
the time will be wrong).

Cheers,
Shaun


Casper H.S. Dik

unread,
Feb 2, 2003, 6:08:00 PM2/2/03
to
"Shaun Clowes" <del...@zero.spam.progsoc.org> writes:


>> If you can't do clock_t * CLK_TCK to get an actual time, I'd say
>> that's a bug.

>You can, but that value will loop after some short amount of time (and thus
>the time will be wrong).

That's not my point; "clock_t" ticks in CLK_TCK units and my impression
was that clock_t was ticking faster but CLK_TCK was unchanged.

Anyway, the 'short time' is 248 days for 100Hz and 24.8 for 1000.

Shaun Clowes

unread,
Feb 2, 2003, 7:58:41 PM2/2/03
to
> >> If you can't do clock_t * CLK_TCK to get an actual time, I'd say
> >> that's a bug.
>
> >You can, but that value will loop after some short amount of time (and
thus
> >the time will be wrong).
>
> That's not my point; "clock_t" ticks in CLK_TCK units and my impression
> was that clock_t was ticking faster but CLK_TCK was unchanged.

Sorry if I gave that impression, the userland view of a clock tick remains
100Hz and the timer is represented as 100Hz, calculations work as expected.
However the kernelland timer is stored at a 512Hz interval (I'm talking
Linux here, I consider this behaviour to be a bug) and then transformed into
100Hz when requested. Thus the kernel timer loops every 97.1 (or so days)
even though logic would suggest the clock should only loop every 497.1 days.

Cheers,
Shaun

0 new messages