mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-04 14:08:37 +00:00
[rpcsx-os] fork: implement vm and vfs fork
stub metadbg device implement notification device implement sys_pipe
This commit is contained in:
parent
39092c7f16
commit
525ef02e8a
22 changed files with 379 additions and 76 deletions
|
|
@ -6,6 +6,7 @@ add_library(obj.orbis-utils-ipc OBJECT
|
|||
)
|
||||
add_library(obj.orbis-kernel OBJECT
|
||||
src/module.cpp
|
||||
src/pipe.cpp
|
||||
src/sysvec.cpp
|
||||
src/evf.cpp
|
||||
src/KernelContext.cpp
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "evf.hpp"
|
||||
#include "ipmi.hpp"
|
||||
#include "orbis/utils/IdMap.hpp"
|
||||
#include "osem.hpp"
|
||||
#include "utils/LinkedNode.hpp"
|
||||
#include "utils/SharedCV.hpp"
|
||||
|
|
@ -54,6 +55,15 @@ public:
|
|||
void deleteProcess(Process *proc);
|
||||
Process *findProcessById(pid_t pid) const;
|
||||
|
||||
utils::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();
|
||||
|
||||
void *kalloc(std::size_t size,
|
||||
|
|
@ -161,6 +171,8 @@ private:
|
|||
|
||||
std::atomic<long> m_tsc_freq{0};
|
||||
|
||||
shared_mutex m_thread_id_mtx;
|
||||
OwningIdMap<char, long, 256, 0> m_thread_id_map;
|
||||
mutable shared_mutex m_proc_mtx;
|
||||
utils::LinkedNode<Process> *m_processes = nullptr;
|
||||
|
||||
|
|
|
|||
13
orbis-kernel/include/orbis/pipe.hpp
Normal file
13
orbis-kernel/include/orbis/pipe.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "file.hpp"
|
||||
#include "utils/Rc.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct Pipe final : File {
|
||||
kvector<std::byte> data;
|
||||
};
|
||||
|
||||
Ref<Pipe> createPipe();
|
||||
} // namespace orbis
|
||||
|
|
@ -70,6 +70,7 @@ struct ProcessOps {
|
|||
SysResult (*thr_wake)(Thread *thread, slong id);
|
||||
SysResult (*thr_set_name)(Thread *thread, slong id, ptr<const char> name);
|
||||
|
||||
SysResult (*fork)(Thread *thread, slong status);
|
||||
SysResult (*exit)(Thread *thread, sint status);
|
||||
|
||||
SysResult (*processNeeded)(Thread *thread);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
namespace orbis {
|
||||
inline namespace utils {
|
||||
// IPC-ready lightweight condition variable
|
||||
class shared_cv {
|
||||
class shared_cv final {
|
||||
enum : unsigned {
|
||||
c_waiter_mask = 0xffff,
|
||||
c_signal_mask = 0x7fff0000,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ KernelContext &g_context = *[]() -> KernelContext * {
|
|||
auto ptr = mmap(reinterpret_cast<void *>(0x200'0000'0000), 0x1'0000'0000,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
if (!ptr)
|
||||
if (ptr == MAP_FAILED)
|
||||
std::abort();
|
||||
|
||||
return new (ptr) KernelContext;
|
||||
|
|
@ -163,6 +163,9 @@ void KernelContext::kfree(void *ptr, std::size_t size) {
|
|||
~(__STDCPP_DEFAULT_NEW_ALIGNMENT__ - 1);
|
||||
if (!size)
|
||||
std::abort();
|
||||
if ((uintptr_t)ptr == 0x2000001a2b0) {
|
||||
std::fprintf(stderr, "free %p-%p (%zu)\n", ptr, (char *)ptr + size, size);
|
||||
}
|
||||
std::memset(ptr, 0xcc, size);
|
||||
|
||||
pthread_mutex_lock(&m_heap_mtx);
|
||||
|
|
|
|||
61
orbis-kernel/src/pipe.cpp
Normal file
61
orbis-kernel/src/pipe.cpp
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#include "pipe.hpp"
|
||||
#include "error/ErrorCode.hpp"
|
||||
#include "file.hpp"
|
||||
#include "uio.hpp"
|
||||
#include <span>
|
||||
#include <thread>
|
||||
|
||||
static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *thread) {
|
||||
auto pipe = static_cast<orbis::Pipe *>(file);
|
||||
while (true) {
|
||||
if (pipe->data.empty()) {
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
std::lock_guard lock(pipe->mtx);
|
||||
|
||||
if (pipe->data.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto vec : std::span(uio->iov, uio->iovcnt)) {
|
||||
auto size = std::min<std::size_t>(pipe->data.size(), vec.len);
|
||||
uio->offset += size;
|
||||
std::memcpy(vec.base, pipe->data.data(), size);
|
||||
|
||||
if (pipe->data.size() == size) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::memmove(pipe->data.data(), pipe->data.data() + size,
|
||||
pipe->data.size() - size);
|
||||
pipe->data.resize(pipe->data.size() - size);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static orbis::ErrorCode pipe_write(orbis::File *file, orbis::Uio *uio,
|
||||
orbis::Thread *thread) {
|
||||
auto pipe = static_cast<orbis::Pipe *>(file);
|
||||
std::lock_guard lock(pipe->mtx);
|
||||
|
||||
for (auto vec : std::span(uio->iov, uio->iovcnt)) {
|
||||
auto offset = pipe->data.size();
|
||||
pipe->data.resize(offset + vec.len);
|
||||
std::memcpy(pipe->data.data(), vec.base, vec.len);
|
||||
}
|
||||
uio->resid = 0;
|
||||
return {};
|
||||
}
|
||||
|
||||
static orbis::FileOps pipe_ops = {.read = pipe_read, .write = pipe_write};
|
||||
|
||||
orbis::Ref<orbis::Pipe> orbis::createPipe() {
|
||||
auto result = knew<Pipe>();
|
||||
result->ops = &pipe_ops;
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
#include "KernelContext.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
@ -11,42 +10,8 @@ orbis::SysResult orbis::sys_pdfork(Thread *thread, ptr<sint> fdp, sint flags) {
|
|||
|
||||
orbis::SysResult orbis::sys_vfork(Thread *thread) { return ErrorCode::NOSYS; }
|
||||
orbis::SysResult orbis::sys_rfork(Thread *thread, sint flags) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, flags);
|
||||
|
||||
int hostPid = ::fork();
|
||||
if (hostPid) {
|
||||
thread->retval[0] = 10001;
|
||||
thread->retval[1] = 0;
|
||||
} else {
|
||||
auto process = g_context.createProcess(10001);
|
||||
std::lock_guard lock(thread->tproc->fileDescriptors.mutex);
|
||||
process->sysent = thread->tproc->sysent;
|
||||
process->onSysEnter = thread->tproc->onSysEnter;
|
||||
process->onSysExit = thread->tproc->onSysExit;
|
||||
process->ops = thread->tproc->ops;
|
||||
process->isSystem = thread->tproc->isSystem;
|
||||
for (auto [id, mod] : thread->tproc->modulesMap) {
|
||||
if (!process->modulesMap.insert(id, mod)) {
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto [id, mod] : thread->tproc->fileDescriptors) {
|
||||
if (!process->fileDescriptors.insert(id, mod)) {
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
auto [baseId, newThread] = process->threadsMap.emplace();
|
||||
newThread->tproc = process;
|
||||
newThread->tid = process->pid + baseId;
|
||||
newThread->state = orbis::ThreadState::RUNNING;
|
||||
newThread->context = thread->context;
|
||||
newThread->fsBase = thread->fsBase;
|
||||
|
||||
orbis::g_currentThread = newThread;
|
||||
newThread->retval[0] = 0;
|
||||
newThread->retval[1] = 1;
|
||||
if (auto fork = thread->tproc->ops->fork) {
|
||||
return fork(thread, flags);
|
||||
}
|
||||
return {};
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include <pipe.hpp>
|
||||
|
||||
orbis::SysResult orbis::sys_pipe(Thread *thread) { return ErrorCode::NOSYS; }
|
||||
orbis::SysResult orbis::sys_pipe(Thread *thread) {
|
||||
auto pipe = createPipe();
|
||||
thread->retval[0] = thread->tproc->fileDescriptors.insert(pipe);
|
||||
thread->retval[1] = thread->tproc->fileDescriptors.insert(pipe);
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue