hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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 };