]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add nanosleep and usleep Windows shims
authorOndřej Surý <ondrej@sury.org>
Tue, 27 Apr 2021 08:16:01 +0000 (10:16 +0200)
committerOndřej Surý <ondrej@sury.org>
Mon, 3 May 2021 18:22:54 +0000 (20:22 +0200)
This commit adds POSIX nanosleep() and usleep() shim implementation for
Windows to help implementors use less #ifdef _WIN32 in the code.

bin/tools/mdig.c
configure.ac
lib/dns/tests/dnstest.c
lib/isc/tests/doh_test.c
lib/isc/tests/isctest.c
lib/isc/tests/netmgr_test.c
lib/isc/tests/quota_test.c
lib/isc/win32/include/isc/time.h
lib/isc/win32/libisc.def.in
lib/isc/win32/time.c
lib/ns/tests/nstest.c

index b35292f51ebf3aabd73955a68628bdc8ce489566..a8c47b61979c46dbd2e0dc3e2b50c0afaeae7ce0 100644 (file)
@@ -2060,21 +2060,6 @@ parse_args(bool is_batchfile, int argc, char **argv) {
        }
 }
 
-#ifdef WIN32
-static void
-usleep(unsigned int usec) {
-       HANDLE timer;
-       LARGE_INTEGER ft;
-
-       ft.QuadPart = -(10 * (__int64)usec);
-
-       timer = CreateWaitableTimer(NULL, TRUE, NULL);
-       SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
-       WaitForSingleObject(timer, INFINITE);
-       CloseHandle(timer);
-}
-#endif
-
 /*% Main processing routine for mdig */
 int
 main(int argc, char *argv[]) {
index 2cb914d9946586b960c4dd621c60a6d7f2639069..e16e0f7bc1ce6f0cad3fb8fedecd8256ce56da38 100644 (file)
@@ -1149,8 +1149,6 @@ AC_COMPILE_IFELSE(
 #
 AC_CHECK_FUNCS([if_nametoindex])
 
-AC_CHECK_FUNCS(nanosleep usleep explicit_bzero)
-
 ISC_ATOMIC_LIBS=""
 AC_CHECK_HEADERS(
   [stdatomic.h],
index 9562846dd27af7ab004db09ba3750632620afc11..71f0e0c74366f71aa5b4017344fa4ce87241e0e0 100644 (file)
@@ -340,21 +340,11 @@ dns_test_closezonemgr(void) {
  */
 void
 dns_test_nap(uint32_t usec) {
-#ifdef HAVE_NANOSLEEP
        struct timespec ts;
 
        ts.tv_sec = usec / 1000000;
        ts.tv_nsec = (usec % 1000000) * 1000;
        nanosleep(&ts, NULL);
-#elif HAVE_USLEEP
-       usleep(usec);
-#else  /* ifdef HAVE_NANOSLEEP */
-       /*
-        * No fractional-second sleep function is available, so we
-        * round up to the nearest second and sleep instead
-        */
-       sleep((usec / 1000000) + 1);
-#endif /* ifdef HAVE_NANOSLEEP */
 }
 
 isc_result_t
index 71dedbad6af0275699abaddad2f8752cd79028f3..759adc97abe263772d03db71acab8fe8d9367aa2 100644 (file)
@@ -653,7 +653,7 @@ doh_timeout_recovery(void **state) {
                if (atomic_load(&ctimeouts) == 5) {
                        break;
                }
-               usleep(1000);
+               isc_test_nap(1000);
        }
        assert_true(atomic_load(&ctimeouts) == 5);
 
@@ -717,7 +717,7 @@ doh_connect_thread(isc_threadarg_t arg) {
                 * errors, to prevent a thundering herd problem.
                 */
                if (atomic_load(&slowdown)) {
-                       usleep(1000 * workers);
+                       isc_test_nap(1000 * workers);
                        atomic_store(&slowdown, false);
                }
                connect_send_request(
index d86007903b1ebaeba90234d1708d21e55743cc23..c9b6b6929f5966d4bbade5343f8562ce7bb8fdc4 100644 (file)
@@ -171,19 +171,9 @@ isc_test_end(void) {
  */
 void
 isc_test_nap(uint32_t usec) {
-#ifdef HAVE_NANOSLEEP
        struct timespec ts;
 
        ts.tv_sec = usec / 1000000;
        ts.tv_nsec = (usec % 1000000) * 1000;
        nanosleep(&ts, NULL);
-#elif HAVE_USLEEP
-       usleep(usec);
-#else  /* ifdef HAVE_NANOSLEEP */
-       /*
-        * No fractional-second sleep function is available, so we
-        * round up to the nearest second and sleep instead
-        */
-       sleep((usec / 1000000) + 1);
-#endif /* ifdef HAVE_NANOSLEEP */
 }
index 8f1ae9ece7726acdec9ddaad8ae9d06e284632c6..f167e7433f021eb8ca240e8732de94ec9c7060ab 100644 (file)
@@ -137,7 +137,7 @@ static isc_nm_recv_cb_t connect_readcb = NULL;
                                __r = WAIT_REPEATS;         \
                        }                                   \
                        __o = __l;                          \
-                       usleep(T_WAIT);                     \
+                       isc_test_nap(T_WAIT);               \
                } while (__r > 0);                          \
                X(v);                                       \
                P(__r);                                     \
@@ -606,7 +606,7 @@ connect_thread(isc_threadarg_t arg) {
                         * start slowing down the connections to prevent the
                         * thundering herd problem.
                         */
-                       usleep((active - workers) * 1000);
+                       isc_test_nap((active - workers) * 1000);
                }
                connect(connect_nm);
        }
@@ -1071,7 +1071,7 @@ udp_half_recv_send(void **state __attribute__((unused))) {
        assert_null(listen_sock);
 
        /* Try to send a little while longer */
-       usleep((esends / 2) * 10000);
+       isc_test_nap((esends / 2) * 10000);
 
        isc_nm_closedown(connect_nm);
 
@@ -1519,7 +1519,7 @@ stream_half_recv_send(void **state __attribute__((unused))) {
        assert_null(listen_sock);
 
        /* Try to send a little while longer */
-       usleep((esends / 2) * 10000);
+       isc_test_nap((esends / 2) * 10000);
 
        isc_nm_closedown(connect_nm);
 
@@ -1787,7 +1787,7 @@ tcpdns_noresponse(void **state __attribute__((unused))) {
                NULL, noop_accept_cb, NULL, 0, 0, NULL, &listen_sock);
        if (result != ISC_R_SUCCESS) {
                isc_refcount_decrement(&active_cconnects);
-               usleep(1000);
+               isc_test_nap(1000);
        }
        assert_int_equal(result, ISC_R_SUCCESS);
 
@@ -2073,7 +2073,7 @@ tcpdns_half_recv_send(void **state __attribute__((unused))) {
        assert_null(listen_sock);
 
        /* Try to send a little while longer */
-       usleep((esends / 2) * 10000);
+       isc_test_nap((esends / 2) * 10000);
 
        isc_nm_closedown(connect_nm);
 
@@ -2675,7 +2675,7 @@ tlsdns_half_recv_send(void **state __attribute__((unused))) {
        assert_null(listen_sock);
 
        /* Try to send a little while longer */
-       usleep((esends / 2) * 10000);
+       isc_test_nap((esends / 2) * 10000);
 
        isc_nm_closedown(connect_nm);
 
index 1def0c74563c9e5bba38aaa6a0085367e6fb3620..6a8c09beceb42a16ad40094c604f0bc901a7f92b 100644 (file)
@@ -28,6 +28,8 @@
 #include <isc/thread.h>
 #include <isc/util.h>
 
+#include "isctest.h"
+
 static void
 isc_quota_get_set_test(void **state) {
        UNUSED(state);
@@ -256,7 +258,7 @@ isc_thread_t g_threads[10 * 100];
 static void *
 quota_detach(void *quotap) {
        isc_quota_t *quota = (isc_quota_t *)quotap;
-       usleep(10000);
+       isc_test_nap(10000);
        isc_quota_detach(&quota);
        return ((isc_threadresult_t)0);
 }
index c52a04061c8de62d85c0069caeee996b252954c2..8637c712535431635adcdfad78d09e98b91c4c91 100644 (file)
  *** POSIX Shims
  ***/
 
-inline struct tm *
-gmtime_r(const time_t *clock, struct tm *result) {
-       errno_t ret = gmtime_s(result, clock);
-       if (ret != 0) {
-               errno = ret;
-               return (NULL);
-       }
-       return (result);
-}
-
-inline struct tm *
-localtime_r(const time_t *clock, struct tm *result) {
-       errno_t ret = localtime_s(result, clock);
-       if (ret != 0) {
-               errno = ret;
-               return (NULL);
-       }
-       return (result);
-}
+struct tm *
+gmtime_r(const time_t *clock, struct tm *result);
+
+struct tm *
+localtime_r(const time_t *clock, struct tm *result);
+
+int
+nanosleep(const struct timespec *req, struct timespec *rem);
+
+typedef uint32_t useconds_t;
+
+int
+usleep(useconds_t usec);
 
 /***
  *** Intervals
index 1404a8316c4df5a29abc2d9a857dd7573e65bdc5..04faf9de85b86e6ac6f0c1cec120722a4ba42e85 100644 (file)
@@ -671,6 +671,10 @@ isc_thread_join
 isc_thread_setaffinity
 isc_thread_setconcurrency
 isc_thread_setname
+gmtime_r
+localtime_r
+nanosleep
+usleep
 isc_time_add
 isc_time_compare
 isc_time_formatISO8601
index 3cce3536ff3f082616ed200f8d8ab38b7067b20b..316bc904301860ba6748589d99d8841ca48559ac 100644 (file)
@@ -20,6 +20,7 @@
 #include <windows.h>
 
 #include <isc/assertions.h>
+#include <isc/once.h>
 #include <isc/string.h>
 #include <isc/time.h>
 #include <isc/tm.h>
@@ -543,3 +544,106 @@ isc_time_formatshorttimestamp(const isc_time_t *t, char *buf,
                buf[0] = 0;
        }
 }
+
+/*
+ * POSIX Shims
+ */
+
+struct tm *
+gmtime_r(const time_t *clock, struct tm *result) {
+       errno_t ret = gmtime_s(result, clock);
+       if (ret != 0) {
+               errno = ret;
+               return (NULL);
+       }
+       return (result);
+}
+
+struct tm *
+localtime_r(const time_t *clock, struct tm *result) {
+       errno_t ret = localtime_s(result, clock);
+       if (ret != 0) {
+               errno = ret;
+               return (NULL);
+       }
+       return (result);
+}
+
+#define BILLION 1000000000
+
+static isc_once_t nsec_ticks_once = ISC_ONCE_INIT;
+static double nsec_ticks = 0;
+
+static void
+nsec_ticks_init(void) {
+       LARGE_INTEGER ticks;
+       RUNTIME_CHECK(QueryPerformanceFrequency(&ticks) != 0);
+       nsec_ticks = (double)ticks.QuadPart / 1000000000.0;
+       RUNTIME_CHECK(nsec_ticks != 0.0);
+}
+
+int
+nanosleep(const struct timespec *req, struct timespec *rem) {
+       int_fast64_t sleep_msec;
+       uint_fast64_t ticks, until;
+       LARGE_INTEGER before, after;
+
+       RUNTIME_CHECK(isc_once_do(&nsec_ticks_once, nsec_ticks_init) ==
+                     ISC_R_SUCCESS);
+
+       if (req->tv_nsec < 0 || BILLION <= req->tv_nsec) {
+               errno = EINVAL;
+               return (-1);
+       }
+
+       /* Sleep() is not interruptible; there is no remaining delay ever  */
+       if (rem != NULL) {
+               rem->tv_sec = 0;
+               rem->tv_nsec = 0;
+       }
+
+       if (req->tv_sec >= 0) {
+               /*
+                * For requested delays of one second or more, 15ms resolution
+                * granularity is sufficient.
+                */
+               Sleep(req->tv_sec * 1000 + req->tv_nsec / 1000000);
+
+               return (0);
+       }
+
+       /* Sleep has <-8,8> ms precision, so substract 10 milliseconds */
+       sleep_msec = (int64_t)req->tv_nsec / 1000000 - 10;
+       ticks = req->tv_nsec * nsec_ticks;
+
+       RUNTIME_CHECK(QueryPerformanceCounter(&before) != 0);
+
+       until = before.QuadPart + ticks;
+
+       if (sleep_msec > 0) {
+               Sleep(sleep_msec);
+       }
+
+       while (true) {
+               LARGE_INTEGER after;
+               RUNTIME_CHECK(QueryPerformanceCounter(&after) != 0);
+               if (after.QuadPart >= until) {
+                       break;
+               }
+       }
+
+done:
+       return (0);
+}
+
+int
+usleep(useconds_t useconds) {
+       struct timespec req;
+
+       req.tv_sec = useconds / 1000000;
+       req.tv_nsec = (useconds * 1000) % 1000000000;
+
+       nanosleep(&req, NULL);
+
+       return (0);
+}
index 0f309f01a86b0368afb030cb569f08e9c491315e..173a5c80e7adf75552cc5c8eac9a699783146781 100644 (file)
@@ -893,21 +893,11 @@ ns_test_hook_catch_call(void *arg, void *data, isc_result_t *resultp) {
  */
 void
 ns_test_nap(uint32_t usec) {
-#ifdef HAVE_NANOSLEEP
        struct timespec ts;
 
        ts.tv_sec = usec / 1000000;
        ts.tv_nsec = (usec % 1000000) * 1000;
        nanosleep(&ts, NULL);
-#elif HAVE_USLEEP
-       usleep(usec);
-#else  /* ifdef HAVE_NANOSLEEP */
-       /*
-        * No fractional-second sleep function is available, so we
-        * round up to the nearest second and sleep instead
-        */
-       sleep((usec / 1000000) + 1);
-#endif /* ifdef HAVE_NANOSLEEP */
 }
 
 isc_result_t