GCC Code Coverage Report


Directory: ./
File: Svc/WasmSequencer/WasmSequencerInterpreter.cpp
Date: 2026-10-14 21:15:02
Exec Total Coverage
Lines: 409 419 97.6%
Functions: 43 43 100.0%
Branches: 218 238 91.6%

Line Branch Exec Source
1 // ======================================================================
2 // \title WasmSequencerInterpreter.cpp
3 // \author tumbar
4 // \brief cpp file for WasmSequencer engine state machine
5 // ======================================================================
6
7 #include "Fw/Com/ComPacket.hpp"
8 #include "Fw/Types/Assert.hpp"
9 #include "Fw/Types/LinearBufferTemplate.hpp"
10 #include "Fw/Types/Serializable.hpp"
11 #include "Fw/Types/SuccessEnumAc.hpp"
12 #include "Svc/Seq/BlockStateEnumAc.hpp"
13 #include "Svc/WasmSequencer/WasmSequencer.hpp"
14 #include "Svc/WasmSequencer/WasmSequencer_HostFunctionEnumAc.hpp"
15 #include "Svc/WasmSequencer/WasmSequencer_TrapReasonEnumAc.hpp"
16 #include "config/FwAssertArgTypeAliasAc.h"
17 #include "spacewasm.h"
18
19 namespace Svc {
20
21 // ----------------------------------------------------------------------
22 // Implementations for internal state machine actions
23 // ----------------------------------------------------------------------
24
25 23 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_cmdReplyOK(
26 SmId smId,
27 Svc_WasmSequencer_InterpreterStateMachine::Signal signal,
28 const Svc::WasmSequencer_CommandRequest& value) {
29
2/2
✓ Branch 6 taken 23 times.
✓ Branch 17 taken 23 times.
23 this->cmdResponse_out(value.get_opcode(), value.get_cmdSeq(), Fw::CmdResponse::OK);
30 23 }
31
32 225 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_signalEntered(
33 SmId smId,
34 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
35 225 this->interpreter_sendSignal_entered();
36 225 }
37
38 223 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_spin(
39 SmId smId,
40 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
41 223 FW_ASSERT(this->m_wasm);
42
43
1/1
✓ Branch 2 taken 223 times.
223 Fw::ParamValid prmValid;
44
1/1
✓ Branch 5 taken 223 times.
223 const auto fuelParam = this->paramGet_INSTRUCTION_FUEL(prmValid);
45 // Min of 1 so we don't spin the component queue forever
46
1/2
✓ Branch 0 taken 223 times.
✗ Branch 1 not taken.
223 const auto fuel = (fuelParam == 0) ? 1 : fuelParam;
47
48 223 spacewasm_trap_t trap = SPACEWASM_TRAP_NONE;
49
1/1
✓ Branch 5 taken 223 times.
223 const spacewasm_run_status_t runStatus = spacewasm_run(this->m_wasm, fuel, &trap);
50
51
4/5
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 56 times.
✗ Branch 4 not taken.
223 switch (runStatus) {
52 67 case SPACEWASM_RUN_FINISHED: {
53 67 spacewasm_value_t result;
54
1/1
✓ Branch 5 taken 67 times.
67 auto status = spacewasm_get_result(this->m_wasm, spacewasm_valtype_t::SPACEWASM_I32, &result);
55
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 if (status == SPACEWASM_ERR_NOT_FOUND) {
56 // Return status code was "void" (success)
57 ✗ this->interpreter_sendSignal_interpreterFinished(0);
58 } else {
59 67 FW_ASSERT(status == SPACEWASM_OK);
60 67 FW_ASSERT(result.tag == spacewasm_valtype_t::SPACEWASM_I32);
61
1/1
✓ Branch 5 taken 67 times.
67 this->interpreter_sendSignal_interpreterFinished(result.u.i32_);
62 }
63
64 67 break;
65 }
66 40 case SPACEWASM_RUN_TRAP:
67 // Filter out HOST traps due to exit/panic. These host functions just use trap as a mechanism
68 // to kill the interpreter.
69
8/8
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 13 times.
✓ Branch 8 taken 23 times.
✓ Branch 9 taken 4 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 21 times.
✓ Branch 12 taken 6 times.
✓ Branch 13 taken 34 times.
63 if (trap == SPACEWASM_TRAP_HOST && (this->m_exit.reason == WasmSequencer_ExitReason::HOST_EXIT ||
70 23 this->m_exit.reason == WasmSequencer_ExitReason::HOST_PANIC)) {
71
2/2
✓ Branch 6 taken 6 times.
✓ Branch 10 taken 6 times.
6 this->interpreter_sendSignal_interpreterTrap(WasmSequencer_TrapReason::NONE);
72 } else {
73
3/3
✓ Branch 6 taken 34 times.
✓ Branch 9 taken 34 times.
✓ Branch 13 taken 34 times.
34 this->interpreter_sendSignal_interpreterTrap(WasmSequencer::mapTrapReason(trap));
74 }
75 40 break;
76 60 case SPACEWASM_RUN_PAUSE:
77
1/1
✓ Branch 5 taken 60 times.
60 this->interpreter_sendSignal_interpreterHostFunctionNeedsPause();
78 60 break;
79 56 case SPACEWASM_RUN_OUT_OF_FUEL:
80
1/1
✓ Branch 5 taken 56 times.
56 this->interpreter_sendSignal_interpreterOutOfFuel();
81 56 break;
82 ✗ default:
83 ✗ FW_ASSERT(false, runStatus);
84 ✗ break;
85 }
86 446 }
87
88 364 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_reset(
89 SmId smId,
90 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
91
2/2
✓ Branch 4 taken 146 times.
✓ Branch 5 taken 218 times.
364 if (this->m_wasm != nullptr) {
92 146 auto status = spacewasm_reset(this->m_wasm);
93 146 FW_ASSERT(status == SPACEWASM_OK);
94 } else {
95 218 FW_ASSERT(signal == Svc_WasmSequencer_InterpreterStateMachine::Signal::__FPRIME_INITIAL_TRANSITION);
96 }
97 364 }
98
99 147 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_clearExitStatus(
100 SmId smId,
101 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
102 147 this->m_exit.reason = WasmSequencer_ExitReason::UNKNOWN;
103 147 this->m_exit.lastHostFunction = WasmSequencer_HostFunction::NONE;
104 147 this->m_exit.code = 0;
105 147 this->m_exit.lastTrapReason = WasmSequencer_TrapReason::NONE;
106 147 }
107
108 67 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setExitReason_INTERPRETER_FINISHED(
109 SmId smId,
110 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
111 67 this->m_exit.reason = WasmSequencer_ExitReason::INTERPRETER_FINISHED;
112 67 }
113
114 40 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setExitReason_INTERPRETER_TRAP(
115 SmId smId,
116 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
117
2/2
✓ Branch 6 taken 34 times.
✓ Branch 7 taken 6 times.
40 if (this->m_exit.reason == WasmSequencer_ExitReason::UNKNOWN) {
118 34 this->m_exit.reason = WasmSequencer_ExitReason::INTERPRETER_TRAP;
119 }
120 40 }
121
122 2 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setExitReason_REPLY_TIMEOUT(
123 SmId smId,
124 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
125 2 this->m_exit.reason = WasmSequencer_ExitReason::REPLY_TIMEOUT;
126 2 }
127
128 15 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setExitReason_HOST_FAILURE(
129 SmId smId,
130 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
131 15 this->m_exit.reason = WasmSequencer_ExitReason::HOST_FAILURE;
132 15 }
133
134 5 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setExitReason_UNEXPECTED_REPLY(
135 SmId smId,
136 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
137 5 this->m_exit.reason = WasmSequencer_ExitReason::UNEXPECTED_REPLY;
138 5 }
139
140 2 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setExitReason_TIMER_INCOMPARABLE(
141 SmId smId,
142 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
143 2 this->m_exit.reason = WasmSequencer_ExitReason::TIMER_INCOMPARABLE;
144 2 }
145
146 15 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setExitReason_CANCEL(
147 SmId smId,
148 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
149 15 this->m_exit.reason = WasmSequencer_ExitReason::CANCEL;
150 15 }
151
152 67 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setExitCode(
153 SmId smId,
154 Svc_WasmSequencer_InterpreterStateMachine::Signal signal,
155 I32 value) {
156 67 this->m_exit.code = value;
157 67 }
158
159 40 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setTrapReason(
160 SmId smId,
161 Svc_WasmSequencer_InterpreterStateMachine::Signal signal,
162 const Svc::WasmSequencer_TrapReason& value) {
163 40 this->m_exit.lastTrapReason = value;
164 40 }
165
166 60 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setLastHostFunction(
167 SmId smId,
168 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
169 60 this->m_exit.lastHostFunction = this->m_pendingHostFunction.kind;
170 60 }
171
172 146 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_finish(
173 SmId smId,
174 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
175 146 this->controller_sendSignal_engineFinished(this->m_executingContext);
176 146 }
177
178 7 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_reportPaused(
179 SmId smId,
180 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
181 7 this->log_ACTIVITY_HI_SequencePaused();
182 7 }
183
184 153 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_clearPause(
185 SmId smId,
186 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
187 153 this->m_pendingPause = false;
188 153 }
189
190 60 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_dispatchPendingHostFunction(
191 SmId smId,
192 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
193
9/11
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 5 times.
✓ Branch 10 taken 11 times.
✓ Branch 11 taken 4 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 3 times.
✓ Branch 15 taken 10 times.
✗ Branch 16 not taken.
60 switch (this->m_pendingHostFunction.kind) {
194 ✗ case WasmSequencer_HostFunction::NONE:
195 // Invalid host function
196 ✗ FW_ASSERT(false);
197 ✗ break;
198 18 case WasmSequencer_HostFunction::COMMAND:
199 18 this->dispatchCommand();
200 18 break;
201 6 case WasmSequencer_HostFunction::TELEMETRY:
202 6 this->dispatchTelemetry();
203 6 break;
204 5 case WasmSequencer_HostFunction::PARAMETER:
205 5 this->dispatchParameter();
206 5 break;
207 11 case WasmSequencer_HostFunction::EVENT:
208 11 this->dispatchEvent();
209 11 break;
210 4 case WasmSequencer_HostFunction::RSLEEP:
211 4 this->dispatchRelativeSleep();
212 4 break;
213 1 case WasmSequencer_HostFunction::ASLEEP:
214 1 this->dispatchAbsoluteSleep();
215 1 break;
216 2 case WasmSequencer_HostFunction::TIME:
217 2 this->dispatchTime();
218 2 break;
219 3 case WasmSequencer_HostFunction::SERIAL_OUT:
220 3 this->dispatchSerialOut();
221 3 break;
222 10 case WasmSequencer_HostFunction::SERIAL_RECV:
223 10 this->dispatchSerialRecv();
224 10 break;
225 }
226 60 }
227
228 32 Fw::Success WasmSequencer ::readGuestMemory(WasmSequencer_HostFunction::T kind, U32 addr, U8* dst, FwSizeType len) {
229 32 const spacewasm_status_t status = spacewasm_mem_read(this->m_pendingHostFunction.caller, addr, dst, len);
230
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 28 times.
32 if (status != SPACEWASM_OK) {
231
3/3
✓ Branch 6 taken 4 times.
✓ Branch 11 taken 4 times.
✓ Branch 15 taken 4 times.
4 this->log_WARNING_HI_HostFunctionInvalidPointer(kind, static_cast<WasmSequencer_Status::T>(status));
232 4 return Fw::Success::FAILURE;
233 } else {
234 28 return Fw::Success::SUCCESS;
235 }
236 }
237
238 30 Fw::Success WasmSequencer ::writeGuestMemory(WasmSequencer_HostFunction::T kind,
239 U32 addr,
240 const U8* src,
241 FwSizeType len) {
242 30 const spacewasm_status_t status = spacewasm_mem_write(this->m_pendingHostFunction.caller, addr, src, len);
243
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 23 times.
30 if (status != SPACEWASM_OK) {
244
3/3
✓ Branch 6 taken 7 times.
✓ Branch 11 taken 7 times.
✓ Branch 15 taken 7 times.
7 this->log_WARNING_HI_HostFunctionInvalidPointer(kind, static_cast<WasmSequencer_Status::T>(status));
245 7 return Fw::Success::FAILURE;
246 } else {
247 23 return Fw::Success::SUCCESS;
248 }
249 }
250
251 // ----------------------------------------------------------------------
252 // Per-host-function dispatch helpers (arms of dispatchPendingHostFunction)
253 // ----------------------------------------------------------------------
254
255 18 void WasmSequencer ::dispatchCommand() {
256
1/1
✓ Branch 2 taken 18 times.
18 Fw::ComBuffer cmd;
257
258 // Write the CMD descriptor to the ComBuffer
259
1/1
✓ Branch 2 taken 18 times.
18 auto serStatus = cmd.serializeFrom(static_cast<FwPacketDescriptorType>(Fw::ComPacketType::FW_PACKET_COMMAND));
260 18 FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus);
261
262 // Copy the com buffer from the guest memory into our memory
263
3/3
✓ Branch 6 taken 18 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 16 times.
36 if (this->readGuestMemory(Svc::WasmSequencer_HostFunction::COMMAND, this->m_pendingHostFunction.u.command.ptr,
264 18 cmd.getBuffAddr() + sizeof(FwPacketDescriptorType),
265 36 this->m_pendingHostFunction.u.command.len) != Fw::Success::SUCCESS) {
266
1/1
✓ Branch 5 taken 2 times.
2 this->interpreter_sendSignal_hostResponseFailure();
267 2 return;
268 }
269
270 // Memory read succeeded, update the ComBuffer to hold the encoded command
271
1/1
✓ Branch 6 taken 16 times.
16 serStatus = cmd.moveSerToOffset(this->m_pendingHostFunction.u.command.len + sizeof(FwPacketDescriptorType));
272 16 FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus);
273
274 // Dispatch command to CmdDisp. The command context (cmdUid)
275 // encodes the current sequence + command instance so we can
276 // reject late/stale responses in cmdResponseIn_handler.
277 16 this->m_tlm.commandsDispatched++;
278
279 // Start the host-function timeout clock: we are about to block in
280 // AWAITING_RESPONSE until the command response comes back in.
281
2/2
✓ Branch 3 taken 16 times.
✓ Branch 12 taken 16 times.
16 this->m_hostFunctionStart = this->getTime();
282 16 this->m_hasHostFunctionStart = true;
283
284
2/2
✓ Branch 8 taken 16 times.
✓ Branch 11 taken 16 times.
16 this->cmdOut_out(0, cmd, this->makeCmdUid());
285 18 }
286
287 6 void WasmSequencer ::dispatchTelemetry() {
288
1/1
✓ Branch 2 taken 6 times.
6 Fw::Time time;
289
1/1
✓ Branch 2 taken 6 times.
6 Fw::TlmBuffer tlmBuffer;
290
291
1/1
✓ Branch 7 taken 6 times.
6 auto valid = this->getTlmChan_out(0, this->m_pendingHostFunction.u.telemetry.chanId, time, tlmBuffer);
292
293 // Write the response into guest memory
294 6 FW_ASSERT(this->m_pendingHostFunction.u.telemetry.timeLen == Fw::Time::SERIALIZED_SIZE,
295 static_cast<FwAssertArgType>(this->m_pendingHostFunction.u.telemetry.timeLen), Fw::Time::SERIALIZED_SIZE);
296
1/1
✓ Branch 2 taken 6 times.
6 Fw::LinearBufferTemplate<Fw::Time::SERIALIZED_SIZE> timeBuf;
297
298
1/1
✓ Branch 2 taken 6 times.
6 auto serStatus = time.serializeTo(timeBuf);
299 6 FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus);
300
301 // Write the time
302
3/3
✓ Branch 3 taken 6 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 5 times.
12 if (this->writeGuestMemory(Svc::WasmSequencer_HostFunction::TELEMETRY,
303 6 this->m_pendingHostFunction.u.telemetry.timePtr, timeBuf.getBuffAddr(),
304 12 this->m_pendingHostFunction.u.telemetry.timeLen) != Fw::Success::SUCCESS) {
305
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResponseFailure();
306 1 return;
307 }
308
309
3/3
✓ Branch 2 taken 5 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 4 times.
5 if (tlmBuffer.getSize() > this->m_pendingHostFunction.u.telemetry.valueLen) {
310
2/2
✓ Branch 8 taken 1 times.
✓ Branch 12 taken 1 times.
2 this->log_WARNING_HI_BufferTooSmall(WasmSequencer_HostFunction::TELEMETRY,
311 1 this->m_pendingHostFunction.u.telemetry.valueLen,
312
1/1
✓ Branch 2 taken 1 times.
1 static_cast<U32>(tlmBuffer.getSize()));
313
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResponseFailure();
314 1 return;
315 }
316
317 // Write the value
318
4/4
✓ Branch 1 taken 4 times.
✓ Branch 6 taken 4 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 3 times.
12 if (this->writeGuestMemory(Svc::WasmSequencer_HostFunction::TELEMETRY,
319 4 this->m_pendingHostFunction.u.telemetry.valuePtr, tlmBuffer.getBuffAddr(),
320 8 tlmBuffer.getSize()) != Fw::Success::SUCCESS) {
321
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResponseFailure();
322 1 return;
323 }
324
325
2/3
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✓ Branch 9 taken 3 times.
3 this->interpreter_sendSignal_hostResumeI32(static_cast<I32>(valid.e));
326 15 }
327
328 5 void WasmSequencer ::dispatchParameter() {
329
1/1
✓ Branch 2 taken 5 times.
5 Fw::ParamBuffer prmBuf;
330
1/1
✓ Branch 7 taken 5 times.
5 auto prmStatus = this->getParam_out(0, this->m_pendingHostFunction.u.parameter.prmId, prmBuf);
331
332
3/3
✓ Branch 2 taken 5 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 4 times.
5 if (prmBuf.getSize() > this->m_pendingHostFunction.u.parameter.len) {
333
2/2
✓ Branch 8 taken 1 times.
✓ Branch 12 taken 1 times.
2 this->log_WARNING_HI_BufferTooSmall(WasmSequencer_HostFunction::PARAMETER,
334 1 this->m_pendingHostFunction.u.parameter.len,
335
1/1
✓ Branch 2 taken 1 times.
1 static_cast<U32>(prmBuf.getSize()));
336
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResponseFailure();
337 1 return;
338 }
339
340 // Write the parameter to linear memory
341
4/4
✓ Branch 1 taken 4 times.
✓ Branch 8 taken 4 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 3 times.
12 if (this->writeGuestMemory(Svc::WasmSequencer_HostFunction::PARAMETER, this->m_pendingHostFunction.u.parameter.ptr,
342 12 prmBuf.getBuffAddr(), prmBuf.getSize()) != Fw::Success::SUCCESS) {
343
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResponseFailure();
344 1 return;
345 }
346
347
2/3
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✓ Branch 9 taken 3 times.
3 this->interpreter_sendSignal_hostResumeI32(static_cast<I32>(prmStatus.e));
348 7 }
349
350 11 void WasmSequencer ::dispatchEvent() {
351 11 U8 stringStorage[FW_LOG_STRING_MAX_SIZE + 1];
352 11 FW_ASSERT(this->m_pendingHostFunction.u.event.msgLen <= FW_LOG_STRING_MAX_SIZE,
353 static_cast<FwAssertArgType>(this->m_pendingHostFunction.u.event.msgLen), FW_LOG_STRING_MAX_SIZE);
354
1/1
✓ Branch 2 taken 11 times.
11 const Fw::ExternalString msg(reinterpret_cast<char*>(stringStorage), FW_LOG_STRING_MAX_SIZE + 1);
355
356
3/3
✓ Branch 4 taken 11 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 10 times.
22 if (this->readGuestMemory(Svc::WasmSequencer_HostFunction::EVENT, this->m_pendingHostFunction.u.event.msgPtr,
357 22 stringStorage, this->m_pendingHostFunction.u.event.msgLen) != Fw::Success::SUCCESS) {
358
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResponseFailure();
359 1 return;
360 }
361 10 stringStorage[this->m_pendingHostFunction.u.event.msgLen] = 0;
362
363 // Emit the event at the guest-requested severity. FATAL and
364 // COMMAND are forbidden for guest programs (FATAL would let
365 // untrusted code trigger the FatalHandler; COMMAND is reserved
366 // for the command dispatcher). A forbidden or out-of-range
367 // severity is reported via HostFunctionInvalidSeverity, carrying
368 // the raw id and the guest message, and the guest continues.
369 10 const I32 rawSeverity = static_cast<I32>(this->m_pendingHostFunction.u.event.rawSeverity);
370
6/6
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 3 times.
10 switch (static_cast<Fw::LogSeverity::T>(rawSeverity)) {
371 1 case Fw::LogSeverity::WARNING_HI:
372
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_HI_LogWarningHi(msg);
373 1 break;
374 1 case Fw::LogSeverity::WARNING_LO:
375
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_LO_LogWarningLo(msg);
376 1 break;
377 3 case Fw::LogSeverity::ACTIVITY_HI:
378
1/1
✓ Branch 5 taken 3 times.
3 this->log_ACTIVITY_HI_LogActivityHi(msg);
379 3 break;
380 1 case Fw::LogSeverity::ACTIVITY_LO:
381
1/1
✓ Branch 5 taken 1 times.
1 this->log_ACTIVITY_LO_LogActivityLo(msg);
382 1 break;
383 1 case Fw::LogSeverity::DIAGNOSTIC:
384
1/1
✓ Branch 5 taken 1 times.
1 this->log_DIAGNOSTIC_LogDiagnostic(msg);
385 1 break;
386 3 case Fw::LogSeverity::FATAL: // fallthrough to catch restricted severities
387 case Fw::LogSeverity::COMMAND:
388 default:
389
1/1
✓ Branch 5 taken 3 times.
3 this->log_WARNING_HI_HostFunctionInvalidSeverity(rawSeverity, msg);
390 3 break;
391 }
392
393
1/1
✓ Branch 5 taken 10 times.
10 this->interpreter_sendSignal_hostResume();
394 11 }
395
396 4 void WasmSequencer ::dispatchRelativeSleep() {
397 4 const U32 seconds = static_cast<U32>(this->m_pendingHostFunction.u.rsleep.us / 1000000);
398 4 const U32 useconds = static_cast<U32>(this->m_pendingHostFunction.u.rsleep.us % 1000000);
399
400
1/1
✓ Branch 3 taken 4 times.
4 const Fw::Time now = this->getTime();
401 const U64 deadlineSeconds =
402
2/2
✓ Branch 2 taken 4 times.
✓ Branch 6 taken 4 times.
4 static_cast<U64>(now.getSeconds()) + seconds + (static_cast<U64>(now.getUSeconds()) + useconds) / 1000000u;
403
404
1/1
✓ Branch 2 taken 4 times.
4 Fw::Time timer = now;
405
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
4 if (deadlineSeconds > static_cast<U64>(std::numeric_limits<U32>::max())) {
406
1/1
✓ Branch 3 taken 1 times.
1 timer.set(std::numeric_limits<U32>::max(), 999999u);
407 } else {
408
1/1
✓ Branch 2 taken 3 times.
3 timer.add(seconds, useconds);
409 }
410
411
1/1
✓ Branch 6 taken 4 times.
4 this->m_pendingTimer = timer;
412 4 this->m_hasPendingTimer = true;
413 8 }
414
415 1 void WasmSequencer ::dispatchAbsoluteSleep() {
416 1 U32 seconds = static_cast<U32>(this->m_pendingHostFunction.u.asleep.us / 1000000);
417 1 U32 useconds = static_cast<U32>(this->m_pendingHostFunction.u.asleep.us % 1000000);
418
419 // Absolute is relative to epoch, we still need to get the time for base/context
420
1/1
✓ Branch 3 taken 1 times.
1 Fw::Time timer = this->getTime();
421
1/1
✓ Branch 2 taken 1 times.
1 timer.set(seconds, useconds);
422
423
1/1
✓ Branch 6 taken 1 times.
1 this->m_pendingTimer = timer;
424 1 this->m_hasPendingTimer = true;
425 2 }
426
427 2 void WasmSequencer ::dispatchTime() {
428
1/1
✓ Branch 3 taken 2 times.
2 auto time = this->getTime();
429
430 2 FW_ASSERT(this->m_pendingHostFunction.u.time.len == Fw::Time::SERIALIZED_SIZE,
431 static_cast<FwAssertArgType>(this->m_pendingHostFunction.u.time.len), Fw::Time::SERIALIZED_SIZE);
432
1/1
✓ Branch 2 taken 2 times.
2 Fw::LinearBufferTemplate<Fw::Time::SERIALIZED_SIZE> timeBuf;
433
434
1/1
✓ Branch 2 taken 2 times.
2 auto serStatus = time.serializeTo(timeBuf);
435 2 FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus);
436
437 // Write the time
438
3/3
✓ Branch 5 taken 2 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 1 times.
4 if (this->writeGuestMemory(Svc::WasmSequencer_HostFunction::TIME, this->m_pendingHostFunction.u.time.ptr,
439 4 timeBuf.getBuffAddr(), this->m_pendingHostFunction.u.time.len) != Fw::Success::SUCCESS) {
440
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResponseFailure();
441 1 return;
442 }
443
444
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResume();
445 3 }
446
447 3 void WasmSequencer ::dispatchSerialOut() {
448 3 const FwIndexType portNum = static_cast<FwIndexType>(this->m_pendingHostFunction.u.serialOut.index);
449
450 // Copy the payload out of guest memory into our own buffer
451
3/3
✓ Branch 6 taken 3 times.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 2 times.
6 if (this->readGuestMemory(Svc::WasmSequencer_HostFunction::SERIAL_OUT, this->m_pendingHostFunction.u.serialOut.ptr,
452 3 this->m_serialOutBuffer.getBuffAddr(),
453 6 this->m_pendingHostFunction.u.serialOut.len) != Fw::Success::SUCCESS) {
454 1 this->interpreter_sendSignal_hostResponseFailure();
455 1 return;
456 }
457
458 2 auto serStatus = this->m_serialOutBuffer.setBuffLen(this->m_pendingHostFunction.u.serialOut.len);
459 2 FW_ASSERT(serStatus == Fw::FW_SERIALIZE_OK, serStatus);
460
461 // Invoke the serial output port.
462 2 serStatus = this->serialOut_out(portNum, this->m_serialOutBuffer);
463
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (serStatus != Fw::FW_SERIALIZE_OK) {
464
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->log_WARNING_HI_SerialPortSendFailed(Svc::WasmSequencer_HostFunction::SERIAL_OUT,
465 static_cast<I32>(serStatus));
466 1 this->interpreter_sendSignal_hostResponseFailure();
467 1 return;
468 }
469
470 // Send worked, wake up the interpreter
471 1 this->interpreter_sendSignal_hostResume();
472 }
473
474 10 void WasmSequencer ::dispatchSerialRecv() {
475 10 const FwIndexType portNum = static_cast<FwIndexType>(this->m_pendingHostFunction.u.serialRecv.index);
476 10 FW_ASSERT(portNum < NUM_SERIALIN_INPUT_PORTS, portNum);
477
1/1
✓ Branch 5 taken 10 times.
10 Os::ScopeLock scopeLock(this->m_serialInMutex);
478 10 auto& queue = this->m_serialInQueue[portNum];
479
480 // Check if there is an available message on the queue
481
3/3
✓ Branch 2 taken 10 times.
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 3 times.
10 if (queue.get_allocated_size() > 0) {
482 // There is data available signal to the state machine to pull this data and wake up without blocking
483
1/1
✓ Branch 5 taken 7 times.
7 this->interpreter_sendSignal_serialInMessage(portNum);
484 } else {
485 // Check if we should block or not
486
3/5
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
3 switch (this->m_pendingHostFunction.u.serialRecv.blockingType) {
487 2 case Svc::BlockState::BLOCK:
488 // Do not immediately resume the interpreter, this will let the state machine asynchronously
489 // wait for a signal that we got a message (or timeout).
490
2/2
✓ Branch 3 taken 2 times.
✓ Branch 12 taken 2 times.
2 this->m_hostFunctionStart = this->getTime();
491 2 this->m_hasHostFunctionStart = true;
492 2 break;
493 1 case Svc::BlockState::NO_BLOCK:
494 // We are non-blocking and the queue is empty, report this back to the interpreter and wake back
495 // up
496 1 constexpr I32 FPRIME_SERIAL_RECV_QUEUE_STATUS_EMPTY = 1;
497
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResumeI32(FPRIME_SERIAL_RECV_QUEUE_STATUS_EMPTY);
498 1 break;
499 }
500 }
501 20 }
502
503 205 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_clearPendingHostFunction(
504 SmId smId,
505 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
506 205 this->m_pendingHostFunction.kind = WasmSequencer_HostFunction::NONE;
507 205 this->m_pendingHostFunction.caller = nullptr;
508 205 this->m_hasPendingTimer = false;
509 205 this->m_hasHostFunctionStart = false;
510 205 }
511
512 147 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_setContext(
513 SmId smId,
514 Svc_WasmSequencer_InterpreterStateMachine::Signal signal,
515 const Svc::WasmSequencer_RequestContext& value) {
516 147 FW_ASSERT(!this->m_hasExecutingContext);
517 147 this->m_hasExecutingContext = true;
518 147 this->m_executingContext = value;
519
520 // A fresh execution window is starting. Bump the sequence counter so any command
521 // dispatched from this program carries a distinct cmdUid
522 147 this->m_sequencesStarted++;
523 147 }
524
525 364 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_clearContext(
526 SmId smId,
527 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
528 364 this->m_hasExecutingContext = false;
529 364 }
530
531 14 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_resume(
532 SmId smId,
533 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
534 14 FW_ASSERT(this->m_wasm != nullptr);
535 14 auto status = spacewasm_resume(this->m_wasm);
536 14 FW_ASSERT(status == SPACEWASM_OK, status);
537 14 }
538
539 17 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_resumeI32(
540 SmId smId,
541 Svc_WasmSequencer_InterpreterStateMachine::Signal signal,
542 I32 value) {
543 17 FW_ASSERT(this->m_wasm != nullptr);
544 17 spacewasm_value_t return_val;
545 17 return_val.tag = SPACEWASM_I32;
546 17 return_val.u.i32_ = value;
547
548
1/1
✓ Branch 5 taken 17 times.
17 auto status = spacewasm_resume_value(this->m_wasm, return_val);
549 17 FW_ASSERT(status == SPACEWASM_OK, status);
550 17 }
551
552 5 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_checkSleepTimers(
553 SmId smId,
554 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
555 // Check if we have overrun the timer
556 5 FW_ASSERT(this->m_hasPendingTimer);
557
558
1/1
✓ Branch 3 taken 5 times.
5 const Fw::Time now = this->getTime();
559
4/5
✓ Branch 5 taken 5 times.
✓ Branch 14 taken 2 times.
✓ Branch 15 taken 2 times.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
5 switch (Fw::Time::compare(now, this->m_pendingTimer)) {
560 2 case Fw::TimeComparison::LT:
561 // No timer overrun
562 2 break;
563 2 case Fw::TimeComparison::EQ:
564 case Fw::TimeComparison::GT: {
565 // Timeout!
566
1/1
✓ Branch 5 taken 2 times.
2 this->interpreter_sendSignal_hostResume();
567 2 break;
568 }
569 1 case Fw::TimeComparison::INCOMPARABLE:
570 // Time base / context changed since we set the timer
571
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResponseTimeIncomparable();
572 1 break;
573 }
574 10 }
575
576 6 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_checkTimeout(
577 SmId smId,
578 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) {
579 // Only blocking host functions that await an external event are subject to the
580 // host-function timeout (COMMAND -> cmdResponseIn, blocking SERIAL_RECV -> serialIn).
581 // Sleeps have their own wake timer (checkSleepTimers), separate from this timeout.
582
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
6 if (!this->m_hasHostFunctionStart) {
583 ✗ return;
584 }
585
586
1/1
✓ Branch 2 taken 6 times.
6 Fw::ParamValid prmValid;
587
1/1
✓ Branch 5 taken 6 times.
6 const F32 timeoutSecs = this->paramGet_HOST_FUNCTION_TIMEOUT_SECS(prmValid);
588
589 // A non-positive or out-of-range timeout disables the check entirely.
590
5/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 5 times.
6 if (timeoutSecs <= 0.0f || timeoutSecs >= static_cast<F32>(std::numeric_limits<U32>::max())) {
591 1 return;
592 }
593
594 // Deadline = function start + timeout. Round microseconds up so the timeout
595 // is never reported early.
596 5 U32 seconds = static_cast<U32>(timeoutSecs);
597 5 U32 useconds = static_cast<U32>((timeoutSecs - static_cast<F32>(seconds)) * 1000000.0f + 0.5f);
598
599 // Rounding up can push the microsecond field to 1000000; carry it into
600 // seconds so Fw::Time::add() always receives a normalized (< 1e6) value.
601
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (useconds >= 1000000u) {
602 ✗ seconds += useconds / 1000000u;
603 ✗ useconds %= 1000000u;
604 }
605
606
1/1
✓ Branch 5 taken 5 times.
5 Fw::Time deadline = this->m_hostFunctionStart;
607
1/1
✓ Branch 2 taken 5 times.
5 deadline.add(seconds, useconds);
608
609
1/1
✓ Branch 3 taken 5 times.
5 const Fw::Time now = this->getTime();
610
4/5
✓ Branch 2 taken 5 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
5 switch (Fw::Time::compare(now, deadline)) {
611 2 case Fw::TimeComparison::LT:
612 // Deadline not yet reached.
613 2 break;
614 2 case Fw::TimeComparison::EQ:
615 case Fw::TimeComparison::GT:
616 // Host function timed out waiting for its reply.
617
1/1
✓ Branch 5 taken 2 times.
2 this->interpreter_sendSignal_hostResponseTimeout();
618 2 break;
619 1 case Fw::TimeComparison::INCOMPARABLE:
620 // Time base / context changed since the host function started.
621
1/1
✓ Branch 5 taken 1 times.
1 this->interpreter_sendSignal_hostResponseTimeIncomparable();
622 1 break;
623 }
624 6 }
625
626 8 void WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_action_dequeueSerialAndResume(
627 SmId smId,
628 Svc_WasmSequencer_InterpreterStateMachine::Signal signal,
629 const FwIndexType& value) {
630 8 const FwIndexType portNum = static_cast<FwIndexType>(this->m_pendingHostFunction.u.serialRecv.index);
631 8 FW_ASSERT(portNum < NUM_SERIALIN_INPUT_PORTS, portNum);
632
1/1
✓ Branch 5 taken 8 times.
8 Os::ScopeLock scopeLock(this->m_serialInMutex);
633 8 auto& queue = this->m_serialInQueue[portNum];
634
635 8 this->m_dequeueSucceeded = false;
636
637 // Message is available, pull out the size
638 8 U32 msgSize;
639
1/1
✓ Branch 2 taken 8 times.
8 auto status = queue.peek(msgSize);
640 8 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
641
642
2/2
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 7 times.
8 if (msgSize > this->m_pendingHostFunction.u.serialRecv.dataSize) {
643
2/2
✓ Branch 8 taken 1 times.
✓ Branch 12 taken 1 times.
2 this->log_WARNING_HI_BufferTooSmall(Svc::WasmSequencer_HostFunction::SERIAL_RECV,
644 1 this->m_pendingHostFunction.u.serialRecv.dataSize, msgSize);
645 // The frame doesn't fit in the guest's buffer and never will; drop it from the queue
646 // so it doesn't poison every subsequent serial_recv call on this port.
647
1/1
✓ Branch 2 taken 1 times.
1 status = queue.rotate(static_cast<U32>(sizeof(U32)) + msgSize);
648 1 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
649 1 return;
650 }
651
652 // The queue holds [U32 size][payload]; skip the size prefix when copying the payload.
653 7 const U32 queuePayloadStart = sizeof(U32);
654 7 const U32 dataSize = static_cast<U32>(sizeof(U32)) + msgSize;
655
656 // Write the message size in little endian to the guest memory
657
1/1
✓ Branch 2 taken 7 times.
7 Fw::LinearBufferTemplate<sizeof(U32)> msgSizeSer;
658
1/1
✓ Branch 2 taken 7 times.
7 status = msgSizeSer.serializeFrom(msgSize, Fw::Endianness::LITTLE);
659 7 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
660
661
3/3
✓ Branch 3 taken 7 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 6 times.
14 if (this->writeGuestMemory(Svc::WasmSequencer_HostFunction::SERIAL_RECV,
662 7 this->m_pendingHostFunction.u.serialRecv.actualSizePtr, msgSizeSer.getBuffAddr(),
663 14 sizeof(U32)) != Fw::Success::SUCCESS) {
664 1 return;
665 }
666
667 // Pull the message off the queue, we may need to do it in multiple chunks
668 6 constexpr U32 CHUNK_SIZE = 32;
669 6 U8 scratch[CHUNK_SIZE];
670
671 // Pull all the full chunks off the queue
672 6 U32 queueOffset = queuePayloadStart;
673
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
8 for (; (queueOffset + CHUNK_SIZE) <= dataSize; queueOffset += CHUNK_SIZE) {
674
1/1
✓ Branch 2 taken 3 times.
3 status = queue.peek(scratch, CHUNK_SIZE, queueOffset);
675 3 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
676
677 // Copy the data into the guest memory
678
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2 times.
3 if (this->writeGuestMemory(Svc::WasmSequencer_HostFunction::SERIAL_RECV,
679
1/1
✓ Branch 5 taken 3 times.
3 this->m_pendingHostFunction.u.serialRecv.dataPtr + (queueOffset - queuePayloadStart),
680 6 scratch, CHUNK_SIZE) != Fw::Success::SUCCESS) {
681 1 return;
682 }
683 }
684
685 // Pull out the final partial chunk
686
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 if (queueOffset < dataSize) {
687 4 const U32 remaining = dataSize - queueOffset;
688 4 FW_ASSERT(remaining < CHUNK_SIZE, static_cast<FwAssertArgType>(dataSize),
689 static_cast<FwAssertArgType>(queueOffset), CHUNK_SIZE);
690
691
1/1
✓ Branch 2 taken 4 times.
4 status = queue.peek(scratch, remaining, queueOffset);
692 4 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
693
694 // Copy the data into the guest memory
695
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 3 times.
4 if (this->writeGuestMemory(Svc::WasmSequencer_HostFunction::SERIAL_RECV,
696
1/1
✓ Branch 5 taken 4 times.
4 this->m_pendingHostFunction.u.serialRecv.dataPtr + (queueOffset - queuePayloadStart),
697 8 scratch, remaining) != Fw::Success::SUCCESS) {
698 1 return;
699 }
700 }
701
702 // Dequeue the message now that we fully copied it into guest memory
703
1/1
✓ Branch 2 taken 4 times.
4 status = queue.rotate(dataSize);
704 4 FW_ASSERT(status == Fw::FW_SERIALIZE_OK);
705
706 4 this->m_dequeueSucceeded = true;
707
708 // Yay, we successfully dequeued a message from the queue, wake up the interpreter to tell it about our success
709 4 constexpr I32 FPRIME_SERIAL_RECV_QUEUE_STATUS_OK = 0;
710 4 spacewasm_value_t return_val;
711 4 return_val.tag = SPACEWASM_I32;
712 4 return_val.u.i32_ = FPRIME_SERIAL_RECV_QUEUE_STATUS_OK;
713
714
1/1
✓ Branch 5 taken 4 times.
4 auto resumeStatus = spacewasm_resume_value(this->m_wasm, return_val);
715 4 FW_ASSERT(resumeStatus == SPACEWASM_OK, resumeStatus);
716 11 }
717
718 // ----------------------------------------------------------------------
719 // Implementations for internal state machine guards
720 // ----------------------------------------------------------------------
721
722 289 bool WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_guard_pendingPause(
723 SmId smId,
724 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) const {
725
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 289 times.
289 return this->m_pendingPause;
726 }
727
728 3 bool WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_guard_pendingHostFunction(
729 SmId smId,
730 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) const {
731 3 return this->m_pendingHostFunction.isPending();
732 }
733
734 60 bool WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_guard_pendingHostFunctionIsSleep(
735 SmId smId,
736 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) const {
737
4/4
✓ Branch 11 taken 59 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 55 times.
119 return this->m_pendingHostFunction.kind == WasmSequencer_HostFunction::ASLEEP ||
738 119 this->m_pendingHostFunction.kind == WasmSequencer_HostFunction::RSLEEP;
739 }
740
741 8 bool WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_guard_blockingSerialIn(
742 SmId smId,
743 Svc_WasmSequencer_InterpreterStateMachine::Signal signal,
744 const FwIndexType& value) const {
745
1/2
✓ Branch 11 taken 8 times.
✗ Branch 12 not taken.
16 return (this->m_pendingHostFunction.kind == Svc::WasmSequencer_HostFunction::SERIAL_RECV &&
746
1/2
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
16 this->m_pendingHostFunction.u.serialRecv.index == static_cast<U32>(value));
747 }
748
749 8 bool WasmSequencer ::Svc_WasmSequencer_InterpreterStateMachine_guard_dequeueSucceeded(
750 SmId smId,
751 Svc_WasmSequencer_InterpreterStateMachine::Signal signal) const {
752
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
8 return this->m_dequeueSucceeded;
753 }
754
755 } // namespace Svc
756