Coverage Report

Created: 2025-07-01 06:18

/src/WasmEdge/lib/executor/engine/threadInstr.cpp
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: Apache-2.0
2
// SPDX-FileCopyrightText: 2019-2024 Second State INC
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
16
0
  uint32_t Address = RawAddress.get<uint32_t>();
17
18
0
  if (Address >
19
0
      std::numeric_limits<uint32_t>::max() - Instr.getMemoryOffset()) {
20
0
    spdlog::error(ErrCode::Value::MemoryOutOfBounds);
21
0
    spdlog::error(ErrInfo::InfoBoundary(
22
0
        Address + static_cast<uint64_t>(Instr.getMemoryOffset()),
23
0
        sizeof(uint32_t), MemInst.getBoundIdx()));
24
0
    spdlog::error(
25
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
26
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
27
0
  }
28
0
  Address += Instr.getMemoryOffset();
29
30
0
  if (Address % sizeof(uint32_t) != 0) {
31
0
    spdlog::error(ErrCode::Value::UnalignedAtomicAccess);
32
0
    spdlog::error(
33
0
        ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
34
0
    return Unexpect(ErrCode::Value::UnalignedAtomicAccess);
35
0
  }
36
37
0
  uint32_t Count = RawCount.get<uint32_t>();
38
0
  EXPECTED_TRY(
39
0
      auto Total,
40
0
      atomicNotify(MemInst, Address, Count).map_error([&Instr](auto E) {
41
0
        spdlog::error(E);
42
0
        spdlog::error(
43
0
            ErrInfo::InfoInstruction(Instr.getOpCode(), Instr.getOffset()));
44
0
        return E;
45
0
      }));
46
0
  RawAddress.emplace<uint32_t>(Total);
47
0
  return {};
48
0
}
49
50
0
Expect<void> Executor::runMemoryFenceOp() {
51
0
  std::atomic_thread_fence(std::memory_order_release);
52
0
  return {};
53
0
}
54
55
Expect<uint32_t>
56
Executor::atomicNotify(Runtime::Instance::MemoryInstance &MemInst,
57
0
                       uint32_t Address, uint32_t Count) noexcept {
58
  // The error message should be handled by the caller, or the AOT mode will
59
  // produce the duplicated messages.
60
0
  if (auto *AtomicObj = MemInst.getPointer<std::atomic<uint32_t> *>(Address);
61
0
      !AtomicObj) {
62
0
    return Unexpect(ErrCode::Value::MemoryOutOfBounds);
63
0
  }
64
65
0
  std::unique_lock<decltype(WaiterMapMutex)> Locker(WaiterMapMutex);
66
0
  uint32_t Total = 0;
67
0
  auto Range = WaiterMap.equal_range(Address);
68
0
  for (auto Iterator = Range.first; Total < Count && Iterator != Range.second;
69
0
       ++Iterator) {
70
0
    if (likely(&MemInst == Iterator->second.MemInst)) {
71
0
      Iterator->second.Cond.notify_all();
72
0
      ++Total;
73
0
    }
74
0
  }
75
0
  return Total;
76
0
}
77
78
0
void Executor::atomicNotifyAll() noexcept {
79
0
  std::unique_lock<decltype(WaiterMapMutex)> Locker(WaiterMapMutex);
80
0
  for (auto Iterator = WaiterMap.begin(); Iterator != WaiterMap.end();
81
0
       ++Iterator) {
82
0
    Iterator->second.Cond.notify_all();
83
0
  }
84
0
}
85
86
} // namespace Executor
87
} // namespace WasmEdge