GCC Code Coverage Report


Directory: Svc/WasmSequencer/
File: WasmSequencerController.cpp
Date: 2026-09-23 21:15:03
Exec Total Coverage
Lines: 219 224 97.8%
Functions: 34 34 100.0%
Branches: 139 143 97.2%

Line Branch Exec Source
1 // ======================================================================
2 // \title WasmSequencerController.cpp
3 // \author tumbar
4 // \brief cpp file for WasmSequencer controller state machine
5 // ======================================================================
6
7 #include "Fw/Cmd/CmdResponseEnumAc.hpp"
8 #include "Fw/Types/Assert.hpp"
9 #include "Os/File.hpp"
10 #include "Svc/Seq/BlockStateEnumAc.hpp"
11 #include "Svc/WasmSequencer/WasmSequencer.hpp"
12 #include "Svc/WasmSequencer/WasmSequencer_LoadRequestSerializableAc.hpp"
13 #include "Svc/WasmSequencer/WasmSequencer_ModuleIdxAliasAc.hpp"
14 #include "Svc/WasmSequencer/WasmSequencer_SignalSourceEnumAc.hpp"
15 #include "config/FwAssertArgTypeAliasAc.h"
16 #include "spacewasm.h"
17
18 namespace Svc {
19
20 // ----------------------------------------------------------------------
21 // Implementations for internal state machine actions
22 // ----------------------------------------------------------------------
23
24 11 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_processInvoke(
25 SmId smId,
26 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
27 const Svc::WasmSequencer_InvokeRequest& value) {
28 // Resolve the module name to its index within the engine.
29 11 FW_ASSERT(this->m_wasm != nullptr);
30 11 U32 moduleIdx = 0;
31 const spacewasm_status_t findStatus =
32
1/1
✓ Branch 13 taken 11 times.
11 spacewasm_find_module(this->m_wasm, value.get_moduleName().toChar(), &moduleIdx);
33
34
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 if (findStatus != SPACEWASM_OK) {
35
1/1
✓ Branch 11 taken 2 times.
2 this->log_WARNING_LO_ModuleNotFound(value.get_moduleName());
36
1/1
✓ Branch 9 taken 2 times.
2 this->controller_sendSignal_invokeFailed(value.get_context());
37 } else {
38 // Store the arguments for the ARGS host function round trip and carry the
39 // resolved module index forward in the request context.
40
1/1
✓ Branch 10 taken 9 times.
9 this->m_args = value.get_args();
41
1/1
✓ Branch 6 taken 9 times.
9 Svc::WasmSequencer_RequestContext context = value.get_context();
42
1/1
✓ Branch 2 taken 9 times.
9 context.set_moduleIdx(static_cast<WasmSequencer_ModuleIdx>(moduleIdx));
43
1/1
✓ Branch 5 taken 9 times.
9 this->controller_sendSignal_invoked(context);
44 9 }
45 11 }
46
47 142 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_respond_noblock_OK(
48 SmId smId,
49 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
50 const Svc::WasmSequencer_RequestContext& value) {
51 // Respond only to NO_BLOCK requests
52
2/2
✓ Branch 4 taken 29 times.
✓ Branch 5 taken 113 times.
142 if (value.get_block() == Svc::BlockState::NO_BLOCK) {
53 // Respond to this request!
54
2/2
✓ Branch 5 taken 29 times.
✓ Branch 9 taken 29 times.
29 this->respondToRequest(value, Fw::CmdResponse::OK);
55 }
56 142 }
57
58 28 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_respond_ERROR(
59 SmId smId,
60 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
61 const Svc::WasmSequencer_RequestContext& value) {
62
2/2
✓ Branch 5 taken 28 times.
✓ Branch 9 taken 28 times.
28 this->respondToRequest(value, Fw::CmdResponse::EXECUTION_ERROR);
63
64 // Respond to all wait requests
65
2/2
✓ Branch 5 taken 28 times.
✓ Branch 9 taken 28 times.
28 this->respondToWaiting(Fw::CmdResponse::EXECUTION_ERROR);
66
67 // Respond to port requests
68
2/2
✓ Branch 5 taken 28 times.
✓ Branch 9 taken 28 times.
28 this->reportSeqAborted(value, Fw::CmdResponse::EXECUTION_ERROR);
69 28 }
70
71 24 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_incrementSequenceFailure(
72 SmId smId,
73 Svc_WasmSequencer_ControllerStateMachine::Signal signal) {
74 24 this->m_tlm.sequencesFailed++;
75 24 }
76
77 8 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_setCancelRequested(
78 SmId smId,
79 Svc_WasmSequencer_ControllerStateMachine::Signal signal) {
80 8 this->m_cancelRequested = true;
81 8 }
82
83 450 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_clearCancelRequested(
84 SmId smId,
85 Svc_WasmSequencer_ControllerStateMachine::Signal signal) {
86 450 this->m_cancelRequested = false;
87 450 }
88
89 7 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_cancelPendingRequest(
90 SmId smId,
91 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
92 const Svc::WasmSequencer_RequestContext& value) {
93 7 this->m_tlm.sequencesCancelled++;
94
2/2
✓ Branch 5 taken 7 times.
✓ Branch 9 taken 7 times.
7 this->respondToRequest(value, Fw::CmdResponse::EXECUTION_ERROR);
95
2/2
✓ Branch 5 taken 7 times.
✓ Branch 9 taken 7 times.
7 this->respondToWaiting(Fw::CmdResponse::EXECUTION_ERROR);
96
97 // Respond to port requests
98
2/2
✓ Branch 5 taken 7 times.
✓ Branch 9 taken 7 times.
7 this->reportSeqAborted(value, Fw::CmdResponse::EXECUTION_ERROR);
99 7 }
100
101 1 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_respondInvoke_BUSY(
102 SmId smId,
103 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
104 const Svc::WasmSequencer_InvokeRequest& value) {
105
3/3
✓ Branch 7 taken 1 times.
✓ Branch 20 taken 1 times.
✓ Branch 24 taken 1 times.
1 this->log_WARNING_LO_ControllerBusy(value.get_context().get_source(), this->controller_getState());
106
2/2
✓ Branch 5 taken 1 times.
✓ Branch 13 taken 1 times.
1 this->respondToRequest(value.get_context(), Fw::CmdResponse::BUSY);
107 1 }
108
109 1 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_respondInvoke_ERROR(
110 SmId smId,
111 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
112 const Svc::WasmSequencer_InvokeRequest& value) {
113 1 this->log_WARNING_LO_ControllerCannotInvoke();
114
2/2
✓ Branch 5 taken 1 times.
✓ Branch 13 taken 1 times.
1 this->respondToRequest(value.get_context(), Fw::CmdResponse::EXECUTION_ERROR);
115 1 }
116
117 3 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_respondLoad_BUSY(
118 SmId smId,
119 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
120 const Svc::WasmSequencer_LoadRequest& value) {
121
3/3
✓ Branch 7 taken 3 times.
✓ Branch 20 taken 3 times.
✓ Branch 24 taken 3 times.
3 this->log_WARNING_LO_ControllerBusy(value.get_context().get_source(), this->controller_getState());
122
2/2
✓ Branch 5 taken 3 times.
✓ Branch 13 taken 3 times.
3 this->respondToRequest(value.get_context(), Fw::CmdResponse::BUSY);
123
124 // Respond to port requests
125
2/2
✓ Branch 5 taken 3 times.
✓ Branch 13 taken 3 times.
3 this->reportSeqAborted(value.get_context(), Fw::CmdResponse::BUSY);
126 3 }
127
128 110 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_respond_block_OK(
129 SmId smId,
130 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
131 const Svc::WasmSequencer_RequestContext& value) {
132 // Respond only to BLOCK requests
133
2/2
✓ Branch 4 taken 96 times.
✓ Branch 5 taken 14 times.
110 if (value.get_block() == Svc::BlockState::BLOCK) {
134 // Respond to this request!
135
2/2
✓ Branch 5 taken 96 times.
✓ Branch 9 taken 96 times.
96 this->respondToRequest(value, Fw::CmdResponse::OK);
136 }
137
138 // Respond to all wait requests
139
2/2
✓ Branch 5 taken 110 times.
✓ Branch 9 taken 110 times.
110 this->respondToWaiting(Fw::CmdResponse::OK);
140
141 // If this concluded an active RUN, report the done to internal callers.
142
2/2
✓ Branch 5 taken 110 times.
✓ Branch 9 taken 110 times.
110 this->reportSeqDone(value, Fw::CmdResponse::OK);
143 110 }
144
145 77 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_respond_block_ERROR(
146 SmId smId,
147 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
148 const Svc::WasmSequencer_RequestContext& value) {
149 // Respond only to BLOCK requests
150
2/2
✓ Branch 4 taken 62 times.
✓ Branch 5 taken 15 times.
77 if (value.get_block() == Svc::BlockState::BLOCK) {
151 // Respond to this request!
152
2/2
✓ Branch 5 taken 62 times.
✓ Branch 9 taken 62 times.
62 this->respondToRequest(value, Fw::CmdResponse::EXECUTION_ERROR);
153 }
154
155 // Respond to all wait requests
156
2/2
✓ Branch 5 taken 77 times.
✓ Branch 9 taken 77 times.
77 this->respondToWaiting(Fw::CmdResponse::EXECUTION_ERROR);
157
158 // If this concluded an active RUN, report the done to internal callers.
159
2/2
✓ Branch 5 taken 77 times.
✓ Branch 9 taken 77 times.
77 this->reportSeqDone(value, Fw::CmdResponse::EXECUTION_ERROR);
160 77 }
161
162 212 bool WasmSequencer ::resolveSequencePath(const Fw::StringBase& fileName, Fw::String& filePath) {
163 // Resolve the requested path against the SEQ_BASE_DIR parameter
164
1/1
✓ Branch 2 taken 212 times.
212 Fw::ParamValid baseDirValid;
165
1/1
✓ Branch 3 taken 212 times.
212 const Fw::ParamString baseDir = this->paramGet_SEQ_BASE_DIR(baseDirValid);
166
167
3/3
✓ Branch 2 taken 212 times.
✓ Branch 4 taken 207 times.
✓ Branch 5 taken 5 times.
212 if (baseDir.length() == 0) {
168
1/1
✓ Branch 7 taken 207 times.
207 filePath = fileName;
169 207 return true;
170 }
171
172 // With a base dir configured, SEQ_BASE_DIR acts as a containment boundary.
173 // A ground-supplied file name containing a ".." component could escape it
174 // (e.g. "../../etc/passwd"), so reject such names rather than opening a path
175 // outside the configured base directory.
176
3/3
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 4 times.
5 if (WasmSequencer::pathHasParentTraversal(fileName)) {
177
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_HI_SequenceFilePathNotContained(baseDir, fileName);
178 1 return false;
179 }
180
181 // Join the base dir and file name with exactly one '/' separator. Without an
182 // explicit separator a base dir that lacks a trailing slash both mis-resolves
183 // ordinary names ("seqs" + "a.wasm" -> "seqsa.wasm") and can escape the
184 // containment boundary ("seqs" + "_priv/x.wasm" -> "seqs_priv/x.wasm", a sibling
185 // directory). The ".." rejection above plus a guaranteed base-dir prefix keeps
186 // the resolved path inside the configured directory.
187
1/1
✓ Branch 2 taken 4 times.
4 const FwSizeType baseLen = static_cast<FwSizeType>(baseDir.length());
188
3/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 2 times.
4 const char* const separator = (baseLen > 0 && baseDir.toChar()[baseLen - 1] == '/') ? "" : "/";
189
190
2/2
✓ Branch 15 taken 4 times.
✓ Branch 20 taken 4 times.
4 const Fw::FormatStatus fmtStatus = filePath.format("%s%s%s", baseDir.toChar(), separator, fileName.toChar());
191
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
4 if (fmtStatus != Fw::FormatStatus::SUCCESS) {
192 1 FW_ASSERT(fmtStatus == Fw::FormatStatus::OVERFLOWED, static_cast<FwAssertArgType>(fmtStatus));
193
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_HI_SequenceFilePathTooLong(baseDir, fileName);
194 1 return false;
195 }
196
197 3 return true;
198 212 }
199
200 namespace {
201 struct WasmFileReader {
202 204 explicit WasmFileReader(Os::File& loadFile) : m_loadFile(loadFile) {}
203
204 402 spacewasm_read_result_t readChunk(const U8** outBuf, std::size_t* outLen) {
205 402 FwSizeType size = sizeof(this->m_readBuf);
206
1/1
✓ Branch 7 taken 402 times.
402 const Os::File::Status status = this->m_loadFile.read(this->m_readBuf, size);
207
208 spacewasm_read_result_t readStatus;
209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 402 times.
402 if (status != Os::File::Status::OP_OK) {
210 ✗ *outLen = 0;
211 ✗ readStatus = SPACEWASM_READ_ERROR;
212 } else {
213 // `size` is updated in-place with the number of bytes actually read.
214 402 *outBuf = this->m_readBuf;
215 402 *outLen = static_cast<std::size_t>(size);
216
217
2/2
✓ Branch 0 taken 198 times.
✓ Branch 1 taken 204 times.
402 if (size == 0) {
218 198 readStatus = SPACEWASM_READ_EOF;
219 } else {
220 204 readStatus = SPACEWASM_READ_OK;
221 }
222 }
223
224 402 return readStatus;
225 }
226
227 402 static spacewasm_read_result_t readChunkCallback(void* userdata, const U8** outBuf, size_t* outLen) {
228 402 FW_ASSERT(userdata != nullptr);
229 402 return static_cast<WasmFileReader*>(userdata)->readChunk(outBuf, outLen);
230 }
231
232 //! Currently loading file handle
233 Os::File& m_loadFile;
234
235 //! Buffer handed to the streaming loader, filled from `m_loadFile`.
236 U8 m_readBuf[Svc::WasmSequencerConfig::LOAD_READ_CHUNK_SIZE]{};
237 };
238 } // namespace
239
240 212 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_load(
241 SmId smId,
242 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
243 const Svc::WasmSequencer_LoadRequest& value) {
244 212 FW_ASSERT(this->m_wasm != nullptr);
245 212 FW_ASSERT(this->m_guest_allocator != nullptr);
246
247
1/1
✓ Branch 10 taken 212 times.
212 this->m_args = value.get_args();
248
249 // Resolve the sequence file path against SEQ_BASE_DIR
250
1/1
✓ Branch 2 taken 212 times.
212 Fw::String filePath;
251
3/3
✓ Branch 10 taken 212 times.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 210 times.
212 if (!this->resolveSequencePath(value.get_fileName(), filePath)) {
252
1/1
✓ Branch 9 taken 2 times.
2 this->controller_sendSignal_loadFailed(value.get_context());
253 2 return;
254 }
255
256 // Record the sequence name for telemetry (module name, or filename stem).
257
1/1
✓ Branch 10 taken 210 times.
210 this->setSequenceName(filePath, value.get_moduleName());
258
259
1/1
✓ Branch 2 taken 210 times.
210 Os::File file;
260
1/1
✓ Branch 4 taken 210 times.
210 const Os::File::Status openStatus = file.open(filePath.toChar(), Os::File::OPEN_READ);
261
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 204 times.
210 if (openStatus != Os::File::Status::OP_OK) {
262
1/1
✓ Branch 5 taken 6 times.
6 this->log_WARNING_HI_FileOpenError(filePath, openStatus);
263
1/1
✓ Branch 9 taken 6 times.
6 this->controller_sendSignal_loadFailed(value.get_context());
264 6 return;
265 }
266
267
1/1
✓ Branch 12 taken 204 times.
204 this->m_lastLoadFileName = value.get_fileName();
268
269
1/1
✓ Branch 4 taken 204 times.
204 this->takeAllocatorLock();
270
271 204 U32 moduleIndex = 0;
272
1/1
✓ Branch 6 taken 204 times.
204 Svc::WasmSequencer_RequestContext next = value.get_context();
273
274 204 WasmFileReader reader(file);
275
276 auto status =
277
1/1
✓ Branch 15 taken 204 times.
204 spacewasm_load_module(this->m_wasm, value.get_moduleName().toChar(), &WasmFileReader::readChunkCallback,
278 204 &reader, this->m_guest_allocator, &moduleIndex);
279
280
1/1
✓ Branch 2 taken 204 times.
204 next.set_moduleIdx(static_cast<WasmSequencer_ModuleIdx>(moduleIndex));
281
282
1/1
✓ Branch 4 taken 204 times.
204 this->releaseAllocatorLock();
283
284
1/1
✓ Branch 2 taken 204 times.
204 file.close();
285
286
2/2
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 7 times.
204 if (status == SPACEWASM_OK) {
287
1/1
✓ Branch 5 taken 197 times.
197 this->controller_sendSignal_loadSucceeded(next);
288 } else {
289
2/2
✓ Branch 6 taken 7 times.
✓ Branch 10 taken 7 times.
7 this->log_WARNING_HI_ModuleLoadFailed(WasmSequencer_Status(status));
290
1/1
✓ Branch 9 taken 7 times.
7 this->controller_sendSignal_loadFailed(value.get_context());
291 }
292 218 }
293
294 13 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_invokeStart(
295 SmId smId,
296 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
297 const Svc::WasmSequencer_RequestContext& value) {
298 13 U32 start_module_idx;
299 13 U32 start_function_idx;
300
301 // Get the module's start function WasmRef
302
1/1
✓ Branch 9 taken 13 times.
13 auto status = spacewasm_module_start(this->m_wasm, value.get_moduleIdx(), &start_module_idx, &start_function_idx);
303 13 FW_ASSERT(status == SPACEWASM_OK, status);
304
305
1/1
✓ Branch 7 taken 13 times.
13 this->m_invokeStatus = spacewasm_invoke(this->m_wasm, start_module_idx, start_function_idx, nullptr, 0);
306 13 }
307
308 144 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_invokeMain(
309 SmId smId,
310 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
311 const Svc::WasmSequencer_RequestContext& value) {
312 // Resolve the main function of given module index
313 144 U32 funcIndex = 0;
314
1/1
✓ Branch 9 taken 144 times.
144 auto status = spacewasm_find_export_func(this->m_wasm, static_cast<U32>(value.get_moduleIdx()), "main", &funcIndex);
315
316 // This should always succeed because our state machine is checking whether this module has a main/is-valid
317 144 FW_ASSERT(status == SPACEWASM_OK, status);
318
319 288 this->m_invokeStatus =
320
1/1
✓ Branch 10 taken 144 times.
288 spacewasm_invoke(this->m_wasm, static_cast<U32>(value.get_moduleIdx()), funcIndex, nullptr, 0);
321 144 }
322 3 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_reportModuleInvalidMain(
323 SmId smId,
324 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
325 const Svc::WasmSequencer_RequestContext& value) {
326 // Get the failure status of why the main module is invalid
327 3 auto problemStatus = this->validateModuleMain(value.get_moduleIdx());
328
2/2
✓ Branch 6 taken 3 times.
✓ Branch 14 taken 3 times.
3 this->log_WARNING_HI_InvalidModuleEntrypoint(value.get_moduleIdx(), WasmSequencer_Status(problemStatus));
329 3 }
330
331 2 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_reportModuleMainInvokeFailed(
332 SmId smId,
333 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
334 const Svc::WasmSequencer_RequestContext& value) {
335
2/2
✓ Branch 10 taken 2 times.
✓ Branch 14 taken 2 times.
2 this->log_WARNING_HI_ModuleMainInvokeFailed(WasmSequencer_Status(this->m_invokeStatus));
336 2 }
337
338 2 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_reportModuleStartInvokeFailed(
339 SmId smId,
340 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
341 const Svc::WasmSequencer_RequestContext& value) {
342
2/2
✓ Branch 10 taken 2 times.
✓ Branch 14 taken 2 times.
2 this->log_WARNING_HI_ModuleStartInvokeFailed(WasmSequencer_Status(this->m_invokeStatus));
343 2 }
344
345 142 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_reportModuleStarted(
346 SmId smId,
347 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
348 const Svc::WasmSequencer_RequestContext& value) {
349 142 this->log_ACTIVITY_HI_SequenceStarting(value.get_moduleIdx());
350
6/6
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 131 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 134 times.
✓ Branch 9 taken 8 times.
153 if (value.get_source() == Svc::WasmSequencer_SignalSource::COMMAND_RUN ||
351 11 value.get_source() == Svc::WasmSequencer_SignalSource::PORT_RUN) {
352
2/2
✓ Branch 5 taken 133 times.
✓ Branch 6 taken 1 times.
134 if (this->isConnected_seqStartOut_OutputPort(0)) {
353 133 this->seqStartOut_out(0, this->m_lastLoadFileName, this->m_args);
354 }
355 }
356 142 }
357
358 341 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_resetStore(
359 SmId smId,
360 Svc_WasmSequencer_ControllerStateMachine::Signal signal) {
361
2/2
✓ Branch 4 taken 224 times.
✓ Branch 5 taken 117 times.
341 if (this->m_wasm == nullptr) {
362 // The store has not been created yet.
363 // This should be the initial transition
364 224 FW_ASSERT(signal == Svc_WasmSequencer_ControllerStateMachine::Signal::__FPRIME_INITIAL_TRANSITION,
365 static_cast<FwAssertArgType>(signal));
366
367 // `configure()` will initialize the first store
368 } else {
369 117 this->destroyStore();
370 117 this->createStore();
371 }
372 341 }
373
374 153 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_runEngine(
375 SmId smId,
376 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
377 const Svc::WasmSequencer_RequestContext& value) {
378 153 this->interpreter_sendSignal_run(value);
379 153 }
380
381 64 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_reportModuleSucceeded(
382 SmId smId,
383 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
384 const Svc::WasmSequencer_RequestContext& value) {
385 64 this->m_tlm.sequencesSucceeded++;
386 64 this->log_ACTIVITY_HI_SequenceSucceeded(value.get_moduleIdx());
387 64 }
388
389 4 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_reportModuleStartFailed(
390 SmId smId,
391 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
392 const Svc::WasmSequencer_RequestContext& value) {
393 // A failure while running a module's start function (LOAD-with-start, or the
394 // start phase of a RUN-with-start).
395
2/2
✓ Branch 5 taken 4 times.
✓ Branch 12 taken 4 times.
4 this->reportSequenceRuntimeFailure(value.get_moduleIdx(), WasmSequencer_SequencePhase::START);
396 4 }
397
398 77 void WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_action_reportModuleMainFailed(
399 SmId smId,
400 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
401 const Svc::WasmSequencer_RequestContext& value) {
402 // A failure while running a module's main function.
403
2/2
✓ Branch 5 taken 77 times.
✓ Branch 12 taken 77 times.
77 this->reportSequenceRuntimeFailure(value.get_moduleIdx(), WasmSequencer_SequencePhase::MAIN);
404 77 }
405
406 81 void WasmSequencer ::reportSequenceRuntimeFailure(WasmSequencer_ModuleIdx moduleIdx,
407 WasmSequencer_SequencePhase phase) {
408
5/5
✓ Branch 6 taken 15 times.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 35 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 27 times.
81 switch (this->m_exit.reason) {
409 15 case WasmSequencer_ExitReason::CANCEL:
410 15 this->m_tlm.sequencesCancelled++;
411 15 this->log_ACTIVITY_HI_SequenceCancelled(moduleIdx, phase);
412 15 break;
413 2 case WasmSequencer_ExitReason::HOST_PANIC:
414 2 this->m_tlm.sequencesFailed++;
415 2 this->log_WARNING_HI_SequencePanic(moduleIdx, phase, this->m_exit.code);
416 2 break;
417 35 case WasmSequencer_ExitReason::INTERPRETER_TRAP:
418 35 this->m_tlm.sequencesFailed++;
419 35 this->log_WARNING_HI_SequenceTrapped(moduleIdx, phase, this->m_exit.lastTrapReason);
420 35 break;
421 2 case WasmSequencer_ExitReason::INTERPRETER_FINISHED: // fallthrough is intended
422 case WasmSequencer_ExitReason::HOST_EXIT:
423 // Only reached on the failure path: a non-zero main return value or a
424 // non-zero fprime.exit code.
425 2 this->m_tlm.sequencesFailed++;
426 2 this->log_WARNING_HI_SequenceExited(moduleIdx, phase, this->m_exit.code);
427 2 break;
428 27 case WasmSequencer_ExitReason::UNKNOWN:
429 case WasmSequencer_ExitReason::REPLY_TIMEOUT:
430 case WasmSequencer_ExitReason::HOST_FAILURE:
431 case WasmSequencer_ExitReason::UNEXPECTED_REPLY:
432 case WasmSequencer_ExitReason::TIMER_INCOMPARABLE:
433 default:
434 27 this->m_tlm.sequencesFailed++;
435 54 this->log_WARNING_HI_SequenceHostFailure(moduleIdx, phase, this->m_exit.reason,
436 27 this->m_exit.lastHostFunction);
437 27 break;
438 }
439 81 }
440
441 // ----------------------------------------------------------------------
442 // Implementations for internal state machine guards
443 // ----------------------------------------------------------------------
444
445 190 bool WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_guard_moduleHasStart(
446 SmId smId,
447 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
448 const Svc::WasmSequencer_RequestContext& value) const {
449 190 U32 start_module_idx;
450 190 U32 start_function_idx;
451
1/1
✓ Branch 9 taken 190 times.
190 auto status = spacewasm_module_start(this->m_wasm, static_cast<U32>(value.get_moduleIdx()), &start_module_idx,
452 &start_function_idx);
453
454
2/3
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 177 times.
✗ Branch 2 not taken.
190 switch (status) {
455 13 case SPACEWASM_OK:
456 13 return true;
457 177 case SPACEWASM_ERR_NOT_FOUND:
458 177 return false;
459 ✗ default:
460 // All other status means we passed the c api invalid options
461 ✗ FW_ASSERT(false, status);
462 ✗ return false;
463 }
464 }
465
466 153 bool WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_guard_moduleHasValidMain(
467 SmId smId,
468 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
469 const Svc::WasmSequencer_RequestContext& value) const {
470 153 return this->validateModuleMain(value.get_moduleIdx()) == SPACEWASM_OK;
471 }
472
473 157 bool WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_guard_invokeSucceeded(
474 SmId smId,
475 Svc_WasmSequencer_ControllerStateMachine::Signal signal,
476 const Svc::WasmSequencer_RequestContext& value) const {
477 157 return this->m_invokeStatus == SPACEWASM_OK;
478 }
479
480 152 bool WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_guard_interpreterSucceeded(
481 SmId smId,
482 Svc_WasmSequencer_ControllerStateMachine::Signal signal) const {
483 // The engine sets m_exit.reason and m_exit.code before signalling
484 // engineFinished. A run succeeds only when it finished with a zero code:
485 // main returned 0 (a void return reports code 0) or the guest called
486 // fprime.exit(0)
487
2/2
✓ Branch 11 taken 73 times.
✓ Branch 12 taken 79 times.
152 switch (this->m_exit.reason) {
488 73 case WasmSequencer_ExitReason::INTERPRETER_FINISHED:
489 case WasmSequencer_ExitReason::HOST_EXIT:
490 73 return this->m_exit.code == 0;
491 79 default:
492 79 return false;
493 }
494 }
495
496 209 bool WasmSequencer ::Svc_WasmSequencer_ControllerStateMachine_guard_cancelRequested(
497 SmId smId,
498 Svc_WasmSequencer_ControllerStateMachine::Signal signal) const {
499
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 209 times.
209 return this->m_cancelRequested;
500 }
501
502 } // namespace Svc
503