|
@@ -1,118 +1,34 @@
|
|
|
+//+private
|
|
|
//+build linux, darwin, freebsd, openbsd
|
|
|
package time
|
|
|
|
|
|
-IS_SUPPORTED :: true // NOTE: Times on Darwin are UTC.
|
|
|
+import "core:sys/unix"
|
|
|
|
|
|
-when ODIN_OS == .Darwin {
|
|
|
- foreign import libc "System.framework"
|
|
|
-} else {
|
|
|
- foreign import libc "system:c"
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-@(default_calling_convention="c")
|
|
|
-foreign libc {
|
|
|
- @(link_name="clock_gettime") _unix_clock_gettime :: proc(clock_id: u64, timespec: ^TimeSpec) -> i32 ---
|
|
|
- @(link_name="sleep") _unix_sleep :: proc(seconds: u32) -> i32 ---
|
|
|
- @(link_name="nanosleep") _unix_nanosleep :: proc(requested: ^TimeSpec, remaining: ^TimeSpec) -> i32 ---
|
|
|
-}
|
|
|
-
|
|
|
-foreign import "system:pthread"
|
|
|
-
|
|
|
-import "core:c"
|
|
|
-
|
|
|
-@(private="file")
|
|
|
-@(default_calling_convention="c")
|
|
|
-foreign pthread {
|
|
|
- sched_yield :: proc() -> c.int ---
|
|
|
-}
|
|
|
-
|
|
|
-_yield :: proc "contextless" () {
|
|
|
- sched_yield()
|
|
|
-}
|
|
|
-
|
|
|
-TimeSpec :: struct {
|
|
|
- tv_sec : i64, /* seconds */
|
|
|
- tv_nsec : i64, /* nanoseconds */
|
|
|
-}
|
|
|
-
|
|
|
-when ODIN_OS == .OpenBSD {
|
|
|
- CLOCK_REALTIME :: 0
|
|
|
- CLOCK_PROCESS_CPUTIME_ID :: 2
|
|
|
- CLOCK_MONOTONIC :: 3
|
|
|
- CLOCK_THREAD_CPUTIME_ID :: 4
|
|
|
- CLOCK_UPTIME :: 5
|
|
|
- CLOCK_BOOTTIME :: 6
|
|
|
-
|
|
|
- // CLOCK_MONOTONIC_RAW doesn't exist, use CLOCK_MONOTONIC
|
|
|
- CLOCK_MONOTONIC_RAW :: CLOCK_MONOTONIC
|
|
|
-} else {
|
|
|
- CLOCK_REALTIME :: 0 // NOTE(tetra): May jump in time, when user changes the system time.
|
|
|
- CLOCK_MONOTONIC :: 1 // NOTE(tetra): May stand still while system is asleep.
|
|
|
- CLOCK_PROCESS_CPUTIME_ID :: 2
|
|
|
- CLOCK_THREAD_CPUTIME_ID :: 3
|
|
|
- CLOCK_MONOTONIC_RAW :: 4 // NOTE(tetra): "RAW" means: Not adjusted by NTP.
|
|
|
- CLOCK_REALTIME_COARSE :: 5 // NOTE(tetra): "COARSE" clocks are apparently much faster, but not "fine-grained."
|
|
|
- CLOCK_MONOTONIC_COARSE :: 6
|
|
|
- CLOCK_BOOTTIME :: 7 // NOTE(tetra): Same as MONOTONIC, except also including time system was asleep.
|
|
|
- CLOCK_REALTIME_ALARM :: 8
|
|
|
- CLOCK_BOOTTIME_ALARM :: 9
|
|
|
-}
|
|
|
-
|
|
|
-// TODO(tetra, 2019-11-05): The original implementation of this package for Darwin used this constants.
|
|
|
-// I do not know if Darwin programmers are used to the existance of these constants or not, so
|
|
|
-// I'm leaving aliases to them for now.
|
|
|
-CLOCK_SYSTEM :: CLOCK_REALTIME
|
|
|
-CLOCK_CALENDAR :: CLOCK_MONOTONIC
|
|
|
+_IS_SUPPORTED :: true // NOTE: Times on Darwin are UTC.
|
|
|
|
|
|
-
|
|
|
-clock_gettime :: proc "contextless" (clock_id: u64) -> TimeSpec {
|
|
|
- ts : TimeSpec // NOTE(tetra): Do we need to initialize this?
|
|
|
- _unix_clock_gettime(clock_id, &ts)
|
|
|
- return ts
|
|
|
-}
|
|
|
-
|
|
|
-now :: proc() -> Time {
|
|
|
- time_spec_now := clock_gettime(CLOCK_REALTIME)
|
|
|
+_now :: proc "contextless" () -> Time {
|
|
|
+ time_spec_now: unix.timespec
|
|
|
+ unix.clock_gettime(unix.CLOCK_REALTIME, &time_spec_now)
|
|
|
ns := time_spec_now.tv_sec * 1e9 + time_spec_now.tv_nsec
|
|
|
return Time{_nsec=ns}
|
|
|
}
|
|
|
|
|
|
-boot_time :: proc() -> Time {
|
|
|
- ts_now := clock_gettime(CLOCK_REALTIME)
|
|
|
- ts_boottime := clock_gettime(CLOCK_BOOTTIME)
|
|
|
-
|
|
|
- ns := (ts_now.tv_sec - ts_boottime.tv_sec) * 1e9 + ts_now.tv_nsec - ts_boottime.tv_nsec
|
|
|
- return Time{_nsec=ns}
|
|
|
-}
|
|
|
-
|
|
|
-seconds_since_boot :: proc() -> f64 {
|
|
|
- ts_boottime := clock_gettime(CLOCK_BOOTTIME)
|
|
|
- return f64(ts_boottime.tv_sec) + f64(ts_boottime.tv_nsec) / 1e9
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-sleep :: proc(d: Duration) {
|
|
|
+_sleep :: proc "contextless" (d: Duration) {
|
|
|
ds := duration_seconds(d)
|
|
|
seconds := u32(ds)
|
|
|
nanoseconds := i64((ds - f64(seconds)) * 1e9)
|
|
|
|
|
|
- if seconds > 0 { _unix_sleep(seconds) }
|
|
|
- if nanoseconds > 0 { nanosleep(nanoseconds) }
|
|
|
+ if seconds > 0 { unix.sleep(seconds) }
|
|
|
+ if nanoseconds > 0 { unix.inline_nanosleep(nanoseconds) }
|
|
|
}
|
|
|
|
|
|
-nanosleep :: proc(nanoseconds: i64) -> int {
|
|
|
- // NOTE(tetra): Should we remove this assert? We are measuring nanoseconds after all...
|
|
|
- assert(nanoseconds <= 999999999)
|
|
|
-
|
|
|
- requested := TimeSpec{tv_nsec = nanoseconds}
|
|
|
- remaining: TimeSpec // NOTE(tetra): Do we need to initialize this?
|
|
|
- return int(_unix_nanosleep(&requested, &remaining))
|
|
|
+_tick_now :: proc "contextless" () -> Tick {
|
|
|
+ t: unix.timespec
|
|
|
+ unix.clock_gettime(unix.CLOCK_MONOTONIC_RAW, &t)
|
|
|
+ return Tick{_nsec = t.tv_sec*1e9 + t.tv_nsec}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-_tick_now :: proc "contextless" () -> Tick {
|
|
|
- t := clock_gettime(CLOCK_MONOTONIC_RAW)
|
|
|
- _nsec := t.tv_sec*1e9 + t.tv_nsec
|
|
|
- return Tick{_nsec = _nsec}
|
|
|
+_yield :: proc "contextless" () {
|
|
|
+ unix.sched_yield()
|
|
|
}
|
|
|
+
|