[rpcsx-os/orbis-kernel] random bugfixes

ipmi: fixed respond sync, get message, try get message, try send message
event: detach event emitter from file
signals: basic implementation
linker: fixed zero symbol relocation, fixed exec relocation
shared_cv/mutex: implement eintr response support
shared_cv: fixed possible loop instead of wait
ipmi: implement invoke async, respond async, get result, get client app id, client get name
rpcsx-os: add safemode flag
This commit is contained in:
DH 2024-01-13 20:57:02 +03:00
parent 8791312d4f
commit 65e653f5ef
81 changed files with 2586 additions and 761 deletions

View file

@ -1,16 +1,15 @@
#pragma once
#include "AudioOut.hpp"
#include "KernelAllocator.hpp"
#include "evf.hpp"
#include "ipmi.hpp"
#include "orbis/utils/IdMap.hpp"
#include "osem.hpp"
#include "thread/types.hpp"
#include "utils/IdMap.hpp"
#include "utils/LinkedNode.hpp"
#include "utils/SharedCV.hpp"
#include "utils/SharedMutex.hpp"
#include "AudioOut.hpp"
#include "KernelAllocator.hpp"
#include "orbis/thread/types.hpp"
#include <algorithm>
#include <cstdint>
#include <mutex>
#include <pthread.h>
@ -175,6 +174,10 @@ public:
AudioOut *audioOut = nullptr;
uint sdkVersion{};
uint fwSdkVersion{};
uint safeMode{};
shared_mutex regMgrMtx;
kmap<std::uint32_t, std::uint32_t> regMgrInt;
private:
mutable pthread_mutex_t m_heap_mtx;

View file

@ -57,8 +57,8 @@ struct FileOps {
Thread *thread) = nullptr;
ErrorCode (*sendmsg)(orbis::File *file, msghdr *msg, sint flags,
Thread *thread) = nullptr;
ErrorCode (*recvfrom)(orbis::File *file, void *buf, size_t len,
sint flags, SocketAddress *from, uint32_t *fromlenaddr,
ErrorCode (*recvfrom)(orbis::File *file, void *buf, size_t len, sint flags,
SocketAddress *from, uint32_t *fromlenaddr,
Thread *thread) = nullptr;
ErrorCode (*recvmsg)(orbis::File *file, msghdr *msg, sint flags,
Thread *thread) = nullptr;
@ -75,11 +75,15 @@ struct FileOps {
struct File : RcBase {
shared_mutex mtx;
EventEmitter event;
Ref<EventEmitter> event;
const FileOps *ops = nullptr;
Ref<RcBase> device;
std::uint64_t nextOff = 0;
int flags = 0;
int mode = 0;
int hostFd = -1;
utils::kvector<Dirent> dirEntries;
bool noBlock() const { return (flags & 4) != 0; }
};
} // namespace orbis

View file

@ -16,7 +16,7 @@ struct Thread;
struct IpmiServer : RcBase {
struct IpmiPacketInfo {
ptr<void> userData;
ulong inputSize;
uint type;
uint clientKid;
ptr<void> eventHandler;
@ -26,6 +26,8 @@ struct IpmiServer : RcBase {
struct Packet {
IpmiPacketInfo info;
lwpid_t clientTid;
Ref<IpmiSession> session;
kvector<std::byte> message;
};
@ -36,6 +38,7 @@ struct IpmiServer : RcBase {
slong serverTid{};
};
kmap<std::uint32_t, std::uint32_t> tidToClientTid;
kstring name;
ptr<void> serverImpl;
ptr<void> eventHandler;
@ -51,24 +54,36 @@ struct IpmiServer : RcBase {
};
struct IpmiClient : RcBase {
struct MessageQueue {
shared_cv messageCv;
kdeque<kvector<std::byte>> messages;
};
struct AsyncResponse {
uint methodId;
sint errorCode;
kvector<kvector<std::byte>> data;
};
kstring name;
ptr<void> clientImpl;
ptr<void> userData;
Ref<IpmiSession> session;
shared_mutex mutex;
shared_cv sessionCv;
sint pid;
kdeque<kvector<std::byte>> messages;
Process *process;
kdeque<MessageQueue> messageQueues;
kdeque<EventFlag> eventFlags;
shared_cv messageCv;
kdeque<AsyncResponse> asyncResponses;
explicit IpmiClient(kstring name) : name(std::move(name)) {}
};
struct IpmiSession : RcBase {
struct MessageResponse {
struct SyncResponse {
sint errorCode;
kvector<std::byte> data;
std::uint32_t callerTid;
kvector<kvector<std::byte>> data;
};
ptr<void> sessionImpl;
@ -77,9 +92,9 @@ struct IpmiSession : RcBase {
Ref<IpmiServer> server;
shared_mutex mutex;
shared_cv responseCv;
kdeque<MessageResponse> messageResponses;
kdeque<SyncResponse> syncResponses;
shared_cv connectCv;
bool expectedOutput = false; // TODO: verify
uint expectedOutput{0};
sint connectionStatus{0};
};
@ -108,20 +123,19 @@ static_assert(sizeof(IpmiCreateClientConfig) == 0x150);
struct IpmiBufferInfo {
ptr<void> data;
uint64_t capacity;
uint64_t size;
};
struct IpmiDataInfo {
ptr<void> data;
uint64_t size;
uint64_t capacity; //?
};
static_assert(sizeof(IpmiBufferInfo) == 0x10);
static_assert(sizeof(IpmiDataInfo) == 0x18);
// static_assert(sizeof(IpmiBufferInfo) == 0x18);
// static_assert(sizeof(IpmiDataInfo) == 0x10);
struct IpmiSyncMessageHeader {
struct [[gnu::packed]] IpmiSyncMessageHeader {
orbis::ptr<void> sessionImpl;
orbis::uint pid;
orbis::uint methodId;
@ -129,10 +143,18 @@ struct IpmiSyncMessageHeader {
orbis::uint numOutData;
};
struct [[gnu::packed]] IpmiAsyncMessageHeader {
orbis::ptr<void> sessionImpl;
orbis::uint methodId;
orbis::uint pid;
orbis::uint numInData;
};
static_assert(sizeof(IpmiSyncMessageHeader) == 0x18);
ErrorCode ipmiCreateClient(Process *proc, void *clientImpl, const char *name,
const IpmiCreateClientConfig &config, Ref<IpmiClient> &result);
const IpmiCreateClientConfig &config,
Ref<IpmiClient> &result);
ErrorCode ipmiCreateServer(Process *proc, void *serverImpl, const char *name,
const IpmiCreateServerConfig &config,
Ref<IpmiServer> &result);
@ -162,9 +184,10 @@ SysResult sysIpmiSessionRespondSync(Thread *thread, ptr<uint> result, uint kid,
SysResult sysIpmiClientInvokeAsyncMethod(Thread *thread, ptr<uint> result,
uint kid, ptr<void> params,
uint64_t paramsSz);
SysResult sysIpmiClientTryGetResult(Thread *thread, ptr<uint> result,
uint kid, ptr<void> params,
uint64_t paramsSz);
SysResult sysImpiSessionRespondAsync(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientTryGetResult(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientGetMessage(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientTryGetMessage(Thread *thread, ptr<uint> result, uint kid,
@ -181,10 +204,15 @@ SysResult sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result,
uint64_t paramsSz);
SysResult sysIpmiClientConnect(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiSessionGetClientAppId(Thread *thread, ptr<uint> result,
uint kid, ptr<void> params,
uint64_t paramsSz);
SysResult sysIpmiSessionGetUserData(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiServerGetName(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientGetName(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientWaitEventFlag(Thread *thread, ptr<uint> result, uint kid,
ptr<void> params, uint64_t paramsSz);
SysResult sysIpmiClientPollEventFlag(Thread *thread, ptr<uint> result, uint kid,

View file

@ -84,7 +84,7 @@ struct KNote {
~KNote();
};
struct EventEmitter {
struct EventEmitter : orbis::RcBase {
shared_mutex mutex;
std::set<KNote *, std::less<>, kallocator<KNote *>> notes;

View file

@ -1,6 +1,8 @@
#include "orbis-config.hpp"
#include <orbis/error.hpp>
#include <orbis/thread.hpp>
#include <orbis/time.hpp>
#include <orbis/module/ModuleHandle.hpp>
#include <orbis/thread/cpuset.hpp>
#include <orbis/thread/types.hpp>
namespace orbis {
using acl_type_t = sint;
@ -11,17 +13,24 @@ using cpuwhich_t = sint;
using cpulevel_t = sint;
using SceKernelModule = ModuleHandle;
struct Thread;
struct AuthInfo;
struct MemoryProtection;
struct ModuleInfo;
struct ModuleInfoEx;
struct KEvent;
struct timespec;
struct timesec;
struct timezone;
struct timeval;
struct Stat;
struct stack_t;
struct IoVec;
struct BatchMapEntry;
struct UContext;
struct SigSet;
struct SigAction;
struct SocketAddress;
SysResult nosys(Thread *thread);
@ -29,7 +38,7 @@ SysResult sys_exit(Thread *thread, sint status);
SysResult sys_fork(Thread *thread);
SysResult sys_read(Thread *thread, sint fd, ptr<void> buf, size_t nbyte);
SysResult sys_write(Thread *thread, sint fd, ptr<const void> buf, size_t nbyte);
SysResult sys_open(Thread *thread, ptr<char> path, sint flags, sint mode);
SysResult sys_open(Thread *thread, ptr<const char> path, sint flags, sint mode);
SysResult sys_close(Thread *thread, sint fd);
SysResult sys_wait4(Thread *thread, sint pid, ptr<sint> status, sint options,
ptr<struct rusage> rusage);
@ -125,15 +134,14 @@ SysResult sys_bind(Thread *thread, sint s, caddr_t name, sint namelen);
SysResult sys_setsockopt(Thread *thread, sint s, sint level, sint name,
caddr_t val, sint valsize);
SysResult sys_listen(Thread *thread, sint s, sint backlog);
SysResult sys_gettimeofday(Thread *thread, ptr<orbis::timeval> tp,
ptr<orbis::timezone> tzp);
SysResult sys_gettimeofday(Thread *thread, ptr<timeval> tp, ptr<timezone> tzp);
SysResult sys_getrusage(Thread *thread, sint who, ptr<struct rusage> rusage);
SysResult sys_getsockopt(Thread *thread, sint s, sint level, sint name,
caddr_t val, ptr<sint> avalsize);
SysResult sys_readv(Thread *thread, sint fd, ptr<IoVec> iovp, uint iovcnt);
SysResult sys_writev(Thread *thread, sint fd, ptr<IoVec> iovp, uint iovcnt);
SysResult sys_settimeofday(Thread *thread, ptr<struct timeval> tp,
ptr<orbis::timezone> tzp);
ptr<timezone> tzp);
SysResult sys_fchown(Thread *thread, sint fd, sint uid, sint gid);
SysResult sys_fchmod(Thread *thread, sint fd, sint mode);
SysResult sys_setreuid(Thread *thread, sint ruid, sint euid);
@ -230,8 +238,8 @@ SysResult sys_ktimer_settime(Thread *thread, sint timerid, sint flags,
SysResult sys_ktimer_gettime(Thread *thread, sint timerid,
ptr<struct itimerspec> value);
SysResult sys_ktimer_getoverrun(Thread *thread, sint timerid);
SysResult sys_nanosleep(Thread *thread, cptr<orbis::timespec> rqtp,
ptr<orbis::timespec> rmtp);
SysResult sys_nanosleep(Thread *thread, cptr<timespec> rqtp,
ptr<timespec> rmtp);
SysResult sys_ntp_gettime(Thread *thread, ptr<struct ntptimeval> ntvp);
SysResult sys_minherit(Thread *thread, ptr<void> addr, size_t len,
sint inherit);
@ -305,14 +313,14 @@ SysResult sys_jail(Thread *thread, ptr<struct jail> jail);
SysResult sys_nnpfs_syscall(Thread *thread, sint operation, ptr<char> a_pathP,
sint opcode, ptr<void> a_paramsP,
sint a_followSymlinks);
SysResult sys_sigprocmask(Thread *thread, sint how, ptr<uint64_t> set,
ptr<uint64_t> oset);
SysResult sys_sigsuspend(Thread *thread, ptr<const struct sigset> set);
SysResult sys_sigpending(Thread *thread, ptr<struct sigset> set);
SysResult sys_sigtimedwait(Thread *thread, ptr<const struct sigset> set,
SysResult sys_sigprocmask(Thread *thread, sint how, ptr<SigSet> set,
ptr<SigSet> oset);
SysResult sys_sigsuspend(Thread *thread, ptr<const SigSet> set);
SysResult sys_sigpending(Thread *thread, ptr<SigSet> set);
SysResult sys_sigtimedwait(Thread *thread, ptr<const SigSet> set,
ptr<struct siginfo> info,
ptr<const timespec> timeout);
SysResult sys_sigwaitinfo(Thread *thread, ptr<const struct sigset> set,
SysResult sys_sigwaitinfo(Thread *thread, ptr<const SigSet> set,
ptr<struct siginfo> info);
SysResult sys___acl_get_file(Thread *thread, ptr<char> path, acl_type_t type,
ptr<struct acl> aclp);
@ -412,13 +420,13 @@ SysResult sys_extattr_delete_link(Thread *thread, ptr<const char> path,
sint attrnamespace, ptr<const char> attrname);
SysResult sys___mac_execve(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv,
ptr<ptr<char>> envv, ptr<struct mac> mac_p);
SysResult sys_sigaction(Thread *thread, sint sig, ptr<struct sigaction> act,
ptr<struct sigaction> oact);
SysResult sys_sigreturn(Thread *thread, ptr<struct ucontext> sigcntxp);
SysResult sys_getcontext(Thread *thread, ptr<struct ucontext> ucp);
SysResult sys_setcontext(Thread *thread, ptr<struct ucontext> ucp);
SysResult sys_swapcontext(Thread *thread, ptr<struct ucontext> oucp,
ptr<struct ucontext> ucp);
SysResult sys_sigaction(Thread *thread, sint sig, ptr<SigAction> act,
ptr<SigAction> oact);
SysResult sys_sigreturn(Thread *thread, ptr<UContext> sigcntxp);
SysResult sys_getcontext(Thread *thread, ptr<UContext> ucp);
SysResult sys_setcontext(Thread *thread, ptr<UContext> ucp);
SysResult sys_swapcontext(Thread *thread, ptr<UContext> oucp,
ptr<UContext> ucp);
SysResult sys_swapoff(Thread *thread, ptr<const char> name);
SysResult sys___acl_get_link(Thread *thread, ptr<const char> path,
acl_type_t type, ptr<struct acl> aclp);
@ -428,10 +436,9 @@ SysResult sys___acl_delete_link(Thread *thread, ptr<const char> path,
acl_type_t type);
SysResult sys___acl_aclcheck_link(Thread *thread, ptr<const char> path,
acl_type_t type, ptr<struct acl> aclp);
SysResult sys_sigwait(Thread *thread, ptr<const struct sigset> set,
ptr<sint> sig);
SysResult sys_thr_create(Thread *thread, ptr<struct ucontext> ctxt,
ptr<slong> arg, sint flags);
SysResult sys_sigwait(Thread *thread, ptr<const SigSet> set, ptr<sint> sig);
SysResult sys_thr_create(Thread *thread, ptr<UContext> ctxt, ptr<slong> arg,
sint flags);
SysResult sys_thr_exit(Thread *thread, ptr<slong> state);
SysResult sys_thr_self(Thread *thread, ptr<slong> id);
SysResult sys_thr_kill(Thread *thread, slong id, sint sig);
@ -636,8 +643,9 @@ SysResult sys_evf_cancel(Thread *thread, sint id, uint64_t value,
ptr<sint> pNumWaitThreads);
SysResult sys_query_memory_protection(Thread *thread, ptr<void> address,
ptr<MemoryProtection> protection);
SysResult sys_batch_map(Thread *thread, sint unk, sint flags, ptr<BatchMapEntry> entries,
sint entriesCount, ptr<sint> processedCount);
SysResult sys_batch_map(Thread *thread, sint unk, sint flags,
ptr<BatchMapEntry> entries, sint entriesCount,
ptr<sint> processedCount);
SysResult sys_osem_create(Thread *thread, ptr<const char[32]> name, uint attrs,
sint initCount, sint maxCount);
SysResult sys_osem_delete(Thread *thread, sint id);
@ -746,15 +754,16 @@ SysResult sys_physhm_unlink(Thread *thread /* TODO */);
SysResult sys_resume_internal_hdd(Thread *thread /* TODO */);
SysResult sys_thr_suspend_ucontext(Thread *thread, lwpid_t tid);
SysResult sys_thr_resume_ucontext(Thread *thread, lwpid_t tid);
SysResult sys_thr_get_ucontext(Thread *thread, lwpid_t tid, ptr<UContext> context);
SysResult sys_thr_set_ucontext(Thread *thread, lwpid_t tid, ptr<UContext> context);
SysResult sys_thr_get_ucontext(Thread *thread, lwpid_t tid,
ptr<UContext> context);
SysResult sys_thr_set_ucontext(Thread *thread, lwpid_t tid,
ptr<UContext> context);
SysResult sys_set_timezone_info(Thread *thread /* TODO */);
SysResult sys_set_phys_fmem_limit(Thread *thread /* TODO */);
SysResult sys_utc_to_localtime(Thread *thread, int64_t time, int64_t *localtime,
orbis::timesec *_sec, int *_dst_sec);
timesec *_sec, int *_dst_sec);
SysResult sys_localtime_to_utc(Thread *thread, int64_t time, uint unk,
int64_t *ptime, orbis::timesec *_sec,
int *_dst_sec);
int64_t *ptime, timesec *_sec, int *_dst_sec);
SysResult sys_set_uevt(Thread *thread /* TODO */);
SysResult sys_get_cpu_usage_proc(Thread *thread /* TODO */);
SysResult sys_get_map_statistics(Thread *thread /* TODO */);

View file

@ -66,6 +66,7 @@ struct Process final {
bool isInSandbox = false;
EventEmitter event;
std::uint32_t sdkVersion = -1;
std::uint64_t nextTlsSlot = 1;
std::uint64_t lastTlsOffset = 0;
@ -81,6 +82,8 @@ struct Process final {
utils::kmap<void *, utils::kstring> namedObjNames;
utils::OwningIdMap<NamedObjInfo, uint, 65535, 1> namedObjIds;
utils::kmap<std::int32_t, SigAction> sigActions;
// Named memory ranges for debugging
utils::shared_mutex namedMemMutex;
utils::kmap<NamedMemoryRange, utils::kstring> namedMem;

View file

@ -12,6 +12,7 @@ struct timespec;
struct File;
struct MemoryProtection;
struct IoVec;
struct UContext;
struct ProcessOps {
SysResult (*mmap)(Thread *thread, caddr_t addr, size_t len, sint prot,
@ -64,7 +65,7 @@ struct ProcessOps {
uint64_t arg3);
SysResult (*dynlib_unload_prx)(Thread *thread, ModuleHandle handle);
SysResult (*thr_create)(Thread *thread, ptr<struct ucontext> ctxt,
SysResult (*thr_create)(Thread *thread, ptr<UContext> ctxt,
ptr<slong> arg, sint flags);
SysResult (*thr_new)(Thread *thread, ptr<thr_param> param, sint param_size);
SysResult (*thr_exit)(Thread *thread, ptr<slong> state);

View file

@ -19,5 +19,6 @@ enum class RegisterId {
rax,
rsp,
rflags,
rip,
};
} // namespace orbis

View file

@ -4,12 +4,16 @@
#include "orbis-config.hpp"
#include "types.hpp"
#include "../KernelAllocator.hpp"
#include "../ucontext.hpp"
#include "../utils/SharedCV.hpp"
#include "../utils/SharedMutex.hpp"
#include <atomic>
#include <thread>
namespace orbis {
struct Process;
struct Thread {
utils::shared_mutex mtx;
Process *tproc = nullptr;
@ -21,8 +25,14 @@ struct Thread {
uint64_t gsBase{};
char name[32]{};
uint64_t sigMask[4] = {0x7fff'ffff, 0};
SigSet sigMask = {0x7fff'ffff, ~0u, ~0u, ~0u};
utils::shared_mutex suspend_mtx;
utils::shared_cv suspend_cv;
kdeque<int> signalQueue;
kvector<UContext> sigReturns;
std::atomic<unsigned> suspended{0};
std::int64_t hostTid = -1;
lwpid_t tid = -1;
ThreadState state = ThreadState::INACTIVE;
std::thread handle;
@ -35,6 +45,10 @@ struct Thread {
// Print backtrace
void where();
void suspend();
void resume();
void sendSignal(int signo);
// FIXME: implement thread destruction
void incRef() {}
void decRef() {}

View file

@ -54,7 +54,20 @@ struct Stack {
};
struct SigSet {
ulong bits[2];
static constexpr auto min = 1;
static constexpr auto max = 128;
uint bits[4];
bool test(unsigned signal) const {
return (bits[(signal - 1) >> 5] & (1 << ((signal - 1) & 31))) != 0;
}
void set(unsigned signal) {
bits[(signal - 1) >> 5] |= (1 << ((signal - 1) & 31));
}
void clear(unsigned signal) {
bits[(signal - 1) >> 5] &= ~(1 << ((signal - 1) & 31));
}
};
struct UContext {
@ -67,4 +80,87 @@ struct UContext {
sint spare[4];
sint unk1[3];
};
static_assert(sizeof(UContext) == 0x500);
enum Signal {
kSigHup = 1,
kSigInt = 2,
kSigQuit = 3,
kSigIll = 4,
kSigTrap = 5,
kSigAbrt = 6,
kSigEmt = 7,
kSigFpe = 8,
kSigKill = 9,
kSigBus = 10,
kSigSegv = 11,
kSigSys = 12,
kSigPipe = 13,
kSigAlrm = 14,
kSigUrg = 16,
kSigStop = 17,
kSigTstp = 18,
kSigCont = 19,
kSigChld = 20,
kSigTtin = 21,
kSigTtou = 22,
kSigIo = 23,
kSigXcpu = 24,
kSigXfsz = 25,
kSigVtalrm = 26,
kSigProf = 27,
kSigWinch = 28,
kSigInfo = 29,
kSigUsr1 = 30,
kSigUsr2 = 31,
kSigThr = 32,
};
struct SigAction {
ptr<void(int32_t, void *, void *)> handler;
sint flags;
SigSet mask;
};
union SigVal {
sint integer;
ptr<void> pointer;
};
struct SigInfo {
sint signo;
sint errno_;
sint code;
sint pid;
slong uid;
sint status;
ptr<void> addr;
SigVal value;
union {
struct {
sint trapno;
} fault;
struct {
sint timerid;
sint overrun;
} timer;
struct {
sint mqd;
} mesgq;
struct {
slong band;
} poll;
struct {
slong spare1;
sint spare2[7];
} spare;
} reason;
};
} // namespace orbis

View file

@ -34,7 +34,7 @@ protected:
}
// Internal waiting function
void impl_wait(shared_mutex &mutex, unsigned _val,
int impl_wait(shared_mutex &mutex, unsigned _val,
std::uint64_t usec_timeout) noexcept;
// Try to notify up to _count threads
@ -43,14 +43,14 @@ protected:
public:
constexpr shared_cv() = default;
void wait(shared_mutex &mutex, std::uint64_t usec_timeout = -1) noexcept {
int wait(shared_mutex &mutex, std::uint64_t usec_timeout = -1) noexcept {
const unsigned _val = add_waiter();
if (!_val) {
return;
return 0;
}
mutex.unlock();
impl_wait(mutex, _val, usec_timeout);
return impl_wait(mutex, _val, usec_timeout);
}
// Wake one thread

View file

@ -20,7 +20,7 @@ class shared_mutex final {
void impl_lock_shared(unsigned val);
void impl_unlock_shared(unsigned old);
void impl_wait();
int impl_wait();
void impl_signal();
void impl_lock(unsigned val);
void impl_unlock(unsigned old);

View file

@ -4,8 +4,9 @@
#include "orbis/utils/Logs.hpp"
#include <chrono>
#include <sys/mman.h>
#include <sys/unistd.h>
#include <unistd.h>
#include <thread>
#include <csignal>
namespace orbis {
thread_local Thread *g_currentThread;
@ -13,7 +14,7 @@ thread_local Thread *g_currentThread;
KernelContext &g_context = *[]() -> KernelContext * {
// Allocate global shared kernel memory
// TODO: randomize for hardening and reduce size
auto ptr = mmap(reinterpret_cast<void *>(0x200'0000'0000), 0x1'0000'0000,
auto ptr = mmap(reinterpret_cast<void *>(0x200'0000'0000), 0x2'0000'0000,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (ptr == MAP_FAILED)
@ -32,7 +33,7 @@ KernelContext::KernelContext() {
pthread_mutexattr_destroy(&mtx_attr);
// std::printf("orbis::KernelContext initialized, addr=%p\n", this);
// std::printf("TSC frequency: %lu\n", getTscFreq());
std::printf("TSC frequency: %lu\n", getTscFreq());
}
KernelContext::~KernelContext() {}
@ -71,7 +72,7 @@ void KernelContext::deleteProcess(Process *proc) {
}
Process *KernelContext::findProcessById(pid_t pid) const {
for (std::size_t i = 0; i < 5; ++i) {
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) {
@ -87,7 +88,7 @@ Process *KernelContext::findProcessById(pid_t pid) const {
}
Process *KernelContext::findProcessByHostId(std::uint64_t pid) const {
for (std::size_t i = 0; i < 5; ++i) {
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) {
@ -215,6 +216,7 @@ KernelContext::getUmtxChainIndexed(int i, Thread *t, uint32_t flags,
if (flags & 1) {
pid = 0; // Process shared (TODO)
ORBIS_LOG_WARNING("Using process-shared umtx", t->tid, ptr, (p % 0x4000));
t->where();
}
auto n = p + pid;
if (flags & 1)
@ -238,5 +240,21 @@ void log_class_string<kstring>::format(std::string &out, const void *arg) {
}
} // namespace logs
void Thread::suspend() {
sendSignal(-1);
}
void Thread::resume() {
sendSignal(-2);
}
void Thread::sendSignal(int signo) {
std::lock_guard lock(mtx);
signalQueue.push_back(signo);
if (::tgkill(tproc->hostPid, hostTid, SIGUSR1) < 0) {
perror("tgkill");
}
}
void Thread::where() { tproc->ops->where(this); }
} // namespace orbis

View file

@ -21,8 +21,12 @@ void orbis::EventEmitter::emit(uint filter, uint fflags, intptr_t data) {
if (note->event.filter != filter) {
continue;
}
if (fflags != 0 && ((note->event.fflags & fflags) == 0)) {
continue;
if (fflags != 0) {
if ((note->event.fflags & fflags) == 0) {
continue;
}
note->event.fflags = fflags;
}
std::lock_guard lock(note->mutex);

View file

@ -33,6 +33,7 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode,
thread->evfIsCancelled = -1;
std::unique_lock lock(queueMtx);
int result = 0;
while (true) {
if (isDeleted) {
if (thread->evfIsCancelled == UINT64_MAX)
@ -77,10 +78,10 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode,
waitingThreads.emplace_back(waitingThread);
if (timeout) {
thread->sync_cv.wait(queueMtx, *timeout);
result = thread->sync_cv.wait(queueMtx, *timeout);
update_timeout();
} else {
thread->sync_cv.wait(queueMtx);
result = thread->sync_cv.wait(queueMtx);
}
if (thread->evfIsCancelled == UINT64_MAX) {
@ -89,7 +90,7 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode,
}
// TODO: update thread state
return {};
return ErrorCode{result};
}
orbis::ErrorCode orbis::EventFlag::tryWait(Thread *thread,
@ -137,7 +138,7 @@ std::size_t orbis::EventFlag::notify(NotifyType type, std::uint64_t bits) {
// TODO: update thread state
// release wait on waiter thread
thread->thread->sync_cv.notify_one(queueMtx);
thread->thread->sync_cv.notify_all(queueMtx);
return true;
};

View file

@ -3,6 +3,7 @@
#include "thread/Process.hpp"
#include "utils/Logs.hpp"
#include <chrono>
#include <sys/mman.h>
orbis::ErrorCode orbis::ipmiCreateClient(Process *proc, void *clientImpl,
const char *name,
@ -15,9 +16,10 @@ orbis::ErrorCode orbis::ipmiCreateClient(Process *proc, void *clientImpl,
client->clientImpl = clientImpl;
client->name = name;
client->pid = proc->pid;
client->process = proc;
client->userData = config.userData;
client->eventFlags.resize(32);
client->messageQueues.resize(32);
result = client;
return {};
}
@ -72,7 +74,7 @@ orbis::ErrorCode orbis::ipmiCreateSession(Thread *thread, void *sessionImpl,
session->client = conReq.client;
session->server = server;
conReq.client->session = session;
conReq.client->sessionCv.notify_all(conReq.client->mutex);
conReq.client->sessionCv.notify_one(conReq.client->mutex);
return {};
}
@ -241,7 +243,6 @@ orbis::SysResult orbis::sysIpmiServerReceivePacket(Thread *thread,
IpmiServer::Packet _packet;
ORBIS_LOG_ERROR(__FUNCTION__, server->name, ": waiting for packet");
{
std::lock_guard lock(server->mutex);
while (server->packets.empty()) {
@ -251,20 +252,39 @@ orbis::SysResult orbis::sysIpmiServerReceivePacket(Thread *thread,
_packet = std::move(server->packets.front());
server->packets.pop_front();
}
ORBIS_LOG_ERROR(__FUNCTION__, server->name, ": got packet");
if (_packet.info.type == 0x1) {
// on connection packet
for (auto &conn : server->connectionRequests) {
if ((ptr<void>)conn.clientTid == _packet.info.userData) {
if (conn.clientTid == _packet.info.inputSize) {
conn.serverTid = thread->tid;
_packet.info.userData = nullptr;
_packet.info.inputSize = 0;
break;
}
}
} else if ((_packet.info.type & ~(0x10 | 0x8000)) == 0x41) {
auto syncMessage = (IpmiSyncMessageHeader *)_packet.message.data();
ORBIS_LOG_ERROR(__FUNCTION__, server->name, syncMessage->methodId,
syncMessage->numInData, syncMessage->numOutData,
syncMessage->pid);
} else if ((_packet.info.type & ~0x10) == 0x43) {
auto asyncMessage = (IpmiAsyncMessageHeader *)_packet.message.data();
ORBIS_LOG_ERROR(__FUNCTION__, server->name, asyncMessage->methodId,
asyncMessage->numInData, asyncMessage->pid);
ORBIS_LOG_ERROR(__FUNCTION__, server->name,
*(std::uint64_t *)(*(long *)server->eventHandler + 0x18));
}
if (_params.bufferSize < _packet.message.size()) {
ORBIS_LOG_ERROR(__FUNCTION__, "too small buffer", _params.bufferSize,
_packet.message.size());
return ErrorCode::INVAL;
}
server->tidToClientTid[thread->tid] = _packet.clientTid;
ORBIS_RET_ON_ERROR(uwriteRaw((ptr<std::byte>)_params.buffer,
_packet.message.data(), _packet.message.size()));
_params.bufferSize = _packet.message.size();
@ -280,7 +300,6 @@ orbis::SysResult orbis::sysIpmiSendConnectResult(Thread *thread,
ptr<void> params,
uint64_t paramsSz) {
if (paramsSz != sizeof(sint)) {
ORBIS_LOG_ERROR(__FUNCTION__, "wrong param size");
return ErrorCode::INVAL;
}
@ -296,9 +315,9 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread,
uint64_t paramsSz) {
struct IpmiRespondParams {
sint errorCode;
uint32_t unk1;
ptr<IpmiBufferInfo> buffers;
uint32_t bufferCount;
ptr<IpmiBufferInfo> buffers;
uint32_t flags;
uint32_t padding;
};
@ -316,35 +335,37 @@ orbis::SysResult orbis::sysIpmiSessionRespondSync(Thread *thread,
IpmiRespondParams _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiRespondParams>(params)));
if (_params.bufferCount > 1) {
ORBIS_LOG_ERROR(__FUNCTION__, "unexpected buffers count");
return ErrorCode::INVAL;
}
kvector<kvector<std::byte>> buffers;
ORBIS_LOG_ERROR(__FUNCTION__, session->client->name);
thread->where();
if ((_params.flags & 1) || _params.bufferCount != 1) {
auto count = _params.bufferCount;
buffers.reserve(count);
for (uint32_t i = 0; i < count; ++i) {
IpmiBufferInfo _buffer;
ORBIS_RET_ON_ERROR(uread(_buffer, _params.buffers + i));
kvector<std::byte> data;
if (_params.errorCode == 0 && _params.bufferCount > 0 &&
session->expectedOutput) {
IpmiBufferInfo _buffer;
ORBIS_RET_ON_ERROR(uread(_buffer, _params.buffers));
data.resize(_buffer.size);
ORBIS_RET_ON_ERROR(ureadRaw(data.data(), _buffer.data, _buffer.size));
auto &bufferData = buffers.emplace_back();
bufferData.resize(_buffer.size);
ORBIS_RET_ON_ERROR(
ureadRaw(bufferData.data(), _buffer.data, _buffer.size));
}
}
std::lock_guard lock(session->mutex);
ORBIS_LOG_ERROR(__FUNCTION__, _params.errorCode);
std::uint32_t clientTid;
{
std::lock_guard serverLock(session->server->mutex);
clientTid = session->server->tidToClientTid.at(thread->tid);
}
session->messageResponses.push_front({
session->syncResponses.push_front({
.errorCode = _params.errorCode,
.data = std::move(data),
.callerTid = clientTid,
.data = std::move(buffers),
});
session->responseCv.notify_one(session->mutex);
session->responseCv.notify_all(session->mutex);
return uwrite(result, 0u);
}
orbis::SysResult orbis::sysIpmiClientInvokeAsyncMethod(Thread *thread,
@ -354,8 +375,8 @@ orbis::SysResult orbis::sysIpmiClientInvokeAsyncMethod(Thread *thread,
uint64_t paramsSz) {
struct IpmiAsyncCallParams {
uint32_t method;
uint32_t unkNotifee0;
uint64_t unkNotifee1;
uint32_t evfIndex;
uint64_t evfValue;
uint32_t numInData;
uint32_t padding1;
ptr<IpmiDataInfo> pInData;
@ -378,20 +399,121 @@ orbis::SysResult orbis::sysIpmiClientInvokeAsyncMethod(Thread *thread,
IpmiAsyncCallParams _params;
ORBIS_RET_ON_ERROR(uread(_params, (ptr<IpmiAsyncCallParams>)params));
ORBIS_LOG_TODO(__FUNCTION__, thread->tid, client->name, _params.method,
_params.unkNotifee0, _params.unkNotifee1, _params.numInData,
_params.padding1, _params.pInData, _params.pResult,
_params.flags);
thread->where();
if (_params.flags > 1) {
return ErrorCode::INVAL;
}
if (_params.unkNotifee0 != -1) {
client->eventFlags[_params.unkNotifee0].set(1);
}
std::lock_guard clientLock(client->mutex);
auto session = client->session;
if (session == nullptr) {
return ErrorCode::INVAL;
}
std::lock_guard sessionLock(session->mutex);
auto server = session->server;
if (server == nullptr) {
return ErrorCode::INVAL;
}
{
std::lock_guard serverLock(server->mutex);
std::size_t inSize = 0;
for (auto &data : std::span(_params.pInData, _params.numInData)) {
inSize += data.size;
}
auto size = sizeof(IpmiAsyncMessageHeader) + inSize +
_params.numInData * sizeof(uint32_t);
kvector<std::byte> message(size);
auto msg = new (message.data()) IpmiAsyncMessageHeader;
msg->sessionImpl = session->sessionImpl;
msg->pid = thread->tproc->pid;
msg->methodId = _params.method;
msg->numInData = _params.numInData;
auto bufLoc = std::bit_cast<char *>(msg + 1);
for (auto &data : std::span(_params.pInData, _params.numInData)) {
*std::bit_cast<uint32_t *>(bufLoc) = data.size;
bufLoc += sizeof(uint32_t);
ORBIS_RET_ON_ERROR(ureadRaw(bufLoc, data.data, data.size));
bufLoc += data.size;
}
uint type = 0x43;
if ((_params.flags & 1) == 0) {
type |= 0x10;
}
server->packets.push_back(
{{.type = type, .clientKid = kid}, 0, session, std::move(message)});
server->receiveCv.notify_one(server->mutex);
}
if (_params.evfIndex != -1 && _params.evfValue != 0) {
client->eventFlags[_params.evfIndex].set(_params.evfValue);
}
ORBIS_RET_ON_ERROR(uwrite(_params.pResult, 0));
return uwrite(result, 0u);
}
orbis::SysResult orbis::sysImpiSessionRespondAsync(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
uint64_t paramsSz) {
struct IpmiAsyncRespondParams {
uint method;
uint pid;
sint result;
uint32_t numOutData;
ptr<IpmiDataInfo> pOutData;
uint32_t unk2; // == 1
};
static_assert(sizeof(IpmiAsyncRespondParams) == 0x20);
if (paramsSz != sizeof(IpmiAsyncRespondParams)) {
return ErrorCode::INVAL;
}
auto session = thread->tproc->ipmiMap.get(kid).cast<IpmiSession>();
if (session == nullptr) {
return ErrorCode::INVAL;
}
auto client = session->client;
if (client == nullptr) {
return ErrorCode::INVAL;
}
IpmiAsyncRespondParams _params;
ORBIS_RET_ON_ERROR(uread(_params, (ptr<IpmiAsyncRespondParams>)params));
kvector<kvector<std::byte>> outData;
outData.reserve(_params.numOutData);
for (auto data : std::span(_params.pOutData, _params.numOutData)) {
auto &elem = outData.emplace_back();
elem.resize(data.size);
ORBIS_RET_ON_ERROR(ureadRaw(elem.data(), data.data, data.size));
}
std::lock_guard clientLock(client->mutex);
client->asyncResponses.push_back({
.methodId = _params.method,
.errorCode = _params.result,
.data = std::move(outData),
});
return uwrite(result, 0u);
}
orbis::SysResult orbis::sysIpmiClientTryGetResult(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
@ -421,19 +543,66 @@ orbis::SysResult orbis::sysIpmiClientTryGetResult(Thread *thread,
return ErrorCode::INVAL;
}
ORBIS_LOG_TODO(__FUNCTION__, thread->tid, client->name, _params.method,
_params.unk, _params.pResult, _params.numOutData,
_params.padding, _params.pOutData, _params.padding2);
thread->where();
ORBIS_RET_ON_ERROR(uwrite(_params.pResult, 0));
return uwrite(result, 0u);
while (true) {
{
std::lock_guard clientLock(client->mutex);
for (auto it = client->asyncResponses.begin();
it != client->asyncResponses.end(); ++it) {
if (it->methodId != _params.method) {
continue;
}
auto response = std::move(*it);
client->asyncResponses.erase(it);
ORBIS_RET_ON_ERROR(uwrite(_params.pResult, it->errorCode));
if (response.data.size() != _params.numOutData) {
ORBIS_LOG_ERROR(__FUNCTION__, "responses count mismatch",
response.data.size(), _params.numOutData);
}
for (std::size_t i = 0; i < response.data.size(); ++i) {
if (response.data.size() > _params.numOutData) {
ORBIS_LOG_ERROR(__FUNCTION__, "too many responses",
response.data.size(), _params.numOutData);
break;
}
IpmiBufferInfo _outData;
ORBIS_RET_ON_ERROR(uread(_outData, _params.pOutData + i));
auto &data = response.data[i];
if (_outData.capacity < data.size()) {
ORBIS_LOG_ERROR(__FUNCTION__, "too big response", _outData.capacity,
data.size());
continue;
}
_outData.size = data.size();
ORBIS_RET_ON_ERROR(
uwriteRaw(_outData.data, data.data(), data.size()));
ORBIS_RET_ON_ERROR(uwrite(_params.pOutData + i, _outData));
}
return uwrite(result, 0u);
}
}
std::this_thread::sleep_for(std::chrono::microseconds(200));
}
// return uwrite(result, 0x80020000 + static_cast<int>(ErrorCode::AGAIN));
}
orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
uint64_t paramsSz) {
struct SceIpmiClientGetArgs {
uint32_t unk; // 0
uint32_t queueIndex;
uint32_t padding;
ptr<std::byte> message;
ptr<uint64_t> pSize;
@ -456,23 +625,24 @@ orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
SceIpmiClientGetArgs _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientGetArgs>(params)));
ORBIS_LOG_ERROR(__FUNCTION__, client->name, client->messages.size(),
_params.unk, _params.padding, _params.message, _params.pSize,
_params.maxSize, _params.pTimeout);
std::lock_guard lock(client->mutex);
if (_params.queueIndex >= client->messageQueues.size()) {
return ErrorCode::INVAL;
}
auto &queue = client->messageQueues[_params.queueIndex];
using clock = std::chrono::high_resolution_clock;
clock::time_point timeoutPoint = clock::time_point::max();
if (_params.pTimeout != nullptr) {
std::uint32_t timeout{};
ORBIS_LOG_ERROR(__FUNCTION__, timeout);
ORBIS_RET_ON_ERROR(uread(timeout, _params.pTimeout));
timeoutPoint = clock::now() + std::chrono::microseconds(timeout);
}
if (client->messages.empty()) {
if (queue.messages.empty()) {
if (timeoutPoint != clock::time_point::max()) {
while (true) {
auto now = clock::now();
@ -484,9 +654,9 @@ orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
auto waitTime = std::chrono::duration_cast<std::chrono::microseconds>(
timeoutPoint - now);
client->messageCv.wait(client->mutex, waitTime.count());
queue.messageCv.wait(client->mutex, waitTime.count());
if (!client->messages.empty()) {
if (!queue.messages.empty()) {
now = clock::now();
if (now >= timeoutPoint) {
@ -503,13 +673,13 @@ orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
}
}
} else {
while (client->messages.empty()) {
client->messageCv.wait(client->mutex);
while (queue.messages.empty()) {
queue.messageCv.wait(client->mutex);
}
}
}
auto &message = client->messages.front();
auto &message = queue.messages.front();
if (_params.maxSize < message.size()) {
ORBIS_LOG_ERROR(__FUNCTION__, "too small buffer");
@ -520,7 +690,7 @@ orbis::SysResult orbis::sysIpmiClientGetMessage(Thread *thread,
ORBIS_RET_ON_ERROR(uwrite(_params.pSize, message.size()));
ORBIS_RET_ON_ERROR(
uwriteRaw(_params.message, message.data(), message.size()));
client->messages.pop_front();
queue.messages.pop_front();
return uwrite<uint>(result, 0);
}
@ -529,7 +699,7 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
ptr<void> params,
uint64_t paramsSz) {
struct SceIpmiClientTryGetArgs {
uint32_t unk; // 0
uint32_t queueIndex;
uint32_t padding;
ptr<std::byte> message;
ptr<uint64_t> pSize;
@ -548,18 +718,23 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
return ErrorCode::INVAL;
}
// ORBIS_LOG_ERROR(__FUNCTION__, client->name, client->messages.size());
SceIpmiClientTryGetArgs _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientTryGetArgs>(params)));
std::lock_guard lock(client->mutex);
if (client->messages.empty()) {
if (_params.queueIndex >= client->messageQueues.size()) {
return ErrorCode::INVAL;
}
auto &queue = client->messageQueues[_params.queueIndex];
if (queue.messages.empty()) {
return uwrite<uint>(result,
0x80020000 + static_cast<int>(ErrorCode::AGAIN));
}
auto &message = client->messages.front();
auto &message = queue.messages.front();
if (_params.maxSize < message.size()) {
ORBIS_LOG_ERROR(__FUNCTION__, "too small buffer");
@ -570,7 +745,7 @@ orbis::SysResult orbis::sysIpmiClientTryGetMessage(Thread *thread,
ORBIS_RET_ON_ERROR(uwrite(_params.pSize, message.size()));
ORBIS_RET_ON_ERROR(
uwriteRaw(_params.message, message.data(), message.size()));
client->messages.pop_front();
queue.messages.pop_front();
return uwrite<uint>(result, 0);
}
@ -579,7 +754,7 @@ orbis::SysResult orbis::sysIpmiSessionTrySendMessage(Thread *thread,
ptr<void> params,
uint64_t paramsSz) {
struct SceIpmiClientTrySendArgs {
uint32_t unk; // 0
uint32_t queueIndex;
uint32_t padding;
ptr<std::byte> message;
uint64_t size;
@ -609,12 +784,16 @@ orbis::SysResult orbis::sysIpmiSessionTrySendMessage(Thread *thread,
auto client = session->client;
std::lock_guard lockClient(client->mutex);
ORBIS_LOG_ERROR(__FUNCTION__, session->server->name, client->name,
client->messages.size(), _params.message, _params.size);
auto &message = client->messages.emplace_back();
if (_params.queueIndex >= client->messageQueues.size()) {
return ErrorCode::INVAL;
}
auto &queue = client->messageQueues[_params.queueIndex];
auto &message = queue.messages.emplace_back();
message.resize(_params.size);
ORBIS_RET_ON_ERROR(ureadRaw(message.data(), _params.message, _params.size));
client->messageCv.notify_one(client->mutex);
queue.messageCv.notify_all(client->mutex);
return uwrite<uint>(result, 0);
}
@ -640,11 +819,6 @@ orbis::SysResult orbis::sysIpmiClientDisconnect(Thread *thread,
ORBIS_RET_ON_ERROR(uread(_params, ptr<SceIpmiClientDisconnectArgs>(params)));
ORBIS_LOG_ERROR(__FUNCTION__, client->name, _params.status);
std::lock_guard lock(client->mutex);
auto &message = client->messages.front();
ORBIS_RET_ON_ERROR(uwrite(_params.status, 0));
return uwrite<uint>(result, 0);
}
@ -669,7 +843,8 @@ orbis::SysResult orbis::sysIpmiSessionGetClientPid(Thread *thread,
IpmiGetClientPidParams _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiGetClientPidParams>(params)));
ORBIS_RET_ON_ERROR(uwrite<uint32_t>(_params.pid, session->client->pid));
ORBIS_RET_ON_ERROR(
uwrite<uint32_t>(_params.pid, session->client->process->pid));
return uwrite<uint>(result, 0);
}
orbis::SysResult
@ -680,8 +855,8 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
uint32_t numInData;
uint32_t numOutData;
uint32_t unk;
ptr<IpmiBufferInfo> pInData;
ptr<IpmiDataInfo> pOutData;
ptr<IpmiDataInfo> pInData;
ptr<IpmiBufferInfo> pOutData;
ptr<sint> pResult;
uint32_t flags;
};
@ -705,23 +880,12 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
return ErrorCode::INVAL;
}
std::lock_guard clientLock(client->mutex);
auto session = client->session;
if (session == nullptr) {
// ORBIS_LOG_TODO(__FUNCTION__, "waiting for connection", client->name,
// _params.method);
// while (session == nullptr) {
// client->sessionCv.wait(client->mutex);
// session = client->session;
// }
return ErrorCode::INVAL;
}
ORBIS_LOG_ERROR(__FUNCTION__, client->name, "sync call", _params.method);
// thread->where();
std::lock_guard sessionLock(session->mutex);
auto server = session->server;
@ -732,23 +896,14 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
{
std::lock_guard serverLock(server->mutex);
// ORBIS_LOG_TODO("IPMI: invokeSyncMethod", client->name, _params.method,
// _params.numInData, _params.unk, _params.numOutData,
// _params.pInData, _params.pOutData, _params.pResult,
// _params.flags);
std::size_t inSize = 0;
for (auto &data : std::span(_params.pInData, _params.numInData)) {
inSize += data.size;
}
std::size_t outSize = 0;
for (auto &data : std::span(_params.pOutData, _params.numOutData)) {
outSize += data.size;
}
auto size = sizeof(IpmiSyncMessageHeader) + inSize + outSize +
_params.numInData * sizeof(uint32_t) +
_params.numOutData * sizeof(uint32_t);
auto headerSize = sizeof(IpmiSyncMessageHeader) + inSize +
_params.numInData * sizeof(uint32_t);
auto size = headerSize + _params.numOutData * sizeof(uint);
kvector<std::byte> message(size);
auto msg = new (message.data()) IpmiSyncMessageHeader;
@ -758,8 +913,6 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
msg->numInData = _params.numInData;
msg->numOutData = _params.numOutData;
ORBIS_LOG_TODO("IPMI: sync call", client->name, _params.method,
thread->tproc->pid);
auto bufLoc = std::bit_cast<char *>(msg + 1);
for (auto &data : std::span(_params.pInData, _params.numInData)) {
@ -770,51 +923,87 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
}
for (auto &data : std::span(_params.pOutData, _params.numOutData)) {
*std::bit_cast<uint32_t *>(bufLoc) = data.size;
bufLoc += sizeof(uint32_t) + data.size;
*std::bit_cast<uint32_t *>(bufLoc) = data.capacity;
bufLoc += sizeof(uint32_t);
}
uint type = 0x41;
if (_params.numInData == 1 && _params.numOutData == 1 &&
server->pid == thread->tproc->pid) {
if ((_params.flags & 1) == 0) {
type |= 0x10;
}
if ((_params.flags & 1) == 0) {
if (server->pid == thread->tproc->pid) {
type |= 0x8000;
}
session->expectedOutput = _params.numOutData > 0;
server->packets.push_back(
{{.type = type, .clientKid = kid}, std::move(message)});
server->receiveCv.notify_all(server->mutex);
{{.inputSize = headerSize, .type = type, .clientKid = kid},
thread->tid,
session,
std::move(message)});
server->receiveCv.notify_one(server->mutex);
}
while (session->messageResponses.empty()) {
IpmiSession::SyncResponse response;
while (true) {
session->responseCv.wait(session->mutex);
}
auto response = std::move(session->messageResponses.front());
session->messageResponses.pop_front();
bool found = false;
for (auto it = session->syncResponses.begin();
it != session->syncResponses.end(); ++it) {
if (it->callerTid != thread->tid) {
continue;
}
response = std::move(*it);
session->syncResponses.erase(it);
found = true;
break;
}
if (found) {
break;
}
}
if (response.errorCode != 0) {
thread->where();
}
ORBIS_RET_ON_ERROR(uwrite(_params.pResult, response.errorCode));
if (_params.numOutData > 0 && _params.pOutData->size < response.data.size()) {
return ErrorCode::INVAL;
if (response.data.size() != _params.numOutData) {
ORBIS_LOG_ERROR(__FUNCTION__, "responses amount mismatch",
response.data.size(), _params.numOutData);
}
if (_params.numOutData && _params.pOutData->size) {
ORBIS_RET_ON_ERROR(uwriteRaw(_params.pOutData->data, response.data.data(),
response.data.size()));
_params.pOutData->size = response.data.size();
for (std::size_t i = 0; i < response.data.size(); ++i) {
if (response.data.size() > _params.numOutData) {
ORBIS_LOG_ERROR(__FUNCTION__, "too many responses", response.data.size(),
_params.numOutData);
break;
}
IpmiBufferInfo _outData;
ORBIS_RET_ON_ERROR(uread(_outData, _params.pOutData + i));
auto &data = response.data[i];
if (_outData.capacity < data.size()) {
ORBIS_LOG_ERROR(__FUNCTION__, "too big response", _outData.capacity,
data.size());
continue;
}
ORBIS_LOG_ERROR(__FUNCTION__, i, _outData.data, _outData.capacity,
data.size());
_outData.size = data.size();
ORBIS_RET_ON_ERROR(uwriteRaw(_outData.data, data.data(), data.size()));
ORBIS_RET_ON_ERROR(uwrite(_params.pOutData + i, _outData));
}
ORBIS_LOG_TODO(__FUNCTION__, "sync message response", client->name,
_params.method, response.errorCode, response.data.size());
return uwrite<uint>(result, 0);
}
@ -822,10 +1011,10 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
uint kid, ptr<void> params,
uint64_t paramsSz) {
struct IpmiClientConnectParams {
ptr<void> arg0;
ptr<void> arg1;
ptr<void> userData;
ulong userDataLen;
ptr<sint> status;
ptr<void> arg3;
ptr<sint> arg3;
};
static_assert(sizeof(IpmiClientConnectParams) == 0x20);
@ -847,17 +1036,10 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
IpmiClientConnectParams _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiClientConnectParams>(params)));
ORBIS_LOG_ERROR(__FUNCTION__, client->name, "connect");
auto server = g_context.findIpmiServer(client->name);
if (server == nullptr) {
ORBIS_LOG_ERROR(__FUNCTION__, "waiting for server", client->name);
while (server == nullptr) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
server = g_context.findIpmiServer(client->name);
}
return SysResult::notAnError(ErrorCode::NOENT);
}
std::lock_guard clientLock(client->mutex);
@ -889,8 +1071,8 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
};
struct ConnectMessageHeader {
uint32_t pid;
uint32_t unk0;
uint32_t clientPid;
uint32_t clientKid;
QueueStats sync;
QueueStats async;
uint numEventFlag;
@ -903,34 +1085,49 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
static_assert(sizeof(ConnectMessageHeader) == 0x150);
struct ConnectFields {
uint unk0;
uint unk1;
};
kvector<std::byte> message{sizeof(ConnectMessageHeader) +
sizeof(ConnectFields)};
kvector<std::byte> message{
sizeof(ConnectMessageHeader) + sizeof(uint) +
std::max<std::size_t>(_params.userDataLen, 0x10)};
auto header = new (message.data()) ConnectMessageHeader{};
header->pid = thread->tproc->pid;
header->clientPid = thread->tproc->pid;
header->clientKid = kid;
server->packets.push_back(
{{
.userData = (ptr<void>)static_cast<ulong>(thread->tid),
.type = 1,
.clientKid = kid,
},
std::move(message)});
header->sync.maxOutstanding = 1;
header->sync.inDataSizeHardLimit = 0x10000;
header->sync.outDataSizeHardLimit = 0x10000;
header->async.maxOutstanding = 8;
header->async.inDataSizeHardLimit = 0x10000;
header->async.outDataSizeHardLimit = 0x10000;
header->numEventFlag = client->eventFlags.size();
header->numMsgQueue = client->messageQueues.size();
for (auto &size : header->msgQueueSize) {
size = 0x10000;
}
if (_params.userDataLen != 0) {
auto bufLoc = std::bit_cast<char *>(header + 1);
*std::bit_cast<uint *>(bufLoc) = _params.userDataLen;
ORBIS_RET_ON_ERROR(ureadRaw(bufLoc + sizeof(uint), _params.userData,
_params.userDataLen));
}
server->packets.push_back({{
.inputSize = static_cast<ulong>(thread->tid),
.type = 1,
.clientKid = kid,
},
0,
nullptr,
std::move(message)});
server->receiveCv.notify_one(server->mutex);
}
ORBIS_LOG_ERROR(__FUNCTION__, client->name, "connect: packet sent");
while (client->session == nullptr) {
client->sessionCv.wait(client->mutex);
}
ORBIS_LOG_ERROR(__FUNCTION__, client->name, "connect: session created");
ORBIS_RET_ON_ERROR(uwrite(_params.status, 0)); // TODO
{
@ -940,6 +1137,32 @@ orbis::SysResult orbis::sysIpmiClientConnect(Thread *thread, ptr<uint> result,
return uwrite(result, 0u);
}
orbis::SysResult orbis::sysIpmiSessionGetClientAppId(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
uint64_t paramsSz) {
struct IpmiGetUserDataParam {
ptr<uint> data;
};
if (paramsSz != sizeof(IpmiGetUserDataParam)) {
return ErrorCode::INVAL;
}
auto session =
dynamic_cast<IpmiSession *>(thread->tproc->ipmiMap.get(kid).get());
if (session == nullptr) {
return ErrorCode::INVAL;
}
IpmiGetUserDataParam _params;
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiGetUserDataParam>(params)));
ORBIS_RET_ON_ERROR(
uwrite(_params.data, session->client->process->appInfo.appId));
return uwrite<uint>(result, 0);
}
orbis::SysResult orbis::sysIpmiSessionGetUserData(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
@ -990,6 +1213,31 @@ orbis::SysResult orbis::sysIpmiServerGetName(Thread *thread, ptr<uint> result,
return uwrite<uint>(result, 0);
}
orbis::SysResult orbis::sysIpmiClientGetName(Thread *thread, ptr<uint> result,
uint kid, ptr<void> params,
uint64_t paramsSz) {
struct IpmiGetClientNameParams {
ptr<char> name;
};
if (paramsSz != sizeof(IpmiGetClientNameParams)) {
return ErrorCode::INVAL;
}
auto client = thread->tproc->ipmiMap.get(kid).cast<IpmiClient>();
if (client == nullptr) {
return ErrorCode::INVAL;
}
IpmiGetClientNameParams _param;
ORBIS_RET_ON_ERROR(uread(_param, ptr<IpmiGetClientNameParams>(params)));
ORBIS_RET_ON_ERROR(
uwriteRaw(_param.name, client->name.c_str(), client->name.size() + 1));
return uwrite<uint>(result, 0);
}
orbis::SysResult orbis::sysIpmiClientWaitEventFlag(Thread *thread,
ptr<uint> result, uint kid,
ptr<void> params,
@ -1015,10 +1263,6 @@ orbis::SysResult orbis::sysIpmiClientWaitEventFlag(Thread *thread,
return ErrorCode::INVAL;
}
ORBIS_LOG_TODO(__FUNCTION__, thread->tid, kid, client->name, _params.index,
_params.padding0, _params.patternSet, _params.mode,
_params.padding1, _params.pPatternSet, _params.pTimeout);
if (client->eventFlags.size() <= _params.index) {
return ErrorCode::INVAL;
}
@ -1030,17 +1274,20 @@ orbis::SysResult orbis::sysIpmiClientWaitEventFlag(Thread *thread,
}
auto &evf = client->eventFlags[_params.index];
auto waitResult =
evf.wait(thread, _params.mode, _params.patternSet, &resultTimeout);
auto waitResult = evf.wait(thread, _params.mode, _params.patternSet,
_params.pTimeout != 0 ? &resultTimeout : nullptr);
if (_params.pPatternSet != nullptr) {
ORBIS_RET_ON_ERROR(uwrite(_params.pPatternSet, thread->evfResultPattern));
}
// FIXME
// if (_params.pPatternSet != nullptr) {
// ORBIS_RET_ON_ERROR(uwrite(_params.pPatternSet, thread->evfResultPattern));
// }
ORBIS_RET_ON_ERROR(uwrite(result, 0u));
if (_params.pTimeout != nullptr) {
ORBIS_RET_ON_ERROR(uwrite(_params.pTimeout, resultTimeout));
}
if (waitResult == ErrorCode::TIMEDOUT) {
return SysResult::notAnError(ErrorCode::TIMEDOUT);
}
return waitResult;
}
@ -1072,10 +1319,6 @@ orbis::SysResult orbis::sysIpmiClientPollEventFlag(Thread *thread,
return ErrorCode::INVAL;
}
// ORBIS_LOG_TODO(__FUNCTION__, thread->tid, kid, client->name, _params.index,
// _params.padding0, _params.patternSet, _params.mode,
// _params.padding1, _params.pPatternSet);
if (client->eventFlags.size() <= _params.index) {
return ErrorCode::INVAL;
}
@ -1116,8 +1359,6 @@ orbis::SysResult orbis::sysIpmiSessionSetEventFlag(Thread *thread,
return ErrorCode::INVAL;
}
ORBIS_LOG_TODO(__FUNCTION__, session->client->name, _params.patternSet,
_params.index);
auto client = session->client;
if (client == nullptr) {
return ErrorCode::INVAL;

View file

@ -172,7 +172,7 @@ static orbis::SysResult doPltRelocation(orbis::Process *process,
return orbis::ErrorCode::INVAL;
}
*where = reinterpret_cast<std::uintptr_t>(defObj->base) + S;
*where = S ? reinterpret_cast<std::uintptr_t>(defObj->base) + S : 0;
}
return {};
}
@ -285,7 +285,7 @@ static orbis::SysResult doRelocation(orbis::Process *process,
if (defObj == nullptr) {
return orbis::ErrorCode::INVAL;
}
*where = reinterpret_cast<std::uintptr_t>(defObj->base) + S + A;
*where = S ? reinterpret_cast<std::uintptr_t>(defObj->base) + S + A : 0;
return {};
}
return {};
@ -295,7 +295,7 @@ static orbis::SysResult doRelocation(orbis::Process *process,
if (defObj == nullptr) {
return orbis::ErrorCode::INVAL;
}
*where32 = reinterpret_cast<std::uintptr_t>(defObj->base) + S + A - P;
*where32 = S ? reinterpret_cast<std::uintptr_t>(defObj->base) + S + A - P : 0;
return {};
}
// case kRelCopy:
@ -306,7 +306,7 @@ static orbis::SysResult doRelocation(orbis::Process *process,
if (defObj == nullptr) {
return orbis::ErrorCode::INVAL;
}
*where = reinterpret_cast<std::uintptr_t>(defObj->base) + S;
*where = S ? reinterpret_cast<std::uintptr_t>(defObj->base) + S : 0;
return {};
}
case kRelRelative:

View file

@ -47,7 +47,7 @@ static orbis::ErrorCode pipe_read(orbis::File *file, orbis::Uio *uio,
break;
}
file->event.emit(orbis::kEvFiltWrite);
pipe->event->emit(orbis::kEvFiltWrite);
return {};
}
@ -64,7 +64,7 @@ static orbis::ErrorCode pipe_write(orbis::File *file, orbis::Uio *uio,
cnt += vec.len;
}
file->event.emit(orbis::kEvFiltRead);
pipe->event->emit(orbis::kEvFiltRead);
pipe->cv.notify_one(file->mtx);
uio->resid -= cnt;
uio->offset += cnt;
@ -82,6 +82,8 @@ static orbis::FileOps pipe_ops = {
std::pair<orbis::Ref<orbis::Pipe>, orbis::Ref<orbis::Pipe>> orbis::createPipe() {
auto a = knew<Pipe>();
auto b = knew<Pipe>();
a->event = knew<EventEmitter>();
b->event = knew<EventEmitter>();
a->ops = &pipe_ops;
b->ops = &pipe_ops;
a->other = b;

View file

@ -1,15 +1,15 @@
#include "sys/sysproto.hpp"
orbis::SysResult orbis::sys_getcontext(Thread *thread,
ptr<struct ucontext> ucp) {
ptr<UContext> ucp) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_setcontext(Thread *thread,
ptr<struct ucontext> ucp) {
ptr<UContext> ucp) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_swapcontext(Thread *thread,
ptr<struct ucontext> oucp,
ptr<struct ucontext> ucp) {
ptr<UContext> oucp,
ptr<UContext> ucp) {
return ErrorCode::NOSYS;
}

View file

@ -1,6 +1,9 @@
#include "file.hpp"
#include "orbis/utils/Logs.hpp"
#include "stat.hpp"
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
orbis::SysResult orbis::sys_getdtablesize(Thread *thread) {
return ErrorCode::NOSYS;

View file

@ -1,6 +1,7 @@
#include "sys/sysproto.hpp"
#include "KernelContext.hpp"
#include "thread/Process.hpp"
orbis::SysResult orbis::sys_kenv(Thread *thread, sint what,
ptr<const char> name, ptr<char> value,

View file

@ -104,14 +104,20 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
return ErrorCode::BADF;
}
std::unique_lock lock(fd->event.mutex);
nodeIt->file = fd;
// if (change.filter == kEvFiltWrite) {
// nodeIt->triggered = true;
// kq->cv.notify_all(kq->mtx);
// }
fd->event.notes.insert(&*nodeIt);
if (auto eventEmitter = fd->event) {
std::unique_lock lock(eventEmitter->mutex);
// if (change.filter == kEvFiltWrite) {
// nodeIt->triggered = true;
// kq->cv.notify_all(kq->mtx);
// }
nodeIt->triggered = true;
eventEmitter->notes.insert(&*nodeIt);
kq->cv.notify_all(kq->mtx);
} else if (note.file->hostFd < 0) {
ORBIS_LOG_ERROR("Unimplemented event emitter", change.ident);
}
}
}
}
@ -156,13 +162,23 @@ static SysResult keventChange(KQueue *kq, KEvent &change, Thread *thread) {
(nodeIt->event.fflags & ~kNoteFFlagsMask) | (fflags & kNoteFFlagsMask);
if (change.fflags & kNoteTrigger) {
nodeIt->event.udata = change.udata;
nodeIt->triggered = true;
kq->cv.notify_all(kq->mtx);
}
} else if (change.filter == kEvFiltGraphicsCore ||
change.filter == kEvFiltDisplay || change.filter == kEvFiltRegEv) {
} else if (change.filter == kEvFiltGraphicsCore) {
nodeIt->triggered = true;
if (change.ident == 0x84) {
// clock change event
nodeIt->event.data |= 1000ull << 16; // clock
}
kq->cv.notify_all(kq->mtx);
} else if (change.filter == kEvFiltDisplay) {
if (change.ident != 0x51000100000000 && change.ident != 0x63010100000000) {
nodeIt->triggered = true;
kq->cv.notify_all(kq->mtx);
}
}
return {};
@ -233,7 +249,7 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
auto now = clock::now();
auto nowValue = now.time_since_epoch().count();
if (nowValue < nowValue + nsec) {
if (nowValue <= nowValue + nsec) {
timeoutPoint = now + std::chrono::nanoseconds(nsec);
}
}
@ -242,76 +258,101 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
std::vector<KEvent> result;
result.reserve(nevents);
ErrorCode errorCode{};
if (kq->notes.empty()) {
// ORBIS_LOG_ERROR(__FUNCTION__, "attempt to wait empty kqueue", fd,
// nevents, timeoutPoint.time_since_epoch().count()); thread->where();
// nevents,
// timeoutPoint.time_since_epoch().count());
// thread->where();
// return{};
// std::abort();
return {};
}
// ORBIS_LOG_TODO(__FUNCTION__, "kevent wait", fd);
while (true) {
bool waitHack = false;
bool canSleep = true;
std::lock_guard lock(kq->mtx);
for (auto it = kq->notes.begin(); it != kq->notes.end();) {
if (result.size() >= nevents) {
break;
}
auto &note = *it;
std::lock_guard lock(note.mutex);
{
std::lock_guard lock(kq->mtx);
for (auto it = kq->notes.begin(); it != kq->notes.end();) {
if (result.size() >= nevents) {
break;
}
if (!note.triggered) {
if (note.event.filter == kEvFiltRead) {
if (note.file->hostFd < 0 ||
isReadEventTriggered(note.file->hostFd)) {
note.triggered = true;
} else {
canSleep = false;
auto &note = *it;
bool erase = false;
{
std::lock_guard lock(note.mutex);
if (!note.triggered) {
if (note.event.filter == kEvFiltRead) {
if (note.file->hostFd >= 0 ) {
if (isReadEventTriggered(note.file->hostFd)) {
note.triggered = true;
} else {
canSleep = false;
}
}
} else if (note.event.filter == kEvFiltWrite) {
if (note.file->hostFd >= 0) {
if (isWriteEventTriggered(note.file->hostFd)) {
note.triggered = true;
} else {
canSleep = false;
}
}
}
}
} else if (note.event.filter == kEvFiltWrite) {
if (note.file->hostFd < 0 ||
isWriteEventTriggered(note.file->hostFd)) {
note.triggered = true;
} else {
canSleep = false;
if (note.enabled && note.triggered) {
result.push_back(note.event);
if (note.event.filter == kEvFiltGraphicsCore ||
note.event.filter == kEvFiltDisplay) {
waitHack = true;
}
if (note.event.flags & kEvDispatch) {
note.enabled = false;
}
if (note.event.flags & kEvOneshot) {
erase = true;
}
if (note.event.filter == kEvFiltRead || note.event.filter == kEvFiltWrite) {
note.triggered = false;
}
}
}
}
if (note.enabled && note.triggered) {
result.push_back(note.event);
if (note.event.filter == kEvFiltGraphicsCore ||
note.event.filter == kEvFiltDisplay) {
waitHack = true;
}
if (note.event.flags & kEvDispatch) {
note.enabled = false;
}
if (note.event.flags & kEvOneshot) {
if (erase) {
it = kq->notes.erase(it);
continue;
} else {
++it;
}
}
++it;
}
if (!result.empty()) {
// if (waitHack) {
// std::this_thread::sleep_for(std::chrono::milliseconds(3));
// std::this_thread::sleep_for(std::chrono::milliseconds(30));
// }
break;
}
if (timeoutPoint != clock::time_point::max()) {
std::lock_guard lock(kq->mtx);
auto now = clock::now();
if (now >= timeoutPoint) {
errorCode = ErrorCode::TIMEDOUT;
break;
}
@ -322,13 +363,27 @@ orbis::SysResult orbis::sys_kevent(Thread *thread, sint fd,
}
} else {
if (canSleep) {
std::lock_guard lock(kq->mtx);
kq->cv.wait(kq->mtx);
} else {
std::this_thread::sleep_for(std::chrono::microseconds(30));
}
}
}
// ORBIS_LOG_TODO(__FUNCTION__, "kevent wakeup", fd);
// for (auto evt : result) {
// ORBIS_LOG_TODO(__FUNCTION__,
// evt.ident,
// evt.filter,
// evt.flags,
// evt.fflags,
// evt.data,
// evt.udata
// );
// }
ORBIS_RET_ON_ERROR(
uwriteRaw(eventlist, result.data(), result.size() * sizeof(KEvent)));
thread->retval[0] = result.size();

View file

@ -1,4 +1,7 @@
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp"
orbis::SysResult orbis::sys_execve(Thread *thread, ptr<char> fname,
ptr<ptr<char>> argv, ptr<ptr<char>> envv) {

View file

@ -1,11 +1,11 @@
#include "KernelContext.hpp"
#include "sys/sysproto.hpp"
#include "thread/ProcessOps.hpp"
#include "utils/Logs.hpp"
#include <chrono>
#include <sys/resource.h>
#include <sys/wait.h>
#include <thread>
#include <unistd.h>
#include "thread/Process.hpp"
orbis::SysResult orbis::sys_exit(Thread *thread, sint status) {
if (auto exit = thread->tproc->ops->exit) {

View file

@ -1,5 +1,7 @@
#include "KernelContext.hpp"
#include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp"
#include <cstdlib>
#include <unistd.h>

View file

@ -1,5 +1,8 @@
#include "file.hpp"
#include "orbis/utils/Logs.hpp"
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "uio.hpp"
#include <sstream>
@ -39,11 +42,13 @@ orbis::SysResult orbis::sys_read(Thread *thread, sint fd, ptr<void> buf,
auto cnt = io.offset - file->nextOff;
file->nextOff = io.offset;
// ORBIS_LOG_ERROR(__FUNCTION__, fd, buf, nbyte, cnt);
thread->retval[0] = cnt;
return {};
}
orbis::SysResult orbis::sys_pread(Thread *thread, sint fd, ptr<void> buf,
size_t nbyte, off_t offset) {
// ORBIS_LOG_ERROR(__FUNCTION__, fd, buf, nbyte, offset);
Ref<File> file = thread->tproc->fileDescriptors.get(fd);
if (file == nullptr) {
return ErrorCode::BADF;

View file

@ -1,4 +1,5 @@
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "utils/Logs.hpp"
#include <thread>

View file

@ -1,4 +1,6 @@
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "utils/Logs.hpp"
#include <pipe.hpp>

View file

@ -1,4 +1,6 @@
#include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/Thread.hpp"
#include "utils/Logs.hpp"
orbis::SysResult orbis::sys_getpid(Thread *thread) {
@ -16,7 +18,10 @@ orbis::SysResult orbis::sys_getpgid(Thread *thread, pid_t pid) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_getsid(Thread *thread, pid_t pid) { return {}; }
orbis::SysResult orbis::sys_getuid(Thread *thread) { return ErrorCode::NOSYS; }
orbis::SysResult orbis::sys_getuid(Thread *thread) {
thread->retval[0] = 1;
return {};
}
orbis::SysResult orbis::sys_geteuid(Thread *thread) { return ErrorCode::NOSYS; }
orbis::SysResult orbis::sys_getgid(Thread *thread) { return ErrorCode::NOSYS; }
orbis::SysResult orbis::sys_getegid(Thread *thread) { return ErrorCode::NOSYS; }

View file

@ -1,4 +1,5 @@
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "utils/Logs.hpp"
namespace orbis {
@ -88,5 +89,5 @@ orbis::SysResult orbis::sys_getrlimit(Thread *thread, uint which,
}
orbis::SysResult orbis::sys_getrusage(Thread *thread, sint who,
ptr<struct rusage> rusage) {
return ErrorCode::NOSYS;
return {};
}

View file

@ -8,10 +8,16 @@
#include "orbis/time.hpp"
#include "osem.hpp"
#include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp"
#include "ucontext.hpp"
#include "uio.hpp"
#include "utils/Logs.hpp"
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <thread>
orbis::SysResult orbis::sys_netcontrol(Thread *thread, sint fd, uint op,
ptr<void> buf, uint nbuf) {
@ -63,24 +69,33 @@ 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);
if (op == 1) {
// set int
if (len != sizeof(uint32_t)) {
return ErrorCode::INVAL;
}
ORBIS_LOG_ERROR(__FUNCTION__, op, id, *(std::uint32_t *)value);
g_context.regMgrInt[id] = *(std::uint32_t *)value;
return {};
}
if (op == 2) {
// get int
if (len != sizeof(uint32_t)) {
return ErrorCode::INVAL;
}
if (id == 0x2010000) {
return uwrite((ptr<uint>)value, 0u);
}
if (id == 0x7802c000) {
return uwrite((ptr<uint>)value, 0u);
}
if (id == 0x78020500) {
return uwrite((ptr<uint>)value, 0u);
}
if (id == 0x78020b00) {
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;
return uwrite((ptr<uint>)value, 0u);
return {};
}
return uwrite((ptr<uint>)value, intValIt->second);
return {};
}
@ -93,6 +108,8 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
return ErrorCode::INVAL;
}
std::memset(value, 0, len);
ORBIS_LOG_ERROR(__FUNCTION__, op, id, len);
thread->where();
return {};
@ -319,8 +336,8 @@ orbis::SysResult orbis::sys_evf_trywait(Thread *thread, sint id,
}
auto result = evf->tryWait(thread, mode, patternSet);
ORBIS_LOG_TRACE(__FUNCTION__, evf->name, thread->tid, id, patternSet, mode,
pPatternSet, result);
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, evf->name, thread->tid, id,
patternSet, mode, pPatternSet, result);
if (pPatternSet != nullptr) {
ORBIS_RET_ON_ERROR(uwrite(pPatternSet, thread->evfResultPattern));
@ -670,7 +687,9 @@ orbis::SysResult orbis::sys_namedobj_delete(Thread *thread, uint id,
return {};
}
orbis::SysResult orbis::sys_set_vm_container(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
ORBIS_LOG_TODO(__FUNCTION__);
thread->where();
return {};
}
orbis::SysResult orbis::sys_debug_init(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
@ -956,7 +975,21 @@ orbis::SysResult orbis::sys_mdbg_service(Thread *thread, uint32_t op,
}
case 7: {
// TODO: read string from userspace
if (auto open = thread->tproc->ops->open) {
Ref<File> console;
auto result = open(thread, "/dev/console", 0, 0, &console);
if (!result.value() && console && console->ops->write) {
IoVec vec{.base = (char *)arg0, .len = std::strlen((char *)arg0)};
Uio uio{
.iov = &vec,
.iovcnt = 1,
};
if (console->ops->write(console.get(), &uio, thread) == ErrorCode{}) {
return {};
}
}
}
ORBIS_LOG_NOTICE("sys_mdbg_service", (char *)arg0);
break;
}
@ -1189,6 +1222,8 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
case 0x241:
return sysIpmiClientInvokeAsyncMethod(thread, result, kid, params,
paramsSz);
case 0x242:
return sysImpiSessionRespondAsync(thread, result, kid, params, paramsSz);
case 0x243:
return sysIpmiClientTryGetResult(thread, result, kid, params, paramsSz);
case 0x251:
@ -1205,10 +1240,14 @@ orbis::SysResult orbis::sys_ipmimgr_call(Thread *thread, uint op, uint kid,
return sysIpmiClientInvokeSyncMethod(thread, result, kid, params, paramsSz);
case 0x400:
return sysIpmiClientConnect(thread, result, kid, params, paramsSz);
case 0x463:
return sysIpmiSessionGetClientAppId(thread, result, kid, params, paramsSz);
case 0x468:
return sysIpmiSessionGetUserData(thread, result, kid, params, paramsSz);
case 0x46a:
return sysIpmiServerGetName(thread, result, kid, params, paramsSz);
case 0x46b:
return sysIpmiClientGetName(thread, result, kid, params, paramsSz);
case 0x490:
return sysIpmiClientWaitEventFlag(thread, result, kid, params, paramsSz);
case 0x491:
@ -1279,15 +1318,85 @@ orbis::SysResult orbis::sys_resume_internal_hdd(Thread *thread /* TODO */) {
}
orbis::SysResult orbis::sys_thr_suspend_ucontext(Thread *thread, lwpid_t tid) {
// ORBIS_LOG_FATAL(__FUNCTION__, tid);
auto t = tid == thread->tid ? thread
: thread->tproc->threadsMap.get(tid % 10000 - 1);
if (t == nullptr) {
return ErrorCode::SRCH;
}
while (true) {
unsigned prevSuspend = 0;
if (t->suspended.compare_exchange_strong(prevSuspend, 1)) {
t->suspend();
while (t->suspended == 0) {
std::this_thread::yield();
}
break;
}
if (t->suspended.compare_exchange_strong(prevSuspend, prevSuspend + 1)) {
break;
}
}
return {};
}
orbis::SysResult orbis::sys_thr_resume_ucontext(Thread *thread, lwpid_t tid) {
// ORBIS_LOG_FATAL(__FUNCTION__, tid);
auto t = tid == thread->tid ? thread
: thread->tproc->threadsMap.get(tid % 10000 - 1);
if (t == nullptr) {
return ErrorCode::SRCH;
}
while (true) {
unsigned prevSuspend = 1;
if (t->suspended.compare_exchange_strong(prevSuspend, 0)) {
t->resume();
while (t->suspended != 0) {
std::this_thread::yield();
}
break;
}
if (prevSuspend == 0) {
return ErrorCode::INVAL;
}
if (t->suspended.compare_exchange_strong(prevSuspend, prevSuspend - 1)) {
break;
}
}
return {};
}
orbis::SysResult orbis::sys_thr_get_ucontext(Thread *thread, lwpid_t tid,
ptr<UContext> context) {
// ORBIS_LOG_FATAL(__FUNCTION__, tid, context);
auto t = tid == thread->tid ? thread
: thread->tproc->threadsMap.get(tid % 10000 - 1);
if (t == nullptr) {
return ErrorCode::SRCH;
}
std::lock_guard lock(t->mtx);
if (t->suspended == 0) {
return ErrorCode::INVAL;
}
for (auto it = t->sigReturns.rbegin(); it != t->sigReturns.rend(); ++it) {
auto &savedContext = t->sigReturns.back();
if (savedContext.mcontext.rip < 0x100'0000'0000) {
return uwrite(context, savedContext);
}
}
ORBIS_LOG_FATAL(__FUNCTION__, "not found guest context");
*context = {};
return {};
}
orbis::SysResult orbis::sys_thr_set_ucontext(Thread *thread, lwpid_t tid,
@ -1296,7 +1405,9 @@ orbis::SysResult orbis::sys_thr_set_ucontext(Thread *thread, lwpid_t tid,
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_set_timezone_info(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
ORBIS_LOG_ERROR(__FUNCTION__);
thread->where();
return {};
}
orbis::SysResult orbis::sys_set_phys_fmem_limit(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
@ -1423,7 +1534,9 @@ orbis::SysResult orbis::sys_blockpool_batch(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_fdatasync(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;
ORBIS_LOG_TODO(__FUNCTION__);
thread->where();
return {};
}
orbis::SysResult orbis::sys_dynlib_get_list2(Thread *thread /* TODO */) {
return ErrorCode::NOSYS;

View file

@ -1,67 +1,90 @@
#include "KernelContext.hpp"
#include "sys/sysproto.hpp"
#include "thread/Process.hpp"
#include "thread/Thread.hpp"
#include "ucontext.hpp"
#include "utils/Logs.hpp"
#include <csignal>
orbis::SysResult orbis::sys_sigaction(Thread *thread, sint sig,
ptr<struct sigaction> act,
ptr<struct sigaction> oact) {
return {};
}
orbis::SysResult orbis::sys_sigprocmask(Thread *thread, sint how,
ptr<uint64_t> set, ptr<uint64_t> oset) {
if (oset) {
for (std::size_t i = 0; i < 2; ++i) {
oset[i] = thread->sigMask[i];
ptr<SigAction> act, ptr<SigAction> oact) {
ORBIS_LOG_WARNING(__FUNCTION__, sig, act, oact);
auto &sigAct = thread->tproc->sigActions[sig];
if (oact != nullptr) {
if (auto errc = uwrite(oact, sigAct); errc != orbis::ErrorCode{}) {
return errc;
}
}
if (act != nullptr) {
if (auto errc = uread(sigAct, act); errc != ErrorCode{}) {
return errc;
}
ORBIS_LOG_WARNING(__FUNCTION__, sigAct.handler, sigAct.flags,
sigAct.mask.bits[0], sigAct.mask.bits[1],
sigAct.mask.bits[2], sigAct.mask.bits[3]);
}
return {};
}
orbis::SysResult orbis::sys_sigprocmask(Thread *thread, sint how,
ptr<SigSet> set, ptr<SigSet> oset) {
if (oset) {
ORBIS_RET_ON_ERROR(uwrite(oset, thread->sigMask));
}
if (set) {
SigSet _set;
ORBIS_RET_ON_ERROR(uread(_set, set));
switch (how) {
case 0: // unblock
for (std::size_t i = 0; i < 2; ++i) {
thread->sigMask[i] &= ~set[i];
}
case 1: // block
for (std::size_t i = 0; i < 2; ++i) {
thread->sigMask[i] |= set[i];
for (std::size_t i = 0; i < 4; ++i) {
thread->sigMask.bits[i] |= _set.bits[i];
}
break;
case 2: // unblock
for (std::size_t i = 0; i < 4; ++i) {
thread->sigMask.bits[i] &= ~_set.bits[i];
}
break;
case 3: // set
for (std::size_t i = 0; i < 2; ++i) {
thread->sigMask[i] = set[i];
}
thread->sigMask = _set;
break;
default:
ORBIS_LOG_ERROR("sys_sigprocmask: unimplemented how", how);
thread->where();
return {};
return ErrorCode::INVAL;
}
thread->sigMask.clear(kSigKill);
thread->sigMask.clear(kSigStop);
}
return {};
}
orbis::SysResult orbis::sys_sigwait(Thread *thread,
ptr<const struct sigset> set,
orbis::SysResult orbis::sys_sigwait(Thread *thread, ptr<const SigSet> set,
ptr<sint> sig) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigtimedwait(Thread *thread,
ptr<const struct sigset> set,
orbis::SysResult orbis::sys_sigtimedwait(Thread *thread, ptr<const SigSet> set,
ptr<struct siginfo> info,
ptr<const timespec> timeout) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigwaitinfo(Thread *thread,
ptr<const struct sigset> set,
orbis::SysResult orbis::sys_sigwaitinfo(Thread *thread, ptr<const SigSet> set,
ptr<struct siginfo> info) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigpending(Thread *thread, ptr<struct sigset> set) {
orbis::SysResult orbis::sys_sigpending(Thread *thread, ptr<SigSet> set) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigsuspend(Thread *thread,
ptr<const struct sigset> set) {
orbis::SysResult orbis::sys_sigsuspend(Thread *thread, ptr<const SigSet> set) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigaltstack(Thread *thread, ptr<struct stack_t> ss,
@ -69,7 +92,7 @@ orbis::SysResult orbis::sys_sigaltstack(Thread *thread, ptr<struct stack_t> ss,
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_kill(Thread *thread, sint pid, sint signum) {
ORBIS_LOG_ERROR(__FUNCTION__, pid, signum);
ORBIS_LOG_WARNING(__FUNCTION__, pid, signum);
int hostPid = pid;
if (pid > 0) {
@ -81,10 +104,10 @@ orbis::SysResult orbis::sys_kill(Thread *thread, sint pid, sint signum) {
}
// TODO: wrap signal
int result = ::kill(hostPid, signum);
if (result < 0) {
return static_cast<ErrorCode>(errno);
}
// int result = ::kill(hostPid, signum);
// if (result < 0) {
// return static_cast<ErrorCode>(errno);
// }
return {};
}
@ -96,8 +119,18 @@ orbis::SysResult orbis::sys_sigqueue(Thread *thread, pid_t pid, sint signum,
ptr<void> value) {
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_sigreturn(Thread *thread,
ptr<struct ucontext> sigcntxp) {
return ErrorCode::NOSYS;
orbis::SysResult orbis::sys_sigreturn(Thread *thread, ptr<UContext> sigcntxp) {
ORBIS_LOG_WARNING(__FUNCTION__, sigcntxp);
// auto sigRet = thread->sigReturns.front();
// thread->sigReturns.erase(thread->sigReturns.begin(), thread->sigReturns.begin() + 1);
// writeRegister(thread->context, RegisterId::rip, sigRet.rip);
// writeRegister(thread->context, RegisterId::rsp, sigRet.rsp);
// ORBIS_LOG_ERROR(__FUNCTION__, sigRet.rip, sigRet.rsp);
return {};
}
orbis::SysResult orbis::nosys(Thread *thread) {
thread->sendSignal(kSigSys);
return{};
}
orbis::SysResult orbis::nosys(Thread *thread) { return ErrorCode::NOSYS; }

View file

@ -1,16 +1,20 @@
#include "KernelContext.hpp"
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "time.hpp"
#include "utils/Logs.hpp"
orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
uint namelen, ptr<void> old,
ptr<size_t> oldlenp, ptr<void> new_,
size_t newlen) {
namespace orbis {
SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
ptr<void> old, ptr<size_t> oldlenp, ptr<void> new_,
size_t newlen) {
enum sysctl_ctl { unspec, kern, vm, vfs, net, debug, hw, machdep, user };
enum sysctl_kern {
usrstack = 33,
proc = 14,
boottime = 21,
usrstack = 33,
arnd = 37,
// FIXME
@ -22,10 +26,12 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
rng_pseudo,
backup_restore_mode,
console,
init_safe_mode
init_safe_mode,
geom,
};
enum sysctl_hw {
ncpu = 3,
pagesize = 7,
// FIXME
@ -49,6 +55,8 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
tsc_freq = 1000,
liverpool,
bootparams,
idps,
openpsid_for_sys,
};
enum sysctl_machdep_liverpool {
@ -59,6 +67,10 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
is_main_on_standby = 1000,
};
enum sysctl_kern_geom {
updtfmt = 1000,
};
struct ProcInfo {
char data[0x448];
};
@ -139,9 +151,47 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
*(uint64_t *)old = 0;
return {};
}
if (name[0] == kern && name[1] == geom && name[2] == updtfmt) {
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
return ErrorCode::INVAL;
}
*(uint32_t *)old = 0;
return {};
}
}
if (namelen == 4) {
if (name[0] == kern && name[1] == proc && name[2] == 37) {
if (oldlenp && old && *oldlenp == 4) {
return uwrite(ptr<uint32_t>(old), ~0u);
}
}
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]);
if (process == nullptr) {
ORBIS_LOG_ERROR("get sdk version by pid: process not found", name[3],
thread->tproc->pid);
return ErrorCode::SRCH;
}
}
size_t oldlen;
ORBIS_RET_ON_ERROR(uread(oldlen, oldlenp));
if (oldlen < sizeof(uint32_t)) {
return ErrorCode::INVAL;
}
ORBIS_RET_ON_ERROR(uwrite(ptr<uint32_t>(old), process->sdkVersion));
ORBIS_LOG_ERROR("get sdk version by pid", name[3], process->sdkVersion);
return uwrite(oldlenp, sizeof(uint32_t));
}
if (name[0] == kern && name[1] == proc && name[2] == 1) {
ORBIS_LOG_ERROR("KERN_PROC_PROC 2");
@ -388,6 +438,31 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
dest[count++] = hw;
dest[count++] = config;
dest[count++] = optical_out;
} else if (searchName == "machdep.idps") {
if (*oldlenp < 2 * sizeof(uint32_t)) {
std::fprintf(stderr, " %s error\n", searchName.data());
return ErrorCode::INVAL;
}
dest[count++] = machdep;
dest[count++] = idps;
} else if (searchName == "kern.geom.updtfmt") {
if (*oldlenp < 3 * sizeof(uint32_t)) {
std::fprintf(stderr, " %s error\n", searchName.data());
return ErrorCode::INVAL;
}
dest[count++] = kern;
dest[count++] = geom;
dest[count++] = updtfmt;
} else if (searchName == "machdep.openpsid_for_sys") {
if (*oldlenp < 2 * sizeof(uint32_t)) {
std::fprintf(stderr, " %s error\n", searchName.data());
return ErrorCode::INVAL;
}
dest[count++] = machdep;
dest[count++] = openpsid_for_sys;
}
if (count == 0) {
@ -409,6 +484,19 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
case sysctl_ctl::kern:
switch (name[1]) {
case sysctl_kern::boottime: {
// FIXME: implement boottime support
if (*oldlenp < sizeof(timeval) || new_ != nullptr || newlen != 0) {
return ErrorCode::INVAL;
}
*oldlenp = sizeof(timeval);
*ptr<timeval>(old) = {
.tv_sec = 60,
.tv_usec = 0,
};
return {};
}
case sysctl_kern::usrstack: {
if (*oldlenp != 8 || new_ != nullptr || newlen != 0) {
return ErrorCode::INVAL;
@ -424,7 +512,7 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
return ErrorCode::INVAL;
}
*(uint32_t *)old = 1;
*(uint32_t *)old = 6;
return {};
case sysctl_kern::sdk_version: {
@ -432,8 +520,8 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
return ErrorCode::INVAL;
}
std::printf("Reporting SDK version %x\n", g_context.sdkVersion);
*(uint32_t *)old = g_context.sdkVersion;
std::printf("Reporting SDK version %x\n", thread->tproc->sdkVersion);
*(uint32_t *)old = thread->tproc->sdkVersion;
return {};
}
@ -501,6 +589,22 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
*(std::uint32_t *)old = 0;
return {};
case sysctl_kern::init_safe_mode:
if (old && oldlenp) {
ORBIS_LOG_ERROR("sysctl: get kern.init_safe_mode", oldlenp, new_,
newlen);
if (*oldlenp != 4) {
return ErrorCode::INVAL;
}
*(std::uint32_t *)old = g_context.safeMode;
}
if (new_ != nullptr && newlen == 4) {
ORBIS_LOG_ERROR("sysctl: set kern.init_safe_mode",
*(std::uint32_t *)new_, newlen);
}
return {};
default:
return ErrorCode::INVAL;
}
@ -550,6 +654,15 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
*(uint32_t *)old = 0x4000;
return {};
case sysctl_hw::ncpu:
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
} else {
*(uint32_t *)old = 7;
return {};
}
default:
break;
}
@ -562,13 +675,37 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
return ErrorCode::INVAL;
}
*(uint64_t *)old = g_context.getTscFreq();
if (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();
}
return {};
}
case sysctl_machdep::idps: {
if (*oldlenp != 16 || new_ != nullptr || newlen != 0) {
return ErrorCode::INVAL;
}
std::memset(old, 0, 16);
return uwrite<short>((short *)((char *)old + 4), 0x8401);
}
case sysctl_machdep::openpsid_for_sys: {
if (*oldlenp != 16 || new_ != nullptr || newlen != 0) {
return ErrorCode::INVAL;
}
std::memset(old, 0, 16);
return {};
}
default:
break;
}
}
case sysctl_ctl::user:
break;
}
@ -588,3 +725,29 @@ orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
thread->where();
return {};
}
} // namespace orbis
orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
uint namelen, ptr<void> old,
ptr<size_t> oldlenp, ptr<void> new_,
size_t newlen) {
auto result = kern_sysctl(thread, name, namelen, old, oldlenp, new_, newlen);
if (result.isError()) {
std::string concatName;
for (unsigned int i = 0; i < namelen; ++i) {
if (i != 0) {
concatName += '.';
}
concatName += std::to_string(name[i]);
}
std::size_t oldLen = oldlenp ? *oldlenp : 0;
ORBIS_LOG_TODO(__FUNCTION__, concatName, oldLen, new_, newlen);
thread->where();
}
return result;
}

View file

@ -1,7 +1,11 @@
#include "sys/sysproto.hpp"
#include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "ucontext.hpp"
orbis::SysResult orbis::sys_thr_create(Thread *thread,
ptr<struct ucontext> ctxt,
ptr<UContext> ctxt,
ptr<slong> arg, sint flags) {
if (auto thr_create = thread->tproc->ops->thr_create) {
return thr_create(thread, ctxt, arg, flags);

View file

@ -1,7 +1,7 @@
#include "sys/sysproto.hpp"
#include "time.hpp"
#include "utils/Logs.hpp"
#include <ctime>
#include <sys/time.h>
enum class ClockId {
Realtime = 0,

View file

@ -1,4 +1,8 @@
#include "file.hpp"
#include "sys/sysproto.hpp"
#include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "uio.hpp"
#include "utils/Logs.hpp"
#include <sys/socket.h>

View file

@ -1,5 +1,9 @@
#include "file.hpp"
#include "orbis-config.hpp"
#include "sys/sysproto.hpp"
#include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
orbis::SysResult orbis::sys_shm_open(Thread *thread, ptr<const char> path,
sint flags, mode_t mode) {

View file

@ -1,5 +1,6 @@
#include "orbis/utils/Logs.hpp"
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "time.hpp"
#include "umtx.hpp"
#include <chrono>

View file

@ -1,5 +1,8 @@
#include "stat.hpp"
#include "sys/sysproto.hpp"
#include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include "utils/Logs.hpp"
#include <filesystem>
#include <span>
@ -26,7 +29,7 @@ orbis::SysResult orbis::sys_statfs(Thread *thread, ptr<char> path,
return {};
}
std::strncpy(buf->f_fstypename, "exfatfs", sizeof(buf->f_fstypename));
std::strncpy(buf->f_fstypename, "unionfs", sizeof(buf->f_fstypename));
std::strncpy(buf->f_mntfromname, "/dev/super-hdd",
sizeof(buf->f_mntfromname));
std::strncpy(buf->f_mntonname, "/system/", sizeof(buf->f_mntonname));
@ -41,7 +44,7 @@ orbis::SysResult orbis::sys_fstatfs(Thread *thread, sint fd,
return {};
}
std::strncpy(buf->f_fstypename, "exfatfs", sizeof(buf->f_fstypename));
std::strncpy(buf->f_fstypename, "unionfs", sizeof(buf->f_fstypename));
std::strncpy(buf->f_mntfromname, "/dev/super-hdd",
sizeof(buf->f_mntfromname));
std::strncpy(buf->f_mntonname, "/system/", sizeof(buf->f_mntonname));
@ -66,7 +69,9 @@ orbis::SysResult orbis::sys_chroot(Thread *thread, ptr<char> path) {
thread->tproc->root = path;
return {};
}
orbis::SysResult orbis::sys_open(Thread *thread, ptr<char> path, sint flags,
// volatile bool debuggerPresent = false;
orbis::SysResult orbis::sys_open(Thread *thread, ptr<const char> path, sint flags,
sint mode) {
if (auto open = thread->tproc->ops->open) {
Ref<File> file;
@ -77,7 +82,17 @@ orbis::SysResult orbis::sys_open(Thread *thread, ptr<char> path, sint flags,
auto fd = thread->tproc->fileDescriptors.insert(file);
thread->retval[0] = fd;
// ORBIS_LOG_NOTICE(__FUNCTION__, path, flags, mode, fd);
// if (path == std::string_view{"/app0/psm/Application/resource/Sce.Vsh.ShellUI.SystemMessage.rco"}) {
ORBIS_LOG_SUCCESS(__FUNCTION__, thread->tid, path, flags, mode, fd);
if (path == std::string_view{"/app0/wave/wave1.fbxd"}) {
thread->where();
}
// while (debuggerPresent == false) {
// std::this_thread::sleep_for(std::chrono::seconds(1));
// }
// // thread->where();
// }
return {};
}
@ -85,6 +100,23 @@ orbis::SysResult orbis::sys_open(Thread *thread, ptr<char> path, sint flags,
}
orbis::SysResult orbis::sys_openat(Thread *thread, sint fd, ptr<char> path,
sint flag, mode_t mode) {
ORBIS_LOG_WARNING(__FUNCTION__, fd, path, flag, mode);
if (fd == -100) {
std::string cwd;
{
std::lock_guard lock(thread->tproc->mtx);
cwd = std::string(thread->tproc->cwd);
}
return sys_open(thread, (cwd + "/" + path).c_str(), flag, mode);
}
Ref<File> file = thread->tproc->fileDescriptors.get(fd);
if (file == nullptr) {
return ErrorCode::BADF;
}
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_mknod(Thread *thread, ptr<char> path, sint mode,
@ -171,6 +203,7 @@ orbis::SysResult orbis::sys_lseek(Thread *thread, sint fd, off_t offset,
return ErrorCode::NOSYS;
}
ORBIS_LOG_ERROR(__FUNCTION__, fd, offset, whence, file->nextOff);
thread->retval[0] = file->nextOff;
return {};
}
@ -195,6 +228,7 @@ orbis::SysResult orbis::sys_eaccess(Thread *thread, ptr<char> path,
return ErrorCode::NOSYS;
}
orbis::SysResult orbis::sys_stat(Thread *thread, ptr<char> path, ptr<Stat> ub) {
ORBIS_LOG_WARNING(__FUNCTION__, path);
Ref<File> file;
auto result = thread->tproc->ops->open(thread, path, 0, 0, &file);
if (result.isError()) {
@ -246,7 +280,21 @@ orbis::SysResult orbis::sys_lpathconf(Thread *thread, ptr<char> path,
}
orbis::SysResult orbis::sys_readlink(Thread *thread, ptr<char> path,
ptr<char> buf, size_t count) {
return ErrorCode::INVAL;
char _path[1024];
ORBIS_RET_ON_ERROR(ureadString(_path, sizeof(_path), path));
auto pathLen = std::strlen(_path);
if (pathLen > count) {
return ErrorCode::NAMETOOLONG;
}
Ref<File> file;
if (auto error = thread->tproc->ops->open(thread, path, 0, 0, &file); error.value()) {
return error;
}
ORBIS_RET_ON_ERROR(uwriteRaw(buf, _path, pathLen));
thread->retval[0] = pathLen;
return{};
}
orbis::SysResult orbis::sys_readlinkat(Thread *thread, sint fd, ptr<char> path,
ptr<char> buf, size_t bufsize) {
@ -390,6 +438,10 @@ orbis::SysResult orbis::sys_getdirentries(Thread *thread, sint fd,
if (result.isError())
return result;
for (auto &entry : std::span(entries + pos, next - pos)) {
ORBIS_LOG_ERROR(__FUNCTION__, entry.name);
}
if (basep) {
result = uwrite(basep, slong(file->nextOff));
if (result.isError())

View file

@ -1,6 +1,23 @@
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include <mutex>
#include <string>
orbis::SysResult orbis::sys___getcwd(Thread *thread, ptr<char> buf,
uint buflen) {
return ErrorCode::NOSYS;
std::string cwd;
{
std::lock_guard lock(thread->tproc->mtx);
cwd = std::string(thread->tproc->cwd);
}
if (buflen < cwd.size() + 1) {
return ErrorCode::NOMEM;
}
ORBIS_RET_ON_ERROR(uwriteRaw(buf, cwd.data(), cwd.size() + 1));
return{};
}

View file

@ -1,4 +1,7 @@
#include "sys/sysproto.hpp"
#include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
orbis::SysResult orbis::sys_mount(Thread *thread, ptr<char> type,
ptr<char> path, sint flags, caddr_t data) {

View file

@ -1,5 +1,8 @@
#include "error.hpp"
#include "sys/sysproto.hpp"
#include "thread/ProcessOps.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
orbis::SysResult orbis::sys_sbrk(Thread *, sint) {
return ErrorCode::OPNOTSUPP;

View file

@ -1,6 +1,8 @@
#include "sys/syscall.hpp"
#include "sys/sysentry.hpp"
#include "sys/sysproto.hpp"
#include "thread/Thread.hpp"
#include "thread/Process.hpp"
#include <algorithm>
#include <unordered_map>

View file

@ -33,7 +33,7 @@ uint UmtxChain::notify_one(const UmtxKey &key) {
if (it == sleep_queue.end())
return 0;
it->second.thr = nullptr;
it->second.cv.notify_one(mtx);
it->second.cv.notify_all(mtx);
this->erase(&*it);
return 1;
}
@ -62,7 +62,7 @@ orbis::ErrorCode orbis::umtx_unlock_umtx(Thread *thread, ptr<umtx> umtx,
orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
std::uint64_t ut, bool is32, bool ipc) {
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, addr, id, ut, is32);
ORBIS_LOG_NOTICE(__FUNCTION__, thread->tid, addr, id, ut, is32);
auto [chain, key, lock] = g_context.getUmtxChain0(thread, ipc, addr);
auto node = chain.enqueue(key, thread);
ErrorCode result = {};
@ -74,15 +74,15 @@ orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
if (val == id) {
if (ut + 1 == 0) {
while (true) {
node->second.cv.wait(chain.mtx);
if (node->second.thr != thread)
result = ErrorCode{node->second.cv.wait(chain.mtx)};
if (result != ErrorCode{} || node->second.thr != thread)
break;
}
} else {
auto start = std::chrono::steady_clock::now();
std::uint64_t udiff = 0;
while (true) {
node->second.cv.wait(chain.mtx, ut - udiff);
result = ErrorCode{node->second.cv.wait(chain.mtx, ut - udiff)};
if (node->second.thr != thread)
break;
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
@ -92,16 +92,21 @@ orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
result = ErrorCode::TIMEDOUT;
break;
}
if (result != ErrorCode{}) {
break;
}
}
}
}
ORBIS_LOG_NOTICE(__FUNCTION__, "wakeup", thread->tid, addr);
if (node->second.thr == thread)
chain.erase(node);
return result;
}
orbis::ErrorCode orbis::umtx_wake(Thread *thread, ptr<void> addr, sint n_wake) {
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, addr, n_wake);
ORBIS_LOG_NOTICE(__FUNCTION__, thread->tid, addr, n_wake);
auto [chain, key, lock] = g_context.getUmtxChain0(thread, true, addr);
std::size_t count = chain.sleep_queue.count(key);
if (key.pid == 0) {
@ -174,16 +179,14 @@ static ErrorCode do_lock_normal(Thread *thread, ptr<umutex> m, uint flags,
auto [chain, key, lock] = g_context.getUmtxChain1(thread, flags, m);
auto node = chain.enqueue(key, thread);
if (m->owner.compare_exchange_strong(owner, owner | kUmutexContested)) {
node->second.cv.wait(chain.mtx, ut);
if (node->second.thr == thread) {
error = ErrorCode{node->second.cv.wait(chain.mtx, ut)};
if (error == ErrorCode{} && node->second.thr == thread) {
error = ErrorCode::TIMEDOUT;
}
}
if (node->second.thr == thread)
chain.erase(node);
}
return {};
}
static ErrorCode do_lock_pi(Thread *thread, ptr<umutex> m, uint flags,
std::uint64_t ut, umutex_lock_mode mode) {
@ -219,7 +222,7 @@ static ErrorCode do_unlock_normal(Thread *thread, ptr<umutex> m, uint flags) {
return {};
}
if (count)
chain.notify_one(key);
chain.notify_all(key);
if (!ok)
return ErrorCode::INVAL;
return {};
@ -303,12 +306,24 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
return ErrorCode::INVAL;
}
if ((wflags & kCvWaitClockId) != 0 && ut + 1) {
ORBIS_LOG_FATAL("umtx_cv_wait: CLOCK_ID unimplemented", wflags);
std::abort();
ORBIS_LOG_WARNING("umtx_cv_wait: CLOCK_ID", wflags, cv->clockid);
// std::abort();
return ErrorCode::NOSYS;
}
if ((wflags & kCvWaitAbsTime) != 0 && ut + 1) {
ORBIS_LOG_FATAL("umtx_cv_wait: ABSTIME unimplemented", wflags);
ORBIS_LOG_WARNING("umtx_cv_wait: ABSTIME unimplemented", wflags);
auto now = std::chrono::time_point_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now())
.time_since_epoch()
.count();
if (now > ut) {
ut = 0;
} else {
ut = ut - now;
}
std::abort();
return ErrorCode::NOSYS;
}
@ -316,29 +331,39 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
auto [chain, key, lock] = g_context.getUmtxChain0(thread, cv->flags, cv);
auto node = chain.enqueue(key, thread);
if (!cv->has_waiters.load(std::memory_order::relaxed))
if (!cv->has_waiters.load(std::memory_order::relaxed)) {
cv->has_waiters.store(1, std::memory_order::relaxed);
}
ErrorCode result = umtx_unlock_umutex(thread, m);
if (result == ErrorCode{}) {
if (ut + 1 == 0) {
while (true) {
node->second.cv.wait(chain.mtx, ut);
if (node->second.thr != thread)
result = ErrorCode{node->second.cv.wait(chain.mtx, ut)};
if (result != ErrorCode{} || node->second.thr != thread) {
break;
}
}
} else {
auto start = std::chrono::steady_clock::now();
std::uint64_t udiff = 0;
while (true) {
node->second.cv.wait(chain.mtx, ut - udiff);
if (node->second.thr != thread)
ORBIS_LOG_WARNING(__FUNCTION__, ut - udiff);
result = ErrorCode{node->second.cv.wait(chain.mtx, ut - udiff)};
if (node->second.thr != thread) {
ORBIS_LOG_WARNING(__FUNCTION__, "wakeup");
break;
}
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - start)
.count();
if (udiff >= ut) {
result = ErrorCode::TIMEDOUT;
ORBIS_LOG_WARNING(__FUNCTION__, "timeout");
break;
}
if (result != ErrorCode{}) {
break;
}
}
@ -421,8 +446,8 @@ orbis::ErrorCode orbis::umtx_rw_rdlock(Thread *thread, ptr<urwlock> rwlock,
if (ut + 1 == 0) {
while (true) {
node->second.cv.wait(chain.mtx, ut);
if (node->second.thr != thread) {
result = ErrorCode{node->second.cv.wait(chain.mtx, ut)};
if (result != ErrorCode{} || node->second.thr != thread) {
break;
}
}
@ -430,7 +455,7 @@ orbis::ErrorCode orbis::umtx_rw_rdlock(Thread *thread, ptr<urwlock> rwlock,
auto start = std::chrono::steady_clock::now();
std::uint64_t udiff = 0;
while (true) {
node->second.cv.wait(chain.mtx, ut - udiff);
result = ErrorCode{node->second.cv.wait(chain.mtx, ut - udiff)};
if (node->second.thr != thread)
break;
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
@ -440,6 +465,10 @@ orbis::ErrorCode orbis::umtx_rw_rdlock(Thread *thread, ptr<urwlock> rwlock,
result = ErrorCode::TIMEDOUT;
break;
}
if (result != ErrorCode{}) {
break;
}
}
}
@ -517,8 +546,8 @@ orbis::ErrorCode orbis::umtx_rw_wrlock(Thread *thread, ptr<urwlock> rwlock,
if (ut + 1 == 0) {
while (true) {
node->second.cv.wait(chain.mtx, ut);
if (node->second.thr != thread) {
error = ErrorCode{node->second.cv.wait(chain.mtx, ut)};
if (error != ErrorCode{} || node->second.thr != thread) {
break;
}
}
@ -526,7 +555,7 @@ orbis::ErrorCode orbis::umtx_rw_wrlock(Thread *thread, ptr<urwlock> rwlock,
auto start = std::chrono::steady_clock::now();
std::uint64_t udiff = 0;
while (true) {
node->second.cv.wait(chain.mtx, ut - udiff);
error = ErrorCode{node->second.cv.wait(chain.mtx, ut - udiff)};
if (node->second.thr != thread)
break;
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
@ -536,6 +565,9 @@ orbis::ErrorCode orbis::umtx_rw_wrlock(Thread *thread, ptr<urwlock> rwlock,
error = ErrorCode::TIMEDOUT;
break;
}
if (error != ErrorCode{}) {
break;
}
}
}
@ -697,15 +729,15 @@ orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<usem> sem,
if (!sem->count) {
if (ut + 1 == 0) {
while (true) {
node->second.cv.wait(chain.mtx, ut);
if (node->second.thr != thread)
result = ErrorCode{node->second.cv.wait(chain.mtx, ut)};
if (result != ErrorCode{} || node->second.thr != thread)
break;
}
} else {
auto start = std::chrono::steady_clock::now();
std::uint64_t udiff = 0;
while (true) {
node->second.cv.wait(chain.mtx, ut - udiff);
result = ErrorCode{node->second.cv.wait(chain.mtx, ut - udiff)};
if (node->second.thr != thread)
break;
udiff = std::chrono::duration_cast<std::chrono::microseconds>(
@ -715,6 +747,9 @@ orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<usem> sem,
result = ErrorCode::TIMEDOUT;
break;
}
if (result != ErrorCode{}) {
break;
}
}
}
}

View file

@ -5,7 +5,7 @@
#include <unistd.h>
namespace orbis::utils {
void shared_cv::impl_wait(shared_mutex &mutex, unsigned _val,
int shared_cv::impl_wait(shared_mutex &mutex, unsigned _val,
std::uint64_t usec_timeout) noexcept {
// Not supposed to fail
if (!_val) {
@ -17,8 +17,10 @@ void shared_cv::impl_wait(shared_mutex &mutex, unsigned _val,
timeout.tv_nsec = (usec_timeout % 1000'000) * 1000;
timeout.tv_sec = (usec_timeout / 1000'000);
int result = 0;
while (true) {
auto result = syscall(SYS_futex, &m_value, FUTEX_WAIT, _val,
result = syscall(SYS_futex, &m_value, FUTEX_WAIT, _val,
usec_timeout + 1 ? &timeout : nullptr, 0, 0);
if (result < 0) {
result = errno;
@ -27,7 +29,7 @@ void shared_cv::impl_wait(shared_mutex &mutex, unsigned _val,
// Cleanup
const auto old = atomic_fetch_op(m_value, [&](unsigned &value) {
// Remove waiter if no signals
if (!(value & ~c_waiter_mask) && result != EAGAIN && result != EINTR) {
if (!(value & ~c_waiter_mask) && result != EAGAIN) {
value -= 1;
}
@ -43,22 +45,24 @@ void shared_cv::impl_wait(shared_mutex &mutex, unsigned _val,
// Lock is already acquired
if (old & c_locked_mask) {
return;
return 0;
}
// Wait directly (waiter has been added)
if (old & c_signal_mask) {
mutex.impl_wait();
return;
return mutex.impl_wait();
}
// Possibly spurious wakeup
if (result != EAGAIN && result != EINTR) {
if (result != EAGAIN) {
break;
}
_val = old;
}
mutex.lock();
return result;
}
void shared_cv::impl_wake(shared_mutex &mutex, int _count) noexcept {

View file

@ -48,7 +48,7 @@ void shared_mutex::impl_lock_shared(unsigned val) {
if ((old % c_sig) + c_one >= c_sig)
std::abort(); // "shared_mutex overflow"
impl_wait();
while (impl_wait() != 0) {}
lock_downgrade();
}
void shared_mutex::impl_unlock_shared(unsigned old) {
@ -60,7 +60,7 @@ void shared_mutex::impl_unlock_shared(unsigned old) {
impl_signal();
}
}
void shared_mutex::impl_wait() {
int shared_mutex::impl_wait() {
while (true) {
const auto [old, ok] = atomic_fetch_op(m_value, [](unsigned &value) {
if (value >= c_sig) {
@ -75,8 +75,15 @@ void shared_mutex::impl_wait() {
break;
}
syscall(SYS_futex, &m_value, FUTEX_WAIT, old, 0, 0, 0);
int result = syscall(SYS_futex, &m_value, FUTEX_WAIT, old, 0, 0, 0);
if (result < 0) {
result = errno;
}
if (result == EINTR) {
return EINTR;
}
}
return{};
}
void shared_mutex::impl_signal() {
m_value += c_sig;
@ -116,7 +123,7 @@ void shared_mutex::impl_lock(unsigned val) {
if ((old % c_sig) + c_one >= c_sig)
std::abort(); // "shared_mutex overflow"
impl_wait();
while (impl_wait() != 0) {}
}
void shared_mutex::impl_unlock(unsigned old) {
if (old - c_one >= c_err)
@ -148,7 +155,7 @@ void shared_mutex::impl_lock_upgrade() {
return;
}
impl_wait();
while (impl_wait() != 0) {}
}
bool shared_mutex::lock_forced(int count) {
if (count == 0)