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
|
//go:build none
// Ignore the //go:build above. This file is manually included on Linux and
// MacOS to provide os/signal support.
#include <stdint.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
// Signal handler in the runtime.
void tinygo_signal_handler(int sig);
// Enable a signal from the runtime.
void tinygo_signal_enable(uint32_t sig) {
struct sigaction act = { 0 };
act.sa_handler = &tinygo_signal_handler;
sigaction(sig, &act, NULL);
}
void tinygo_signal_ignore(uint32_t sig) {
struct sigaction act = { 0 };
act.sa_handler = SIG_IGN;
sigaction(sig, &act, NULL);
}
void tinygo_signal_disable(uint32_t sig) {
struct sigaction act = { 0 };
act.sa_handler = SIG_DFL;
sigaction(sig, &act, NULL);
}
// Implement waitForEvents and sleep with signals.
// Warning: sigprocmask is not defined in a multithreaded program so will need
// to be replaced with something else once we implement threading on POSIX.
// Signals active before a call to tinygo_wfi_mask.
static sigset_t active_signals;
static void tinygo_set_signals(sigset_t *mask, uint32_t signals) {
sigemptyset(mask);
for (int i=0; i<32; i++) {
if ((signals & (1<<i)) != 0) {
sigaddset(mask, i);
}
}
}
// Mask the given signals.
// This function must always restore the previous signals using
// tinygo_wfi_unmask, to create a critical section.
void tinygo_wfi_mask(uint32_t active) {
sigset_t mask;
tinygo_set_signals(&mask, active);
sigprocmask(SIG_BLOCK, &mask, &active_signals);
}
// Wait until a signal becomes pending (or is already pending), and return the
// signal.
#if !defined(__APPLE__)
int tinygo_wfi_sleep(uint32_t active, uint64_t timeout) {
sigset_t active_set;
tinygo_set_signals(&active_set, active);
struct timespec ts = {0};
ts.tv_sec = timeout / 1000000000;
ts.tv_nsec = timeout % 1000000000;
int result = sigtimedwait(&active_set, NULL, &ts);
return result;
}
#endif
// Wait until any of the active signals becomes pending (or returns immediately
// if one is already pending).
int tinygo_wfi_wait(uint32_t active) {
sigset_t active_set;
tinygo_set_signals(&active_set, active);
int sig = 0;
sigwait(&active_set, &sig);
return sig;
}
// Restore previous signal mask.
void tinygo_wfi_unmask(void) {
sigprocmask(SIG_SETMASK, &active_signals, NULL);
}
|