time_unix.odin 2.4 KB

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