1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
// SPDX-License-Identifier: MPL-2.0
// (c) Hare authors <https://harelang.org>
// TODO: work when _NSIG != 64
export fn alarm(sec: uint) uint = {
let nval = itimerval { ... };
let oval = itimerval { ... };
nval.it_value.tv_sec = sec: time_t;
setitimer(ITIMER_REAL, &nval, &oval)!;
if (oval.it_value.tv_usec != 0) {
oval.it_value.tv_sec += 1;
};
return oval.it_value.tv_sec: uint;
};
export def ITIMER_REAL: int = 0;
export def ITIMER_VIRTUAL: int = 1;
export def ITIMER_PROF: int = 2;
export type itimerval = struct {
it_interval: timeval,
it_value: timeval,
};
export fn getitimer(
which: int,
cur: *itimerval,
) (void | errno) = {
wrap_return(syscall2(SYS_getitimer, which: u64, cur: uintptr: u64))?;
};
export fn setitimer(
which: int,
newval: *itimerval,
oldval: nullable *itimerval,
) (void | errno) = {
wrap_return(syscall3(SYS_setitimer,
which: u64,
newval: uintptr: u64,
oldval: uintptr: u64))?;
};
export fn sigwait(set: *sigset, sig: *int) (void | errno) = {
*sig = sigtimedwait(set, null, null)?;
};
export fn sigwaitinfo(
set: *sigset,
info: nullable *siginfo,
) (int | errno) = {
return sigtimedwait(set, info, null);
};
export fn sigtimedwait(
set: *sigset,
info: nullable *siginfo,
timeout: nullable *timespec,
) (int | errno) = {
return wrap_return(syscall3(SYS_rt_sigtimedwait,
set: uintptr: u64,
info: uintptr: u64,
timeout: uintptr: u64,
))?: int;
};
export fn sigemptyset(set: *sigset) void = {
set.__val[0] = 0;
};
export fn sigaddset(set: *sigset, signum: int) (void | errno) = {
if (signum < 1 || signum > NSIG) {
return EINVAL;
};
signum -= 1;
set.__val[0] |= 1u64 << signum: u64;
};
export fn sigdelset(set: *sigset, signum: int) (void | errno) = {
if (signum < 1 || signum > NSIG) {
return EINVAL;
};
signum -= 1;
set.__val[0] &= ~(1u64 << signum: u64);
};
export fn sigismember(set: *sigset, signum: int) (bool | errno) = {
if (signum < 1 || signum > NSIG) {
return EINVAL;
};
signum -= 1;
return set.__val[0] & 1u64 << signum: u64 != 0;
};
export fn sigfillset(set: *sigset) void = {
set.__val[0] = ~0u64;
};
// Test sigset operations do not fail for valid signal numbers.
@test fn sigset_valid_signum() void = {
let set: sigset = sigset { ... };
sigemptyset(&set);
assert(!(sigismember(&set, 1) is errno), "Unexpected error");
assert(!(sigismember(&set, 15) is errno), "Unexpected error");
assert(!(sigismember(&set, NSIG) is errno), "Unexpected error");
assert(!(sigaddset(&set, 1) is errno), "Unexpected error");
assert(!(sigaddset(&set, 15) is errno), "Unexpected error");
assert(!(sigaddset(&set, NSIG) is errno), "Unexpected error");
// It's ok to add a signal that is already present in the set.
assert(!(sigaddset(&set, 1) is errno), "Unexpected error");
assert(!(sigdelset(&set, 1) is errno), "Unexpected error");
assert(!(sigdelset(&set, 15) is errno), "Unexpected error");
assert(!(sigdelset(&set, NSIG) is errno), "Unexpected error");
// It's ok to delete a signal that is not present in the set.
assert(!(sigdelset(&set, 10) is errno), "Unexpected error");
};
// Test sigset operations fail for invalid signal numbers.
@test fn sigset_invalid_signum() void = {
let set: sigset = sigset { ... };
sigemptyset(&set);
assert(sigismember(&set, -1) is errno, "Expected error");
assert(sigismember(&set, 0) is errno, "Expected error");
assert(sigismember(&set, NSIG + 1) is errno, "Expected error");
assert(sigaddset(&set, -1) is errno, "Expected error");
assert(sigaddset(&set, 0) is errno, "Expected error");
assert(sigaddset(&set, NSIG + 1) is errno, "Expected error");
assert(sigdelset(&set, -1) is errno, "Expected error");
assert(sigdelset(&set, 0) is errno, "Expected error");
assert(sigdelset(&set, NSIG + 1) is errno, "Expected error");
};
|