Skip to contentSkip to conversation

usleep

DISCUSSION Lee Chin 8 participants 14 messages Jun 11, 2003 – Jun 13, 2003 1 message not in the archive

lore
Share & tools
lore

Lee Chin

author
#0 lore raw

I would think the following code would wait for 1 second each itteration before printing hello, but it waits way too long. Replacing the for loop body with a usleep(1000000) works great... what am I missing here?

Thanks
Lee

#include <unistd.h>

int main()

{
    while (1)
    {
        int i;

        printf("hello\n");
        for(i = 0; i < 50; i++)
        {
            usleep(1000);
        }

    }

}

Signature · 9 lines
__________________________________________________________
Sign-up for your own FREE Personalized E-mail at Mail.com
http://www.mail.com/?sr=signup

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs
#1 lore raw

for the #include statemen I assume you are using some sort of C languagbe (even C, C++ or C#) Well... my man of usleep says that it makes the system wait for any number of microseconds... make the maths.

Anyway... I really don't remebmer the value of a microsecond... I THINK it was something like "1 x 10 ^ -6" or something alike... (excuse the quotation aberration).

Quoted 23 lines · Lee Chin

I would think the following code would wait for 1 second each itteration before printing hello, but it waits way too long. Replacing the for loop body with a usleep(1000000) works great... what am I missing here?

Thanks
Lee

#include <unistd.h>

int main()

{
    while (1)
    {
        int i;

        printf("hello\n");
        for(i = 0; i < 50; i++)
        {
            usleep(1000);
        }

    }

}

Signature · 11 lines
Alan Bort
Linux Registered User 298277 -Country Manager- [http://counter.li.org]
[ http://www.linuxquestions.org ] Username: Ciccio
[ http://es.tldp.org ]
Ciccio.-

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs
#2 lore raw
In reply to Lee Chin
Quoted 2 lines · Lee Chin

I would think the following code would wait for 1 second each itteration before printing hello, but it waits way too long. Replacing the for loop body with a usleep(1000000) works great... what am I missing here?

Why would you expect this loop to wait 1 second? The usleep() call is for 1/1000 of a second, and you call it 50 times. 50/1000 seconds is hardly equal to 1 second.

In fact, compiled on my system, the loop as written does introduce just about a 1 second delay (30 iterations take 29 seconds, timed crudely with a wristwatch ... just right, since the initial printf() happens before the first loop run).

The ability of a system to resolve time is limited by the kernel and the hardware. If you read the man page for nanosleep() -- the POSIX replacement for usleep -- it specifies this limitation on that call's behavior. SO does the man page for usleep, though the writing here is fuzzier.

An i386 has a hardware timer that beats about 72 times per second, leaving me uncertain as to how accurate timings below 14 msec can be on this hardware using the kernel's internal timer.

If you need more accurate timing, you might want to look at using /dev/rtc (described in the kernel Documentation directory), which relies on IRQ8 and the system's real-time-clock hardware.

The test system I used, BTW, is a P-III 1 Ghz, and I ran the program with an ssh connection as STDOUT.

Quoted 19 lines

Thanks
Lee

#include <unistd.h>

int main()

{
    while (1)
    {
        int i;

        printf("hello\n");
        for(i = 0; i < 50; i++)
        {
            usleep(1000);
        }

    }
Quoted 1 line

}

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

A message that is not in the archive (sent off-list or not yet received): [email protected] .mcmaster.ca

#4 lore raw
Quoted 4 lines · Mark Hahn
Quoted 1 line

An i386 has a hardware timer that beats about 72 times per second, leaving

well, it has several hardware counter/timers, but that setting is not special (and isn't it only used by DOS?)

Actually, I wrote that from memory (of timer limitations I encountered when programming in VB on Windows 2000), and I think I got the actual numbers wrong.

Quoted 4 lines
Quoted 2 lines

me uncertain as to how accurate timings below 14 msec can be on this hardware using the kernel's internal timer.

timers can be set MUCH faster than that.

In principle, yes. usleep() timers can be *set* to 1 usec. That's not the question. The question is how *accurate* timers based on usleep() can be at low settings.

This experiment says they are not very accurate. I changed Lee's loop to be:

  for(i = 0; i < 500; i++)
                {
           usleep(10);
        }

Now 500 x 10 = 5000 usec, or 1/200 seconds. But the loop actually takes 10 seconds to iterate. This implies that usleep() has a minimum delay of 10/500 seconds, or 20 msec, built into it (at least on my test system).

My best guess is that this limitation derives either from the timer code in the Linux kernel or from the system hardware that code relies on.

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

#5 lore raw

QNX. do some research on that OS. Long time ago I heard that it was a real time OS and that programming and running programs on it was VERY much more accurate than the standard INTEL. I don't really know what you want... if you wan precission then this might be your solution... if you dont... then try the bes aproximation possible and use it...

Quoted 39 lines · Ray Olszewski
Quoted 4 lines · Mark Hahn
Quoted 1 line

An i386 has a hardware timer that beats about 72 times per second, leaving

well, it has several hardware counter/timers, but that setting is not special (and isn't it only used by DOS?)

Actually, I wrote that from memory (of timer limitations I encountered when programming in VB on Windows 2000), and I think I got the actual numbers wrong.

Quoted 4 lines
Quoted 2 lines

me uncertain as to how accurate timings below 14 msec can be on this hardware using the kernel's internal timer.

timers can be set MUCH faster than that.

In principle, yes. usleep() timers can be *set* to 1 usec. That's not the question. The question is how *accurate* timers based on usleep() can be at low settings.

This experiment says they are not very accurate. I changed Lee's loop to be:

   for(i = 0; i < 500; i++)
                 {
            usleep(10);
         }

Now 500 x 10 = 5000 usec, or 1/200 seconds. But the loop actually takes 10 seconds to iterate. This implies that usleep() has a minimum delay of 10/500 seconds, or 20 msec, built into it (at least on my test system).

My best guess is that this limitation derives either from the timer code in the Linux kernel or from the system hardware that code relies on.

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

Signature · 11 lines
Alan Bort
Linux Registered User 298277 -Country Manager- [http://counter.li.org]
[ http://www.linuxquestions.org ] Username: Ciccio
[ http://es.tldp.org ]
Ciccio.-

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs
#6 lore raw
In reply to Ray Olszewski

Hi Ray.

Quoted 4 lines

Now 500 x 10 = 5000 usec, or 1/200 seconds. But the loop actually takes 10 seconds to iterate. This implies that usleep() has a minimum delay of 10/500 seconds, or 20 msec, built into it (at least on my test system).

The standard PC BIOS sets up the hardware timer with a tick interval of 18.2 ms which is probably what you are seeing. Memory says that the reason for this is that there are 2^16 (65,536) such ticks per hour, and that apparently made the original IBM PC BIOS somewhat simpler as a result.

Best wishes from Riley.
---
* Nothing as pretty as a smile, nothing as ugly as a frown.

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.488 / Virus Database: 287 - Release Date: 5-Jun-2003

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

#7 lore raw
Quoted 7 lines · Riley Williams

Hi Ray.

Quoted 4 lines

Now 500 x 10 = 5000 usec, or 1/200 seconds. But the loop actually takes 10 seconds to iterate. This implies that usleep() has a minimum delay of 10/500 seconds, or 20 msec, built into it (at least on my test system).

Quoted 7 lines

The standard PC BIOS sets up the hardware timer with a tick interval of 18.2 ms which is probably what you are seeing. Memory says that the reason for this is that there are 2^16 (65,536) such ticks per hour, and that apparently made the original IBM PC BIOS somewhat simpler as a result.

Best wishes from Riley.

Thanks, Riley. This is indeed what I was remembering, albeit imperfectly.

Having done a bit more reading, I find that the standard Linux kernel causes modern computers (Pentium or newer) to generate "heartbeat" interrupts on IRQ0 at the rate of 100 per second, that is, every 10 msec. (This is separate from the RTC, which generates interrupts on IRQ8 at a rate that can be controlled more readily than by editing kernel source.) You can verify this by hand, by comparing uptime (in seconds) to the IRQ0 entry in /proc/interrupts. (I actually get 99.998 per second this way, perhaps because ntp reseting of real time affects uptime reports.)

For that reason, on a standard kernel (and a customized one is apparently a big deal, because a lot of stuff assumes the kernel gets ticks at this rate) nothing can be timed at a finer timing than 10 msec using kernel time facilities ... for finer timing, you have to use the more flexible facility of the IRQ8 RTC, which can be programmed to provide up to 8192 beats per second.

386s and 486s might still, I think, have the coarser timing you describe from DOS days. I no longer have any running here to check, though.

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

#8 lore raw
In reply to Ray Olszewski
Quoted 1 line

An i386 has a hardware timer that beats about 72 times per second, leaving

well, it has several hardware counter/timers, but that setting is not special (and isn't it only used by DOS?)

Quoted 2 lines

me uncertain as to how accurate timings below 14 msec can be on this hardware using the kernel's internal timer.

timers can be set MUCH faster than that.

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

#9 lore raw
In reply to Ray Olszewski
Quoted 6 lines · Ray Olszewski

At 05:55 PM 6/11/2003 -0500, Lee Chin wrote:

In fact, compiled on my system, the loop as written does introduce just about a 1 second delay (30 iterations take 29 seconds, timed crudely with a wristwatch ... just right, since the initial printf() happens before the first loop run).

Who needs a wristwatch when you're running on unix.

time the_command

will give you much more accurate timings than you could ever get with a wristwatch.

Signature · 10 lines
Stephen Samuel +1(604)876-0426                [email protected]
		   http://www.bcgreen.com/~samuel/
Powerful committed communication, reaching through fear, uncertainty and
doubt to touch the jewel within each person and bring it to life.

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs
#10 lore raw
In reply to Lee Chin
Quoted 3 lines · Lee Chin

I would think the following code would wait for 1 second each itteration before printing hello, but it waits way too long. Replacing the for loop body with a usleep(1000000) works great... what am I missing here?

usleep = micro sleep = sleep in 1/1000000 second incrememnts.

Signature · 11 lines
Martin's distress was in contrast to the bitter satisfaction of some
of his fellow marines as they surveyed the scene. "The Iraqis are sick
people and we are the chemotherapy," said Corporal Ryan Dupre. "I am
starting to hate this country. Wait till I get hold of a friggin' Iraqi.
No, I won't get hold of one. I'll just kill him."
	- http://www.informationclearinghouse.info/article2479.htm
-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs
#11 lore raw
In reply to Lee Chin
Quoted 2 lines

I would think the following code would wait for 1 second each itteration before printing hello,

well, usleep takes microseconds, so as you've written it, you should expect it to take 1ms per usleep or 50ms between hello's. further, the man page doesn't claim that it'll actually sleep for exactly the specified microseconds.

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

int main() {
    int c = 20;
    while (c--) {
        int i;
        printf("hello\n");
        for(i = 0; i < 50; i++) {
            usleep(1000);
        }
    }
    return 0;
}

(not that a correct program needs both the stdio and a return from main.)

| [hahn@hahn hahn]$ /usr/bin/time ./chin
| hello
...

| hello
| 0.00user 0.00system 0:19.99elapsed 0%CPU (0avgtext+0avgdata 0maxresident)k
| 0inputs+0outputs (71major+10minor)pagefaults 0swaps
| [hahn@hahn hahn]$ setrealtime time ./chin
| hello
...
| hello
| 0.13user 0.87system 0:01.00elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
| 0inputs+0outputs (71major+10minor)pagefaults 0swaps

hmm, so on its own, 20 iterations of your loop take 20 seconds, one second per iteration, and the usleep is actually lasting 20ms. this is the traditional behavior (and correct, since the man page permits this kind of fuzziness).

if run in realtime mode, 20*50 usleep(1000)'s take 1.00 seconds, cool.

also, if I add:
#include <sys/time.h>

void myusleep(unsigned us) {
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = us;
    select(0,0,0,0,&tv);
}

then it behaves pretty much exactly as expected. (good code would handle the case where us>1000000 and where select is interrupted by a signal.)

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs

#12 lore raw
In reply to Lee Chin
Quoted 4 lines

I would think the following code would wait for 1 second each itteration before printing hello, but it waits way too long. Replacing the for loop body with a usleep(1000000) works great... what am I missing here?

Essentially, that usleep() isn't actually terribly accurate for short waits. First, you always give up the rest of your timeslice, which delays you a few milliseconds (more if there's contention for the processor). Second, kernel timers will always fire a short period after the actual specified time, which gives you a further small, roughly constant delay. Third, you aren't actually woken up immediately after the timer goes off; you simply become eligible for scheduling again.

This means that when you call usleep(x), you actually end up sleeping for x + n us, where n is a few thousand. If you call usleep(1000000), this will probably be less than one percent of the total time slept, so nobody really cares. If you call usleep(1000), it's likely to be several times the actual sleep time required, which you almost certainly do care about.

If you really can't call usleep() or nanosleep() with a big number, the only option is probably to spin: the kernel can't cope with really fine-grained scheduling. If you're root, you can use a real time process, in which case the kernel will do the spinning for you for delays of less than 2ms. Depending on the exact delay being used and how you calibrate the busy wait, this may be slightly more accurate.

Steven Smith,
[email protected].

#13 lore raw
In reply to Lee Chin

On my box, (a P3/450) usleep seems to have an overhead of about 10000usec and a minimum response time of about 20000

/* my test prog:
* (based on yours)
*/

#include <unistd.h>
#include <sys/time.h>

struct timeval tv1,tv2;
#define PAUSE 100000

int main()

{
    while (1)
    {
        int i;
        double sum=0.0,t;
        gettimeofday(&tv2, NULL);
        printf("hello\n");
        for(i = 0; i < 20 ; i++)
        {
                gettimeofday(&tv1, NULL);
            usleep(PAUSE);
               gettimeofday(&tv2, NULL);
               printf("slept %9.6fs\n", t=tv2.tv_sec+tv2.tv_usec*.000001 -tv1.tv_sec-tv1.tv_usec*.000001 );
               sum+=t;
        }
        printf ("average %9.6fs\n",sum/i);
        sleep (5);
    }
}
Quoted 5 lines · Lee Chin

I would think the following code would wait for 1 second each itteration before printing hello, but it waits way too long. Replacing the for loop body with a usleep(1000000) works great... what am I missing here?

Thanks
Lee

Signature · 10 lines
Stephen Samuel +1(604)876-0426                [email protected]
		   http://www.bcgreen.com/~samuel/
Powerful committed communication, reaching through fear, uncertainty and
doubt to touch the jewel within each person and bring it to life.

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs
#14 lore raw
Quoted 2 lines

On my box, (a P3/450) usleep seems to have an overhead of about 10000usec and a minimum response time of about 20000

which is perfectly correct/expected. although "overhead" isn't quite right: instead, say it has a resolution of 1/HZ and a minimum of 2/HZ.

-
To unsubscribe from this list: send the line "unsubscribe linux-newbie" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.linux-learn.org/faqs