aboutsummaryrefslogtreecommitdiff
path: root/kernel/kapi/interrupts.stress.cpp
blob: d3baf7b8ddd3f10c53aa1a7f762b115769e13ce9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <kapi/interrupts.hpp>

#include <kernel/test_support/cpu.hpp>

#include <catch2/catch_test_macros.hpp>

#include <future>
#include <mutex>

SCENARIO("irq_lock remote unlock protection", "[kapi][interrupts]")
{
  GIVEN("a simple irq_lock")
  {
    auto lock = kapi::interrupts::irq_lock{};

    WHEN("it is locked on the main core")
    {
      auto guard = std::lock_guard{lock};

      THEN("unlocking it on a different core panics")
      {
        auto unlocker = [&] {
          try
          {
            lock.unlock();
            return false;
          }
          catch (kernel::tests::cpu::halt const &)
          {
            return true;
          }
        };

        auto result = std::async(std::launch::async, unlocker);

        REQUIRE(result.get());
      }
    }
  }

  GIVEN("A heap allocated irq_lock")
  {
    // We use plain new-delete here, since the destruction path of std::shared_ptr is fully noexcept.
    auto lock = new kapi::interrupts::irq_lock<>{};

    THEN("destroying it on a different core panics")
    {
      auto destroyer = [&] {
        try
        {
          delete lock;
          return false;
        }
        catch (kernel::tests::cpu::halt const &)
        {
          return true;
        }
      };

      auto result = std::async(std::launch::async, destroyer);

      REQUIRE(result.get());
    }
  }
}