aboutsummaryrefslogtreecommitdiff
path: root/kernel/src/kapi/memory.cpp
blob: ebd4c157a6a4e90cbb6839e5fbcfe3908af8713b (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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include "kapi/memory.hpp"

#include "kapi/system.hpp"

#include <cstddef>
#include <optional>
#include <utility>

namespace teachos::memory
{

  namespace
  {
    struct bad_frame_allocator final : public frame_allocator
    {
      bad_frame_allocator static instance;

      auto allocate_many(std::size_t) noexcept -> std::optional<std::pair<frame, std::size_t>> override
      {
        system::panic("Tried to allocate frames without an active allocator.");
      }

      auto release_many(std::pair<frame, std::size_t>) -> void override
      {
        system::panic("Tried to release frames without an active allocator.");
      }
    };

    struct bad_page_mapper final : public page_mapper
    {
      bad_page_mapper static instance;

      auto map(page, frame, flags) -> std::byte * override
      {
        system::panic("Tried to map a page without an active mapper.");
      }

      auto unmap(page) -> void override
      {
        system::panic("Tried to unmap a page without an active mapper.");
      }

      auto try_unmap(page) noexcept -> bool override
      {
        return false;
      }
    };

    constinit bad_frame_allocator bad_frame_allocator::instance{};
    constinit bad_page_mapper bad_page_mapper::instance{};
  }  // namespace

  constinit auto static active_frame_allocator = static_cast<frame_allocator *>(&bad_frame_allocator::instance);
  constinit auto static active_page_mapper = static_cast<page_mapper *>(&bad_page_mapper::instance);

  auto set_frame_allocator(frame_allocator & allocator) -> std::optional<frame_allocator *>
  {
    if (&allocator == active_frame_allocator)
    {
      return {};
    }
    return std::exchange(active_frame_allocator, &allocator);
  }

  auto set_page_mapper(page_mapper & mapper) -> std::optional<page_mapper *>
  {
    if (&mapper == active_page_mapper)
    {
      return {};
    }
    return std::exchange(active_page_mapper, &mapper);
  }

  auto allocate_frame() -> std::optional<frame>
  {
    return active_frame_allocator->allocate();
  }

  auto allocate_many_frames(std::size_t count) -> std::optional<std::pair<frame, std::size_t>>
  {
    return active_frame_allocator->allocate_many(count);
  }

  auto map(page page, frame frame) -> std::byte *
  {
    return active_page_mapper->map(page, frame, page_mapper::flags::empty);
  }

  auto unmap(page page) -> void
  {
    return active_page_mapper->unmap(page);
  }

}  // namespace teachos::memory