hare

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

signal.ha (3996B)


      1 // SPDX-License-Identifier: MPL-2.0
      2 // (c) Hare authors <https://harelang.org>
      3 
      4 // TODO: work when _NSIG != 32
      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 = sigwaitinfo(set, null)?;
     46 };
     47 
     48 export fn sigwaitinfo(
     49 	set: *sigset,
     50 	info: nullable *siginfo,
     51 ) (int | errno) = {
     52 	return wrap_return(syscall2(SYS_sigwaitinfo,
     53 		set: uintptr: u64,
     54 		info: uintptr: u64,
     55 	))?: int;
     56 };
     57 
     58 export fn sigtimedwait(
     59 	set: *sigset,
     60 	info: nullable *siginfo,
     61 	timeout: nullable *timespec,
     62 ) (int | errno) = {
     63 	return wrap_return(syscall3(SYS_sigtimedwait,
     64 		set: uintptr: u64,
     65 		info: uintptr: u64,
     66 		timeout: uintptr: u64,
     67 	))?: int;
     68 };
     69 
     70 export fn sigemptyset(set: *sigset) void = {
     71 	for (let i = 0z; i < len(set.__bits); i += 1) {
     72 		set.__bits[i] = 0;
     73 	};
     74 };
     75 
     76 export fn sigaddset(set: *sigset, signum: int) (void | errno) = {
     77 	if (signum < 1 || signum > NSIG) {
     78 		return EINVAL;
     79 	};
     80 	signum -= 1;
     81 	set.__bits[signum >> 5] |= (1 << signum): u32;
     82 };
     83 
     84 export fn sigdelset(set: *sigset, signum: int) (void | errno) = {
     85 	if (signum < 1 || signum > NSIG) {
     86 		return EINVAL;
     87 	};
     88 	signum -= 1;
     89 	set.__bits[signum >> 5] &= ~(1 << signum: u32);
     90 };
     91 
     92 export fn sigismember(set: *sigset, signum: int) (bool | errno) = {
     93 	if (signum < 1 || signum > NSIG) {
     94 		return EINVAL;
     95 	};
     96 	signum -= 1;
     97 	return (set.__bits[signum >> 5] & (1 << signum: u32)) != 0;
     98 };
     99 
    100 export fn sigfillset(set: *sigset) (void | errno) = {
    101 	for (let i = 0z; i < len(set.__bits); i += 1) {
    102 		set.__bits[i] = ~0u32;
    103 	};
    104 };
    105 
    106 // Test sigset operations do not fail for valid signal numbers.
    107 @test fn sigset_valid_signum() void = {
    108 	let set: sigset = sigset { ... };
    109 	sigemptyset(&set);
    110 
    111 	assert(!(sigismember(&set, 1) is errno), "Unexpected error");
    112 	assert(!(sigismember(&set, 15) is errno), "Unexpected error");
    113 	assert(!(sigismember(&set, NSIG) is errno), "Unexpected error");
    114 
    115 	assert(!(sigaddset(&set, 1) is errno), "Unexpected error");
    116 	assert(!(sigaddset(&set, 15) is errno), "Unexpected error");
    117 	assert(!(sigaddset(&set, NSIG) is errno), "Unexpected error");
    118 
    119 	// It's ok to add a signal that is already present in the set.
    120 	assert(!(sigaddset(&set, 1) is errno), "Unexpected error");
    121 
    122 	assert(!(sigdelset(&set, 1) is errno), "Unexpected error");
    123 	assert(!(sigdelset(&set, 15) is errno), "Unexpected error");
    124 	assert(!(sigdelset(&set, NSIG) is errno), "Unexpected error");
    125 
    126 	// It's ok to delete a signal that is not present in the set.
    127 	assert(!(sigdelset(&set, 10) is errno), "Unexpected error");
    128 };
    129 
    130 // Test sigset operations fail for invalid signal numbers.
    131 @test fn sigset_invalid_signum() void = {
    132 	let set: sigset = sigset { ... };
    133 	sigemptyset(&set);
    134 
    135 	assert(sigismember(&set, -1) is errno, "Expected error");
    136 	assert(sigismember(&set, 0) is errno, "Expected error");
    137 	assert(sigismember(&set, NSIG + 1) is errno, "Expected error");
    138 
    139 	assert(sigaddset(&set, -1) is errno, "Expected error");
    140 	assert(sigaddset(&set, 0) is errno, "Expected error");
    141 	assert(sigaddset(&set, NSIG + 1) is errno, "Expected error");
    142 
    143 	assert(sigdelset(&set, -1) is errno, "Expected error");
    144 	assert(sigdelset(&set, 0) is errno, "Expected error");
    145 	assert(sigdelset(&set, NSIG + 1) is errno, "Expected error");
    146 };