time_unix.odin 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. //+build linux, darwin, freebsd, openbsd, netbsd, haiku
  2. package unix
  3. when ODIN_OS == .Darwin {
  4. foreign import libc "system:System.framework"
  5. } else {
  6. foreign import libc "system:c"
  7. }
  8. import "core:c"
  9. when ODIN_OS == .NetBSD {
  10. @(default_calling_convention="c")
  11. foreign libc {
  12. @(link_name="__clock_gettime50") clock_gettime :: proc(clock_id: u64, timespec: ^timespec) -> c.int ---
  13. @(link_name="__nanosleep50") nanosleep :: proc(requested, remaining: ^timespec) -> c.int ---
  14. @(link_name="sleep") sleep :: proc(seconds: c.uint) -> c.int ---
  15. }
  16. } else {
  17. @(default_calling_convention="c")
  18. foreign libc {
  19. clock_gettime :: proc(clock_id: u64, timespec: ^timespec) -> c.int ---
  20. sleep :: proc(seconds: c.uint) -> c.int ---
  21. nanosleep :: proc(requested, remaining: ^timespec) -> c.int ---
  22. }
  23. }
  24. timespec :: struct {
  25. tv_sec: i64, // seconds
  26. tv_nsec: i64, // nanoseconds
  27. }
  28. when ODIN_OS == .OpenBSD {
  29. CLOCK_REALTIME :: 0
  30. CLOCK_PROCESS_CPUTIME_ID :: 2
  31. CLOCK_MONOTONIC :: 3
  32. CLOCK_THREAD_CPUTIME_ID :: 4
  33. CLOCK_UPTIME :: 5
  34. CLOCK_BOOTTIME :: 6
  35. // CLOCK_MONOTONIC_RAW doesn't exist, use CLOCK_MONOTONIC
  36. CLOCK_MONOTONIC_RAW :: CLOCK_MONOTONIC
  37. } else {
  38. CLOCK_REALTIME :: 0 // NOTE(tetra): May jump in time, when user changes the system time.
  39. CLOCK_MONOTONIC :: 1 // NOTE(tetra): May stand still while system is asleep.
  40. CLOCK_PROCESS_CPUTIME_ID :: 2
  41. CLOCK_THREAD_CPUTIME_ID :: 3
  42. CLOCK_MONOTONIC_RAW :: 4 // NOTE(tetra): "RAW" means: Not adjusted by NTP.
  43. CLOCK_REALTIME_COARSE :: 5 // NOTE(tetra): "COARSE" clocks are apparently much faster, but not "fine-grained."
  44. CLOCK_MONOTONIC_COARSE :: 6
  45. CLOCK_BOOTTIME :: 7 // NOTE(tetra): Same as MONOTONIC, except also including time system was asleep.
  46. CLOCK_REALTIME_ALARM :: 8
  47. CLOCK_BOOTTIME_ALARM :: 9
  48. }
  49. // TODO(tetra, 2019-11-05): The original implementation of this package for Darwin used this constants.
  50. // I do not know if Darwin programmers are used to the existance of these constants or not, so
  51. // I'm leaving aliases to them for now.
  52. CLOCK_SYSTEM :: CLOCK_REALTIME
  53. CLOCK_CALENDAR :: CLOCK_MONOTONIC
  54. boot_time_in_nanoseconds :: proc "c" () -> i64 {
  55. ts_now, ts_boottime: timespec
  56. clock_gettime(CLOCK_REALTIME, &ts_now)
  57. clock_gettime(CLOCK_BOOTTIME, &ts_boottime)
  58. ns := (ts_now.tv_sec - ts_boottime.tv_sec) * 1e9 + ts_now.tv_nsec - ts_boottime.tv_nsec
  59. return i64(ns)
  60. }
  61. seconds_since_boot :: proc "c" () -> f64 {
  62. ts_boottime: timespec
  63. clock_gettime(CLOCK_BOOTTIME, &ts_boottime)
  64. return f64(ts_boottime.tv_sec) + f64(ts_boottime.tv_nsec) / 1e9
  65. }
  66. inline_nanosleep :: proc "c" (nanoseconds: i64) -> (remaining: timespec, res: i32) {
  67. s, ns := nanoseconds / 1e9, nanoseconds % 1e9
  68. requested := timespec{tv_sec=s, tv_nsec=ns}
  69. res = nanosleep(&requested, &remaining)
  70. return
  71. }