mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-04 22:19:02 +00:00
[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:
parent
8791312d4f
commit
65e653f5ef
81 changed files with 2586 additions and 761 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ struct KNote {
|
|||
~KNote();
|
||||
};
|
||||
|
||||
struct EventEmitter {
|
||||
struct EventEmitter : orbis::RcBase {
|
||||
shared_mutex mutex;
|
||||
std::set<KNote *, std::less<>, kallocator<KNote *>> notes;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@ enum class RegisterId {
|
|||
rax,
|
||||
rsp,
|
||||
rflags,
|
||||
rip,
|
||||
};
|
||||
} // namespace orbis
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 ¬e = *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 ¬e = *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();
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include "KernelContext.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "thread/ProcessOps.hpp"
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <thread>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
#include "sys/sysproto.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "thread/Process.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
#include <pipe.hpp>
|
||||
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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 {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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{};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue