kernel: avoid global storage usage for process/thread local variables

enables multiple guest processes emulation in single host process
This commit is contained in:
DH 2025-10-11 15:22:34 +03:00
parent 05dee2c8e3
commit aee92cce57
6 changed files with 97 additions and 102 deletions

View file

@ -32,7 +32,7 @@ struct RcAppInfo : rx::RcBase, AppInfoEx {
orbis::uint32_t appState = 0;
};
class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final {
class KernelContext final {
public:
KernelContext();
~KernelContext();

View file

@ -1,23 +1,21 @@
#pragma once
#include "rx/Serializer.hpp"
#include <cstddef>
#include <kernel/KernelObject.hpp>
namespace orbis {
struct OrbisNamespace;
template <rx::Serializable StateT>
using GlobalObjectRef =
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::GlobalScope,
StateT>;
extern std::byte *g_globalStorage;
template <rx::Serializable StateT>
using ProcessLocalObjectRef =
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ProcessScope,
StateT>;
template <rx::Serializable T> class GlobalObjectRef {
std::uint32_t mOffset;
template <rx::Serializable StateT>
using ThreadLocalObjectRef =
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ThreadScope,
StateT>;
public:
explicit GlobalObjectRef(std::uint32_t offset) : mOffset(offset) {}
T *get() { return reinterpret_cast<T *>(g_globalStorage + mOffset); }
T *operator->() { return get(); }
};
template <rx::Serializable StateT>
GlobalObjectRef<StateT> createGlobalObject() {
@ -33,8 +31,7 @@ createProcessLocalObject() {
auto layoutOffset = kernel::StaticKernelObjectStorage<
OrbisNamespace,
kernel::detail::ProcessScope>::template Allocate<StateT>();
return kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ProcessScope,
StateT>(layoutOffset);
return {layoutOffset};
}
template <rx::Serializable StateT>
@ -42,67 +39,30 @@ kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ThreadScope, StateT>
createThreadLocalObject() {
auto layoutOffset = kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ThreadScope>::template Allocate<StateT>();
return kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ThreadScope,
StateT>(layoutOffset);
return {layoutOffset};
}
inline void constructAllGlobals() {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::GlobalScope>::ConstructAll();
}
inline void constructAllProcessLocals() {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ProcessScope>::ConstructAll();
}
inline void constructAllThreadLocals() {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ThreadScope>::ConstructAll();
OrbisNamespace,
kernel::detail::GlobalScope>::ConstructAll(g_globalStorage);
}
inline void destructAllGlobals() {
kernel::StaticKernelObjectStorage<OrbisNamespace,
kernel::detail::GlobalScope>::DestructAll();
}
inline void destructAllProcessLocals() {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ProcessScope>::DestructAll();
}
inline void destructAllThreadLocals() {
kernel::StaticKernelObjectStorage<OrbisNamespace,
kernel::detail::ThreadScope>::DestructAll();
OrbisNamespace,
kernel::detail::GlobalScope>::DestructAll(g_globalStorage);
}
inline void serializeAllGlobals(rx::Serializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::GlobalScope>::SerializeAll(s);
}
inline void serializeAllProcessLocals(rx::Serializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ProcessScope>::SerializeAll(s);
}
inline void serializeAllThreadLocals(rx::Serializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ThreadScope>::SerializeAll(s);
OrbisNamespace,
kernel::detail::GlobalScope>::SerializeAll(g_globalStorage, s);
}
inline void deserializeAllGlobals(rx::Deserializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::GlobalScope>::DeserializeAll(s);
}
inline void deserializeAllProcessLocals(rx::Deserializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ProcessScope>::DeserializeAll(s);
}
inline void deserializeAllThreadLocals(rx::Deserializer &s) {
kernel::StaticKernelObjectStorage<
OrbisNamespace, kernel::detail::ThreadScope>::DeserializeAll(s);
OrbisNamespace,
kernel::detail::GlobalScope>::DeserializeAll(g_globalStorage, s);
}
} // namespace orbis

View file

@ -1,4 +1,7 @@
#pragma once
#include "KernelAllocator.hpp"
#include "KernelObject.hpp"
#include "kernel/KernelObject.hpp"
#include "orbis-config.hpp"
#include "../event.hpp"
@ -15,6 +18,7 @@
#include "orbis/file.hpp"
#include "orbis/module/Module.hpp"
#include "rx/IdMap.hpp"
#include "rx/Serializer.hpp"
#include "rx/SharedMutex.hpp"
#include <optional>
@ -52,7 +56,13 @@ enum class ProcessType : std::uint8_t {
};
struct Process final {
using Storage =
kernel::StaticKernelObjectStorage<OrbisNamespace,
kernel::detail::ProcessScope>;
KernelContext *context = nullptr;
std::byte *storage = nullptr;
pid_t pid = -1;
int gfxRing = 0;
std::uint64_t hostPid = -1;
@ -101,5 +111,29 @@ struct Process final {
// Named memory ranges for debugging
rx::shared_mutex namedMemMutex;
kmap<NamedMemoryRange, kstring> namedMem;
// FIXME: implement process destruction
void incRef() {}
void decRef() {}
void allocate() {
if (auto size = Storage::GetSize()) {
storage = (std::byte *)kalloc(size, Storage::GetAlignment());
}
}
void deallocate() {
if (auto size = Storage::GetSize()) {
kfree(storage, size);
storage = nullptr;
}
}
template <rx::Serializable T>
T *get(
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ProcessScope, T>
ref) {
return ref.get(storage);
}
};
} // namespace orbis

View file

@ -1,8 +1,10 @@
#pragma once
#include "KernelObject.hpp"
#include "ThreadState.hpp"
#include "cpuset.hpp"
#include "orbis-config.hpp"
#include "rx/Serializer.hpp"
#include "types.hpp"
#include "../KernelAllocator.hpp"
@ -16,9 +18,14 @@ namespace orbis {
struct Process;
static constexpr std::uint32_t kThreadSuspendFlag = 1 << 31;
struct Thread {
struct Thread final {
using Storage =
kernel::StaticKernelObjectStorage<OrbisNamespace,
kernel::detail::ThreadScope>;
rx::shared_mutex mtx;
Process *tproc = nullptr;
std::byte *storage = nullptr;
uint64_t retval[2]{};
void *context{};
kvector<void *> altStack;
@ -75,6 +82,25 @@ struct Thread {
void notifyUnblockedSignal(int signo);
void setSigMask(SigSet newSigMask);
void allocate() {
if (auto size = Storage::GetSize()) {
storage = (std::byte *)kalloc(size, Storage::GetAlignment());
}
}
void deallocate() {
if (auto size = Storage::GetSize()) {
kfree(storage, size);
storage = nullptr;
}
}
template <rx::Serializable T>
T *get(kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ThreadScope, T>
ref) {
return ref.get(storage);
}
// FIXME: implement thread destruction
void incRef() {}
void decRef() {}

View file

@ -39,7 +39,8 @@ struct KernelMemoryResource {
};
static KernelMemoryResource *sMemoryResource;
static std::byte *sGlobalStorage;
std::byte *g_globalStorage;
using GlobalStorage =
kernel::StaticKernelObjectStorage<OrbisNamespace,
kernel::detail::GlobalScope>;
@ -69,15 +70,15 @@ void initializeAllocator() {
rx::print(stderr, "global: size {}, alignment {}\n", GlobalStorage::GetSize(),
GlobalStorage::GetAlignment());
// allocate whole global storage
sGlobalStorage = (std::byte *)sMemoryResource->kalloc(
g_globalStorage = (std::byte *)sMemoryResource->kalloc(
GlobalStorage::GetSize(), GlobalStorage::GetAlignment());
}
void deinitializeAllocator() {
sMemoryResource->kfree(sGlobalStorage, GlobalStorage::GetSize());
sMemoryResource->kfree(g_globalStorage, GlobalStorage::GetSize());
delete sMemoryResource;
sMemoryResource = nullptr;
sGlobalStorage = nullptr;
g_globalStorage = nullptr;
}
void *KernelMemoryResource::kalloc(std::size_t size, std::size_t align) {
@ -213,9 +214,3 @@ void *kalloc(std::size_t size, std::size_t align) {
return sMemoryResource->kalloc(size, align);
}
} // namespace orbis
template <>
std::byte *
kernel::getScopeStorage<orbis::OrbisNamespace, kernel::detail::GlobalScope>() {
return orbis::sGlobalStorage;
}