Coverage Report

Created: 2026-06-30 06:10

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
0
  uint32_t Align =
20
0
      AddrType == AddressType::I32 ? sizeof(uint32_t) : sizeof(uint64_t);
21
22
0
  if (Address % Align != 0) {
23
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
24
0
    spdlog::error(
25
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
26
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
27
0
  }
28
29
0
  uint64_t Count = extractAddr(RawCount, AddrType);
30
0
  EXPECTED_TRY(
31
0
      auto Total,
32
0
      atomicNotify(MemInst, Address, Count).map_error([&Instr](auto E) {
33
0
        spdlog::error(E);
34
0
        spdlog::error(
35
0
            ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
36
0
        return E;
37
0
      }));
38
0
  RawAddress = emplaceAddr(Total, AddrType);
39
0
  return {};
40
0
}
41
42
0
Expect<void> Executor::runMemoryFenceOp() {
43
0
  std::atomic_thread_fence(std::memory_order_release);
44
0
  return {};
45
0
}
46
47
Expect<uint64_t>
48
Executor::atomicNotify(Runtime::Instance::MemoryInstance &MemInst,
49
0
                       uint64_t Address, uint64_t Count) noexcept {
50
  // The error message should be handled by the caller, or the AOT mode will
51
  // produce the duplicated messages.
52
0
  if (auto *AtomicObj = MemInst.getPointer<std::atomic<uint64_t> *>(Address);
53
0
      !AtomicObj) {
54
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
55
0
  }
56
57
0
  auto &WaiterMapMtx = MemInst.getWaiterMapMutex();
58
0
  auto &WaiterMap = MemInst.getWaiterMap();
59
0
  std::unique_lock<std::mutex> Locker(WaiterMapMtx);
60
0
  uint64_t Total = 0;
61
0
  auto Range = WaiterMap.equal_range(Address);
62
0
  for (auto Iterator = Range.first; Total < Count && Iterator != Range.second;
63
0
       ++Iterator) {
64
0
    {
65
0
      std::unique_lock<std::mutex> WaiterLocker(Iterator->second.Mutex);
66
0
      Iterator->second.Notified = true;
67
0
    }
68
0
    Iterator->second.Cond.notify_all();
69
0
    ++Total;
70
0
  }
71
0
  return Total;
72
0
}
73
74
0
void Executor::atomicNotifyAll() noexcept {
75
0
  if (auto *MemInst = WaitingMemory.load(std::memory_order_acquire)) {
76
0
    MemInst->notifyAllWaiters();
77
0
  }
78
0
}
79
80
} // namespace Executor
81
} // namespace WasmEdge