summaryrefslogtreecommitdiffhomepage
path: root/Private/Source/SMPManager.cxx
blob: 27bf589292f6e178bb7fc4be5a18750e7d5fe428 (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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 *	========================================================
 *
 *	HCore
 * 	Copyright Mahrouss Logic, all rights reserved.
 *
 * 	========================================================
 */

#include <ArchKit/Arch.hpp>
#include <KernelKit/ProcessManager.hpp>
#include <KernelKit/SMPManager.hpp>

/// BUGS: 0

///! @brief This file handles multi processing in HCore.
///! @brief Multi processing is needed for multi-tasking operations.

namespace HCore {
// A HardwareThread class takes care of it's owned hardware thread.
// It has a stack for it's core.

// @brief constructor
HardwareThread::HardwareThread() = default;

// @brief destructor
HardwareThread::~HardwareThread() = default;

//! @brief returns the id

const ThreadID& HardwareThread::ID() noexcept { return m_ID; }

//! @brief returns the kind

const ThreadKind& HardwareThread::Kind() noexcept { return m_Kind; }

//! @brief is the core busy?

bool HardwareThread::IsBusy() noexcept { return m_Busy; }

/// @brief Get processor stack frame.

HAL::StackFrame* HardwareThread::StackFrame() noexcept {
  MUST_PASS(m_Stack);
  return m_Stack;
}

void HardwareThread::Busy(const bool busy) noexcept { m_Busy = busy; }

HardwareThread::operator bool() { return m_Stack; }

/// @brief Wakeup the processor.

void HardwareThread::Wake(const bool wakeup) noexcept {
  m_Wakeup = wakeup;

  if (!m_Wakeup)
    rt_hang_thread(m_Stack);
  else
    rt_wakeup_thread(m_Stack);
}

bool HardwareThread::Switch(HAL::StackFrame* stack) {
  if (stack == nullptr) return false;

  return rt_do_context_switch(m_Stack, stack) == 0;
}

///! @brief Tells if processor is waked up.
bool HardwareThread::IsWakeup() noexcept { return m_Wakeup; }

//! @brief Constructor and destructor

///! @brief Default constructor.
SMPManager::SMPManager() = default;

///! @brief Default destructor.
SMPManager::~SMPManager() = default;

/// @brief Shared singleton function
Ref<SMPManager> SMPManager::Shared() {
  static SMPManager manager;
  return {manager};
}

/// @brief Get Stack Frame of Core
HAL::StackFramePtr SMPManager::GetStackFrame() noexcept {
  if (m_ThreadList[m_CurrentThread].Leak() &&
      ProcessHelper::GetCurrentPID() ==
          m_ThreadList[m_CurrentThread].Leak().Leak().m_PID)
    return m_ThreadList[m_CurrentThread].Leak().Leak().m_Stack;

  return nullptr;
}

/// @brief Finds and switch to a free core.
bool SMPManager::Switch(HAL::StackFrame* stack) {
  if (stack == nullptr) return false;

  for (SizeT idx = 0; idx < kMaxHarts; ++idx) {
    // stack != nullptr -> if core is used, then continue.
    if (!m_ThreadList[idx].Leak() ||
        !m_ThreadList[idx].Leak().Leak().IsWakeup() ||
        m_ThreadList[idx].Leak().Leak().IsBusy())
      continue;

    m_ThreadList[idx].Leak().Leak().m_ID = idx;
    m_ThreadList[idx].Leak().Leak().m_Stack = stack;
    m_ThreadList[idx].Leak().Leak().m_PID = ProcessHelper::GetCurrentPID();

    m_ThreadList[idx].Leak().Leak().Busy(true);

    Boolean ret = (rt_do_context_switch(rt_get_current_context(), stack) == 0);

    m_ThreadList[idx].Leak().Leak().Busy(false);

    return ret;
  }

  return false;
}

/**
 * Index Hardware thread
 * @param idx the index
 * @return the reference to the hardware thread.
 */
Ref<HardwareThread> SMPManager::operator[](const SizeT& idx) {
  return m_ThreadList[idx].Leak();
}

/**
 * Check if thread pool isn't empty.
 * @return
 */
SMPManager::operator bool() noexcept { return !m_ThreadList.Empty(); }

/**
 * Reverse operator bool
 * @return
 */
bool SMPManager::operator!() noexcept { return m_ThreadList.Empty(); }
}  // namespace HCore