mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-06 06:55:09 +00:00
move orbis-kernel to kernel/orbis
This commit is contained in:
parent
7419457efd
commit
ecaf607a8f
120 changed files with 1 additions and 1 deletions
29
kernel/orbis/include/orbis/AppInfo.hpp
Normal file
29
kernel/orbis/include/orbis/AppInfo.hpp
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
#include <array>
|
||||
|
||||
namespace orbis {
|
||||
struct AppInfo {
|
||||
uint32_t appId;
|
||||
uint32_t unk0;
|
||||
uint32_t unk1;
|
||||
uint32_t appType;
|
||||
char titleId[10];
|
||||
uint16_t unk2;
|
||||
uint32_t unk3;
|
||||
slong unk4;
|
||||
slong unk5;
|
||||
slong unk6;
|
||||
slong unk7;
|
||||
slong unk8;
|
||||
};
|
||||
static_assert(sizeof(AppInfo) == 72);
|
||||
|
||||
struct AppInfoEx : AppInfo {
|
||||
slong unk9;
|
||||
slong unk10;
|
||||
};
|
||||
|
||||
static_assert(sizeof(AppInfoEx) == 88);
|
||||
} // namespace orbis
|
||||
25
kernel/orbis/include/orbis/AuthInfo.hpp
Normal file
25
kernel/orbis/include/orbis/AuthInfo.hpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct AuthInfo {
|
||||
uint64_t unk0;
|
||||
uint64_t caps[4];
|
||||
uint64_t attrs[4];
|
||||
uint64_t ucred[8];
|
||||
|
||||
bool isSyscoreProcess() const { return ucred[2] == 0x3800000000000007; }
|
||||
bool isShellUiProcess() const { return ucred[2] == 0x380000000000000f; }
|
||||
|
||||
bool hasUseHp3dPipeCapability() const {
|
||||
return ucred[2] == 0x3800000000000009;
|
||||
}
|
||||
|
||||
bool hasMmapSelfCapability() const { return ((ucred[4] >> 0x3a) & 1) != 1; }
|
||||
bool hasSystemCapability() const { return ((ucred[3] >> 0x3e) & 1) != 0; }
|
||||
bool hasSceProgramAttribute() const { return ((ucred[3] >> 0x1f) & 1) != 0; }
|
||||
};
|
||||
|
||||
static_assert(sizeof(AuthInfo) == 136);
|
||||
} // namespace orbis
|
||||
141
kernel/orbis/include/orbis/Budget.hpp
Normal file
141
kernel/orbis/include/orbis/Budget.hpp
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
#include "utils/BitSet.hpp"
|
||||
#include "utils/Rc.hpp"
|
||||
#include "utils/SharedMutex.hpp"
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
#include <string_view>
|
||||
|
||||
namespace orbis {
|
||||
enum class BudgetResource : uint32_t {
|
||||
Invalid,
|
||||
Dmem,
|
||||
Vmem,
|
||||
Fmem,
|
||||
CpuSet,
|
||||
File,
|
||||
Socket,
|
||||
Equeue,
|
||||
Pipe,
|
||||
Device,
|
||||
Thread,
|
||||
IpSocket,
|
||||
|
||||
_count,
|
||||
};
|
||||
|
||||
struct BudgetItem {
|
||||
uint64_t total;
|
||||
uint64_t used;
|
||||
};
|
||||
|
||||
struct BudgetInfo {
|
||||
BudgetResource resourceId;
|
||||
uint32_t flags; // ?
|
||||
BudgetItem item;
|
||||
};
|
||||
|
||||
static_assert(sizeof(BudgetInfo) == 0x18);
|
||||
|
||||
using BudgetInfoList =
|
||||
std::array<BudgetInfo, static_cast<int>(BudgetResource::_count)>;
|
||||
|
||||
class Budget : public RcBase {
|
||||
using BudgetList =
|
||||
std::array<BudgetItem, static_cast<int>(BudgetResource::_count)>;
|
||||
|
||||
public:
|
||||
enum class ProcessType : orbis::uint32_t {
|
||||
BigApp,
|
||||
MiniApp,
|
||||
System,
|
||||
NonGameMiniApp,
|
||||
_last = NonGameMiniApp
|
||||
};
|
||||
|
||||
Budget(std::string_view name, ProcessType pType,
|
||||
std::span<const BudgetInfo> budgets)
|
||||
: mProcessType(pType) {
|
||||
for (auto info : budgets) {
|
||||
if (info.resourceId == BudgetResource::Invalid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int resourceIndex = static_cast<int>(info.resourceId);
|
||||
|
||||
mUsed.set(resourceIndex);
|
||||
mList[resourceIndex] = info.item;
|
||||
}
|
||||
|
||||
std::strncpy(mName, name.data(), std::min(name.size(), sizeof(mName)));
|
||||
mName[sizeof(mName) - 1] = 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] BudgetItem get(BudgetResource resourceId) const {
|
||||
std::lock_guard lock(mMtx);
|
||||
return mList[static_cast<int>(resourceId)];
|
||||
}
|
||||
|
||||
[[nodiscard]] BudgetList getBudgetList() const {
|
||||
std::lock_guard lock(mMtx);
|
||||
return mList;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::pair<BudgetInfoList, int> getList() const {
|
||||
auto budgetList = getBudgetList();
|
||||
|
||||
BudgetInfoList result{};
|
||||
int count = 0;
|
||||
|
||||
for (auto resourceId : mUsed) {
|
||||
result[count].resourceId = static_cast<BudgetResource>(resourceId);
|
||||
result[count].item = budgetList[resourceId];
|
||||
count++;
|
||||
}
|
||||
|
||||
return {result, count};
|
||||
}
|
||||
|
||||
bool acquire(BudgetResource resourceId, std::uint64_t size = 1) {
|
||||
auto &budget = mList[static_cast<int>(resourceId)];
|
||||
|
||||
std::lock_guard lock(mMtx);
|
||||
|
||||
if (budget.used + size > budget.total) {
|
||||
return false;
|
||||
}
|
||||
|
||||
budget.used += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
void release(BudgetResource resourceId, std::uint64_t size) {
|
||||
auto &budget = mList[static_cast<int>(resourceId)];
|
||||
|
||||
std::lock_guard lock(mMtx);
|
||||
|
||||
if (size >= budget.used) {
|
||||
budget.used = 0;
|
||||
} else {
|
||||
budget.used -= size;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasResource(BudgetResource resourceId) const {
|
||||
return mUsed.test(static_cast<int>(resourceId));
|
||||
}
|
||||
|
||||
[[nodiscard]] int size() const { return mUsed.popcount(); }
|
||||
[[nodiscard]] ProcessType processType() const { return mProcessType; }
|
||||
|
||||
private:
|
||||
mutable shared_mutex mMtx;
|
||||
orbis::BitSet<static_cast<int>(BudgetResource::_count)> mUsed;
|
||||
ProcessType mProcessType{};
|
||||
BudgetList mList;
|
||||
char mName[32]{};
|
||||
};
|
||||
} // namespace orbis
|
||||
78
kernel/orbis/include/orbis/KernelAllocator.hpp
Normal file
78
kernel/orbis/include/orbis/KernelAllocator.hpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#pragma once
|
||||
|
||||
#include "utils/Rc.hpp"
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace orbis {
|
||||
inline namespace utils {
|
||||
void *kalloc(std::size_t size, std::size_t align);
|
||||
void kfree(void *ptr, std::size_t size);
|
||||
template <typename T> struct kallocator {
|
||||
using value_type = T;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using propagate_on_container_move_assignment = std::true_type;
|
||||
|
||||
constexpr kallocator() = default;
|
||||
template <typename U> constexpr kallocator(const kallocator<U> &) noexcept {}
|
||||
|
||||
template <typename U> struct rebind {
|
||||
using other = kallocator<U>;
|
||||
};
|
||||
|
||||
T *allocate(std::size_t n) {
|
||||
return static_cast<T *>(kalloc(sizeof(T) * n, alignof(T)));
|
||||
}
|
||||
|
||||
void deallocate(T *p, std::size_t n) { kfree(p, sizeof(T) * n); }
|
||||
|
||||
template <typename U>
|
||||
friend constexpr bool operator==(const kallocator &,
|
||||
const kallocator<U> &) noexcept {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
using kstring =
|
||||
std::basic_string<char, std::char_traits<char>, kallocator<char>>;
|
||||
template <typename T> using kvector = std::vector<T, kallocator<T>>;
|
||||
template <typename T> using kdeque = std::deque<T, kallocator<T>>;
|
||||
template <typename K, typename T, typename Cmp = std::less<>>
|
||||
using kmap = std::map<K, T, Cmp, kallocator<std::pair<const K, T>>>;
|
||||
template <typename K, typename T, typename Cmp = std::less<>>
|
||||
using kmultimap = std::multimap<K, T, Cmp, kallocator<std::pair<const K, T>>>;
|
||||
template <typename K, typename T, typename Hash = std::hash<K>,
|
||||
typename Pred = std::equal_to<K>>
|
||||
using kunmap =
|
||||
std::unordered_map<K, T, Hash, Pred, kallocator<std::pair<const K, T>>>;
|
||||
} // namespace utils
|
||||
|
||||
template <typename T, typename... Args>
|
||||
requires(std::is_constructible_v<T, Args...>)
|
||||
T *knew(Args &&...args) {
|
||||
auto loc = static_cast<T *>(utils::kalloc(sizeof(T), alignof(T)));
|
||||
auto res = std::construct_at(loc, std::forward<Args>(args)...);
|
||||
if constexpr (requires(T *t) { t->_total_size = sizeof(T); })
|
||||
res->_total_size = sizeof(T);
|
||||
return res;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
template <typename T> void kdelete(T *ptr) {
|
||||
auto total_size = sizeof(T);
|
||||
if constexpr (requires(T *t) { t->_total_size = sizeof(T); })
|
||||
total_size = ptr->_total_size;
|
||||
else
|
||||
static_assert(std::is_final_v<T>, "Uncertain type size");
|
||||
ptr->~T();
|
||||
utils::kfree(ptr, total_size);
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
} // namespace orbis
|
||||
260
kernel/orbis/include/orbis/KernelContext.hpp
Normal file
260
kernel/orbis/include/orbis/KernelContext.hpp
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
#pragma once
|
||||
#include "AppInfo.hpp"
|
||||
#include "Budget.hpp"
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "evf.hpp"
|
||||
#include "ipmi.hpp"
|
||||
#include "orbis/note.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 <cstdint>
|
||||
#include <mutex>
|
||||
#include <pthread.h>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
|
||||
namespace orbis {
|
||||
struct Process;
|
||||
struct Thread;
|
||||
|
||||
struct UmtxKey {
|
||||
// TODO: may contain a reference to a shared memory
|
||||
std::uintptr_t addr;
|
||||
orbis::pid_t pid;
|
||||
|
||||
auto operator<=>(const UmtxKey &) const = default;
|
||||
};
|
||||
|
||||
struct UmtxCond {
|
||||
Thread *thr;
|
||||
utils::shared_cv cv;
|
||||
|
||||
UmtxCond(Thread *thr) : thr(thr) {}
|
||||
};
|
||||
|
||||
struct UmtxChain {
|
||||
utils::shared_mutex mtx;
|
||||
using queue_type = utils::kmultimap<UmtxKey, UmtxCond>;
|
||||
queue_type sleep_queue;
|
||||
queue_type spare_queue;
|
||||
|
||||
std::pair<const UmtxKey, UmtxCond> *enqueue(UmtxKey &key, Thread *thr);
|
||||
void erase(std::pair<const UmtxKey, UmtxCond> *obj);
|
||||
queue_type::iterator erase(queue_type::iterator it);
|
||||
uint notify_one(const UmtxKey &key);
|
||||
uint notify_all(const UmtxKey &key);
|
||||
uint notify_n(const UmtxKey &key, sint count);
|
||||
};
|
||||
|
||||
enum class FwType : std::uint8_t {
|
||||
Unknown,
|
||||
Ps4,
|
||||
Ps5,
|
||||
};
|
||||
|
||||
struct RcAppInfo : RcBase, AppInfoEx {
|
||||
orbis::uint32_t appState = 0;
|
||||
};
|
||||
|
||||
class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final {
|
||||
public:
|
||||
KernelContext();
|
||||
~KernelContext();
|
||||
|
||||
Process *createProcess(pid_t pid);
|
||||
void deleteProcess(Process *proc);
|
||||
Process *findProcessById(pid_t pid) const;
|
||||
Process *findProcessByHostId(std::uint64_t pid) const;
|
||||
|
||||
utils::LinkedNode<Process> *getProcessList() { return m_processes; }
|
||||
|
||||
long allocatePid() {
|
||||
std::lock_guard lock(m_thread_id_mtx);
|
||||
return m_thread_id_map.emplace(0).first;
|
||||
}
|
||||
|
||||
long getTscFreq();
|
||||
|
||||
void *kalloc(std::size_t size,
|
||||
std::size_t align = __STDCPP_DEFAULT_NEW_ALIGNMENT__);
|
||||
void kfree(void *ptr, std::size_t size);
|
||||
|
||||
std::pair<EventFlag *, bool> createEventFlag(utils::kstring name,
|
||||
std::int32_t flags,
|
||||
std::uint64_t initPattern) {
|
||||
std::lock_guard lock(m_evf_mtx);
|
||||
|
||||
auto [it, inserted] = m_event_flags.try_emplace(std::move(name), nullptr);
|
||||
if (inserted) {
|
||||
it->second = knew<EventFlag>(flags, initPattern);
|
||||
std::strncpy(it->second->name, it->first.c_str(), 32);
|
||||
}
|
||||
|
||||
return {it->second.get(), inserted};
|
||||
}
|
||||
|
||||
Ref<EventFlag> findEventFlag(std::string_view name) {
|
||||
std::lock_guard lock(m_evf_mtx);
|
||||
|
||||
if (auto it = m_event_flags.find(name); it != m_event_flags.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<Semaphore *, bool> createSemaphore(utils::kstring name,
|
||||
std::uint32_t attrs,
|
||||
std::int32_t initCount,
|
||||
std::int32_t maxCount) {
|
||||
std::lock_guard lock(m_sem_mtx);
|
||||
auto [it, inserted] = m_semaphores.try_emplace(std::move(name), nullptr);
|
||||
if (inserted) {
|
||||
it->second = knew<Semaphore>(attrs, initCount, maxCount);
|
||||
}
|
||||
|
||||
return {it->second.get(), inserted};
|
||||
}
|
||||
|
||||
Ref<Semaphore> findSemaphore(std::string_view name) {
|
||||
std::lock_guard lock(m_sem_mtx);
|
||||
if (auto it = m_semaphores.find(name); it != m_semaphores.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::pair<Ref<IpmiServer>, ErrorCode> createIpmiServer(utils::kstring name) {
|
||||
std::lock_guard lock(m_sem_mtx);
|
||||
auto [it, inserted] = mIpmiServers.try_emplace(std::move(name), nullptr);
|
||||
|
||||
if (!inserted) {
|
||||
return {it->second, ErrorCode::EXIST};
|
||||
}
|
||||
|
||||
it->second = knew<IpmiServer>(it->first);
|
||||
|
||||
if (it->second == nullptr) {
|
||||
mIpmiServers.erase(it);
|
||||
return {nullptr, ErrorCode::NOMEM};
|
||||
}
|
||||
|
||||
return {it->second, {}};
|
||||
}
|
||||
|
||||
Ref<IpmiServer> findIpmiServer(std::string_view name) {
|
||||
std::lock_guard lock(m_sem_mtx);
|
||||
if (auto it = mIpmiServers.find(name); it != mIpmiServers.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
std::tuple<utils::kmap<utils::kstring, char[128]> &,
|
||||
std::unique_lock<shared_mutex>>
|
||||
getKernelEnv() {
|
||||
std::unique_lock lock(m_kenv_mtx);
|
||||
return {m_kenv, std::move(lock)};
|
||||
}
|
||||
|
||||
void setKernelEnv(std::string_view key, std::string_view value) {
|
||||
auto &kenvValue = m_kenv[utils::kstring(key)];
|
||||
auto len = std::min(sizeof(kenvValue) - 1, value.size());
|
||||
std::memcpy(kenvValue, value.data(), len);
|
||||
kenvValue[len] = '0';
|
||||
}
|
||||
|
||||
enum {
|
||||
c_golden_ratio_prime = 2654404609u,
|
||||
c_umtx_chains = 512,
|
||||
c_umtx_shifts = 23,
|
||||
};
|
||||
|
||||
// Use getUmtxChain0 or getUmtxChain1
|
||||
std::tuple<UmtxChain &, UmtxKey, std::unique_lock<shared_mutex>>
|
||||
getUmtxChainIndexed(int i, Thread *t, uint32_t flags, void *ptr);
|
||||
|
||||
// Internal Umtx: Wait/Cv/Sem
|
||||
auto getUmtxChain0(Thread *t, uint32_t flags, void *ptr) {
|
||||
return getUmtxChainIndexed(0, t, flags, ptr);
|
||||
}
|
||||
|
||||
// Internal Umtx: Mutex/Umtx/Rwlock
|
||||
auto getUmtxChain1(Thread *t, uint32_t flags, void *ptr) {
|
||||
return getUmtxChainIndexed(1, t, flags, ptr);
|
||||
}
|
||||
|
||||
Ref<EventEmitter> deviceEventEmitter;
|
||||
Ref<RcBase> shmDevice;
|
||||
Ref<RcBase> dmemDevice;
|
||||
Ref<RcBase> blockpoolDevice;
|
||||
Ref<RcBase> gpuDevice;
|
||||
Ref<RcBase> dceDevice;
|
||||
shared_mutex gpuDeviceMtx;
|
||||
uint sdkVersion{};
|
||||
uint fwSdkVersion{};
|
||||
uint safeMode{};
|
||||
utils::RcIdMap<RcBase, sint, 4097, 1> ipmiMap;
|
||||
RcIdMap<RcAppInfo> appInfos;
|
||||
RcIdMap<Budget, sint, 4097, 1> budgets;
|
||||
Ref<Budget> processTypeBudgets[4];
|
||||
|
||||
shared_mutex regMgrMtx;
|
||||
kmap<std::uint32_t, std::uint32_t> regMgrInt;
|
||||
std::vector<std::tuple<std::uint8_t *, size_t>> dialogs{};
|
||||
|
||||
FwType fwType = FwType::Unknown;
|
||||
bool isDevKit = false;
|
||||
|
||||
Ref<Budget> createProcessTypeBudget(Budget::ProcessType processType,
|
||||
std::string_view name,
|
||||
std::span<const BudgetInfo> items) {
|
||||
auto budget = orbis::knew<orbis::Budget>(name, processType, items);
|
||||
processTypeBudgets[static_cast<int>(processType)] =
|
||||
orbis::knew<orbis::Budget>(name, processType, items);
|
||||
return budget;
|
||||
}
|
||||
|
||||
Ref<Budget> getProcessTypeBudget(Budget::ProcessType processType) {
|
||||
return processTypeBudgets[static_cast<int>(processType)];
|
||||
}
|
||||
|
||||
private:
|
||||
shared_mutex m_heap_mtx;
|
||||
shared_mutex m_heap_map_mtx;
|
||||
void *m_heap_next = this + 1;
|
||||
|
||||
utils::kmultimap<std::size_t, void *> m_free_heap;
|
||||
utils::kmultimap<std::size_t, void *> m_used_node;
|
||||
|
||||
UmtxChain m_umtx_chains[2][c_umtx_chains]{};
|
||||
|
||||
std::atomic<long> m_tsc_freq{0};
|
||||
|
||||
shared_mutex m_thread_id_mtx;
|
||||
OwningIdMap<char, long, 256, 0> m_thread_id_map;
|
||||
mutable shared_mutex m_proc_mtx;
|
||||
utils::LinkedNode<Process> *m_processes = nullptr;
|
||||
|
||||
shared_mutex m_evf_mtx;
|
||||
utils::kmap<utils::kstring, Ref<EventFlag>> m_event_flags;
|
||||
|
||||
shared_mutex m_sem_mtx;
|
||||
utils::kmap<utils::kstring, Ref<Semaphore>> m_semaphores;
|
||||
|
||||
shared_mutex mIpmiServerMtx;
|
||||
utils::kmap<utils::kstring, Ref<IpmiServer>> mIpmiServers;
|
||||
|
||||
shared_mutex m_kenv_mtx;
|
||||
utils::kmap<utils::kstring, char[128]> m_kenv; // max size: 127 + '\0'
|
||||
};
|
||||
|
||||
extern KernelContext &g_context;
|
||||
} // namespace orbis
|
||||
9
kernel/orbis/include/orbis/SocketAddress.hpp
Normal file
9
kernel/orbis/include/orbis/SocketAddress.hpp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
namespace orbis {
|
||||
struct SocketAddress {
|
||||
unsigned char len;
|
||||
unsigned char family;
|
||||
char data[14];
|
||||
};
|
||||
} // namespace orbis
|
||||
166
kernel/orbis/include/orbis/error.hpp
Normal file
166
kernel/orbis/include/orbis/error.hpp
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
#pragma once
|
||||
|
||||
#include "error/ErrorCode.hpp" // IWYU pragma: export
|
||||
#include "error/SysResult.hpp" // IWYU pragma: export
|
||||
#include <system_error>
|
||||
|
||||
namespace orbis {
|
||||
static orbis::ErrorCode toErrorCode(std::errc errc) {
|
||||
if (errc == std::errc{}) {
|
||||
return {};
|
||||
}
|
||||
|
||||
switch (errc) {
|
||||
case std::errc::address_family_not_supported:
|
||||
return orbis::ErrorCode::AFNOSUPPORT;
|
||||
case std::errc::address_in_use:
|
||||
return orbis::ErrorCode::ADDRINUSE;
|
||||
case std::errc::address_not_available:
|
||||
return orbis::ErrorCode::ADDRNOTAVAIL;
|
||||
case std::errc::already_connected:
|
||||
return orbis::ErrorCode::ISCONN;
|
||||
case std::errc::argument_out_of_domain:
|
||||
return orbis::ErrorCode::DOM;
|
||||
case std::errc::bad_address:
|
||||
return orbis::ErrorCode::FAULT;
|
||||
case std::errc::bad_file_descriptor:
|
||||
return orbis::ErrorCode::BADF;
|
||||
case std::errc::bad_message:
|
||||
return orbis::ErrorCode::BADMSG;
|
||||
case std::errc::broken_pipe:
|
||||
return orbis::ErrorCode::PIPE;
|
||||
case std::errc::connection_aborted:
|
||||
return orbis::ErrorCode::CONNABORTED;
|
||||
case std::errc::connection_already_in_progress:
|
||||
return orbis::ErrorCode::ALREADY;
|
||||
case std::errc::connection_refused:
|
||||
return orbis::ErrorCode::CONNREFUSED;
|
||||
case std::errc::connection_reset:
|
||||
return orbis::ErrorCode::CONNRESET;
|
||||
case std::errc::cross_device_link:
|
||||
return orbis::ErrorCode::XDEV;
|
||||
case std::errc::destination_address_required:
|
||||
return orbis::ErrorCode::DESTADDRREQ;
|
||||
case std::errc::device_or_resource_busy:
|
||||
return orbis::ErrorCode::BUSY;
|
||||
case std::errc::directory_not_empty:
|
||||
return orbis::ErrorCode::NOTEMPTY;
|
||||
case std::errc::executable_format_error:
|
||||
return orbis::ErrorCode::NOEXEC;
|
||||
case std::errc::file_exists:
|
||||
return orbis::ErrorCode::EXIST;
|
||||
case std::errc::file_too_large:
|
||||
return orbis::ErrorCode::FBIG;
|
||||
case std::errc::filename_too_long:
|
||||
return orbis::ErrorCode::NAMETOOLONG;
|
||||
case std::errc::function_not_supported:
|
||||
return orbis::ErrorCode::NOSYS;
|
||||
case std::errc::host_unreachable:
|
||||
return orbis::ErrorCode::HOSTUNREACH;
|
||||
case std::errc::identifier_removed:
|
||||
return orbis::ErrorCode::IDRM;
|
||||
case std::errc::illegal_byte_sequence:
|
||||
return orbis::ErrorCode::ILSEQ;
|
||||
case std::errc::inappropriate_io_control_operation:
|
||||
return orbis::ErrorCode::NOTTY;
|
||||
case std::errc::interrupted:
|
||||
return orbis::ErrorCode::INTR;
|
||||
case std::errc::invalid_argument:
|
||||
return orbis::ErrorCode::INVAL;
|
||||
case std::errc::invalid_seek:
|
||||
return orbis::ErrorCode::SPIPE;
|
||||
case std::errc::io_error:
|
||||
return orbis::ErrorCode::IO;
|
||||
case std::errc::is_a_directory:
|
||||
return orbis::ErrorCode::ISDIR;
|
||||
case std::errc::message_size:
|
||||
return orbis::ErrorCode::MSGSIZE;
|
||||
case std::errc::network_down:
|
||||
return orbis::ErrorCode::NETDOWN;
|
||||
case std::errc::network_reset:
|
||||
return orbis::ErrorCode::NETRESET;
|
||||
case std::errc::network_unreachable:
|
||||
return orbis::ErrorCode::NETUNREACH;
|
||||
case std::errc::no_buffer_space:
|
||||
return orbis::ErrorCode::NOBUFS;
|
||||
case std::errc::no_child_process:
|
||||
return orbis::ErrorCode::CHILD;
|
||||
case std::errc::no_link:
|
||||
return orbis::ErrorCode::NOLINK;
|
||||
case std::errc::no_lock_available:
|
||||
return orbis::ErrorCode::NOLCK;
|
||||
case std::errc::no_message:
|
||||
return orbis::ErrorCode::NOMSG;
|
||||
case std::errc::no_protocol_option:
|
||||
return orbis::ErrorCode::NOPROTOOPT;
|
||||
case std::errc::no_space_on_device:
|
||||
return orbis::ErrorCode::NOSPC;
|
||||
case std::errc::no_such_device_or_address:
|
||||
return orbis::ErrorCode::NXIO;
|
||||
case std::errc::no_such_device:
|
||||
return orbis::ErrorCode::NODEV;
|
||||
case std::errc::no_such_file_or_directory:
|
||||
return orbis::ErrorCode::NOENT;
|
||||
case std::errc::no_such_process:
|
||||
return orbis::ErrorCode::SRCH;
|
||||
case std::errc::not_a_directory:
|
||||
return orbis::ErrorCode::NOTDIR;
|
||||
case std::errc::not_a_socket:
|
||||
return orbis::ErrorCode::NOTSOCK;
|
||||
case std::errc::not_connected:
|
||||
return orbis::ErrorCode::NOTCONN;
|
||||
case std::errc::not_enough_memory:
|
||||
return orbis::ErrorCode::NOMEM;
|
||||
case std::errc::not_supported:
|
||||
return orbis::ErrorCode::NOTSUP;
|
||||
case std::errc::operation_canceled:
|
||||
return orbis::ErrorCode::CANCELED;
|
||||
case std::errc::operation_in_progress:
|
||||
return orbis::ErrorCode::INPROGRESS;
|
||||
case std::errc::operation_not_permitted:
|
||||
return orbis::ErrorCode::PERM;
|
||||
case std::errc::operation_would_block:
|
||||
return orbis::ErrorCode::WOULDBLOCK;
|
||||
case std::errc::permission_denied:
|
||||
return orbis::ErrorCode::ACCES;
|
||||
case std::errc::protocol_error:
|
||||
return orbis::ErrorCode::PROTO;
|
||||
case std::errc::protocol_not_supported:
|
||||
return orbis::ErrorCode::PROTONOSUPPORT;
|
||||
case std::errc::read_only_file_system:
|
||||
return orbis::ErrorCode::ROFS;
|
||||
case std::errc::resource_deadlock_would_occur:
|
||||
return orbis::ErrorCode::DEADLK;
|
||||
case std::errc::result_out_of_range:
|
||||
return orbis::ErrorCode::RANGE;
|
||||
case std::errc::text_file_busy:
|
||||
return orbis::ErrorCode::TXTBSY;
|
||||
case std::errc::timed_out:
|
||||
return orbis::ErrorCode::TIMEDOUT;
|
||||
case std::errc::too_many_files_open_in_system:
|
||||
return orbis::ErrorCode::NFILE;
|
||||
case std::errc::too_many_files_open:
|
||||
return orbis::ErrorCode::MFILE;
|
||||
case std::errc::too_many_links:
|
||||
return orbis::ErrorCode::MLINK;
|
||||
case std::errc::too_many_symbolic_link_levels:
|
||||
return orbis::ErrorCode::LOOP;
|
||||
case std::errc::value_too_large:
|
||||
return orbis::ErrorCode::OVERFLOW;
|
||||
case std::errc::wrong_protocol_type:
|
||||
return orbis::ErrorCode::PROTOTYPE;
|
||||
default:
|
||||
return orbis::ErrorCode::FAULT;
|
||||
}
|
||||
}
|
||||
|
||||
inline constexpr orbis::ErrorCode toErrorCode(const std::error_code &code) {
|
||||
if (!code) {
|
||||
return {};
|
||||
}
|
||||
if (code.category() != std::generic_category()) {
|
||||
return orbis::ErrorCode::DOOFUS;
|
||||
}
|
||||
return toErrorCode(static_cast<std::errc>(code.value()));
|
||||
}
|
||||
} // namespace orbis
|
||||
118
kernel/orbis/include/orbis/error/ErrorCode.hpp
Normal file
118
kernel/orbis/include/orbis/error/ErrorCode.hpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#pragma once
|
||||
|
||||
namespace orbis {
|
||||
enum class ErrorCode : int {
|
||||
PERM = 1, // Operation not permitted
|
||||
NOENT = 2, // No such file or directory
|
||||
SRCH = 3, // No such process
|
||||
INTR = 4, // Interrupted system call
|
||||
IO = 5, // Input/output error
|
||||
NXIO = 6, // Device not configured
|
||||
TOOBIG = 7, // Argument list too long
|
||||
NOEXEC = 8, // Exec format error
|
||||
BADF = 9, // Bad file descriptor
|
||||
CHILD = 10, // No child processes
|
||||
DEADLK = 11, // Resource deadlock avoided
|
||||
|
||||
NOMEM = 12, // Cannot allocate memory
|
||||
ACCES = 13, // Permission denied
|
||||
FAULT = 14, // Bad address
|
||||
NOTBLK = 15, // Block device required
|
||||
BUSY = 16, // Device busy
|
||||
EXIST = 17, // File exists
|
||||
XDEV = 18, // Cross-device link
|
||||
NODEV = 19, // Operation not supported by device
|
||||
NOTDIR = 20, // Not a directory
|
||||
ISDIR = 21, // Is a directory
|
||||
INVAL = 22, // Invalid argument
|
||||
NFILE = 23, // Too many open files in system
|
||||
MFILE = 24, // Too many open files
|
||||
NOTTY = 25, // Inappropriate ioctl for device
|
||||
TXTBSY = 26, // Text file busy
|
||||
FBIG = 27, // File too large
|
||||
NOSPC = 28, // No space left on device
|
||||
SPIPE = 29, // Illegal seek
|
||||
ROFS = 30, // Read-only filesystem
|
||||
MLINK = 31, // Too many links
|
||||
PIPE = 32, // Broken pipe
|
||||
|
||||
DOM = 33, // Numerical argument out of domain
|
||||
RANGE = 34, // Result too large
|
||||
|
||||
AGAIN = 35, // Resource temporarily unavailable
|
||||
WOULDBLOCK = AGAIN, // Operation would block
|
||||
INPROGRESS = 36, // Operation now in progress
|
||||
ALREADY = 37, // Operation already in progress
|
||||
|
||||
NOTSOCK = 38, // Socket operation on non-socket
|
||||
DESTADDRREQ = 39, // Destination address required
|
||||
MSGSIZE = 40, // Message too long
|
||||
PROTOTYPE = 41, // Protocol wrong type for socket
|
||||
NOPROTOOPT = 42, // Protocol not available
|
||||
PROTONOSUPPORT = 43, // Protocol not supported
|
||||
SOCKTNOSUPPORT = 44, // Socket type not supported
|
||||
OPNOTSUPP = 45, // Operation not supported
|
||||
NOTSUP = OPNOTSUPP, // Operation not supported
|
||||
PFNOSUPPORT = 46, // Protocol family not supported
|
||||
AFNOSUPPORT = 47, // Address family not supported by protocol family
|
||||
ADDRINUSE = 48, // Address already in use
|
||||
ADDRNOTAVAIL = 49, // Can't assign requested address
|
||||
|
||||
NETDOWN = 50, // Network is down
|
||||
NETUNREACH = 51, // Network is unreachable
|
||||
NETRESET = 52, // Network dropped connection on reset
|
||||
CONNABORTED = 53, // Software caused connection abort
|
||||
CONNRESET = 54, // Connection reset by peer
|
||||
NOBUFS = 55, // No buffer space available
|
||||
ISCONN = 56, // Socket is already connected
|
||||
NOTCONN = 57, // Socket is not connected
|
||||
SHUTDOWN = 58, // Can't send after socket shutdown
|
||||
TOOMANYREFS = 59, // Too many references: can't splice
|
||||
TIMEDOUT = 60, // Operation timed out
|
||||
CONNREFUSED = 61, // Connection refused
|
||||
|
||||
LOOP = 62, // Too many levels of symbolic links
|
||||
NAMETOOLONG = 63, // File name too long
|
||||
HOSTDOWN = 64, // Host is down
|
||||
HOSTUNREACH = 65, // No route to host
|
||||
NOTEMPTY = 66, // Directory not empty
|
||||
PROCLIM = 67, // Too many processes
|
||||
USERS = 68, // Too many users
|
||||
DQUOT = 69, // Disc quota exceeded
|
||||
STALE = 70, // Stale NFS file handle
|
||||
REMOTE = 71, // Too many levels of remote in path
|
||||
BADRPC = 72, // RPC struct is bad
|
||||
RPCMISMATCH = 73, // RPC version wrong
|
||||
PROGUNAVAIL = 74, // RPC prog. not avail
|
||||
PROGMISMATCH = 75, // Program version wrong
|
||||
PROCUNAVAIL = 76, // Bad procedure for program
|
||||
NOLCK = 77, // No locks available
|
||||
NOSYS = 78, // Function not implemented
|
||||
FTYPE = 79, // Inappropriate file type or format
|
||||
AUTH = 80, // Authentication error
|
||||
NEEDAUTH = 81, // Need authenticator
|
||||
IDRM = 82, // Identifier removed
|
||||
NOMSG = 83, // No message of desired type
|
||||
OVERFLOW = 84, // Value too large to be stored in data type
|
||||
CANCELED = 85, // Operation canceled
|
||||
ILSEQ = 86, // Illegal byte sequence
|
||||
NOATTR = 87, // Attribute not found
|
||||
|
||||
DOOFUS = 88, // Programming error
|
||||
|
||||
BADMSG = 89, // Bad message
|
||||
MULTIHOP = 90, // Multihop attempted
|
||||
NOLINK = 91, // Link has been severed
|
||||
PROTO = 92, // Protocol error
|
||||
|
||||
NOTCAPABLE = 93, // Capabilities insufficient
|
||||
CAPMODE = 94, // Not permitted in capability mode
|
||||
};
|
||||
} // namespace orbis
|
||||
|
||||
#define ORBIS_RET_ON_ERROR(...) \
|
||||
do { \
|
||||
if (auto errc___ = (__VA_ARGS__); errc___ != ::orbis::ErrorCode{}) { \
|
||||
return errc___; \
|
||||
} \
|
||||
} while (false)
|
||||
31
kernel/orbis/include/orbis/error/SysResult.hpp
Normal file
31
kernel/orbis/include/orbis/error/SysResult.hpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
#include <compare>
|
||||
|
||||
namespace orbis {
|
||||
enum class ErrorCode : int;
|
||||
|
||||
class SysResult {
|
||||
int mValue = 0;
|
||||
|
||||
public:
|
||||
SysResult() = default;
|
||||
SysResult(ErrorCode ec) : mValue(-static_cast<int>(ec)) {}
|
||||
|
||||
[[nodiscard]] static SysResult notAnError(ErrorCode ec) {
|
||||
SysResult result;
|
||||
result.mValue = static_cast<int>(ec);
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] int value() const { return mValue < 0 ? -mValue : mValue; }
|
||||
[[nodiscard]] bool isError() const { return mValue < 0; }
|
||||
|
||||
[[nodiscard]] auto operator<=>(ErrorCode ec) const {
|
||||
return static_cast<ErrorCode>(value()) <=> ec;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto operator<=>(SysResult other) const {
|
||||
return value() <=> other.value();
|
||||
}
|
||||
};
|
||||
} // namespace orbis
|
||||
14
kernel/orbis/include/orbis/event.hpp
Normal file
14
kernel/orbis/include/orbis/event.hpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
#include "file.hpp"
|
||||
#include "note.hpp"
|
||||
#include "utils/SharedCV.hpp"
|
||||
#include <list>
|
||||
|
||||
namespace orbis {
|
||||
struct KQueue : orbis::File {
|
||||
shared_cv cv;
|
||||
kstring name;
|
||||
kvector<KEvent> triggeredEvents;
|
||||
std::list<KNote, kallocator<KNote>> notes;
|
||||
};
|
||||
} // namespace orbis
|
||||
95
kernel/orbis/include/orbis/evf.hpp
Normal file
95
kernel/orbis/include/orbis/evf.hpp
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#pragma once
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "utils/SharedMutex.hpp"
|
||||
#include <atomic>
|
||||
|
||||
namespace orbis {
|
||||
enum {
|
||||
kEvfAttrThFifo = 0x01,
|
||||
kEvfAttrThPrio = 0x02,
|
||||
kEvfAttrSingle = 0x10,
|
||||
kEvfAttrMulti = 0x20,
|
||||
kEvfAttrShared = 0x100,
|
||||
};
|
||||
|
||||
enum {
|
||||
kEvfWaitModeAnd = 0x01,
|
||||
kEvfWaitModeOr = 0x02,
|
||||
kEvfWaitModeClearAll = 0x10,
|
||||
kEvfWaitModeClearPat = 0x20,
|
||||
};
|
||||
|
||||
struct EventFlag final {
|
||||
char name[32];
|
||||
|
||||
bool isDeleted = false;
|
||||
std::uint8_t attrs = kEvfAttrMulti | kEvfAttrThFifo;
|
||||
std::atomic<unsigned> references{0};
|
||||
std::atomic<std::uint64_t> value{0};
|
||||
|
||||
struct WaitingThread {
|
||||
Thread *thread;
|
||||
std::uint64_t bitPattern;
|
||||
std::uint8_t waitMode;
|
||||
|
||||
bool operator==(const WaitingThread &) const = default;
|
||||
|
||||
bool test(std::uint64_t value) const {
|
||||
if (waitMode & kEvfWaitModeAnd) {
|
||||
return (value & bitPattern) == bitPattern;
|
||||
}
|
||||
|
||||
return (value & bitPattern) != 0;
|
||||
}
|
||||
|
||||
std::uint64_t applyClear(std::uint64_t value) {
|
||||
if (waitMode & kEvfWaitModeClearAll) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (waitMode & kEvfWaitModeClearPat) {
|
||||
return value & ~bitPattern;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
utils::shared_mutex queueMtx;
|
||||
utils::kvector<WaitingThread> waitingThreads;
|
||||
|
||||
enum class NotifyType { Set, Cancel, Destroy };
|
||||
|
||||
EventFlag() = default;
|
||||
EventFlag(std::int32_t attrs, std::uint64_t initPattern)
|
||||
: attrs(attrs), value(initPattern) {}
|
||||
|
||||
ErrorCode wait(Thread *thread, std::uint8_t waitMode,
|
||||
std::uint64_t bitPattern, std::uint32_t *timeout);
|
||||
ErrorCode tryWait(Thread *thread, std::uint8_t waitMode,
|
||||
std::uint64_t bitPattern);
|
||||
std::size_t notify(NotifyType type, std::uint64_t bits);
|
||||
|
||||
std::size_t destroy() { return notify(NotifyType::Destroy, {}); }
|
||||
|
||||
std::size_t cancel(std::uint64_t value) {
|
||||
return notify(NotifyType::Cancel, value);
|
||||
}
|
||||
|
||||
std::size_t set(std::uint64_t bits) { return notify(NotifyType::Set, bits); }
|
||||
|
||||
void clear(std::uint64_t bits) {
|
||||
writer_lock lock(queueMtx);
|
||||
value.fetch_and(bits, std::memory_order::relaxed);
|
||||
}
|
||||
|
||||
void incRef() { references.fetch_add(1, std::memory_order::relaxed); }
|
||||
|
||||
void decRef() {
|
||||
if (references.fetch_sub(1, std::memory_order::relaxed) == 1) {
|
||||
kdelete(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace orbis
|
||||
89
kernel/orbis/include/orbis/file.hpp
Normal file
89
kernel/orbis/include/orbis/file.hpp
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
#pragma once
|
||||
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "error/ErrorCode.hpp"
|
||||
#include "note.hpp"
|
||||
#include "stat.hpp"
|
||||
#include "utils/Rc.hpp"
|
||||
#include "utils/SharedMutex.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace orbis {
|
||||
struct File;
|
||||
struct KNote;
|
||||
struct Thread;
|
||||
struct Stat;
|
||||
struct Uio;
|
||||
struct SocketAddress;
|
||||
struct msghdr;
|
||||
struct sf_hdtr;
|
||||
|
||||
struct FileOps {
|
||||
std::int32_t flags;
|
||||
ErrorCode (*ioctl)(File *file, std::uint64_t request, void *argp,
|
||||
Thread *thread) = nullptr;
|
||||
ErrorCode (*read)(File *file, Uio *uio, Thread *thread) = nullptr;
|
||||
ErrorCode (*write)(File *file, Uio *uio, Thread *thread) = nullptr;
|
||||
|
||||
ErrorCode (*truncate)(File *file, std::uint64_t len,
|
||||
Thread *thread) = nullptr;
|
||||
|
||||
ErrorCode (*poll)(File *file, std::uint32_t events, Thread *thread) = nullptr;
|
||||
|
||||
ErrorCode (*kqfilter)(File *file, KNote *kn, Thread *thread) = nullptr;
|
||||
|
||||
ErrorCode (*stat)(File *file, Stat *sb, Thread *thread) = nullptr;
|
||||
|
||||
ErrorCode (*mkdir)(File *file, const char *path, std::int32_t mode) = nullptr;
|
||||
|
||||
// TODO: chown
|
||||
// TODO: chmod
|
||||
|
||||
ErrorCode (*mmap)(File *file, void **address, std::uint64_t size,
|
||||
std::int32_t prot, std::int32_t flags, std::int64_t offset,
|
||||
Thread *thread) = nullptr;
|
||||
ErrorCode (*munmap)(File *file, void **address, std::uint64_t size,
|
||||
Thread *thread) = nullptr;
|
||||
|
||||
ErrorCode (*bind)(orbis::File *file, SocketAddress *address,
|
||||
std::size_t addressLen, Thread *thread) = nullptr;
|
||||
ErrorCode (*listen)(orbis::File *file, int backlog, Thread *thread) = nullptr;
|
||||
ErrorCode (*accept)(orbis::File *file, SocketAddress *address,
|
||||
std::uint32_t *addressLen, Thread *thread) = nullptr;
|
||||
ErrorCode (*connect)(orbis::File *file, SocketAddress *address,
|
||||
std::uint32_t addressLen, Thread *thread) = nullptr;
|
||||
ErrorCode (*sendto)(orbis::File *file, const void *buf, size_t len,
|
||||
sint flags, caddr_t to, sint tolen,
|
||||
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,
|
||||
Thread *thread) = nullptr;
|
||||
ErrorCode (*recvmsg)(orbis::File *file, msghdr *msg, sint flags,
|
||||
Thread *thread) = nullptr;
|
||||
ErrorCode (*shutdown)(orbis::File *file, sint how, Thread *thread) = nullptr;
|
||||
ErrorCode (*setsockopt)(orbis::File *file, sint level, sint name,
|
||||
const void *val, sint valsize,
|
||||
Thread *thread) = nullptr;
|
||||
ErrorCode (*getsockopt)(orbis::File *file, sint level, sint name, void *val,
|
||||
sint *avalsize, Thread *thread) = nullptr;
|
||||
ErrorCode (*sendfile)(orbis::File *file, sint fd, off_t offset, size_t nbytes,
|
||||
ptr<struct sf_hdtr> hdtr, ptr<off_t> sbytes, sint flags,
|
||||
Thread *thread) = nullptr;
|
||||
};
|
||||
|
||||
struct File : RcBase {
|
||||
shared_mutex mtx;
|
||||
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
|
||||
254
kernel/orbis/include/orbis/ipmi.hpp
Normal file
254
kernel/orbis/include/orbis/ipmi.hpp
Normal file
|
|
@ -0,0 +1,254 @@
|
|||
#pragma once
|
||||
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "evf.hpp"
|
||||
#include "orbis-config.hpp"
|
||||
#include "orbis/utils/SharedCV.hpp"
|
||||
#include "orbis/utils/SharedMutex.hpp"
|
||||
#include "utils/Rc.hpp"
|
||||
#include <list>
|
||||
#include <optional>
|
||||
|
||||
namespace orbis {
|
||||
struct IpmiSession;
|
||||
struct IpmiClient;
|
||||
struct Thread;
|
||||
|
||||
struct IpmiServer : RcBase {
|
||||
struct IpmiPacketInfo {
|
||||
ulong inputSize;
|
||||
uint type;
|
||||
uint clientKid;
|
||||
ptr<void> eventHandler;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiPacketInfo) == 0x18);
|
||||
|
||||
struct Packet {
|
||||
IpmiPacketInfo info;
|
||||
lwpid_t clientTid;
|
||||
Ref<IpmiSession> session;
|
||||
kvector<std::byte> message;
|
||||
};
|
||||
|
||||
struct ConnectionRequest {
|
||||
Ref<IpmiClient> client;
|
||||
slong clientTid{};
|
||||
slong clientPid{};
|
||||
slong serverTid{};
|
||||
};
|
||||
|
||||
kmap<std::uint32_t, std::uint32_t> tidToClientTid;
|
||||
kstring name;
|
||||
ptr<void> serverImpl;
|
||||
ptr<void> eventHandler;
|
||||
ptr<void> userData;
|
||||
shared_mutex mutex;
|
||||
shared_cv receiveCv;
|
||||
sint pid;
|
||||
kdeque<Packet> packets;
|
||||
std::list<ConnectionRequest, kallocator<ConnectionRequest>>
|
||||
connectionRequests;
|
||||
|
||||
explicit IpmiServer(kstring name) : name(std::move(name)) {}
|
||||
};
|
||||
|
||||
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;
|
||||
shared_cv asyncResponseCv;
|
||||
shared_cv connectCv;
|
||||
std::optional<sint> connectionStatus{};
|
||||
Process *process;
|
||||
kdeque<MessageQueue> messageQueues;
|
||||
kdeque<EventFlag> eventFlags;
|
||||
kdeque<AsyncResponse> asyncResponses;
|
||||
|
||||
explicit IpmiClient(kstring name) : name(std::move(name)) {}
|
||||
};
|
||||
|
||||
struct IpmiSession : RcBase {
|
||||
struct SyncResponse {
|
||||
sint errorCode;
|
||||
std::uint32_t callerTid;
|
||||
kvector<kvector<std::byte>> data;
|
||||
};
|
||||
|
||||
ptr<void> sessionImpl;
|
||||
ptr<void> userData;
|
||||
Ref<IpmiClient> client;
|
||||
Ref<IpmiServer> server;
|
||||
shared_mutex mutex;
|
||||
shared_cv responseCv;
|
||||
kdeque<SyncResponse> syncResponses;
|
||||
uint expectedOutput{0};
|
||||
};
|
||||
|
||||
struct IpmiCreateServerConfig {
|
||||
orbis::uint64_t size;
|
||||
orbis::uint32_t unk1;
|
||||
orbis::uint32_t unk2;
|
||||
orbis::uint32_t unk3;
|
||||
orbis::uint32_t unk4;
|
||||
orbis::uint32_t enableMultipleServerThreads;
|
||||
orbis::uint32_t unk5;
|
||||
orbis::uint64_t unk6;
|
||||
orbis::ptr<void> userData;
|
||||
orbis::ptr<void> eventHandler;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiCreateServerConfig) == 0x38);
|
||||
|
||||
struct IpmiCreateClientConfig {
|
||||
orbis::uint64_t size;
|
||||
orbis::uint32_t unk[80];
|
||||
orbis::ptr<void> userData;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiCreateClientConfig) == 0x150);
|
||||
|
||||
struct IpmiBufferInfo {
|
||||
ptr<void> data;
|
||||
uint64_t capacity;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
struct IpmiDataInfo {
|
||||
ptr<void> data;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiBufferInfo) == 0x18);
|
||||
static_assert(sizeof(IpmiDataInfo) == 0x10);
|
||||
|
||||
struct IpmiSyncCallParams {
|
||||
uint32_t method;
|
||||
uint32_t numInData;
|
||||
uint32_t numOutData;
|
||||
uint32_t unk;
|
||||
ptr<IpmiDataInfo> pInData;
|
||||
ptr<IpmiBufferInfo> pOutData;
|
||||
ptr<sint> pResult;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiSyncCallParams) == 0x30);
|
||||
|
||||
struct [[gnu::packed]] IpmiSyncMessageHeader {
|
||||
orbis::ptr<void> sessionImpl;
|
||||
orbis::uint pid;
|
||||
orbis::uint methodId;
|
||||
orbis::uint numInData;
|
||||
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);
|
||||
|
||||
struct IpmiCreateClientParams {
|
||||
ptr<void> clientImpl;
|
||||
ptr<const char> name;
|
||||
ptr<IpmiCreateClientConfig> config;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiCreateClientParams) == 0x18);
|
||||
|
||||
struct IpmiClientConnectParams {
|
||||
ptr<void> userData;
|
||||
ulong userDataLen;
|
||||
ptr<sint> status;
|
||||
ptr<sint> arg3;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiClientConnectParams) == 0x20);
|
||||
|
||||
ErrorCode ipmiCreateClient(Process *proc, void *clientImpl, const char *name,
|
||||
const IpmiCreateClientConfig &config,
|
||||
Ref<IpmiClient> &result);
|
||||
ErrorCode ipmiCreateServer(Process *proc, void *serverImpl, const char *name,
|
||||
const IpmiCreateServerConfig &config,
|
||||
Ref<IpmiServer> &result);
|
||||
ErrorCode ipmiCreateSession(Thread *thread, void *sessionImpl,
|
||||
ptr<void> userData, Ref<IpmiSession> &result);
|
||||
|
||||
SysResult sysIpmiCreateClient(Thread *thread, ptr<uint> result,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiCreateServer(Thread *thread, ptr<uint> result,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiCreateSession(Thread *thread, ptr<uint> result,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
|
||||
SysResult sysIpmiDestroyClient(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiDestroyServer(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiDestroySession(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
|
||||
SysResult sysIpmiServerReceivePacket(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiSendConnectResult(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiSessionRespondSync(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiClientInvokeAsyncMethod(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,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiSessionTrySendMessage(Thread *thread, ptr<uint> result,
|
||||
uint kid, ptr<void> params,
|
||||
uint64_t paramsSz);
|
||||
SysResult sysIpmiClientDisconnect(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiSessionGetClientPid(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result,
|
||||
uint kid, ptr<void> params,
|
||||
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,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
SysResult sysIpmiSessionSetEventFlag(Thread *thread, ptr<uint> result, uint kid,
|
||||
ptr<void> params, uint64_t paramsSz);
|
||||
|
||||
} // namespace orbis
|
||||
7
kernel/orbis/include/orbis/module.hpp
Normal file
7
kernel/orbis/include/orbis/module.hpp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "module/Module.hpp" // IWYU pragma: export
|
||||
#include "module/ModuleHandle.hpp" // IWYU pragma: export
|
||||
#include "module/ModuleInfo.hpp" // IWYU pragma: export
|
||||
#include "module/ModuleInfoEx.hpp" // IWYU pragma: export
|
||||
#include "module/ModuleSegment.hpp" // IWYU pragma: export
|
||||
151
kernel/orbis/include/orbis/module/Module.hpp
Normal file
151
kernel/orbis/include/orbis/module/Module.hpp
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
#pragma once
|
||||
|
||||
#include "ModuleHandle.hpp"
|
||||
#include "ModuleSegment.hpp"
|
||||
|
||||
#include "../KernelAllocator.hpp"
|
||||
#include "../utils/Rc.hpp"
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace orbis {
|
||||
struct Thread;
|
||||
struct Process;
|
||||
|
||||
enum class DynType : std::uint8_t {
|
||||
None,
|
||||
FreeBsd,
|
||||
Ps4,
|
||||
Ps5,
|
||||
};
|
||||
|
||||
struct ModuleNeeded {
|
||||
utils::kstring name;
|
||||
std::uint16_t version;
|
||||
std::uint64_t attr;
|
||||
bool isExport;
|
||||
};
|
||||
|
||||
enum class SymbolBind : std::uint8_t { Local, Global, Weak, Unique = 10 };
|
||||
|
||||
enum class SymbolVisibility : std::uint8_t {
|
||||
Default,
|
||||
Internal,
|
||||
Hidden,
|
||||
Protected
|
||||
};
|
||||
|
||||
enum class SymbolType : std::uint8_t {
|
||||
NoType,
|
||||
Object,
|
||||
Function,
|
||||
Section,
|
||||
File,
|
||||
Common,
|
||||
Tls,
|
||||
IFunc = 10,
|
||||
};
|
||||
|
||||
struct Symbol {
|
||||
std::int32_t moduleIndex;
|
||||
std::uint32_t libraryIndex;
|
||||
std::uint64_t id;
|
||||
std::uint64_t address;
|
||||
std::uint64_t size;
|
||||
SymbolVisibility visibility;
|
||||
SymbolBind bind;
|
||||
SymbolType type;
|
||||
};
|
||||
|
||||
struct Relocation {
|
||||
std::uint64_t offset;
|
||||
std::uint32_t relType;
|
||||
std::uint32_t symbolIndex;
|
||||
std::int64_t addend;
|
||||
};
|
||||
|
||||
struct Module final {
|
||||
Process *proc{};
|
||||
utils::kstring vfsPath;
|
||||
char moduleName[256]{};
|
||||
char soName[256]{};
|
||||
ModuleHandle id{};
|
||||
uint32_t tlsIndex{};
|
||||
ptr<void> tlsInit{};
|
||||
uint32_t tlsInitSize{};
|
||||
uint32_t tlsSize{};
|
||||
uint32_t tlsOffset{};
|
||||
uint32_t tlsAlign{};
|
||||
ptr<void> initProc{};
|
||||
ptr<void> finiProc{};
|
||||
ptr<void> ehFrameHdr{};
|
||||
ptr<void> ehFrame{};
|
||||
uint32_t ehFrameHdrSize{};
|
||||
uint32_t ehFrameSize{};
|
||||
ModuleSegment segments[16]{};
|
||||
uint32_t segmentCount{};
|
||||
std::uint8_t fingerprint[20]{};
|
||||
ptr<void> base{};
|
||||
uint64_t size{};
|
||||
ptr<void> stackStart{};
|
||||
ptr<void> stackEnd{};
|
||||
ptr<void> processParam{};
|
||||
uint64_t processParamSize{};
|
||||
ptr<void> moduleParam{};
|
||||
uint64_t moduleParamSize{};
|
||||
|
||||
ptr<uint64_t> pltGot{};
|
||||
|
||||
uint64_t attributes{};
|
||||
uint16_t version{};
|
||||
uint16_t type{};
|
||||
uint16_t flags{};
|
||||
uint64_t entryPoint{};
|
||||
|
||||
DynType dynType = DynType::None;
|
||||
|
||||
uint32_t phNum{};
|
||||
uint64_t phdrAddress{};
|
||||
|
||||
bool isTlsDone = false;
|
||||
|
||||
utils::kstring interp;
|
||||
utils::kvector<Symbol> symbols;
|
||||
utils::kvector<Relocation> pltRelocations;
|
||||
utils::kvector<Relocation> nonPltRelocations;
|
||||
utils::kvector<ModuleNeeded> neededModules;
|
||||
utils::kvector<ModuleNeeded> neededLibraries;
|
||||
utils::kvector<utils::Ref<Module>> importedModules;
|
||||
utils::kvector<utils::Ref<Module>> namespaceModules;
|
||||
utils::kvector<utils::kstring> needed;
|
||||
|
||||
std::atomic<unsigned> references{0};
|
||||
unsigned _total_size = 0;
|
||||
|
||||
void incRef() {
|
||||
if (_total_size != sizeof(Module))
|
||||
std::abort();
|
||||
if (references.fetch_add(1, std::memory_order::relaxed) > 512) {
|
||||
assert(!"too many references");
|
||||
}
|
||||
}
|
||||
|
||||
void decRef() {
|
||||
if (references.fetch_sub(1, std::memory_order::relaxed) == 1 &&
|
||||
proc != nullptr) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
orbis::SysResult relocate(Process *process);
|
||||
|
||||
private:
|
||||
void destroy();
|
||||
};
|
||||
|
||||
utils::Ref<Module> createModule(Thread *p, std::string vfsPath,
|
||||
const char *name);
|
||||
} // namespace orbis
|
||||
7
kernel/orbis/include/orbis/module/ModuleHandle.hpp
Normal file
7
kernel/orbis/include/orbis/module/ModuleHandle.hpp
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace orbis {
|
||||
enum class ModuleHandle : std::uint32_t {};
|
||||
} // namespace orbis
|
||||
15
kernel/orbis/include/orbis/module/ModuleInfo.hpp
Normal file
15
kernel/orbis/include/orbis/module/ModuleInfo.hpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include "ModuleSegment.hpp"
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct ModuleInfo {
|
||||
uint64_t size;
|
||||
char name[256];
|
||||
ModuleSegment segments[4];
|
||||
uint32_t segmentCount;
|
||||
uint8_t fingerprint[20];
|
||||
};
|
||||
} // namespace orbis
|
||||
30
kernel/orbis/include/orbis/module/ModuleInfoEx.hpp
Normal file
30
kernel/orbis/include/orbis/module/ModuleInfoEx.hpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "ModuleSegment.hpp"
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct ModuleInfoEx {
|
||||
uint64_t size;
|
||||
char name[256];
|
||||
uint32_t id;
|
||||
uint32_t tlsIndex;
|
||||
ptr<void> tlsInit;
|
||||
uint32_t tlsInitSize;
|
||||
uint32_t tlsSize;
|
||||
uint32_t tlsOffset;
|
||||
uint32_t tlsAlign;
|
||||
ptr<void> initProc;
|
||||
ptr<void> finiProc;
|
||||
uint64_t reserved1;
|
||||
uint64_t reserved2;
|
||||
ptr<void> ehFrameHdr;
|
||||
ptr<void> ehFrame;
|
||||
uint32_t ehFrameHdrSize;
|
||||
uint32_t ehFrameSize;
|
||||
ModuleSegment segments[4];
|
||||
uint32_t segmentCount;
|
||||
uint32_t refCount;
|
||||
};
|
||||
} // namespace orbis
|
||||
11
kernel/orbis/include/orbis/module/ModuleSegment.hpp
Normal file
11
kernel/orbis/include/orbis/module/ModuleSegment.hpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct ModuleSegment {
|
||||
ptr<void> addr;
|
||||
uint32_t size;
|
||||
uint32_t prot;
|
||||
};
|
||||
} // namespace orbis
|
||||
113
kernel/orbis/include/orbis/note.hpp
Normal file
113
kernel/orbis/include/orbis/note.hpp
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
#pragma once
|
||||
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "orbis-config.hpp"
|
||||
#include "orbis/utils/Rc.hpp"
|
||||
#include "utils/SharedMutex.hpp"
|
||||
#include <limits>
|
||||
#include <set>
|
||||
|
||||
namespace orbis {
|
||||
struct File;
|
||||
static constexpr auto kEvFiltRead = -1;
|
||||
static constexpr auto kEvFiltWrite = -2;
|
||||
static constexpr auto kEvFiltAio = -3;
|
||||
static constexpr auto kEvFiltVnode = -4;
|
||||
static constexpr auto kEvFiltProc = -5;
|
||||
static constexpr auto kEvFiltSignal = -6;
|
||||
static constexpr auto kEvFiltTimer = -7;
|
||||
static constexpr auto kEvFiltFs = -9;
|
||||
static constexpr auto kEvFiltLio = -10;
|
||||
static constexpr auto kEvFiltUser = -11;
|
||||
static constexpr auto kEvFiltPolling = -12;
|
||||
static constexpr auto kEvFiltDisplay = -13;
|
||||
static constexpr auto kEvFiltGraphicsCore = -14;
|
||||
static constexpr auto kEvFiltHrTimer = -15;
|
||||
static constexpr auto kEvFiltUvdTrap = -16;
|
||||
static constexpr auto kEvFiltVceTrap = -17;
|
||||
static constexpr auto kEvFiltSdmaTrap = -18;
|
||||
static constexpr auto kEvFiltRegEv = -19;
|
||||
static constexpr auto kEvFiltGpuException = -20;
|
||||
static constexpr auto kEvFiltGpuSystemException = -21;
|
||||
static constexpr auto kEvFiltGpuDbgGcEv = -22;
|
||||
static constexpr auto kEvFiltSysCount = 22;
|
||||
|
||||
// actions
|
||||
static constexpr auto kEvAdd = 0x0001;
|
||||
static constexpr auto kEvDelete = 0x0002;
|
||||
static constexpr auto kEvEnable = 0x0004;
|
||||
static constexpr auto kEvDisable = 0x0008;
|
||||
|
||||
// flags
|
||||
static constexpr auto kEvOneshot = 0x0010;
|
||||
static constexpr auto kEvClear = 0x0020;
|
||||
static constexpr auto kEvReceipt = 0x0040;
|
||||
static constexpr auto kEvDispatch = 0x0080;
|
||||
static constexpr auto kEvSysFlags = 0xf000;
|
||||
static constexpr auto kEvFlag1 = 0x2000;
|
||||
|
||||
static constexpr auto kEvEof = 0x8000;
|
||||
static constexpr auto kEvError = 0x4000;
|
||||
|
||||
// kEvFiltUser
|
||||
static constexpr auto kNoteFFNop = 0x00000000;
|
||||
static constexpr auto kNoteFFAnd = 0x40000000;
|
||||
static constexpr auto kNoteFFOr = 0x80000000;
|
||||
static constexpr auto kNoteFFCopy = 0xc0000000;
|
||||
static constexpr auto kNoteFFCtrlMask = 0xc0000000;
|
||||
static constexpr auto kNoteFFlagsMask = 0x00ffffff;
|
||||
static constexpr auto kNoteTrigger = 0x01000000;
|
||||
|
||||
// kEvFiltProc
|
||||
static constexpr auto kNoteExit = 0x80000000;
|
||||
static constexpr auto kNoteFork = 0x40000000;
|
||||
static constexpr auto kNoteExec = 0x20000000;
|
||||
|
||||
struct KEvent {
|
||||
uintptr_t ident;
|
||||
sshort filter;
|
||||
ushort flags;
|
||||
uint fflags;
|
||||
intptr_t data;
|
||||
ptr<void> udata;
|
||||
};
|
||||
|
||||
struct EventEmitter;
|
||||
struct KQueue;
|
||||
struct KNote {
|
||||
shared_mutex mutex;
|
||||
KQueue *queue;
|
||||
Ref<File> file;
|
||||
KEvent event{};
|
||||
bool enabled = true;
|
||||
bool triggered = false;
|
||||
void *linked = nullptr; // TODO: use Ref<>
|
||||
kvector<Ref<EventEmitter>> emitters;
|
||||
|
||||
~KNote();
|
||||
};
|
||||
|
||||
struct EventEmitter : orbis::RcBase {
|
||||
shared_mutex mutex;
|
||||
std::set<KNote *, std::less<>, kallocator<KNote *>> notes;
|
||||
|
||||
void emit(sshort filter, uint fflags = 0, intptr_t data = 0,
|
||||
uintptr_t ident = std::numeric_limits<uintptr_t>::max());
|
||||
void emit(sshort filter, void *userData,
|
||||
std::optional<intptr_t> (*filterFn)(void *userData, KNote *note));
|
||||
|
||||
template <typename T>
|
||||
void emit(sshort filter, T &&fn)
|
||||
requires requires(KNote *note) {
|
||||
{ fn(note) } -> std::same_as<std::optional<intptr_t>>;
|
||||
}
|
||||
{
|
||||
emit(filter, &fn, [](void *userData, KNote *note) {
|
||||
return (*static_cast<std::remove_cvref_t<T> *>(userData))(note);
|
||||
});
|
||||
}
|
||||
|
||||
void subscribe(KNote *note);
|
||||
void unsubscribe(KNote *note);
|
||||
};
|
||||
} // namespace orbis
|
||||
45
kernel/orbis/include/orbis/osem.hpp
Normal file
45
kernel/orbis/include/orbis/osem.hpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "thread/Thread.hpp"
|
||||
#include "utils/SharedCV.hpp"
|
||||
#include "utils/SharedMutex.hpp"
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
|
||||
namespace orbis {
|
||||
enum {
|
||||
kSemaAttrThFifo = 1,
|
||||
kSemaAttrThPrio = 2,
|
||||
kSemaAttrShared = 256,
|
||||
};
|
||||
|
||||
struct Semaphore final {
|
||||
char name[32];
|
||||
|
||||
bool isDeleted = false;
|
||||
std::uint8_t attrs;
|
||||
std::atomic<unsigned> references{0};
|
||||
std::atomic<sint> value;
|
||||
const sint maxValue;
|
||||
utils::shared_mutex mtx;
|
||||
utils::shared_cv cond;
|
||||
|
||||
Semaphore(uint attrs, sint value, sint max)
|
||||
: attrs(attrs), value(value), maxValue(max) {}
|
||||
|
||||
void destroy() {
|
||||
std::lock_guard lock(mtx);
|
||||
isDeleted = true;
|
||||
cond.notify_all(mtx);
|
||||
}
|
||||
|
||||
void incRef() { references.fetch_add(1, std::memory_order::relaxed); }
|
||||
|
||||
void decRef() {
|
||||
if (references.fetch_sub(1, std::memory_order::relaxed) == 1) {
|
||||
kdelete(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace orbis
|
||||
18
kernel/orbis/include/orbis/pipe.hpp
Normal file
18
kernel/orbis/include/orbis/pipe.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "KernelAllocator.hpp"
|
||||
#include "file.hpp"
|
||||
#include "utils/Rc.hpp"
|
||||
#include "utils/SharedCV.hpp"
|
||||
#include "utils/SharedMutex.hpp"
|
||||
#include <utility>
|
||||
|
||||
namespace orbis {
|
||||
struct Pipe final : File {
|
||||
shared_cv cv;
|
||||
kvector<std::byte> data;
|
||||
Ref<Pipe> other;
|
||||
};
|
||||
|
||||
std::pair<Ref<Pipe>, Ref<Pipe>> createPipe();
|
||||
} // namespace orbis
|
||||
47
kernel/orbis/include/orbis/stat.hpp
Normal file
47
kernel/orbis/include/orbis/stat.hpp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
#include "time.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct Stat {
|
||||
uint32_t dev; // inode's device
|
||||
uint32_t ino; // inode's number
|
||||
uint16_t mode; // inode protection mode
|
||||
uint16_t nlink; // number of hard links
|
||||
uint32_t uid; // user ID of the file's owner
|
||||
uint32_t gid; // group ID of the file's group
|
||||
uint32_t rdev; // device type
|
||||
timespec atim; // time of last access
|
||||
timespec mtim; // time of last data modification
|
||||
timespec ctim; // time of last file status change
|
||||
off_t size; // file size, in bytes
|
||||
int64_t blocks; // blocks allocated for file
|
||||
uint32_t blksize; // optimal blocksize for I/O
|
||||
uint32_t flags; // user defined flags for file
|
||||
uint32_t gen; // file generation number
|
||||
int32_t lspare;
|
||||
timespec birthtim; // time of file creation
|
||||
};
|
||||
|
||||
struct Dirent {
|
||||
uint32_t fileno;
|
||||
uint16_t reclen;
|
||||
uint8_t type;
|
||||
uint8_t namlen;
|
||||
char name[256];
|
||||
};
|
||||
|
||||
enum {
|
||||
kDtUnknown = 0,
|
||||
kDtFifo = 1,
|
||||
kDtChr = 2,
|
||||
kDtDir = 4,
|
||||
kDtBlk = 6,
|
||||
kDtReg = 8,
|
||||
kDtLnk = 10,
|
||||
kDtSock = 12,
|
||||
kDtWht = 14,
|
||||
};
|
||||
|
||||
} // namespace orbis
|
||||
11
kernel/orbis/include/orbis/sys/sys_sce.hpp
Normal file
11
kernel/orbis/include/orbis/sys/sys_sce.hpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
namespace orbis {
|
||||
enum {
|
||||
kNamedObjTypeMutex = 0x101,
|
||||
kNamedObjTypeCond = 0x102,
|
||||
kNamedObjTypeRwlock = 0x103,
|
||||
kNamedObjTypeBarrier = 0x104,
|
||||
kNamedObjTypeEqueue = 0x107,
|
||||
};
|
||||
}
|
||||
599
kernel/orbis/include/orbis/sys/syscall.hpp
Normal file
599
kernel/orbis/include/orbis/sys/syscall.hpp
Normal file
|
|
@ -0,0 +1,599 @@
|
|||
#pragma once
|
||||
|
||||
namespace orbis {
|
||||
enum Syscall {
|
||||
kSYS_syscall = 0,
|
||||
kSYS_exit = 1,
|
||||
kSYS_fork = 2,
|
||||
kSYS_read = 3,
|
||||
kSYS_write = 4,
|
||||
kSYS_open = 5,
|
||||
kSYS_close = 6,
|
||||
kSYS_wait4 = 7,
|
||||
kSYS_link = 9,
|
||||
kSYS_unlink = 10,
|
||||
kSYS_chdir = 12,
|
||||
kSYS_fchdir = 13,
|
||||
kSYS_mknod = 14,
|
||||
kSYS_chmod = 15,
|
||||
kSYS_chown = 16,
|
||||
kSYS_break = 17,
|
||||
kSYS_freebsd4_getfsstat = 18,
|
||||
kSYS_getpid = 20,
|
||||
kSYS_mount = 21,
|
||||
kSYS_unmount = 22,
|
||||
kSYS_setuid = 23,
|
||||
kSYS_getuid = 24,
|
||||
kSYS_geteuid = 25,
|
||||
kSYS_ptrace = 26,
|
||||
kSYS_recvmsg = 27,
|
||||
kSYS_sendmsg = 28,
|
||||
kSYS_recvfrom = 29,
|
||||
kSYS_accept = 30,
|
||||
kSYS_getpeername = 31,
|
||||
kSYS_getsockname = 32,
|
||||
kSYS_access = 33,
|
||||
kSYS_chflags = 34,
|
||||
kSYS_fchflags = 35,
|
||||
kSYS_sync = 36,
|
||||
kSYS_kill = 37,
|
||||
kSYS_getppid = 39,
|
||||
kSYS_dup = 41,
|
||||
kSYS_pipe = 42,
|
||||
kSYS_getegid = 43,
|
||||
kSYS_profil = 44,
|
||||
kSYS_ktrace = 45,
|
||||
kSYS_getgid = 47,
|
||||
kSYS_getlogin = 49,
|
||||
kSYS_setlogin = 50,
|
||||
kSYS_acct = 51,
|
||||
kSYS_sigaltstack = 53,
|
||||
kSYS_ioctl = 54,
|
||||
kSYS_reboot = 55,
|
||||
kSYS_revoke = 56,
|
||||
kSYS_symlink = 57,
|
||||
kSYS_readlink = 58,
|
||||
kSYS_execve = 59,
|
||||
kSYS_umask = 60,
|
||||
kSYS_chroot = 61,
|
||||
kSYS_msync = 65,
|
||||
kSYS_vfork = 66,
|
||||
kSYS_sbrk = 69,
|
||||
kSYS_sstk = 70,
|
||||
kSYS_vadvise = 72,
|
||||
kSYS_munmap = 73,
|
||||
kSYS_mprotect = 74,
|
||||
kSYS_madvise = 75,
|
||||
kSYS_mincore = 78,
|
||||
kSYS_getgroups = 79,
|
||||
kSYS_setgroups = 80,
|
||||
kSYS_getpgrp = 81,
|
||||
kSYS_setpgid = 82,
|
||||
kSYS_setitimer = 83,
|
||||
kSYS_swapon = 85,
|
||||
kSYS_getitimer = 86,
|
||||
kSYS_getdtablesize = 89,
|
||||
kSYS_dup2 = 90,
|
||||
kSYS_fcntl = 92,
|
||||
kSYS_select = 93,
|
||||
kSYS_fsync = 95,
|
||||
kSYS_setpriority = 96,
|
||||
kSYS_socket = 97,
|
||||
kSYS_connect = 98,
|
||||
kSYS_getpriority = 100,
|
||||
kSYS_bind = 104,
|
||||
kSYS_setsockopt = 105,
|
||||
kSYS_listen = 106,
|
||||
kSYS_gettimeofday = 116,
|
||||
kSYS_getrusage = 117,
|
||||
kSYS_getsockopt = 118,
|
||||
kSYS_readv = 120,
|
||||
kSYS_writev = 121,
|
||||
kSYS_settimeofday = 122,
|
||||
kSYS_fchown = 123,
|
||||
kSYS_fchmod = 124,
|
||||
kSYS_setreuid = 126,
|
||||
kSYS_setregid = 127,
|
||||
kSYS_rename = 128,
|
||||
kSYS_flock = 131,
|
||||
kSYS_mkfifo = 132,
|
||||
kSYS_sendto = 133,
|
||||
kSYS_shutdown = 134,
|
||||
kSYS_socketpair = 135,
|
||||
kSYS_mkdir = 136,
|
||||
kSYS_rmdir = 137,
|
||||
kSYS_utimes = 138,
|
||||
kSYS_adjtime = 140,
|
||||
kSYS_setsid = 147,
|
||||
kSYS_quotactl = 148,
|
||||
kSYS_nlm_syscall = 154,
|
||||
kSYS_nfssvc = 155,
|
||||
kSYS_freebsd4_statfs = 157,
|
||||
kSYS_freebsd4_fstatfs = 158,
|
||||
kSYS_lgetfh = 160,
|
||||
kSYS_getfh = 161,
|
||||
kSYS_freebsd4_getdomainname = 162,
|
||||
kSYS_freebsd4_setdomainname = 163,
|
||||
kSYS_freebsd4_uname = 164,
|
||||
kSYS_sysarch = 165,
|
||||
kSYS_rtprio = 166,
|
||||
kSYS_semsys = 169,
|
||||
kSYS_msgsys = 170,
|
||||
kSYS_shmsys = 171,
|
||||
kSYS_freebsd6_pread = 173,
|
||||
kSYS_freebsd6_pwrite = 174,
|
||||
kSYS_setfib = 175,
|
||||
kSYS_ntp_adjtime = 176,
|
||||
kSYS_setgid = 181,
|
||||
kSYS_setegid = 182,
|
||||
kSYS_seteuid = 183,
|
||||
kSYS_stat = 188,
|
||||
kSYS_fstat = 189,
|
||||
kSYS_lstat = 190,
|
||||
kSYS_pathconf = 191,
|
||||
kSYS_fpathconf = 192,
|
||||
kSYS_getrlimit = 194,
|
||||
kSYS_setrlimit = 195,
|
||||
kSYS_getdirentries = 196,
|
||||
kSYS_freebsd6_mmap = 197,
|
||||
kSYS___syscall = 198,
|
||||
kSYS_freebsd6_lseek = 199,
|
||||
kSYS_freebsd6_truncate = 200,
|
||||
kSYS_freebsd6_ftruncate = 201,
|
||||
kSYS___sysctl = 202,
|
||||
kSYS_mlock = 203,
|
||||
kSYS_munlock = 204,
|
||||
kSYS_undelete = 205,
|
||||
kSYS_futimes = 206,
|
||||
kSYS_getpgid = 207,
|
||||
kSYS_poll = 209,
|
||||
kSYS_freebsd7___semctl = 220,
|
||||
kSYS_semget = 221,
|
||||
kSYS_semop = 222,
|
||||
kSYS_freebsd7_msgctl = 224,
|
||||
kSYS_msgget = 225,
|
||||
kSYS_msgsnd = 226,
|
||||
kSYS_msgrcv = 227,
|
||||
kSYS_shmat = 228,
|
||||
kSYS_freebsd7_shmctl = 229,
|
||||
kSYS_shmdt = 230,
|
||||
kSYS_shmget = 231,
|
||||
kSYS_clock_gettime = 232,
|
||||
kSYS_clock_settime = 233,
|
||||
kSYS_clock_getres = 234,
|
||||
kSYS_ktimer_create = 235,
|
||||
kSYS_ktimer_delete = 236,
|
||||
kSYS_ktimer_settime = 237,
|
||||
kSYS_ktimer_gettime = 238,
|
||||
kSYS_ktimer_getoverrun = 239,
|
||||
kSYS_nanosleep = 240,
|
||||
kSYS_ffclock_getcounter = 241,
|
||||
kSYS_ffclock_setestimate = 242,
|
||||
kSYS_ffclock_getestimate = 243,
|
||||
kSYS_clock_getcpuclockid2 = 247,
|
||||
kSYS_ntp_gettime = 248,
|
||||
kSYS_minherit = 250,
|
||||
kSYS_rfork = 251,
|
||||
kSYS_openbsd_poll = 252,
|
||||
kSYS_issetugid = 253,
|
||||
kSYS_lchown = 254,
|
||||
kSYS_aio_read = 255,
|
||||
kSYS_aio_write = 256,
|
||||
kSYS_lio_listio = 257,
|
||||
kSYS_getdents = 272,
|
||||
kSYS_lchmod = 274,
|
||||
kSYS_netbsd_lchown = 275,
|
||||
kSYS_lutimes = 276,
|
||||
kSYS_netbsd_msync = 277,
|
||||
kSYS_nstat = 278,
|
||||
kSYS_nfstat = 279,
|
||||
kSYS_nlstat = 280,
|
||||
kSYS_preadv = 289,
|
||||
kSYS_pwritev = 290,
|
||||
kSYS_freebsd4_fhstatfs = 297,
|
||||
kSYS_fhopen = 298,
|
||||
kSYS_fhstat = 299,
|
||||
kSYS_modnext = 300,
|
||||
kSYS_modstat = 301,
|
||||
kSYS_modfnext = 302,
|
||||
kSYS_modfind = 303,
|
||||
kSYS_kldload = 304,
|
||||
kSYS_kldunload = 305,
|
||||
kSYS_kldfind = 306,
|
||||
kSYS_kldnext = 307,
|
||||
kSYS_kldstat = 308,
|
||||
kSYS_kldfirstmod = 309,
|
||||
kSYS_getsid = 310,
|
||||
kSYS_setresuid = 311,
|
||||
kSYS_setresgid = 312,
|
||||
kSYS_aio_return = 314,
|
||||
kSYS_aio_suspend = 315,
|
||||
kSYS_aio_cancel = 316,
|
||||
kSYS_aio_error = 317,
|
||||
kSYS_oaio_read = 318,
|
||||
kSYS_oaio_write = 319,
|
||||
kSYS_olio_listio = 320,
|
||||
kSYS_yield = 321,
|
||||
kSYS_mlockall = 324,
|
||||
kSYS_munlockall = 325,
|
||||
kSYS___getcwd = 326,
|
||||
kSYS_sched_setparam = 327,
|
||||
kSYS_sched_getparam = 328,
|
||||
kSYS_sched_setscheduler = 329,
|
||||
kSYS_sched_getscheduler = 330,
|
||||
kSYS_sched_yield = 331,
|
||||
kSYS_sched_get_priority_max = 332,
|
||||
kSYS_sched_get_priority_min = 333,
|
||||
kSYS_sched_rr_get_interval = 334,
|
||||
kSYS_utrace = 335,
|
||||
kSYS_freebsd4_sendfile = 336,
|
||||
kSYS_kldsym = 337,
|
||||
kSYS_jail = 338,
|
||||
kSYS_nnpfs_syscall = 339,
|
||||
kSYS_sigprocmask = 340,
|
||||
kSYS_sigsuspend = 341,
|
||||
kSYS_freebsd4_sigaction = 342,
|
||||
kSYS_sigpending = 343,
|
||||
kSYS_freebsd4_sigreturn = 344,
|
||||
kSYS_sigtimedwait = 345,
|
||||
kSYS_sigwaitinfo = 346,
|
||||
kSYS___acl_get_file = 347,
|
||||
kSYS___acl_set_file = 348,
|
||||
kSYS___acl_get_fd = 349,
|
||||
kSYS___acl_set_fd = 350,
|
||||
kSYS___acl_delete_file = 351,
|
||||
kSYS___acl_delete_fd = 352,
|
||||
kSYS___acl_aclcheck_file = 353,
|
||||
kSYS___acl_aclcheck_fd = 354,
|
||||
kSYS_extattrctl = 355,
|
||||
kSYS_extattr_set_file = 356,
|
||||
kSYS_extattr_get_file = 357,
|
||||
kSYS_extattr_delete_file = 358,
|
||||
kSYS_aio_waitcomplete = 359,
|
||||
kSYS_getresuid = 360,
|
||||
kSYS_getresgid = 361,
|
||||
kSYS_kqueue = 362,
|
||||
kSYS_kevent = 363,
|
||||
kSYS_extattr_set_fd = 371,
|
||||
kSYS_extattr_get_fd = 372,
|
||||
kSYS_extattr_delete_fd = 373,
|
||||
kSYS___setugid = 374,
|
||||
kSYS_eaccess = 376,
|
||||
kSYS_afs3_syscall = 377,
|
||||
kSYS_nmount = 378,
|
||||
kSYS___mac_get_proc = 384,
|
||||
kSYS___mac_set_proc = 385,
|
||||
kSYS___mac_get_fd = 386,
|
||||
kSYS___mac_get_file = 387,
|
||||
kSYS___mac_set_fd = 388,
|
||||
kSYS___mac_set_file = 389,
|
||||
kSYS_kenv = 390,
|
||||
kSYS_lchflags = 391,
|
||||
kSYS_uuidgen = 392,
|
||||
kSYS_sendfile = 393,
|
||||
kSYS_mac_syscall = 394,
|
||||
kSYS_getfsstat = 395,
|
||||
kSYS_statfs = 396,
|
||||
kSYS_fstatfs = 397,
|
||||
kSYS_fhstatfs = 398,
|
||||
kSYS_ksem_close = 400,
|
||||
kSYS_ksem_post = 401,
|
||||
kSYS_ksem_wait = 402,
|
||||
kSYS_ksem_trywait = 403,
|
||||
kSYS_ksem_init = 404,
|
||||
kSYS_ksem_open = 405,
|
||||
kSYS_ksem_unlink = 406,
|
||||
kSYS_ksem_getvalue = 407,
|
||||
kSYS_ksem_destroy = 408,
|
||||
kSYS___mac_get_pid = 409,
|
||||
kSYS___mac_get_link = 410,
|
||||
kSYS___mac_set_link = 411,
|
||||
kSYS_extattr_set_link = 412,
|
||||
kSYS_extattr_get_link = 413,
|
||||
kSYS_extattr_delete_link = 414,
|
||||
kSYS___mac_execve = 415,
|
||||
kSYS_sigaction = 416,
|
||||
kSYS_sigreturn = 417,
|
||||
kSYS_getcontext = 421,
|
||||
kSYS_setcontext = 422,
|
||||
kSYS_swapcontext = 423,
|
||||
kSYS_swapoff = 424,
|
||||
kSYS___acl_get_link = 425,
|
||||
kSYS___acl_set_link = 426,
|
||||
kSYS___acl_delete_link = 427,
|
||||
kSYS___acl_aclcheck_link = 428,
|
||||
kSYS_sigwait = 429,
|
||||
kSYS_thr_create = 430,
|
||||
kSYS_thr_exit = 431,
|
||||
kSYS_thr_self = 432,
|
||||
kSYS_thr_kill = 433,
|
||||
kSYS__umtx_lock = 434,
|
||||
kSYS__umtx_unlock = 435,
|
||||
kSYS_jail_attach = 436,
|
||||
kSYS_extattr_list_fd = 437,
|
||||
kSYS_extattr_list_file = 438,
|
||||
kSYS_extattr_list_link = 439,
|
||||
kSYS_ksem_timedwait = 441,
|
||||
kSYS_thr_suspend = 442,
|
||||
kSYS_thr_wake = 443,
|
||||
kSYS_kldunloadf = 444,
|
||||
kSYS_audit = 445,
|
||||
kSYS_auditon = 446,
|
||||
kSYS_getauid = 447,
|
||||
kSYS_setauid = 448,
|
||||
kSYS_getaudit = 449,
|
||||
kSYS_setaudit = 450,
|
||||
kSYS_getaudit_addr = 451,
|
||||
kSYS_setaudit_addr = 452,
|
||||
kSYS_auditctl = 453,
|
||||
kSYS__umtx_op = 454,
|
||||
kSYS_thr_new = 455,
|
||||
kSYS_sigqueue = 456,
|
||||
kSYS_kmq_open = 457,
|
||||
kSYS_kmq_setattr = 458,
|
||||
kSYS_kmq_timedreceive = 459,
|
||||
kSYS_kmq_timedsend = 460,
|
||||
kSYS_kmq_notify = 461,
|
||||
kSYS_kmq_unlink = 462,
|
||||
kSYS_abort2 = 463,
|
||||
kSYS_thr_set_name = 464,
|
||||
kSYS_aio_fsync = 465,
|
||||
kSYS_rtprio_thread = 466,
|
||||
kSYS_sctp_peeloff = 471,
|
||||
kSYS_sctp_generic_sendmsg = 472,
|
||||
kSYS_sctp_generic_sendmsg_iov = 473,
|
||||
kSYS_sctp_generic_recvmsg = 474,
|
||||
kSYS_pread = 475,
|
||||
kSYS_pwrite = 476,
|
||||
kSYS_mmap = 477,
|
||||
kSYS_lseek = 478,
|
||||
kSYS_truncate = 479,
|
||||
kSYS_ftruncate = 480,
|
||||
kSYS_thr_kill2 = 481,
|
||||
kSYS_shm_open = 482,
|
||||
kSYS_shm_unlink = 483,
|
||||
kSYS_cpuset = 484,
|
||||
kSYS_cpuset_setid = 485,
|
||||
kSYS_cpuset_getid = 486,
|
||||
kSYS_cpuset_getaffinity = 487,
|
||||
kSYS_cpuset_setaffinity = 488,
|
||||
kSYS_faccessat = 489,
|
||||
kSYS_fchmodat = 490,
|
||||
kSYS_fchownat = 491,
|
||||
kSYS_fexecve = 492,
|
||||
kSYS_fstatat = 493,
|
||||
kSYS_futimesat = 494,
|
||||
kSYS_linkat = 495,
|
||||
kSYS_mkdirat = 496,
|
||||
kSYS_mkfifoat = 497,
|
||||
kSYS_mknodat = 498,
|
||||
kSYS_openat = 499,
|
||||
kSYS_readlinkat = 500,
|
||||
kSYS_renameat = 501,
|
||||
kSYS_symlinkat = 502,
|
||||
kSYS_unlinkat = 503,
|
||||
kSYS_posix_openpt = 504,
|
||||
kSYS_gssd_syscall = 505,
|
||||
kSYS_jail_get = 506,
|
||||
kSYS_jail_set = 507,
|
||||
kSYS_jail_remove = 508,
|
||||
kSYS_closefrom = 509,
|
||||
kSYS___semctl = 510,
|
||||
kSYS_msgctl = 511,
|
||||
kSYS_shmctl = 512,
|
||||
kSYS_lpathconf = 513,
|
||||
kSYS_cap_new = 514,
|
||||
kSYS_cap_getrights = 515,
|
||||
kSYS_cap_enter = 516,
|
||||
kSYS_cap_getmode = 517,
|
||||
kSYS_pdfork = 518,
|
||||
kSYS_pdkill = 519,
|
||||
kSYS_pdgetpid = 520,
|
||||
kSYS_pselect = 522,
|
||||
kSYS_getloginclass = 523,
|
||||
kSYS_setloginclass = 524,
|
||||
kSYS_rctl_get_racct = 525,
|
||||
kSYS_rctl_get_rules = 526,
|
||||
kSYS_rctl_get_limits = 527,
|
||||
kSYS_rctl_add_rule = 528,
|
||||
kSYS_rctl_remove_rule = 529,
|
||||
kSYS_posix_fallocate = 530,
|
||||
kSYS_posix_fadvise = 531,
|
||||
|
||||
kSYS_netcontrol = 99,
|
||||
kSYS_netabort = 101,
|
||||
kSYS_netgetsockinfo = 102,
|
||||
kSYS_socketex = 113,
|
||||
kSYS_socketclose = 114,
|
||||
kSYS_netgetiflist = 125,
|
||||
kSYS_kqueueex = 141,
|
||||
kSYS_mtypeprotect = 379,
|
||||
kSYS_regmgr_call = 532,
|
||||
kSYS_jitshm_create = 533,
|
||||
kSYS_jitshm_alias = 534,
|
||||
kSYS_dl_get_list = 535,
|
||||
kSYS_dl_get_info = 536,
|
||||
kSYS_dl_notify_event = 537,
|
||||
kSYS_evf_create = 538,
|
||||
kSYS_evf_delete = 539,
|
||||
kSYS_evf_open = 540,
|
||||
kSYS_evf_close = 541,
|
||||
kSYS_evf_wait = 542,
|
||||
kSYS_evf_trywait = 543,
|
||||
kSYS_evf_set = 544,
|
||||
kSYS_evf_clear = 545,
|
||||
kSYS_evf_cancel = 546,
|
||||
kSYS_query_memory_protection = 547,
|
||||
kSYS_batch_map = 548,
|
||||
kSYS_osem_create = 549,
|
||||
kSYS_osem_delete = 550,
|
||||
kSYS_osem_open = 551,
|
||||
kSYS_osem_close = 552,
|
||||
kSYS_osem_wait = 553,
|
||||
kSYS_osem_trywait = 554,
|
||||
kSYS_osem_post = 555,
|
||||
kSYS_osem_cancel = 556,
|
||||
kSYS_namedobj_create = 557,
|
||||
kSYS_namedobj_delete = 558,
|
||||
kSYS_set_vm_container = 559,
|
||||
kSYS_debug_init = 560,
|
||||
kSYS_suspend_process = 561,
|
||||
kSYS_resume_process = 562,
|
||||
kSYS_opmc_enable = 563,
|
||||
kSYS_opmc_disable = 564,
|
||||
kSYS_opmc_set_ctl = 565,
|
||||
kSYS_opmc_set_ctr = 566,
|
||||
kSYS_opmc_get_ctr = 567,
|
||||
kSYS_budget_create = 568,
|
||||
kSYS_budget_delete = 569,
|
||||
kSYS_budget_get = 570,
|
||||
kSYS_budget_set = 571,
|
||||
kSYS_virtual_query = 572,
|
||||
kSYS_mdbg_call = 573,
|
||||
kSYS_obs_sblock_create = 574,
|
||||
kSYS_obs_sblock_delete = 575,
|
||||
kSYS_obs_sblock_enter = 576,
|
||||
kSYS_obs_sblock_exit = 577,
|
||||
kSYS_obs_sblock_xenter = 578,
|
||||
kSYS_obs_sblock_xexit = 579,
|
||||
kSYS_obs_eport_create = 580,
|
||||
kSYS_obs_eport_delete = 581,
|
||||
kSYS_obs_eport_trigger = 582,
|
||||
kSYS_obs_eport_open = 583,
|
||||
kSYS_obs_eport_close = 584,
|
||||
kSYS_is_in_sandbox = 585,
|
||||
kSYS_dmem_container = 586,
|
||||
kSYS_get_authinfo = 587,
|
||||
kSYS_mname = 588,
|
||||
kSYS_dynlib_dlopen = 589,
|
||||
kSYS_dynlib_dlclose = 590,
|
||||
kSYS_dynlib_dlsym = 591,
|
||||
kSYS_dynlib_get_list = 592,
|
||||
kSYS_dynlib_get_info = 593,
|
||||
kSYS_dynlib_load_prx = 594,
|
||||
kSYS_dynlib_unload_prx = 595,
|
||||
kSYS_dynlib_do_copy_relocations = 596,
|
||||
kSYS_dynlib_prepare_dlclose = 597,
|
||||
kSYS_dynlib_get_proc_param = 598,
|
||||
kSYS_dynlib_process_needed_and_relocate = 599,
|
||||
kSYS_sandbox_path = 600,
|
||||
kSYS_mdbg_service = 601,
|
||||
kSYS_randomized_path = 602,
|
||||
kSYS_rdup = 603,
|
||||
kSYS_dl_get_metadata = 604,
|
||||
kSYS_workaround8849 = 605,
|
||||
kSYS_is_development_mode = 606,
|
||||
kSYS_get_self_auth_info = 607,
|
||||
kSYS_dynlib_get_info_ex = 608,
|
||||
kSYS_budget_getid = 609,
|
||||
kSYS_budget_get_ptype = 610,
|
||||
kSYS_get_paging_stats_of_all_threads = 611,
|
||||
kSYS_get_proc_type_info = 612,
|
||||
kSYS_get_resident_count = 613,
|
||||
kSYS_prepare_to_suspend_process = 614,
|
||||
kSYS_get_resident_fmem_count = 615,
|
||||
kSYS_thr_get_name = 616,
|
||||
kSYS_set_gpo = 617,
|
||||
kSYS_get_paging_stats_of_all_objects = 618,
|
||||
kSYS_test_debug_rwmem = 619,
|
||||
kSYS_free_stack = 620,
|
||||
kSYS_suspend_system = 621,
|
||||
kSYS_ipmimgr_call = 622,
|
||||
kSYS_get_gpo = 623,
|
||||
kSYS_get_vm_map_timestamp = 624,
|
||||
kSYS_opmc_set_hw = 625,
|
||||
kSYS_opmc_get_hw = 626,
|
||||
kSYS_get_cpu_usage_all = 627,
|
||||
kSYS_mmap_dmem = 628,
|
||||
kSYS_physhm_open = 629,
|
||||
kSYS_physhm_unlink = 630,
|
||||
kSYS_resume_internal_hdd = 631,
|
||||
kSYS_thr_suspend_ucontext = 632,
|
||||
kSYS_thr_resume_ucontext = 633,
|
||||
kSYS_thr_get_ucontext = 634,
|
||||
kSYS_thr_set_ucontext = 635,
|
||||
kSYS_set_timezone_info = 636,
|
||||
kSYS_set_phys_fmem_limit = 637,
|
||||
kSYS_utc_to_localtime = 638,
|
||||
kSYS_localtime_to_utc = 639,
|
||||
kSYS_set_uevt = 640,
|
||||
kSYS_get_cpu_usage_proc = 641,
|
||||
kSYS_get_map_statistics = 642,
|
||||
kSYS_set_chicken_switches = 643,
|
||||
kSYS_extend_page_table_pool = 644,
|
||||
kSYS_extend_page_table_pool2 = 645,
|
||||
kSYS_get_kernel_mem_statistics = 646,
|
||||
kSYS_get_sdk_compiled_version = 647,
|
||||
kSYS_app_state_change = 648,
|
||||
kSYS_dynlib_get_obj_member = 649,
|
||||
kSYS_budget_get_ptype_of_budget = 650,
|
||||
kSYS_prepare_to_resume_process = 651,
|
||||
kSYS_process_terminate = 652,
|
||||
kSYS_blockpool_open = 653,
|
||||
kSYS_blockpool_map = 654,
|
||||
kSYS_blockpool_unmap = 655,
|
||||
kSYS_dynlib_get_info_for_libdbg = 656,
|
||||
kSYS_blockpool_batch = 657,
|
||||
kSYS_fdatasync = 658,
|
||||
kSYS_dynlib_get_list2 = 659,
|
||||
kSYS_dynlib_get_info2 = 660,
|
||||
kSYS_aio_submit = 661,
|
||||
kSYS_aio_multi_delete = 662,
|
||||
kSYS_aio_multi_wait = 663,
|
||||
kSYS_aio_multi_poll = 664,
|
||||
kSYS_aio_get_data = 665,
|
||||
kSYS_aio_multi_cancel = 666,
|
||||
kSYS_get_bio_usage_all = 667,
|
||||
kSYS_aio_create = 668,
|
||||
kSYS_aio_submit_cmd = 669,
|
||||
kSYS_aio_init = 670,
|
||||
kSYS_get_page_table_stats = 671,
|
||||
kSYS_dynlib_get_list_for_libdbg = 672,
|
||||
kSYS_blockpool_move = 673,
|
||||
kSYS_virtual_query_all = 674,
|
||||
kSYS_reserve_2mb_page = 675,
|
||||
kSYS_cpumode_yield = 676,
|
||||
|
||||
kSYS_wait6 = 677,
|
||||
kSYS_cap_rights_limit = 678,
|
||||
kSYS_cap_ioctls_limit = 679,
|
||||
kSYS_cap_ioctls_get = 680,
|
||||
kSYS_cap_fcntls_limit = 681,
|
||||
kSYS_cap_fcntls_get = 682,
|
||||
kSYS_bindat = 683,
|
||||
kSYS_connectat = 684,
|
||||
kSYS_chflagsat = 685,
|
||||
kSYS_accept4 = 686,
|
||||
kSYS_pipe2 = 687,
|
||||
kSYS_aio_mlock = 688,
|
||||
kSYS_procctl = 689,
|
||||
kSYS_ppoll = 690,
|
||||
kSYS_futimens = 691,
|
||||
kSYS_utimensat = 692,
|
||||
kSYS_numa_getaffinity = 693,
|
||||
kSYS_numa_setaffinity = 694,
|
||||
kSYS_apr_submit = 700,
|
||||
kSYS_apr_resolve = 701,
|
||||
kSYS_apr_stat = 702,
|
||||
kSYS_apr_wait = 703,
|
||||
kSYS_apr_ctrl = 704,
|
||||
kSYS_get_phys_page_size = 705,
|
||||
kSYS_begin_app_mount = 706,
|
||||
kSYS_end_app_mount = 707,
|
||||
kSYS_fsc2h_ctrl = 708,
|
||||
kSYS_streamwrite = 709,
|
||||
kSYS_app_save = 710,
|
||||
kSYS_app_restore = 711,
|
||||
kSYS_saved_app_delete = 712,
|
||||
kSYS_get_ppr_sdk_compiled_version = 713,
|
||||
kSYS_notify_app_event = 714,
|
||||
kSYS_ioreq = 715,
|
||||
kSYS_openintr = 716,
|
||||
kSYS_dl_get_info_2 = 717,
|
||||
kSYS_acinfo_add = 718,
|
||||
kSYS_acinfo_delete = 719,
|
||||
kSYS_acinfo_get_all_for_coredump = 720,
|
||||
kSYS_ampr_ctrl_debug = 721,
|
||||
kSYS_workspace_ctrl = 722,
|
||||
};
|
||||
} // namespace orbis
|
||||
15
kernel/orbis/include/orbis/sys/sysentry.hpp
Normal file
15
kernel/orbis/include/orbis/sys/sysentry.hpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
#include "orbis/thread/sysent.hpp"
|
||||
|
||||
namespace orbis {
|
||||
extern sysentvec freebsd9_sysvec;
|
||||
extern sysentvec freebsd11_sysvec;
|
||||
extern sysentvec ps4_sysvec;
|
||||
extern sysentvec ps5_sysvec;
|
||||
|
||||
struct Thread;
|
||||
void syscall_entry(Thread *thread);
|
||||
const char *getSysentName(SysResult (*sysent)(Thread *, uint64_t *));
|
||||
} // namespace orbis
|
||||
854
kernel/orbis/include/orbis/sys/sysproto.hpp
Normal file
854
kernel/orbis/include/orbis/sys/sysproto.hpp
Normal file
|
|
@ -0,0 +1,854 @@
|
|||
#include "orbis-config.hpp"
|
||||
#include <orbis/Budget.hpp>
|
||||
#include <orbis/error.hpp>
|
||||
#include <orbis/module/ModuleHandle.hpp>
|
||||
#include <orbis/thread/cpuset.hpp>
|
||||
#include <orbis/thread/types.hpp>
|
||||
|
||||
namespace orbis {
|
||||
using acl_type_t = sint;
|
||||
using key_t = sint;
|
||||
using semid_t = uint64_t;
|
||||
using cpusetid_t = sint;
|
||||
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;
|
||||
struct AppMountInfo;
|
||||
|
||||
SysResult nosys(Thread *thread);
|
||||
|
||||
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<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);
|
||||
SysResult sys_link(Thread *thread, ptr<char> path, ptr<char> link);
|
||||
SysResult sys_unlink(Thread *thread, ptr<char> path);
|
||||
SysResult sys_chdir(Thread *thread, ptr<char> path);
|
||||
SysResult sys_fchdir(Thread *thread, sint fd);
|
||||
SysResult sys_mknod(Thread *thread, ptr<char> path, sint mode, sint dev);
|
||||
SysResult sys_chmod(Thread *thread, ptr<char> path, sint mode);
|
||||
SysResult sys_chown(Thread *thread, ptr<char> path, sint uid, sint gid);
|
||||
SysResult sys_obreak(Thread *thread, ptr<char> nsize);
|
||||
SysResult sys_getpid(Thread *thread);
|
||||
SysResult sys_mount(Thread *thread, ptr<char> type, ptr<char> path, sint flags,
|
||||
caddr_t data);
|
||||
SysResult sys_unmount(Thread *thread, ptr<char> path, sint flags);
|
||||
SysResult sys_setuid(Thread *thread, uid_t uid);
|
||||
SysResult sys_getuid(Thread *thread);
|
||||
SysResult sys_geteuid(Thread *thread);
|
||||
SysResult sys_ptrace(Thread *thread, sint req, pid_t pid, caddr_t addr,
|
||||
sint data);
|
||||
SysResult sys_recvmsg(Thread *thread, sint s, ptr<struct msghdr> msg,
|
||||
sint flags);
|
||||
SysResult sys_sendmsg(Thread *thread, sint s, ptr<struct msghdr> msg,
|
||||
sint flags);
|
||||
SysResult sys_recvfrom(Thread *thread, sint s, caddr_t buf, size_t len,
|
||||
sint flags, ptr<SocketAddress> from,
|
||||
ptr<uint32_t> fromlenaddr);
|
||||
SysResult sys_accept(Thread *thread, sint s, ptr<SocketAddress> from,
|
||||
ptr<uint32_t> fromlenaddr);
|
||||
SysResult sys_getpeername(Thread *thread, sint fdes, ptr<SocketAddress> asa,
|
||||
ptr<uint32_t> alen);
|
||||
SysResult sys_getsockname(Thread *thread, sint fdes, ptr<SocketAddress> asa,
|
||||
ptr<uint32_t> alen);
|
||||
SysResult sys_access(Thread *thread, ptr<char> path, sint flags);
|
||||
SysResult sys_chflags(Thread *thread, ptr<char> path, sint flags);
|
||||
SysResult sys_fchflags(Thread *thread, sint fd, sint flags);
|
||||
SysResult sys_sync(Thread *thread);
|
||||
SysResult sys_kill(Thread *thread, sint pid, sint signum);
|
||||
SysResult sys_getppid(Thread *thread);
|
||||
SysResult sys_dup(Thread *thread, uint fd);
|
||||
SysResult sys_pipe(Thread *thread);
|
||||
SysResult sys_getegid(Thread *thread);
|
||||
SysResult sys_profil(Thread *thread, caddr_t samples, size_t size,
|
||||
size_t offset, uint scale);
|
||||
SysResult sys_ktrace(Thread *thread, ptr<const char> fname, sint ops, sint facs,
|
||||
sint pit);
|
||||
SysResult sys_getgid(Thread *thread);
|
||||
SysResult sys_getlogin(Thread *thread, ptr<char> namebuf, uint namelen);
|
||||
SysResult sys_setlogin(Thread *thread, ptr<char> namebuf);
|
||||
SysResult sys_acct(Thread *thread, ptr<char> path);
|
||||
SysResult sys_sigaltstack(Thread *thread, ptr<stack_t> ss, ptr<stack_t> oss);
|
||||
SysResult sys_ioctl(Thread *thread, sint fd, ulong com, caddr_t data);
|
||||
SysResult sys_reboot(Thread *thread, sint opt);
|
||||
SysResult sys_revoke(Thread *thread, ptr<char> path);
|
||||
SysResult sys_symlink(Thread *thread, ptr<char> path, ptr<char> link);
|
||||
SysResult sys_readlink(Thread *thread, ptr<char> path, ptr<char> buf,
|
||||
size_t count);
|
||||
SysResult sys_execve(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv,
|
||||
ptr<ptr<char>> envv);
|
||||
SysResult sys_umask(Thread *thread, sint newmask);
|
||||
SysResult sys_chroot(Thread *thread, ptr<char> path);
|
||||
SysResult sys_msync(Thread *thread, ptr<void> addr, size_t len, sint flags);
|
||||
SysResult sys_vfork(Thread *thread);
|
||||
SysResult sys_sbrk(Thread *thread, sint incr);
|
||||
SysResult sys_sstk(Thread *thread, sint incr);
|
||||
SysResult sys_ovadvise(Thread *thread, sint anom);
|
||||
SysResult sys_munmap(Thread *thread, ptr<void> addr, size_t len);
|
||||
SysResult sys_mprotect(Thread *thread, ptr<const void> addr, size_t len,
|
||||
sint prot);
|
||||
SysResult sys_madvise(Thread *thread, ptr<void> addr, size_t len, sint behav);
|
||||
SysResult sys_mincore(Thread *thread, ptr<const void> addr, size_t len,
|
||||
ptr<char> vec);
|
||||
SysResult sys_getgroups(Thread *thread, uint gidsetsize, ptr<gid_t> gidset);
|
||||
SysResult sys_setgroups(Thread *thread, uint gidsetsize, ptr<gid_t> gidset);
|
||||
SysResult sys_getpgrp(Thread *thread);
|
||||
SysResult sys_setpgid(Thread *thread, sint pid, sint pgid);
|
||||
SysResult sys_setitimer(Thread *thread, uint which, ptr<struct itimerval> itv,
|
||||
ptr<struct itimerval> oitv);
|
||||
SysResult sys_swapon(Thread *thread, ptr<char> name);
|
||||
SysResult sys_getitimer(Thread *thread, uint which, ptr<struct itimerval> itv);
|
||||
SysResult sys_getdtablesize(Thread *thread);
|
||||
SysResult sys_dup2(Thread *thread, uint from, uint to);
|
||||
SysResult sys_fcntl(Thread *thread, sint fd, sint cmd, slong arg);
|
||||
SysResult sys_select(Thread *thread, sint nd, ptr<struct fd_set_t> in,
|
||||
ptr<struct fd_set_t> out, ptr<struct fd_set_t> ex,
|
||||
ptr<struct timeval> tv);
|
||||
SysResult sys_fsync(Thread *thread, sint fd);
|
||||
SysResult sys_setpriority(Thread *thread, sint which, sint who, sint prio);
|
||||
SysResult sys_socket(Thread *thread, sint domain, sint type, sint protocol);
|
||||
SysResult sys_connect(Thread *thread, sint s, caddr_t name, sint namelen);
|
||||
SysResult sys_getpriority(Thread *thread, sint which, sint who);
|
||||
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<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<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);
|
||||
SysResult sys_setregid(Thread *thread, sint rgid, sint egid);
|
||||
SysResult sys_rename(Thread *thread, ptr<char> from, ptr<char> to);
|
||||
SysResult sys_flock(Thread *thread, sint fd, sint how);
|
||||
SysResult sys_mkfifo(Thread *thread, ptr<char> path, sint mode);
|
||||
SysResult sys_sendto(Thread *thread, sint s, caddr_t buf, size_t len,
|
||||
sint flags, caddr_t to, sint tolen);
|
||||
SysResult sys_shutdown(Thread *thread, sint s, sint how);
|
||||
SysResult sys_socketpair(Thread *thread, sint domain, sint type, sint protocol,
|
||||
ptr<sint> rsv);
|
||||
SysResult sys_mkdir(Thread *thread, ptr<char> path, sint mode);
|
||||
SysResult sys_rmdir(Thread *thread, ptr<char> path);
|
||||
SysResult sys_utimes(Thread *thread, ptr<char> path, ptr<struct timeval> tptr);
|
||||
SysResult sys_adjtime(Thread *thread, ptr<struct timeval> delta,
|
||||
ptr<struct timeval> olddelta);
|
||||
SysResult sys_setsid(Thread *thread);
|
||||
SysResult sys_quotactl(Thread *thread, ptr<char> path, sint cmd, sint uid,
|
||||
caddr_t arg);
|
||||
SysResult sys_nlm_syscall(Thread *thread, sint debug_level, sint grace_period,
|
||||
sint addr_count, ptr<ptr<char>> addrs);
|
||||
SysResult sys_nfssvc(Thread *thread, sint flag, caddr_t argp);
|
||||
SysResult sys_lgetfh(Thread *thread, ptr<char> fname, ptr<struct fhandle> fhp);
|
||||
SysResult sys_getfh(Thread *thread, ptr<char> fname, ptr<struct fhandle> fhp);
|
||||
SysResult sys_sysarch(Thread *thread, sint op, ptr<char> parms);
|
||||
SysResult sys_rtprio(Thread *thread, sint function, pid_t pid,
|
||||
ptr<struct rtprio> rtp);
|
||||
SysResult sys_semsys(Thread *thread, sint which, sint a2, sint a3, sint a4,
|
||||
sint a5);
|
||||
SysResult sys_msgsys(Thread *thread, sint which, sint a2, sint a3, sint a4,
|
||||
sint a5, sint a6);
|
||||
SysResult sys_shmsys(Thread *thread, sint which, sint a2, sint a3, sint a4);
|
||||
SysResult sys_freebsd6_pread(Thread *thread, sint fd, ptr<void> buf,
|
||||
size_t nbyte, sint pad, off_t offset);
|
||||
SysResult sys_freebsd6_pwrite(Thread *thread, sint fd, ptr<const void> buf,
|
||||
size_t nbyte, sint pad, off_t offset);
|
||||
SysResult sys_setfib(Thread *thread, sint fib);
|
||||
SysResult sys_ntp_adjtime(Thread *thread, ptr<struct timex> tp);
|
||||
SysResult sys_setgid(Thread *thread, gid_t gid);
|
||||
SysResult sys_setegid(Thread *thread, gid_t egid);
|
||||
SysResult sys_seteuid(Thread *thread, uid_t euid);
|
||||
SysResult sys_stat(Thread *thread, ptr<char> path, ptr<Stat> ub);
|
||||
SysResult sys_fstat(Thread *thread, sint fd, ptr<Stat> ub);
|
||||
SysResult sys_lstat(Thread *thread, ptr<char> path, ptr<Stat> ub);
|
||||
SysResult sys_pathconf(Thread *thread, ptr<char> path, sint name);
|
||||
SysResult sys_fpathconf(Thread *thread, sint fd, sint name);
|
||||
SysResult sys_getrlimit(Thread *thread, uint which, ptr<struct rlimit> rlp);
|
||||
SysResult sys_setrlimit(Thread *thread, uint which, ptr<struct rlimit> rlp);
|
||||
SysResult sys_getdirentries(Thread *thread, sint fd, ptr<char> buf, uint count,
|
||||
ptr<slong> basep);
|
||||
SysResult sys_freebsd6_mmap(Thread *thread, caddr_t addr, size_t len, sint prot,
|
||||
sint flags, sint fd, sint pad, off_t pos);
|
||||
SysResult sys_freebsd6_lseek(Thread *thread, sint fd, sint pad, off_t offset,
|
||||
sint whence);
|
||||
SysResult sys_freebsd6_truncate(Thread *thread, ptr<char> path, sint pad,
|
||||
off_t length);
|
||||
SysResult sys_freebsd6_ftruncate(Thread *thread, sint fd, sint pad,
|
||||
off_t length);
|
||||
SysResult sys___sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
||||
ptr<void> old, ptr<size_t> oldenp, ptr<void> new_,
|
||||
size_t newlen);
|
||||
SysResult sys_mlock(Thread *thread, ptr<const void> addr, size_t len);
|
||||
SysResult sys_munlock(Thread *thread, ptr<const void> addr, size_t len);
|
||||
SysResult sys_undelete(Thread *thread, ptr<char> path);
|
||||
SysResult sys_futimes(Thread *thread, sint fd, ptr<struct timeval> tptr);
|
||||
SysResult sys_getpgid(Thread *thread, pid_t pid);
|
||||
SysResult sys_poll(Thread *thread, ptr<struct pollfd> fds, uint nfds,
|
||||
sint timeout);
|
||||
SysResult sys_semget(Thread *thread, key_t key, sint nsems, sint semflg);
|
||||
SysResult sys_semop(Thread *thread, sint semid, ptr<struct sembuf> sops,
|
||||
size_t nspos);
|
||||
SysResult sys_msgget(Thread *thread, key_t key, sint msgflg);
|
||||
SysResult sys_msgsnd(Thread *thread, sint msqid, ptr<const void> msgp,
|
||||
size_t msgsz, sint msgflg);
|
||||
SysResult sys_msgrcv(Thread *thread, sint msqid, ptr<void> msgp, size_t msgsz,
|
||||
slong msgtyp, sint msgflg);
|
||||
SysResult sys_shmat(Thread *thread, sint shmid, ptr<const void> shmaddr,
|
||||
sint shmflg);
|
||||
SysResult sys_shmdt(Thread *thread, ptr<const void> shmaddr);
|
||||
SysResult sys_shmget(Thread *thread, key_t key, size_t size, sint shmflg);
|
||||
SysResult sys_clock_gettime(Thread *thread, clockid_t clock_id,
|
||||
ptr<timespec> tp);
|
||||
SysResult sys_clock_settime(Thread *thread, clockid_t clock_id,
|
||||
ptr<const timespec> tp);
|
||||
SysResult sys_clock_getres(Thread *thread, clockid_t clock_id,
|
||||
ptr<timespec> tp);
|
||||
SysResult sys_ktimer_create(Thread *thread, clockid_t clock_id,
|
||||
ptr<struct sigevent> evp, ptr<sint> timerid);
|
||||
SysResult sys_ktimer_delete(Thread *thread, sint timerid);
|
||||
SysResult sys_ktimer_settime(Thread *thread, sint timerid, sint flags,
|
||||
ptr<const struct itimerspec> value,
|
||||
ptr<struct itimerspec> ovalue);
|
||||
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<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);
|
||||
SysResult sys_rfork(Thread *thread, sint flags);
|
||||
SysResult sys_openbsd_poll(Thread *thread, ptr<struct pollfd> fds, uint nfds,
|
||||
sint timeout);
|
||||
SysResult sys_issetugid(Thread *thread);
|
||||
SysResult sys_lchown(Thread *thread, ptr<char> path, sint uid, sint gid);
|
||||
SysResult sys_aio_read(Thread *thread, ptr<struct aiocb> aiocbp);
|
||||
SysResult sys_aio_write(Thread *thread, ptr<struct aiocb> aiocbp);
|
||||
SysResult sys_lio_listio(Thread *thread, sint mode,
|
||||
ptr<cptr<struct aiocb>> aiocbp, sint nent,
|
||||
ptr<struct sigevent> sig);
|
||||
SysResult sys_getdents(Thread *thread, sint fd, ptr<char> buf, size_t count);
|
||||
SysResult sys_lchmod(Thread *thread, ptr<char> path, mode_t mode);
|
||||
SysResult sys_lutimes(Thread *thread, ptr<char> path, ptr<struct timeval> tptr);
|
||||
SysResult sys_nstat(Thread *thread, ptr<char> path, ptr<struct nstat> ub);
|
||||
SysResult sys_nfstat(Thread *thread, sint fd, ptr<struct nstat> sb);
|
||||
SysResult sys_nlstat(Thread *thread, ptr<char> path, ptr<struct nstat> ub);
|
||||
SysResult sys_preadv(Thread *thread, sint fd, ptr<IoVec> iovp, uint iovcnt,
|
||||
off_t offset);
|
||||
SysResult sys_pwritev(Thread *thread, sint fd, ptr<IoVec> iovp, uint iovcnt,
|
||||
off_t offset);
|
||||
SysResult sys_fhopen(Thread *thread, ptr<const struct fhandle> u_fhp,
|
||||
sint flags);
|
||||
SysResult sys_fhstat(Thread *thread, ptr<const struct fhandle> u_fhp,
|
||||
ptr<Stat> sb);
|
||||
SysResult sys_modnext(Thread *thread, sint modid);
|
||||
SysResult sys_modstat(Thread *thread, sint modid, ptr<struct module_stat> stat);
|
||||
SysResult sys_modfnext(Thread *thread, sint modid);
|
||||
SysResult sys_modfind(Thread *thread, ptr<const char> name);
|
||||
SysResult sys_kldload(Thread *thread, ptr<const char> file);
|
||||
SysResult sys_kldunload(Thread *thread, sint fileid);
|
||||
SysResult sys_kldfind(Thread *thread, ptr<const char> name);
|
||||
SysResult sys_kldnext(Thread *thread, sint fileid);
|
||||
SysResult sys_kldstat(Thread *thread, sint fileid,
|
||||
ptr<struct kld_file_stat> stat);
|
||||
SysResult sys_kldfirstmod(Thread *thread, sint fileid);
|
||||
SysResult sys_getsid(Thread *thread, pid_t pid);
|
||||
SysResult sys_setresuid(Thread *thread, uid_t ruid, uid_t euid, uid_t suid);
|
||||
SysResult sys_setresgid(Thread *thread, gid_t rgid, gid_t egid, gid_t sgid);
|
||||
SysResult sys_aio_return(Thread *thread, ptr<struct aiocb> aiocbp);
|
||||
SysResult sys_aio_suspend(Thread *thread, ptr<struct aiocb> aiocbp, sint nent,
|
||||
ptr<const timespec> timeout);
|
||||
SysResult sys_aio_cancel(Thread *thread, sint fd, ptr<struct aiocb> aiocbp);
|
||||
SysResult sys_aio_error(Thread *thread, ptr<struct aiocb> aiocbp);
|
||||
SysResult sys_oaio_read(Thread *thread, ptr<struct aiocb> aiocbp);
|
||||
SysResult sys_oaio_write(Thread *thread, ptr<struct aiocb> aiocbp);
|
||||
SysResult sys_olio_listio(Thread *thread, sint mode,
|
||||
ptr<cptr<struct aiocb>> acb_list, sint nent,
|
||||
ptr<struct osigevent> sig);
|
||||
SysResult sys_yield(Thread *thread);
|
||||
SysResult sys_mlockall(Thread *thread, sint how);
|
||||
SysResult sys_munlockall(Thread *thread);
|
||||
SysResult sys___getcwd(Thread *thread, ptr<char> buf, uint buflen);
|
||||
SysResult sys_sched_setparam(Thread *thread, pid_t pid,
|
||||
ptr<const struct sched_param> param);
|
||||
SysResult sys_sched_getparam(Thread *thread, pid_t pid,
|
||||
ptr<struct sched_param> param);
|
||||
SysResult sys_sched_setscheduler(Thread *thread, pid_t pid, sint policy,
|
||||
ptr<const struct sched_param> param);
|
||||
SysResult sys_sched_getscheduler(Thread *thread, pid_t pid);
|
||||
SysResult sys_sched_yield(Thread *thread);
|
||||
SysResult sys_sched_get_priority_max(Thread *thread, sint policy);
|
||||
SysResult sys_sched_get_priority_min(Thread *thread, sint policy);
|
||||
SysResult sys_sched_rr_get_interval(Thread *thread, pid_t pid,
|
||||
ptr<timespec> interval);
|
||||
SysResult sys_utrace(Thread *thread, ptr<const void> addr, size_t len);
|
||||
SysResult sys_kldsym(Thread *thread, sint fileid, sint cmd, ptr<void> data);
|
||||
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<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 SigSet> set,
|
||||
ptr<struct siginfo> info);
|
||||
SysResult sys___acl_get_file(Thread *thread, ptr<char> path, acl_type_t type,
|
||||
ptr<struct acl> aclp);
|
||||
SysResult sys___acl_set_file(Thread *thread, ptr<char> path, acl_type_t type,
|
||||
ptr<struct acl> aclp);
|
||||
SysResult sys___acl_get_fd(Thread *thread, sint filedes, acl_type_t type,
|
||||
ptr<struct acl> aclp);
|
||||
SysResult sys___acl_set_fd(Thread *thread, sint filedes, acl_type_t type,
|
||||
ptr<struct acl> aclp);
|
||||
SysResult sys___acl_delete_file(Thread *thread, ptr<char> path,
|
||||
acl_type_t type);
|
||||
SysResult sys___acl_delete_fd(Thread *thread, sint filedes, acl_type_t type);
|
||||
SysResult sys___acl_aclcheck_file(Thread *thread, ptr<char> path,
|
||||
acl_type_t type, ptr<struct acl> aclp);
|
||||
SysResult sys___acl_aclcheck_fd(Thread *thread, sint filedes, acl_type_t type,
|
||||
ptr<struct acl> aclp);
|
||||
SysResult sys_extattrctl(Thread *thread, ptr<char> path, char cmd,
|
||||
ptr<const char> filename, sint attrnamespace,
|
||||
ptr<const char> attrname);
|
||||
SysResult sys_extattr_set_file(Thread *thread, ptr<char> path,
|
||||
sint attrnamespace, ptr<const char> filename,
|
||||
ptr<void> data, size_t nbytes);
|
||||
SysResult sys_extattr_get_file(Thread *thread, ptr<char> path,
|
||||
sint attrnamespace, ptr<const char> filename,
|
||||
ptr<void> data, size_t nbytes);
|
||||
SysResult sys_extattr_delete_file(Thread *thread, ptr<char> path,
|
||||
sint attrnamespace, ptr<const char> attrname);
|
||||
SysResult sys_aio_waitcomplete(Thread *thread, ptr<ptr<struct aiocb>> aiocbp,
|
||||
ptr<timespec> timeout);
|
||||
SysResult sys_getresuid(Thread *thread, ptr<uid_t> ruid, ptr<uid_t> euid,
|
||||
ptr<uid_t> suid);
|
||||
SysResult sys_getresgid(Thread *thread, ptr<gid_t> rgid, ptr<gid_t> egid,
|
||||
ptr<gid_t> sgid);
|
||||
SysResult sys_kqueue(Thread *thread);
|
||||
SysResult sys_kevent(Thread *thread, sint fd, ptr<KEvent> changelist,
|
||||
sint nchanges, ptr<KEvent> eventlist, sint nevents,
|
||||
ptr<const timespec> timeout);
|
||||
SysResult sys_extattr_set_fd(Thread *thread, sint fd, sint attrnamespace,
|
||||
ptr<const char> attrname, ptr<void> data,
|
||||
size_t nbytes);
|
||||
SysResult sys_extattr_get_fd(Thread *thread, sint fd, sint attrnamespace,
|
||||
ptr<const char> attrname, ptr<void> data,
|
||||
size_t nbytes);
|
||||
SysResult sys_extattr_delete_fd(Thread *thread, sint fd, sint attrnamespace,
|
||||
ptr<const char> attrname);
|
||||
SysResult sys___setugid(Thread *thread, sint flags);
|
||||
SysResult sys_eaccess(Thread *thread, ptr<char> path, sint flags);
|
||||
SysResult sys_afs3_syscall(Thread *thread, slong syscall, slong param1,
|
||||
slong param2, slong param3, slong param4,
|
||||
slong param5, slong param6);
|
||||
SysResult sys_nmount(Thread *thread, ptr<IoVec> iovp, uint iovcnt, sint flags);
|
||||
SysResult sys___mac_get_proc(Thread *thread, ptr<struct mac> mac_p);
|
||||
SysResult sys___mac_set_proc(Thread *thread, ptr<struct mac> mac_p);
|
||||
SysResult sys___mac_get_fd(Thread *thread, sint fd, ptr<struct mac> mac_p);
|
||||
SysResult sys___mac_get_file(Thread *thread, ptr<const char> path,
|
||||
ptr<struct mac> mac_p);
|
||||
SysResult sys___mac_set_fd(Thread *thread, sint fd, ptr<struct mac> mac_p);
|
||||
SysResult sys___mac_set_file(Thread *thread, ptr<const char> path,
|
||||
ptr<struct mac> mac_p);
|
||||
SysResult sys_kenv(Thread *thread, sint what, ptr<const char> name,
|
||||
ptr<char> value, sint len);
|
||||
SysResult sys_lchflags(Thread *thread, ptr<const char> path, sint flags);
|
||||
SysResult sys_uuidgen(Thread *thread, ptr<struct uuid> store, sint count);
|
||||
SysResult sys_sendfile(Thread *thread, sint fd, sint s, off_t offset,
|
||||
size_t nbytes, ptr<struct sf_hdtr> hdtr,
|
||||
ptr<off_t> sbytes, sint flags);
|
||||
SysResult sys_mac_syscall(Thread *thread, ptr<const char> policy, sint call,
|
||||
ptr<void> arg);
|
||||
SysResult sys_getfsstat(Thread *thread, ptr<struct statfs> buf, slong bufsize,
|
||||
sint flags);
|
||||
SysResult sys_statfs(Thread *thread, ptr<char> path, ptr<struct statfs> buf);
|
||||
SysResult sys_fstatfs(Thread *thread, sint fd, ptr<struct statfs> buf);
|
||||
SysResult sys_fhstatfs(Thread *thread, ptr<const struct fhandle> u_fhp,
|
||||
ptr<struct statfs> buf);
|
||||
SysResult sys_ksem_close(Thread *thread, semid_t id);
|
||||
SysResult sys_ksem_post(Thread *thread, semid_t id);
|
||||
SysResult sys_ksem_wait(Thread *thread, semid_t id);
|
||||
SysResult sys_ksem_trywait(Thread *thread, semid_t id);
|
||||
SysResult sys_ksem_init(Thread *thread, ptr<semid_t> idp, uint value);
|
||||
SysResult sys_ksem_open(Thread *thread, ptr<semid_t> idp, ptr<const char> name,
|
||||
sint oflag, mode_t mode, uint value);
|
||||
SysResult sys_ksem_unlink(Thread *thread, ptr<const char> name);
|
||||
SysResult sys_ksem_getvalue(Thread *thread, semid_t id, ptr<sint> value);
|
||||
SysResult sys_ksem_destroy(Thread *thread, semid_t id);
|
||||
SysResult sys___mac_get_pid(Thread *thread, pid_t pid, ptr<struct mac> mac_p);
|
||||
SysResult sys___mac_get_link(Thread *thread, ptr<const char> path_p,
|
||||
ptr<struct mac> mac_p);
|
||||
SysResult sys___mac_set_link(Thread *thread, ptr<const char> path_p,
|
||||
ptr<struct mac> mac_p);
|
||||
SysResult sys_extattr_set_link(Thread *thread, ptr<const char> path,
|
||||
sint attrnamespace, ptr<const char> attrname,
|
||||
ptr<void> data, size_t nbytes);
|
||||
SysResult sys_extattr_get_link(Thread *thread, ptr<const char> path,
|
||||
sint attrnamespace, ptr<const char> attrname,
|
||||
ptr<void> data, size_t nbytes);
|
||||
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<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);
|
||||
SysResult sys___acl_set_link(Thread *thread, ptr<const char> path,
|
||||
acl_type_t type, ptr<struct acl> aclp);
|
||||
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 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);
|
||||
SysResult sys__umtx_lock(Thread *thread, ptr<struct umtx> umtx);
|
||||
SysResult sys__umtx_unlock(Thread *thread, ptr<struct umtx> umtx);
|
||||
SysResult sys_jail_attach(Thread *thread, sint jid);
|
||||
SysResult sys_extattr_list_fd(Thread *thread, sint fd, sint attrnamespace,
|
||||
ptr<void> data, size_t nbytes);
|
||||
SysResult sys_extattr_list_file(Thread *thread, ptr<const char> path,
|
||||
sint attrnamespace, ptr<void> data,
|
||||
size_t nbytes);
|
||||
SysResult sys_extattr_list_link(Thread *thread, ptr<const char> path,
|
||||
sint attrnamespace, ptr<void> data,
|
||||
size_t nbytes);
|
||||
SysResult sys_ksem_timedwait(Thread *thread, semid_t id,
|
||||
ptr<const timespec> abstime);
|
||||
SysResult sys_thr_suspend(Thread *thread, ptr<const timespec> timeout);
|
||||
SysResult sys_thr_wake(Thread *thread, slong id);
|
||||
SysResult sys_kldunloadf(Thread *thread, slong fileid, sint flags);
|
||||
SysResult sys_audit(Thread *thread, ptr<const void> record, uint length);
|
||||
SysResult sys_auditon(Thread *thread, sint cmd, ptr<void> data, uint length);
|
||||
SysResult sys_getauid(Thread *thread, ptr<uid_t> auid);
|
||||
SysResult sys_setauid(Thread *thread, ptr<uid_t> auid);
|
||||
SysResult sys_getaudit(Thread *thread, ptr<struct auditinfo> auditinfo);
|
||||
SysResult sys_setaudit(Thread *thread, ptr<struct auditinfo> auditinfo);
|
||||
SysResult sys_getaudit_addr(Thread *thread,
|
||||
ptr<struct auditinfo_addr> auditinfo_addr,
|
||||
uint length);
|
||||
SysResult sys_setaudit_addr(Thread *thread,
|
||||
ptr<struct auditinfo_addr> auditinfo_addr,
|
||||
uint length);
|
||||
SysResult sys_auditctl(Thread *thread, ptr<char> path);
|
||||
SysResult sys__umtx_op(Thread *thread, ptr<void> obj, sint op, ulong val,
|
||||
ptr<void> uaddr1, ptr<void> uaddr2);
|
||||
SysResult sys_thr_new(Thread *thread, ptr<struct thr_param> param,
|
||||
sint param_size);
|
||||
SysResult sys_sigqueue(Thread *thread, pid_t pid, sint signum, ptr<void> value);
|
||||
SysResult sys_kmq_open(Thread *thread, ptr<const char> path, sint flags,
|
||||
mode_t mode, ptr<const struct mq_attr> attr);
|
||||
SysResult sys_kmq_setattr(Thread *thread, sint mqd,
|
||||
ptr<const struct mq_attr> attr,
|
||||
ptr<struct mq_attr> oattr);
|
||||
SysResult sys_kmq_timedreceive(Thread *thread, sint mqd,
|
||||
ptr<const char> msg_ptr, size_t msg_len,
|
||||
ptr<uint> msg_prio,
|
||||
ptr<const timespec> abstimeout);
|
||||
SysResult sys_kmq_timedsend(Thread *thread, sint mqd, ptr<char> msg_ptr,
|
||||
size_t msg_len, ptr<uint> msg_prio,
|
||||
ptr<const timespec> abstimeout);
|
||||
SysResult sys_kmq_notify(Thread *thread, sint mqd,
|
||||
ptr<const struct sigevent> sigev);
|
||||
SysResult sys_kmq_unlink(Thread *thread, ptr<const char> path);
|
||||
SysResult sys_abort2(Thread *thread, ptr<const char> why, sint narg,
|
||||
ptr<ptr<void>> args);
|
||||
SysResult sys_thr_set_name(Thread *thread, slong id, ptr<const char> name);
|
||||
SysResult sys_aio_fsync(Thread *thread, sint op, ptr<struct aiocb> aiocbp);
|
||||
SysResult sys_rtprio_thread(Thread *thread, sint function, lwpid_t lwpid,
|
||||
ptr<struct rtprio> rtp);
|
||||
SysResult sys_sctp_peeloff(Thread *thread, sint sd, uint32_t name);
|
||||
SysResult sys_sctp_generic_sendmsg(Thread *thread, sint sd, caddr_t msg,
|
||||
sint mlen, caddr_t to, __socklen_t tolen,
|
||||
ptr<struct sctp_sndrcvinfo> sinfo,
|
||||
sint flags);
|
||||
SysResult sys_sctp_generic_sendmsg_iov(Thread *thread, sint sd, ptr<IoVec> iov,
|
||||
sint iovlen, caddr_t to,
|
||||
__socklen_t tolen,
|
||||
ptr<struct sctp_sndrcvinfo> sinfo,
|
||||
sint flags);
|
||||
SysResult sys_sctp_generic_recvmsg(Thread *thread, sint sd, ptr<IoVec> iov,
|
||||
sint iovlen, caddr_t from,
|
||||
__socklen_t fromlen,
|
||||
ptr<struct sctp_sndrcvinfo> sinfo,
|
||||
sint flags);
|
||||
SysResult sys_pread(Thread *thread, sint fd, ptr<void> buf, size_t nbyte,
|
||||
off_t offset);
|
||||
SysResult sys_pwrite(Thread *thread, sint fd, ptr<const void> buf, size_t nbyte,
|
||||
off_t offset);
|
||||
SysResult sys_mmap(Thread *thread, caddr_t addr, size_t len, sint prot,
|
||||
sint flags, sint fd, off_t pos);
|
||||
SysResult sys_lseek(Thread *thread, sint fd, off_t offset, sint whence);
|
||||
SysResult sys_truncate(Thread *thread, ptr<char> path, off_t length);
|
||||
SysResult sys_ftruncate(Thread *thread, sint fd, off_t length);
|
||||
SysResult sys_thr_kill2(Thread *thread, pid_t pid, slong id, sint sig);
|
||||
SysResult sys_shm_open(Thread *thread, ptr<const char> path, sint flags,
|
||||
mode_t mode);
|
||||
SysResult sys_shm_unlink(Thread *thread, ptr<const char> path);
|
||||
SysResult sys_cpuset(Thread *thread, ptr<cpusetid_t> setid);
|
||||
SysResult sys_cpuset_setid(Thread *thread, cpuwhich_t which, id_t id,
|
||||
cpusetid_t setid);
|
||||
SysResult sys_cpuset_getid(Thread *thread, cpulevel_t level, cpuwhich_t which,
|
||||
id_t id, ptr<cpusetid_t> setid);
|
||||
SysResult sys_cpuset_getaffinity(Thread *thread, cpulevel_t level,
|
||||
cpuwhich_t which, id_t id, size_t cpusetsize,
|
||||
ptr<cpuset> mask);
|
||||
SysResult sys_cpuset_setaffinity(Thread *thread, cpulevel_t level,
|
||||
cpuwhich_t which, id_t id, size_t cpusetsize,
|
||||
ptr<const cpuset> mask);
|
||||
SysResult sys_faccessat(Thread *thread, sint fd, ptr<char> path, sint mode,
|
||||
sint flag);
|
||||
SysResult sys_fchmodat(Thread *thread, sint fd, ptr<char> path, mode_t mode,
|
||||
sint flag);
|
||||
SysResult sys_fchownat(Thread *thread, sint fd, ptr<char> path, uid_t uid,
|
||||
gid_t gid, sint flag);
|
||||
SysResult sys_fexecve(Thread *thread, sint fd, ptr<ptr<char>> argv,
|
||||
ptr<ptr<char>> envv);
|
||||
SysResult sys_fstatat(Thread *thread, sint fd, ptr<char> path, ptr<Stat> buf,
|
||||
sint flag);
|
||||
SysResult sys_futimesat(Thread *thread, sint fd, ptr<char> path,
|
||||
ptr<struct timeval> times);
|
||||
SysResult sys_linkat(Thread *thread, sint fd1, ptr<char> path1, sint fd2,
|
||||
ptr<char> path2, sint flag);
|
||||
SysResult sys_mkdirat(Thread *thread, sint fd, ptr<char> path, mode_t mode);
|
||||
SysResult sys_mkfifoat(Thread *thread, sint fd, ptr<char> path, mode_t mode);
|
||||
SysResult sys_mknodat(Thread *thread, sint fd, ptr<char> path, mode_t mode,
|
||||
dev_t dev);
|
||||
SysResult sys_openat(Thread *thread, sint fd, ptr<char> path, sint flag,
|
||||
mode_t mode);
|
||||
SysResult sys_readlinkat(Thread *thread, sint fd, ptr<char> path, ptr<char> buf,
|
||||
size_t bufsize);
|
||||
SysResult sys_renameat(Thread *thread, sint oldfd, ptr<char> old, sint newfd,
|
||||
ptr<char> new_);
|
||||
SysResult sys_symlinkat(Thread *thread, ptr<char> path1, sint fd,
|
||||
ptr<char> path2);
|
||||
SysResult sys_unlinkat(Thread *thread, sint fd, ptr<char> path, sint flag);
|
||||
SysResult sys_posix_openpt(Thread *thread, sint flags);
|
||||
SysResult sys_gssd_syscall(Thread *thread, ptr<char> path);
|
||||
SysResult sys_jail_get(Thread *thread, ptr<IoVec> iovp, uint iovcnt,
|
||||
sint flags);
|
||||
SysResult sys_jail_set(Thread *thread, ptr<IoVec> iovp, uint iovcnt,
|
||||
sint flags);
|
||||
SysResult sys_jail_remove(Thread *thread, sint jid);
|
||||
SysResult sys_closefrom(Thread *thread, sint lowfd);
|
||||
SysResult sys___semctl(Thread *thread, sint semid, sint semnum, sint cmd,
|
||||
ptr<union semun> arg);
|
||||
SysResult sys_msgctl(Thread *thread, sint msqid, sint cmd,
|
||||
ptr<struct msqid_ds> buf);
|
||||
SysResult sys_shmctl(Thread *thread, sint shmid, sint cmd,
|
||||
ptr<struct shmid_ds> buf);
|
||||
SysResult sys_lpathconf(Thread *thread, ptr<char> path, sint name);
|
||||
SysResult sys_cap_new(Thread *thread, sint fd, uint64_t rights);
|
||||
SysResult sys_cap_getrights(Thread *thread, sint fd, ptr<uint64_t> rights);
|
||||
SysResult sys_cap_enter(Thread *thread);
|
||||
SysResult sys_cap_getmode(Thread *thread, ptr<uint> modep);
|
||||
SysResult sys_pdfork(Thread *thread, ptr<sint> fdp, sint flags);
|
||||
SysResult sys_pdkill(Thread *thread, sint fd, sint signum);
|
||||
SysResult sys_pdgetpid(Thread *thread, sint fd, ptr<pid_t> pidp);
|
||||
SysResult sys_pselect(Thread *thread, sint nd, ptr<fd_set> in, ptr<fd_set> ou,
|
||||
ptr<fd_set> ex, ptr<const timespec> ts,
|
||||
ptr<const sigset_t> sm);
|
||||
SysResult sys_getloginclass(Thread *thread, ptr<char> namebuf, size_t namelen);
|
||||
SysResult sys_setloginclass(Thread *thread, ptr<char> namebuf);
|
||||
SysResult sys_rctl_get_racct(Thread *thread, ptr<const void> inbufp,
|
||||
size_t inbuflen, ptr<void> outbuf,
|
||||
size_t outbuflen);
|
||||
SysResult sys_rctl_get_rules(Thread *thread, ptr<const void> inbufp,
|
||||
size_t inbuflen, ptr<void> outbuf,
|
||||
size_t outbuflen);
|
||||
SysResult sys_rctl_get_limits(Thread *thread, ptr<const void> inbufp,
|
||||
size_t inbuflen, ptr<void> outbuf,
|
||||
size_t outbuflen);
|
||||
SysResult sys_rctl_add_rule(Thread *thread, ptr<const void> inbufp,
|
||||
size_t inbuflen, ptr<void> outbuf,
|
||||
size_t outbuflen);
|
||||
SysResult sys_rctl_remove_rule(Thread *thread, ptr<const void> inbufp,
|
||||
size_t inbuflen, ptr<void> outbuf,
|
||||
size_t outbuflen);
|
||||
SysResult sys_posix_fallocate(Thread *thread, sint fd, off_t offset, off_t len);
|
||||
SysResult sys_posix_fadvise(Thread *thread, sint fd, off_t offset, off_t len,
|
||||
sint advice);
|
||||
|
||||
SysResult sys_netcontrol(Thread *thread, sint fd, uint op, ptr<void> buf,
|
||||
uint nbuf);
|
||||
SysResult sys_netabort(Thread *thread /* TODO */);
|
||||
SysResult sys_netgetsockinfo(Thread *thread /* TODO */);
|
||||
SysResult sys_socketex(Thread *thread, ptr<const char> name, sint domain,
|
||||
sint type, sint protocol);
|
||||
SysResult sys_socketclose(Thread *thread, sint fd);
|
||||
SysResult sys_netgetiflist(Thread *thread /* TODO */);
|
||||
SysResult sys_kqueueex(Thread *thread, ptr<char> name, sint flags);
|
||||
SysResult sys_mtypeprotect(Thread *thread /* TODO */);
|
||||
SysResult sys_regmgr_call(Thread *thread, uint32_t op, uint32_t id,
|
||||
ptr<void> result, ptr<void> value, uint64_t len);
|
||||
SysResult sys_jitshm_create(Thread *thread /* TODO */);
|
||||
SysResult sys_jitshm_alias(Thread *thread /* TODO */);
|
||||
SysResult sys_dl_get_list(Thread *thread /* TODO */);
|
||||
SysResult sys_dl_get_info(Thread *thread /* TODO */);
|
||||
SysResult sys_dl_notify_event(Thread *thread /* TODO */);
|
||||
SysResult sys_evf_create(Thread *thread, ptr<const char[32]> name, sint attrs,
|
||||
uint64_t initPattern);
|
||||
SysResult sys_evf_delete(Thread *thread, sint id);
|
||||
SysResult sys_evf_open(Thread *thread, ptr<const char[32]> name);
|
||||
SysResult sys_evf_close(Thread *thread, sint id);
|
||||
SysResult sys_evf_wait(Thread *thread, sint id, uint64_t patternSet,
|
||||
uint64_t mode, ptr<uint64_t> pPatternSet,
|
||||
ptr<uint> pTimeout);
|
||||
SysResult sys_evf_trywait(Thread *thread, sint id, uint64_t patternSet,
|
||||
uint64_t mode,
|
||||
ptr<uint64_t> pPatternSet); // FIXME: verify args
|
||||
SysResult sys_evf_set(Thread *thread, sint id, uint64_t value);
|
||||
SysResult sys_evf_clear(Thread *thread, sint id, uint64_t value);
|
||||
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_osem_create(Thread *thread, ptr<const char[32]> name, uint attrs,
|
||||
sint initCount, sint maxCount);
|
||||
SysResult sys_osem_delete(Thread *thread, sint id);
|
||||
SysResult sys_osem_open(Thread *thread, ptr<const char[32]> name);
|
||||
SysResult sys_osem_close(Thread *thread, sint id);
|
||||
SysResult sys_osem_wait(Thread *thread, sint id, sint need, ptr<uint> pTimeout);
|
||||
SysResult sys_osem_trywait(Thread *thread, sint id, sint need);
|
||||
SysResult sys_osem_post(Thread *thread, sint id, sint count);
|
||||
SysResult sys_osem_cancel(Thread *thread, sint id, sint set,
|
||||
ptr<uint> pNumWaitThreads);
|
||||
SysResult sys_namedobj_create(Thread *thread, ptr<const char[32]> name,
|
||||
ptr<void> object, uint16_t type);
|
||||
SysResult sys_namedobj_delete(Thread *thread, uint id, uint16_t type);
|
||||
SysResult sys_set_vm_container(Thread *thread /* TODO */);
|
||||
SysResult sys_debug_init(Thread *thread /* TODO */);
|
||||
SysResult sys_suspend_process(Thread *thread, pid_t pid);
|
||||
SysResult sys_resume_process(Thread *thread, pid_t pid);
|
||||
SysResult sys_opmc_enable(Thread *thread /* TODO */);
|
||||
SysResult sys_opmc_disable(Thread *thread /* TODO */);
|
||||
SysResult sys_opmc_set_ctl(Thread *thread /* TODO */);
|
||||
SysResult sys_opmc_set_ctr(Thread *thread /* TODO */);
|
||||
SysResult sys_opmc_get_ctr(Thread *thread /* TODO */);
|
||||
SysResult sys_budget_create(Thread *thread, ptr<char> name,
|
||||
Budget::ProcessType processType,
|
||||
ptr<const BudgetInfo> resources, orbis::uint count,
|
||||
ptr<BudgetInfo> invalidResources);
|
||||
SysResult sys_budget_delete(Thread *thread, sint budget);
|
||||
SysResult sys_budget_get(Thread *thread, sint id, ptr<BudgetInfo> budgetInfo,
|
||||
ptr<sint> count);
|
||||
SysResult sys_budget_set(Thread *thread, sint budget);
|
||||
SysResult sys_virtual_query(Thread *thread, ptr<void> addr, uint64_t unk,
|
||||
ptr<void> info, size_t infosz);
|
||||
SysResult sys_mdbg_call(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_sblock_create(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_sblock_delete(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_sblock_enter(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_sblock_exit(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_sblock_xenter(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_sblock_xexit(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_eport_create(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_eport_delete(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_eport_trigger(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_eport_open(Thread *thread /* TODO */);
|
||||
SysResult sys_obs_eport_close(Thread *thread /* TODO */);
|
||||
SysResult sys_is_in_sandbox(Thread *thread /* TODO */);
|
||||
SysResult sys_dmem_container(Thread *thread, uint id);
|
||||
SysResult sys_get_authinfo(Thread *thread, pid_t pid, ptr<AuthInfo> info);
|
||||
SysResult sys_mname(Thread *thread, uint64_t address, uint64_t length,
|
||||
ptr<const char[32]> name);
|
||||
SysResult sys_dynlib_dlopen(Thread *thread /* TODO */);
|
||||
SysResult sys_dynlib_dlclose(Thread *thread /* TODO */);
|
||||
SysResult sys_dynlib_dlsym(Thread *thread, SceKernelModule handle,
|
||||
ptr<const char> symbol, ptr<ptr<void>> addrp);
|
||||
SysResult sys_dynlib_get_list(Thread *thread, ptr<SceKernelModule> pArray,
|
||||
size_t numArray, ptr<size_t> pActualNum);
|
||||
SysResult sys_dynlib_get_info(Thread *thread, SceKernelModule handle,
|
||||
ptr<ModuleInfo> pInfo);
|
||||
SysResult sys_dynlib_load_prx(Thread *thread, ptr<const char> name,
|
||||
uint64_t arg1, ptr<ModuleHandle> pHandle,
|
||||
uint64_t arg3);
|
||||
SysResult sys_dynlib_unload_prx(Thread *thread,
|
||||
SceKernelModule handle /* TODO*/);
|
||||
SysResult sys_dynlib_do_copy_relocations(Thread *thread);
|
||||
SysResult sys_dynlib_prepare_dlclose(Thread *thread /* TODO */);
|
||||
SysResult sys_dynlib_get_proc_param(Thread *thread, ptr<ptr<void>> procParam,
|
||||
ptr<uint64_t> procParamSize);
|
||||
SysResult sys_dynlib_process_needed_and_relocate(Thread *thread);
|
||||
SysResult sys_sandbox_path(Thread *thread, ptr<const char> path);
|
||||
SysResult sys_mdbg_service(Thread *thread, uint32_t op, ptr<void> arg0,
|
||||
ptr<void> arg1);
|
||||
SysResult sys_randomized_path(Thread *thread, sint type, ptr<char> path,
|
||||
ptr<sint> length);
|
||||
SysResult sys_rdup(Thread *thread, sint a, sint b);
|
||||
SysResult sys_dl_get_metadata(Thread *thread /* TODO */);
|
||||
SysResult sys_workaround8849(Thread *thread /* TODO */);
|
||||
SysResult sys_is_development_mode(Thread *thread /* TODO */);
|
||||
SysResult sys_get_self_auth_info(Thread *thread, ptr<const char> path,
|
||||
ptr<AuthInfo> result);
|
||||
SysResult sys_dynlib_get_info_ex(Thread *thread, SceKernelModule handle,
|
||||
ptr<struct Unk> unk,
|
||||
ptr<ModuleInfoEx> destModuleInfoEx);
|
||||
SysResult sys_budget_getid(Thread *thread);
|
||||
SysResult sys_budget_get_ptype(Thread *thread, sint pid);
|
||||
SysResult sys_get_paging_stats_of_all_threads(Thread *thread /* TODO */);
|
||||
SysResult sys_get_proc_type_info(Thread *thread, ptr<sint> destProcessInfo);
|
||||
SysResult sys_get_resident_count(Thread *thread, pid_t pid);
|
||||
SysResult sys_prepare_to_suspend_process(Thread *thread, pid_t pid);
|
||||
SysResult sys_get_resident_fmem_count(Thread *thread, pid_t pid);
|
||||
SysResult sys_thr_get_name(Thread *thread, lwpid_t lwpid, char *buf,
|
||||
size_t buflen);
|
||||
SysResult sys_set_gpo(Thread *thread /* TODO */);
|
||||
SysResult sys_get_paging_stats_of_all_objects(Thread *thread /* TODO */);
|
||||
SysResult sys_test_debug_rwmem(Thread *thread /* TODO */);
|
||||
SysResult sys_free_stack(Thread *thread /* TODO */);
|
||||
SysResult sys_suspend_system(Thread *thread /* TODO */);
|
||||
SysResult sys_ipmimgr_call(Thread *thread, uint op, uint kid, ptr<uint> result,
|
||||
ptr<void> params, uint64_t paramsz);
|
||||
SysResult sys_get_gpo(Thread *thread /* TODO */);
|
||||
SysResult sys_get_vm_map_timestamp(Thread *thread /* TODO */);
|
||||
SysResult sys_opmc_set_hw(Thread *thread /* TODO */);
|
||||
SysResult sys_opmc_get_hw(Thread *thread /* TODO */);
|
||||
SysResult sys_get_cpu_usage_all(Thread *thread, uint32_t unk,
|
||||
ptr<uint32_t> result);
|
||||
SysResult sys_mmap_dmem(Thread *thread, caddr_t addr, size_t len,
|
||||
sint memoryType, sint prot, sint flags,
|
||||
off_t directMemoryStart);
|
||||
SysResult sys_physhm_open(Thread *thread /* TODO */);
|
||||
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_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,
|
||||
timesec *_sec, int *_dst_sec);
|
||||
SysResult sys_localtime_to_utc(Thread *thread, int64_t time, uint unk,
|
||||
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 */);
|
||||
SysResult sys_set_chicken_switches(Thread *thread /* TODO */);
|
||||
SysResult sys_extend_page_table_pool(Thread *thread);
|
||||
SysResult sys_extend_page_table_pool2(Thread *thread);
|
||||
SysResult sys_get_kernel_mem_statistics(Thread *thread /* TODO */);
|
||||
SysResult sys_get_sdk_compiled_version(Thread *thread, ptr<const char> path);
|
||||
SysResult sys_app_state_change(Thread *thread, sint state);
|
||||
SysResult sys_dynlib_get_obj_member(Thread *thread, SceKernelModule handle,
|
||||
uint64_t index, ptr<ptr<void>> addrp);
|
||||
SysResult sys_budget_get_ptype_of_budget(Thread *thread, sint budgetId);
|
||||
SysResult sys_prepare_to_resume_process(Thread *thread /* TODO */);
|
||||
SysResult sys_process_terminate(Thread *thread /* TODO */);
|
||||
SysResult sys_blockpool_open(Thread *thread);
|
||||
SysResult sys_blockpool_map(Thread *thread, caddr_t addr, size_t len, sint prot,
|
||||
sint flags);
|
||||
SysResult sys_blockpool_unmap(Thread *thread, caddr_t addr, size_t len,
|
||||
sint flags);
|
||||
SysResult sys_dynlib_get_info_for_libdbg(Thread *thread /* TODO */);
|
||||
SysResult sys_blockpool_batch(Thread *thread /* TODO */);
|
||||
SysResult sys_fdatasync(Thread *thread /* TODO */);
|
||||
SysResult sys_dynlib_get_list2(Thread *thread /* TODO */);
|
||||
SysResult sys_dynlib_get_info2(Thread *thread /* TODO */);
|
||||
SysResult sys_aio_submit(Thread *thread /* TODO */);
|
||||
SysResult sys_aio_multi_delete(Thread *thread /* TODO */);
|
||||
SysResult sys_aio_multi_wait(Thread *thread /* TODO */);
|
||||
SysResult sys_aio_multi_poll(Thread *thread /* TODO */);
|
||||
SysResult sys_aio_get_data(Thread *thread /* TODO */);
|
||||
SysResult sys_aio_multi_cancel(Thread *thread /* TODO */);
|
||||
SysResult sys_get_bio_usage_all(Thread *thread /* TODO */);
|
||||
SysResult sys_aio_create(Thread *thread /* TODO */);
|
||||
SysResult sys_aio_submit_cmd(Thread *thread /* TODO */);
|
||||
SysResult sys_aio_init(Thread *thread /* TODO */);
|
||||
SysResult sys_get_page_table_stats(Thread *thread /* TODO */);
|
||||
SysResult sys_dynlib_get_list_for_libdbg(Thread *thread /* TODO */);
|
||||
SysResult sys_blockpool_move(Thread *thread /* TODO */);
|
||||
SysResult sys_virtual_query_all(Thread *thread /* TODO */);
|
||||
SysResult sys_reserve_2mb_page(Thread *thread /* TODO */);
|
||||
SysResult sys_cpumode_yield(Thread *thread /* TODO */);
|
||||
|
||||
SysResult sys_wait6(Thread *thread /* TODO */);
|
||||
SysResult sys_cap_rights_limit(Thread *thread /* TODO */);
|
||||
SysResult sys_cap_ioctls_limit(Thread *thread /* TODO */);
|
||||
SysResult sys_cap_ioctls_get(Thread *thread /* TODO */);
|
||||
SysResult sys_cap_fcntls_limit(Thread *thread /* TODO */);
|
||||
SysResult sys_cap_fcntls_get(Thread *thread /* TODO */);
|
||||
SysResult sys_bindat(Thread *thread /* TODO */);
|
||||
SysResult sys_connectat(Thread *thread /* TODO */);
|
||||
SysResult sys_chflagsat(Thread *thread /* TODO */);
|
||||
SysResult sys_accept4(Thread *thread /* TODO */);
|
||||
SysResult sys_pipe2(Thread *thread /* TODO */);
|
||||
SysResult sys_aio_mlock(Thread *thread /* TODO */);
|
||||
SysResult sys_procctl(Thread *thread /* TODO */);
|
||||
SysResult sys_ppoll(Thread *thread /* TODO */);
|
||||
SysResult sys_futimens(Thread *thread /* TODO */);
|
||||
SysResult sys_utimensat(Thread *thread /* TODO */);
|
||||
SysResult sys_numa_getaffinity(Thread *thread /* TODO */);
|
||||
SysResult sys_numa_setaffinity(Thread *thread /* TODO */);
|
||||
SysResult sys_apr_submit(Thread *thread /* TODO */);
|
||||
SysResult sys_apr_resolve(Thread *thread /* TODO */);
|
||||
SysResult sys_apr_stat(Thread *thread /* TODO */);
|
||||
SysResult sys_apr_wait(Thread *thread /* TODO */);
|
||||
SysResult sys_apr_ctrl(Thread *thread /* TODO */);
|
||||
SysResult sys_get_phys_page_size(Thread *thread /* TODO */);
|
||||
SysResult sys_begin_app_mount(Thread *thread, ptr<AppMountInfo> info);
|
||||
SysResult sys_end_app_mount(Thread *thread /* TODO */);
|
||||
SysResult sys_fsc2h_ctrl(Thread *thread /* TODO */);
|
||||
SysResult sys_streamwrite(Thread *thread /* TODO */);
|
||||
SysResult sys_app_save(Thread *thread /* TODO */);
|
||||
SysResult sys_app_restore(Thread *thread /* TODO */);
|
||||
SysResult sys_saved_app_delete(Thread *thread /* TODO */);
|
||||
SysResult sys_get_ppr_sdk_compiled_version(Thread *thread /* TODO */);
|
||||
SysResult sys_notify_app_event(Thread *thread /* TODO */);
|
||||
SysResult sys_ioreq(Thread *thread /* TODO */);
|
||||
SysResult sys_openintr(Thread *thread /* TODO */);
|
||||
SysResult sys_dl_get_info_2(Thread *thread /* TODO */);
|
||||
SysResult sys_acinfo_add(Thread *thread /* TODO */);
|
||||
SysResult sys_acinfo_delete(Thread *thread /* TODO */);
|
||||
SysResult sys_acinfo_get_all_for_coredump(Thread *thread /* TODO */);
|
||||
SysResult sys_ampr_ctrl_debug(Thread *thread /* TODO */);
|
||||
SysResult sys_workspace_ctrl(Thread *thread /* TODO */);
|
||||
} // namespace orbis
|
||||
10
kernel/orbis/include/orbis/thread.hpp
Normal file
10
kernel/orbis/include/orbis/thread.hpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "thread/Process.hpp" // IWYU pragma: export
|
||||
#include "thread/ProcessOps.hpp" // IWYU pragma: export
|
||||
#include "thread/ProcessState.hpp" // IWYU pragma: export
|
||||
#include "thread/Thread.hpp" // IWYU pragma: export
|
||||
#include "thread/ThreadState.hpp" // IWYU pragma: export
|
||||
#include "thread/cpuset.hpp" // IWYU pragma: export
|
||||
#include "thread/sysent.hpp" // IWYU pragma: export
|
||||
#include "thread/types.hpp" // IWYU pragma: export
|
||||
105
kernel/orbis/include/orbis/thread/Process.hpp
Normal file
105
kernel/orbis/include/orbis/thread/Process.hpp
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
#pragma once
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
#include "../event.hpp"
|
||||
#include "../evf.hpp"
|
||||
#include "../ipmi.hpp"
|
||||
#include "../osem.hpp"
|
||||
#include "../thread/Thread.hpp"
|
||||
#include "../thread/types.hpp"
|
||||
#include "ProcessState.hpp"
|
||||
#include "cpuset.hpp"
|
||||
#include "orbis/AppInfo.hpp"
|
||||
#include "orbis/AuthInfo.hpp"
|
||||
#include "orbis/Budget.hpp"
|
||||
#include "orbis/file.hpp"
|
||||
#include "orbis/module/Module.hpp"
|
||||
#include "orbis/utils/IdMap.hpp"
|
||||
#include "orbis/utils/SharedMutex.hpp"
|
||||
#include <optional>
|
||||
|
||||
namespace orbis {
|
||||
class KernelContext;
|
||||
struct Thread;
|
||||
struct ProcessOps;
|
||||
struct sysentvec;
|
||||
|
||||
struct NamedObjInfo {
|
||||
void *idptr;
|
||||
uint16_t ty;
|
||||
};
|
||||
|
||||
struct NamedMemoryRange {
|
||||
uint64_t begin, end;
|
||||
|
||||
constexpr bool operator<(const NamedMemoryRange &rhs) const {
|
||||
return end <= rhs.begin;
|
||||
}
|
||||
|
||||
friend constexpr bool operator<(const NamedMemoryRange &lhs, uint64_t ptr) {
|
||||
return lhs.end <= ptr;
|
||||
}
|
||||
|
||||
friend constexpr bool operator<(uint64_t ptr, const NamedMemoryRange &rhs) {
|
||||
return ptr < rhs.begin;
|
||||
}
|
||||
};
|
||||
|
||||
enum class ProcessType : std::uint8_t {
|
||||
FreeBsd,
|
||||
Ps4,
|
||||
Ps5,
|
||||
};
|
||||
|
||||
struct Process final {
|
||||
KernelContext *context = nullptr;
|
||||
pid_t pid = -1;
|
||||
int gfxRing = 0;
|
||||
std::uint64_t hostPid = -1;
|
||||
sysentvec *sysent = nullptr;
|
||||
ProcessState state = ProcessState::NEW;
|
||||
Process *parentProcess = nullptr;
|
||||
shared_mutex mtx;
|
||||
int vmId = -1;
|
||||
ProcessType type = ProcessType::FreeBsd;
|
||||
void (*onSysEnter)(Thread *thread, int id, uint64_t *args,
|
||||
int argsCount) = nullptr;
|
||||
void (*onSysExit)(Thread *thread, int id, uint64_t *args, int argsCount,
|
||||
SysResult result) = nullptr;
|
||||
ptr<void> processParam = nullptr;
|
||||
uint64_t processParamSize = 0;
|
||||
const ProcessOps *ops = nullptr;
|
||||
AppInfoEx appInfo{};
|
||||
AuthInfo authInfo{};
|
||||
kstring cwd;
|
||||
kstring root = "/";
|
||||
cpuset affinity{(1 << 7) - 1};
|
||||
sint memoryContainer{1};
|
||||
sint budgetId{};
|
||||
Budget::ProcessType budgetProcessType{};
|
||||
bool isInSandbox = false;
|
||||
EventEmitter event;
|
||||
std::optional<sint> exitStatus;
|
||||
|
||||
std::uint32_t sdkVersion = 0;
|
||||
std::uint64_t nextTlsSlot = 1;
|
||||
std::uint64_t lastTlsOffset = 0;
|
||||
|
||||
utils::RcIdMap<EventFlag, sint, 4097, 1> evfMap;
|
||||
utils::RcIdMap<Semaphore, sint, 4097, 1> semMap;
|
||||
utils::RcIdMap<Module, ModuleHandle> modulesMap;
|
||||
utils::OwningIdMap<Thread, lwpid_t> threadsMap;
|
||||
utils::RcIdMap<orbis::File, sint> fileDescriptors;
|
||||
|
||||
// Named objects for debugging
|
||||
utils::shared_mutex namedObjMutex;
|
||||
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;
|
||||
};
|
||||
} // namespace orbis
|
||||
95
kernel/orbis/include/orbis/thread/ProcessOps.hpp
Normal file
95
kernel/orbis/include/orbis/thread/ProcessOps.hpp
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#pragma once
|
||||
#include "../error/SysResult.hpp"
|
||||
#include "../module/ModuleHandle.hpp"
|
||||
#include "../thread/types.hpp"
|
||||
#include "orbis-config.hpp"
|
||||
#include "orbis/utils/Rc.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct Thread;
|
||||
struct Module;
|
||||
struct timespec;
|
||||
struct File;
|
||||
struct MemoryProtection;
|
||||
struct IoVec;
|
||||
struct UContext;
|
||||
|
||||
struct ProcessOps {
|
||||
SysResult (*mmap)(Thread *thread, caddr_t addr, size_t len, sint prot,
|
||||
sint flags, sint fd, off_t pos);
|
||||
SysResult (*dmem_mmap)(Thread *thread, caddr_t addr, size_t len,
|
||||
sint memoryType, sint prot, sint flags,
|
||||
off_t directMemoryStart);
|
||||
SysResult (*munmap)(Thread *thread, ptr<void> addr, size_t len);
|
||||
SysResult (*msync)(Thread *thread, ptr<void> addr, size_t len, sint flags);
|
||||
SysResult (*mprotect)(Thread *thread, ptr<const void> addr, size_t len,
|
||||
sint prot);
|
||||
SysResult (*minherit)(Thread *thread, ptr<void> addr, size_t len,
|
||||
sint inherit);
|
||||
SysResult (*madvise)(Thread *thread, ptr<void> addr, size_t len, sint behav);
|
||||
SysResult (*mincore)(Thread *thread, ptr<const void> addr, size_t len,
|
||||
ptr<char> vec);
|
||||
SysResult (*mlock)(Thread *thread, ptr<const void> addr, size_t len);
|
||||
SysResult (*mlockall)(Thread *thread, sint how);
|
||||
SysResult (*munlockall)(Thread *thread);
|
||||
SysResult (*munlock)(Thread *thread, ptr<const void> addr, size_t len);
|
||||
SysResult (*virtual_query)(Thread *thread, ptr<const void> addr, sint flags,
|
||||
ptr<void> info, ulong infoSize);
|
||||
SysResult (*query_memory_protection)(Thread *thread, ptr<void> address,
|
||||
ptr<MemoryProtection> protection);
|
||||
|
||||
SysResult (*open)(Thread *thread, ptr<const char> path, sint flags, sint mode,
|
||||
Ref<File> *file);
|
||||
SysResult (*shm_open)(Thread *thread, const char *path, sint flags, sint mode,
|
||||
Ref<File> *file);
|
||||
SysResult (*unlink)(Thread *thread, ptr<const char> path);
|
||||
SysResult (*mkdir)(Thread *thread, ptr<const char> path, sint mode);
|
||||
SysResult (*rmdir)(Thread *thread, ptr<const char> path);
|
||||
SysResult (*rename)(Thread *thread, ptr<const char> from, ptr<const char> to);
|
||||
SysResult (*blockpool_open)(Thread *thread, Ref<File> *file);
|
||||
SysResult (*blockpool_map)(Thread *thread, caddr_t addr, size_t len,
|
||||
sint prot, sint flags);
|
||||
SysResult (*blockpool_unmap)(Thread *thread, caddr_t addr, size_t len);
|
||||
SysResult (*socket)(Thread *thread, ptr<const char> name, sint domain,
|
||||
sint type, sint protocol, Ref<File> *file);
|
||||
SysResult (*socketpair)(Thread *thread, sint domain, sint type, sint protocol,
|
||||
Ref<File> *a, Ref<File> *b);
|
||||
SysResult (*shm_unlink)(Thread *thread, const char *path);
|
||||
SysResult (*dynlib_get_obj_member)(Thread *thread, ModuleHandle handle,
|
||||
uint64_t index, ptr<ptr<void>> addrp);
|
||||
SysResult (*dynlib_dlsym)(Thread *thread, ModuleHandle handle,
|
||||
ptr<const char> symbol, ptr<ptr<void>> addrp);
|
||||
SysResult (*dynlib_do_copy_relocations)(Thread *thread);
|
||||
SysResult (*dynlib_load_prx)(Thread *thread, ptr<const char> name,
|
||||
uint64_t arg1, ptr<ModuleHandle> pHandle,
|
||||
uint64_t arg3);
|
||||
SysResult (*dynlib_unload_prx)(Thread *thread, ModuleHandle handle);
|
||||
|
||||
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);
|
||||
SysResult (*thr_kill)(Thread *thread, slong id, sint sig);
|
||||
SysResult (*thr_kill2)(Thread *thread, pid_t pid, slong id, sint sig);
|
||||
SysResult (*thr_suspend)(Thread *thread, ptr<const timespec> timeout);
|
||||
SysResult (*thr_wake)(Thread *thread, slong id);
|
||||
SysResult (*sigreturn)(Thread *thread, ptr<UContext> context);
|
||||
SysResult (*thr_set_name)(Thread *thread, slong id, ptr<const char> name);
|
||||
|
||||
SysResult (*unmount)(Thread *thread, ptr<char> path, sint flags);
|
||||
SysResult (*nmount)(Thread *thread, ptr<IoVec> iovp, uint iovcnt, sint flags);
|
||||
|
||||
SysResult (*fork)(Thread *thread, slong status);
|
||||
SysResult (*execve)(Thread *thread, ptr<char> fname, ptr<ptr<char>> argv,
|
||||
ptr<ptr<char>> envv);
|
||||
SysResult (*exit)(Thread *thread, sint status);
|
||||
|
||||
SysResult (*processNeeded)(Thread *thread);
|
||||
SysResult (*registerEhFrames)(Thread *thread);
|
||||
|
||||
void (*where)(Thread *);
|
||||
|
||||
void (*unblock)(Thread *);
|
||||
void (*block)(Thread *);
|
||||
};
|
||||
} // namespace orbis
|
||||
11
kernel/orbis/include/orbis/thread/ProcessState.hpp
Normal file
11
kernel/orbis/include/orbis/thread/ProcessState.hpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace orbis {
|
||||
enum class ProcessState : std::uint32_t {
|
||||
NEW, // In creation
|
||||
NORMAL, // threads can be run
|
||||
ZOMBIE
|
||||
};
|
||||
} // namespace orbis
|
||||
24
kernel/orbis/include/orbis/thread/RegisterId.hpp
Normal file
24
kernel/orbis/include/orbis/thread/RegisterId.hpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
namespace orbis {
|
||||
enum class RegisterId {
|
||||
r15,
|
||||
r14,
|
||||
r13,
|
||||
r12,
|
||||
r11,
|
||||
r10,
|
||||
r9,
|
||||
r8,
|
||||
rdi,
|
||||
rsi,
|
||||
rbp,
|
||||
rbx,
|
||||
rdx,
|
||||
rcx,
|
||||
rax,
|
||||
rsp,
|
||||
rflags,
|
||||
rip,
|
||||
};
|
||||
} // namespace orbis
|
||||
111
kernel/orbis/include/orbis/thread/Thread.hpp
Normal file
111
kernel/orbis/include/orbis/thread/Thread.hpp
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
#pragma once
|
||||
|
||||
#include "ThreadState.hpp"
|
||||
#include "cpuset.hpp"
|
||||
#include "orbis-config.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include "../KernelAllocator.hpp"
|
||||
#include "../ucontext.hpp"
|
||||
#include "../utils/SharedAtomic.hpp"
|
||||
#include "../utils/SharedCV.hpp"
|
||||
#include "../utils/SharedMutex.hpp"
|
||||
#include <thread>
|
||||
|
||||
namespace orbis {
|
||||
struct Process;
|
||||
|
||||
static constexpr std::uint32_t kThreadSuspendFlag = 1 << 31;
|
||||
struct Thread {
|
||||
utils::shared_mutex mtx;
|
||||
Process *tproc = nullptr;
|
||||
uint64_t retval[2]{};
|
||||
void *context{};
|
||||
kvector<void *> altStack;
|
||||
ptr<void> stackStart;
|
||||
ptr<void> stackEnd;
|
||||
uint64_t fsBase{};
|
||||
uint64_t gsBase{};
|
||||
char name[32]{};
|
||||
|
||||
cpuset affinity{~0u};
|
||||
SigSet sigMask = {0x7fff'ffff, ~0u, ~0u, ~0u};
|
||||
rtprio prio{
|
||||
.type = 2,
|
||||
.prio = 10,
|
||||
};
|
||||
utils::shared_mutex suspend_mtx;
|
||||
utils::shared_cv suspend_cv;
|
||||
kvector<UContext> sigReturns;
|
||||
kvector<SigInfo> blockedSignals;
|
||||
kvector<SigInfo> queuedSignals;
|
||||
shared_atomic32 suspendFlags{0};
|
||||
|
||||
utils::shared_atomic32 interruptedMtx{ 0 };
|
||||
|
||||
std::int64_t hostTid = -1;
|
||||
lwpid_t tid = -1;
|
||||
unsigned unblocked = 0;
|
||||
ThreadState state = ThreadState::INACTIVE;
|
||||
std::thread handle;
|
||||
std::thread::native_handle_type nativeHandle;
|
||||
|
||||
// Used to wake up thread in sleep queue
|
||||
utils::shared_cv sync_cv;
|
||||
uint64_t evfResultPattern;
|
||||
uint64_t evfIsCancelled;
|
||||
|
||||
[[nodiscard]] std::thread::native_handle_type getNativeHandle() {
|
||||
if (handle.joinable()) {
|
||||
return handle.native_handle();
|
||||
}
|
||||
|
||||
return nativeHandle;
|
||||
}
|
||||
|
||||
// Print backtrace
|
||||
void where();
|
||||
|
||||
bool unblock();
|
||||
bool block();
|
||||
|
||||
void suspend();
|
||||
void resume();
|
||||
void sendSignal(int signo);
|
||||
void notifyUnblockedSignal(int signo);
|
||||
void setSigMask(SigSet newSigMask);
|
||||
|
||||
// FIXME: implement thread destruction
|
||||
void incRef() {}
|
||||
void decRef() {}
|
||||
};
|
||||
|
||||
extern thread_local Thread *g_currentThread;
|
||||
|
||||
struct scoped_unblock {
|
||||
scoped_unblock();
|
||||
~scoped_unblock();
|
||||
|
||||
scoped_unblock(const scoped_unblock &) = delete;
|
||||
};
|
||||
|
||||
class scoped_unblock_now {
|
||||
bool unblocked = false;
|
||||
|
||||
public:
|
||||
scoped_unblock_now() {
|
||||
if (g_currentThread && g_currentThread->context) {
|
||||
g_currentThread->unblock();
|
||||
unblocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
~scoped_unblock_now() {
|
||||
if (unblocked) {
|
||||
g_currentThread->block();
|
||||
}
|
||||
}
|
||||
|
||||
scoped_unblock_now(const scoped_unblock_now &) = delete;
|
||||
};
|
||||
} // namespace orbis
|
||||
13
kernel/orbis/include/orbis/thread/ThreadState.hpp
Normal file
13
kernel/orbis/include/orbis/thread/ThreadState.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace orbis {
|
||||
enum class ThreadState : std::uint32_t {
|
||||
INACTIVE,
|
||||
INHIBITED,
|
||||
CAN_RUN,
|
||||
RUNQ,
|
||||
RUNNING
|
||||
};
|
||||
} // namespace orbis
|
||||
9
kernel/orbis/include/orbis/thread/cpuset.hpp
Normal file
9
kernel/orbis/include/orbis/thread/cpuset.hpp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct cpuset {
|
||||
uint bits;
|
||||
};
|
||||
} // namespace orbis
|
||||
18
kernel/orbis/include/orbis/thread/sysent.hpp
Normal file
18
kernel/orbis/include/orbis/thread/sysent.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct Thread;
|
||||
using sy_call_t = SysResult(Thread *, uint64_t *);
|
||||
|
||||
struct sysent {
|
||||
sint narg;
|
||||
sy_call_t *call;
|
||||
};
|
||||
|
||||
struct sysentvec {
|
||||
sint size;
|
||||
const sysent *table;
|
||||
};
|
||||
} // namespace orbis
|
||||
51
kernel/orbis/include/orbis/thread/types.hpp
Normal file
51
kernel/orbis/include/orbis/thread/types.hpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
namespace orbis {
|
||||
using lwpid_t = int32_t;
|
||||
using pid_t = int32_t;
|
||||
using uid_t = uint32_t;
|
||||
using gid_t = uint32_t;
|
||||
|
||||
struct rtprio {
|
||||
uint16_t type;
|
||||
uint16_t prio;
|
||||
};
|
||||
|
||||
struct thr_param {
|
||||
ptr<void(void *)> start_func;
|
||||
ptr<void> arg;
|
||||
ptr<char> stack_base;
|
||||
size_t stack_size;
|
||||
ptr<char> tls_base;
|
||||
size_t tls_size;
|
||||
ptr<slong> child_tid; // Address to store the new thread identifier, for the
|
||||
// child's use
|
||||
ptr<slong> parent_tid; // Address to store the new thread identifier, for the
|
||||
// parent's use
|
||||
sint flags; // Thread creation flags. The flags member may specify the
|
||||
// following flags:
|
||||
ptr<rtprio> rtp; // Real-time scheduling priority for the new thread. May be
|
||||
// NULL to inherit the priority from the creating thread
|
||||
ptr<char> name;
|
||||
ptr<void> spare[2];
|
||||
};
|
||||
|
||||
static constexpr auto RFFDG = 1 << 2; // copy fd table
|
||||
static constexpr auto RFPROC = 1 << 4; // change child (else changes curproc)
|
||||
static constexpr auto RFMEM = 1 << 5; // share `address space'
|
||||
static constexpr auto RFNOWAIT = 1 << 6; // give child to init
|
||||
static constexpr auto RFCFDG = 1 << 12; // close all fds, zero fd table
|
||||
static constexpr auto RFSIGSHARE = 1 << 14; // share signal handlers
|
||||
static constexpr auto RFLINUXTHPN =
|
||||
1 << 16; // do linux clone exit parent notification
|
||||
static constexpr auto RFTSIGZMB =
|
||||
1 << 19; // select signal for exit parent notification
|
||||
static constexpr auto RFTSIGSHIFT =
|
||||
20; // selected signal number is in bits 20-27
|
||||
static constexpr auto RFTSIGMASK = 0xFF;
|
||||
static constexpr auto RFPROCDESC = 1 << 28; // return a process descriptor
|
||||
static constexpr auto RFPPWAIT =
|
||||
1 << 31; // parent sleeps until child exits (vfork)
|
||||
|
||||
} // namespace orbis
|
||||
23
kernel/orbis/include/orbis/time.hpp
Normal file
23
kernel/orbis/include/orbis/time.hpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct timespec {
|
||||
uint64_t sec;
|
||||
uint64_t nsec;
|
||||
};
|
||||
struct timeval {
|
||||
int64_t tv_sec;
|
||||
int64_t tv_usec;
|
||||
};
|
||||
struct timezone {
|
||||
sint tz_mineast;
|
||||
sint tz_dsttime;
|
||||
};
|
||||
struct timesec {
|
||||
int64_t tz_time;
|
||||
sint tz_secwest;
|
||||
sint tz_dstsec;
|
||||
};
|
||||
} // namespace orbis
|
||||
171
kernel/orbis/include/orbis/ucontext.hpp
Normal file
171
kernel/orbis/include/orbis/ucontext.hpp
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
namespace orbis {
|
||||
|
||||
struct MContext {
|
||||
ulong onstack;
|
||||
ulong rdi;
|
||||
ulong rsi;
|
||||
ulong rdx;
|
||||
ulong rcx;
|
||||
ulong r8;
|
||||
ulong r9;
|
||||
ulong rax;
|
||||
ulong rbx;
|
||||
ulong rbp;
|
||||
ulong r10;
|
||||
ulong r11;
|
||||
ulong r12;
|
||||
ulong r13;
|
||||
ulong r14;
|
||||
ulong r15;
|
||||
uint trapno;
|
||||
ushort fs;
|
||||
ushort gs;
|
||||
ulong addr;
|
||||
uint flags;
|
||||
ushort es;
|
||||
ushort ds;
|
||||
ulong err;
|
||||
ulong rip;
|
||||
ulong cs;
|
||||
ulong rflags;
|
||||
ulong rsp;
|
||||
ulong ss;
|
||||
ulong len;
|
||||
ulong fpformat;
|
||||
ulong ownedfp;
|
||||
ulong lbrfrom;
|
||||
ulong lbrto;
|
||||
ulong aux1;
|
||||
ulong aux2;
|
||||
ulong fpstate[104];
|
||||
ulong fsbase;
|
||||
ulong gsbase;
|
||||
ulong spare[6];
|
||||
};
|
||||
|
||||
struct Stack {
|
||||
ptr<void> sp;
|
||||
size_t size;
|
||||
sint flags;
|
||||
sint align;
|
||||
};
|
||||
|
||||
struct SigSet {
|
||||
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 {
|
||||
SigSet sigmask;
|
||||
sint unk0[12];
|
||||
MContext mcontext;
|
||||
ptr<UContext> link;
|
||||
Stack stack;
|
||||
sint uc_flags;
|
||||
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;
|
||||
};
|
||||
|
||||
struct SigFrame {
|
||||
uint64_t handler;
|
||||
UContext context;
|
||||
SigInfo info;
|
||||
};
|
||||
} // namespace orbis
|
||||
56
kernel/orbis/include/orbis/uio.hpp
Normal file
56
kernel/orbis/include/orbis/uio.hpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#pragma once
|
||||
|
||||
#include "error/ErrorCode.hpp"
|
||||
#include "orbis-config.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <span>
|
||||
|
||||
namespace orbis {
|
||||
struct IoVec {
|
||||
void *base; // Base address
|
||||
std::uint64_t len; // Length
|
||||
};
|
||||
|
||||
enum class UioRw : std::uint8_t { Read, Write };
|
||||
|
||||
// Segment flag values
|
||||
enum class UioSeg : std::uint8_t {
|
||||
UserSpace, // from user data space
|
||||
SysSpace, // from system space
|
||||
NoCopy // don't copy, already in object
|
||||
};
|
||||
|
||||
struct Uio {
|
||||
std::uint64_t offset;
|
||||
IoVec *iov;
|
||||
std::uint32_t iovcnt;
|
||||
std::int64_t resid;
|
||||
UioSeg segflg;
|
||||
UioRw rw;
|
||||
void *td;
|
||||
|
||||
ErrorCode write(const void *data, std::size_t size) {
|
||||
auto pos = reinterpret_cast<const std::byte *>(data);
|
||||
auto end = pos + size;
|
||||
|
||||
for (auto vec : std::span(iov, iovcnt)) {
|
||||
if (pos >= end) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto nextPos = std::min(pos + vec.len, end);
|
||||
ORBIS_RET_ON_ERROR(uwriteRaw(vec.base, pos, nextPos - pos));
|
||||
offset += nextPos - pos;
|
||||
pos = nextPos;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename T> ErrorCode write(const T &object) {
|
||||
return write(&object, sizeof(T));
|
||||
}
|
||||
};
|
||||
} // namespace orbis
|
||||
120
kernel/orbis/include/orbis/umtx.hpp
Normal file
120
kernel/orbis/include/orbis/umtx.hpp
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
#pragma once
|
||||
|
||||
#include "error/ErrorCode.hpp"
|
||||
#include "orbis-config.hpp"
|
||||
#include "thread/types.hpp"
|
||||
#include "time.hpp"
|
||||
#include <atomic>
|
||||
#include <limits>
|
||||
|
||||
namespace orbis {
|
||||
inline constexpr ulong kUmtxUnowned = 0;
|
||||
inline constexpr ulong kUmtxContested = std::numeric_limits<slong>::min();
|
||||
|
||||
inline constexpr auto kUsyncProcessShared = 1;
|
||||
|
||||
inline constexpr auto kUmutexUnowned = 0;
|
||||
inline constexpr auto kUmutexContested = 0x80000000;
|
||||
inline constexpr auto kUmutexErrorCheck = 2;
|
||||
inline constexpr auto kUmutexPrioInherit = 4;
|
||||
inline constexpr auto kUmutexPrioProtect = 8;
|
||||
|
||||
inline constexpr auto kUrwLockPreferReader = 2;
|
||||
inline constexpr auto kUrwLockWriteOwner = 0x80000000;
|
||||
inline constexpr auto kUrwLockWriteWaiters = 0x40000000;
|
||||
inline constexpr auto kUrwLockReadWaiters = 0x20000000;
|
||||
inline constexpr auto kUrwLockMaxReaders = 0x1fffffff;
|
||||
|
||||
inline constexpr auto kCvWaitCheckUnparking = 0x01;
|
||||
inline constexpr auto kCvWaitAbsTime = 0x02;
|
||||
inline constexpr auto kCvWaitClockId = 0x04;
|
||||
|
||||
inline constexpr auto kUmtxOpLock = 0;
|
||||
inline constexpr auto kUmtxOpUnlock = 1;
|
||||
inline constexpr auto kUmtxOpWait = 2;
|
||||
inline constexpr auto kUmtxOpWake = 3;
|
||||
inline constexpr auto kUmtxOpMutexTrylock = 4;
|
||||
inline constexpr auto kUmtxOpMutexLock = 5;
|
||||
inline constexpr auto kUmtxOpMutexUnock = 6;
|
||||
inline constexpr auto kUmtxOpSetCeiling = 7;
|
||||
inline constexpr auto kUmtxOpCvWait = 8;
|
||||
inline constexpr auto kUmtxOpCvSignal = 9;
|
||||
inline constexpr auto kUmtxOpCvBroadcast = 10;
|
||||
inline constexpr auto kUmtxOpWaitUint = 11;
|
||||
inline constexpr auto kUmtxOpRwRdLock = 12;
|
||||
inline constexpr auto kUmtxOpRwWrLock = 13;
|
||||
inline constexpr auto kUmtxOpRwUnlock = 14;
|
||||
inline constexpr auto kUmtxOpWaitUintPrivate = 15;
|
||||
inline constexpr auto kUmtxOpWakePrivate = 16;
|
||||
inline constexpr auto kUmtxOpMutexWait = 17;
|
||||
inline constexpr auto kUmtxOpMutexWake = 18;
|
||||
inline constexpr auto kUmtxOpSemWait = 19;
|
||||
inline constexpr auto kUmtxOpSemWake = 20;
|
||||
inline constexpr auto kUmtxOpNwakePrivate = 21;
|
||||
inline constexpr auto kUmtxOpMutexWake2 = 22;
|
||||
inline constexpr auto kUmtxOpMutexWake3 = 23;
|
||||
|
||||
inline constexpr auto kSemNamed = 2;
|
||||
|
||||
struct umtx {
|
||||
std::atomic<ulong> owner; // Owner of the mutex
|
||||
};
|
||||
|
||||
struct umutex {
|
||||
std::atomic<lwpid_t> owner; // Owner of the mutex
|
||||
uint32_t flags; // Flags of the mutex
|
||||
uint32_t ceilings[2]; // Priority protect ceiling
|
||||
uint32_t spare[4];
|
||||
};
|
||||
|
||||
struct ucond {
|
||||
std::atomic<uint32_t> has_waiters; // Has waiters in kernel
|
||||
uint32_t flags; // Flags of the condition variable
|
||||
uint32_t clockid; // Clock id
|
||||
uint32_t spare[1]; // Spare space
|
||||
};
|
||||
|
||||
struct urwlock {
|
||||
std::atomic<int32_t> state;
|
||||
uint32_t flags;
|
||||
uint32_t blocked_readers;
|
||||
uint32_t blocked_writers;
|
||||
uint32_t spare[4];
|
||||
};
|
||||
|
||||
struct usem {
|
||||
std::atomic<uint32_t> has_waiters;
|
||||
std::atomic<uint32_t> count;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct Thread;
|
||||
ErrorCode umtx_lock_umtx(Thread *thread, ptr<umtx> umtx, ulong id,
|
||||
std::uint64_t ut);
|
||||
ErrorCode umtx_unlock_umtx(Thread *thread, ptr<umtx> umtx, ulong id);
|
||||
ErrorCode umtx_wait(Thread *thread, ptr<void> addr, ulong id, std::uint64_t ut,
|
||||
bool is32, bool ipc);
|
||||
ErrorCode umtx_wake(Thread *thread, ptr<void> addr, sint n_wake);
|
||||
ErrorCode umtx_trylock_umutex(Thread *thread, ptr<umutex> m);
|
||||
ErrorCode umtx_lock_umutex(Thread *thread, ptr<umutex> m, std::uint64_t ut);
|
||||
ErrorCode umtx_unlock_umutex(Thread *thread, ptr<umutex> m);
|
||||
ErrorCode umtx_set_ceiling(Thread *thread, ptr<umutex> m, std::uint32_t ceiling,
|
||||
ptr<uint32_t> oldCeiling);
|
||||
ErrorCode umtx_cv_wait(Thread *thread, ptr<ucond> cv, ptr<umutex> m,
|
||||
std::uint64_t ut, ulong wflags);
|
||||
ErrorCode umtx_cv_signal(Thread *thread, ptr<ucond> cv);
|
||||
ErrorCode umtx_cv_broadcast(Thread *thread, ptr<ucond> cv);
|
||||
ErrorCode umtx_rw_rdlock(Thread *thread, ptr<urwlock> rwlock, slong fflag,
|
||||
ulong ut);
|
||||
ErrorCode umtx_rw_wrlock(Thread *thread, ptr<urwlock> rwlock, ulong ut);
|
||||
ErrorCode umtx_rw_unlock(Thread *thread, ptr<urwlock> rwlock);
|
||||
ErrorCode umtx_wake_private(Thread *thread, ptr<void> uaddr, sint n_wake);
|
||||
ErrorCode umtx_wait_umutex(Thread *thread, ptr<umutex> m, std::uint64_t ut);
|
||||
ErrorCode umtx_wake_umutex(Thread *thread, ptr<umutex> m, sint wakeFlags);
|
||||
ErrorCode umtx_sem_wait(Thread *thread, ptr<usem> sem, std::uint64_t ut);
|
||||
ErrorCode umtx_sem_wake(Thread *thread, ptr<usem> sem);
|
||||
ErrorCode umtx_nwake_private(Thread *thread, ptr<void *> uaddrs,
|
||||
std::int64_t count);
|
||||
ErrorCode umtx_wake2_umutex(Thread *thread, ptr<umutex> m, sint wakeFlags);
|
||||
ErrorCode umtx_wake3_umutex(Thread *thread, ptr<umutex> m, sint wakeFlags);
|
||||
} // namespace orbis
|
||||
74
kernel/orbis/include/orbis/utils/AtomicOp.hpp
Normal file
74
kernel/orbis/include/orbis/utils/AtomicOp.hpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
namespace orbis {
|
||||
inline namespace utils {
|
||||
// Atomic operation; returns old value, or pair of old value and return value
|
||||
// (cancel op if evaluates to false)
|
||||
template <typename T, typename F, typename RT = std::invoke_result_t<F, T &>>
|
||||
inline std::conditional_t<std::is_void_v<RT>, T, std::pair<T, RT>>
|
||||
atomic_fetch_op(std::atomic<T> &v, F func) {
|
||||
T _new, old = v.load();
|
||||
while (true) {
|
||||
_new = old;
|
||||
if constexpr (std::is_void_v<RT>) {
|
||||
std::invoke(func, _new);
|
||||
if (v.compare_exchange_strong(old, _new)) [[likely]] {
|
||||
return old;
|
||||
}
|
||||
} else {
|
||||
RT ret = std::invoke(func, _new);
|
||||
if (!ret || v.compare_exchange_strong(old, _new)) [[likely]] {
|
||||
return {old, std::move(ret)};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Atomic operation; returns function result value, function is the lambda
|
||||
template <typename T, typename F, typename RT = std::invoke_result_t<F, T &>>
|
||||
inline RT atomic_op(std::atomic<T> &v, F func) {
|
||||
T _new, old = v.load();
|
||||
while (true) {
|
||||
_new = old;
|
||||
if constexpr (std::is_void_v<RT>) {
|
||||
std::invoke(func, _new);
|
||||
if (v.compare_exchange_strong(old, _new)) [[likely]] {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
RT result = std::invoke(func, _new);
|
||||
if (v.compare_exchange_strong(old, _new)) [[likely]] {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__ATOMIC_HLE_ACQUIRE) && defined(__ATOMIC_HLE_RELEASE)
|
||||
static constexpr int s_hle_ack = __ATOMIC_SEQ_CST | __ATOMIC_HLE_ACQUIRE;
|
||||
static constexpr int s_hle_rel = __ATOMIC_SEQ_CST | __ATOMIC_HLE_RELEASE;
|
||||
#else
|
||||
static constexpr int s_hle_ack = __ATOMIC_SEQ_CST;
|
||||
static constexpr int s_hle_rel = __ATOMIC_SEQ_CST;
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
inline bool compare_exchange_hle_acq(std::atomic<T> &dest, T &comp, T exch) {
|
||||
static_assert(sizeof(T) == 4 || sizeof(T) == 8);
|
||||
static_assert(std::atomic<T>::is_always_lock_free);
|
||||
return __atomic_compare_exchange(reinterpret_cast<T *>(&dest), &comp, &exch,
|
||||
false, s_hle_ack, s_hle_ack);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T fetch_add_hle_rel(std::atomic<T> &dest, T value) {
|
||||
static_assert(sizeof(T) == 4 || sizeof(T) == 8);
|
||||
static_assert(std::atomic<T>::is_always_lock_free);
|
||||
return __atomic_fetch_add(reinterpret_cast<T *>(&dest), value, s_hle_rel);
|
||||
}
|
||||
} // namespace utils
|
||||
} // namespace orbis
|
||||
132
kernel/orbis/include/orbis/utils/BitSet.hpp
Normal file
132
kernel/orbis/include/orbis/utils/BitSet.hpp
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
#pragma once
|
||||
#include <bit>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace orbis {
|
||||
inline namespace utils {
|
||||
template <std::size_t Count> struct BitSet {
|
||||
using chunk_type = std::uint64_t;
|
||||
static constexpr auto BitsPerChunk = sizeof(chunk_type) * 8;
|
||||
static constexpr auto ChunkCount = (Count + BitsPerChunk - 1) / BitsPerChunk;
|
||||
chunk_type _bits[ChunkCount]{};
|
||||
|
||||
struct iterator_end {};
|
||||
|
||||
struct iterator {
|
||||
iterator() = default;
|
||||
|
||||
constexpr iterator &operator++() {
|
||||
offset = bitSet->countr_zero(offset + 1);
|
||||
return *this;
|
||||
}
|
||||
constexpr bool operator==(const iterator_end &) const {
|
||||
return offset >= Count;
|
||||
}
|
||||
constexpr std::size_t operator*() const { return offset; }
|
||||
|
||||
private:
|
||||
constexpr iterator(const BitSet *bitSet)
|
||||
: bitSet(bitSet), offset(bitSet->countr_zero()) {}
|
||||
|
||||
const BitSet *bitSet = nullptr;
|
||||
std::size_t offset = 0;
|
||||
|
||||
friend BitSet;
|
||||
};
|
||||
|
||||
[[nodiscard]] constexpr std::size_t countr_one() const {
|
||||
std::size_t result = 0;
|
||||
for (auto bits : _bits) {
|
||||
auto count = std::countr_one(bits);
|
||||
result += count;
|
||||
|
||||
if (count != BitsPerChunk) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::size_t popcount() const {
|
||||
std::size_t result = 0;
|
||||
|
||||
for (auto bits : _bits) {
|
||||
result += std::popcount(bits);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::size_t
|
||||
countr_zero(std::size_t offset = 0) const {
|
||||
std::size_t result = 0;
|
||||
|
||||
if (auto chunkOffset = offset % BitsPerChunk) {
|
||||
auto count =
|
||||
std::countr_zero(_bits[offset / BitsPerChunk] >> chunkOffset);
|
||||
|
||||
if (count != BitsPerChunk) {
|
||||
return count + offset;
|
||||
}
|
||||
|
||||
offset = (offset + BitsPerChunk - 1) & ~(BitsPerChunk - 1);
|
||||
}
|
||||
|
||||
for (auto i = offset / BitsPerChunk; i < ChunkCount; ++i) {
|
||||
auto count = std::countr_zero(_bits[i]);
|
||||
result += count;
|
||||
|
||||
if (count != BitsPerChunk) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result + offset;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool empty() const {
|
||||
for (auto bits : _bits) {
|
||||
if (bits != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool full() const {
|
||||
if constexpr (Count < BitsPerChunk) {
|
||||
return _bits[0] == (static_cast<std::uint64_t>(1) << Count) - 1;
|
||||
}
|
||||
|
||||
for (auto bits : _bits) {
|
||||
if (bits != ~static_cast<chunk_type>(0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr void clear(std::size_t index) {
|
||||
_bits[index / BitsPerChunk] &=
|
||||
~(static_cast<chunk_type>(1) << (index % BitsPerChunk));
|
||||
}
|
||||
|
||||
constexpr void set(std::size_t index) {
|
||||
_bits[index / BitsPerChunk] |= static_cast<chunk_type>(1)
|
||||
<< (index % BitsPerChunk);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool test(std::size_t index) const {
|
||||
return (_bits[index / BitsPerChunk] &
|
||||
(static_cast<chunk_type>(1) << (index % BitsPerChunk))) != 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr iterator begin() const { return iterator(this); }
|
||||
[[nodiscard]] constexpr iterator_end end() const { return {}; }
|
||||
};
|
||||
} // namespace utils
|
||||
} // namespace orbis
|
||||
408
kernel/orbis/include/orbis/utils/IdMap.hpp
Normal file
408
kernel/orbis/include/orbis/utils/IdMap.hpp
Normal file
|
|
@ -0,0 +1,408 @@
|
|||
#pragma once
|
||||
|
||||
#include "BitSet.hpp"
|
||||
#include "Rc.hpp"
|
||||
#include "orbis/utils/SharedMutex.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace orbis {
|
||||
inline namespace utils {
|
||||
template <WithRc T, typename IdT = int, std::size_t MaxId = 4096,
|
||||
std::size_t MinId = 0>
|
||||
requires(MaxId > MinId)
|
||||
class RcIdMap {
|
||||
static constexpr auto ChunkSize = std::min<std::size_t>(MaxId - MinId, 64);
|
||||
static constexpr auto ChunkCount =
|
||||
(MaxId - MinId + ChunkSize - 1) / ChunkSize;
|
||||
|
||||
struct IdMapChunk {
|
||||
BitSet<ChunkSize> mask = {};
|
||||
T *objects[ChunkSize]{};
|
||||
|
||||
~IdMapChunk() {
|
||||
std::size_t index = mask.countr_zero();
|
||||
|
||||
while (index < ChunkSize) {
|
||||
objects[index]->decRef();
|
||||
index = mask.countr_zero(index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool insert(std::size_t index, T *object) {
|
||||
if (mask.test(index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mask.set(index);
|
||||
objects[index] = object;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::size_t insert(T *object) {
|
||||
std::size_t index = mask.countr_one();
|
||||
mask.set(index);
|
||||
objects[index] = object;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
T *get(std::size_t index) const { return objects[index]; }
|
||||
|
||||
void remove(std::size_t index) {
|
||||
objects[index]->decRef();
|
||||
objects[index] = nullptr;
|
||||
mask.clear(index);
|
||||
}
|
||||
};
|
||||
|
||||
IdMapChunk m_chunks[ChunkCount]{};
|
||||
BitSet<ChunkCount> m_fullChunks;
|
||||
|
||||
public:
|
||||
static constexpr auto npos = static_cast<IdT>(~static_cast<std::size_t>(0));
|
||||
|
||||
mutable shared_mutex mutex;
|
||||
|
||||
struct end_iterator {};
|
||||
|
||||
class iterator {
|
||||
const IdMapChunk *chunks = nullptr;
|
||||
std::size_t chunk = 0;
|
||||
std::size_t index = 0;
|
||||
|
||||
public:
|
||||
iterator(const IdMapChunk *chunks) : chunks(chunks) { findNext(); }
|
||||
|
||||
iterator &operator++() {
|
||||
++index;
|
||||
findNext();
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<IdT, T *> operator*() const {
|
||||
return {static_cast<IdT>(chunk * ChunkSize + index + MinId),
|
||||
chunks[chunk].objects[index]};
|
||||
}
|
||||
|
||||
bool operator!=(const end_iterator &) const { return chunk < ChunkCount; }
|
||||
bool operator==(const end_iterator &) const { return chunk >= ChunkCount; }
|
||||
|
||||
private:
|
||||
void findNext() {
|
||||
while (chunk < ChunkCount) {
|
||||
index = chunks[chunk].mask.countr_zero(index);
|
||||
|
||||
if (index < ChunkSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
chunk++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void walk(auto cb) {
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
for (std::size_t chunk = 0; chunk < ChunkCount; ++chunk) {
|
||||
std::size_t index = m_chunks[chunk].mask.countr_zero();
|
||||
|
||||
while (index < ChunkSize) {
|
||||
cb(static_cast<IdT>(index + chunk * ChunkSize + MinId),
|
||||
m_chunks[chunk].objects[index]);
|
||||
|
||||
index = m_chunks[chunk].mask.countr_zero(index + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
iterator begin() const { return iterator{m_chunks}; }
|
||||
|
||||
end_iterator end() const { return {}; }
|
||||
|
||||
private:
|
||||
bool insert_impl(IdT id, T *object) {
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
auto raw = static_cast<std::size_t>(id);
|
||||
auto page = (raw - MinId) / ChunkSize;
|
||||
auto index = (raw - MinId) % ChunkSize;
|
||||
|
||||
if (page >= ChunkCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_chunks[page].insert(index, object)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_chunks[page].mask.full()) {
|
||||
m_fullChunks.set(page);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IdT insert_impl(T *object) {
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
auto page = m_fullChunks.countr_one();
|
||||
|
||||
if (page == ChunkCount) {
|
||||
return npos;
|
||||
}
|
||||
|
||||
auto index = m_chunks[page].insert(object);
|
||||
|
||||
if (m_chunks[page].mask.full()) {
|
||||
m_fullChunks.set(page);
|
||||
}
|
||||
|
||||
return {static_cast<IdT>(page * ChunkSize + index + MinId)};
|
||||
}
|
||||
|
||||
public:
|
||||
IdT insert(T *object) {
|
||||
auto result = insert_impl(object);
|
||||
|
||||
if (result != npos) {
|
||||
object->incRef();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
IdT insert(const Ref<T> &ref) { return insert(ref.get()); }
|
||||
|
||||
IdT insert(Ref<T> &&ref) {
|
||||
auto object = ref.release();
|
||||
auto result = insert_impl(object);
|
||||
|
||||
if (result == npos) {
|
||||
object->decRef();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool insert(IdT id, T *object) {
|
||||
if (insert_impl(id, object)) {
|
||||
object->incRef();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool insert(IdT id, const Ref<T> &ref) { return insert(id, ref.get()); }
|
||||
|
||||
bool insert(IdT id, Ref<T> &&ref) {
|
||||
auto object = ref.release();
|
||||
|
||||
if (!insert_impl(id, object)) {
|
||||
object->decRef();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Ref<T> get(IdT id) const {
|
||||
const auto rawId = static_cast<std::size_t>(id) - MinId;
|
||||
|
||||
if (rawId >= MaxId - MinId) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto chunk = rawId / ChunkSize;
|
||||
const auto index = rawId % ChunkSize;
|
||||
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
if (!m_chunks[chunk].mask.test(index)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return m_chunks[chunk].get(index);
|
||||
}
|
||||
|
||||
bool destroy(IdT id)
|
||||
requires requires(T t) { t.destroy(); }
|
||||
{
|
||||
const auto rawId = static_cast<std::size_t>(id) - MinId;
|
||||
|
||||
if (rawId >= MaxId - MinId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto chunk = rawId / ChunkSize;
|
||||
const auto index = rawId % ChunkSize;
|
||||
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
if (!m_chunks[chunk].mask.test(index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_chunks[chunk].get(index)->destroy();
|
||||
m_chunks[chunk].remove(index);
|
||||
m_fullChunks.clear(chunk);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool close(IdT id) {
|
||||
const auto rawId = static_cast<std::size_t>(id) - MinId;
|
||||
|
||||
if (rawId >= MaxId - MinId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto chunk = rawId / ChunkSize;
|
||||
const auto index = rawId % ChunkSize;
|
||||
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
if (!m_chunks[chunk].mask.test(index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_chunks[chunk].remove(index);
|
||||
m_fullChunks.clear(chunk);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename IdT = int, std::size_t MaxId = 4096,
|
||||
std::size_t MinId = 0>
|
||||
requires(MaxId > MinId)
|
||||
struct OwningIdMap {
|
||||
static constexpr auto ChunkSize = std::min<std::size_t>(MaxId - MinId, 64);
|
||||
static constexpr auto ChunkCount =
|
||||
(MaxId - MinId + ChunkSize - 1) / ChunkSize;
|
||||
|
||||
struct IdMapChunk {
|
||||
BitSet<ChunkSize> mask = {};
|
||||
alignas(T) std::byte objects[sizeof(T) * ChunkSize];
|
||||
|
||||
~IdMapChunk() {
|
||||
std::size_t pageOffset = 0;
|
||||
|
||||
for (auto page : mask._bits) {
|
||||
auto tmp = page;
|
||||
|
||||
while (true) {
|
||||
const auto index = std::countr_zero(tmp);
|
||||
|
||||
if (index >= 64) {
|
||||
break;
|
||||
}
|
||||
|
||||
tmp &= ~(static_cast<std::uint64_t>(1) << index);
|
||||
destroy(pageOffset + index);
|
||||
}
|
||||
|
||||
pageOffset += 64;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... ArgsT>
|
||||
std::pair<std::size_t, T *> emplace_new(ArgsT &&...args) {
|
||||
std::size_t index = mask.countr_one();
|
||||
|
||||
if (index >= ChunkSize) {
|
||||
return {};
|
||||
}
|
||||
|
||||
mask.set(index);
|
||||
|
||||
return {index,
|
||||
std::construct_at(get(index), std::forward<ArgsT>(args)...)};
|
||||
}
|
||||
|
||||
T *get(std::size_t index) {
|
||||
return reinterpret_cast<T *>(objects + sizeof(T) * index);
|
||||
}
|
||||
|
||||
void destroy(std::size_t index) {
|
||||
std::destroy_at(get(index));
|
||||
mask.clear(index);
|
||||
}
|
||||
};
|
||||
|
||||
IdMapChunk chunks[ChunkCount]{};
|
||||
BitSet<ChunkCount> fullChunks;
|
||||
|
||||
template <typename... ArgsT>
|
||||
requires(std::is_constructible_v<T, ArgsT...>)
|
||||
std::pair<IdT, T *> emplace(ArgsT &&...args) {
|
||||
auto page = fullChunks.countr_one();
|
||||
|
||||
if (page == ChunkCount) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto newElem = chunks[page].emplace_new(std::forward<ArgsT>(args)...);
|
||||
|
||||
if (chunks[page].mask.full()) {
|
||||
fullChunks.set(page);
|
||||
}
|
||||
|
||||
return {static_cast<IdT>(page * ChunkSize + newElem.first + MinId),
|
||||
newElem.second};
|
||||
}
|
||||
|
||||
T *get(IdT id) {
|
||||
const auto rawId = static_cast<std::size_t>(id) - MinId;
|
||||
const auto chunk = rawId / ChunkSize;
|
||||
const auto index = rawId % ChunkSize;
|
||||
|
||||
if (chunk >= ChunkCount) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!chunks[chunk].mask.test(index)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return chunks[chunk].get(index);
|
||||
}
|
||||
|
||||
bool destroy(IdT id) {
|
||||
const auto rawId = static_cast<std::size_t>(id) - MinId;
|
||||
const auto chunk = rawId / ChunkSize;
|
||||
const auto index = rawId % ChunkSize;
|
||||
|
||||
if (chunk >= ChunkCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!chunks[chunk].mask.test(index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
chunks[chunk].destroy(index);
|
||||
fullChunks.clear(chunk);
|
||||
return true;
|
||||
}
|
||||
|
||||
void walk(auto cb) {
|
||||
for (std::size_t chunk = 0; chunk < ChunkCount; ++chunk) {
|
||||
std::size_t index = chunks[chunk].mask.countr_zero();
|
||||
|
||||
while (index < ChunkSize) {
|
||||
auto id = static_cast<IdT>(index + chunk * ChunkSize + MinId);
|
||||
cb(id, chunks[chunk].get(id));
|
||||
|
||||
index = chunks[chunk].mask.countr_zero(index + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace utils
|
||||
} // namespace orbis
|
||||
48
kernel/orbis/include/orbis/utils/LinkedNode.hpp
Normal file
48
kernel/orbis/include/orbis/utils/LinkedNode.hpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
namespace orbis {
|
||||
inline namespace utils {
|
||||
template <typename T> struct LinkedNode final {
|
||||
T object;
|
||||
LinkedNode *next = nullptr;
|
||||
LinkedNode *prev = nullptr;
|
||||
|
||||
void insertNext(LinkedNode &other) {
|
||||
other.next = next;
|
||||
other.prev = this;
|
||||
|
||||
if (next != nullptr) {
|
||||
next->prev = &other;
|
||||
}
|
||||
|
||||
next = &other;
|
||||
}
|
||||
|
||||
void insertPrev(LinkedNode &other) {
|
||||
other.next = this;
|
||||
other.prev = prev;
|
||||
|
||||
if (prev != nullptr) {
|
||||
prev->next = &other;
|
||||
}
|
||||
|
||||
prev = &other;
|
||||
}
|
||||
|
||||
LinkedNode *erase() {
|
||||
if (prev != nullptr) {
|
||||
prev->next = next;
|
||||
}
|
||||
|
||||
if (next != nullptr) {
|
||||
next->prev = prev;
|
||||
}
|
||||
|
||||
prev = nullptr;
|
||||
auto result = next;
|
||||
next = nullptr;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
} // namespace utils
|
||||
} // namespace orbis
|
||||
127
kernel/orbis/include/orbis/utils/Logs.hpp
Normal file
127
kernel/orbis/include/orbis/utils/Logs.hpp
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
#pragma once
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
|
||||
namespace orbis {
|
||||
inline namespace logs {
|
||||
enum class LogLevel : unsigned char {
|
||||
Always,
|
||||
Fatal,
|
||||
Error,
|
||||
Todo,
|
||||
Success,
|
||||
Warning,
|
||||
Notice,
|
||||
Trace
|
||||
};
|
||||
|
||||
// Currently enabled log level
|
||||
inline std::atomic<LogLevel> logs_level = LogLevel::Notice;
|
||||
|
||||
template <typename T, typename = void> struct log_class_string {
|
||||
static const T &get_object(const void *arg) {
|
||||
return *static_cast<const T *>(arg);
|
||||
}
|
||||
static void format(std::string &out, const void *arg);
|
||||
};
|
||||
|
||||
template <> struct log_class_string<void *, void> {
|
||||
static void format(std::string &out, const void *arg);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct log_class_string<T *, void> : log_class_string<void *, void> {};
|
||||
|
||||
template <> struct log_class_string<char *, void> {
|
||||
static void format_n(std::string &out, const void *str, std::size_t n);
|
||||
static void format(std::string &out, const void *arg);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct log_class_string<const char *, void> : log_class_string<char *> {};
|
||||
|
||||
template <std::size_t N> struct log_class_string<char[N]> {
|
||||
static void format(std::string &out, const void *arg) {
|
||||
log_class_string<char *, void>::format_n(out, arg, N);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t N> struct log_class_string<const char[N]> {
|
||||
static void format(std::string &out, const void *arg) {
|
||||
log_class_string<char *, void>::format_n(out, arg, N);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t N> struct log_class_string<char (*)[N]> {
|
||||
static void format(std::string &out, const void *arg) {
|
||||
log_class_string<char *, void>::format_n(out, *(char **)arg, N);
|
||||
}
|
||||
};
|
||||
|
||||
template <std::size_t N> struct log_class_string<const char (*)[N]> {
|
||||
static void format(std::string &out, const void *arg) {
|
||||
log_class_string<char *, void>::format_n(out, *(char **)arg, N);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct log_class_string<char8_t *, void> : log_class_string<char *> {};
|
||||
|
||||
template <>
|
||||
struct log_class_string<const char8_t *, void> : log_class_string<char *> {};
|
||||
|
||||
template <typename... Args>
|
||||
using log_args_t = const void *(&&)[sizeof...(Args) + 1];
|
||||
|
||||
struct log_type_info {
|
||||
decltype(&log_class_string<int>::format) log_string;
|
||||
|
||||
template <typename T> static constexpr log_type_info make() {
|
||||
return log_type_info{
|
||||
&log_class_string<T>::format,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
constexpr const log_type_info type_info_v[sizeof...(Args) + 1]{
|
||||
log_type_info::make<std::remove_cvref_t<Args>>()...};
|
||||
|
||||
void _orbis_log_print(LogLevel lvl, std::string_view msg,
|
||||
std::string_view names, const log_type_info *sup, ...);
|
||||
|
||||
template <typename... Args>
|
||||
void _orbis_log_impl(LogLevel lvl, std::string_view msg, std::string_view names,
|
||||
const Args &...args) {
|
||||
// Fast filtering
|
||||
if (logs_level.load(std::memory_order::relaxed) < lvl)
|
||||
return;
|
||||
|
||||
_orbis_log_print(lvl, msg, names, type_info_v<Args...>,
|
||||
static_cast<const void *>(&args)...);
|
||||
}
|
||||
|
||||
} // namespace logs
|
||||
} // namespace orbis
|
||||
|
||||
#define ORBIS_LOG_FATAL(msg, ...) \
|
||||
::orbis::_orbis_log_impl(::orbis::LogLevel::Fatal, (msg), #__VA_ARGS__, \
|
||||
##__VA_ARGS__)
|
||||
#define ORBIS_LOG_ERROR(msg, ...) \
|
||||
::orbis::_orbis_log_impl(::orbis::LogLevel::Error, (msg), #__VA_ARGS__, \
|
||||
##__VA_ARGS__)
|
||||
#define ORBIS_LOG_TODO(msg, ...) \
|
||||
::orbis::_orbis_log_impl(::orbis::LogLevel::Todo, (msg), #__VA_ARGS__, \
|
||||
##__VA_ARGS__)
|
||||
#define ORBIS_LOG_SUCCESS(msg, ...) \
|
||||
::orbis::_orbis_log_impl(::orbis::LogLevel::Success, (msg), #__VA_ARGS__, \
|
||||
##__VA_ARGS__)
|
||||
#define ORBIS_LOG_WARNING(msg, ...) \
|
||||
::orbis::_orbis_log_impl(::orbis::LogLevel::Warning, (msg), #__VA_ARGS__, \
|
||||
##__VA_ARGS__)
|
||||
#define ORBIS_LOG_NOTICE(msg, ...) \
|
||||
::orbis::_orbis_log_impl(::orbis::LogLevel::Notice, (msg), #__VA_ARGS__, \
|
||||
##__VA_ARGS__)
|
||||
#define ORBIS_LOG_TRACE(msg, ...) \
|
||||
::orbis::_orbis_log_impl(::orbis::LogLevel::Trace, (msg), #__VA_ARGS__, \
|
||||
##__VA_ARGS__)
|
||||
151
kernel/orbis/include/orbis/utils/Rc.hpp
Normal file
151
kernel/orbis/include/orbis/utils/Rc.hpp
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace orbis {
|
||||
// template <typename T, typename... Args> T *knew(Args &&...args);
|
||||
inline namespace utils {
|
||||
void kfree(void *ptr, std::size_t size);
|
||||
|
||||
struct RcBase {
|
||||
std::atomic<unsigned> references{0};
|
||||
unsigned _total_size = 0; // Set by knew/kcreate
|
||||
|
||||
virtual ~RcBase() = default;
|
||||
|
||||
void incRef() {
|
||||
if (!_total_size)
|
||||
std::abort();
|
||||
if (references.fetch_add(1, std::memory_order::relaxed) > 4096) {
|
||||
assert(!"too many references");
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if object was destroyed
|
||||
bool decRef() {
|
||||
if (references.fetch_sub(1, std::memory_order::relaxed) == 1) {
|
||||
auto size = _total_size;
|
||||
this->~RcBase();
|
||||
orbis::utils::kfree(this, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept WithRc = requires(T t) {
|
||||
t.incRef();
|
||||
t.decRef();
|
||||
};
|
||||
|
||||
template <typename T> class Ref {
|
||||
T *m_ref = nullptr;
|
||||
|
||||
public:
|
||||
Ref() = default;
|
||||
Ref(std::nullptr_t) noexcept {}
|
||||
|
||||
template <typename OT>
|
||||
requires(std::is_base_of_v<T, OT>)
|
||||
Ref(OT *ref) noexcept : m_ref(ref) {
|
||||
if (m_ref != nullptr) {
|
||||
ref->incRef();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OT>
|
||||
requires(std::is_base_of_v<T, OT>)
|
||||
Ref(const Ref<OT> &other) noexcept : m_ref(other.get()) {
|
||||
if (m_ref != nullptr) {
|
||||
m_ref->incRef();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OT>
|
||||
requires(std::is_base_of_v<T, OT>)
|
||||
Ref(Ref<OT> &&other) noexcept : m_ref(other.release()) {}
|
||||
|
||||
Ref(const Ref &other) noexcept : m_ref(other.get()) {
|
||||
if (m_ref != nullptr) {
|
||||
m_ref->incRef();
|
||||
}
|
||||
}
|
||||
Ref(Ref &&other) noexcept : m_ref(other.release()) {}
|
||||
|
||||
template <typename OT>
|
||||
requires(std::is_base_of_v<T, OT>)
|
||||
Ref &operator=(Ref<OT> &&other) noexcept {
|
||||
other.template cast<T>().swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename OT>
|
||||
requires(std::is_base_of_v<T, OT>)
|
||||
Ref &operator=(OT *other) noexcept {
|
||||
*this = Ref(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename OT>
|
||||
requires(std::is_base_of_v<T, OT>)
|
||||
Ref &operator=(const Ref<OT> &other) noexcept {
|
||||
*this = Ref(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ref &operator=(const Ref &other) noexcept {
|
||||
*this = Ref(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ref &operator=(Ref &&other) noexcept {
|
||||
other.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Ref() {
|
||||
if (m_ref != nullptr) {
|
||||
m_ref->decRef();
|
||||
}
|
||||
}
|
||||
|
||||
void swap(Ref<T> &other) noexcept { std::swap(m_ref, other.m_ref); }
|
||||
T *get() const { return m_ref; }
|
||||
T *release() { return std::exchange(m_ref, nullptr); }
|
||||
T *operator->() const { return m_ref; }
|
||||
explicit operator bool() const { return m_ref != nullptr; }
|
||||
bool operator==(const Ref &) const = default;
|
||||
bool operator==(std::nullptr_t) const { return m_ref == nullptr; }
|
||||
auto operator<=>(const T *other) const { return m_ref <=> other; }
|
||||
auto operator<=>(const Ref &other) const = default;
|
||||
|
||||
template <typename OtherT> Ref<OtherT> cast() {
|
||||
return dynamic_cast<OtherT *>(m_ref);
|
||||
}
|
||||
template <typename OtherT> Ref<OtherT> staticCast() {
|
||||
return static_cast<OtherT *>(m_ref);
|
||||
}
|
||||
|
||||
template <typename OtherT> OtherT *rawCast() {
|
||||
return dynamic_cast<OtherT *>(m_ref);
|
||||
}
|
||||
template <typename OtherT> OtherT *rawStaticCast() {
|
||||
return static_cast<OtherT *>(m_ref);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> Ref(T *) -> Ref<T>;
|
||||
|
||||
// template <WithRc T, typename... ArgsT>
|
||||
// requires(std::is_constructible_v<T, ArgsT...>)
|
||||
// Ref<T> kcreate(ArgsT &&...args) {
|
||||
// return Ref<T>(knew<T>(std::forward<ArgsT>(args)...));
|
||||
// }
|
||||
} // namespace utils
|
||||
} // namespace orbis
|
||||
167
kernel/orbis/include/orbis/utils/SharedAtomic.hpp
Normal file
167
kernel/orbis/include/orbis/utils/SharedAtomic.hpp
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <system_error>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
|
||||
namespace orbis {
|
||||
inline void yield() { std::this_thread::yield(); }
|
||||
inline void relax() {
|
||||
#if defined(__GNUC__) && (defined __i386__ || defined __x86_64__)
|
||||
__builtin_ia32_pause();
|
||||
#else
|
||||
yield();
|
||||
#endif
|
||||
}
|
||||
|
||||
static constexpr auto kRelaxSpinCount = 12;
|
||||
static constexpr auto kSpinCount = 16;
|
||||
|
||||
inline namespace utils {
|
||||
inline thread_local bool (*g_scopedUnblock)(bool) = nullptr;
|
||||
|
||||
bool try_spin_wait(auto &&pred) {
|
||||
for (std::size_t i = 0; i < kSpinCount; ++i) {
|
||||
if (pred()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i < kRelaxSpinCount) {
|
||||
relax();
|
||||
} else {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool spin_wait(auto &&pred, auto &&spinCond) {
|
||||
if (try_spin_wait(pred)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
while (spinCond()) {
|
||||
if (pred()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct shared_atomic32 : std::atomic<std::uint32_t> {
|
||||
using atomic::atomic;
|
||||
using atomic::operator=;
|
||||
|
||||
template <typename Clock, typename Dur>
|
||||
std::errc wait(std::uint32_t oldValue,
|
||||
std::chrono::time_point<Clock, Dur> timeout) {
|
||||
if (try_spin_wait(
|
||||
[&] { return load(std::memory_order::acquire) != oldValue; })) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto now = Clock::now();
|
||||
|
||||
if (timeout < now) {
|
||||
return std::errc::timed_out;
|
||||
}
|
||||
|
||||
return wait_impl(
|
||||
oldValue,
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(timeout - now));
|
||||
}
|
||||
|
||||
std::errc wait(std::uint32_t oldValue,
|
||||
std::chrono::microseconds usec_timeout) {
|
||||
return wait_impl(oldValue, usec_timeout);
|
||||
}
|
||||
|
||||
std::errc wait(std::uint32_t oldValue) {
|
||||
if (try_spin_wait(
|
||||
[&] { return load(std::memory_order::acquire) != oldValue; })) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return wait_impl(oldValue);
|
||||
}
|
||||
|
||||
auto wait(auto &fn) -> decltype(fn(std::declval<std::uint32_t &>())) {
|
||||
while (true) {
|
||||
std::uint32_t lastValue;
|
||||
if (try_spin_wait([&] {
|
||||
lastValue = load(std::memory_order::acquire);
|
||||
return fn(lastValue);
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (wait_impl(lastValue) != std::errc{}) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int notify_one() const { return notify_n(1); }
|
||||
int notify_all() const { return notify_n(std::numeric_limits<int>::max()); }
|
||||
|
||||
int notify_n(int count) const;
|
||||
|
||||
// Atomic operation; returns old value, or pair of old value and return value
|
||||
// (cancel op if evaluates to false)
|
||||
template <typename F, typename RT = std::invoke_result_t<F, std::uint32_t &>>
|
||||
std::conditional_t<std::is_void_v<RT>, std::uint32_t,
|
||||
std::pair<std::uint32_t, RT>>
|
||||
fetch_op(F &&func) {
|
||||
std::uint32_t _new;
|
||||
std::uint32_t old = load(std::memory_order::relaxed);
|
||||
while (true) {
|
||||
_new = old;
|
||||
if constexpr (std::is_void_v<RT>) {
|
||||
std::invoke(std::forward<F>(func), _new);
|
||||
if (compare_exchange_strong(old, _new)) [[likely]] {
|
||||
return old;
|
||||
}
|
||||
} else {
|
||||
RT ret = std::invoke(std::forward<F>(func), _new);
|
||||
if (!ret || compare_exchange_strong(old, _new)) [[likely]] {
|
||||
return {old, std::move(ret)};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Atomic operation; returns function result value
|
||||
template <typename F, typename RT = std::invoke_result_t<F, std::uint32_t &>>
|
||||
RT op(F &&func) {
|
||||
std::uint32_t _new;
|
||||
std::uint32_t old = load(std::memory_order::relaxed);
|
||||
|
||||
while (true) {
|
||||
_new = old;
|
||||
if constexpr (std::is_void_v<RT>) {
|
||||
std::invoke(std::forward<F>(func), _new);
|
||||
if (compare_exchange_strong(old, _new)) [[likely]] {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
RT result = std::invoke(std::forward<F>(func), _new);
|
||||
if (compare_exchange_strong(old, _new)) [[likely]] {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] std::errc wait_impl(std::uint32_t oldValue,
|
||||
std::chrono::microseconds usec_timeout =
|
||||
std::chrono::microseconds::max());
|
||||
};
|
||||
} // namespace utils
|
||||
} // namespace orbis
|
||||
92
kernel/orbis/include/orbis/utils/SharedCV.hpp
Normal file
92
kernel/orbis/include/orbis/utils/SharedCV.hpp
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis/utils/SharedAtomic.hpp"
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <orbis/utils/AtomicOp.hpp>
|
||||
#include <orbis/utils/SharedMutex.hpp>
|
||||
#include <system_error>
|
||||
|
||||
namespace orbis {
|
||||
inline namespace utils {
|
||||
// IPC-ready lightweight condition variable
|
||||
class shared_cv final {
|
||||
enum : unsigned {
|
||||
c_waiter_mask = 0xffff,
|
||||
c_signal_mask = 0x7fff0000,
|
||||
#ifdef ORBIS_HAS_FUTEX
|
||||
c_locked_mask = 0x80000000,
|
||||
#endif
|
||||
c_signal_one = c_waiter_mask + 1,
|
||||
};
|
||||
|
||||
shared_atomic32 m_value{0};
|
||||
|
||||
protected:
|
||||
// Increment waiter count
|
||||
unsigned add_waiter() noexcept {
|
||||
return m_value.op([](unsigned &value) -> unsigned {
|
||||
if ((value & c_signal_mask) == c_signal_mask ||
|
||||
(value & c_waiter_mask) == c_waiter_mask) {
|
||||
// Signal or waiter overflow, return immediately
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add waiter (c_waiter_mask)
|
||||
value += 1;
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
// Internal waiting function
|
||||
std::errc impl_wait(shared_mutex &mutex, unsigned _val,
|
||||
std::uint64_t usec_timeout) noexcept;
|
||||
|
||||
// Try to notify up to _count threads
|
||||
void impl_wake(shared_mutex &mutex, int _count) noexcept;
|
||||
|
||||
public:
|
||||
constexpr shared_cv() = default;
|
||||
|
||||
std::errc
|
||||
wait(std::unique_lock<shared_mutex> &lock,
|
||||
std::chrono::microseconds timeout = std::chrono::microseconds::max()) {
|
||||
return wait(*lock.mutex(), timeout.count());
|
||||
}
|
||||
|
||||
template <typename Rep, typename Period>
|
||||
std::errc wait(std::unique_lock<shared_mutex> &lock,
|
||||
std::chrono::duration<Rep, Period> timeout) {
|
||||
return wait(
|
||||
lock,
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(timeout).count());
|
||||
}
|
||||
|
||||
std::errc wait(shared_mutex &mutex,
|
||||
std::uint64_t usec_timeout = -1) noexcept {
|
||||
const unsigned _val = add_waiter();
|
||||
if (!_val) {
|
||||
return {};
|
||||
}
|
||||
|
||||
mutex.unlock();
|
||||
return impl_wait(mutex, _val, usec_timeout);
|
||||
}
|
||||
|
||||
// Wake one thread
|
||||
void notify_one(shared_mutex &mutex) noexcept {
|
||||
if (m_value) {
|
||||
impl_wake(mutex, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Wake all threads
|
||||
void notify_all(shared_mutex &mutex) noexcept {
|
||||
if (m_value) {
|
||||
impl_wake(mutex, INT_MAX);
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace utils
|
||||
} // namespace orbis
|
||||
151
kernel/orbis/include/orbis/utils/SharedMutex.hpp
Normal file
151
kernel/orbis/include/orbis/utils/SharedMutex.hpp
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <orbis/utils/AtomicOp.hpp>
|
||||
#include <orbis/utils/SharedAtomic.hpp>
|
||||
#include <system_error>
|
||||
|
||||
namespace orbis {
|
||||
inline namespace utils {
|
||||
// IPC-ready shared mutex, using only writer lock is recommended
|
||||
class shared_mutex final {
|
||||
friend class shared_cv;
|
||||
|
||||
enum : unsigned {
|
||||
c_one = 1u << 14, // Fixed-point 1.0 value (one writer)
|
||||
c_sig = 1u << 30,
|
||||
c_err = 1u << 31,
|
||||
};
|
||||
|
||||
shared_atomic32 m_value{};
|
||||
|
||||
void impl_lock_shared(unsigned val);
|
||||
void impl_unlock_shared(unsigned old);
|
||||
std::errc impl_wait();
|
||||
void impl_signal();
|
||||
void impl_lock(unsigned val);
|
||||
void impl_unlock(unsigned old);
|
||||
void impl_lock_upgrade();
|
||||
|
||||
public:
|
||||
constexpr shared_mutex() = default;
|
||||
|
||||
bool try_lock_shared() {
|
||||
// Conditional increment
|
||||
unsigned value = m_value.load();
|
||||
return value < c_one - 1 &&
|
||||
m_value.compare_exchange_strong(value, value + 1);
|
||||
}
|
||||
|
||||
// Lock with HLE acquire hint
|
||||
void lock_shared() {
|
||||
unsigned value = m_value.load();
|
||||
if (value < c_one - 1) [[likely]] {
|
||||
unsigned old = value;
|
||||
if (compare_exchange_hle_acq(m_value, old, value + 1)) [[likely]] {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
impl_lock_shared(value + 1);
|
||||
}
|
||||
|
||||
// Unlock with HLE release hint
|
||||
void unlock_shared() {
|
||||
const unsigned value = fetch_add_hle_rel(m_value, -1u);
|
||||
if (value >= c_one) [[unlikely]] {
|
||||
impl_unlock_shared(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock() {
|
||||
unsigned value = 0;
|
||||
return m_value.compare_exchange_strong(value, c_one);
|
||||
}
|
||||
|
||||
// Lock with HLE acquire hint
|
||||
void lock() {
|
||||
unsigned value = 0;
|
||||
if (!compare_exchange_hle_acq(m_value, value, +c_one)) [[unlikely]] {
|
||||
impl_lock(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock with HLE release hint
|
||||
void unlock() {
|
||||
const unsigned value = fetch_add_hle_rel(m_value, 0u - c_one);
|
||||
if (value != c_one) [[unlikely]] {
|
||||
impl_unlock(value);
|
||||
}
|
||||
}
|
||||
|
||||
bool try_lock_upgrade() {
|
||||
unsigned value = m_value.load();
|
||||
|
||||
// Conditional increment, try to convert a single reader into a writer,
|
||||
// ignoring other writers
|
||||
return (value + c_one - 1) % c_one == 0 &&
|
||||
m_value.compare_exchange_strong(value, value + c_one - 1);
|
||||
}
|
||||
|
||||
void lock_upgrade() {
|
||||
if (!try_lock_upgrade()) [[unlikely]] {
|
||||
impl_lock_upgrade();
|
||||
}
|
||||
}
|
||||
|
||||
void lock_downgrade() {
|
||||
// Convert to reader lock (can result in broken state)
|
||||
m_value -= c_one - 1;
|
||||
}
|
||||
|
||||
// Check whether can immediately obtain an exclusive (writer) lock
|
||||
[[nodiscard]] bool is_free() const { return m_value.load() == 0; }
|
||||
|
||||
// Check whether can immediately obtain a shared (reader) lock
|
||||
[[nodiscard]] bool is_lockable() const { return m_value.load() < c_one - 1; }
|
||||
|
||||
private:
|
||||
// For CV
|
||||
bool lock_forced(int count = 1);
|
||||
};
|
||||
|
||||
// Simplified shared (reader) lock implementation.
|
||||
class reader_lock final {
|
||||
shared_mutex &m_mutex;
|
||||
bool m_upgraded = false;
|
||||
|
||||
public:
|
||||
reader_lock(const reader_lock &) = delete;
|
||||
reader_lock &operator=(const reader_lock &) = delete;
|
||||
explicit reader_lock(shared_mutex &mutex) : m_mutex(mutex) {
|
||||
m_mutex.lock_shared();
|
||||
}
|
||||
|
||||
// One-way lock upgrade; note that the observed state could have been changed
|
||||
void upgrade() {
|
||||
if (!m_upgraded) {
|
||||
m_mutex.lock_upgrade();
|
||||
m_upgraded = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to upgrade; if it succeeds, the observed state has NOT been changed
|
||||
bool try_upgrade() {
|
||||
return m_upgraded || (m_upgraded = m_mutex.try_lock_upgrade());
|
||||
}
|
||||
|
||||
~reader_lock() { m_upgraded ? m_mutex.unlock() : m_mutex.unlock_shared(); }
|
||||
};
|
||||
|
||||
class writer_lock final {
|
||||
shared_mutex &m_mutex;
|
||||
|
||||
public:
|
||||
writer_lock(const writer_lock &) = delete;
|
||||
writer_lock &operator=(const writer_lock &) = delete;
|
||||
explicit writer_lock(shared_mutex &mutex) : m_mutex(mutex) { m_mutex.lock(); }
|
||||
~writer_lock() { m_mutex.unlock(); }
|
||||
};
|
||||
} // namespace utils
|
||||
} // namespace orbis
|
||||
13
kernel/orbis/include/orbis/vm.hpp
Normal file
13
kernel/orbis/include/orbis/vm.hpp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "orbis-config.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct MemoryProtection {
|
||||
uint64_t startAddress;
|
||||
uint64_t endAddress;
|
||||
int32_t prot;
|
||||
};
|
||||
|
||||
static_assert(sizeof(MemoryProtection) == 24);
|
||||
} // namespace orbis
|
||||
Loading…
Add table
Add a link
Reference in a new issue