GCC Code Coverage Report


Directory: ./
File: Svc/WasmSequencer/WasmSequencer.cpp
Date: 2026-09-23 21:11:01
Exec Total Coverage
Lines: 296 304 97.4%
Functions: 23 23 100.0%
Branches: 209 224 93.3%

Line Branch Exec Source
1 // ======================================================================
2 // \title WasmSequencer.cpp
3 // \author tumbar
4 // \brief cpp file for WasmSequencer component implementation class
5 // ======================================================================
6
7 #include "Svc/WasmSequencer/WasmSequencer.hpp"
8
9 #include "Fw/Cmd/CmdResponseEnumAc.hpp"
10 #include "Fw/Types/Assert.hpp"
11 #include "Fw/Types/LinearBufferTemplate.hpp"
12 #include "Fw/Types/Serializable.hpp"
13 #include "Fw/Types/SuccessEnumAc.hpp"
14 #include "Os/Mutex.hpp"
15 #include "Svc/Seq/BlockStateEnumAc.hpp"
16 #include "Svc/Seq/SeqArgsSerializableAc.hpp"
17 #include "Svc/WasmSequencer/WasmSequencer_CommandRequestSerializableAc.hpp"
18 #include "Svc/WasmSequencer/WasmSequencer_ControllerStateMachine_StateEnumAc.hpp"
19 #include "Svc/WasmSequencer/WasmSequencer_HostFunctionEnumAc.hpp"
20 #include "Svc/WasmSequencer/WasmSequencer_InvokeRequestSerializableAc.hpp"
21 #include "Svc/WasmSequencer/WasmSequencer_LoadRequestSerializableAc.hpp"
22 #include "Svc/WasmSequencer/WasmSequencer_SignalSourceEnumAc.hpp"
23 #include "Svc/WasmSequencer/fprime_spacewasm/include/fprime_spacewasm.h"
24 #include "Svc/WasmSequencer/spacewasm_include/spacewasm.h"
25 #include "config/FwAssertArgTypeAliasAc.h"
26 #include "config/FwIndexTypeAliasAc.h"
27 #include "config/FwSizeTypeAliasAc.h"
28
29 namespace Svc {
30
31 339 U8* WasmSequencer ::globalAllocCallback(void* userdata, size_t size, size_t align) {
32
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
339 if (userdata == nullptr) {
33 ✗ return nullptr;
34 }
35 339 return static_cast<WasmSequencer*>(userdata)->globalAlloc(static_cast<U32>(size), static_cast<U32>(align));
36 }
37
38 339 void WasmSequencer ::globalDeallocCallback(void* userdata, U8* ptr, size_t size, size_t align) {
39 (void)size;
40 (void)align;
41
1/2
✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
339 if (userdata != nullptr) {
42 339 static_cast<WasmSequencer*>(userdata)->globalDealloc(ptr);
43 }
44 339 }
45
46 // ----------------------------------------------------------------------
47 // Component construction and destruction
48 // ----------------------------------------------------------------------
49
50 224 WasmSequencer ::WasmSequencer(const char* const compName)
51 : WasmSequencerComponentBase(compName),
52 224 m_heapPages(nullptr),
53 224 m_heapPagesUsed(0),
54 224 m_heapPoisoned(false),
55 224 m_guestPool(nullptr),
56 224 m_guestPoolOffset(0),
57 224 m_wasm(nullptr),
58 224 m_hasExecutingContext(false),
59
1/1
✓ Branch 5 taken 224 times.
224 m_pendingTimer(),
60 224 m_hasPendingTimer(false),
61
1/1
✓ Branch 5 taken 224 times.
224 m_hostFunctionStart(),
62 224 m_hasHostFunctionStart(false),
63 224 m_dequeueSucceeded(false),
64 224 m_invokeStatus(SPACEWASM_OK),
65 224 m_pendingPause(false),
66 224 m_cancelRequested(false),
67
12/12
✓ Branch 17 taken 224 times.
✓ Branch 23 taken 224 times.
✓ Branch 29 taken 224 times.
✓ Branch 35 taken 224 times.
✓ Branch 41 taken 224 times.
✓ Branch 51 taken 224 times.
✓ Branch 57 taken 224 times.
✓ Branch 63 taken 1120 times.
✓ Branch 66 taken 1120 times.
✓ Branch 67 taken 224 times.
✓ Branch 73 taken 224 times.
✓ Branch 79 taken 224 times.
1792 m_sequencesStarted(0) {}
68
69 222 void WasmSequencer ::configure(const Config& cfg, Fw::MemAllocator& mallocator) {
70 222 FW_ASSERT(this->m_wasm == nullptr);
71 222 FW_ASSERT(this->m_allocator == nullptr);
72
73 222 getGlobalAllocatorLock()->lock();
74 222 const auto status = spacewasm_fprime_register_global_allocator(&globalAllocCallback, &globalDeallocCallback, this);
75 222 getGlobalAllocatorLock()->unlock();
76
77 222 FW_ASSERT(status == SPACEWASM_OK, status);
78
79 222 this->m_config = cfg;
80
81 // Allocate the heap memory pool
82 {
83 222 FW_ASSERT(
84 this->m_config.heapPages > 0 && this->m_config.heapPages <= Svc::WasmSequencerConfig::SPACEWASM_MAX_PAGES,
85 static_cast<FwAssertArgType>(this->m_config.heapPages), Svc::WasmSequencerConfig::SPACEWASM_MAX_PAGES);
86
87 // Allocate the heap page list
88 {
89 222 FwSizeType actualSize = sizeof(U8*) * this->m_config.heapPages;
90
1/1
✓ Branch 4 taken 222 times.
222 auto ptr = mallocator.checkedAllocate(0, actualSize);
91 222 this->m_heapPages = reinterpret_cast<U8**>(ptr);
92 }
93
94 // Allocate each heap page
95
2/2
✓ Branch 4 taken 888 times.
✓ Branch 5 taken 222 times.
1110 for (FwSizeType i = 0; i < this->m_config.heapPages; i++) {
96 888 auto actualSize = Svc::WasmSequencerConfig::SPACEWASM_PAGE_SIZE;
97 auto ptr =
98
1/1
✓ Branch 4 taken 888 times.
888 mallocator.checkedAllocate(static_cast<FwIndexType>(i) + 1, actualSize, SPACEWASM_MEMORY_ALIGNMENT);
99 888 this->m_heapPages[i] = reinterpret_cast<U8*>(ptr);
100 }
101 222 this->m_heapPagesUsed = 0;
102 }
103
104 // Allocate the guest memory pool
105 {
106 222 auto actualSize = this->m_config.guestMemorySize;
107
1/1
✓ Branch 8 taken 222 times.
222 auto ptr = mallocator.checkedAllocate(static_cast<FwIndexType>(this->m_config.heapPages) + 1, actualSize,
108 SPACEWASM_MEMORY_ALIGNMENT);
109 222 this->m_guestPoolOffset = 0;
110 222 this->m_guestPool = reinterpret_cast<U8*>(ptr);
111 }
112
113 // Allocate the serialOut buffer
114
2/2
✓ Branch 4 taken 221 times.
✓ Branch 5 taken 1 times.
222 if (this->m_config.serialOutMax > 0) {
115 221 auto actualSize = this->m_config.serialOutMax;
116
1/1
✓ Branch 8 taken 221 times.
221 auto ptr = mallocator.checkedAllocate(static_cast<FwIndexType>(this->m_config.heapPages) + 2, actualSize);
117
1/1
✓ Branch 6 taken 221 times.
221 this->m_serialOutBuffer.setExtBuffer(reinterpret_cast<U8*>(ptr), actualSize);
118 }
119
120 // Allocate the serialIn queues
121 {
122
1/1
✓ Branch 5 taken 222 times.
222 Os::ScopeLock scopeLock(this->m_serialInMutex);
123
2/2
✓ Branch 0 taken 1110 times.
✓ Branch 1 taken 222 times.
1332 for (FwIndexType i = 0; i < NUM_SERIALIN_INPUT_PORTS; i++) {
124
2/2
✓ Branch 5 taken 1109 times.
✓ Branch 6 taken 1 times.
1110 if (this->m_config.serialIn[i].size > 0) {
125 1109 auto actualSize = this->m_config.serialIn[i].size;
126 auto ptr =
127
1/1
✓ Branch 8 taken 1109 times.
1109 mallocator.checkedAllocate(static_cast<FwIndexType>(this->m_config.heapPages) + 3 + i, actualSize);
128
1/1
✓ Branch 5 taken 1109 times.
1109 this->m_serialInQueue[i].setup(reinterpret_cast<U8*>(ptr), actualSize);
129 }
130 }
131 222 }
132
133 // Allocate the initial store
134 222 this->m_allocator = &mallocator;
135 222 this->createStore();
136 222 }
137
138 224 void WasmSequencer ::deinit() {
139
2/2
✓ Branch 4 taken 222 times.
✓ Branch 5 taken 2 times.
224 if (this->m_wasm != nullptr) {
140 222 this->destroyStore();
141 }
142
143
2/2
✓ Branch 4 taken 222 times.
✓ Branch 5 taken 2 times.
224 if (this->m_allocator != nullptr) {
144 // Deallocate each heap page
145
2/2
✓ Branch 4 taken 888 times.
✓ Branch 5 taken 222 times.
1110 for (FwSizeType i = 0; i < this->m_config.heapPages; i++) {
146 888 this->m_allocator->deallocate(static_cast<FwIndexType>(i) + 1, this->m_heapPages[i]);
147 888 this->m_heapPages[i] = nullptr;
148 }
149
150 // Deallocate the heap page pool
151 222 this->m_allocator->deallocate(0, this->m_heapPages);
152
153 // Deallocate the guest memory pool
154
1/2
✓ Branch 4 taken 222 times.
✗ Branch 5 not taken.
222 if (this->m_guestPool != nullptr) {
155 222 this->m_allocator->deallocate(static_cast<FwIndexType>(this->m_config.heapPages) + 1, this->m_guestPool);
156 }
157
158 // Deallocate the serialOut buffer
159
2/2
✓ Branch 6 taken 221 times.
✓ Branch 7 taken 1 times.
222 if (this->m_serialOutBuffer.getBuffAddr() != nullptr) {
160 442 this->m_allocator->deallocate(static_cast<FwIndexType>(this->m_config.heapPages) + 2,
161 221 this->m_serialOutBuffer.getBuffAddr());
162 }
163
164 // Deallocate the serialIn queues
165
2/2
✓ Branch 0 taken 1110 times.
✓ Branch 1 taken 222 times.
1332 for (FwIndexType i = 0; i < NUM_SERIALIN_INPUT_PORTS; i++) {
166
2/2
✓ Branch 5 taken 1108 times.
✓ Branch 6 taken 2 times.
1110 if (this->m_serialInQueue[i].get_capacity() > 0) {
167 2216 this->m_allocator->deallocate(static_cast<FwIndexType>(this->m_config.heapPages) + 3 + i,
168 1108 this->m_serialInQueue[i].get_buffer());
169 }
170 }
171 }
172
173 // Release our slot in the process-wide global-allocator registry so it can
174 // be reused by a later sequencer instance.
175 224 getGlobalAllocatorLock()->lock();
176 224 (void)spacewasm_fprime_deregister_global_allocator(this);
177 224 getGlobalAllocatorLock()->unlock();
178
179 // Clean up dangling pointers
180 224 this->m_allocator = nullptr;
181 224 this->m_wasm = nullptr;
182
183 224 WasmSequencerComponentBase::deinit();
184 224 }
185
186 // ----------------------------------------------------------------------
187 // Handler implementations for typed input ports
188 // ----------------------------------------------------------------------
189
190 11 void WasmSequencer ::checkTimers_handler(FwIndexType portNum, U32 context) {
191 // Drive the sleep-wake / host-function-timeout checks in the state machine.
192 11 this->interpreter_sendSignal_checkTimers();
193 11 }
194
195 18 void WasmSequencer ::cmdResponseIn_handler(FwIndexType portNum,
196 FwOpcodeType opCode,
197 U32 cmdSeq,
198 const Fw::CmdResponse& response) {
199 18 FW_ASSERT(this->m_wasm != nullptr);
200
201 // The CmdDisp echoes back the context we sent, not a real cmdSeq. We packed
202 // our cmdUid into that context (see makeCmdUid); rename for clarity.
203 18 const U32 cmdUid = cmdSeq;
204 18 const U16 sequenceIndex = static_cast<U16>((cmdUid & 0xFFFF0000) >> 16);
205 18 const U16 cmdIndex = static_cast<U16>(cmdUid & 0xFFFF);
206 18 const U16 currentSequenceIndex = static_cast<U16>(this->m_sequencesStarted & 0xFFFF);
207 18 const U16 currentCmdIndex = static_cast<U16>(this->m_tlm.commandsDispatched & 0xFFFF);
208
209 // If the response is from a previous execution window, treat it as a nominal
210 // late reply (e.g. a command that returned after a CANCEL) and just report it
211 // without failing the current sequence.
212
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 16 times.
18 if (sequenceIndex != currentSequenceIndex) {
213 2 this->log_WARNING_LO_CmdResponseFromOldSequence(opCode, response, sequenceIndex, currentSequenceIndex);
214 2 return;
215 }
216
217 // From here on the response claims to be from the current sequence, so any
218 // inconsistency is a genuine error that should fail the sequence.
219
4/9
✓ Branch 2 taken 16 times.
✓ Branch 10 taken 16 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 5 times.
✓ Branch 14 taken 11 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
32 if (this->interpreter_getState() !=
220
4/6
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
43 WasmSequencer_InterpreterStateMachine_State::RUNNING_AWAITING_RESPONSE_WAITING ||
221 11 this->m_pendingHostFunction.kind != WasmSequencer_HostFunction::COMMAND) {
222
2/2
✓ Branch 6 taken 5 times.
✓ Branch 10 taken 5 times.
5 this->interpreter_sendSignal_hostResponseUnexpected(WasmSequencer_HostFunction::COMMAND);
223 5 return;
224 }
225
226 // Awaiting a command response, but was it for this exact dispatch instance, or
227 // an earlier one in this sequence with the same opcode?
228
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (cmdIndex != currentCmdIndex) {
229 1 this->log_WARNING_HI_WrongCmdResponseIndex(opCode, response, cmdIndex, currentCmdIndex);
230
2/2
✓ Branch 6 taken 1 times.
✓ Branch 10 taken 1 times.
1 this->interpreter_sendSignal_hostResponseUnexpected(WasmSequencer_HostFunction::COMMAND);
231 1 return;
232 }
233
234 10 this->m_pendingHostFunction.clear();
235
236 // Track commands that came back with a non-OK response.
237
2/2
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 9 times.
10 if (response != Fw::CmdResponse::OK) {
238 1 this->m_tlm.commandsFailed++;
239 }
240
241
1/2
✗ Branch 7 not taken.
✓ Branch 8 taken 10 times.
10 this->interpreter_sendSignal_hostResumeI32(static_cast<I32>(response.e));
242 }
243
244 28 void WasmSequencer ::writeTelemetry_handler(FwIndexType portNum, U32 context) {
245 28 FW_ASSERT(this->m_wasm != nullptr);
246
247
1/1
✓ Branch 3 taken 28 times.
28 auto now = this->getTime();
248
249
3/3
✓ Branch 6 taken 28 times.
✓ Branch 11 taken 28 times.
✓ Branch 15 taken 28 times.
28 this->tlmWrite_ControllerState(this->controller_getState(), now);
250
3/3
✓ Branch 6 taken 28 times.
✓ Branch 11 taken 28 times.
✓ Branch 15 taken 28 times.
28 this->tlmWrite_InterpreterState(this->interpreter_getState(), now);
251
2/2
✓ Branch 6 taken 28 times.
✓ Branch 13 taken 28 times.
28 this->tlmWrite_SequencesSucceeded(this->m_tlm.sequencesSucceeded, now);
252
2/2
✓ Branch 6 taken 28 times.
✓ Branch 13 taken 28 times.
28 this->tlmWrite_SequencesFailed(this->m_tlm.sequencesFailed, now);
253
2/2
✓ Branch 6 taken 28 times.
✓ Branch 13 taken 28 times.
28 this->tlmWrite_SequencesCancelled(this->m_tlm.sequencesCancelled, now);
254
2/2
✓ Branch 6 taken 28 times.
✓ Branch 13 taken 28 times.
28 this->tlmWrite_CommandsDispatched(this->m_tlm.commandsDispatched, now);
255
2/2
✓ Branch 6 taken 28 times.
✓ Branch 13 taken 28 times.
28 this->tlmWrite_CommandsFailed(this->m_tlm.commandsFailed, now);
256
2/2
✓ Branch 6 taken 28 times.
✓ Branch 12 taken 28 times.
28 this->tlmWrite_LastTrapReason(this->m_exit.lastTrapReason, now);
257
2/2
✓ Branch 6 taken 28 times.
✓ Branch 12 taken 28 times.
28 this->tlmWrite_SeqName(this->m_tlm.sequenceName, now);
258 56 }
259
260 12 void WasmSequencer ::seqRunIn_handler(FwIndexType portNum, const Fw::StringBase& filename, const Svc::SeqArgs& args) {
261 12 FW_ASSERT(this->m_wasm != nullptr);
262
263
1/1
✓ Branch 2 taken 12 times.
12 Fw::String runModuleName = "";
264
265
2/2
✓ Branch 6 taken 12 times.
✓ Branch 10 taken 12 times.
36 this->controller_sendSignal_run(Svc::WasmSequencer_LoadRequest(
266 filename, runModuleName, args,
267
2/2
✓ Branch 3 taken 12 times.
✓ Branch 7 taken 12 times.
24 Svc::WasmSequencer_RequestContext(WasmSequencer_SignalSource::PORT_RUN, WasmSequencer_CommandRequest(0, 0),
268 BlockState::NO_BLOCK,
269 /* moduleIdx */ 0 // placeholder, gets filled in after load
270 )));
271 24 }
272
273 2 void WasmSequencer ::seqCancelIn_handler(FwIndexType portNum) {
274 2 this->controller_sendSignal_cancel();
275 2 this->interpreter_sendSignal_cancel();
276 2 }
277
278 // ----------------------------------------------------------------------
279 // Handler implementations for serial input ports
280 // ----------------------------------------------------------------------
281
282 32 void WasmSequencer ::serialIn_handler(FwIndexType portNum, Fw::LinearBufferBase& buffer) {
283 32 FW_ASSERT(portNum < NUM_SERIALIN_INPUT_PORTS, portNum, NUM_SERIALIN_INPUT_PORTS);
284
1/1
✓ Branch 5 taken 32 times.
32 Os::ScopeLock scopeLock(this->m_serialInMutex);
285 32 auto& queue = this->m_serialInQueue[portNum];
286 32 auto fullFullBehavior = this->m_config.serialIn[portNum].fullBehavior;
287
288 // Each message is framed on the queue as [U32 length][payload]
289 32 const FwSizeType headerSize = sizeof(U32);
290
1/1
✓ Branch 7 taken 32 times.
32 const FwSizeType payloadSize = buffer.getSize();
291
1/1
✓ Branch 2 taken 32 times.
32 const FwSizeType capacity = queue.get_capacity();
292
293 // Make sure the queue is sized to hold this framed message at all. This does
294 // not check free space, only that the queue's capacity is large enough.
295
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 29 times.
32 if (headerSize + payloadSize > capacity) {
296 // The largest payload this queue could ever hold is capacity - headerSize. A queue smaller
297 // than the header (including a port left un-configured with capacity 0) can hold nothing.
298 3 const FwSizeType maxPayload = (capacity > headerSize) ? (capacity - headerSize) : 0;
299
1/1
✓ Branch 5 taken 3 times.
3 this->log_WARNING_HI_SerialInFrameTooLarge(static_cast<U32>(portNum), static_cast<U32>(payloadSize),
300 static_cast<U32>(maxPayload));
301 3 return;
302 }
303
304 // Total framed size; <= capacity by the assertions above, so it cannot overflow.
305 29 const FwSizeType frameSize = headerSize + payloadSize;
306
307 // Check if we _can_ push the data to the queue
308
3/3
✓ Branch 2 taken 29 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 25 times.
29 if (frameSize > queue.get_free_size()) {
309 // The queue is full and cannot push this data
310
2/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
4 switch (fullFullBehavior) {
311 2 case SerialInQueueFullBehavior::DROP_OLDEST:
312 // Drop oldest messages until this one fits.
313
3/3
✓ Branch 2 taken 4 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 2 times.
4 while (frameSize > queue.get_free_size()) {
314 2 U32 nextMsgSize;
315
1/1
✓ Branch 2 taken 2 times.
2 auto status = queue.peek(nextMsgSize);
316 2 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, portNum, status);
317
318
1/1
✓ Branch 2 taken 2 times.
2 const FwSizeType allocated = queue.get_allocated_size();
319 2 FW_ASSERT(allocated >= headerSize, portNum, static_cast<FwAssertArgType>(allocated));
320 2 FW_ASSERT(static_cast<FwSizeType>(nextMsgSize) <= allocated - headerSize, portNum,
321 static_cast<FwAssertArgType>(nextMsgSize), static_cast<FwAssertArgType>(allocated));
322
323
1/1
✓ Branch 2 taken 2 times.
2 status = queue.rotate(headerSize + nextMsgSize);
324
325 2 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, portNum, status);
326 }
327
328 // Now it fits, fall through to push the data to the queue
329 2 break;
330 2 case SerialInQueueFullBehavior::DROP_NEWEST:
331 // Drop this message
332 2 return;
333
334 ✗ case SerialInQueueFullBehavior::ASSERT:
335 ✗ FW_ASSERT(false, portNum, static_cast<FwAssertArgType>(frameSize),
336 static_cast<FwAssertArgType>(queue.get_free_size()), static_cast<FwAssertArgType>(capacity));
337 ✗ break;
338 }
339 }
340
341 // The message should be able to be put into the queue.
342 // Enqueue it as a raw [U32 size][payload] frame. We use the raw (const U8*, size)
343
1/1
✓ Branch 2 taken 27 times.
54 Fw::LinearBufferTemplate<sizeof(U32)> sizeSer;
344
1/1
✓ Branch 2 taken 27 times.
27 auto status = sizeSer.serializeFrom(static_cast<U32>(payloadSize));
345 27 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
346
347
1/1
✓ Branch 4 taken 27 times.
27 status = queue.serialize(sizeSer.getBuffAddr(), headerSize);
348 27 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
349
350
1/1
✓ Branch 6 taken 27 times.
27 status = queue.serialize(buffer.getBuffAddr(), payloadSize);
351 27 FW_ASSERT(status == Fw::FW_SERIALIZE_OK, status);
352
353 // Wake up any blocking recv calls
354
1/1
✓ Branch 5 taken 27 times.
27 this->interpreter_sendSignal_serialInMessage(portNum);
355 32 }
356
357 // ----------------------------------------------------------------------
358 // Handler implementations for commands
359 // ----------------------------------------------------------------------
360
361 143 void WasmSequencer ::RUN_cmdHandler(FwOpcodeType opCode,
362 U32 cmdSeq,
363 const Fw::CmdStringArg& fileName,
364 const Svc::BlockState& block,
365 const SeqArgs& seqArgs) {
366 143 FW_ASSERT(this->m_wasm != nullptr);
367
368
1/1
✓ Branch 2 taken 143 times.
143 Fw::String runModuleName = "";
369
2/2
✓ Branch 9 taken 143 times.
✓ Branch 13 taken 143 times.
429 this->controller_sendSignal_run(Svc::WasmSequencer_LoadRequest(
370 fileName, runModuleName, seqArgs,
371
1/1
✓ Branch 3 taken 143 times.
715 Svc::WasmSequencer_RequestContext(WasmSequencer_SignalSource::COMMAND_RUN,
372
1/1
✓ Branch 2 taken 143 times.
286 WasmSequencer_CommandRequest(opCode, cmdSeq), block,
373 /* moduleIdx */ 0 // placeholder, gets filled in after load
374 143 )));
375 286 }
376
377 16 void WasmSequencer ::WAIT_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
378 16 FW_ASSERT(this->m_wasm != nullptr);
379
380
3/3
✓ Branch 3 taken 16 times.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 14 times.
16 switch (this->controller_getState()) {
381 2 case WasmSequencer_ControllerStateMachine_State::IDLE:
382 case WasmSequencer_ControllerStateMachine_State::READY:
383 // Nothing is executing, respond immediately
384
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
385 2 break;
386 14 default: {
387
1/1
✓ Branch 7 taken 14 times.
14 const auto status = this->m_waiting.enqueue(WaitingCmd(opCode, cmdSeq));
388
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 13 times.
14 if (status != Fw::Success::SUCCESS) {
389
1/1
✓ Branch 5 taken 1 times.
1 this->log_WARNING_HI_TooManyBlockingCommands();
390
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
391 }
392 14 }
393 }
394 16 }
395
396 60 void WasmSequencer ::LOAD_cmdHandler(FwOpcodeType opCode,
397 U32 cmdSeq,
398 const Fw::CmdStringArg& fileName,
399 const Fw::CmdStringArg& name) {
400 60 FW_ASSERT(this->m_wasm != nullptr);
401
402
2/2
✓ Branch 12 taken 60 times.
✓ Branch 16 taken 60 times.
180 this->controller_sendSignal_load(Svc::WasmSequencer_LoadRequest(
403
1/1
✓ Branch 2 taken 60 times.
120 fileName, name, Svc::SeqArgs(),
404
1/1
✓ Branch 2 taken 60 times.
240 Svc::WasmSequencer_RequestContext(WasmSequencer_SignalSource::COMMAND_LOAD,
405
1/1
✓ Branch 2 taken 60 times.
120 WasmSequencer_CommandRequest(opCode, cmdSeq), Svc::BlockState::BLOCK,
406 /* moduleIdx */ 0 // placeholder, gets filled in after load
407 )));
408 60 }
409
410 13 void WasmSequencer ::INVOKE_cmdHandler(FwOpcodeType opCode,
411 U32 cmdSeq,
412 const Fw::CmdStringArg& module,
413 const Svc::BlockState& block,
414 const Svc::SeqArgs& seqArgs) {
415 13 FW_ASSERT(this->m_wasm != nullptr);
416
417
2/2
✓ Branch 9 taken 13 times.
✓ Branch 13 taken 13 times.
39 this->controller_sendSignal_invoke(Svc::WasmSequencer_InvokeRequest(
418 module, seqArgs,
419
1/1
✓ Branch 3 taken 13 times.
65 Svc::WasmSequencer_RequestContext(WasmSequencer_SignalSource::COMMAND_INVOKE,
420
1/1
✓ Branch 2 taken 13 times.
26 WasmSequencer_CommandRequest(opCode, cmdSeq), block,
421 /* moduleIdx */ 0 // placeholder, gets filled in after invoke
422 13 )));
423 13 }
424
425 25 void WasmSequencer ::CANCEL_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
426 25 this->controller_sendSignal_cancel();
427
2/2
✓ Branch 6 taken 25 times.
✓ Branch 10 taken 25 times.
25 this->interpreter_sendSignal_cmdCancel(WasmSequencer_CommandRequest(opCode, cmdSeq));
428 25 }
429
430 9 void WasmSequencer ::PAUSE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
431
3/3
✓ Branch 3 taken 9 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 8 times.
9 if (this->interpreter_getState() == WasmSequencer_InterpreterStateMachine_State::IDLE) {
432 1 this->log_WARNING_LO_SequenceNotRunning();
433
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
434 1 return;
435 }
436
437 8 this->m_pendingPause = true;
438
2/2
✓ Branch 6 taken 8 times.
✓ Branch 9 taken 8 times.
8 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
439 }
440
441 5 void WasmSequencer ::CONTINUE_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) {
442 5 FW_ASSERT(this->m_wasm != nullptr);
443
444
4/5
✓ Branch 3 taken 5 times.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 3 times.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
5 switch (this->interpreter_getState()) {
445 1 case WasmSequencer_InterpreterStateMachine_State::RUNNING_AWAITING_RESPONSE_SLEEPING:
446 case WasmSequencer_InterpreterStateMachine_State::RUNNING_AWAITING_RESPONSE_WAITING:
447 case WasmSequencer_InterpreterStateMachine_State::RUNNING_SPINNING:
448 // Already running
449
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
450 1 break;
451 3 case WasmSequencer_InterpreterStateMachine_State::RUNNING_PAUSED:
452 3 this->interpreter_sendSignal_cmd_CONTINUE();
453
2/2
✓ Branch 6 taken 3 times.
✓ Branch 9 taken 3 times.
3 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
454 3 break;
455 1 case WasmSequencer_InterpreterStateMachine_State::IDLE:
456 1 this->log_WARNING_LO_SequenceNotRunning();
457
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
458 1 break;
459 ✗ default:
460 ✗ FW_ASSERT(false, this->interpreter_getState());
461 }
462 5 }
463
464 9 void WasmSequencer ::GLOBAL_SET_I32_cmdHandler(FwOpcodeType opCode,
465 U32 cmdSeq,
466 const Fw::CmdStringArg& moduleName,
467 const Fw::CmdStringArg& name,
468 I32 value) {
469 9 FW_ASSERT(this->m_wasm != nullptr);
470
471 9 spacewasm_value_t s_value;
472 9 s_value.tag = SPACEWASM_I32;
473 9 s_value.u.i32_ = value;
474
475
1/1
✓ Branch 10 taken 9 times.
9 auto status = this->setGlobal(moduleName, name, s_value);
476
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 4 times.
9 if (status == SPACEWASM_OK) {
477
2/2
✓ Branch 6 taken 5 times.
✓ Branch 9 taken 5 times.
5 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
478 } else {
479
2/2
✓ Branch 6 taken 4 times.
✓ Branch 16 taken 4 times.
4 this->log_WARNING_LO_GlobalSetFailed(moduleName, name, status);
480
2/2
✓ Branch 6 taken 4 times.
✓ Branch 9 taken 4 times.
4 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
481 }
482 9 }
483
484 3 void WasmSequencer ::GLOBAL_SET_I64_cmdHandler(FwOpcodeType opCode,
485 U32 cmdSeq,
486 const Fw::CmdStringArg& moduleName,
487 const Fw::CmdStringArg& name,
488 I64 value) {
489 3 FW_ASSERT(this->m_wasm != nullptr);
490
491 3 spacewasm_value_t s_value;
492 3 s_value.tag = SPACEWASM_I64;
493 3 s_value.u.i64_ = value;
494
495
1/1
✓ Branch 10 taken 3 times.
3 auto status = this->setGlobal(moduleName, name, s_value);
496
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (status == SPACEWASM_OK) {
497
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
498 } else {
499
2/2
✓ Branch 6 taken 1 times.
✓ Branch 16 taken 1 times.
1 this->log_WARNING_LO_GlobalSetFailed(moduleName, name, status);
500
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
501 }
502 3 }
503
504 3 void WasmSequencer ::GLOBAL_SET_F32_cmdHandler(FwOpcodeType opCode,
505 U32 cmdSeq,
506 const Fw::CmdStringArg& moduleName,
507 const Fw::CmdStringArg& name,
508 F32 value) {
509 3 FW_ASSERT(this->m_wasm != nullptr);
510
511 3 spacewasm_value_t s_value;
512 3 s_value.tag = SPACEWASM_F32;
513 3 s_value.u.f32_ = value;
514
515
1/1
✓ Branch 10 taken 3 times.
3 auto status = this->setGlobal(moduleName, name, s_value);
516
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (status == SPACEWASM_OK) {
517
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
518 } else {
519
2/2
✓ Branch 6 taken 1 times.
✓ Branch 16 taken 1 times.
1 this->log_WARNING_LO_GlobalSetFailed(moduleName, name, status);
520
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
521 }
522 3 }
523
524 3 void WasmSequencer ::GLOBAL_SET_F64_cmdHandler(FwOpcodeType opCode,
525 U32 cmdSeq,
526 const Fw::CmdStringArg& moduleName,
527 const Fw::CmdStringArg& name,
528 F64 value) {
529 3 FW_ASSERT(this->m_wasm != nullptr);
530
531 3 spacewasm_value_t g_value;
532 3 g_value.tag = SPACEWASM_F64;
533 3 g_value.u.f64_ = value;
534
535
1/1
✓ Branch 10 taken 3 times.
3 auto status = this->setGlobal(moduleName, name, g_value);
536
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (status == SPACEWASM_OK) {
537
2/2
✓ Branch 6 taken 2 times.
✓ Branch 9 taken 2 times.
2 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
538 } else {
539
2/2
✓ Branch 6 taken 1 times.
✓ Branch 16 taken 1 times.
1 this->log_WARNING_LO_GlobalSetFailed(moduleName, name, status);
540
2/2
✓ Branch 6 taken 1 times.
✓ Branch 9 taken 1 times.
1 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
541 }
542 3 }
543
544 25 void WasmSequencer ::GLOBAL_GET_cmdHandler(FwOpcodeType opCode,
545 U32 cmdSeq,
546 const Fw::CmdStringArg& moduleName,
547 const Fw::CmdStringArg& name) {
548 25 FW_ASSERT(this->m_wasm != nullptr);
549
550 25 spacewasm_value_t g_value;
551
1/1
✓ Branch 10 taken 25 times.
25 auto status = this->getGlobal(moduleName, name, g_value);
552
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 4 times.
25 if (status == SPACEWASM_OK) {
553
4/5
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
21 switch (g_value.tag) {
554 12 case SPACEWASM_I32:
555
1/1
✓ Branch 11 taken 12 times.
12 this->log_ACTIVITY_LO_GlobalValueI32(moduleName, name, g_value.u.i32_);
556 12 break;
557 3 case SPACEWASM_I64:
558
1/1
✓ Branch 11 taken 3 times.
3 this->log_ACTIVITY_LO_GlobalValueI64(moduleName, name, g_value.u.i64_);
559 3 break;
560 3 case SPACEWASM_F32:
561
1/1
✓ Branch 11 taken 3 times.
3 this->log_ACTIVITY_LO_GlobalValueF32(moduleName, name, g_value.u.f32_);
562 3 break;
563 3 case SPACEWASM_F64:
564
1/1
✓ Branch 11 taken 3 times.
3 this->log_ACTIVITY_LO_GlobalValueF64(moduleName, name, g_value.u.f64_);
565 3 break;
566 ✗ default:
567 ✗ FW_ASSERT(false, g_value.tag);
568 }
569
570
2/2
✓ Branch 6 taken 21 times.
✓ Branch 9 taken 21 times.
21 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
571 } else {
572
2/2
✓ Branch 6 taken 4 times.
✓ Branch 16 taken 4 times.
4 this->log_WARNING_LO_GlobalGetFailed(moduleName, name, status);
573
2/2
✓ Branch 6 taken 4 times.
✓ Branch 9 taken 4 times.
4 this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::EXECUTION_ERROR);
574 }
575 25 }
576
577 } // namespace Svc
578