[ovs-dev,v2,2/2] util: Add high resolution sleep support.

Message ID 1510692151-14322-2-git-send-email-bhanuprakash.bodireddy@intel.com
State New
Headers show
Series
  • [ovs-dev,v2,1/2] timeval: Introduce macros to convert timespec and timeval.
Related show

Commit Message

Bhanuprakash Bodireddy Nov. 14, 2017, 8:42 p.m.
This commit introduces xnanosleep() for the threads needing high
resolution sleep timeouts.

usleep() that provides microsecond granularity is deprecated and
threads wanting sub-second(ms,us,ns) granularity can use this implementation.

CC: Aaron Conole <aconole@redhat.com>
CC: Alin Gabriel Serdean <aserdean@ovn.org>
CC: Ben Pfaff <blp@ovn.org>
Signed-off-by: Bhanuprakash Bodireddy <bhanuprakash.bodireddy@intel.com>
---
 lib/timeval.c | 19 +++++++++++++++++++
 lib/timeval.h |  1 +
 lib/util.c    | 35 +++++++++++++++++++++++++++++++++++
 lib/util.h    |  1 +
 4 files changed, 56 insertions(+)

Patch

diff --git a/lib/timeval.c b/lib/timeval.c
index 567c26e..2fde90f 100644
--- a/lib/timeval.c
+++ b/lib/timeval.c
@@ -517,6 +517,25 @@  msec_to_timespec(long long int ms, struct timespec *ts)
     ts->tv_nsec = (ms % 1000) * NSEC_PER_MSEC;
 }
 
+void
+nsec_to_timespec(long long int nsec, struct timespec *ts)
+{
+    if (!nsec) {
+        ts->tv_sec = ts->tv_nsec = 0;
+        return;
+    }
+    ts->tv_sec = nsec / NSEC_PER_SEC;
+
+    nsec = nsec % NSEC_PER_SEC;
+    /* This is to handle dates before epoch. */
+    if (OVS_UNLIKELY(nsec < 0)) {
+        nsec += NSEC_PER_SEC;
+        ts->tv_sec--;
+    }
+
+    ts->tv_nsec = nsec;
+}
+
 static void
 timewarp_work(void)
 {
diff --git a/lib/timeval.h b/lib/timeval.h
index 5e2a731..095c334 100644
--- a/lib/timeval.h
+++ b/lib/timeval.h
@@ -80,6 +80,7 @@  size_t strftime_msec(char *s, size_t max, const char *format,
                      const struct tm_msec *);
 void xgettimeofday(struct timeval *);
 void xclock_gettime(clock_t, struct timespec *);
+void nsec_to_timespec(long long int , struct timespec *);
 
 int get_cpu_usage(void);
 
diff --git a/lib/util.c b/lib/util.c
index 17c2c99..2c184d9 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -2205,6 +2205,41 @@  xsleep(unsigned int seconds)
     ovsrcu_quiesce_end();
 }
 
+/* High resolution sleep. */
+void
+xnanosleep(uint64_t nanoseconds)
+{
+    ovsrcu_quiesce_start();
+#ifndef _WIN32
+    int retval;
+    struct timespec ts_sleep;
+    nsec_to_timespec(nanoseconds, &ts_sleep);
+
+    int error = 0;
+    do {
+        retval = nanosleep(&ts_sleep, NULL);
+        error = retval < 0 ? errno : 0;
+    } while (error == EINTR);
+#else
+    HANDLE timer = CreateWaitableTimer(NULL, FALSE, NULL);
+    if (timer) {
+        LARGE_INTEGER duetime;
+        duetime.QuadPart = -nanoseconds;
+        if (SetWaitableTimer(timer, &duetime, 0, NULL, NULL, FALSE)) {
+            WaitForSingleObject(timer, INFINITE);
+        } else {
+            VLOG_ERR_ONCE("SetWaitableTimer Failed (%s)",
+                           ovs_lasterror_to_string());
+        }
+        CloseHandle(timer);
+    } else {
+        VLOG_ERR_ONCE("CreateWaitableTimer Failed (%s)",
+                       ovs_lasterror_to_string());
+    }
+#endif
+    ovsrcu_quiesce_end();
+}
+
 /* Determine whether standard output is a tty or not. This is useful to decide
  * whether to use color output or not when --color option for utilities is set
  * to `auto`.
diff --git a/lib/util.h b/lib/util.h
index 3c43c2c..d355313 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -502,6 +502,7 @@  ovs_u128_and(const ovs_u128 a, const ovs_u128 b)
 }
 
 void xsleep(unsigned int seconds);
+void xnanosleep(uint64_t nanoseconds);
 
 bool is_stdout_a_tty(void);