mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 22:58:46 +00:00
Clean up core:time to be consistent across all platforms
This commit is contained in:
@@ -14,6 +14,7 @@ General_Error :: enum u32 {
|
|||||||
Timeout,
|
Timeout,
|
||||||
|
|
||||||
Invalid_File,
|
Invalid_File,
|
||||||
|
Invalid_Dir,
|
||||||
Invalid_Path,
|
Invalid_Path,
|
||||||
|
|
||||||
Unsupported,
|
Unsupported,
|
||||||
@@ -51,6 +52,7 @@ error_string :: proc(ferr: Error) -> string {
|
|||||||
case .Closed: return "file already closed"
|
case .Closed: return "file already closed"
|
||||||
case .Timeout: return "i/o timeout"
|
case .Timeout: return "i/o timeout"
|
||||||
case .Invalid_File: return "invalid file"
|
case .Invalid_File: return "invalid file"
|
||||||
|
case .Invalid_Dir: return "invalid directory"
|
||||||
case .Invalid_Path: return "invalid path"
|
case .Invalid_Path: return "invalid path"
|
||||||
case .Unsupported: return "unsupported"
|
case .Unsupported: return "unsupported"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ when ODIN_NO_CRT && ODIN_OS == .Windows {
|
|||||||
foreign import lib "system:NtDll.lib"
|
foreign import lib "system:NtDll.lib"
|
||||||
|
|
||||||
@(private="file")
|
@(private="file")
|
||||||
@(default_calling_convention="std")
|
@(default_calling_convention="stdcall")
|
||||||
foreign lib {
|
foreign lib {
|
||||||
RtlMoveMemory :: proc(dst, src: rawptr, length: int) ---
|
RtlMoveMemory :: proc(dst, src: rawptr, length: int) ---
|
||||||
RtlFillMemory :: proc(dst: rawptr, length: int, fill: i32) ---
|
RtlFillMemory :: proc(dst: rawptr, length: int, fill: i32) ---
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ package unix
|
|||||||
foreign import "system:pthread"
|
foreign import "system:pthread"
|
||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
import "core:time"
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// On success, these functions return 0.
|
// On success, these functions return 0.
|
||||||
@@ -72,7 +71,7 @@ foreign pthread {
|
|||||||
|
|
||||||
// assumes the mutex is pre-locked
|
// assumes the mutex is pre-locked
|
||||||
pthread_cond_wait :: proc(cond: ^pthread_cond_t, mutex: ^pthread_mutex_t) -> c.int ---
|
pthread_cond_wait :: proc(cond: ^pthread_cond_t, mutex: ^pthread_mutex_t) -> c.int ---
|
||||||
pthread_cond_timedwait :: proc(cond: ^pthread_cond_t, mutex: ^pthread_mutex_t, timeout: ^time.TimeSpec) -> c.int ---
|
pthread_cond_timedwait :: proc(cond: ^pthread_cond_t, mutex: ^pthread_mutex_t, timeout: ^timespec) -> c.int ---
|
||||||
|
|
||||||
pthread_condattr_init :: proc(attrs: ^pthread_condattr_t) -> c.int ---
|
pthread_condattr_init :: proc(attrs: ^pthread_condattr_t) -> c.int ---
|
||||||
pthread_condattr_destroy :: proc(attrs: ^pthread_condattr_t) -> c.int ---
|
pthread_condattr_destroy :: proc(attrs: ^pthread_condattr_t) -> c.int ---
|
||||||
@@ -95,7 +94,7 @@ foreign pthread {
|
|||||||
|
|
||||||
pthread_mutex_lock :: proc(mutex: ^pthread_mutex_t) -> c.int ---
|
pthread_mutex_lock :: proc(mutex: ^pthread_mutex_t) -> c.int ---
|
||||||
|
|
||||||
pthread_mutex_timedlock :: proc(mutex: ^pthread_mutex_t, timeout: ^time.TimeSpec) -> c.int ---
|
pthread_mutex_timedlock :: proc(mutex: ^pthread_mutex_t, timeout: ^timespec) -> c.int ---
|
||||||
|
|
||||||
pthread_mutex_unlock :: proc(mutex: ^pthread_mutex_t) -> c.int ---
|
pthread_mutex_unlock :: proc(mutex: ^pthread_mutex_t) -> c.int ---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
//+build linux, darwin, freebsd, openbsd
|
||||||
|
package unix
|
||||||
|
|
||||||
|
when ODIN_OS == .Darwin {
|
||||||
|
foreign import libc "System.framework"
|
||||||
|
} else {
|
||||||
|
foreign import libc "system:c"
|
||||||
|
}
|
||||||
|
|
||||||
|
@(default_calling_convention="c")
|
||||||
|
foreign libc {
|
||||||
|
clock_gettime :: proc(clock_id: u64, timespec: ^timespec) -> i32 ---
|
||||||
|
sleep :: proc(seconds: u32) -> i32 ---
|
||||||
|
nanosleep :: proc(requested, remaining: ^timespec) -> i32 ---
|
||||||
|
}
|
||||||
|
|
||||||
|
foreign import "system:pthread"
|
||||||
|
|
||||||
|
import "core:c"
|
||||||
|
|
||||||
|
@(private="file")
|
||||||
|
@(default_calling_convention="c")
|
||||||
|
foreign pthread {
|
||||||
|
sched_yield :: proc() -> c.int ---
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
boot_time_in_nanoseconds :: proc "c" () -> i64 {
|
||||||
|
ts_now, ts_boottime: timespec
|
||||||
|
clock_gettime(CLOCK_REALTIME, &ts_now)
|
||||||
|
clock_gettime(CLOCK_BOOTTIME, &ts_boottime)
|
||||||
|
|
||||||
|
ns := (ts_now.tv_sec - ts_boottime.tv_sec) * 1e9 + ts_now.tv_nsec - ts_boottime.tv_nsec
|
||||||
|
return i64(ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
seconds_since_boot :: proc "c" () -> f64 {
|
||||||
|
ts_boottime: timespec
|
||||||
|
clock_gettime(CLOCK_BOOTTIME, &ts_boottime)
|
||||||
|
return f64(ts_boottime.tv_sec) + f64(ts_boottime.tv_nsec) / 1e9
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline_nanosleep :: proc "c" (nanoseconds: i64) -> (remaining: timespec, res: i32) {
|
||||||
|
s, ns := nanoseconds / 1e9, nanoseconds % 1e9
|
||||||
|
requested := timespec{tv_sec=s, tv_nsec=ns}
|
||||||
|
res = nanosleep(&requested, &remaining)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
+29
-13
@@ -14,6 +14,8 @@ Hour :: 60 * Minute
|
|||||||
MIN_DURATION :: Duration(-1 << 63)
|
MIN_DURATION :: Duration(-1 << 63)
|
||||||
MAX_DURATION :: Duration(1<<63 - 1)
|
MAX_DURATION :: Duration(1<<63 - 1)
|
||||||
|
|
||||||
|
IS_SUPPORTED :: _IS_SUPPORTED
|
||||||
|
|
||||||
Time :: struct {
|
Time :: struct {
|
||||||
_nsec: i64, // zero is 1970-01-01 00:00:00
|
_nsec: i64, // zero is 1970-01-01 00:00:00
|
||||||
}
|
}
|
||||||
@@ -49,6 +51,14 @@ Stopwatch :: struct {
|
|||||||
_accumulation: Duration,
|
_accumulation: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
now :: proc "contextless" () -> Time {
|
||||||
|
return _now()
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep :: proc "contextless" (d: Duration) {
|
||||||
|
_sleep(d)
|
||||||
|
}
|
||||||
|
|
||||||
stopwatch_start :: proc(using stopwatch: ^Stopwatch) {
|
stopwatch_start :: proc(using stopwatch: ^Stopwatch) {
|
||||||
if !running {
|
if !running {
|
||||||
_start_time = tick_now()
|
_start_time = tick_now()
|
||||||
@@ -82,36 +92,36 @@ since :: proc(start: Time) -> Duration {
|
|||||||
return diff(start, now())
|
return diff(start, now())
|
||||||
}
|
}
|
||||||
|
|
||||||
duration_nanoseconds :: proc(d: Duration) -> i64 {
|
duration_nanoseconds :: proc "contextless" (d: Duration) -> i64 {
|
||||||
return i64(d)
|
return i64(d)
|
||||||
}
|
}
|
||||||
duration_microseconds :: proc(d: Duration) -> f64 {
|
duration_microseconds :: proc "contextless" (d: Duration) -> f64 {
|
||||||
return duration_seconds(d) * 1e6
|
return duration_seconds(d) * 1e6
|
||||||
}
|
}
|
||||||
duration_milliseconds :: proc(d: Duration) -> f64 {
|
duration_milliseconds :: proc "contextless" (d: Duration) -> f64 {
|
||||||
return duration_seconds(d) * 1e3
|
return duration_seconds(d) * 1e3
|
||||||
}
|
}
|
||||||
duration_seconds :: proc(d: Duration) -> f64 {
|
duration_seconds :: proc "contextless" (d: Duration) -> f64 {
|
||||||
sec := d / Second
|
sec := d / Second
|
||||||
nsec := d % Second
|
nsec := d % Second
|
||||||
return f64(sec) + f64(nsec)/1e9
|
return f64(sec) + f64(nsec)/1e9
|
||||||
}
|
}
|
||||||
duration_minutes :: proc(d: Duration) -> f64 {
|
duration_minutes :: proc "contextless" (d: Duration) -> f64 {
|
||||||
min := d / Minute
|
min := d / Minute
|
||||||
nsec := d % Minute
|
nsec := d % Minute
|
||||||
return f64(min) + f64(nsec)/(60*1e9)
|
return f64(min) + f64(nsec)/(60*1e9)
|
||||||
}
|
}
|
||||||
duration_hours :: proc(d: Duration) -> f64 {
|
duration_hours :: proc "contextless" (d: Duration) -> f64 {
|
||||||
hour := d / Hour
|
hour := d / Hour
|
||||||
nsec := d % Hour
|
nsec := d % Hour
|
||||||
return f64(hour) + f64(nsec)/(60*60*1e9)
|
return f64(hour) + f64(nsec)/(60*60*1e9)
|
||||||
}
|
}
|
||||||
|
|
||||||
_less_than_half :: #force_inline proc(x, y: Duration) -> bool {
|
|
||||||
return u64(x)+u64(x) < u64(y)
|
|
||||||
}
|
|
||||||
|
|
||||||
duration_round :: proc(d, m: Duration) -> Duration {
|
duration_round :: proc(d, m: Duration) -> Duration {
|
||||||
|
_less_than_half :: #force_inline proc(x, y: Duration) -> bool {
|
||||||
|
return u64(x)+u64(x) < u64(y)
|
||||||
|
}
|
||||||
|
|
||||||
if m <= 0 {
|
if m <= 0 {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
@@ -201,10 +211,12 @@ unix :: proc(sec: i64, nsec: i64) -> Time {
|
|||||||
return Time{(sec*1e9 + nsec) + UNIX_TO_INTERNAL}
|
return Time{(sec*1e9 + nsec) + UNIX_TO_INTERNAL}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to_unix_seconds :: time_to_unix
|
||||||
time_to_unix :: proc(t: Time) -> i64 {
|
time_to_unix :: proc(t: Time) -> i64 {
|
||||||
return t._nsec/1e9
|
return t._nsec/1e9
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to_unix_nanoseconds :: time_to_unix_nano
|
||||||
time_to_unix_nano :: proc(t: Time) -> i64 {
|
time_to_unix_nano :: proc(t: Time) -> i64 {
|
||||||
return t._nsec
|
return t._nsec
|
||||||
}
|
}
|
||||||
@@ -265,20 +277,24 @@ INTERNAL_TO_WALL :: -WALL_TO_INTERNAL
|
|||||||
UNIX_TO_ABSOLUTE :: UNIX_TO_INTERNAL + INTERNAL_TO_ABSOLUTE
|
UNIX_TO_ABSOLUTE :: UNIX_TO_INTERNAL + INTERNAL_TO_ABSOLUTE
|
||||||
ABSOLUTE_TO_UNIX :: -UNIX_TO_ABSOLUTE
|
ABSOLUTE_TO_UNIX :: -UNIX_TO_ABSOLUTE
|
||||||
|
|
||||||
_is_leap_year :: proc(year: int) -> bool {
|
|
||||||
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@(private)
|
||||||
_date :: proc(t: Time, full: bool) -> (year: int, month: Month, day: int, yday: int) {
|
_date :: proc(t: Time, full: bool) -> (year: int, month: Month, day: int, yday: int) {
|
||||||
year, month, day, yday = _abs_date(_time_abs(t), full)
|
year, month, day, yday = _abs_date(_time_abs(t), full)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
_time_abs :: proc(t: Time) -> u64 {
|
_time_abs :: proc(t: Time) -> u64 {
|
||||||
return u64(t._nsec/1e9 + UNIX_TO_ABSOLUTE)
|
return u64(t._nsec/1e9 + UNIX_TO_ABSOLUTE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
_abs_date :: proc(abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) {
|
_abs_date :: proc(abs: u64, full: bool) -> (year: int, month: Month, day: int, yday: int) {
|
||||||
|
_is_leap_year :: proc(year: int) -> bool {
|
||||||
|
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
|
||||||
|
}
|
||||||
|
|
||||||
d := abs / SECONDS_PER_DAY
|
d := abs / SECONDS_PER_DAY
|
||||||
|
|
||||||
// 400 year cycles
|
// 400 year cycles
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
|
//+private
|
||||||
package time
|
package time
|
||||||
|
|
||||||
import "core:sys/es"
|
import "core:sys/es"
|
||||||
|
|
||||||
IS_SUPPORTED :: true;
|
_IS_SUPPORTED :: true
|
||||||
|
|
||||||
now :: proc "contextless" () -> Time {
|
_now :: proc "contextless" () -> Time {
|
||||||
// TODO Replace once there's a proper time API.
|
// TODO Replace once there's a proper time API.
|
||||||
return Time{_nsec = i64(es.TimeStampMs() * 1e6)};
|
return Time{_nsec = i64(es.TimeStampMs() * 1e6)}
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep :: proc "contextless" (d: Duration) {
|
_sleep :: proc "contextless" (d: Duration) {
|
||||||
es.Sleep(u64(d/Millisecond));
|
es.Sleep(u64(d/Millisecond))
|
||||||
}
|
}
|
||||||
|
|
||||||
_tick_now :: proc "contextless" () -> Tick {
|
_tick_now :: proc "contextless" () -> Tick {
|
||||||
return Tick{_nsec = i64(es.TimeStampMs() * 1e6)};
|
return Tick{_nsec = i64(es.TimeStampMs() * 1e6)}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,19 @@
|
|||||||
|
//+private
|
||||||
//+build freestanding
|
//+build freestanding
|
||||||
package time
|
package time
|
||||||
|
|
||||||
IS_SUPPORTED :: false
|
_IS_SUPPORTED :: false
|
||||||
|
|
||||||
now :: proc() -> Time {
|
_now :: proc "contextless" () -> Time {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep :: proc(d: Duration) {
|
_sleep :: proc "contextless" (d: Duration) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_tick_now :: proc "contextless" () -> Tick {
|
_tick_now :: proc "contextless" () -> Tick {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_yield :: proc "contextless" () {
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
|
//+private
|
||||||
//+build js
|
//+build js
|
||||||
package time
|
package time
|
||||||
|
|
||||||
IS_SUPPORTED :: false
|
_IS_SUPPORTED :: false
|
||||||
|
|
||||||
now :: proc() -> Time {
|
_now :: proc "contextless" () -> Time {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep :: proc(d: Duration) {
|
_sleep :: proc "contextless" (d: Duration) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_tick_now :: proc "contextless" () -> Tick {
|
_tick_now :: proc "contextless" () -> Tick {
|
||||||
|
|||||||
+17
-101
@@ -1,118 +1,34 @@
|
|||||||
|
//+private
|
||||||
//+build linux, darwin, freebsd, openbsd
|
//+build linux, darwin, freebsd, openbsd
|
||||||
package time
|
package time
|
||||||
|
|
||||||
IS_SUPPORTED :: true // NOTE: Times on Darwin are UTC.
|
import "core:sys/unix"
|
||||||
|
|
||||||
when ODIN_OS == .Darwin {
|
_IS_SUPPORTED :: true // NOTE: Times on Darwin are UTC.
|
||||||
foreign import libc "System.framework"
|
|
||||||
} else {
|
|
||||||
foreign import libc "system:c"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
_now :: proc "contextless" () -> Time {
|
||||||
@(default_calling_convention="c")
|
time_spec_now: unix.timespec
|
||||||
foreign libc {
|
unix.clock_gettime(unix.CLOCK_REALTIME, &time_spec_now)
|
||||||
@(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
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
ns := time_spec_now.tv_sec * 1e9 + time_spec_now.tv_nsec
|
ns := time_spec_now.tv_sec * 1e9 + time_spec_now.tv_nsec
|
||||||
return Time{_nsec=ns}
|
return Time{_nsec=ns}
|
||||||
}
|
}
|
||||||
|
|
||||||
boot_time :: proc() -> Time {
|
_sleep :: proc "contextless" (d: Duration) {
|
||||||
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) {
|
|
||||||
ds := duration_seconds(d)
|
ds := duration_seconds(d)
|
||||||
seconds := u32(ds)
|
seconds := u32(ds)
|
||||||
nanoseconds := i64((ds - f64(seconds)) * 1e9)
|
nanoseconds := i64((ds - f64(seconds)) * 1e9)
|
||||||
|
|
||||||
if seconds > 0 { _unix_sleep(seconds) }
|
if seconds > 0 { unix.sleep(seconds) }
|
||||||
if nanoseconds > 0 { nanosleep(nanoseconds) }
|
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 {
|
_tick_now :: proc "contextless" () -> Tick {
|
||||||
t := clock_gettime(CLOCK_MONOTONIC_RAW)
|
t: unix.timespec
|
||||||
_nsec := t.tv_sec*1e9 + t.tv_nsec
|
unix.clock_gettime(unix.CLOCK_MONOTONIC_RAW, &t)
|
||||||
return Tick{_nsec = _nsec}
|
return Tick{_nsec = t.tv_sec*1e9 + t.tv_nsec}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_yield :: proc "contextless" () {
|
||||||
|
unix.sched_yield()
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
|
//+private
|
||||||
//+build wasi
|
//+build wasi
|
||||||
package time
|
package time
|
||||||
|
|
||||||
import wasi "core:sys/wasm/wasi"
|
import wasi "core:sys/wasm/wasi"
|
||||||
|
|
||||||
IS_SUPPORTED :: false
|
_IS_SUPPORTED :: false
|
||||||
|
|
||||||
now :: proc() -> Time {
|
_now :: proc "contextless" () -> Time {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep :: proc(d: Duration) {
|
_sleep :: proc "contextless" (d: Duration) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_tick_now :: proc "contextless" () -> Tick {
|
_tick_now :: proc "contextless" () -> Tick {
|
||||||
|
|||||||
@@ -1,22 +1,21 @@
|
|||||||
|
//+private
|
||||||
package time
|
package time
|
||||||
|
|
||||||
import win32 "core:sys/windows"
|
import win32 "core:sys/windows"
|
||||||
|
|
||||||
IS_SUPPORTED :: true
|
_IS_SUPPORTED :: true
|
||||||
|
|
||||||
now :: proc() -> Time {
|
_now :: proc "contextless" () -> Time {
|
||||||
file_time: win32.FILETIME
|
file_time: win32.FILETIME
|
||||||
win32.GetSystemTimeAsFileTime(&file_time)
|
win32.GetSystemTimeAsFileTime(&file_time)
|
||||||
ns := win32.FILETIME_as_unix_nanoseconds(file_time)
|
ns := win32.FILETIME_as_unix_nanoseconds(file_time)
|
||||||
return Time{_nsec=ns}
|
return Time{_nsec=ns}
|
||||||
}
|
}
|
||||||
|
|
||||||
sleep :: proc(d: Duration) {
|
_sleep :: proc "contextless" (d: Duration) {
|
||||||
win32.Sleep(win32.DWORD(d/Millisecond))
|
win32.Sleep(win32.DWORD(d/Millisecond))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_tick_now :: proc "contextless" () -> Tick {
|
_tick_now :: proc "contextless" () -> Tick {
|
||||||
mul_div_u64 :: proc "contextless" (val, num, den: i64) -> i64 {
|
mul_div_u64 :: proc "contextless" (val, num, den: i64) -> i64 {
|
||||||
q := val / den
|
q := val / den
|
||||||
|
|||||||
Reference in New Issue
Block a user