hare

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

signal.ha (3964B)


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