summary refs log tree commit diff stats
path: root/lib/system/timers.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system/timers.nim')
-rw-r--r--lib/system/timers.nim99
1 files changed, 99 insertions, 0 deletions
diff --git a/lib/system/timers.nim b/lib/system/timers.nim
new file mode 100644
index 000000000..ffb0f7716
--- /dev/null
+++ b/lib/system/timers.nim
@@ -0,0 +1,99 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2012 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## Timer support for the realtime GC. Based on
+## `<https://github.com/jckarter/clay/blob/master/compiler/hirestimer.cpp>`_
+
+type
+  Ticks = distinct int64
+  Nanos = int64
+
+when defined(windows):
+
+  proc QueryPerformanceCounter(res: var Ticks) {.
+    importc: "QueryPerformanceCounter", stdcall, dynlib: "kernel32".}
+  proc QueryPerformanceFrequency(res: var int64) {.
+    importc: "QueryPerformanceFrequency", stdcall, dynlib: "kernel32".}
+
+  proc getTicks(): Ticks {.inline.} =
+    QueryPerformanceCounter(result)
+
+  proc `-`(a, b: Ticks): Nanos =
+    var frequency: int64
+    QueryPerformanceFrequency(frequency)
+    var performanceCounterRate = 1e+9'f64 / float64(frequency)
+
+    result = Nanos(float64(a.int64 - b.int64) * performanceCounterRate)
+
+elif defined(macosx) and not defined(emscripten):
+  type
+    MachTimebaseInfoData {.pure, final,
+        importc: "mach_timebase_info_data_t",
+        header: "<mach/mach_time.h>".} = object
+      numer, denom: int32 # note: `uint32` in sources
+
+  proc mach_absolute_time(): uint64 {.importc, header: "<mach/mach_time.h>".}
+  proc mach_timebase_info(info: var MachTimebaseInfoData) {.importc,
+    header: "<mach/mach_time.h>".}
+
+  proc getTicks(): Ticks {.inline.} =
+    result = Ticks(mach_absolute_time())
+
+  var timeBaseInfo: MachTimebaseInfoData
+  mach_timebase_info(timeBaseInfo)
+
+  proc `-`(a, b: Ticks): Nanos =
+    result = (a.int64 - b.int64) * timeBaseInfo.numer div timeBaseInfo.denom
+
+elif defined(posixRealtime):
+  type
+    Clockid {.importc: "clockid_t", header: "<time.h>", final.} = object
+
+    TimeSpec {.importc: "struct timespec", header: "<time.h>",
+               final, pure.} = object ## struct timespec
+      tv_sec: int  ## Seconds.
+      tv_nsec: int ## Nanoseconds.
+
+  var
+    CLOCK_REALTIME {.importc: "CLOCK_REALTIME", header: "<time.h>".}: Clockid
+
+  proc clock_gettime(clkId: Clockid, tp: var Timespec) {.
+    importc: "clock_gettime", header: "<time.h>".}
+
+  proc getTicks(): Ticks =
+    var t: Timespec
+    clock_gettime(CLOCK_REALTIME, t)
+    result = Ticks(int64(t.tv_sec) * 1000000000'i64 + int64(t.tv_nsec))
+
+  proc `-`(a, b: Ticks): Nanos {.borrow.}
+
+else:
+  # fallback Posix implementation:
+  when not declared(Time):
+    when defined(linux):
+      type Time = clong
+    else:
+      type Time = int
+
+  type
+    Timeval {.importc: "struct timeval", header: "<sys/select.h>",
+               final, pure.} = object ## struct timeval
+      tv_sec: Time  ## Seconds.
+      tv_usec: clong ## Microseconds.
+
+  proc posix_gettimeofday(tp: var Timeval, unused: pointer = nil) {.
+    importc: "gettimeofday", header: "<sys/time.h>".}
+
+  proc getTicks(): Ticks =
+    var t: Timeval
+    posix_gettimeofday(t)
+    result = Ticks(int64(t.tv_sec) * 1000_000_000'i64 +
+                    int64(t.tv_usec) * 1000'i64)
+
+  proc `-`(a, b: Ticks): Nanos {.borrow.}