nanosleep is better than sleep and usleep

Don’t know whether you aware of the example code at Tap the interrupt signal, I am using sleep(1) within endless loop at the first sample of code.

The example of the code is to illustrate the tapping Interrupt signal while I hit control+c and ignores the termination of the program. When I hit control+c, I discover a problem. the sleep process elapse straight away although its not yet pass a second where it support to sleep for one second.

It happens to usleep function as well, where both sleep and usleep doesn’t seems to be a good sleep function to use. And I discover a better sleep function from time.h. That is nanosleep. Refers to nanosleep man page, it briefly state that it can cater the problem by storing the remaining time at second param, and with that you can use the remaining to to call nanosleep again.

That means, its not like sleep or usleep, you can use it straight away. Well, I have write a wrapper for miliseconds sleep. With the signal tap handler function in sample code, use to test for usleep and my own msleep.

#include<stdio.h>
#include<time.h>
#include<signal.h>

void sigfunc(int sig_no)
{

}

int __nsleep(const struct timespec *req, struct timespec *rem)
{
    struct timespec temp_rem;
    if(nanosleep(req,rem)==-1)
        __nsleep(rem,&temp_rem);
    else
        return 1;
}

int msleep(unsigned long milisec)
{
    struct timespec req={0},rem={0};
    time_t sec=(int)(milisec/1000);
    milisec=milisec-(sec*1000);
    req.tv_sec=sec;
    req.tv_nsec=milisec*1000000L;
    __nsleep(&req,&rem);
    return 1;
}

int main()
{
    struct sigaction sa={0};
    sa.sa_handler=&sigfunc;
    sigaction(SIGINT, &sa,NULL);

    int a=0;
    scanf("%d",&a);

    for (;;)
    {
        printf("testing...\n");
        if (a==1)
            msleep(1000);
        else
            usleep(1000000);
    }
    return 1;
}

__nsleep is a wrapper for nanosleep, the reason I want to do that wrapper is because I want to make a recursive call to nanosleep. If nanosleep is intercept by signal, it will return -1 and the second param will store the remaining time. With that, I call __nsleep recursively passing the second param as first param now. The second param will be a temp timespac structure variable.

I create another wrapper msleep accepting millisecond, in timespec structure, you can either gives value in nanosecond or second. One thing to be aware is tv_nsec cannot go beyond 999999999, which is 1 second. If beyond that, you have to put it into tv_sec.

Updates:
I found __nsleep() is redundant, and I have a better idea without using recursive and __nsleep at all, instead, directly create a msleep.

int msleep(unsigned long milisec)
{
    struct timespec req={0};
    time_t sec=(int)(milisec/1000);
    milisec=milisec-(sec*1000);
    req.tv_sec=sec;
    req.tv_nsec=milisec*1000000L;
    while(nanosleep(&req,&req)==-1)
         continue;
    return 1;
}

Store back the remaining time to req, If getting return value -1, continue to sleep. Better and cleaner isn’t it? :D

9 thoughts on “nanosleep is better than sleep and usleep

  1. I would change your code to:

    while(nanosleep(&req,&req)==-1 && errno == EINTR)
    continue;

    to avoid a possible infinite loop.

  2. this seems simpler to me and works just fine:

    void msleep(int ms) {
    struct timespec time;
    time.tv_sec = 1000 / ms;
    time.tv_nsec = (1000 % ms) * (1000 * 1000);
    nanosleep(&time,NULL);
    }

  3. sorry, should have tested before, small error in my post before. this should work:

    void msleep(int ms) {
    struct timespec time;
    time.tv_sec = ms / 1000;
    time.tv_nsec = (ms % 1000) * (1000 * 1000);
    nanosleep(&time,NULL);
    }

  4. Here’s what’s cleaner and better:


    void GuaranteedSleep(uint32_t msec)
    {
    struct timespec timeout0;
    struct timespec timeout1;
    struct timespec* tmp;
    struct timespec* t0 = &timeout0;
    struct timespec* t1 = &timeout1;

    t0->tv_sec = msec / 1000;
    t0->tv_nsec = (msec % 1000) * (1000 * 1000);

    while ((nanosleep(t0, t1) == (-1)) && (errno == EINTR))
    {
    tmp = t0;
    t0 = t1;
    t1 = tmp;
    }
    }

  5. I would rather use

    void msleep(u32 msec)
    {
    struct timespec interval;
    struct timespec remainder;

    interval.tv_sec = msec / 1000;
    interval.tv_nsec = (msec % 1000) * (1000 * 1000);

    if (nanosleep(&interval, &remainder) == -1) {
    if (errno == EINTR) {
    (void)printf(“nanosleep interrupted\n”);
    cout << "Remaining secs: " << remainder.tv_sec;
    cout << "Remaining nsecs: " << remainder.tv_nsec;
    }
    else perror("nanosleep");
    }
    }

  6. I know its been a wile since this was posted, but I figured I’d point out the same think can be accomplished with sleep. the big difference between nanosleep and sleep is the resolution.

    The following will sleep for ‘sleepTime’ regardless of interrupts.

    while ((sleepTime = sleep(sleepTime)) > 0);

  7. msleep() with automatically retry only if nanosleep is interrupted by signal.

    int msleep(unsigned int msec)
    {
    struct timespec timeout0;
    struct timespec timeout1;
    struct timespec* tmp;
    struct timespec* t0 = &timeout0;
    struct timespec* t1 = &timeout1;

    t0->tv_sec = msec / 1000;
    t0->tv_nsec = (msec % 1000) * (1000 * 1000);

    while(nanosleep(t0, t1) == -1)
    {
    if(errno == EINTR)
    {
    tmp = t0;
    t0 = t1;
    t1 = tmp;
    }
    else
    return -1;
    }
    return 0;
    }

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>