Bug in 2.4 nanosleep()?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Greetings,

I seems to me that at least 2.4.8 & 2.4.14 have miscalculation
bugs beneath the sys_nanosleep() call.  Calls to nanosleep() on
my Mandrake 8.1 based Dell 450 MHz PII produce poor results
even when called with a resolution of 1/10 of a second.

Is this a) a 2.4 kernel bug, b) a glibc 2.2.4 bug, c) due to
a 450MHz PII being "underpowered", or d) the nature of scheduling
under Linux?  I tried to investigate a), but between all the
jiffies and x86 assembly I got lost.

Look at these results.  Each value should be 1.000 second.
The included program loops N times with a 1/N second sleep,
using three different methods.  Using select(), nanosleep(),
and usleep().

Sleeping 1000 times for one millisecond should take 1 second
of wall clock, yet it takes 20 seconds!  Try the program and
see for yourself.

Thank you for any insights!!

Mike Arras
mkarras110@yahoo.com

My typical results on a quiet machine:

1x 1/1 of a second...
Select    0.997
Nanosleep 1.010
Usleep    1.010

10x 1/10 of a second...
Select    1.000
Nanosleep 1.100
Usleep    1.100

50x 1/50 of a second...
Select    1.000
Nanosleep 1.500
Usleep    1.500

100x 1/100 of a second...
Select    1.001
Nanosleep 2.000
Usleep    2.000

200x 1/200 of a second...
Select    2.000
Nanosleep 4.000
Usleep    4.000

500x 1/500 of a second...
Select    5.000
Nanosleep 10.000
Usleep    10.000

1000x 1/1000 of a second...
Select    10.000
Nanosleep 20.000
Usleep    20.000


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


double precTime(void)
{
    struct timeval tv;

    gettimeofday(&tv, 0);

    return tv.tv_sec + tv.tv_usec / 1000000.0;
}

static void runtimer(int fraction)
{
    struct timeval tm;
    struct timespec ts;
    double startTime, endTime;
    int i;

    printf("%dx 1/%d of a second...\n", fraction, fraction);

    startTime = precTime();
    for (i = 0; i < fraction; i++)
    {
        tm.tv_sec = 0;
        tm.tv_usec = 1000000 / fraction;
        select(0, 0, 0, 0, &tm);
    }
    endTime = precTime();
    printf("Select    %1.3f\n", endTime - startTime);

    startTime = precTime();
    for (i = 0; i < fraction; i++)
    {
        ts.tv_sec = 0;
        ts.tv_nsec = 1000000000 / fraction - 1;
        nanosleep(&ts, 0);
    }
    endTime = precTime();
    printf("Nanosleep %1.3f\n", endTime - startTime);

    startTime = precTime();
    for (i = 0; i < fraction; i++)
    {
        usleep(1000000 / fraction);
    }
    endTime = precTime();
    printf("Usleep    %1.3f\n\n", endTime - startTime);
}

int main(void)
{
    runtimer(1);
    runtimer(10);
    runtimer(50);
    runtimer(100);
    runtimer(200);
    runtimer(500);
    runtimer(1000);

    return 0;
}
--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
IRC Channel:   irc.openprojects.net / #kernelnewbies
Web Page:      http://www.kernelnewbies.org/



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux