mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
orbis: remove process list from context & initial serialization support
modernize kenv add LockableKernelObject utility
This commit is contained in:
parent
f71e3410c1
commit
014012c219
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "rx/Rc.hpp"
|
#include "rx/Rc.hpp"
|
||||||
#include "rx/Serializer.hpp"
|
#include "rx/Serializer.hpp"
|
||||||
|
#include "rx/SharedMutex.hpp"
|
||||||
#include "rx/TypeId.hpp"
|
#include "rx/TypeId.hpp"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -44,6 +45,28 @@ struct KernelObject : KernelObjectBase, StateT {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <rx::Serializable StateT>
|
||||||
|
struct LockableKernelObject : KernelObjectBase, StateT {
|
||||||
|
mutable rx::shared_mutex mtx;
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
LockableKernelObject(Args &&...args)
|
||||||
|
: KernelObjectBase(rx::TypeId::get<StateT>()),
|
||||||
|
StateT(std::forward<Args>(args)...) {}
|
||||||
|
|
||||||
|
virtual void serialize(rx::Serializer &s) const {
|
||||||
|
std::lock_guard lock(*this);
|
||||||
|
s.serialize(static_cast<const StateT &>(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void deserialize(rx::Deserializer &s) {
|
||||||
|
s.deserialize(static_cast<StateT &>(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void lock() const { mtx.lock(); }
|
||||||
|
void unlock() const { mtx.unlock(); }
|
||||||
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct StaticObjectCtl {
|
struct StaticObjectCtl {
|
||||||
std::size_t offset = -1ull;
|
std::size_t offset = -1ull;
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,9 @@ add_library(obj.orbis-kernel OBJECT
|
||||||
src/sys/sys_vm_mmap.cpp
|
src/sys/sys_vm_mmap.cpp
|
||||||
src/sys/sys_vm_unix.cpp
|
src/sys/sys_vm_unix.cpp
|
||||||
|
|
||||||
|
src/thread/Process.cpp
|
||||||
|
src/thread/Thread.cpp
|
||||||
|
|
||||||
src/utils/Logs.cpp
|
src/utils/Logs.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,7 @@
|
||||||
#include "orbis/note.hpp"
|
#include "orbis/note.hpp"
|
||||||
#include "osem.hpp"
|
#include "osem.hpp"
|
||||||
#include "rx/IdMap.hpp"
|
#include "rx/IdMap.hpp"
|
||||||
#include "rx/LinkedNode.hpp"
|
|
||||||
#include "rx/SharedMutex.hpp"
|
#include "rx/SharedMutex.hpp"
|
||||||
#include "thread/types.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
@ -37,18 +35,6 @@ public:
|
||||||
KernelContext();
|
KernelContext();
|
||||||
~KernelContext();
|
~KernelContext();
|
||||||
|
|
||||||
Process *createProcess(pid_t pid);
|
|
||||||
void deleteProcess(Process *proc);
|
|
||||||
Process *findProcessById(pid_t pid) const;
|
|
||||||
Process *findProcessByHostId(std::uint64_t pid) const;
|
|
||||||
|
|
||||||
rx::LinkedNode<Process> *getProcessList() { return m_processes; }
|
|
||||||
|
|
||||||
long allocatePid() {
|
|
||||||
std::lock_guard lock(m_thread_id_mtx);
|
|
||||||
return m_thread_id_map.emplace(0).first;
|
|
||||||
}
|
|
||||||
|
|
||||||
long getTscFreq();
|
long getTscFreq();
|
||||||
|
|
||||||
std::pair<EventFlag *, bool> createEventFlag(kstring name, std::int32_t flags,
|
std::pair<EventFlag *, bool> createEventFlag(kstring name, std::int32_t flags,
|
||||||
|
|
@ -123,17 +109,15 @@ public:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<kmap<kstring, char[128]> &, std::unique_lock<rx::shared_mutex>>
|
std::tuple<kmap<kstring, rx::StaticString<128>> &, std::unique_lock<rx::shared_mutex>>
|
||||||
getKernelEnv() {
|
getKernelEnv() {
|
||||||
std::unique_lock lock(m_kenv_mtx);
|
std::unique_lock lock(m_kenv_mtx);
|
||||||
return {m_kenv, std::move(lock)};
|
return {m_kenv, std::move(lock)};
|
||||||
}
|
}
|
||||||
|
|
||||||
void setKernelEnv(std::string_view key, std::string_view value) {
|
void setKernelEnv(std::string_view key, std::string_view value) {
|
||||||
auto &kenvValue = m_kenv[kstring(key)];
|
std::unique_lock lock(m_kenv_mtx);
|
||||||
auto len = std::min(sizeof(kenvValue) - 1, value.size());
|
m_kenv[kstring(key)] = value;
|
||||||
std::memcpy(kenvValue, value.data(), len);
|
|
||||||
kenvValue[len] = '0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rx::Ref<EventEmitter> deviceEventEmitter;
|
rx::Ref<EventEmitter> deviceEventEmitter;
|
||||||
|
|
@ -177,11 +161,6 @@ public:
|
||||||
private:
|
private:
|
||||||
std::atomic<long> m_tsc_freq{0};
|
std::atomic<long> m_tsc_freq{0};
|
||||||
|
|
||||||
rx::shared_mutex m_thread_id_mtx;
|
|
||||||
rx::OwningIdMap<char, long, 256, 0> m_thread_id_map;
|
|
||||||
mutable rx::shared_mutex m_proc_mtx;
|
|
||||||
rx::LinkedNode<Process> *m_processes = nullptr;
|
|
||||||
|
|
||||||
rx::shared_mutex m_evf_mtx;
|
rx::shared_mutex m_evf_mtx;
|
||||||
kmap<kstring, rx::Ref<EventFlag>> m_event_flags;
|
kmap<kstring, rx::Ref<EventFlag>> m_event_flags;
|
||||||
|
|
||||||
|
|
@ -192,7 +171,7 @@ private:
|
||||||
kmap<kstring, rx::Ref<IpmiServer>> mIpmiServers;
|
kmap<kstring, rx::Ref<IpmiServer>> mIpmiServers;
|
||||||
|
|
||||||
rx::shared_mutex m_kenv_mtx;
|
rx::shared_mutex m_kenv_mtx;
|
||||||
kmap<kstring, char[128]> m_kenv; // max size: 127 + '\0'
|
kmap<kstring, rx::StaticString<128>> m_kenv; // max size: 127 + '\0'
|
||||||
};
|
};
|
||||||
|
|
||||||
extern GlobalObjectRef<KernelContext> g_context;
|
extern GlobalObjectRef<KernelContext> g_context;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ public:
|
||||||
explicit GlobalObjectRef(std::uint32_t offset) : mOffset(offset) {}
|
explicit GlobalObjectRef(std::uint32_t offset) : mOffset(offset) {}
|
||||||
T *get() { return reinterpret_cast<T *>(g_globalStorage + mOffset); }
|
T *get() { return reinterpret_cast<T *>(g_globalStorage + mOffset); }
|
||||||
T *operator->() { return get(); }
|
T *operator->() { return get(); }
|
||||||
|
T &operator*() { return *get(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <rx::Serializable StateT>
|
template <rx::Serializable StateT>
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ struct Process final {
|
||||||
kernel::StaticKernelObjectStorage<OrbisNamespace,
|
kernel::StaticKernelObjectStorage<OrbisNamespace,
|
||||||
kernel::detail::ProcessScope>;
|
kernel::detail::ProcessScope>;
|
||||||
|
|
||||||
|
~Process();
|
||||||
|
|
||||||
KernelContext *context = nullptr;
|
KernelContext *context = nullptr;
|
||||||
std::byte *storage = nullptr;
|
std::byte *storage = nullptr;
|
||||||
|
|
||||||
|
|
@ -97,7 +99,7 @@ struct Process final {
|
||||||
rx::RcIdMap<EventFlag, sint, 4097, 1> evfMap;
|
rx::RcIdMap<EventFlag, sint, 4097, 1> evfMap;
|
||||||
rx::RcIdMap<Semaphore, sint, 4097, 1> semMap;
|
rx::RcIdMap<Semaphore, sint, 4097, 1> semMap;
|
||||||
rx::RcIdMap<Module, ModuleHandle> modulesMap;
|
rx::RcIdMap<Module, ModuleHandle> modulesMap;
|
||||||
rx::OwningIdMap<Thread, lwpid_t> threadsMap;
|
rx::RcIdMap<Thread, lwpid_t> threadsMap;
|
||||||
rx::RcIdMap<orbis::File, sint> fileDescriptors;
|
rx::RcIdMap<orbis::File, sint> fileDescriptors;
|
||||||
|
|
||||||
// Named objects for debugging
|
// Named objects for debugging
|
||||||
|
|
@ -115,18 +117,8 @@ struct Process final {
|
||||||
void incRef() {}
|
void incRef() {}
|
||||||
void decRef() {}
|
void decRef() {}
|
||||||
|
|
||||||
void allocate() {
|
void serialize(rx::Serializer &) const;
|
||||||
if (auto size = Storage::GetSize()) {
|
void deserialize(rx::Deserializer &);
|
||||||
storage = (std::byte *)kalloc(size, Storage::GetAlignment());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocate() {
|
|
||||||
if (auto size = Storage::GetSize()) {
|
|
||||||
kfree(storage, size);
|
|
||||||
storage = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <rx::Serializable T>
|
template <rx::Serializable T>
|
||||||
T *get(
|
T *get(
|
||||||
|
|
@ -135,4 +127,10 @@ struct Process final {
|
||||||
return ref.get(storage);
|
return ref.get(storage);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pid_t allocatePid();
|
||||||
|
Process *createProcess(Process *parentProcess = nullptr, pid_t pid = -1);
|
||||||
|
void deleteProcess(Process *proc);
|
||||||
|
Process *findProcessById(pid_t pid);
|
||||||
|
Process *findProcessByHostId(std::uint64_t pid);
|
||||||
} // namespace orbis
|
} // namespace orbis
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "cpuset.hpp"
|
#include "cpuset.hpp"
|
||||||
#include "orbis-config.hpp"
|
#include "orbis-config.hpp"
|
||||||
#include "rx/Serializer.hpp"
|
#include "rx/Serializer.hpp"
|
||||||
|
#include "rx/StaticString.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
|
|
||||||
#include "../KernelAllocator.hpp"
|
#include "../KernelAllocator.hpp"
|
||||||
|
|
@ -23,6 +24,8 @@ struct Thread final {
|
||||||
kernel::StaticKernelObjectStorage<OrbisNamespace,
|
kernel::StaticKernelObjectStorage<OrbisNamespace,
|
||||||
kernel::detail::ThreadScope>;
|
kernel::detail::ThreadScope>;
|
||||||
|
|
||||||
|
~Thread();
|
||||||
|
|
||||||
rx::shared_mutex mtx;
|
rx::shared_mutex mtx;
|
||||||
Process *tproc = nullptr;
|
Process *tproc = nullptr;
|
||||||
std::byte *storage = nullptr;
|
std::byte *storage = nullptr;
|
||||||
|
|
@ -33,7 +36,7 @@ struct Thread final {
|
||||||
ptr<void> stackEnd;
|
ptr<void> stackEnd;
|
||||||
uint64_t fsBase{};
|
uint64_t fsBase{};
|
||||||
uint64_t gsBase{};
|
uint64_t gsBase{};
|
||||||
char name[32]{};
|
rx::StaticString<32> name;
|
||||||
|
|
||||||
cpuset affinity{~0u};
|
cpuset affinity{~0u};
|
||||||
SigSet sigMask = {0x7fff'ffff, ~0u, ~0u, ~0u};
|
SigSet sigMask = {0x7fff'ffff, ~0u, ~0u, ~0u};
|
||||||
|
|
@ -82,19 +85,6 @@ struct Thread final {
|
||||||
void notifyUnblockedSignal(int signo);
|
void notifyUnblockedSignal(int signo);
|
||||||
void setSigMask(SigSet newSigMask);
|
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>
|
template <rx::Serializable T>
|
||||||
T *get(kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ThreadScope, T>
|
T *get(kernel::StaticObjectRef<OrbisNamespace, kernel::detail::ThreadScope, T>
|
||||||
ref) {
|
ref) {
|
||||||
|
|
@ -106,6 +96,8 @@ struct Thread final {
|
||||||
void decRef() {}
|
void decRef() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Thread *createThread(Process *process, std::string_view name);
|
||||||
|
|
||||||
extern thread_local Thread *g_currentThread;
|
extern thread_local Thread *g_currentThread;
|
||||||
|
|
||||||
struct scoped_unblock {
|
struct scoped_unblock {
|
||||||
|
|
|
||||||
|
|
@ -24,71 +24,6 @@ KernelContext::KernelContext() {
|
||||||
}
|
}
|
||||||
KernelContext::~KernelContext() {}
|
KernelContext::~KernelContext() {}
|
||||||
|
|
||||||
Process *KernelContext::createProcess(pid_t pid) {
|
|
||||||
auto newProcess = knew<rx::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return &newProcess->object;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KernelContext::deleteProcess(Process *proc) {
|
|
||||||
auto procNode = reinterpret_cast<rx::LinkedNode<Process> *>(proc);
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard lock(m_proc_mtx);
|
|
||||||
auto next = procNode->erase();
|
|
||||||
|
|
||||||
if (procNode == m_processes) {
|
|
||||||
m_processes = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kdelete(procNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Process *KernelContext::findProcessById(pid_t pid) const {
|
|
||||||
for (std::size_t i = 0; i < 20; ++i) {
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(50));
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Process *KernelContext::findProcessByHostId(std::uint64_t pid) const {
|
|
||||||
for (std::size_t i = 0; i < 20; ++i) {
|
|
||||||
{
|
|
||||||
std::lock_guard lock(m_proc_mtx);
|
|
||||||
for (auto proc = m_processes; proc != nullptr; proc = proc->next) {
|
|
||||||
if (proc->object.hostPid == pid) {
|
|
||||||
return &proc->object;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(50));
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
long KernelContext::getTscFreq() {
|
long KernelContext::getTscFreq() {
|
||||||
auto cal_tsc = []() -> long {
|
auto cal_tsc = []() -> long {
|
||||||
const long timer_freq = 1'000'000'000;
|
const long timer_freq = 1'000'000'000;
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
|
||||||
while (true) {
|
while (true) {
|
||||||
if (pipe->data.empty()) {
|
if (pipe->data.empty()) {
|
||||||
// pipe->cv.wait(file->mtx);
|
// pipe->cv.wait(file->mtx);
|
||||||
// ORBIS_LOG_ERROR(__FUNCTION__, "wakeup", thread->name, thread->tid,
|
// ORBIS_LOG_ERROR(__FUNCTION__, "wakeup", thread->name.c_str(),
|
||||||
// file); continue;
|
// thread->tid, file); continue;
|
||||||
return orbis::ErrorCode::WOULDBLOCK;
|
return orbis::ErrorCode::WOULDBLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,8 +32,8 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
|
||||||
uio->offset += size;
|
uio->offset += size;
|
||||||
std::memcpy(vec.base, pipe->data.data(), size);
|
std::memcpy(vec.base, pipe->data.data(), size);
|
||||||
|
|
||||||
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file, size,
|
ORBIS_LOG_ERROR(__FUNCTION__, thread->name.c_str(), thread->tid, file,
|
||||||
pipe->data.size(), uio->offset, file->nextOff);
|
size, pipe->data.size(), uio->offset, file->nextOff);
|
||||||
|
|
||||||
if (pipe->data.size() == size) {
|
if (pipe->data.size() == size) {
|
||||||
pipe->data.clear();
|
pipe->data.clear();
|
||||||
|
|
@ -55,7 +55,7 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
|
||||||
static orbis::ErrorCode pipe_write(orbis::File *file, orbis::Uio *uio,
|
static orbis::ErrorCode pipe_write(orbis::File *file, orbis::Uio *uio,
|
||||||
orbis::Thread *thread) {
|
orbis::Thread *thread) {
|
||||||
auto pipe = static_cast<orbis::Pipe *>(file)->other;
|
auto pipe = static_cast<orbis::Pipe *>(file)->other;
|
||||||
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file);
|
ORBIS_LOG_ERROR(__FUNCTION__, thread->name.c_str(), thread->tid, file);
|
||||||
|
|
||||||
std::size_t cnt = 0;
|
std::size_t cnt = 0;
|
||||||
for (auto vec : std::span(uio->iov, uio->iovcnt)) {
|
for (auto vec : std::span(uio->iov, uio->iovcnt)) {
|
||||||
|
|
@ -70,8 +70,8 @@ static orbis::ErrorCode pipe_write(orbis::File *file, orbis::Uio *uio,
|
||||||
uio->resid -= cnt;
|
uio->resid -= cnt;
|
||||||
uio->offset += cnt;
|
uio->offset += cnt;
|
||||||
|
|
||||||
ORBIS_LOG_ERROR(__FUNCTION__, thread->name, thread->tid, file, uio->resid,
|
ORBIS_LOG_ERROR(__FUNCTION__, thread->name.c_str(), thread->tid, file,
|
||||||
uio->offset, file->nextOff, cnt);
|
uio->resid, uio->offset, file->nextOff, cnt);
|
||||||
thread->where();
|
thread->where();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ orbis::SysResult orbis::sys_cpuset_getaffinity(Thread *thread, cpulevel_t level,
|
||||||
case CpuLevel::Which:
|
case CpuLevel::Which:
|
||||||
switch (CpuWhich(which)) {
|
switch (CpuWhich(which)) {
|
||||||
case CpuWhich::Tid: {
|
case CpuWhich::Tid: {
|
||||||
Thread *whichThread = nullptr;
|
rx::Ref<Thread> whichThread = nullptr;
|
||||||
if (id == ~id_t(0) || thread->tid == id) {
|
if (id == ~id_t(0) || thread->tid == id) {
|
||||||
whichThread = thread;
|
whichThread = thread;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -97,7 +97,7 @@ orbis::SysResult orbis::sys_cpuset_getaffinity(Thread *thread, cpulevel_t level,
|
||||||
if (id == ~id_t(0) || id == thread->tproc->pid) {
|
if (id == ~id_t(0) || id == thread->tproc->pid) {
|
||||||
whichProcess = thread->tproc;
|
whichProcess = thread->tproc;
|
||||||
} else {
|
} else {
|
||||||
whichProcess = g_context->findProcessById(id);
|
whichProcess = findProcessById(id);
|
||||||
|
|
||||||
if (whichProcess == nullptr) {
|
if (whichProcess == nullptr) {
|
||||||
return ErrorCode::SRCH;
|
return ErrorCode::SRCH;
|
||||||
|
|
@ -132,7 +132,7 @@ orbis::SysResult orbis::sys_cpuset_setaffinity(Thread *thread, cpulevel_t level,
|
||||||
case CpuLevel::Which:
|
case CpuLevel::Which:
|
||||||
switch (CpuWhich(which)) {
|
switch (CpuWhich(which)) {
|
||||||
case CpuWhich::Tid: {
|
case CpuWhich::Tid: {
|
||||||
Thread *whichThread = nullptr;
|
rx::Ref<Thread> whichThread = nullptr;
|
||||||
if (id == ~id_t(0) || thread->tid == id) {
|
if (id == ~id_t(0) || thread->tid == id) {
|
||||||
whichThread = thread;
|
whichThread = thread;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -163,7 +163,7 @@ orbis::SysResult orbis::sys_cpuset_setaffinity(Thread *thread, cpulevel_t level,
|
||||||
} else {
|
} else {
|
||||||
ORBIS_LOG_ERROR(__FUNCTION__, "process not found", level, which, id,
|
ORBIS_LOG_ERROR(__FUNCTION__, "process not found", level, which, id,
|
||||||
cpusetsize);
|
cpusetsize);
|
||||||
whichProcess = g_context->findProcessById(id);
|
whichProcess = findProcessById(id);
|
||||||
|
|
||||||
if (whichProcess == nullptr) {
|
if (whichProcess == nullptr) {
|
||||||
return ErrorCode::SRCH;
|
return ErrorCode::SRCH;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ orbis::SysResult orbis::sys_kenv(Thread *thread, sint what,
|
||||||
size_t entry = 0;
|
size_t entry = 0;
|
||||||
// Entry: size of both full buffers, the '=' and the '\0' at the end
|
// Entry: size of both full buffers, the '=' and the '\0' at the end
|
||||||
if (value == nullptr || len == 0) {
|
if (value == nullptr || len == 0) {
|
||||||
entry = key.size() + 1 + strnlen(env_value, 128) + 1;
|
entry = key.size() + 1 + env_value.size() + 1;
|
||||||
} else {
|
} else {
|
||||||
char buf[128 * 2 + 2];
|
char buf[128 * 2 + 2];
|
||||||
|
|
||||||
|
|
@ -28,9 +28,8 @@ orbis::SysResult orbis::sys_kenv(Thread *thread, sint what,
|
||||||
|
|
||||||
*_buf++ = '=';
|
*_buf++ = '=';
|
||||||
|
|
||||||
const size_t value_size = strnlen(env_value, 128);
|
std::strncpy(_buf, env_value.data(), env_value.size());
|
||||||
std::strncpy(_buf, env_value, value_size);
|
_buf += env_value.size();
|
||||||
_buf += value_size;
|
|
||||||
|
|
||||||
*_buf++ = '\0';
|
*_buf++ = '\0';
|
||||||
|
|
||||||
|
|
@ -58,16 +57,16 @@ orbis::SysResult orbis::sys_kenv(Thread *thread, sint what,
|
||||||
if (it == kenv.end()) {
|
if (it == kenv.end()) {
|
||||||
return ErrorCode::NOENT;
|
return ErrorCode::NOENT;
|
||||||
}
|
}
|
||||||
const char *buf = it->second;
|
ORBIS_RET_ON_ERROR(uwriteRaw(value, it->second.data(), it->second.size()));
|
||||||
ORBIS_RET_ON_ERROR(uwriteRaw(value, buf, std::min(len, 128)));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kenv_set: {
|
case kenv_set: {
|
||||||
if (len < 1) {
|
if (len < 1) {
|
||||||
return ErrorCode::INVAL;
|
return ErrorCode::INVAL;
|
||||||
}
|
}
|
||||||
char *_value_buf = kenv[kstring(_name)];
|
auto &_value_buf = kenv[kstring(_name)];
|
||||||
ORBIS_RET_ON_ERROR(ureadString(_value_buf, 128, value));
|
ORBIS_RET_ON_ERROR(
|
||||||
|
ureadString(_value_buf.data(), _value_buf.max_size() + 1, value));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kenv_unset: {
|
case kenv_unset: {
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
|
||||||
nodeIt = kq->notes.begin();
|
nodeIt = kq->notes.begin();
|
||||||
|
|
||||||
if (change.filter == kEvFiltProc) {
|
if (change.filter == kEvFiltProc) {
|
||||||
auto process = g_context->findProcessById(change.ident);
|
auto process = findProcessById(change.ident);
|
||||||
if (process == nullptr) {
|
if (process == nullptr) {
|
||||||
return ErrorCode::SRCH;
|
return ErrorCode::SRCH;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ orbis::SysResult orbis::sys_wait4(Thread *thread, sint pid, ptr<sint> status,
|
||||||
|
|
||||||
int hostPid = pid;
|
int hostPid = pid;
|
||||||
if (pid > 0) {
|
if (pid > 0) {
|
||||||
auto process = g_context->findProcessById(pid);
|
auto process = findProcessById(pid);
|
||||||
if (process == nullptr) {
|
if (process == nullptr) {
|
||||||
return ErrorCode::SRCH;
|
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);
|
ORBIS_LOG_ERROR(__FUNCTION__, pid, status, options, rusage, result, stat);
|
||||||
|
|
||||||
auto process = g_context->findProcessByHostId(result);
|
auto process = findProcessByHostId(result);
|
||||||
if (process == nullptr) {
|
if (process == nullptr) {
|
||||||
ORBIS_LOG_ERROR("host process not found", result);
|
ORBIS_LOG_ERROR("host process not found", result);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ orbis::SysResult orbis::sys_rtprio_thread(Thread *thread, sint function,
|
||||||
ORBIS_LOG_ERROR(__FUNCTION__, function, lwpid, rtp->prio, rtp->type);
|
ORBIS_LOG_ERROR(__FUNCTION__, function, lwpid, rtp->prio, rtp->type);
|
||||||
thread->where();
|
thread->where();
|
||||||
|
|
||||||
Thread *targetThread;
|
rx::Ref<Thread> targetThread;
|
||||||
if (lwpid == thread->tid || lwpid == -1) {
|
if (lwpid == thread->tid || lwpid == -1) {
|
||||||
targetThread = thread;
|
targetThread = thread;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
orbis::SysResult orbis::sys_get_authinfo(Thread *thread, pid_t pid,
|
||||||
ptr<AuthInfo> info) {
|
ptr<AuthInfo> info) {
|
||||||
|
|
||||||
auto process = pid > 0 ? g_context->findProcessById(pid) : thread->tproc;
|
auto process = pid > 0 ? findProcessById(pid) : thread->tproc;
|
||||||
if (process == nullptr) {
|
if (process == nullptr) {
|
||||||
return ErrorCode::SRCH;
|
return ErrorCode::SRCH;
|
||||||
}
|
}
|
||||||
|
|
@ -1188,21 +1188,20 @@ orbis::SysResult orbis::sys_randomized_path(Thread *thread, sint type,
|
||||||
}
|
}
|
||||||
orbis::SysResult orbis::sys_rdup(Thread *thread, sint pid, sint fd) {
|
orbis::SysResult orbis::sys_rdup(Thread *thread, sint pid, sint fd) {
|
||||||
ORBIS_LOG_TODO(__FUNCTION__, pid, fd);
|
ORBIS_LOG_TODO(__FUNCTION__, pid, fd);
|
||||||
for (auto it = g_context->getProcessList(); it != nullptr; it = it->next) {
|
auto process = pid == -1 || pid == thread->tproc->pid ? thread->tproc
|
||||||
auto &p = it->object;
|
: findProcessById(pid);
|
||||||
if (p.pid != pid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto file = p.fileDescriptors.get(fd);
|
if (!process) {
|
||||||
if (file == nullptr) {
|
return ErrorCode::SRCH;
|
||||||
return ErrorCode::BADF;
|
|
||||||
}
|
|
||||||
|
|
||||||
thread->retval[0] = thread->tproc->fileDescriptors.insert(std::move(file));
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
return ErrorCode::SRCH;
|
|
||||||
|
auto file = process->fileDescriptors.get(fd);
|
||||||
|
if (file == nullptr) {
|
||||||
|
return ErrorCode::BADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->retval[0] = thread->tproc->fileDescriptors.insert(std::move(file));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
orbis::SysResult orbis::sys_dl_get_metadata(Thread *thread /* TODO */) {
|
orbis::SysResult orbis::sys_dl_get_metadata(Thread *thread /* TODO */) {
|
||||||
return ErrorCode::NOSYS;
|
return ErrorCode::NOSYS;
|
||||||
|
|
@ -1297,7 +1296,7 @@ orbis::SysResult orbis::sys_budget_get_ptype(Thread *thread, sint pid) {
|
||||||
if (pid < 0 || pid == thread->tproc->pid) {
|
if (pid < 0 || pid == thread->tproc->pid) {
|
||||||
process = thread->tproc;
|
process = thread->tproc;
|
||||||
} else {
|
} else {
|
||||||
process = g_context->findProcessById(pid);
|
process = findProcessById(pid);
|
||||||
|
|
||||||
if (!process) {
|
if (!process) {
|
||||||
return ErrorCode::SRCH;
|
return ErrorCode::SRCH;
|
||||||
|
|
@ -1337,14 +1336,14 @@ orbis::SysResult orbis::sys_get_resident_fmem_count(Thread *thread, pid_t pid) {
|
||||||
}
|
}
|
||||||
orbis::SysResult orbis::sys_thr_get_name(Thread *thread, lwpid_t lwpid,
|
orbis::SysResult orbis::sys_thr_get_name(Thread *thread, lwpid_t lwpid,
|
||||||
char *buf, size_t buflen) {
|
char *buf, size_t buflen) {
|
||||||
Thread *searchThread;
|
rx::Ref<Thread> searchThread;
|
||||||
if (thread->tid == lwpid || lwpid == -1) {
|
if (thread->tid == lwpid || lwpid == -1) {
|
||||||
searchThread = thread;
|
searchThread = thread;
|
||||||
} else {
|
} else {
|
||||||
searchThread = thread->tproc->threadsMap.get(lwpid - thread->tproc->pid);
|
searchThread = thread->tproc->threadsMap.get(lwpid - thread->tproc->pid);
|
||||||
|
|
||||||
if (searchThread == nullptr) {
|
if (searchThread == nullptr) {
|
||||||
if (auto process = g_context->findProcessById(lwpid)) {
|
if (auto process = findProcessById(lwpid)) {
|
||||||
searchThread = process->threadsMap.get(lwpid - process->pid);
|
searchThread = process->threadsMap.get(lwpid - process->pid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1354,11 +1353,11 @@ orbis::SysResult orbis::sys_thr_get_name(Thread *thread, lwpid_t lwpid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto namelen = std::strlen(searchThread->name);
|
auto namelen = searchThread->name.length();
|
||||||
|
|
||||||
auto writeLen = std::min(namelen + 1, buflen);
|
auto writeLen = std::min(namelen + 1, buflen);
|
||||||
if (writeLen > 0) {
|
if (writeLen > 0) {
|
||||||
ORBIS_RET_ON_ERROR(uwriteRaw(buf, searchThread->name, writeLen - 1));
|
ORBIS_RET_ON_ERROR(uwriteRaw(buf, searchThread->name.data(), writeLen - 1));
|
||||||
buf[writeLen] = 0;
|
buf[writeLen] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,7 @@ orbis::SysResult orbis::sys_kill(Thread *thread, sint pid, sint signum) {
|
||||||
|
|
||||||
int hostPid = pid;
|
int hostPid = pid;
|
||||||
if (pid > 0) {
|
if (pid > 0) {
|
||||||
auto process = g_context->findProcessById(pid);
|
auto process = findProcessById(pid);
|
||||||
if (process == nullptr) {
|
if (process == nullptr) {
|
||||||
return ErrorCode::SRCH;
|
return ErrorCode::SRCH;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
||||||
ORBIS_LOG_ERROR("KERN_PROC_PROC 2");
|
ORBIS_LOG_ERROR("KERN_PROC_PROC 2");
|
||||||
|
|
||||||
if (namelen >= 4) {
|
if (namelen >= 4) {
|
||||||
auto process = g_context->findProcessById(name[3]);
|
auto process = findProcessById(name[3]);
|
||||||
if (process == nullptr || process->exitStatus.has_value()) {
|
if (process == nullptr || process->exitStatus.has_value()) {
|
||||||
return ErrorCode::SRCH;
|
return ErrorCode::SRCH;
|
||||||
}
|
}
|
||||||
|
|
@ -259,7 +259,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
||||||
if (name[0] == kern && name[1] == proc && name[2] == 36) {
|
if (name[0] == kern && name[1] == proc && name[2] == 36) {
|
||||||
Process *process = thread->tproc;
|
Process *process = thread->tproc;
|
||||||
if (process->pid != name[3]) {
|
if (process->pid != name[3]) {
|
||||||
process = g_context->findProcessById(name[3]);
|
process = findProcessById(name[3]);
|
||||||
if (process == nullptr) {
|
if (process == nullptr) {
|
||||||
ORBIS_LOG_ERROR("get sdk version by pid: process not found", name[3],
|
ORBIS_LOG_ERROR("get sdk version by pid: process not found", name[3],
|
||||||
thread->tproc->pid);
|
thread->tproc->pid);
|
||||||
|
|
@ -290,7 +290,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
||||||
// 1 - 14 - 35 - pid
|
// 1 - 14 - 35 - pid
|
||||||
Process *process = thread->tproc;
|
Process *process = thread->tproc;
|
||||||
if (process->pid != name[3] && name[3] != -1) {
|
if (process->pid != name[3] && name[3] != -1) {
|
||||||
process = g_context->findProcessById(name[3]);
|
process = findProcessById(name[3]);
|
||||||
if (process == nullptr) {
|
if (process == nullptr) {
|
||||||
ORBIS_LOG_ERROR("appinfo process not found", name[3],
|
ORBIS_LOG_ERROR("appinfo process not found", name[3],
|
||||||
thread->tproc->pid);
|
thread->tproc->pid);
|
||||||
|
|
@ -461,7 +461,7 @@ SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
||||||
if (name[0] == kern && name[1] == proc && name[2] == 68) {
|
if (name[0] == kern && name[1] == proc && name[2] == 68) {
|
||||||
Process *process = thread->tproc;
|
Process *process = thread->tproc;
|
||||||
if (process->pid != name[3]) {
|
if (process->pid != name[3]) {
|
||||||
process = g_context->findProcessById(name[3]);
|
process = findProcessById(name[3]);
|
||||||
if (process == nullptr) {
|
if (process == nullptr) {
|
||||||
ORBIS_LOG_ERROR("get ps5 sdk version by pid: process not found",
|
ORBIS_LOG_ERROR("get ps5 sdk version by pid: process not found",
|
||||||
name[3], thread->tproc->pid);
|
name[3], thread->tproc->pid);
|
||||||
|
|
|
||||||
179
kernel/orbis/src/thread/Process.cpp
Normal file
179
kernel/orbis/src/thread/Process.cpp
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
#include "thread/Process.hpp"
|
||||||
|
#include "KernelAllocator.hpp"
|
||||||
|
#include "KernelContext.hpp"
|
||||||
|
#include "KernelObject.hpp"
|
||||||
|
#include "kernel/KernelObject.hpp"
|
||||||
|
#include "rx/LinkedNode.hpp"
|
||||||
|
#include "rx/Serializer.hpp"
|
||||||
|
#include "rx/align.hpp"
|
||||||
|
#include "thread/Thread.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
struct ProcessIdList {
|
||||||
|
rx::OwningIdMap<std::uint8_t, orbis::pid_t, 256, 0> pidMap;
|
||||||
|
|
||||||
|
void serialize(rx::Serializer &s) const {
|
||||||
|
pidMap.walk([&s](std::uint8_t id, orbis::pid_t value) {
|
||||||
|
s.serialize(id);
|
||||||
|
s.serialize(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
s.serialize<std::uint8_t>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserialize(rx::Deserializer &s) {
|
||||||
|
while (true) {
|
||||||
|
auto id = s.deserialize<std::uint8_t>();
|
||||||
|
if (id == static_cast<std::uint8_t>(-1)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto value = s.deserialize<orbis::pid_t>();
|
||||||
|
|
||||||
|
if (s.failure()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pidMap.emplace_at(id, value)) {
|
||||||
|
s.setFailure();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto g_processIdList =
|
||||||
|
orbis::createGlobalObject<kernel::LockableKernelObject<ProcessIdList>>();
|
||||||
|
|
||||||
|
orbis::pid_t orbis::allocatePid() {
|
||||||
|
std::lock_guard lock(*g_processIdList);
|
||||||
|
return g_processIdList->pidMap.emplace(0).first * 10000 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ProcessList {
|
||||||
|
rx::LinkedNode<orbis::Process> *list = nullptr;
|
||||||
|
|
||||||
|
void serialize(rx::Serializer &s) const {
|
||||||
|
for (auto proc = list; proc != nullptr; proc = proc->next) {
|
||||||
|
s.serialize(proc->object.pid);
|
||||||
|
s.serialize(proc->object);
|
||||||
|
}
|
||||||
|
|
||||||
|
s.serialize<pid_t>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserialize(rx::Deserializer &s) {
|
||||||
|
while (true) {
|
||||||
|
auto pid = s.deserialize<pid_t>();
|
||||||
|
if (pid == static_cast<pid_t>(-1) || s.failure()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto process = orbis::createProcess(nullptr, pid);
|
||||||
|
s.deserialize(*process);
|
||||||
|
|
||||||
|
if (s.failure()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static auto g_processList =
|
||||||
|
orbis::createGlobalObject<kernel::LockableKernelObject<ProcessList>>();
|
||||||
|
|
||||||
|
void orbis::deleteProcess(orbis::Process *proc) {
|
||||||
|
auto procNode = reinterpret_cast<rx::LinkedNode<Process> *>(proc);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard lock(*g_processList);
|
||||||
|
auto next = procNode->erase();
|
||||||
|
|
||||||
|
if (procNode == g_processList->list) {
|
||||||
|
g_processList->list = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kdelete(procNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
orbis::Process *orbis::findProcessById(pid_t pid) {
|
||||||
|
for (std::size_t i = 0; i < 20; ++i) {
|
||||||
|
{
|
||||||
|
std::lock_guard lock(*g_processList);
|
||||||
|
for (auto proc = g_processList->list; proc != nullptr;
|
||||||
|
proc = proc->next) {
|
||||||
|
if (proc->object.pid == pid) {
|
||||||
|
return &proc->object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::this_thread::sleep_for(std::chrono::microseconds(50));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
orbis::Process *orbis::findProcessByHostId(std::uint64_t pid) {
|
||||||
|
for (std::size_t i = 0; i < 20; ++i) {
|
||||||
|
{
|
||||||
|
std::lock_guard lock(*g_processList);
|
||||||
|
for (auto proc = g_processList->list; proc != nullptr;
|
||||||
|
proc = proc->next) {
|
||||||
|
if (proc->object.hostPid == pid) {
|
||||||
|
return &proc->object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::microseconds(50));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void orbis::Process::serialize(rx::Serializer &s) const {
|
||||||
|
Process::Storage::SerializeAll(storage, s);
|
||||||
|
}
|
||||||
|
void orbis::Process::deserialize(rx::Deserializer &s) {
|
||||||
|
Process::Storage::DeserializeAll(storage, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
orbis::Process::~Process() {
|
||||||
|
Process::Storage::DestructAll(storage);
|
||||||
|
|
||||||
|
auto size = sizeof(Process);
|
||||||
|
size = rx::alignUp(size, Process::Storage::GetAlignment());
|
||||||
|
size += Process::Storage::GetSize();
|
||||||
|
|
||||||
|
kfree(this, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
orbis::Process *orbis::createProcess(Process *parentProcess, pid_t pid) {
|
||||||
|
if (pid == static_cast<pid_t>(-1)) {
|
||||||
|
pid = allocatePid();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto size = sizeof(rx::LinkedNode<Process>);
|
||||||
|
size = rx::alignUp(size, Process::Storage::GetAlignment());
|
||||||
|
auto storageOffset = size;
|
||||||
|
size += Process::Storage::GetSize();
|
||||||
|
|
||||||
|
auto memory = (std::byte *)kalloc(
|
||||||
|
size, std::max<std::size_t>(alignof(rx::LinkedNode<Process>),
|
||||||
|
Process::Storage::GetAlignment()));
|
||||||
|
|
||||||
|
auto result = new (memory) rx::LinkedNode<Process>();
|
||||||
|
result->object.context = g_context.get();
|
||||||
|
result->object.storage = memory + storageOffset;
|
||||||
|
result->object.parentProcess = parentProcess;
|
||||||
|
result->object.pid = pid;
|
||||||
|
Process::Storage::ConstructAll(result->object.storage);
|
||||||
|
|
||||||
|
std::lock_guard lock(*g_processList);
|
||||||
|
if (auto list = g_processList->list) {
|
||||||
|
list->insertPrev(*result);
|
||||||
|
}
|
||||||
|
g_processList->list = result;
|
||||||
|
return &result->object;
|
||||||
|
}
|
||||||
38
kernel/orbis/src/thread/Thread.cpp
Normal file
38
kernel/orbis/src/thread/Thread.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include "thread/Thread.hpp"
|
||||||
|
#include "thread/Process.hpp"
|
||||||
|
|
||||||
|
orbis::Thread::~Thread() {
|
||||||
|
Thread::Storage::DestructAll(storage);
|
||||||
|
|
||||||
|
auto size = sizeof(Thread);
|
||||||
|
size = rx::alignUp(size, Thread::Storage::GetAlignment());
|
||||||
|
size += Thread::Storage::GetSize();
|
||||||
|
|
||||||
|
kfree(this, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
orbis::Thread *orbis::createThread(Process *process, std::string_view name) {
|
||||||
|
auto size = sizeof(Thread);
|
||||||
|
size = rx::alignUp(size, Thread::Storage::GetAlignment());
|
||||||
|
auto storageOffset = size;
|
||||||
|
size += Thread::Storage::GetSize();
|
||||||
|
|
||||||
|
auto memory = (std::byte *)kalloc(
|
||||||
|
size,
|
||||||
|
std::max<std::size_t>(alignof(Thread), Thread::Storage::GetAlignment()));
|
||||||
|
|
||||||
|
auto result = new (memory) Thread();
|
||||||
|
result->storage = memory + storageOffset;
|
||||||
|
result->tproc = process;
|
||||||
|
result->name = name;
|
||||||
|
|
||||||
|
Thread::Storage::ConstructAll(result->storage);
|
||||||
|
|
||||||
|
std::lock_guard lock(process->mtx);
|
||||||
|
auto baseId = process->threadsMap.insert(result);
|
||||||
|
result->tproc = process;
|
||||||
|
result->tid = process->pid + baseId;
|
||||||
|
result->state = orbis::ThreadState::RUNNING;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "io-device.hpp"
|
#include "io-device.hpp"
|
||||||
#include "orbis/KernelContext.hpp"
|
#include "orbis/KernelContext.hpp"
|
||||||
#include "orbis/osem.hpp"
|
#include "orbis/osem.hpp"
|
||||||
|
#include "orbis/thread/Process.hpp"
|
||||||
#include "orbis/utils/Logs.hpp"
|
#include "orbis/utils/Logs.hpp"
|
||||||
#include "rx/format.hpp"
|
#include "rx/format.hpp"
|
||||||
#include "rx/hexdump.hpp"
|
#include "rx/hexdump.hpp"
|
||||||
|
|
@ -357,7 +358,7 @@ ipmi::IpmiServer &ipmi::createIpmiServer(orbis::Process *process,
|
||||||
if ((packet.info.type & ~0x8010) == 0x41) {
|
if ((packet.info.type & ~0x8010) == 0x41) {
|
||||||
auto msgHeader = std::bit_cast<orbis::IpmiSyncMessageHeader *>(
|
auto msgHeader = std::bit_cast<orbis::IpmiSyncMessageHeader *>(
|
||||||
packet.message.data());
|
packet.message.data());
|
||||||
auto process = orbis::g_context->findProcessById(msgHeader->pid);
|
auto process = orbis::findProcessById(msgHeader->pid);
|
||||||
if (process == nullptr) {
|
if (process == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -378,7 +379,7 @@ ipmi::IpmiServer &ipmi::createIpmiServer(orbis::Process *process,
|
||||||
|
|
||||||
if ((packet.info.type & ~0x10) == 0x43) {
|
if ((packet.info.type & ~0x10) == 0x43) {
|
||||||
auto msgHeader = (orbis::IpmiAsyncMessageHeader *)packet.message.data();
|
auto msgHeader = (orbis::IpmiAsyncMessageHeader *)packet.message.data();
|
||||||
auto process = orbis::g_context->findProcessById(msgHeader->pid);
|
auto process = orbis::findProcessById(msgHeader->pid);
|
||||||
if (process == nullptr) {
|
if (process == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -534,20 +534,6 @@ static void guestInitFd(orbis::Thread *mainThread) {
|
||||||
mainThread->tproc->fileDescriptors.insert(stderrFile);
|
mainThread->tproc->fileDescriptors.insert(stderrFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static orbis::Process *createGuestProcess() {
|
|
||||||
auto pid = orbis::g_context->allocatePid() * 10000 + 1;
|
|
||||||
return orbis::g_context->createProcess(pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static orbis::Thread *createGuestThread() {
|
|
||||||
auto process = createGuestProcess();
|
|
||||||
auto [baseId, thread] = process->threadsMap.emplace();
|
|
||||||
thread->tproc = process;
|
|
||||||
thread->tid = process->pid + baseId;
|
|
||||||
thread->state = orbis::ThreadState::RUNNING;
|
|
||||||
return thread;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ExecEnv {
|
struct ExecEnv {
|
||||||
std::uint64_t entryPoint;
|
std::uint64_t entryPoint;
|
||||||
std::uint64_t interpBase;
|
std::uint64_t interpBase;
|
||||||
|
|
@ -789,7 +775,7 @@ static orbis::SysResult launchDaemon(orbis::Thread *thread, std::string path,
|
||||||
std::vector<std::string> argv,
|
std::vector<std::string> argv,
|
||||||
std::vector<std::string> envv,
|
std::vector<std::string> envv,
|
||||||
orbis::AppInfoEx appInfo) {
|
orbis::AppInfoEx appInfo) {
|
||||||
auto childPid = orbis::g_context->allocatePid() * 10000 + 1;
|
auto childPid = orbis::allocatePid();
|
||||||
auto flag = orbis::knew<std::atomic<bool>>();
|
auto flag = orbis::knew<std::atomic<bool>>();
|
||||||
*flag = false;
|
*flag = false;
|
||||||
|
|
||||||
|
|
@ -805,7 +791,7 @@ static orbis::SysResult launchDaemon(orbis::Thread *thread, std::string path,
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto process = orbis::g_context->createProcess(childPid);
|
auto process = orbis::createProcess(thread->tproc, childPid);
|
||||||
auto logFd = ::open(("log-" + std::to_string(childPid) + ".txt").c_str(),
|
auto logFd = ::open(("log-" + std::to_string(childPid) + ".txt").c_str(),
|
||||||
O_CREAT | O_TRUNC | O_WRONLY, 0666);
|
O_CREAT | O_TRUNC | O_WRONLY, 0666);
|
||||||
|
|
||||||
|
|
@ -817,7 +803,6 @@ static orbis::SysResult launchDaemon(orbis::Thread *thread, std::string path,
|
||||||
process->onSysEnter = thread->tproc->onSysEnter;
|
process->onSysEnter = thread->tproc->onSysEnter;
|
||||||
process->onSysExit = thread->tproc->onSysExit;
|
process->onSysExit = thread->tproc->onSysExit;
|
||||||
process->ops = thread->tproc->ops;
|
process->ops = thread->tproc->ops;
|
||||||
process->parentProcess = thread->tproc;
|
|
||||||
process->appInfo = appInfo;
|
process->appInfo = appInfo;
|
||||||
|
|
||||||
process->authInfo = {
|
process->authInfo = {
|
||||||
|
|
@ -845,10 +830,9 @@ static orbis::SysResult launchDaemon(orbis::Thread *thread, std::string path,
|
||||||
|
|
||||||
*flag = true;
|
*flag = true;
|
||||||
|
|
||||||
auto [baseId, newThread] = process->threadsMap.emplace();
|
auto newThread = orbis::createThread(process, path);
|
||||||
newThread->tproc = process;
|
newThread->hostTid = ::gettid();
|
||||||
newThread->tid = process->pid + baseId;
|
newThread->nativeHandle = pthread_self();
|
||||||
newThread->state = orbis::ThreadState::RUNNING;
|
|
||||||
newThread->context = thread->context;
|
newThread->context = thread->context;
|
||||||
newThread->fsBase = thread->fsBase;
|
newThread->fsBase = thread->fsBase;
|
||||||
|
|
||||||
|
|
@ -1060,8 +1044,8 @@ int main(int argc, const char *argv[]) {
|
||||||
rx::thread::initialize();
|
rx::thread::initialize();
|
||||||
|
|
||||||
// vm::printHostStats();
|
// vm::printHostStats();
|
||||||
orbis::g_context->allocatePid();
|
orbis::allocatePid();
|
||||||
auto initProcess = orbis::g_context->createProcess(asRoot ? 1 : 10);
|
auto initProcess = orbis::createProcess(nullptr, asRoot ? 1 : 10);
|
||||||
// pthread_setname_np(pthread_self(), "10.MAINTHREAD");
|
// pthread_setname_np(pthread_self(), "10.MAINTHREAD");
|
||||||
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
@ -1216,10 +1200,9 @@ int main(int argc, const char *argv[]) {
|
||||||
initProcess->isInSandbox = true;
|
initProcess->isInSandbox = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [baseId, mainThread] = initProcess->threadsMap.emplace();
|
auto mainThread = orbis::createThread(initProcess, "");
|
||||||
mainThread->tproc = initProcess;
|
mainThread->hostTid = ::gettid();
|
||||||
mainThread->tid = initProcess->pid + baseId;
|
mainThread->nativeHandle = pthread_self();
|
||||||
mainThread->state = orbis::ThreadState::RUNNING;
|
|
||||||
orbis::g_currentThread = mainThread;
|
orbis::g_currentThread = mainThread;
|
||||||
|
|
||||||
if (!isSystem && !vfs::exists(guestArgv[0], mainThread) &&
|
if (!isSystem && !vfs::exists(guestArgv[0], mainThread) &&
|
||||||
|
|
@ -1345,7 +1328,8 @@ int main(int argc, const char *argv[]) {
|
||||||
// version
|
// version
|
||||||
if (orbis::g_context->fwType != orbis::FwType::Ps5 &&
|
if (orbis::g_context->fwType != orbis::FwType::Ps5 &&
|
||||||
orbis::g_context->fwSdkVersion >= 0x5050000) {
|
orbis::g_context->fwSdkVersion >= 0x5050000) {
|
||||||
auto fakeIpmiThread = createGuestThread();
|
auto fakeIpmiThread =
|
||||||
|
orbis::createThread(initProcess, "SceSysAudioSystemIpc");
|
||||||
ipmi::audioIpmiClient =
|
ipmi::audioIpmiClient =
|
||||||
ipmi::createIpmiClient(fakeIpmiThread, "SceSysAudioSystemIpc");
|
ipmi::createIpmiClient(fakeIpmiThread, "SceSysAudioSystemIpc");
|
||||||
// HACK: here is a bug in audiod because we send this very early and
|
// HACK: here is a bug in audiod because we send this very early and
|
||||||
|
|
|
||||||
|
|
@ -537,13 +537,14 @@ SysResult thr_new(orbis::Thread *thread, orbis::ptr<thr_param> param,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto proc = thread->tproc;
|
char _name[32]{};
|
||||||
std::lock_guard lock(proc->mtx);
|
if (_param.name != 0) {
|
||||||
auto [baseId, childThread] = proc->threadsMap.emplace();
|
ORBIS_RET_ON_ERROR(ureadString(_name, sizeof(_name), _param.name));
|
||||||
std::lock_guard lockThr(childThread->mtx);
|
}
|
||||||
childThread->tproc = proc;
|
|
||||||
childThread->tid = proc->pid + baseId;
|
auto childThread = orbis::createThread(thread->tproc, _name);
|
||||||
childThread->state = orbis::ThreadState::RUNQ;
|
|
||||||
|
std::lock_guard lock(childThread->mtx);
|
||||||
childThread->stackStart = _param.stack_base;
|
childThread->stackStart = _param.stack_base;
|
||||||
childThread->stackEnd = _param.stack_base + _param.stack_size;
|
childThread->stackEnd = _param.stack_base + _param.stack_size;
|
||||||
childThread->fsBase = reinterpret_cast<std::uintptr_t>(_param.tls_base);
|
childThread->fsBase = reinterpret_cast<std::uintptr_t>(_param.tls_base);
|
||||||
|
|
@ -560,11 +561,6 @@ SysResult thr_new(orbis::Thread *thread, orbis::ptr<thr_param> param,
|
||||||
childThread->stackStart, _param.rtp, _param.name,
|
childThread->stackStart, _param.rtp, _param.name,
|
||||||
_param.spare[0], _param.spare[1]);
|
_param.spare[0], _param.spare[1]);
|
||||||
|
|
||||||
if (_param.name != 0) {
|
|
||||||
ORBIS_RET_ON_ERROR(
|
|
||||||
ureadString(childThread->name, sizeof(childThread->name), _param.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_param.rtp != 0) {
|
if (_param.rtp != 0) {
|
||||||
rtprio _rtp;
|
rtprio _rtp;
|
||||||
ORBIS_RET_ON_ERROR(uread(_rtp, _param.rtp));
|
ORBIS_RET_ON_ERROR(uread(_rtp, _param.rtp));
|
||||||
|
|
@ -760,7 +756,7 @@ SysResult processNeeded(Thread *thread) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SysResult fork(Thread *thread, slong flags) {
|
SysResult fork(Thread *thread, slong flags) {
|
||||||
auto childPid = g_context->allocatePid() * 10000 + 1;
|
auto childPid = orbis::allocatePid();
|
||||||
ORBIS_LOG_TODO(__FUNCTION__, flags, childPid, thread->tid);
|
ORBIS_LOG_TODO(__FUNCTION__, flags, childPid, thread->tid);
|
||||||
thread->where();
|
thread->where();
|
||||||
auto flag = knew<std::atomic<bool>>();
|
auto flag = knew<std::atomic<bool>>();
|
||||||
|
|
@ -783,13 +779,12 @@ SysResult fork(Thread *thread, slong flags) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto process = g_context->createProcess(childPid);
|
auto process = orbis::createProcess(thread->tproc, childPid);
|
||||||
process->hostPid = ::getpid();
|
process->hostPid = ::getpid();
|
||||||
process->sysent = thread->tproc->sysent;
|
process->sysent = thread->tproc->sysent;
|
||||||
process->onSysEnter = thread->tproc->onSysEnter;
|
process->onSysEnter = thread->tproc->onSysEnter;
|
||||||
process->onSysExit = thread->tproc->onSysExit;
|
process->onSysExit = thread->tproc->onSysExit;
|
||||||
process->ops = thread->tproc->ops;
|
process->ops = thread->tproc->ops;
|
||||||
process->parentProcess = thread->tproc;
|
|
||||||
process->authInfo = thread->tproc->authInfo;
|
process->authInfo = thread->tproc->authInfo;
|
||||||
process->sdkVersion = thread->tproc->sdkVersion;
|
process->sdkVersion = thread->tproc->sdkVersion;
|
||||||
process->type = thread->tproc->type;
|
process->type = thread->tproc->type;
|
||||||
|
|
@ -813,11 +808,8 @@ SysResult fork(Thread *thread, slong flags) {
|
||||||
|
|
||||||
*flag = true;
|
*flag = true;
|
||||||
|
|
||||||
auto [baseId, newThread] = process->threadsMap.emplace();
|
auto newThread = orbis::createThread(process, thread->name);
|
||||||
newThread->tproc = process;
|
|
||||||
newThread->hostTid = ::gettid();
|
newThread->hostTid = ::gettid();
|
||||||
newThread->tid = process->pid + baseId;
|
|
||||||
newThread->state = orbis::ThreadState::RUNNING;
|
|
||||||
newThread->context = thread->context;
|
newThread->context = thread->context;
|
||||||
newThread->fsBase = thread->fsBase;
|
newThread->fsBase = thread->fsBase;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
#include "BitSet.hpp"
|
#include "BitSet.hpp"
|
||||||
#include "Rc.hpp"
|
#include "Rc.hpp"
|
||||||
#include "SharedMutex.hpp"
|
#include "SharedMutex.hpp"
|
||||||
|
#include "FunctionRef.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <bit>
|
#include <bit>
|
||||||
|
|
@ -324,10 +325,24 @@ struct OwningIdMap {
|
||||||
std::construct_at(get(index), std::forward<ArgsT>(args)...)};
|
std::construct_at(get(index), std::forward<ArgsT>(args)...)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename... ArgsT>
|
||||||
|
T *emplace_new_at(std::size_t index, ArgsT &&...args) {
|
||||||
|
if (mask.test(index)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
mask.set(index);
|
||||||
|
return std::construct_at(get(index), std::forward<ArgsT>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
T *get(std::size_t index) {
|
T *get(std::size_t index) {
|
||||||
return reinterpret_cast<T *>(objects + sizeof(T) * index);
|
return reinterpret_cast<T *>(objects + sizeof(T) * index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const T *get(std::size_t index) const {
|
||||||
|
return reinterpret_cast<const T *>(objects + sizeof(T) * index);
|
||||||
|
}
|
||||||
|
|
||||||
void destroy(std::size_t index) {
|
void destroy(std::size_t index) {
|
||||||
std::destroy_at(get(index));
|
std::destroy_at(get(index));
|
||||||
mask.clear(index);
|
mask.clear(index);
|
||||||
|
|
@ -337,6 +352,25 @@ struct OwningIdMap {
|
||||||
IdMapChunk chunks[ChunkCount]{};
|
IdMapChunk chunks[ChunkCount]{};
|
||||||
BitSet<ChunkCount> fullChunks;
|
BitSet<ChunkCount> fullChunks;
|
||||||
|
|
||||||
|
template <typename... ArgsT>
|
||||||
|
requires(std::is_constructible_v<T, ArgsT...>)
|
||||||
|
T *emplace_at(IdT id, ArgsT &&...args) {
|
||||||
|
auto page = static_cast<std::uint64_t>(id) / ChunkSize;
|
||||||
|
if (page >= ChunkCount) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto newElem =
|
||||||
|
chunks[page].emplace_new_at(static_cast<std::uint64_t>(id) % ChunkSize,
|
||||||
|
std::forward<ArgsT>(args)...);
|
||||||
|
|
||||||
|
if (chunks[page].mask.full()) {
|
||||||
|
fullChunks.set(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newElem;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename... ArgsT>
|
template <typename... ArgsT>
|
||||||
requires(std::is_constructible_v<T, ArgsT...>)
|
requires(std::is_constructible_v<T, ArgsT...>)
|
||||||
std::pair<IdT, T *> emplace(ArgsT &&...args) {
|
std::pair<IdT, T *> emplace(ArgsT &&...args) {
|
||||||
|
|
@ -390,13 +424,13 @@ struct OwningIdMap {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void walk(auto cb) {
|
void walk(FunctionRef<void(IdT, const T &)> cb) const {
|
||||||
for (std::size_t chunk = 0; chunk < ChunkCount; ++chunk) {
|
for (std::size_t chunk = 0; chunk < ChunkCount; ++chunk) {
|
||||||
std::size_t index = chunks[chunk].mask.countr_zero();
|
std::size_t index = chunks[chunk].mask.countr_zero();
|
||||||
|
|
||||||
while (index < ChunkSize) {
|
while (index < ChunkSize) {
|
||||||
auto id = static_cast<IdT>(index + chunk * ChunkSize + MinId);
|
auto id = static_cast<IdT>(index + chunk * ChunkSize + MinId);
|
||||||
cb(id, chunks[chunk].get(id));
|
cb(id, *chunks[chunk].get(id));
|
||||||
|
|
||||||
index = chunks[chunk].mask.countr_zero(index + 1);
|
index = chunks[chunk].mask.countr_zero(index + 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue