mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-10 00:45:37 +00:00
kernel: split context and allocator & initial implementation of process/thread local objects
Some checks are pending
Formatting check / formatting-check (push) Waiting to run
Build RPCSX / build-linux (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.1-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.2-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.4-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.5-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv9-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv9.1-a) (push) Waiting to run
Build RPCSX / build-android (x86_64, x86-64) (push) Waiting to run
Some checks are pending
Formatting check / formatting-check (push) Waiting to run
Build RPCSX / build-linux (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.1-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.2-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.4-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv8.5-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv9-a) (push) Waiting to run
Build RPCSX / build-android (arm64-v8a, armv9.1-a) (push) Waiting to run
Build RPCSX / build-android (x86_64, x86-64) (push) Waiting to run
This commit is contained in:
parent
b358d6b2c9
commit
2589143798
34 changed files with 774 additions and 597 deletions
|
|
@ -1,139 +0,0 @@
|
|||
#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 ®istry;
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
180
kernel/include/kernel/KernelObject.hpp
Normal file
180
kernel/include/kernel/KernelObject.hpp
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
#pragma once
|
||||
|
||||
#include "rx/Rc.hpp"
|
||||
#include "rx/Serializer.hpp"
|
||||
#include "rx/TypeId.hpp"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace kernel {
|
||||
class KernelObjectBase : public rx::RcBase {
|
||||
rx::TypeId mType;
|
||||
|
||||
public:
|
||||
KernelObjectBase(rx::TypeId type) : mType(type) {}
|
||||
[[nodiscard]] rx::TypeId getType() const { return mType; }
|
||||
|
||||
template <typename T> [[nodiscard]] bool isa() const {
|
||||
return mType == rx::TypeId::get<T>();
|
||||
}
|
||||
};
|
||||
|
||||
template <rx::Serializable StateT>
|
||||
struct KernelObject : KernelObjectBase, StateT {
|
||||
template <typename... Args>
|
||||
KernelObject(Args &&...args)
|
||||
: KernelObjectBase(rx::TypeId::get<StateT>()),
|
||||
StateT(std::forward<Args>(args)...) {}
|
||||
|
||||
virtual void serialize(rx::Serializer &s) const {
|
||||
if constexpr (requires(const KernelObject &instance) {
|
||||
instance.lock();
|
||||
instance.unlock();
|
||||
}) {
|
||||
std::lock_guard lock(*this);
|
||||
s.serialize(static_cast<const StateT &>(*this));
|
||||
} else {
|
||||
s.serialize(static_cast<const StateT &>(*this));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void deserialize(rx::Deserializer &s) {
|
||||
s.deserialize(static_cast<StateT &>(*this));
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
struct StaticObjectCtl {
|
||||
std::size_t offset = -1ull;
|
||||
void (*construct)(void *object);
|
||||
void (*destruct)(void *object);
|
||||
void (*serialize)(void *object, rx::Serializer &);
|
||||
void (*deserialize)(void *object, rx::Deserializer &);
|
||||
|
||||
template <typename T> constexpr static StaticObjectCtl Create() {
|
||||
return {
|
||||
.construct =
|
||||
+[](void *object) {
|
||||
std::construct_at(reinterpret_cast<T *>(object));
|
||||
},
|
||||
.destruct = +[](void *object) { reinterpret_cast<T *>(object)->~T(); },
|
||||
.serialize =
|
||||
+[](void *object, rx::Serializer &serializer) {
|
||||
serializer.serialize(*reinterpret_cast<T *>(object));
|
||||
},
|
||||
.deserialize =
|
||||
+[](void *object, rx::Deserializer &deserializer) {
|
||||
deserializer.deserialize(*reinterpret_cast<T *>(object));
|
||||
},
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
struct GlobalScope;
|
||||
struct ProcessScope;
|
||||
struct ThreadScope;
|
||||
} // namespace detail
|
||||
|
||||
template <typename NamespaceT, typename ScopeT> std::byte *getScopeStorage();
|
||||
|
||||
template <typename NamespaceT, typename ScopeT>
|
||||
struct StaticKernelObjectStorage {
|
||||
template <typename T> static std::uint32_t Allocate() {
|
||||
auto &instance = GetInstance();
|
||||
|
||||
auto object = detail::StaticObjectCtl::Create<T>();
|
||||
instance.m_registry.push_back(object);
|
||||
|
||||
auto offset = instance.m_size;
|
||||
offset = rx::alignUp(offset, alignof(T));
|
||||
instance.m_registry.back().offset = offset;
|
||||
instance.m_size = offset + sizeof(T);
|
||||
instance.m_alignment =
|
||||
std::max<std::size_t>(alignof(T), instance.m_alignment);
|
||||
// std::printf(
|
||||
// "%s::Allocate(%s, %zu, %zu) -> %zu\n",
|
||||
// rx::TypeId::get<StaticKernelObjectStorage<NamespaceT,
|
||||
// ScopeT>>().getName().data(), rx::TypeId::get<T>().getName().data(),
|
||||
// sizeof(T), alignof(T), offset);
|
||||
return offset;
|
||||
}
|
||||
|
||||
static std::size_t GetSize() { return GetInstance().m_size; }
|
||||
static std::size_t GetAlignment() { return GetInstance().m_alignment; }
|
||||
static std::byte *getScopeStorage() {
|
||||
return kernel::getScopeStorage<NamespaceT, ScopeT>();
|
||||
}
|
||||
|
||||
static void ConstructAll() {
|
||||
auto &instance = GetInstance();
|
||||
auto storage = getScopeStorage();
|
||||
|
||||
for (auto objectCtl : instance.m_registry) {
|
||||
objectCtl.construct(storage + objectCtl.offset);
|
||||
}
|
||||
}
|
||||
|
||||
static void DestructAll() {
|
||||
auto &instance = GetInstance();
|
||||
auto storage = getScopeStorage();
|
||||
|
||||
for (auto objectCtl : instance.m_registry) {
|
||||
objectCtl.destruct(storage + objectCtl.offset);
|
||||
}
|
||||
}
|
||||
|
||||
static void SerializeAll(rx::Serializer &s) {
|
||||
auto &instance = GetInstance();
|
||||
auto storage = getScopeStorage();
|
||||
|
||||
s.serialize(instance.m_size);
|
||||
s.serialize(instance.m_registry.size());
|
||||
|
||||
for (auto objectCtl : instance.m_registry) {
|
||||
objectCtl.serialize(storage + objectCtl.offset, s);
|
||||
}
|
||||
}
|
||||
|
||||
static void DeserializeAll(rx::Deserializer &s) {
|
||||
auto &instance = GetInstance();
|
||||
auto storage = getScopeStorage();
|
||||
|
||||
auto size = s.deserialize<std::size_t>();
|
||||
auto registrySize = s.deserialize<std::size_t>();
|
||||
|
||||
if (size != instance.m_size || registrySize != instance.m_registry.size()) {
|
||||
s.setFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto objectCtl : instance.m_registry) {
|
||||
objectCtl.deserialize(storage + objectCtl.offset, s);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static StaticKernelObjectStorage &GetInstance() {
|
||||
static StaticKernelObjectStorage instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::vector<detail::StaticObjectCtl> m_registry;
|
||||
std::size_t m_size = 0;
|
||||
std::size_t m_alignment = 1;
|
||||
};
|
||||
|
||||
template <typename NamespaceT, typename ScopeT, rx::Serializable T>
|
||||
class StaticObjectRef {
|
||||
std::uint32_t mOffset;
|
||||
|
||||
public:
|
||||
explicit StaticObjectRef(std::uint32_t offset) : mOffset(offset) {}
|
||||
|
||||
T *get() {
|
||||
return reinterpret_cast<T *>(getScopeStorage<NamespaceT, ScopeT>() +
|
||||
mOffset);
|
||||
}
|
||||
|
||||
T *operator->() { return get(); }
|
||||
};
|
||||
} // namespace kernel
|
||||
|
|
@ -7,6 +7,7 @@ add_library(obj.orbis-kernel OBJECT
|
|||
src/event.cpp
|
||||
src/evf.cpp
|
||||
src/ipmi.cpp
|
||||
src/KernelAllocator.cpp
|
||||
src/KernelContext.cpp
|
||||
src/umtx.cpp
|
||||
src/sys/sys_acct.cpp
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
#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
|
||||
|
|
@ -10,7 +10,6 @@
|
|||
#include <vector>
|
||||
|
||||
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 {
|
||||
|
|
@ -51,7 +50,6 @@ 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>
|
||||
requires(std::is_constructible_v<T, Args...>)
|
||||
|
|
@ -61,17 +59,17 @@ T *knew(Args &&...args) {
|
|||
struct DynamicObject final : T {
|
||||
using T::T;
|
||||
|
||||
void operator delete(void *pointer) { utils::kfree(pointer, sizeof(T)); }
|
||||
void operator delete(void *pointer) { kfree(pointer, sizeof(T)); }
|
||||
};
|
||||
|
||||
auto loc = static_cast<DynamicObject *>(
|
||||
utils::kalloc(sizeof(DynamicObject), alignof(DynamicObject)));
|
||||
kalloc(sizeof(DynamicObject), alignof(DynamicObject)));
|
||||
return std::construct_at(loc, std::forward<Args>(args)...);
|
||||
} else {
|
||||
static_assert(!std::is_polymorphic_v<T>,
|
||||
"Polymorphic type should be derived from rx::RcBase");
|
||||
|
||||
auto loc = static_cast<T *>(utils::kalloc(sizeof(T), alignof(T)));
|
||||
auto loc = static_cast<T *>(kalloc(sizeof(T), alignof(T)));
|
||||
return std::construct_at(loc, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
|
@ -80,8 +78,10 @@ T *knew(Args &&...args) {
|
|||
template <typename T> void kdelete(T *ptr) {
|
||||
static_assert(std::is_final_v<T>, "Uncertain type size");
|
||||
ptr->~T();
|
||||
utils::kfree(ptr, sizeof(T));
|
||||
kfree(ptr, sizeof(T));
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
void initializeAllocator();
|
||||
void deinitializeAllocator();
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include "AppInfo.hpp"
|
||||
#include "Budget.hpp"
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "KernelObject.hpp"
|
||||
#include "evf.hpp"
|
||||
#include "ipmi.hpp"
|
||||
#include "orbis/note.hpp"
|
||||
|
|
@ -50,12 +50,7 @@ public:
|
|||
|
||||
long getTscFreq();
|
||||
|
||||
void *kalloc(std::size_t size,
|
||||
std::size_t align = __STDCPP_DEFAULT_NEW_ALIGNMENT__);
|
||||
void kfree(void *ptr, std::size_t size);
|
||||
|
||||
std::pair<EventFlag *, bool> createEventFlag(utils::kstring name,
|
||||
std::int32_t flags,
|
||||
std::pair<EventFlag *, bool> createEventFlag(kstring name, std::int32_t flags,
|
||||
std::uint64_t initPattern) {
|
||||
std::lock_guard lock(m_evf_mtx);
|
||||
|
||||
|
|
@ -78,7 +73,7 @@ public:
|
|||
return {};
|
||||
}
|
||||
|
||||
std::pair<Semaphore *, bool> createSemaphore(utils::kstring name,
|
||||
std::pair<Semaphore *, bool> createSemaphore(kstring name,
|
||||
std::uint32_t attrs,
|
||||
std::int32_t initCount,
|
||||
std::int32_t maxCount) {
|
||||
|
|
@ -100,8 +95,7 @@ public:
|
|||
return {};
|
||||
}
|
||||
|
||||
std::pair<rx::Ref<IpmiServer>, ErrorCode>
|
||||
createIpmiServer(utils::kstring name) {
|
||||
std::pair<rx::Ref<IpmiServer>, ErrorCode> createIpmiServer(kstring name) {
|
||||
std::lock_guard lock(m_sem_mtx);
|
||||
auto [it, inserted] = mIpmiServers.try_emplace(std::move(name), nullptr);
|
||||
|
||||
|
|
@ -128,15 +122,14 @@ public:
|
|||
return {};
|
||||
}
|
||||
|
||||
std::tuple<utils::kmap<utils::kstring, char[128]> &,
|
||||
std::unique_lock<rx::shared_mutex>>
|
||||
std::tuple<kmap<kstring, char[128]> &, std::unique_lock<rx::shared_mutex>>
|
||||
getKernelEnv() {
|
||||
std::unique_lock lock(m_kenv_mtx);
|
||||
return {m_kenv, std::move(lock)};
|
||||
}
|
||||
|
||||
void setKernelEnv(std::string_view key, std::string_view value) {
|
||||
auto &kenvValue = m_kenv[utils::kstring(key)];
|
||||
auto &kenvValue = m_kenv[kstring(key)];
|
||||
auto len = std::min(sizeof(kenvValue) - 1, value.size());
|
||||
std::memcpy(kenvValue, value.data(), len);
|
||||
kenvValue[len] = '0';
|
||||
|
|
@ -177,14 +170,10 @@ public:
|
|||
return processTypeBudgets[static_cast<int>(processType)];
|
||||
}
|
||||
|
||||
void serialize(rx::Serializer &) const {}
|
||||
void deserialize(rx::Deserializer &) {}
|
||||
|
||||
private:
|
||||
rx::shared_mutex m_heap_mtx;
|
||||
rx::shared_mutex m_heap_map_mtx;
|
||||
void *m_heap_next = this + 1;
|
||||
|
||||
utils::kmultimap<std::size_t, void *> m_free_heap;
|
||||
utils::kmultimap<std::size_t, void *> m_used_node;
|
||||
|
||||
std::atomic<long> m_tsc_freq{0};
|
||||
|
||||
rx::shared_mutex m_thread_id_mtx;
|
||||
|
|
@ -193,17 +182,17 @@ private:
|
|||
rx::LinkedNode<Process> *m_processes = nullptr;
|
||||
|
||||
rx::shared_mutex m_evf_mtx;
|
||||
utils::kmap<utils::kstring, rx::Ref<EventFlag>> m_event_flags;
|
||||
kmap<kstring, rx::Ref<EventFlag>> m_event_flags;
|
||||
|
||||
rx::shared_mutex m_sem_mtx;
|
||||
utils::kmap<utils::kstring, rx::Ref<Semaphore>> m_semaphores;
|
||||
kmap<kstring, rx::Ref<Semaphore>> m_semaphores;
|
||||
|
||||
rx::shared_mutex mIpmiServerMtx;
|
||||
utils::kmap<utils::kstring, rx::Ref<IpmiServer>> mIpmiServers;
|
||||
kmap<kstring, rx::Ref<IpmiServer>> mIpmiServers;
|
||||
|
||||
rx::shared_mutex m_kenv_mtx;
|
||||
utils::kmap<utils::kstring, char[128]> m_kenv; // max size: 127 + '\0'
|
||||
kmap<kstring, char[128]> m_kenv; // max size: 127 + '\0'
|
||||
};
|
||||
|
||||
extern KernelContext &g_context;
|
||||
extern GlobalObjectRef<KernelContext> g_context;
|
||||
} // namespace orbis
|
||||
|
|
|
|||
108
kernel/orbis/include/orbis/KernelObject.hpp
Normal file
108
kernel/orbis/include/orbis/KernelObject.hpp
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
#pragma once
|
||||
#include <kernel/KernelObject.hpp>
|
||||
|
||||
namespace orbis {
|
||||
struct OrbisNamespace;
|
||||
|
||||
template <rx::Serializable StateT>
|
||||
using GlobalObjectRef =
|
||||
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::GlobalScope,
|
||||
StateT>;
|
||||
|
||||
template <rx::Serializable StateT>
|
||||
using ProcessLocalObjectRef =
|
||||
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ProcessScope,
|
||||
StateT>;
|
||||
|
||||
template <rx::Serializable StateT>
|
||||
using ThreadLocalObjectRef =
|
||||
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ThreadScope,
|
||||
StateT>;
|
||||
|
||||
template <rx::Serializable StateT>
|
||||
GlobalObjectRef<StateT> createGlobalObject() {
|
||||
auto layoutOffset = kernel::StaticKernelObjectStorage<
|
||||
OrbisNamespace, kernel::detail::GlobalScope>::template Allocate<StateT>();
|
||||
|
||||
return GlobalObjectRef<StateT>(layoutOffset);
|
||||
}
|
||||
|
||||
template <rx::Serializable StateT>
|
||||
kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ProcessScope, StateT>
|
||||
createProcessLocalObject() {
|
||||
auto layoutOffset = kernel::StaticKernelObjectStorage<
|
||||
OrbisNamespace,
|
||||
kernel::detail::ProcessScope>::template Allocate<StateT>();
|
||||
return kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ProcessScope,
|
||||
StateT>(layoutOffset);
|
||||
}
|
||||
|
||||
template <rx::Serializable StateT>
|
||||
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);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
} // namespace orbis
|
||||
|
|
@ -57,7 +57,7 @@ struct EventFlag final {
|
|||
};
|
||||
|
||||
rx::shared_mutex queueMtx;
|
||||
utils::kvector<WaitingThread> waitingThreads;
|
||||
kvector<WaitingThread> waitingThreads;
|
||||
|
||||
enum class NotifyType { Set, Cancel, Destroy };
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ struct File : rx::RcBase {
|
|||
int flags = 0;
|
||||
int mode = 0;
|
||||
int hostFd = -1;
|
||||
utils::kvector<Dirent> dirEntries;
|
||||
kvector<Dirent> dirEntries;
|
||||
|
||||
bool noBlock() const { return (flags & 4) != 0; }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ enum class DynType : std::uint8_t {
|
|||
};
|
||||
|
||||
struct ModuleNeeded {
|
||||
utils::kstring name;
|
||||
kstring name;
|
||||
std::uint16_t version;
|
||||
std::uint64_t attr;
|
||||
bool isExport;
|
||||
|
|
@ -67,7 +67,7 @@ struct Relocation {
|
|||
|
||||
struct Module final {
|
||||
Process *proc{};
|
||||
utils::kstring vfsPath;
|
||||
kstring vfsPath;
|
||||
char moduleName[256]{};
|
||||
char soName[256]{};
|
||||
ModuleHandle id{};
|
||||
|
|
@ -110,15 +110,15 @@ struct Module final {
|
|||
|
||||
bool isTlsDone = false;
|
||||
|
||||
utils::kstring interp;
|
||||
utils::kvector<Symbol> symbols;
|
||||
utils::kvector<Relocation> pltRelocations;
|
||||
utils::kvector<Relocation> nonPltRelocations;
|
||||
utils::kvector<ModuleNeeded> neededModules;
|
||||
utils::kvector<ModuleNeeded> neededLibraries;
|
||||
utils::kvector<rx::Ref<Module>> importedModules;
|
||||
utils::kvector<rx::Ref<Module>> namespaceModules;
|
||||
utils::kvector<utils::kstring> needed;
|
||||
kstring interp;
|
||||
kvector<Symbol> symbols;
|
||||
kvector<Relocation> pltRelocations;
|
||||
kvector<Relocation> nonPltRelocations;
|
||||
kvector<ModuleNeeded> neededModules;
|
||||
kvector<ModuleNeeded> neededLibraries;
|
||||
kvector<rx::Ref<Module>> importedModules;
|
||||
kvector<rx::Ref<Module>> namespaceModules;
|
||||
kvector<kstring> needed;
|
||||
|
||||
std::atomic<unsigned> references{0};
|
||||
|
||||
|
|
|
|||
|
|
@ -93,13 +93,13 @@ struct Process final {
|
|||
|
||||
// Named objects for debugging
|
||||
rx::shared_mutex namedObjMutex;
|
||||
utils::kmap<void *, utils::kstring> namedObjNames;
|
||||
kmap<void *, kstring> namedObjNames;
|
||||
rx::OwningIdMap<NamedObjInfo, uint, 65535, 1> namedObjIds;
|
||||
|
||||
utils::kmap<std::int32_t, SigAction> sigActions;
|
||||
kmap<std::int32_t, SigAction> sigActions;
|
||||
|
||||
// Named memory ranges for debugging
|
||||
rx::shared_mutex namedMemMutex;
|
||||
utils::kmap<NamedMemoryRange, utils::kstring> namedMem;
|
||||
kmap<NamedMemoryRange, kstring> namedMem;
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
|
|||
221
kernel/orbis/src/KernelAllocator.cpp
Normal file
221
kernel/orbis/src/KernelAllocator.cpp
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
#include "KernelAllocator.hpp"
|
||||
#include "KernelObject.hpp"
|
||||
#include "rx/Serializer.hpp"
|
||||
#include "rx/SharedMutex.hpp"
|
||||
#include "rx/print.hpp"
|
||||
#include <sys/mman.h>
|
||||
|
||||
static const std::uint64_t g_allocProtWord = 0xDEADBEAFBADCAFE1;
|
||||
static constexpr std::uintptr_t kHeapBaseAddress = 0x00000600'0000'0000;
|
||||
static constexpr auto kHeapSize = 0x1'0000'0000;
|
||||
static constexpr int kDebugHeap = 0;
|
||||
|
||||
namespace orbis {
|
||||
struct KernelMemoryResource {
|
||||
mutable rx::shared_mutex m_heap_mtx;
|
||||
rx::shared_mutex m_heap_map_mtx;
|
||||
void *m_heap_next = nullptr;
|
||||
|
||||
kmultimap<std::size_t, void *> m_free_heap;
|
||||
kmultimap<std::size_t, void *> m_used_node;
|
||||
|
||||
~KernelMemoryResource() {
|
||||
::munmap(std::bit_cast<void *>(kHeapBaseAddress), kHeapSize);
|
||||
}
|
||||
|
||||
void *kalloc(std::size_t size,
|
||||
std::size_t align = __STDCPP_DEFAULT_NEW_ALIGNMENT__);
|
||||
void kfree(void *ptr, std::size_t size);
|
||||
|
||||
void serialize(rx::Serializer &) const {
|
||||
// FIXME: implement
|
||||
}
|
||||
void deserialize(rx::Deserializer &) {
|
||||
// FIXME: implement
|
||||
}
|
||||
|
||||
void lock() const { m_heap_mtx.lock(); }
|
||||
void unlock() const { m_heap_mtx.unlock(); }
|
||||
};
|
||||
|
||||
static KernelMemoryResource *sMemoryResource;
|
||||
static std::byte *sGlobalStorage;
|
||||
using GlobalStorage =
|
||||
kernel::StaticKernelObjectStorage<OrbisNamespace,
|
||||
kernel::detail::GlobalScope>;
|
||||
|
||||
void initializeAllocator() {
|
||||
auto ptr = (std::byte *)::mmap(std::bit_cast<void *>(kHeapBaseAddress),
|
||||
kHeapSize, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
|
||||
if (ptr == MAP_FAILED) {
|
||||
perror("mmap failed");
|
||||
FILE *maps = std::fopen("/proc/self/maps", "r");
|
||||
char *line = nullptr;
|
||||
std::size_t size = 0;
|
||||
while (getline(&line, &size, maps) > 0) {
|
||||
std::puts(line);
|
||||
}
|
||||
|
||||
std::free(line);
|
||||
std::fclose(maps);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
sMemoryResource = new (ptr) KernelMemoryResource();
|
||||
sMemoryResource->m_heap_next = ptr + sizeof(KernelMemoryResource);
|
||||
|
||||
rx::print(stderr, "global: size {}, alignment {}\n", GlobalStorage::GetSize(),
|
||||
GlobalStorage::GetAlignment());
|
||||
// allocate whole global storage
|
||||
sGlobalStorage = (std::byte *)sMemoryResource->kalloc(
|
||||
GlobalStorage::GetSize(), GlobalStorage::GetAlignment());
|
||||
}
|
||||
|
||||
void deinitializeAllocator() {
|
||||
sMemoryResource->kfree(sGlobalStorage, GlobalStorage::GetSize());
|
||||
delete sMemoryResource;
|
||||
sMemoryResource = nullptr;
|
||||
sGlobalStorage = nullptr;
|
||||
}
|
||||
|
||||
void *KernelMemoryResource::kalloc(std::size_t size, std::size_t align) {
|
||||
size = (size + (__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1)) &
|
||||
~(__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1);
|
||||
if (!size)
|
||||
std::abort();
|
||||
|
||||
if (m_heap_map_mtx.try_lock()) {
|
||||
std::lock_guard lock(m_heap_map_mtx, std::adopt_lock);
|
||||
|
||||
// Try to reuse previously freed block
|
||||
for (auto [it, end] = m_free_heap.equal_range(size); it != end; ++it) {
|
||||
auto result = it->second;
|
||||
if (!(std::bit_cast<std::uintptr_t>(result) & (align - 1))) {
|
||||
auto node = m_free_heap.extract(it);
|
||||
node.key() = 0;
|
||||
node.mapped() = nullptr;
|
||||
m_used_node.insert(m_used_node.begin(), std::move(node));
|
||||
|
||||
// std::fprintf(stderr, "kalloc: reuse %p-%p, size = %lx\n", result,
|
||||
// (char *)result + size, size);
|
||||
|
||||
if (kDebugHeap > 0) {
|
||||
std::memcpy(std::bit_cast<std::byte *>(result) + size,
|
||||
&g_allocProtWord, sizeof(g_allocProtWord));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard lock(m_heap_mtx);
|
||||
align = std::max<std::size_t>(align, __STDCPP_DEFAULT_NEW_ALIGNMENT__);
|
||||
auto heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
|
||||
heap = (heap + (align - 1)) & ~(align - 1);
|
||||
|
||||
if (kDebugHeap > 1) {
|
||||
if (auto diff = (heap + size + sizeof(g_allocProtWord)) % 4096; diff != 0) {
|
||||
heap += 4096 - diff;
|
||||
heap &= ~(align - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (heap + size > kHeapBaseAddress + kHeapSize) {
|
||||
std::fprintf(stderr, "out of kernel memory");
|
||||
std::abort();
|
||||
}
|
||||
// Check overflow
|
||||
if (heap + size < heap) {
|
||||
std::fprintf(stderr, "too big allocation");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
// std::fprintf(stderr, "kalloc: allocate %lx-%lx, size = %lx, align=%lx\n",
|
||||
// heap, heap + size, size, align);
|
||||
|
||||
auto result = reinterpret_cast<void *>(heap);
|
||||
if (kDebugHeap > 0) {
|
||||
std::memcpy(std::bit_cast<std::byte *>(result) + size, &g_allocProtWord,
|
||||
sizeof(g_allocProtWord));
|
||||
}
|
||||
|
||||
if (kDebugHeap > 0) {
|
||||
m_heap_next =
|
||||
reinterpret_cast<void *>(heap + size + sizeof(g_allocProtWord));
|
||||
} else {
|
||||
m_heap_next = reinterpret_cast<void *>(heap + size);
|
||||
}
|
||||
|
||||
if (kDebugHeap > 1) {
|
||||
heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
|
||||
align = std::min<std::size_t>(align, 4096);
|
||||
heap = (heap + (align - 1)) & ~(align - 1);
|
||||
size = 4096;
|
||||
// std::fprintf(stderr, "kalloc: protect %lx-%lx, size = %lx, align=%lx\n",
|
||||
// heap, heap + size, size, align);
|
||||
|
||||
auto result = ::mmap(reinterpret_cast<void *>(heap), size, PROT_NONE,
|
||||
MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
||||
if (result == MAP_FAILED) {
|
||||
std::fprintf(stderr, "failed to protect memory");
|
||||
std::abort();
|
||||
}
|
||||
m_heap_next = reinterpret_cast<void *>(heap + size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void KernelMemoryResource::kfree(void *ptr, std::size_t size) {
|
||||
size = (size + (__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1)) &
|
||||
~(__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1);
|
||||
if (!size)
|
||||
std::abort();
|
||||
|
||||
if (std::bit_cast<std::uintptr_t>(ptr) < kHeapBaseAddress ||
|
||||
std::bit_cast<std::uintptr_t>(ptr) + size >
|
||||
kHeapBaseAddress + kHeapSize) {
|
||||
std::fprintf(stderr, "kfree: invalid address");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
if (kDebugHeap > 0) {
|
||||
if (std::memcmp(std::bit_cast<std::byte *>(ptr) + size, &g_allocProtWord,
|
||||
sizeof(g_allocProtWord)) != 0) {
|
||||
std::fprintf(stderr, "kernel heap corruption\n");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
std::memset(ptr, 0xcc, size + sizeof(g_allocProtWord));
|
||||
}
|
||||
|
||||
// std::fprintf(stderr, "kfree: release %p-%p, size = %lx\n", ptr,
|
||||
// (char *)ptr + size, size);
|
||||
|
||||
std::lock_guard lock(m_heap_map_mtx);
|
||||
if (!m_used_node.empty()) {
|
||||
auto node = m_used_node.extract(m_used_node.begin());
|
||||
node.key() = size;
|
||||
node.mapped() = ptr;
|
||||
m_free_heap.insert(std::move(node));
|
||||
} else {
|
||||
m_free_heap.emplace(size, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void kfree(void *ptr, std::size_t size) {
|
||||
return sMemoryResource->kfree(ptr, size);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "orbis/KernelContext.hpp"
|
||||
#include "KernelObject.hpp"
|
||||
#include "orbis/thread/Process.hpp"
|
||||
#include "orbis/thread/ProcessOps.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
|
|
@ -13,37 +14,10 @@
|
|||
#include <unistd.h>
|
||||
#include <utility>
|
||||
|
||||
static const std::uint64_t g_allocProtWord = 0xDEADBEAFBADCAFE1;
|
||||
static constexpr std::uintptr_t kHeapBaseAddress = 0x00000600'0000'0000;
|
||||
static constexpr auto kHeapSize = 0x1'0000'0000;
|
||||
static constexpr int kDebugHeap = 0;
|
||||
|
||||
namespace orbis {
|
||||
GlobalObjectRef<KernelContext> g_context = createGlobalObject<KernelContext>();
|
||||
thread_local Thread *g_currentThread;
|
||||
|
||||
KernelContext &g_context = *[]() -> KernelContext * {
|
||||
// Allocate global shared kernel memory
|
||||
// TODO: randomize for hardening and reduce size
|
||||
auto ptr = mmap(std::bit_cast<void *>(kHeapBaseAddress), kHeapSize,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (ptr == MAP_FAILED) {
|
||||
perror("mmap failed");
|
||||
FILE *maps = fopen("/proc/self/maps", "r");
|
||||
char *line = nullptr;
|
||||
std::size_t size = 0;
|
||||
while (getline(&line, &size, maps) > 0) {
|
||||
std::printf("%s", line);
|
||||
}
|
||||
|
||||
free(line);
|
||||
fclose(maps);
|
||||
std::abort();
|
||||
}
|
||||
|
||||
return new (ptr) KernelContext;
|
||||
}();
|
||||
|
||||
KernelContext::KernelContext() {
|
||||
// std::printf("orbis::KernelContext initialized, addr=%p\n", this);
|
||||
// std::printf("TSC frequency: %lu\n", getTscFreq());
|
||||
|
|
@ -158,138 +132,6 @@ long KernelContext::getTscFreq() {
|
|||
return m_tsc_freq.load();
|
||||
}
|
||||
|
||||
void *KernelContext::kalloc(std::size_t size, std::size_t align) {
|
||||
size = (size + (__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1)) &
|
||||
~(__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1);
|
||||
if (!size)
|
||||
std::abort();
|
||||
|
||||
if (m_heap_map_mtx.try_lock()) {
|
||||
std::lock_guard lock(m_heap_map_mtx, std::adopt_lock);
|
||||
|
||||
// Try to reuse previously freed block
|
||||
for (auto [it, end] = m_free_heap.equal_range(size); it != end; ++it) {
|
||||
auto result = it->second;
|
||||
if (!(std::bit_cast<std::uintptr_t>(result) & (align - 1))) {
|
||||
auto node = m_free_heap.extract(it);
|
||||
node.key() = 0;
|
||||
node.mapped() = nullptr;
|
||||
m_used_node.insert(m_used_node.begin(), std::move(node));
|
||||
|
||||
// std::fprintf(stderr, "kalloc: reuse %p-%p, size = %lx\n", result,
|
||||
// (char *)result + size, size);
|
||||
|
||||
if (kDebugHeap > 0) {
|
||||
std::memcpy(std::bit_cast<std::byte *>(result) + size,
|
||||
&g_allocProtWord, sizeof(g_allocProtWord));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard lock(m_heap_mtx);
|
||||
align = std::max<std::size_t>(align, __STDCPP_DEFAULT_NEW_ALIGNMENT__);
|
||||
auto heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
|
||||
heap = (heap + (align - 1)) & ~(align - 1);
|
||||
|
||||
if (kDebugHeap > 1) {
|
||||
if (auto diff = (heap + size + sizeof(g_allocProtWord)) % 4096; diff != 0) {
|
||||
heap += 4096 - diff;
|
||||
heap &= ~(align - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (heap + size > kHeapBaseAddress + kHeapSize) {
|
||||
std::fprintf(stderr, "out of kernel memory");
|
||||
std::abort();
|
||||
}
|
||||
// Check overflow
|
||||
if (heap + size < heap) {
|
||||
std::fprintf(stderr, "too big allocation");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
// std::fprintf(stderr, "kalloc: allocate %lx-%lx, size = %lx, align=%lx\n",
|
||||
// heap, heap + size, size, align);
|
||||
|
||||
auto result = reinterpret_cast<void *>(heap);
|
||||
if (kDebugHeap > 0) {
|
||||
std::memcpy(std::bit_cast<std::byte *>(result) + size, &g_allocProtWord,
|
||||
sizeof(g_allocProtWord));
|
||||
}
|
||||
|
||||
if (kDebugHeap > 0) {
|
||||
m_heap_next =
|
||||
reinterpret_cast<void *>(heap + size + sizeof(g_allocProtWord));
|
||||
} else {
|
||||
m_heap_next = reinterpret_cast<void *>(heap + size);
|
||||
}
|
||||
|
||||
if (kDebugHeap > 1) {
|
||||
heap = reinterpret_cast<std::uintptr_t>(m_heap_next);
|
||||
align = std::min<std::size_t>(align, 4096);
|
||||
heap = (heap + (align - 1)) & ~(align - 1);
|
||||
size = 4096;
|
||||
// std::fprintf(stderr, "kalloc: protect %lx-%lx, size = %lx, align=%lx\n",
|
||||
// heap, heap + size, size, align);
|
||||
|
||||
auto result = ::mmap(reinterpret_cast<void *>(heap), size, PROT_NONE,
|
||||
MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, -1, 0);
|
||||
if (result == MAP_FAILED) {
|
||||
std::fprintf(stderr, "failed to protect memory");
|
||||
std::abort();
|
||||
}
|
||||
m_heap_next = reinterpret_cast<void *>(heap + size);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void KernelContext::kfree(void *ptr, std::size_t size) {
|
||||
size = (size + (__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1)) &
|
||||
~(__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1);
|
||||
if (!size)
|
||||
std::abort();
|
||||
|
||||
if (std::bit_cast<std::uintptr_t>(ptr) < kHeapBaseAddress ||
|
||||
std::bit_cast<std::uintptr_t>(ptr) + size >
|
||||
kHeapBaseAddress + kHeapSize) {
|
||||
std::fprintf(stderr, "kfree: invalid address");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
if (kDebugHeap > 0) {
|
||||
if (std::memcmp(std::bit_cast<std::byte *>(ptr) + size, &g_allocProtWord,
|
||||
sizeof(g_allocProtWord)) != 0) {
|
||||
std::fprintf(stderr, "kernel heap corruption\n");
|
||||
std::abort();
|
||||
}
|
||||
|
||||
std::memset(ptr, 0xcc, size + sizeof(g_allocProtWord));
|
||||
}
|
||||
|
||||
// std::fprintf(stderr, "kfree: release %p-%p, size = %lx\n", ptr,
|
||||
// (char *)ptr + size, size);
|
||||
|
||||
std::lock_guard lock(m_heap_map_mtx);
|
||||
if (!m_used_node.empty()) {
|
||||
auto node = m_used_node.extract(m_used_node.begin());
|
||||
node.key() = size;
|
||||
node.mapped() = ptr;
|
||||
m_free_heap.insert(std::move(node));
|
||||
} else {
|
||||
m_free_heap.emplace(size, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
inline namespace utils {
|
||||
void kfree(void *ptr, std::size_t size) { return g_context.kfree(ptr, size); }
|
||||
void *kalloc(std::size_t size, std::size_t align) {
|
||||
return g_context.kalloc(size, align);
|
||||
}
|
||||
} // namespace utils
|
||||
|
||||
inline namespace logs {
|
||||
template <>
|
||||
void log_class_string<kstring>::format(std::string &out, const void *arg) {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ orbis::ErrorCode orbis::ipmiCreateServer(Process *proc, void *serverImpl,
|
|||
const char *name,
|
||||
const IpmiCreateServerConfig &config,
|
||||
rx::Ref<IpmiServer> &result) {
|
||||
auto [server, errorCode] = g_context.createIpmiServer(name);
|
||||
auto [server, errorCode] = g_context->createIpmiServer(name);
|
||||
ORBIS_RET_ON_ERROR(errorCode);
|
||||
|
||||
server->serverImpl = serverImpl;
|
||||
|
|
@ -44,9 +44,9 @@ orbis::ErrorCode orbis::ipmiCreateServer(Process *proc, void *serverImpl,
|
|||
orbis::ErrorCode orbis::ipmiCreateSession(Thread *thread, void *sessionImpl,
|
||||
ptr<void> userData,
|
||||
rx::Ref<IpmiSession> &result) {
|
||||
std::unique_lock ipmiMapLock(g_context.ipmiMap.mutex);
|
||||
std::unique_lock ipmiMapLock(g_context->ipmiMap.mutex);
|
||||
|
||||
for (auto [kid, obj] : g_context.ipmiMap) {
|
||||
for (auto [kid, obj] : g_context->ipmiMap) {
|
||||
auto server = dynamic_cast<IpmiServer *>(obj);
|
||||
if (server == nullptr) {
|
||||
continue;
|
||||
|
|
@ -104,7 +104,7 @@ orbis::SysResult orbis::sysIpmiCreateClient(Thread *thread, ptr<uint> result,
|
|||
ORBIS_RET_ON_ERROR(ipmiCreateClient(thread->tproc, _params.clientImpl, _name,
|
||||
_config, client));
|
||||
|
||||
auto kid = g_context.ipmiMap.insert(std::move(client));
|
||||
auto kid = g_context->ipmiMap.insert(std::move(client));
|
||||
|
||||
if (kid == -1) {
|
||||
return ErrorCode::MFILE;
|
||||
|
|
@ -139,7 +139,7 @@ orbis::SysResult orbis::sysIpmiCreateServer(Thread *thread, ptr<uint> result,
|
|||
ORBIS_RET_ON_ERROR(ureadString(_name, sizeof(_name), _params.name));
|
||||
ORBIS_RET_ON_ERROR(ipmiCreateServer(thread->tproc, _params.serverImpl, _name,
|
||||
_config, server));
|
||||
auto kid = g_context.ipmiMap.insert(std::move(server));
|
||||
auto kid = g_context->ipmiMap.insert(std::move(server));
|
||||
|
||||
if (kid == -1) {
|
||||
return ErrorCode::MFILE;
|
||||
|
|
@ -184,7 +184,7 @@ orbis::SysResult orbis::sysIpmiCreateSession(Thread *thread, ptr<uint> result,
|
|||
ORBIS_RET_ON_ERROR(
|
||||
ipmiCreateSession(thread, _params.sessionImpl, _userData.data, session));
|
||||
|
||||
auto kid = g_context.ipmiMap.insert(std::move(session));
|
||||
auto kid = g_context->ipmiMap.insert(std::move(session));
|
||||
|
||||
if (kid == -1) {
|
||||
return ErrorCode::MFILE;
|
||||
|
|
@ -233,7 +233,7 @@ orbis::SysResult orbis::sysIpmiServerReceivePacket(Thread *thread,
|
|||
ORBIS_RET_ON_ERROR(
|
||||
uread(_params, ptr<IpmiServerReceivePacketParams>(params)));
|
||||
|
||||
auto server = g_context.ipmiMap.get(kid).cast<IpmiServer>();
|
||||
auto server = g_context->ipmiMap.get(kid).cast<IpmiServer>();
|
||||
|
||||
if (server == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -301,7 +301,7 @@ orbis::SysResult orbis::sysIpmiSendConnectResult(Thread *thread,
|
|||
|
||||
ORBIS_LOG_NOTICE(__FUNCTION__, kid);
|
||||
|
||||
auto ipmiObject = g_context.ipmiMap.get(kid);
|
||||
auto ipmiObject = g_context->ipmiMap.get(kid);
|
||||
if (ipmiObject == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
|
@ -352,7 +352,7 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
|
||||
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -422,7 +422,7 @@ orbis::SysResult orbis::sysIpmiClientInvokeAsyncMethod(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
|
||||
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -513,7 +513,7 @@ orbis::SysResult orbis::sysImpiSessionRespondAsync(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
|
||||
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -572,7 +572,7 @@ orbis::SysResult orbis::sysIpmiClientTryGetResult(Thread *thread,
|
|||
IpmiTryGetResultParams _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, (ptr<IpmiTryGetResultParams>)params));
|
||||
|
||||
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
|
||||
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -649,7 +649,7 @@ orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
|
||||
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -750,7 +750,7 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
|
||||
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -804,7 +804,7 @@ orbis::SysResult orbis::sysIpmiSessionTrySendMessage(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
|
||||
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -847,7 +847,7 @@ orbis::SysResult orbis::sysIpmiClientDisconnect(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
|
||||
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -873,7 +873,7 @@ orbis::SysResult orbis::sysIpmiSessionGetClientPid(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
|
||||
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -900,7 +900,7 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
|
||||
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -1040,7 +1040,7 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
|
||||
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -1053,7 +1053,7 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
|
|||
IpmiClientConnectParams _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiClientConnectParams>(params)));
|
||||
|
||||
auto server = g_context.findIpmiServer(client->name);
|
||||
auto server = g_context->findIpmiServer(client->name);
|
||||
|
||||
if (server == nullptr) {
|
||||
return SysResult::notAnError(ErrorCode::NOENT);
|
||||
|
|
@ -1173,7 +1173,7 @@ orbis::SysResult orbis::sysIpmiSessionGetClientAppId(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
|
||||
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -1198,7 +1198,7 @@ orbis::SysResult orbis::sysIpmiSessionGetUserData(Thread *thread,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
|
||||
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -1221,7 +1221,7 @@ orbis::SysResult orbis::sysIpmiServerGetName(Thread *thread, ptr<uint> result,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto server = g_context.ipmiMap.get(kid).cast<IpmiServer>();
|
||||
auto server = g_context->ipmiMap.get(kid).cast<IpmiServer>();
|
||||
|
||||
if (server == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -1246,7 +1246,7 @@ orbis::SysResult orbis::sysIpmiClientGetName(Thread *thread, ptr<uint> result,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
|
||||
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -1283,7 +1283,7 @@ orbis::SysResult orbis::sysIpmiClientWaitEventFlag(Thread *thread,
|
|||
IpmiWaitEventFlagParam _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiWaitEventFlagParam>(params)));
|
||||
|
||||
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
|
||||
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -1344,7 +1344,7 @@ orbis::SysResult orbis::sysIpmiClientPollEventFlag(Thread *thread,
|
|||
IpmiPollEventFlagParam _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiPollEventFlagParam>(params)));
|
||||
|
||||
auto client = g_context.ipmiMap.get(kid).cast<IpmiClient>();
|
||||
auto client = g_context->ipmiMap.get(kid).cast<IpmiClient>();
|
||||
|
||||
if (client == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
@ -1384,7 +1384,7 @@ orbis::SysResult orbis::sysIpmiSessionSetEventFlag(Thread *thread,
|
|||
IpmiSetEventFlagParam _params;
|
||||
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiSetEventFlagParam>(params)));
|
||||
|
||||
auto session = g_context.ipmiMap.get(kid).cast<IpmiSession>();
|
||||
auto session = g_context->ipmiMap.get(kid).cast<IpmiSession>();
|
||||
|
||||
if (session == nullptr) {
|
||||
return ErrorCode::INVAL;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ orbis::SysResult orbis::sys_cpuset_getaffinity(Thread *thread, cpulevel_t level,
|
|||
if (id == ~id_t(0) || id == thread->tproc->pid) {
|
||||
whichProcess = thread->tproc;
|
||||
} else {
|
||||
whichProcess = g_context.findProcessById(id);
|
||||
whichProcess = g_context->findProcessById(id);
|
||||
|
||||
if (whichProcess == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
|
|
@ -163,7 +163,7 @@ orbis::SysResult orbis::sys_cpuset_setaffinity(Thread *thread, cpulevel_t level,
|
|||
} else {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, "process not found", level, which, id,
|
||||
cpusetsize);
|
||||
whichProcess = g_context.findProcessById(id);
|
||||
whichProcess = g_context->findProcessById(id);
|
||||
|
||||
if (whichProcess == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
|
|||
nodeIt = kq->notes.begin();
|
||||
|
||||
if (change.filter == kEvFiltProc) {
|
||||
auto process = g_context.findProcessById(change.ident);
|
||||
auto process = g_context->findProcessById(change.ident);
|
||||
if (process == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
|
|
@ -124,7 +124,7 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
|
|||
}
|
||||
} else if (change.filter == kEvFiltGraphicsCore ||
|
||||
change.filter == kEvFiltDisplay) {
|
||||
g_context.deviceEventEmitter->subscribe(&*nodeIt);
|
||||
g_context->deviceEventEmitter->subscribe(&*nodeIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -185,7 +185,7 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
|
|||
nodeIt->event.data |= 1000ull << 16; // clock
|
||||
|
||||
kq->cv.notify_all(kq->mtx);
|
||||
} else if (g_context.fwType == FwType::Ps5 &&
|
||||
} else if (g_context->fwType == FwType::Ps5 &&
|
||||
change.filter == kEvFiltGraphicsCore && change.ident == 0) {
|
||||
nodeIt->triggered = true;
|
||||
kq->cv.notify_all(kq->mtx);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ orbis::SysResult orbis::sys_wait4(Thread *thread, sint pid, ptr<sint> status,
|
|||
|
||||
int hostPid = pid;
|
||||
if (pid > 0) {
|
||||
auto process = g_context.findProcessById(pid);
|
||||
auto process = g_context->findProcessById(pid);
|
||||
if (process == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ orbis::SysResult orbis::sys_wait4(Thread *thread, sint pid, ptr<sint> status,
|
|||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, pid, status, options, rusage, result, stat);
|
||||
|
||||
auto process = g_context.findProcessByHostId(result);
|
||||
auto process = g_context->findProcessByHostId(result);
|
||||
if (process == nullptr) {
|
||||
ORBIS_LOG_ERROR("host process not found", result);
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
|
|||
// ORBIS_LOG_ERROR(__FUNCTION__, op, id, len);
|
||||
// thread->where();
|
||||
|
||||
std::lock_guard lock(orbis::g_context.regMgrMtx);
|
||||
std::lock_guard lock(orbis::g_context->regMgrMtx);
|
||||
|
||||
if (op == 1) {
|
||||
// set int
|
||||
|
|
@ -89,7 +89,7 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
|
|||
}
|
||||
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, op, id, *(std::uint32_t *)value);
|
||||
g_context.regMgrInt[id] = *(std::uint32_t *)value;
|
||||
g_context->regMgrInt[id] = *(std::uint32_t *)value;
|
||||
return {};
|
||||
}
|
||||
if (op == 2) {
|
||||
|
|
@ -98,8 +98,8 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto intValIt = g_context.regMgrInt.find(id);
|
||||
if (intValIt == g_context.regMgrInt.end()) {
|
||||
auto intValIt = g_context->regMgrInt.find(id);
|
||||
if (intValIt == g_context->regMgrInt.end()) {
|
||||
ORBIS_LOG_ERROR("registry int entry not exists", op, id, len);
|
||||
thread->where();
|
||||
// return ErrorCode::NOENT;
|
||||
|
|
@ -774,7 +774,7 @@ orbis::SysResult orbis::sys_budget_create(Thread *thread, ptr<char> name,
|
|||
BudgetInfo _resources[kMaxBudgets];
|
||||
ORBIS_RET_ON_ERROR(uread(_resources, resources, count));
|
||||
|
||||
auto processTypeBudget = g_context.getProcessTypeBudget(processType);
|
||||
auto processTypeBudget = g_context->getProcessTypeBudget(processType);
|
||||
int invalidResourceCount = 0;
|
||||
|
||||
for (auto &resource : std::span(_resources, count)) {
|
||||
|
|
@ -804,7 +804,7 @@ orbis::SysResult orbis::sys_budget_create(Thread *thread, ptr<char> name,
|
|||
|
||||
rx::Ref budget =
|
||||
orbis::knew<Budget>(_name, processType, std::span(_resources, count));
|
||||
auto id = g_context.budgets.insert(budget);
|
||||
auto id = g_context->budgets.insert(budget);
|
||||
thread->retval[0] = id;
|
||||
return {};
|
||||
}
|
||||
|
|
@ -845,9 +845,9 @@ orbis::SysResult orbis::sys_budget_get(Thread *thread, sint id,
|
|||
}
|
||||
|
||||
budget =
|
||||
g_context.getProcessTypeBudget(static_cast<Budget::ProcessType>(id));
|
||||
g_context->getProcessTypeBudget(static_cast<Budget::ProcessType>(id));
|
||||
} else {
|
||||
budget = g_context.budgets.get(id);
|
||||
budget = g_context->budgets.get(id);
|
||||
|
||||
if (!budget) {
|
||||
return ErrorCode::SRCH;
|
||||
|
|
@ -873,7 +873,7 @@ orbis::SysResult orbis::sys_budget_set(Thread *thread, sint budgetId) {
|
|||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
auto budget = g_context.budgets.get(budgetId);
|
||||
auto budget = g_context->budgets.get(budgetId);
|
||||
if (!budget) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
|
|
@ -940,7 +940,7 @@ orbis::SysResult orbis::sys_dmem_container(Thread *thread, uint id) {
|
|||
orbis::SysResult orbis::sys_get_authinfo(Thread *thread, pid_t pid,
|
||||
ptr<AuthInfo> info) {
|
||||
|
||||
auto process = pid > 0 ? g_context.findProcessById(pid) : thread->tproc;
|
||||
auto process = pid > 0 ? g_context->findProcessById(pid) : thread->tproc;
|
||||
if (process == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
|
|
@ -1188,7 +1188,7 @@ orbis::SysResult orbis::sys_randomized_path(Thread *thread, sint type,
|
|||
}
|
||||
orbis::SysResult orbis::sys_rdup(Thread *thread, sint pid, sint fd) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, pid, fd);
|
||||
for (auto it = g_context.getProcessList(); it != nullptr; it = it->next) {
|
||||
for (auto it = g_context->getProcessList(); it != nullptr; it = it->next) {
|
||||
auto &p = it->object;
|
||||
if (p.pid != pid) {
|
||||
continue;
|
||||
|
|
@ -1297,7 +1297,7 @@ orbis::SysResult orbis::sys_budget_get_ptype(Thread *thread, sint pid) {
|
|||
if (pid < 0 || pid == thread->tproc->pid) {
|
||||
process = thread->tproc;
|
||||
} else {
|
||||
process = g_context.findProcessById(pid);
|
||||
process = g_context->findProcessById(pid);
|
||||
|
||||
if (!process) {
|
||||
return ErrorCode::SRCH;
|
||||
|
|
@ -1344,7 +1344,7 @@ orbis::SysResult orbis::sys_thr_get_name(Thread *thread, lwpid_t lwpid,
|
|||
searchThread = thread->tproc->threadsMap.get(lwpid - thread->tproc->pid);
|
||||
|
||||
if (searchThread == nullptr) {
|
||||
if (auto process = g_context.findProcessById(lwpid)) {
|
||||
if (auto process = g_context->findProcessById(lwpid)) {
|
||||
searchThread = process->threadsMap.get(lwpid - process->pid);
|
||||
}
|
||||
}
|
||||
|
|
@ -1446,7 +1446,7 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
|
|||
return sysIpmiSessionSetEventFlag(thread, result, kid, params, paramsSz);
|
||||
}
|
||||
|
||||
if (auto ipmi = g_context.ipmiMap.get(kid)) {
|
||||
if (auto ipmi = g_context->ipmiMap.get(kid)) {
|
||||
if (auto client = ipmi.cast<IpmiClient>()) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, thread->tid, op, client->name, result,
|
||||
params, paramsSz);
|
||||
|
|
@ -1652,7 +1652,7 @@ orbis::sys_get_kernel_mem_statistics(Thread *thread /* TODO */) {
|
|||
orbis::SysResult orbis::sys_get_sdk_compiled_version(Thread *thread,
|
||||
ptr<const char> path) {
|
||||
ORBIS_LOG_ERROR(__FUNCTION__, path);
|
||||
thread->retval[0] = g_context.sdkVersion;
|
||||
thread->retval[0] = g_context->sdkVersion;
|
||||
return {};
|
||||
}
|
||||
orbis::SysResult orbis::sys_app_state_change(Thread *thread, sint state) {
|
||||
|
|
@ -1680,7 +1680,7 @@ orbis::SysResult orbis::sys_budget_get_ptype_of_budget(Thread *thread,
|
|||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
rx::Ref<Budget> budget = g_context.budgets.get(budgetId);
|
||||
rx::Ref<Budget> budget = g_context->budgets.get(budgetId);
|
||||
|
||||
if (!budget) {
|
||||
return ErrorCode::SRCH;
|
||||
|
|
@ -1877,10 +1877,10 @@ orbis::SysResult orbis::sys_begin_app_mount(Thread *thread,
|
|||
rx::Ref appInfo = orbis::knew<RcAppInfo>();
|
||||
|
||||
AppInfoEx *appInfoData = appInfo.get();
|
||||
auto handle = g_context.appInfos.insert(appInfo);
|
||||
auto handle = g_context->appInfos.insert(appInfo);
|
||||
ORBIS_LOG_TODO(__FUNCTION__, handle);
|
||||
thread->where();
|
||||
if (handle == decltype(g_context.appInfos)::npos) {
|
||||
if (handle == decltype(g_context->appInfos)::npos) {
|
||||
return ErrorCode::DOOFUS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ orbis::SysResult orbis::sys_kill(Thread *thread, sint pid, sint signum) {
|
|||
|
||||
int hostPid = pid;
|
||||
if (pid > 0) {
|
||||
auto process = g_context.findProcessById(pid);
|
||||
auto process = g_context->findProcessById(pid);
|
||||
if (process == nullptr) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
// 4.17.0.0.3.0
|
||||
if (name[0] == net && name[1] == 17 && name[2] == 0 && name[3] == 0 &&
|
||||
name[4] == 3 && name[5] == 0) {
|
||||
if (g_context.fwSdkVersion == 0) {
|
||||
if (g_context->fwSdkVersion == 0) {
|
||||
// proto fw
|
||||
return {};
|
||||
}
|
||||
|
|
@ -197,7 +197,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto budget = g_context.budgets.get(thread->tproc->budgetId);
|
||||
auto budget = g_context->budgets.get(thread->tproc->budgetId);
|
||||
auto fmem = budget->get(BudgetResource::Fmem);
|
||||
*(uint64_t *)old = fmem.total;
|
||||
return {};
|
||||
|
|
@ -208,7 +208,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
auto budget = g_context.budgets.get(thread->tproc->budgetId);
|
||||
auto budget = g_context->budgets.get(thread->tproc->budgetId);
|
||||
auto fmem = budget->get(BudgetResource::Fmem);
|
||||
|
||||
auto result = (uint64_t *)old;
|
||||
|
|
@ -225,7 +225,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
ORBIS_LOG_ERROR("KERN_PROC_PROC 2");
|
||||
|
||||
if (namelen >= 4) {
|
||||
auto process = g_context.findProcessById(name[3]);
|
||||
auto process = g_context->findProcessById(name[3]);
|
||||
if (process == nullptr || process->exitStatus.has_value()) {
|
||||
return ErrorCode::SRCH;
|
||||
}
|
||||
|
|
@ -245,7 +245,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
}
|
||||
|
||||
if (name[0] == kern && name[1] == proc && name[2] == 55) {
|
||||
if (g_context.fwType != FwType::Ps5) {
|
||||
if (g_context->fwType != FwType::Ps5) {
|
||||
return orbis::ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
|
|
@ -259,7 +259,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
if (name[0] == kern && name[1] == proc && name[2] == 36) {
|
||||
Process *process = thread->tproc;
|
||||
if (process->pid != name[3]) {
|
||||
process = g_context.findProcessById(name[3]);
|
||||
process = g_context->findProcessById(name[3]);
|
||||
if (process == nullptr) {
|
||||
ORBIS_LOG_ERROR("get sdk version by pid: process not found", name[3],
|
||||
thread->tproc->pid);
|
||||
|
|
@ -276,7 +276,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
|
||||
auto sdkVersion = process->sdkVersion;
|
||||
if (sdkVersion == 0) {
|
||||
sdkVersion = g_context.fwSdkVersion;
|
||||
sdkVersion = g_context->fwSdkVersion;
|
||||
}
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwrite(ptr<uint32_t>(old), sdkVersion));
|
||||
|
|
@ -290,7 +290,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
// 1 - 14 - 35 - pid
|
||||
Process *process = thread->tproc;
|
||||
if (process->pid != name[3] && name[3] != -1) {
|
||||
process = g_context.findProcessById(name[3]);
|
||||
process = g_context->findProcessById(name[3]);
|
||||
if (process == nullptr) {
|
||||
ORBIS_LOG_ERROR("appinfo process not found", name[3],
|
||||
thread->tproc->pid);
|
||||
|
|
@ -384,7 +384,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
}
|
||||
|
||||
if (name[0] == kern && name[1] == proc && name[2] == 64) {
|
||||
auto appInfo = g_context.appInfos.get(name[3]);
|
||||
auto appInfo = g_context->appInfos.get(name[3]);
|
||||
if (appInfo == nullptr) {
|
||||
return ErrorCode::SRCH; // ?
|
||||
}
|
||||
|
|
@ -418,7 +418,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
if (name[0] == 1 && name[1] == proc && name[2] == 65) {
|
||||
// AppInfo by appId get/set
|
||||
// 1 - 14 - 65 - appId
|
||||
auto appInfo = g_context.appInfos.get(name[3]);
|
||||
auto appInfo = g_context->appInfos.get(name[3]);
|
||||
if (appInfo == nullptr) {
|
||||
ORBIS_LOG_ERROR("appinfo appId not found", name[3], thread->tproc->pid);
|
||||
return ErrorCode::SRCH;
|
||||
|
|
@ -461,7 +461,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
if (name[0] == kern && name[1] == proc && name[2] == 68) {
|
||||
Process *process = thread->tproc;
|
||||
if (process->pid != name[3]) {
|
||||
process = g_context.findProcessById(name[3]);
|
||||
process = g_context->findProcessById(name[3]);
|
||||
if (process == nullptr) {
|
||||
ORBIS_LOG_ERROR("get ps5 sdk version by pid: process not found",
|
||||
name[3], thread->tproc->pid);
|
||||
|
|
@ -478,7 +478,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
|
||||
auto sdkVersion = process->sdkVersion;
|
||||
if (sdkVersion == 0) {
|
||||
sdkVersion = g_context.fwSdkVersion;
|
||||
sdkVersion = g_context->fwSdkVersion;
|
||||
}
|
||||
|
||||
ORBIS_RET_ON_ERROR(uwrite(ptr<uint32_t>(old), sdkVersion));
|
||||
|
|
@ -699,7 +699,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
dest[count++] = budgets;
|
||||
dest[count++] = mlock_avail;
|
||||
} else if (searchName == "hw.sce_main_socid") {
|
||||
if (g_context.fwType != FwType::Ps5) {
|
||||
if (g_context->fwType != FwType::Ps5) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
|
|
@ -844,7 +844,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
*(std::uint32_t *)old = g_context.safeMode;
|
||||
*(std::uint32_t *)old = g_context->safeMode;
|
||||
}
|
||||
if (new_ != nullptr && newlen == 4) {
|
||||
ORBIS_LOG_ERROR("sysctl: set kern.init_safe_mode",
|
||||
|
|
@ -902,7 +902,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
return {};
|
||||
|
||||
case sysctl_hw::sce_main_socid:
|
||||
if (g_context.fwType != FwType::Ps5) {
|
||||
if (g_context->fwType != FwType::Ps5) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
||||
|
|
@ -933,13 +933,13 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
if (g_context.fwType != FwType::Ps5 &&
|
||||
if (g_context->fwType != FwType::Ps5 &&
|
||||
std::string_view((char *)thread->tproc->appInfo.titleId) ==
|
||||
"NPXS20973") {
|
||||
ORBIS_LOG_ERROR("get tsc freq: returning patched value");
|
||||
*(uint64_t *)old = 1000000;
|
||||
} else {
|
||||
*(uint64_t *)old = g_context.getTscFreq();
|
||||
*(uint64_t *)old = g_context->getTscFreq();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include "orbis/umtx.hpp"
|
||||
#include "GlobalKernelObject.hpp"
|
||||
#include "KernelObject.hpp"
|
||||
#include "error.hpp"
|
||||
#include "orbis-config.hpp"
|
||||
#include "orbis/thread.hpp"
|
||||
|
|
@ -25,7 +25,7 @@ struct UmtxCond {
|
|||
|
||||
struct UmtxChain {
|
||||
rx::shared_mutex mtx;
|
||||
using queue_type = utils::kmultimap<UmtxKey, UmtxCond>;
|
||||
using queue_type = kmultimap<UmtxKey, UmtxCond>;
|
||||
queue_type sleep_queue;
|
||||
queue_type spare_queue;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue