Landin library reference discuss source

compiler/tests/fixtures/runtime/signals-fake-firmware/main.ldn

1--  D449, D477: core/io/fake's signals over a round of turns, within a
2--  32 KiB firmware image.  A fibre written against `any signal.signals`
3--  watches SIGUSR1 and SIGTERM and waits for each in turn; another fibre
4--  takes a turn and then raises SIGUSR1, SIGHUP, which nobody watches and
5--  is dropped, and SIGTERM twice, the second while the first waits to be
6--  read and so one event with it.  The waiter hears SIGUSR1 and then
7--  SIGTERM, each with the number the fake gives it.  Last, a fibre
8--  waiting for a signal is woken by `stop_watching`, its wait failing
9--  `io_failed`.
10import core/failure
11import core/fibre
12import core/fibre/stacks
13import core/io
14import core/io/fake
15import core/io/signal
16
17--  What the waiter heard: each signal's number, in order, and `s` when a
18--  wait failed because watching stopped.
19mut heard: [8]u32 = zeroed
20mut count: usize = 0
21
22note: (number: u32) -> none =
23    heard[count] = number
24    inc count
25end note
26
27--  Every task's state, one type so the group's `admit` is one routine in
28--  the image: the source as any provider of signals, and as the fake a
29--  test raises signals into.
30waiting: type = struct
31    signals: any signal.signals
32    source: fake.signals
33end waiting
34
35--  Hear signals until SIGTERM.  Nothing in it knows the source is a fake.
36until_terminate: (inout state: waiting) -> none ! failure.reason =
37    try state.signals.watch(signal.user1)
38    try state.signals.watch(signal.terminate)
39    loop do
40        received: signal.event = try state.signals.next_signal()
41        note(received.number)
42        break when received.which == signal.terminate
43    end loop
44end until_terminate
45
46--  Take a turn, so the waiter waits first, and raise four signals.
47raise_four: (inout state: waiting) -> none ! failure.reason =
48    fibre.yield(state.source)
49    fake.raise(state.source, signal.user1)
50    fake.raise(state.source, signal.hangup)
51    fake.raise(state.source, signal.terminate)
52    fake.raise(state.source, signal.terminate)
53end raise_four
54
55--  Wait for a signal that never comes.
56wait_in_vain: (inout state: waiting) -> none ! failure.reason =
57    try state.signals.watch(signal.hangup)
58    received: signal.event = state.signals.next_signal() else (problem)
59        if problem == io.io_failed then note(0) end if
60        return
61    end
62    _ = received
63end wait_in_vain
64
65--  Module storage, so the stacks are no frame's: Cortex-M0's reset stack
66--  is 4 KiB, and its 12 KiB of RAM below that hold two stacks of 4 KiB.
67fixed if compiler.word_size == 32 then
68    mut backing: [2 * 4096]u8 = zeroed
69else
70    mut backing: [2 * 8192]u8 = zeroed
71end if
72
73run: (signals: fake.signals, counts: ptr fake.signals_space)
74     -> none ! failure.reason =
75    runs: any fibre.turns = any(addr signals)
76    mut tasks := try fibre.turns_over(runs, backing, 2)
77    defer fibre.join(tasks) else none
78    parts: waiting = (signals: any(addr signals), source: signals)
79    try fibre.admit(tasks, until_terminate, parts)
80    try fibre.admit(tasks, raise_four, parts)
81    try fibre.join(tasks)
82    fail io.io_failed when counts.val.raised <> 4
83      or counts.val.ignored <> 1 or counts.val.delivered <> 2
84      or counts.val.turns == 0
85    try fibre.admit(tasks, wait_in_vain, parts)
86    fibre.yield(signals)
87    try signal.stop_watching(signals)
88    try fibre.join(tasks)
89end run
90
91public main: () -> (code: i32) =
92    code = 1
93    mut state: stacks.round_space = zeroed
94    mut entries: [3]usize = zeroed
95    idler: stacks.spin = zeroed
96    round := stacks.round_over(state, entries, any(addr idler)) else (problem)
97        _ = problem
98        return
99    end
100    mut space: fake.signals_space = zeroed
101    signals := fake.signals_over(space, any(addr round))
102    run(signals, addr space) else (problem)
103        _ = problem
104        return
105    end
106    code = 2
107    return when count <> 3 or heard[0] <> 10 or heard[1] <> 15
108      or heard[2] <> 0
109    code = 42
110end main