File: signal.ha

package info (click to toggle)
hare 0.26.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 7,352 kB
  • sloc: asm: 1,374; makefile: 123; sh: 117; lisp: 101
file content (139 lines) | stat: -rw-r--r-- 3,795 bytes parent folder | download | duplicates (2)
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");
};