hare

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

commit 198b6bc554ae29cc49c21d7904fd130716e60f14
parent bbe9e6bb6f1cc4fc91cd096fda424ee42d33ca9d
Author: Sebastian <sebastian@sebsite.pw>
Date:   Sat,  9 Dec 2023 21:31:54 -0500

time: change signature of *_to_timespec funcs

Also fixes a memory management "bug" in sleep. The variable req was set
to the address of a variable local to the loop, which works as of now
but which I assume is undefined behavior (the spec is currently silent
about this so it's tough to say).

This is a breaking change: existing code can be migrated by taking the
value of the function result, rather than creating a binding and passing
it in as a pointer.

Signed-off-by: Sebastian <sebastian@sebsite.pw>

Diffstat:
Mlinux/timerfd/+linux/timerfd.ha | 13++++---------
Mtime/+freebsd/functions.ha | 22++++++++++------------
Mtime/+linux/functions.ha | 20+++++++++-----------
Mtime/+openbsd/functions.ha | 22++++++++++------------
Munix/poll/+freebsd.ha | 3+--
Munix/poll/+linux.ha | 3+--
Munix/poll/+openbsd.ha | 3+--
7 files changed, 36 insertions(+), 50 deletions(-)

diff --git a/linux/timerfd/+linux/timerfd.ha b/linux/timerfd/+linux/timerfd.ha @@ -63,27 +63,22 @@ export fn set( exp: expiration, flags: set_flag, ) (void | errors::error) = { - let interval_timespec = rt::timespec { ... }; const timerspec = match (exp) { case let o: oneshot => - time::duration_to_timespec(o, &interval_timespec); yield rt::itimerspec { it_interval = rt::timespec { tv_sec = 0, tv_nsec = 0 }, - it_value = interval_timespec, + it_value = time::duration_to_timespec(o), }; case let i: interval => - time::duration_to_timespec(i, &interval_timespec); + const interval_timespec = time::duration_to_timespec(i); yield rt::itimerspec { it_interval = interval_timespec, it_value = interval_timespec, }; case let id: interval_delayed => - let delay_timespec = rt::timespec { ... }; - time::duration_to_timespec(id.0, &interval_timespec); - time::duration_to_timespec(id.1, &delay_timespec); yield rt::itimerspec { - it_interval = interval_timespec, - it_value = delay_timespec, + it_interval = time::duration_to_timespec(id.0), + it_value = time::duration_to_timespec(id.1), }; }; diff --git a/time/+freebsd/functions.ha b/time/+freebsd/functions.ha @@ -5,16 +5,16 @@ use rt; // Converts a [[duration]] to an [[rt::timespec]]. This function is // non-portable. -export fn duration_to_timespec(n: duration, ts: *rt::timespec) void = { - ts.tv_sec = n / SECOND; - ts.tv_nsec = n % SECOND; +export fn duration_to_timespec(n: duration) rt::timespec = rt::timespec { + tv_sec = n / SECOND, + tv_nsec = n % SECOND, }; // Converts an [[instant]] to an [[rt::timespec]]. This function is // non-portable. -export fn instant_to_timespec(t: instant, ts: *rt::timespec) void = { - ts.tv_sec = t.sec; - ts.tv_nsec = t.nsec; +export fn instant_to_timespec(t: instant) rt::timespec = rt::timespec { + tv_sec = t.sec, + tv_nsec = t.nsec, }; // Converts a [[rt::timespec]] to an [[instant]]. This function is @@ -25,20 +25,18 @@ export fn timespec_to_instant(ts: rt::timespec) instant = instant { }; // Yields the process to the kernel and returns after the requested duration. -export fn sleep(n: duration) void = { - let in = rt::timespec { ... }; - duration_to_timespec(n, &in); - let req = &in; +export fn sleep(d: duration) void = { + let req = duration_to_timespec(d); for (true) { let res = rt::timespec { ... }; - match (rt::nanosleep(req, &res)) { + match (rt::nanosleep(&req, &res)) { case void => return; case let err: rt::errno => switch (err) { case rt::EINTR => - req = &res; + req = res; case => abort("Unexpected error from nanosleep"); }; diff --git a/time/+linux/functions.ha b/time/+linux/functions.ha @@ -6,16 +6,16 @@ use rt; // Converts a [[duration]] to an [[rt::timespec]]. This function is // non-portable. -export fn duration_to_timespec(d: duration, ts: *rt::timespec) void = { - ts.tv_sec = d / SECOND; - ts.tv_nsec = d % SECOND; +export fn duration_to_timespec(d: duration) rt::timespec = rt::timespec { + tv_sec = d / SECOND, + tv_nsec = d % SECOND, }; // Converts an [[instant]] to an [[rt::timespec]]. This function is // non-portable. -export fn instant_to_timespec(t: instant, ts: *rt::timespec) void = { - ts.tv_sec = t.sec; - ts.tv_nsec = t.nsec; +export fn instant_to_timespec(t: instant) rt::timespec = rt::timespec { + tv_sec = t.sec, + tv_nsec = t.nsec, }; // Converts a [[rt::timespec]] to an [[instant]]. This function is non-portable. @@ -26,19 +26,17 @@ export fn timespec_to_instant(ts: rt::timespec) instant = instant { // Yields the process to the kernel and returns after the requested duration. export fn sleep(d: duration) void = { - let in = rt::timespec { ... }; - duration_to_timespec(d, &in); - let req = &in; + let req = duration_to_timespec(d); for (true) { let res = rt::timespec { ... }; - match (rt::nanosleep(req, &res)) { + match (rt::nanosleep(&req, &res)) { case void => return; case let err: rt::errno => switch (err) { case rt::EINTR => - req = &res; + req = res; case => abort("Unexpected error from nanosleep"); }; diff --git a/time/+openbsd/functions.ha b/time/+openbsd/functions.ha @@ -5,16 +5,16 @@ use rt; // Converts a [[duration]] to an [[rt::timespec]]. This function is // non-portable. -export fn duration_to_timespec(n: duration, ts: *rt::timespec) void = { - ts.tv_sec = n / SECOND; - ts.tv_nsec = n % SECOND; +export fn duration_to_timespec(n: duration) rt::timespec = rt::timespec { + tv_sec = n / SECOND, + tv_nsec = n % SECOND, }; // Converts an [[instant]] to an [[rt::timespec]]. This function is // non-portable. -export fn instant_to_timespec(t: instant, ts: *rt::timespec) void = { - ts.tv_sec = t.sec; - ts.tv_nsec = t.nsec; +export fn instant_to_timespec(t: instant) rt::timespec = rt::timespec { + tv_sec = t.sec, + tv_nsec = t.nsec, }; // Converts a [[rt::timespec]] to an [[instant]]. This function is @@ -25,20 +25,18 @@ export fn timespec_to_instant(ts: rt::timespec) instant = instant { }; // Yields the process to the kernel and returns after the requested duration. -export fn sleep(n: duration) void = { - let in = rt::timespec { ... }; - duration_to_timespec(n, &in); - let req = &in; +export fn sleep(d: duration) void = { + let req = duration_to_timespec(d); for (true) { let res = rt::timespec { ... }; - match (rt::nanosleep(req, &res)) { + match (rt::nanosleep(&req, &res)) { case void => return; case let err: rt::errno => switch (err) { case rt::EINTR => - req = &res; + req = res; case => abort("Unexpected error from nanosleep"); }; diff --git a/unix/poll/+freebsd.ha b/unix/poll/+freebsd.ha @@ -39,8 +39,7 @@ export fn poll( fds: []pollfd, timeout: time::duration, ) (uint | error) = { - let ts = rt::timespec { ... }; - time::duration_to_timespec(timeout, &ts); + let ts = time::duration_to_timespec(timeout); let ts = if (timeout == INDEF) null else &ts; match (rt::ppoll(fds: *[*]pollfd: *[*]rt::pollfd, len(fds): rt::nfds_t, ts, null)) { case let err: rt::errno => diff --git a/unix/poll/+linux.ha b/unix/poll/+linux.ha @@ -39,8 +39,7 @@ export fn poll( fds: []pollfd, timeout: time::duration, ) (uint | error) = { - let ts = rt::timespec { ... }; - time::duration_to_timespec(timeout, &ts); + let ts = time::duration_to_timespec(timeout); let ts = if (timeout == INDEF) null else &ts; match (rt::ppoll(fds: *[*]pollfd: *[*]rt::pollfd, len(fds), ts, null)) { case let err: rt::errno => diff --git a/unix/poll/+openbsd.ha b/unix/poll/+openbsd.ha @@ -39,8 +39,7 @@ export fn poll( fds: []pollfd, timeout: time::duration, ) (uint | error) = { - let ts = rt::timespec { ... }; - time::duration_to_timespec(timeout, &ts); + let ts = time::duration_to_timespec(timeout); let ts = if (timeout == INDEF) null else &ts; match (rt::ppoll(fds: *[*]pollfd: *[*]rt::pollfd, len(fds): rt::nfds_t, ts, null)) { case let err: rt::errno =>