rpcsx/orbis-kernel/include/orbis/KernelContext.hpp

179 lines
4.7 KiB
C++
Raw Normal View History

2023-07-03 13:10:16 +02:00
#pragma once
#include "evf.hpp"
2023-07-29 23:44:24 +02:00
#include "ipmi.hpp"
#include "osem.hpp"
2023-07-03 13:10:16 +02:00
#include "utils/LinkedNode.hpp"
#include "utils/SharedCV.hpp"
2023-07-03 13:10:16 +02:00
#include "utils/SharedMutex.hpp"
2023-08-15 02:04:25 +02:00
#include "AudioOut.hpp"
2023-07-04 18:19:17 +02:00
#include "KernelAllocator.hpp"
#include "orbis/thread/types.hpp"
2023-07-03 13:10:16 +02:00
#include <algorithm>
#include <cstdint>
#include <mutex>
#include <pthread.h>
2023-07-03 13:10:16 +02:00
#include <utility>
namespace orbis {
2023-07-04 18:19:17 +02:00
struct Process;
struct Thread;
struct UmtxKey {
// TODO: may contain a reference to a shared memory
2023-07-22 11:03:46 +02:00
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;
utils::kmultimap<UmtxKey, UmtxCond> sleep_queue;
utils::kmultimap<UmtxKey, UmtxCond> spare_queue;
std::pair<const UmtxKey, UmtxCond> *enqueue(UmtxKey &key, Thread *thr);
void erase(std::pair<const UmtxKey, UmtxCond> *obj);
uint notify_one(const UmtxKey &key);
uint notify_all(const UmtxKey &key);
};
2023-07-03 13:10:16 +02:00
2023-07-04 18:19:17 +02:00
class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final {
public:
KernelContext();
~KernelContext();
2023-07-03 13:10:16 +02:00
2023-07-04 18:19:17 +02:00
Process *createProcess(pid_t pid);
void deleteProcess(Process *proc);
Process *findProcessById(pid_t pid) const;
2023-07-03 13:10:16 +02:00
2023-07-15 09:15:32 +02:00
long getTscFreq();
void *kalloc(std::size_t size,
std::size_t align = __STDCPP_DEFAULT_NEW_ALIGNMENT__);
void kfree(void *ptr, std::size_t size);
2023-07-03 13:10:16 +02:00
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);
2023-07-17 18:15:08 +02:00
std::strncpy(it->second->name, it->first.c_str(), 32);
}
return {it->second.get(), inserted};
2023-07-05 00:43:47 +02:00
}
Ref<EventFlag> findEventFlag(std::string_view name) {
std::lock_guard lock(m_evf_mtx);
2023-07-05 00:43:47 +02:00
if (auto it = m_event_flags.find(name); it != m_event_flags.end()) {
return it->second;
}
return {};
2023-07-05 00:43:47 +02:00
}
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<IpmiServer *, bool> createIpmiServer(utils::kstring name) {
2023-07-29 23:44:24 +02:00
std::lock_guard lock(m_sem_mtx);
auto [it, inserted] = mIpmiServers.try_emplace(std::move(name), nullptr);
if (inserted) {
it->second = knew<IpmiServer>(name);
}
return {it->second.get(), inserted};
}
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 {};
}
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>>
2023-07-22 11:03:46 +02:00
getUmtxChainIndexed(int i, Thread *t, uint32_t flags, void *ptr);
// Internal Umtx: Wait/Cv/Sem
2023-07-22 11:03:46 +02:00
auto getUmtxChain0(Thread *t, uint32_t flags, void *ptr) {
return getUmtxChainIndexed(0, t, flags, ptr);
}
// Internal Umtx: Mutex/Umtx/Rwlock
2023-07-22 11:03:46 +02:00
auto getUmtxChain1(Thread *t, uint32_t flags, void *ptr) {
return getUmtxChainIndexed(1, t, flags, ptr);
}
2023-07-29 21:46:28 +02:00
Ref<RcBase> shmDevice;
2023-07-30 00:45:28 +02:00
Ref<RcBase> dmemDevice;
2023-07-30 13:56:25 +02:00
Ref<RcBase> blockpoolDevice;
2023-08-15 02:04:25 +02:00
AudioOut *audioOut = nullptr;
2023-07-29 21:46:28 +02:00
2023-07-03 13:10:16 +02:00
private:
mutable pthread_mutex_t m_heap_mtx;
void *m_heap_next = this + 1;
bool m_heap_is_freeing = false;
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]{};
2023-07-15 09:15:32 +02:00
std::atomic<long> m_tsc_freq{0};
2023-07-03 13:10:16 +02:00
mutable shared_mutex m_proc_mtx;
utils::LinkedNode<Process> *m_processes = nullptr;
2023-07-17 18:15:08 +02:00
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;
2023-07-29 23:44:24 +02:00
shared_mutex mIpmiServerMtx;
utils::kmap<utils::kstring, Ref<IpmiServer>> mIpmiServers;
2023-07-03 13:10:16 +02:00
};
2023-07-04 18:19:17 +02:00
extern KernelContext &g_context;
} // namespace orbis