kernel: Add GlobalKernelObject utility

This commit is contained in:
DH 2025-10-06 01:57:23 +03:00
parent fd9bf42538
commit e66ce512d2
6 changed files with 180 additions and 3 deletions

View file

@ -272,14 +272,13 @@ target_compile_definitions(rx PRIVATE
if (WITH_PS4) if (WITH_PS4)
find_package(nlohmann_json CONFIG) find_package(nlohmann_json CONFIG)
add_subdirectory(tools) add_subdirectory(tools)
add_subdirectory(kernel/orbis)
endif() endif()
add_subdirectory(rpcsx) add_subdirectory(rpcsx)
add_subdirectory(kernel)
if (WITH_PS3) if (WITH_PS3)
include(ConfigureCompiler) include(ConfigureCompiler)
add_subdirectory(kernel/cellos)
add_subdirectory(rpcs3) add_subdirectory(rpcs3)
add_subdirectory(ps3fw) add_subdirectory(ps3fw)
endif() endif()

10
kernel/CMakeLists.txt Normal file
View file

@ -0,0 +1,10 @@
add_library(kernel INTERFACE)
target_include_directories(kernel INTERFACE include)
if (WITH_PS3)
add_subdirectory(cellos)
endif()
if (WITH_PS4)
add_subdirectory(orbis)
endif()

View file

@ -0,0 +1,139 @@
#pragma once
#include "rx/LinkedNode.hpp"
#include "rx/Serializer.hpp"
#include <cassert>
namespace kernel {
namespace detail {
struct GlobalObjectCtl {
void (*construct)();
void (*destruct)();
void (*serialize)(rx::Serializer &);
void (*deserialize)(rx::Deserializer &);
};
template <typename NamespaceT, typename T> struct GlobalKernelObjectInstance {
static inline T *instance = nullptr;
static inline rx::LinkedNode<GlobalObjectCtl> ctl = {
.object = {
.construct = +[] { instance->construct(); },
.destruct = +[] { instance->destruct(); },
.serialize = +[](rx::Serializer &s) { instance->serialize(s); },
.deserialize = +[](rx::Deserializer &s) { instance->deserialize(s); },
},
};
};
} // namespace detail
template <typename NamespaceT> struct GlobalKernelObjectStorage {
template <typename T> static void AddObject() {
auto node = &detail::GlobalKernelObjectInstance<NamespaceT, T>::ctl;
auto head = GetHead();
if (head) {
head->prev = node;
node->next = head;
}
*GetHeadPtr() = node;
}
static void ConstructAll() {
for (auto it = GetHead(); it != nullptr; it = it->next) {
it->object.construct();
}
}
static void DestructAll() {
for (auto it = GetHead(); it != nullptr; it = it->next) {
it->object.destruct();
}
}
static void SerializeAll(rx::Serializer &s) {
for (auto it = GetHead(); it != nullptr; it = it->next) {
it->object.serialize(s);
}
}
static void DeserializeAll(rx::Deserializer &s) {
for (auto it = GetHead(); it != nullptr; it = it->next) {
it->object.deserialize(s);
}
}
private:
static rx::LinkedNode<detail::GlobalObjectCtl> *GetHead() {
return *GetHeadPtr();
}
static rx::LinkedNode<detail::GlobalObjectCtl> **GetHeadPtr() {
static rx::LinkedNode<detail::GlobalObjectCtl> *registry;
return &registry;
}
};
template <rx::Serializable T, typename NamespaceT>
requires std::is_default_constructible_v<T>
class GlobalKernelObject {
union U {
T object;
U() {}
~U() {}
};
U mHolder;
public:
template <typename = void> GlobalKernelObject() {
auto &instance =
detail::GlobalKernelObjectInstance<NamespaceT,
GlobalKernelObject>::instance;
assert(instance == nullptr);
instance = this;
GlobalKernelObjectStorage<NamespaceT>::template AddObject<
GlobalKernelObject>();
}
T *operator->() { return &mHolder.object; }
const T *operator->() const { return &mHolder.object; }
T &operator*() { return mHolder.object; }
const T &operator*() const { return mHolder.object; }
operator T &() { return mHolder.object; }
operator const T &() const { return mHolder.object; }
void serialize(rx::Serializer &s)
requires rx::Serializable<T>
{
s.serialize(mHolder.object);
}
void deserialize(rx::Deserializer &s)
requires rx::Serializable<T>
{
std::construct_at(&mHolder.object);
s.deserialize(mHolder.object);
}
T &get() { return mHolder.object; }
const T &get() const { return mHolder.object; }
private:
template <typename... Args>
requires(std::is_constructible_v<T, Args && ...>)
void construct(Args &&...args) noexcept(
std::is_nothrow_constructible_v<T, Args &&...>) {
std::construct_at(&mHolder.object, std::forward<Args>(args)...);
}
template <typename... Args>
void destruct() noexcept(std::is_nothrow_destructible_v<T>) {
mHolder.object.~T();
}
friend detail::GlobalKernelObjectInstance<NamespaceT, GlobalKernelObject>;
};
} // namespace kernel

View file

@ -67,7 +67,7 @@ add_library(obj.orbis-kernel OBJECT
src/utils/Logs.cpp src/utils/Logs.cpp
) )
target_link_libraries(obj.orbis-kernel PUBLIC orbis::kernel::config rx) target_link_libraries(obj.orbis-kernel PUBLIC orbis::kernel::config rx kernel)
target_include_directories(obj.orbis-kernel target_include_directories(obj.orbis-kernel
PUBLIC PUBLIC

View file

@ -0,0 +1,26 @@
#pragma once
#include <kernel/GlobalKernelObject.hpp>
namespace orbis {
struct OrbisNamespace;
template <rx::Serializable T>
using GlobalKernelObject = kernel::GlobalKernelObject<T, OrbisNamespace>;
template <rx::Serializable T> GlobalKernelObject<T> createGlobalObject() {
return {};
}
inline void constructAllGlobals() {
kernel::GlobalKernelObjectStorage<OrbisNamespace>::ConstructAll();
}
inline void destructAllGlobals() {
kernel::GlobalKernelObjectStorage<OrbisNamespace>::DestructAll();
}
template <typename T> T &getGlobalObject() {
assert(detail::GlobalKernelObjectInstance<GlobalKernelObject<T>>::instance);
return kernel::detail::GlobalKernelObjectInstance<
OrbisNamespace, GlobalKernelObject<T>>::instance->get();
}
} // namespace orbis

View file

@ -26,6 +26,7 @@
#include <elf.h> #include <elf.h>
#include <linux/prctl.h> #include <linux/prctl.h>
#include <orbis/GlobalKernelObject.hpp>
#include <orbis/KernelContext.hpp> #include <orbis/KernelContext.hpp>
#include <orbis/module.hpp> #include <orbis/module.hpp>
#include <orbis/module/Module.hpp> #include <orbis/module/Module.hpp>
@ -1265,6 +1266,8 @@ int main(int argc, const char *argv[]) {
guestInitDev(); guestInitDev();
guestInitFd(mainThread); guestInitFd(mainThread);
orbis::constructAllGlobals();
// data transfer mode // data transfer mode
// 0 - normal // 0 - normal
// 1 - source // 1 - source