mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-04 22:19:02 +00:00
Initial kernel allocator
This commit is contained in:
parent
0f76e72de1
commit
d7a34f0904
25 changed files with 247 additions and 144 deletions
57
orbis-kernel/include/orbis/KernelAllocator.hpp
Normal file
57
orbis-kernel/include/orbis/KernelAllocator.hpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
|
||||
#include "utils/Rc.hpp"
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace orbis {
|
||||
inline namespace utils {
|
||||
void *kalloc(std::size_t size, std::size_t align);
|
||||
void kfree(void* ptr, std::size_t size);
|
||||
template <typename T> struct kallocator {
|
||||
using value_type = T;
|
||||
|
||||
template <typename U> struct rebind { using other = kallocator<U>; };
|
||||
|
||||
T *allocate(std::size_t n) {
|
||||
return static_cast<T *>(kalloc(sizeof(T) * n, alignof(T)));
|
||||
}
|
||||
|
||||
void deallocate(T *p, std::size_t n) {
|
||||
kfree(p, sizeof(T) * n);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
friend constexpr bool operator==(const kallocator &,
|
||||
const kallocator<U> &) noexcept {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> using kvector = std::vector<T, kallocator<T>>;
|
||||
template <typename T> using kdeque = std::deque<T, kallocator<T>>;
|
||||
template <typename K, typename T, typename Cmp = std::less<>>
|
||||
using kmap = std::map<K, T, Cmp, kallocator<std::pair<const K, T>>>;
|
||||
template <typename K, typename T, typename Hash = std::hash<K>,
|
||||
typename Pred = std::equal_to<K>>
|
||||
using kunmap =
|
||||
std::unordered_map<K, T, Hash, Pred, kallocator<std::pair<const K, T>>>;
|
||||
} // namespace utils
|
||||
|
||||
template <typename T, typename... Args> T *knew(Args &&...args) {
|
||||
auto loc = static_cast<T *>(utils::kalloc(sizeof(T), alignof(T)));
|
||||
auto res = std::construct_at(loc, std::forward<Args>(args)...);
|
||||
if constexpr (WithRc<T>)
|
||||
res->_total_size = sizeof(T);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T> void kdelete(T *ptr) {
|
||||
ptr->~T();
|
||||
utils::kfree(ptr, sizeof(T));
|
||||
}
|
||||
|
||||
} // namespace orbis
|
||||
|
|
@ -1,97 +1,41 @@
|
|||
#pragma once
|
||||
#include "orbis/thread/Process.hpp"
|
||||
#include "utils/LinkedNode.hpp"
|
||||
#include "utils/SharedMutex.hpp"
|
||||
|
||||
#include "orbis/thread/types.hpp"
|
||||
#include "KernelAllocator.hpp"
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace orbis {
|
||||
class KernelContext {
|
||||
struct Process;
|
||||
|
||||
class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final {
|
||||
public:
|
||||
struct EventListener {
|
||||
virtual ~EventListener() = default;
|
||||
virtual void onProcessCreated(Process *) = 0;
|
||||
virtual void onProcessDeleted(pid_t pid) = 0;
|
||||
};
|
||||
KernelContext();
|
||||
~KernelContext();
|
||||
|
||||
~KernelContext() {
|
||||
while (m_processes != nullptr) {
|
||||
deleteProcess(&m_processes->object);
|
||||
}
|
||||
}
|
||||
Process *createProcess(pid_t pid);
|
||||
void deleteProcess(Process *proc);
|
||||
Process *findProcessById(pid_t pid) const;
|
||||
|
||||
void addEventListener(EventListener *listener) {
|
||||
m_event_listeners.push_back(listener);
|
||||
}
|
||||
|
||||
void removeEventListener(EventListener *listener) {
|
||||
auto it =
|
||||
std::find(m_event_listeners.begin(), m_event_listeners.end(), listener);
|
||||
|
||||
if (it != m_event_listeners.end()) {
|
||||
m_event_listeners.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
Process *createProcess(pid_t pid) {
|
||||
auto newProcess = new utils::LinkedNode<Process>();
|
||||
newProcess->object.context = this;
|
||||
newProcess->object.pid = pid;
|
||||
newProcess->object.state = ProcessState::NEW;
|
||||
|
||||
{
|
||||
std::lock_guard lock(m_proc_mtx);
|
||||
if (m_processes != nullptr) {
|
||||
m_processes->insertPrev(*newProcess);
|
||||
}
|
||||
|
||||
m_processes = newProcess;
|
||||
}
|
||||
|
||||
for (auto listener : m_event_listeners) {
|
||||
listener->onProcessCreated(&newProcess->object);
|
||||
}
|
||||
|
||||
return &newProcess->object;
|
||||
}
|
||||
|
||||
void deleteProcess(Process *proc) {
|
||||
auto procNode = reinterpret_cast<utils::LinkedNode<Process> *>(proc);
|
||||
auto pid = proc->pid;
|
||||
|
||||
{
|
||||
std::lock_guard lock(m_proc_mtx);
|
||||
auto next = procNode->erase();
|
||||
|
||||
if (procNode == m_processes) {
|
||||
m_processes = next;
|
||||
}
|
||||
}
|
||||
|
||||
delete procNode;
|
||||
|
||||
for (auto listener : m_event_listeners) {
|
||||
listener->onProcessDeleted(pid);
|
||||
}
|
||||
}
|
||||
|
||||
Process *findProcessById(pid_t pid) const {
|
||||
std::lock_guard lock(m_proc_mtx);
|
||||
for (auto proc = m_processes; proc != nullptr; proc = proc->next) {
|
||||
if (proc->object.pid == pid) {
|
||||
return &proc->object;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
static void *kalloc(std::size_t size,
|
||||
std::size_t align = __STDCPP_DEFAULT_NEW_ALIGNMENT__);
|
||||
static void kfree(void *ptr, std::size_t size);
|
||||
|
||||
private:
|
||||
mutable shared_mutex m_proc_mtx;
|
||||
utils::LinkedNode<Process> *m_processes = nullptr;
|
||||
std::vector<EventListener *> m_event_listeners;
|
||||
|
||||
struct node {
|
||||
std::size_t size;
|
||||
node *next;
|
||||
};
|
||||
|
||||
mutable shared_mutex m_heap_mtx;
|
||||
void *m_heap_next = this + 1;
|
||||
node *m_free_list = nullptr;
|
||||
};
|
||||
} // namespace orbis
|
||||
|
||||
extern KernelContext &g_context;
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "ModuleSegment.hpp"
|
||||
|
||||
#include "../utils/Rc.hpp"
|
||||
#include "../KernelAllocator.hpp"
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
#include <cstddef>
|
||||
|
|
@ -65,7 +66,7 @@ struct Relocation {
|
|||
std::int64_t addend;
|
||||
};
|
||||
|
||||
struct Module {
|
||||
struct Module final {
|
||||
Process *proc{};
|
||||
std::string vfsPath;
|
||||
char moduleName[256]{};
|
||||
|
|
@ -108,16 +109,17 @@ struct Module {
|
|||
|
||||
bool isTlsDone = false;
|
||||
|
||||
std::vector<Symbol> symbols;
|
||||
std::vector<Relocation> pltRelocations;
|
||||
std::vector<Relocation> nonPltRelocations;
|
||||
std::vector<ModuleNeeded> neededModules;
|
||||
std::vector<ModuleNeeded> neededLibraries;
|
||||
std::vector<utils::Ref<Module>> importedModules;
|
||||
std::vector<utils::Ref<Module>> namespaceModules;
|
||||
std::vector<std::string> needed;
|
||||
utils::kvector<Symbol> symbols;
|
||||
utils::kvector<Relocation> pltRelocations;
|
||||
utils::kvector<Relocation> nonPltRelocations;
|
||||
utils::kvector<ModuleNeeded> neededModules;
|
||||
utils::kvector<ModuleNeeded> neededLibraries;
|
||||
utils::kvector<utils::Ref<Module>> importedModules;
|
||||
utils::kvector<utils::Ref<Module>> namespaceModules;
|
||||
utils::kvector<std::string> needed;
|
||||
|
||||
std::atomic<unsigned> references{0};
|
||||
unsigned _total_size = 0;
|
||||
|
||||
void incRef() {
|
||||
if (references.fetch_add(1, std::memory_order::relaxed) > 512) {
|
||||
|
|
|
|||
|
|
@ -6,9 +6,13 @@
|
|||
#include <utility>
|
||||
|
||||
namespace orbis {
|
||||
template <typename T, typename... Args> T *knew(Args &&...args);
|
||||
inline namespace utils {
|
||||
void kfree(void* ptr, std::size_t size);
|
||||
|
||||
struct RcBase {
|
||||
std::atomic<unsigned> references{0};
|
||||
unsigned _total_size = 0; // Set by knew/kcreate
|
||||
|
||||
virtual ~RcBase() = default;
|
||||
|
||||
|
|
@ -21,7 +25,9 @@ struct RcBase {
|
|||
// returns true if object was destroyed
|
||||
bool decRef() {
|
||||
if (references.fetch_sub(1, std::memory_order::relaxed) == 1) {
|
||||
delete this;
|
||||
auto size = _total_size;
|
||||
this->~RcBase();
|
||||
orbis::utils::kfree(this, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -116,9 +122,8 @@ public:
|
|||
|
||||
template <WithRc T, typename... ArgsT>
|
||||
requires(std::is_constructible_v<T, ArgsT...>)
|
||||
Ref<T> create(ArgsT &&...args) {
|
||||
auto result = new T(std::forward<ArgsT>(args)...);
|
||||
return Ref<T>(result);
|
||||
Ref<T> kcreate(ArgsT &&...args) {
|
||||
return Ref<T>(knew<T>(std::forward<ArgsT>(args)...));
|
||||
}
|
||||
} // namespace utils
|
||||
} // namespace orbis
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue