Coverage Report

Created: 2026-09-28 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/WasmEdge/lib/executor/engine/threadInstr.cpp
Line
Count
Source
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: Copyright The WasmEdge Authors
3
4
#include "executor/executor.h"
5
6
namespace WasmEdge {
7
namespace Executor {
8
9
Expect<void>
10
Executor::runAtomicNotifyOp(Runtime::StackManager &StackMgr,
11
                            Runtime::Instance::MemoryInstance &MemInst,
12
0
                            const AST::Instruction &Instr) {
13
0
  ValVariant RawCount = StackMgr.pop();
14
0
  ValVariant &RawAddress = StackMgr.getTop();
15
0
  const auto AddrType = MemInst.getMemoryType().getLimit().getAddrType();
16
0
  uint64_t Address = extractAddr(RawAddress, AddrType);
17
0
  EXPECTED_TRY(checkOffsetOverflow(MemInst, Instr, Address, sizeof(uint32_t)));
18
0
  Address += Instr.getMemoryOffset();
19
20
0
  if (Address % sizeof(uint32_t) != 0) {
21
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
22
0
    spdlog::error(
23
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
24
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
25
0
  }
26
27
0
  uint64_t Count = extractAddr(RawCount, AddressType::I32);
28
0
  EXPECTED_TRY(
29
0
      auto Total,
30
0
      atomicNotify(MemInst, Address, Count).map_error([&Instr](auto E) {
31
0
        spdlog::error(E);
32
0
        spdlog::error(
33
0
            ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
34
0
        return E;
35
0
      }));
36
0
  RawAddress = emplaceAddr(Total, AddressType::I32);
37
0
  return {};
38
0
}
39
40
0
Expect<void> Executor::runMemoryFenceOp() {
41
0
  std::atomic_thread_fence(std::memory_order_release);
42
0
  return {};
43
0
}
44
45
Expect<uint64_t>
46
Executor::atomicNotify(Runtime::Instance::MemoryInstance &MemInst,
47
0
                       uint64_t Address, uint64_t Count) noexcept {
48
  // The error message should be handled by the caller, or the AOT mode will
49
  // produce the duplicated messages.
50
0
  if (!MemInst.checkAccessBound(Address, sizeof(uint32_t))) {
51
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
52
0
  }
53
54
0
  auto &WaiterMapMtx = MemInst.getWaiterMapMutex();
55
0
  auto &WaiterMap = MemInst.getWaiterMap();
56
0
  std::unique_lock<std::mutex> Locker(WaiterMapMtx);
57
0
  uint64_t Total = 0;
58
0
  auto Range = WaiterMap.equal_range(Address);
59
0
  for (auto Iterator = Range.first; Total < Count && Iterator != Range.second;
60
0
       ++Iterator) {
61
0
    {
62
0
      std::unique_lock<std::mutex> WaiterLocker(Iterator->second.Mutex);
63
0
      Iterator->second.Notified = true;
64
0
    }
65
0
    Iterator->second.Cond.notify_all();
66
0
    ++Total;
67
0
  }
68
0
  return Total;
69
0
}
70
71
0
void Executor::atomicNotifyAll() noexcept {
72
0
  if (auto *MemInst = WaitingMemory.load(std::memory_order_acquire)) {
73
0
    MemInst->notifyAllWaiters();
74
0
  }
75
0
}
76
77
} // namespace Executor
78
} // namespace WasmEdge