ofpbuf: Fix trivial spelling typo.
[cascardo/ovs.git] / python / ovs / timeval.py
index ba0e54e..9a0cf67 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import sys
 import time
 
+try:
+    import ctypes
+
+    LIBRT = 'librt.so.1'
+    clock_gettime_name = 'clock_gettime'
+
+    if sys.platform.startswith("linux"):
+        CLOCK_MONOTONIC = 1
+        time_t = ctypes.c_long
+    elif sys.platform.startswith("netbsd"):
+        # NetBSD uses function renaming for ABI versioning.  While the proper
+        # way to get the appropriate version is of course "#include <time.h>",
+        # it is difficult with ctypes.  The following is appropriate for
+        # recent versions of NetBSD, including NetBSD-6.
+        LIBRT = 'libc.so.12'
+        clock_gettime_name = '__clock_gettime50'
+        CLOCK_MONOTONIC = 3
+        time_t = ctypes.c_int64
+    elif sys.platform.startswith("freebsd"):
+        CLOCK_MONOTONIC = 4
+        time_t = ctypes.c_int64
+    else:
+        raise Exception
+
+    class timespec(ctypes.Structure):
+        _fields_ = [
+            ('tv_sec', time_t),
+            ('tv_nsec', ctypes.c_long),
+        ]
+
+    librt = ctypes.CDLL(LIBRT)
+    clock_gettime = getattr(librt, clock_gettime_name)
+    clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)]
+except:
+    # Librt shared library could not be loaded
+    librt = None
+
+
+def monotonic():
+    if not librt:
+        return time.time()
+
+    t = timespec()
+    if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) == 0:
+        return t.tv_sec + t.tv_nsec * 1e-9
+    # Kernel does not support CLOCK_MONOTONIC
+    return time.time()
+
+
+# Use time.monotonic() if Python version >= 3.3
+if not hasattr(time, 'monotonic'):
+    time.monotonic = monotonic
+
 
 def msec():
-    """Returns the current time, as the amount of time since the epoch, in
-    milliseconds, as a float."""
-    return time.time() * 1000.0
+    """ Returns the system's monotonic time if possible, otherwise returns the
+    current time as the amount of time since the epoch, in milliseconds, as a
+    float."""
+    return time.monotonic() * 1000.0
 
 
 def postfork():