hare

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

signal.ha (3792B)


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