Sleeping for milliseconds on Windows, Linux, Solaris, HP-UX, IBM AIX, Vxworks, Wind River Linux?

38,194

Solution 1

Propably a wrapper using platform specific #defines will do:

#if defined(WIN32)
  #include <windows.h>
#elif defined(__UNIX__)
  #include <unistd.h>
#else
#endif

...

int millisleep(unsigned ms)
{
#if defined(WIN32)
  SetLastError(0);
  Sleep(ms);
  return GetLastError() ?-1 :0;
#elif defined(LINUX)
  return usleep(1000 * ms);
#else
#error ("no milli sleep available for platform")
  return -1;
#endif
}

Update

Referring to Jonathan's comment below, please find a more modern, more portable (and as well corrected :}) version here:

#if defined(WIN32)
  #include <windows.h>
#elif defined(__unix__)
  #include <time.h>
  #include <unistd.h>
#else
#endif

...

int millisleep(unsigned ms)
{
#if defined(WIN32)

  SetLastError(0);
  Sleep(ms);
  return GetLastError() ?-1 :0;

#elif _POSIX_C_SOURCE >= 199309L

  /* prefer to use nanosleep() */

  const struct timespec ts = {
    ms / 1000, /* seconds */
    (ms % 1000) * 1000 * 1000 /* nano seconds */
  };

  return nanosleep(&ts, NULL);

#elif _BSD_SOURCE || \
  (_XOPEN_SOURCE >= 500 || \
     _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \
  !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)

  /* else fallback to obsolte usleep() */

  return usleep(1000 * ms);

#else

# error ("No millisecond sleep available for this platform!")
  return -1;

#endif
}

Solution 2

I note that usleep is obsolescent but its a lot simpler than nanosleep. So I used it when I needed an enhanced sleep that would allow easy adjustment from seconds while debugging my scripts to milliseconds or zero for production.

This snooze function combines the advantages of sleep & usleep so that you can enter an int or float for your desired delay and 0.1 will sleep a 10th of a second while 3 will sleep for 3 seconds. 3.5 seconds is treated as 3 seconds.

Tested on Linux Mint 18.3 (Ubuntu 16.04.9) as C and C++ with gcc 5.4.0.

#include <unistd.h>

void snooze(double t) {(t > 1.0) ? sleep(t) : usleep(t*1000000);}

snooze(0.01);  // call function to sleep for 10ms



For completeness, this is a nanosleep version. It's potentially more accurate than the usleep version and isn't threatened by obsolescence.

#include <time.h>
#include <math.h>

void snooze(double t) {
    struct timespec req = {t, fmod(t, 1.0) * 1E9};
    nanosleep(&req, NULL);
}

// struct timespec req = {t, fmod(t, 1.0) * 1E9};
//  is equivalent to:
// struct timespec req = {0};
// req.tv_sec = t;
// req.tv_nsec = fmod(t, 1.0) * 1000000000L;

// NULL as value for *rem so no resumption after signal interrupts

snooze(1.99);  // call for delay of 1.99 seconds

As suggested by @alk, the following versions return the called sleep function's error should one occur or 0 if successful. Defining the structure rem(aining) also permits resumption after a signal interrupt.

int snooze(double t) {
    return (t > 1.0) ? sleep(t) : usleep(t*1000000);
}

int snooze(double t) {
    struct timespec req = {t, fmod(t, 1.0) * 1E9};
    struct timespec rem = {0, 0.0};
    return nanosleep(&req, &rem);
}

Solution 3

Consider select with empty FD sets and the timeout you want. From man select:

Some code calls select() with all three sets empty, nfds zero, and a non-NULL timeout as a fairly portable way to sleep with subsecond precision.

Actually it might be the best solution for any non-Windows system.

Share:
38,194
rashok
Author by

rashok

A Passionate Developer

Updated on April 30, 2020

Comments

  • rashok
    rashok about 4 years

    I have to write a C program which has to sleep for milliseconds, which has to run on various platforms like Windows, Linux, Solaris, HP-UX, IBM AIX, Vxworks, and Windriver Linux

    • On Windows, the Sleep system call will work on milliseconds only.
    • On Linux, sleep will work on seconds; usleep will perform on microseconds and it's available on Solaris also.
    • In Vxworks, I hope I can implement using taskDelay and sysClkRateSet.

    How can I achieve this millisecond sleep on HP-UX, IBM AIX and Wind River Linux?

  • rashok
    rashok about 11 years
    Thanks for your reply. currently we are using this only, in some platform select is not available. Like windriver linux select is not available.
  • Jonathan Leffler
    Jonathan Leffler almost 7 years
    Under POSIX 2004, the usleep() call was marked 'obsolescent', and it was removed from POSIX 2008. The preferred alternative is nanosleep(). The general trend in POSIX is to prefer struct timespec, which has nanosecond resolution, over alternatives such as struct timeval which has only microsecond resolution, or usleep() which doesn't use a structure but works with microsecond resolution too.
  • alk
    alk almost 7 years
    @JonathanLeffler: Thanks for notifying. Corrected.
  • alk
    alk about 6 years
    For complete completeness you might want to take care of the value returned by the functions used.
  • John 9631
    John 9631 about 6 years
    Thanks for the suggestion alk. I've added options.
  • Simon Kissane
    Simon Kissane about 3 years
    @rashok select function exists on HP-UX and AIX. I am surprised by statement it doesn't exist on Wind River Linux. Wind River Linux is Linux, so how can it be missing the select system call? (or its newer replacements, newselect or pselect6).