functions.ha (3028B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use rt; 5 6 // Converts a [[duration]] to an [[rt::timespec]]. This function is 7 // non-portable. 8 export fn duration_to_timespec(n: duration) rt::timespec = rt::timespec { 9 tv_sec = n / SECOND, 10 tv_nsec = n % SECOND, 11 }; 12 13 // Converts a [[duration]] to an [[rt::timeval]]. This function is 14 // non-portable. 15 export fn duration_to_timeval(d: duration) rt::timeval = rt::timeval { 16 tv_sec = d / SECOND, 17 tv_usec = d % SECOND / 1000, 18 }; 19 20 // Converts an [[instant]] to an [[rt::timespec]]. This function is 21 // non-portable. 22 export fn instant_to_timespec(t: instant) rt::timespec = rt::timespec { 23 tv_sec = t.sec, 24 tv_nsec = t.nsec, 25 }; 26 27 // Converts a [[rt::timespec]] to an [[instant]]. This function is 28 // non-portable. 29 export fn timespec_to_instant(ts: rt::timespec) instant = instant { 30 sec = ts.tv_sec, 31 nsec = ts.tv_nsec, 32 }; 33 34 // Yields the process to the kernel and returns after the requested duration. 35 export fn sleep(d: duration) void = { 36 let req = duration_to_timespec(d); 37 38 for (true) { 39 let res = rt::timespec { ... }; 40 match (rt::nanosleep(&req, &res)) { 41 case void => 42 return; 43 case let err: rt::errno => 44 switch (err) { 45 case rt::EINTR => 46 req = res; 47 case => 48 abort("Unexpected error from nanosleep"); 49 }; 50 }; 51 }; 52 }; 53 54 // An enumeration of clocks available on this system. Different clocks represent 55 // times from different epochs, and have different characteristics with regards 56 // to leap seconds, NTP adjustments, and so on. All systems provide the REALTIME 57 // and MONOTONIC clocks at least; use of other clocks is not guaranteed to be 58 // portable. 59 export type clock = enum { 60 // The current wall-clock time. This may jump forwards or backwards in 61 // time to account for leap seconds, NTP adjustments, etc. 62 REALTIME = rt::CLOCK_REALTIME, 63 64 // The current monotonic time. This clock measures from some undefined 65 // epoch and is not affected by leap seconds, NTP adjustments, and 66 // changes to the system time: it always increases by one second per 67 // second. 68 MONOTONIC = rt::CLOCK_MONOTONIC, 69 70 // The uptime clock. It is the time that has elapsed since the system 71 // booted. Begins at zero. 72 BOOT = rt::CLOCK_BOOTTIME, 73 74 // The runtime clock. It only advances while the system is not suspended 75 // and begins when the system is booted. Begins at zero. 76 UPTIME = rt::CLOCK_UPTIME, 77 78 // The process CPU clock. It begins at zero and is advanced while the 79 // calling process is running in user or kernel mode. 80 PROCESS_CPU = rt::CLOCK_PROCESS_CPUTIME_ID, 81 82 // The thread CPU clock. It begins at zero and is advanced while the 83 // calling thread is running in user or kernel mode. 84 THREAD_CPU = rt::CLOCK_THREAD_CPUTIME_ID, 85 }; 86 87 // Returns the current time for a given clock. 88 export fn now(clock: clock) instant = { 89 let ts = rt::timespec { ... }; 90 match (rt::clock_gettime(clock, &ts)) { 91 case void => 92 return timespec_to_instant(ts); 93 case let err: rt::errno => 94 abort("Unexpected error from clock_gettime"); 95 }; 96 };