diff --git a/CMakeLists.txt b/CMakeLists.txt index 46461c6ac..c8f4f698a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -208,10 +208,9 @@ set(GNM_LIB src/core/libraries/gnmdriver/gnmdriver.cpp src/core/libraries/gnmdriver/gnm_error.h ) -set(KERNEL_LIB src/core/libraries/kernel/event_flag/event_flag.cpp - src/core/libraries/kernel/event_flag/event_flag.h - src/core/libraries/kernel/event_flag/event_flag_obj.cpp - src/core/libraries/kernel/event_flag/event_flag_obj.h +set(KERNEL_LIB + src/core/libraries/kernel/threads/event_flag.cpp + src/core/libraries/kernel/threads/event_flag.h src/core/libraries/kernel/threads/thr_attr.cpp src/core/libraries/kernel/threads/thr_cond.cpp src/core/libraries/kernel/threads/thr_create.cpp @@ -220,16 +219,19 @@ set(KERNEL_LIB src/core/libraries/kernel/event_flag/event_flag.cpp src/core/libraries/kernel/threads/thr_rwlock.cpp src/core/libraries/kernel/threads/thr_sem.cpp src/core/libraries/kernel/threads/thr_spec.cpp + src/core/libraries/kernel/threads/thr_stack.cpp + src/core/libraries/kernel/threads/thr_clean.cpp + src/core/libraries/kernel/threads/thread_state.cpp + src/core/libraries/kernel/threads/thread_state.h + src/core/libraries/kernel/threads/thr_ctrdtr.cpp src/core/libraries/kernel/cpu_management.cpp src/core/libraries/kernel/cpu_management.h - src/core/libraries/kernel/event_queue.cpp - src/core/libraries/kernel/event_queue.h src/core/libraries/kernel/event_queues.cpp src/core/libraries/kernel/event_queues.h src/core/libraries/kernel/file_system.cpp src/core/libraries/kernel/file_system.h - src/core/libraries/kernel/libkernel.cpp - src/core/libraries/kernel/libkernel.h + src/core/libraries/kernel/kernel.cpp + src/core/libraries/kernel/kernel.h src/core/libraries/kernel/memory_management.cpp src/core/libraries/kernel/memory_management.h src/core/libraries/kernel/thread_management.cpp @@ -457,7 +459,10 @@ set(COMMON src/common/logging/backend.cpp src/common/signal_context.h src/common/signal_context.cpp src/common/singleton.h + src/common/slab_heap.h src/common/slot_vector.h + src/common/spin_lock.cpp + src/common/spin_lock.h src/common/string_util.cpp src/common/string_util.h src/common/thread.cpp @@ -816,14 +821,6 @@ else() src/emulator.h src/sdl_window.h src/sdl_window.cpp - src/core/libraries/kernel/threads/thr_stack.cpp - src/core/libraries/kernel/threads/thr_exit.cpp - src/core/libraries/kernel/threads/thr_clean.cpp - src/core/libraries/kernel/threads/thread_state.h src/core/libraries/kernel/threads/thread_state.cpp - src/core/libraries/kernel/threads/thr_ctrdtr.cpp - src/common/slab_heap.h - src/common/spin_lock.cpp - src/common/spin_lock.h ) endif() diff --git a/src/common/debug.h b/src/common/debug.h index 596ad7b84..091c6191d 100644 --- a/src/common/debug.h +++ b/src/common/debug.h @@ -41,7 +41,7 @@ enum MarkersPalette : int { #define RENDERER_TRACE ZoneScopedC(RendererMarkerColor) #define HLE_TRACE ZoneScopedC(HleMarkerColor) -#define TRACE_HINT(str) ZoneText(str.c_str(), str.size()) +#define TRACE_HINT(str) ZoneText(str.data(), str.size()) #define TRACE_WARN(msg) \ [](const auto& msg) { TracyMessageC(msg.c_str(), msg.size(), tracy::Color::DarkOrange); }(msg); diff --git a/src/core/libraries/audio3d/audio3d_impl.cpp b/src/core/libraries/audio3d/audio3d_impl.cpp index c267c096f..3069e8800 100644 --- a/src/core/libraries/audio3d/audio3d_impl.cpp +++ b/src/core/libraries/audio3d/audio3d_impl.cpp @@ -6,7 +6,7 @@ #include "common/logging/log.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" using namespace Libraries::Kernel; diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index c96fb4ec7..cd1e4de7d 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -1,6 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#pragma clang optimize off + #include "gnm_error.h" #include "gnmdriver.h" @@ -8,7 +8,6 @@ #include "common/config.h" #include "common/debug.h" #include "common/logging/log.h" -#include "common/path_util.h" #include "common/slot_vector.h" #include "core/address_space.h" #include "core/debug_state.h" diff --git a/src/core/libraries/kernel/event_flag/event_flag.h b/src/core/libraries/kernel/event_flag/event_flag.h deleted file mode 100644 index 2147e3f15..000000000 --- a/src/core/libraries/kernel/event_flag/event_flag.h +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/types.h" -#include "event_flag_codes.h" -#include "event_flag_obj.h" - -namespace Core::Loader { -class SymbolsResolver; -} - -namespace Libraries::Kernel { - -using OrbisKernelUseconds = u32; -using OrbisKernelEventFlag = EventFlagInternal*; - -struct OrbisKernelEventFlagOptParam { - size_t size; -}; - -int PS4_SYSV_ABI sceKernelCreateEventFlag(OrbisKernelEventFlag* ef, const char* pName, u32 attr, - u64 initPattern, - const OrbisKernelEventFlagOptParam* pOptParam); -int PS4_SYSV_ABI sceKernelDeleteEventFlag(OrbisKernelEventFlag ef); -int PS4_SYSV_ABI sceKernelOpenEventFlag(); -int PS4_SYSV_ABI sceKernelCloseEventFlag(); -int PS4_SYSV_ABI sceKernelClearEventFlag(OrbisKernelEventFlag ef, u64 bitPattern); -int PS4_SYSV_ABI sceKernelCancelEventFlag(OrbisKernelEventFlag ef, u64 setPattern, - int* pNumWaitThreads); -int PS4_SYSV_ABI sceKernelSetEventFlag(OrbisKernelEventFlag ef, u64 bitPattern); -int PS4_SYSV_ABI sceKernelPollEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, u32 waitMode, - u64* pResultPat); -int PS4_SYSV_ABI sceKernelWaitEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, u32 waitMode, - u64* pResultPat, OrbisKernelUseconds* pTimeout); - -void RegisterKernelEventFlag(Core::Loader::SymbolsResolver* sym); - -} // namespace Libraries::Kernel \ No newline at end of file diff --git a/src/core/libraries/kernel/event_flag/event_flag_codes.h b/src/core/libraries/kernel/event_flag/event_flag_codes.h deleted file mode 100644 index 92b265c8d..000000000 --- a/src/core/libraries/kernel/event_flag/event_flag_codes.h +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -constexpr int ORBIS_KERNEL_EVF_ATTR_TH_FIFO = 0x01; -constexpr int ORBIS_KERNEL_EVF_ATTR_TH_PRIO = 0x02; -constexpr int ORBIS_KERNEL_EVF_ATTR_SINGLE = 0x10; -constexpr int ORBIS_KERNEL_EVF_ATTR_MULTI = 0x20; - -constexpr int ORBIS_KERNEL_EVF_WAITMODE_AND = 0x01; -constexpr int ORBIS_KERNEL_EVF_WAITMODE_OR = 0x02; -constexpr int ORBIS_KERNEL_EVF_WAITMODE_CLEAR_ALL = 0x10; -constexpr int ORBIS_KERNEL_EVF_WAITMODE_CLEAR_PAT = 0x20; \ No newline at end of file diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.cpp b/src/core/libraries/kernel/event_flag/event_flag_obj.cpp deleted file mode 100644 index 6d6dcf7a9..000000000 --- a/src/core/libraries/kernel/event_flag/event_flag_obj.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include - -#include "core/libraries/error_codes.h" -#include "event_flag_obj.h" - -namespace Libraries::Kernel { -int EventFlagInternal::Wait(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result, - u32* ptr_micros) { - std::unique_lock lock{m_mutex}; - - uint32_t micros = 0; - bool infinitely = true; - if (ptr_micros != nullptr) { - micros = *ptr_micros; - infinitely = false; - } - - if (m_thread_mode == ThreadMode::Single && m_waiting_threads > 0) { - return ORBIS_KERNEL_ERROR_EPERM; - } - - auto const start = std::chrono::system_clock::now(); - m_waiting_threads++; - auto waitFunc = [this, wait_mode, bits] { - return (m_status == Status::Canceled || m_status == Status::Deleted || - (wait_mode == WaitMode::And && (m_bits & bits) == bits) || - (wait_mode == WaitMode::Or && (m_bits & bits) != 0)); - }; - - if (infinitely) { - m_cond_var.wait(lock, waitFunc); - } else { - if (!m_cond_var.wait_for(lock, std::chrono::microseconds(micros), waitFunc)) { - if (result != nullptr) { - *result = m_bits; - } - *ptr_micros = 0; - --m_waiting_threads; - return ORBIS_KERNEL_ERROR_ETIMEDOUT; - } - } - --m_waiting_threads; - if (result != nullptr) { - *result = m_bits; - } - - auto elapsed = std::chrono::duration_cast( - std::chrono::system_clock::now() - start) - .count(); - if (result != nullptr) { - *result = m_bits; - } - - if (ptr_micros != nullptr) { - *ptr_micros = (elapsed >= micros ? 0 : micros - elapsed); - } - - if (m_status == Status::Canceled) { - return ORBIS_KERNEL_ERROR_ECANCELED; - } else if (m_status == Status::Deleted) { - return ORBIS_KERNEL_ERROR_EACCES; - } - - if (clear_mode == ClearMode::All) { - m_bits = 0; - } else if (clear_mode == ClearMode::Bits) { - m_bits &= ~bits; - } - - return ORBIS_OK; -} - -int EventFlagInternal::Poll(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result) { - u32 micros = 0; - auto ret = Wait(bits, wait_mode, clear_mode, result, µs); - if (ret == ORBIS_KERNEL_ERROR_ETIMEDOUT) { - // Poll returns EBUSY instead. - ret = ORBIS_KERNEL_ERROR_EBUSY; - } - return ret; -} - -void EventFlagInternal::Set(u64 bits) { - std::unique_lock lock{m_mutex}; - - while (m_status != Status::Set) { - m_mutex.unlock(); - std::this_thread::sleep_for(std::chrono::microseconds(10)); - m_mutex.lock(); - } - - m_bits |= bits; - - m_cond_var.notify_all(); -} - -void EventFlagInternal::Clear(u64 bits) { - std::unique_lock lock{m_mutex}; - while (m_status != Status::Set) { - m_mutex.unlock(); - std::this_thread::sleep_for(std::chrono::microseconds(10)); - m_mutex.lock(); - } - - m_bits &= bits; -} - -} // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/event_flag/event_flag_obj.h b/src/core/libraries/kernel/event_flag/event_flag_obj.h deleted file mode 100644 index 8d1624e2b..000000000 --- a/src/core/libraries/kernel/event_flag/event_flag_obj.h +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include - -#include "common/types.h" - -namespace Libraries::Kernel { - -class EventFlagInternal { -public: - enum class ClearMode { None, All, Bits }; - - enum class WaitMode { And, Or }; - - enum class ThreadMode { Single, Multi }; - - enum class QueueMode { Fifo, ThreadPrio }; - - EventFlagInternal(const std::string& name, ThreadMode thread_mode, QueueMode queue_mode, - uint64_t bits) - : m_name(name), m_thread_mode(thread_mode), m_queue_mode(queue_mode), m_bits(bits){}; - - int Wait(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result, u32* ptr_micros); - int Poll(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result); - void Set(u64 bits); - void Clear(u64 bits); - -private: - enum class Status { Set, Canceled, Deleted }; - - std::mutex m_mutex; - std::condition_variable m_cond_var; - Status m_status = Status::Set; - int m_waiting_threads = 0; - std::string m_name; - ThreadMode m_thread_mode = ThreadMode::Single; - QueueMode m_queue_mode = QueueMode::Fifo; - u64 m_bits = 0; -}; -} // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/event_queue.cpp b/src/core/libraries/kernel/event_queue.cpp deleted file mode 100644 index 938718b80..000000000 --- a/src/core/libraries/kernel/event_queue.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#include - -#include "common/assert.h" -#include "core/libraries/kernel/event_queue.h" - -namespace Libraries::Kernel { - -EqueueInternal::~EqueueInternal() = default; - -bool EqueueInternal::AddEvent(EqueueEvent& event) { - std::scoped_lock lock{m_mutex}; - - event.time_added = std::chrono::steady_clock::now(); - - const auto& it = std::ranges::find(m_events, event); - if (it != m_events.cend()) { - *it = std::move(event); - } else { - m_events.emplace_back(std::move(event)); - } - - return true; -} - -bool EqueueInternal::RemoveEvent(u64 id) { - bool has_found = false; - std::scoped_lock lock{m_mutex}; - - const auto& it = - std::ranges::find_if(m_events, [id](auto& ev) { return ev.event.ident == id; }); - if (it != m_events.cend()) { - m_events.erase(it); - has_found = true; - } - return has_found; -} - -int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) { - int count = 0; - - const auto predicate = [&] { - count = GetTriggeredEvents(ev, num); - return count > 0; - }; - - if (micros == 0) { - std::unique_lock lock{m_mutex}; - m_cond.wait(lock, predicate); - } else { - std::unique_lock lock{m_mutex}; - m_cond.wait_for(lock, std::chrono::microseconds(micros), predicate); - } - - if (HasSmallTimer()) { - if (count > 0) { - const auto time_waited = std::chrono::duration_cast( - std::chrono::steady_clock::now() - m_events[0].time_added) - .count(); - count = WaitForSmallTimer(ev, num, std::max(0l, long(micros - time_waited))); - } - small_timer_event.event.data = 0; - } - - if (ev->flags & SceKernelEvent::Flags::OneShot) { - for (auto ev_id = 0u; ev_id < count; ++ev_id) { - RemoveEvent(ev->ident); - } - } - - return count; -} - -bool EqueueInternal::TriggerEvent(u64 ident, s16 filter, void* trigger_data) { - bool has_found = false; - { - std::scoped_lock lock{m_mutex}; - - for (auto& event : m_events) { - if ((event.event.ident == ident) && (event.event.filter == filter)) { - event.Trigger(trigger_data); - has_found = true; - } - } - } - m_cond.notify_one(); - return has_found; -} - -int EqueueInternal::GetTriggeredEvents(SceKernelEvent* ev, int num) { - int count = 0; - - for (auto& event : m_events) { - if (event.IsTriggered()) { - if (event.event.flags & SceKernelEvent::Flags::Clear) { - event.Reset(); - } - ev[count++] = event.event; - if (count == num) { - break; - } - } - } - - return count; -} - -bool EqueueInternal::AddSmallTimer(EqueueEvent& ev) { - // We assume that only one timer event (with the same ident across calls) - // can be posted to the queue, based on observations so far. In the opposite case, - // the small timer storage and wait logic should be reworked. - ASSERT(!HasSmallTimer() || small_timer_event.event.ident == ev.event.ident); - ev.time_added = std::chrono::steady_clock::now(); - small_timer_event = std::move(ev); - return true; -} - -int EqueueInternal::WaitForSmallTimer(SceKernelEvent* ev, int num, u32 micros) { - int count{}; - - ASSERT(num == 1); - - auto curr_clock = std::chrono::steady_clock::now(); - const auto wait_end_us = curr_clock + std::chrono::microseconds{micros}; - - do { - curr_clock = std::chrono::steady_clock::now(); - { - std::scoped_lock lock{m_mutex}; - if ((curr_clock - small_timer_event.time_added) > - std::chrono::microseconds{small_timer_event.event.data}) { - ev[count++] = small_timer_event.event; - small_timer_event.event.data = 0; - break; - } - } - std::this_thread::yield(); - } while (curr_clock < wait_end_us); - - return count; -} - -} // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/event_queue.h b/src/core/libraries/kernel/event_queue.h deleted file mode 100644 index f717f7318..000000000 --- a/src/core/libraries/kernel/event_queue.h +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include -#include -#include -#include -#include -#include "common/types.h" - -namespace Core::Loader { -class SymbolsResolver; -} - -namespace Libraries::Kernel { - -class EqueueInternal; -struct EqueueEvent; - -struct SceKernelEvent { - enum Filter : s16 { - None = 0, - Read = -1, - Write = -2, - Aio = -3, - Vnode = -4, - Proc = -5, - Signal = -6, - Timer = -7, - Fs = -9, - Lio = -10, - User = -11, - Polling = -12, - VideoOut = -13, - GraphicsCore = -14, - HrTimer = -15, - }; - - enum Flags : u16 { - Add = 1u, - Delete = 2u, - Enable = 4u, - Disable = 8u, - OneShot = 0x10u, - Clear = 0x20u, - Receipt = 0x40u, - Dispatch = 0x80u, - Flag1 = 0x2000u, - System = 0xf000u, - }; - - u64 ident = 0; /* identifier for this event */ - Filter filter = Filter::None; /* filter for event */ - u16 flags = 0; - u32 fflags = 0; - u64 data = 0; - void* udata = nullptr; /* opaque user data identifier */ -}; - -struct EqueueEvent { - SceKernelEvent event; - void* data = nullptr; - std::chrono::steady_clock::time_point time_added; - std::unique_ptr timer; - - void Reset() { - is_triggered = false; - event.fflags = 0; - event.data = 0; - } - - void Trigger(void* data) { - is_triggered = true; - event.fflags++; - event.data = reinterpret_cast(data); - } - - bool IsTriggered() const { - return is_triggered; - } - - bool operator==(const EqueueEvent& ev) const { - return ev.event.ident == event.ident; - } - -private: - bool is_triggered = false; -}; - -class EqueueInternal { -public: - EqueueInternal() = default; - virtual ~EqueueInternal(); - void setName(const std::string& m_name) { - this->m_name = m_name; - } - const auto& GetName() const { - return m_name; - } - bool AddEvent(EqueueEvent& event); - bool RemoveEvent(u64 id); - int WaitForEvents(SceKernelEvent* ev, int num, u32 micros); - bool TriggerEvent(u64 ident, s16 filter, void* trigger_data); - int GetTriggeredEvents(SceKernelEvent* ev, int num); - - bool AddSmallTimer(EqueueEvent& event); - bool HasSmallTimer() const { - return small_timer_event.event.data != 0; - } - int WaitForSmallTimer(SceKernelEvent* ev, int num, u32 micros); - -private: - std::string m_name; - std::mutex m_mutex; - std::vector m_events; - EqueueEvent small_timer_event{}; - std::condition_variable m_cond; -}; - -} // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/event_queues.cpp b/src/core/libraries/kernel/event_queues.cpp index f83e226f9..96344f8cd 100644 --- a/src/core/libraries/kernel/event_queues.cpp +++ b/src/core/libraries/kernel/event_queues.cpp @@ -10,6 +10,138 @@ namespace Libraries::Kernel { +bool EqueueInternal::AddEvent(EqueueEvent& event) { + std::scoped_lock lock{m_mutex}; + + event.time_added = std::chrono::steady_clock::now(); + + const auto& it = std::ranges::find(m_events, event); + if (it != m_events.cend()) { + *it = std::move(event); + } else { + m_events.emplace_back(std::move(event)); + } + + return true; +} + +bool EqueueInternal::RemoveEvent(u64 id) { + bool has_found = false; + std::scoped_lock lock{m_mutex}; + + const auto& it = + std::ranges::find_if(m_events, [id](auto& ev) { return ev.event.ident == id; }); + if (it != m_events.cend()) { + m_events.erase(it); + has_found = true; + } + return has_found; +} + +int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) { + int count = 0; + + const auto predicate = [&] { + count = GetTriggeredEvents(ev, num); + return count > 0; + }; + + if (micros == 0) { + std::unique_lock lock{m_mutex}; + m_cond.wait(lock, predicate); + } else { + std::unique_lock lock{m_mutex}; + m_cond.wait_for(lock, std::chrono::microseconds(micros), predicate); + } + + if (HasSmallTimer()) { + if (count > 0) { + const auto time_waited = std::chrono::duration_cast( + std::chrono::steady_clock::now() - m_events[0].time_added) + .count(); + count = WaitForSmallTimer(ev, num, std::max(0l, long(micros - time_waited))); + } + small_timer_event.event.data = 0; + } + + if (ev->flags & SceKernelEvent::Flags::OneShot) { + for (auto ev_id = 0u; ev_id < count; ++ev_id) { + RemoveEvent(ev->ident); + } + } + + return count; +} + +bool EqueueInternal::TriggerEvent(u64 ident, s16 filter, void* trigger_data) { + bool has_found = false; + { + std::scoped_lock lock{m_mutex}; + + for (auto& event : m_events) { + if ((event.event.ident == ident) && (event.event.filter == filter)) { + event.Trigger(trigger_data); + has_found = true; + } + } + } + m_cond.notify_one(); + return has_found; +} + +int EqueueInternal::GetTriggeredEvents(SceKernelEvent* ev, int num) { + int count = 0; + + for (auto& event : m_events) { + if (event.IsTriggered()) { + if (event.event.flags & SceKernelEvent::Flags::Clear) { + event.Reset(); + } + ev[count++] = event.event; + if (count == num) { + break; + } + } + } + + return count; +} + +bool EqueueInternal::AddSmallTimer(EqueueEvent& ev) { + // We assume that only one timer event (with the same ident across calls) + // can be posted to the queue, based on observations so far. In the opposite case, + // the small timer storage and wait logic should be reworked. + ASSERT(!HasSmallTimer() || small_timer_event.event.ident == ev.event.ident); + ev.time_added = std::chrono::steady_clock::now(); + small_timer_event = std::move(ev); + return true; +} + +int EqueueInternal::WaitForSmallTimer(SceKernelEvent* ev, int num, u32 micros) { + int count{}; + + ASSERT(num == 1); + + auto curr_clock = std::chrono::steady_clock::now(); + const auto wait_end_us = curr_clock + std::chrono::microseconds{micros}; + + do { + curr_clock = std::chrono::steady_clock::now(); + { + std::scoped_lock lock{m_mutex}; + if ((curr_clock - small_timer_event.time_added) > + std::chrono::microseconds{small_timer_event.event.data}) { + ev[count++] = small_timer_event.event; + small_timer_event.event.data = 0; + break; + } + } + std::this_thread::yield(); + } while (curr_clock < wait_end_us); + + return count; +} + extern boost::asio::io_context io_context; extern void KernelSignalRequest(); @@ -43,8 +175,7 @@ int PS4_SYSV_ABI sceKernelCreateEqueue(SceKernelEqueue* eq, const char* name) { LOG_INFO(Kernel_Event, "name = {}", name); - *eq = new EqueueInternal; - (*eq)->setName(std::string(name)); + *eq = new EqueueInternal(name); return ORBIS_OK; } diff --git a/src/core/libraries/kernel/event_queues.h b/src/core/libraries/kernel/event_queues.h index 690f4f9f6..5a13bdecd 100644 --- a/src/core/libraries/kernel/event_queues.h +++ b/src/core/libraries/kernel/event_queues.h @@ -3,7 +3,13 @@ #pragma once -#include "core/libraries/kernel/event_queue.h" +#include +#include +#include +#include +#include + +#include "common/types.h" namespace Core::Loader { class SymbolsResolver; @@ -11,22 +17,111 @@ class SymbolsResolver; namespace Libraries::Kernel { +class EqueueInternal; +struct EqueueEvent; + +struct SceKernelEvent { + enum Filter : s16 { + None = 0, + Read = -1, + Write = -2, + Aio = -3, + Vnode = -4, + Proc = -5, + Signal = -6, + Timer = -7, + Fs = -9, + Lio = -10, + User = -11, + Polling = -12, + VideoOut = -13, + GraphicsCore = -14, + HrTimer = -15, + }; + + enum Flags : u16 { + Add = 1u, + Delete = 2u, + Enable = 4u, + Disable = 8u, + OneShot = 0x10u, + Clear = 0x20u, + Receipt = 0x40u, + Dispatch = 0x80u, + Flag1 = 0x2000u, + System = 0xf000u, + }; + + u64 ident = 0; /* identifier for this event */ + Filter filter = Filter::None; /* filter for event */ + u16 flags = 0; + u32 fflags = 0; + u64 data = 0; + void* udata = nullptr; /* opaque user data identifier */ +}; + +struct EqueueEvent { + SceKernelEvent event; + void* data = nullptr; + std::chrono::steady_clock::time_point time_added; + std::unique_ptr timer; + + void Reset() { + is_triggered = false; + event.fflags = 0; + event.data = 0; + } + + void Trigger(void* data) { + is_triggered = true; + event.fflags++; + event.data = reinterpret_cast(data); + } + + bool IsTriggered() const { + return is_triggered; + } + + bool operator==(const EqueueEvent& ev) const { + return ev.event.ident == event.ident; + } + +private: + bool is_triggered = false; +}; + +class EqueueInternal { +public: + explicit EqueueInternal(std::string_view name) : m_name(name) {} + + std::string_view GetName() const { + return m_name; + } + + bool AddEvent(EqueueEvent& event); + bool RemoveEvent(u64 id); + int WaitForEvents(SceKernelEvent* ev, int num, u32 micros); + bool TriggerEvent(u64 ident, s16 filter, void* trigger_data); + int GetTriggeredEvents(SceKernelEvent* ev, int num); + + bool AddSmallTimer(EqueueEvent& event); + bool HasSmallTimer() const { + return small_timer_event.event.data != 0; + } + + int WaitForSmallTimer(SceKernelEvent* ev, int num, u32 micros); + +private: + std::string m_name; + std::mutex m_mutex; + std::vector m_events; + EqueueEvent small_timer_event{}; + std::condition_variable m_cond; +}; + using SceKernelUseconds = u32; using SceKernelEqueue = EqueueInternal*; -int PS4_SYSV_ABI sceKernelCreateEqueue(SceKernelEqueue* eq, const char* name); -int PS4_SYSV_ABI sceKernelDeleteEqueue(SceKernelEqueue eq); -int PS4_SYSV_ABI sceKernelWaitEqueue(SceKernelEqueue eq, SceKernelEvent* ev, int num, int* out, - SceKernelUseconds* timo); -void* PS4_SYSV_ABI sceKernelGetEventUserData(const SceKernelEvent* ev); -u64 PS4_SYSV_ABI sceKernelGetEventId(const SceKernelEvent* ev); -int PS4_SYSV_ABI sceKernelTriggerUserEvent(SceKernelEqueue eq, int id, void* udata); -int PS4_SYSV_ABI sceKernelDeleteUserEvent(SceKernelEqueue eq, int id); -int PS4_SYSV_ABI sceKernelAddUserEvent(SceKernelEqueue eq, int id); -int PS4_SYSV_ABI sceKernelAddUserEventEdge(SceKernelEqueue eq, int id); -s32 PS4_SYSV_ABI sceKernelAddHRTimerEvent(SceKernelEqueue eq, int id, timespec* ts, void* udata); -s16 PS4_SYSV_ABI sceKernelGetEventFilter(const SceKernelEvent* ev); - void RegisterEventQueue(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 3dd850adb..56286eb98 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -9,7 +9,7 @@ #include "core/libraries/error_codes.h" #include "core/libraries/kernel/file_system.h" #include "core/libraries/libs.h" -#include "libkernel.h" +#include "kernel.h" namespace Libraries::Kernel { diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/kernel.cpp similarity index 99% rename from src/core/libraries/kernel/libkernel.cpp rename to src/core/libraries/kernel/kernel.cpp index 9db42f326..764ef0e2f 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/kernel.cpp @@ -14,10 +14,10 @@ #include "core/file_sys/fs.h" #include "core/libraries/error_codes.h" #include "core/libraries/kernel/cpu_management.h" -#include "core/libraries/kernel/event_flag/event_flag.h" +#include "core/libraries/kernel/threads/event_flag.h" #include "core/libraries/kernel/event_queues.h" #include "core/libraries/kernel/file_system.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/memory_management.h" #include "core/libraries/kernel/thread_management.h" #include "core/libraries/kernel/time_management.h" diff --git a/src/core/libraries/kernel/libkernel.h b/src/core/libraries/kernel/kernel.h similarity index 100% rename from src/core/libraries/kernel/libkernel.h rename to src/core/libraries/kernel/kernel.h diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index c34ef45f6..c33e6ea04 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/thread_management.h" #include "core/libraries/kernel/threads/threads.h" diff --git a/src/core/libraries/kernel/event_flag/event_flag.cpp b/src/core/libraries/kernel/threads/event_flag.cpp similarity index 56% rename from src/core/libraries/kernel/event_flag/event_flag.cpp rename to src/core/libraries/kernel/threads/event_flag.cpp index f83ae0a7f..5b17a4104 100644 --- a/src/core/libraries/kernel/event_flag/event_flag.cpp +++ b/src/core/libraries/kernel/threads/event_flag.cpp @@ -1,13 +1,157 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include +#include + #include "common/assert.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" #include "core/libraries/libs.h" -#include "event_flag.h" namespace Libraries::Kernel { + +constexpr int ORBIS_KERNEL_EVF_ATTR_TH_FIFO = 0x01; +constexpr int ORBIS_KERNEL_EVF_ATTR_TH_PRIO = 0x02; +constexpr int ORBIS_KERNEL_EVF_ATTR_SINGLE = 0x10; +constexpr int ORBIS_KERNEL_EVF_ATTR_MULTI = 0x20; + +constexpr int ORBIS_KERNEL_EVF_WAITMODE_AND = 0x01; +constexpr int ORBIS_KERNEL_EVF_WAITMODE_OR = 0x02; +constexpr int ORBIS_KERNEL_EVF_WAITMODE_CLEAR_ALL = 0x10; +constexpr int ORBIS_KERNEL_EVF_WAITMODE_CLEAR_PAT = 0x20; + +class EventFlagInternal { +public: + enum class ClearMode { None, All, Bits }; + enum class WaitMode { And, Or }; + enum class ThreadMode { Single, Multi }; + enum class QueueMode { Fifo, ThreadPrio }; + + EventFlagInternal(const std::string& name, ThreadMode thread_mode, QueueMode queue_mode, + uint64_t bits) + : m_name(name), m_thread_mode(thread_mode), m_queue_mode(queue_mode), m_bits(bits){}; + + int Wait(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result, u32* ptr_micros) { + std::unique_lock lock{m_mutex}; + + uint32_t micros = 0; + bool infinitely = true; + if (ptr_micros != nullptr) { + micros = *ptr_micros; + infinitely = false; + } + + if (m_thread_mode == ThreadMode::Single && m_waiting_threads > 0) { + return ORBIS_KERNEL_ERROR_EPERM; + } + + auto const start = std::chrono::system_clock::now(); + m_waiting_threads++; + auto waitFunc = [this, wait_mode, bits] { + return (m_status == Status::Canceled || m_status == Status::Deleted || + (wait_mode == WaitMode::And && (m_bits & bits) == bits) || + (wait_mode == WaitMode::Or && (m_bits & bits) != 0)); + }; + + if (infinitely) { + m_cond_var.wait(lock, waitFunc); + } else { + if (!m_cond_var.wait_for(lock, std::chrono::microseconds(micros), waitFunc)) { + if (result != nullptr) { + *result = m_bits; + } + *ptr_micros = 0; + --m_waiting_threads; + return ORBIS_KERNEL_ERROR_ETIMEDOUT; + } + } + --m_waiting_threads; + if (result != nullptr) { + *result = m_bits; + } + + auto elapsed = std::chrono::duration_cast( + std::chrono::system_clock::now() - start) + .count(); + if (result != nullptr) { + *result = m_bits; + } + + if (ptr_micros != nullptr) { + *ptr_micros = (elapsed >= micros ? 0 : micros - elapsed); + } + + if (m_status == Status::Canceled) { + return ORBIS_KERNEL_ERROR_ECANCELED; + } else if (m_status == Status::Deleted) { + return ORBIS_KERNEL_ERROR_EACCES; + } + + if (clear_mode == ClearMode::All) { + m_bits = 0; + } else if (clear_mode == ClearMode::Bits) { + m_bits &= ~bits; + } + + return ORBIS_OK; + } + + int Poll(u64 bits, WaitMode wait_mode, ClearMode clear_mode, u64* result) { + u32 micros = 0; + auto ret = Wait(bits, wait_mode, clear_mode, result, µs); + if (ret == ORBIS_KERNEL_ERROR_ETIMEDOUT) { + // Poll returns EBUSY instead. + ret = ORBIS_KERNEL_ERROR_EBUSY; + } + return ret; + } + + void Set(u64 bits) { + std::unique_lock lock{m_mutex}; + + while (m_status != Status::Set) { + m_mutex.unlock(); + std::this_thread::sleep_for(std::chrono::microseconds(10)); + m_mutex.lock(); + } + + m_bits |= bits; + + m_cond_var.notify_all(); + } + + void Clear(u64 bits) { + std::unique_lock lock{m_mutex}; + while (m_status != Status::Set) { + m_mutex.unlock(); + std::this_thread::sleep_for(std::chrono::microseconds(10)); + m_mutex.lock(); + } + + m_bits &= bits; + } + +private: + enum class Status { Set, Canceled, Deleted }; + + std::mutex m_mutex; + std::condition_variable m_cond_var; + Status m_status = Status::Set; + int m_waiting_threads = 0; + std::string m_name; + ThreadMode m_thread_mode = ThreadMode::Single; + QueueMode m_queue_mode = QueueMode::Fifo; + u64 m_bits = 0; +}; + +using OrbisKernelUseconds = u32; +using OrbisKernelEventFlag = EventFlagInternal*; + +struct OrbisKernelEventFlagOptParam { + size_t size; +}; + int PS4_SYSV_ABI sceKernelCreateEventFlag(OrbisKernelEventFlag* ef, const char* pName, u32 attr, u64 initPattern, const OrbisKernelEventFlagOptParam* pOptParam) { @@ -25,9 +169,8 @@ int PS4_SYSV_ABI sceKernelCreateEventFlag(OrbisKernelEventFlag* ef, const char* return ORBIS_KERNEL_ERROR_ENAMETOOLONG; } - EventFlagInternal::ThreadMode thread_mode = EventFlagInternal::ThreadMode::Single; - EventFlagInternal::QueueMode queue_mode = EventFlagInternal::QueueMode::Fifo; - + auto thread_mode = EventFlagInternal::ThreadMode::Single; + auto queue_mode = EventFlagInternal::QueueMode::Fifo; switch (attr & 0xfu) { case 0x01: queue_mode = EventFlagInternal::QueueMode::Fifo; @@ -61,6 +204,7 @@ int PS4_SYSV_ABI sceKernelCreateEventFlag(OrbisKernelEventFlag* ef, const char* *ef = new EventFlagInternal(std::string(pName), thread_mode, queue_mode, initPattern); return ORBIS_OK; } + int PS4_SYSV_ABI sceKernelDeleteEventFlag(OrbisKernelEventFlag ef) { if (ef == nullptr) { return ORBIS_KERNEL_ERROR_ESRCH; @@ -69,24 +213,29 @@ int PS4_SYSV_ABI sceKernelDeleteEventFlag(OrbisKernelEventFlag ef) { delete ef; return ORBIS_OK; } + int PS4_SYSV_ABI sceKernelOpenEventFlag() { LOG_ERROR(Kernel_Event, "(STUBBED) called"); return ORBIS_OK; } + int PS4_SYSV_ABI sceKernelCloseEventFlag() { LOG_ERROR(Kernel_Event, "(STUBBED) called"); return ORBIS_OK; } + int PS4_SYSV_ABI sceKernelClearEventFlag(OrbisKernelEventFlag ef, u64 bitPattern) { LOG_DEBUG(Kernel_Event, "called"); ef->Clear(bitPattern); return ORBIS_OK; } + int PS4_SYSV_ABI sceKernelCancelEventFlag(OrbisKernelEventFlag ef, u64 setPattern, int* pNumWaitThreads) { LOG_ERROR(Kernel_Event, "(STUBBED) called"); return ORBIS_OK; } + int PS4_SYSV_ABI sceKernelSetEventFlag(OrbisKernelEventFlag ef, u64 bitPattern) { LOG_TRACE(Kernel_Event, "called"); if (ef == nullptr) { @@ -95,6 +244,7 @@ int PS4_SYSV_ABI sceKernelSetEventFlag(OrbisKernelEventFlag ef, u64 bitPattern) ef->Set(bitPattern); return ORBIS_OK; } + int PS4_SYSV_ABI sceKernelPollEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, u32 waitMode, u64* pResultPat) { LOG_DEBUG(Kernel_Event, "called bitPattern = {:#x} waitMode = {:#x}", bitPattern, waitMode); @@ -107,9 +257,8 @@ int PS4_SYSV_ABI sceKernelPollEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, return ORBIS_KERNEL_ERROR_EINVAL; } - EventFlagInternal::WaitMode wait = EventFlagInternal::WaitMode::And; - EventFlagInternal::ClearMode clear = EventFlagInternal::ClearMode::None; - + auto wait = EventFlagInternal::WaitMode::And; + auto clear = EventFlagInternal::ClearMode::None; switch (waitMode & 0xf) { case 0x01: wait = EventFlagInternal::WaitMode::And; @@ -154,9 +303,8 @@ int PS4_SYSV_ABI sceKernelWaitEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, return ORBIS_KERNEL_ERROR_EINVAL; } - EventFlagInternal::WaitMode wait = EventFlagInternal::WaitMode::And; - EventFlagInternal::ClearMode clear = EventFlagInternal::ClearMode::None; - + auto wait = EventFlagInternal::WaitMode::And; + auto clear = EventFlagInternal::ClearMode::None; switch (waitMode & 0xf) { case 0x01: wait = EventFlagInternal::WaitMode::And; @@ -190,6 +338,7 @@ int PS4_SYSV_ABI sceKernelWaitEventFlag(OrbisKernelEventFlag ef, u64 bitPattern, return result; } + void RegisterKernelEventFlag(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("PZku4ZrXJqg", "libkernel", 1, "libkernel", 1, 1, sceKernelCancelEventFlag); LIB_FUNCTION("7uhBFWRAS60", "libkernel", 1, "libkernel", 1, 1, sceKernelClearEventFlag); @@ -201,4 +350,5 @@ void RegisterKernelEventFlag(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("IOnSvHzqu6A", "libkernel", 1, "libkernel", 1, 1, sceKernelSetEventFlag); LIB_FUNCTION("JTvBflhYazQ", "libkernel", 1, "libkernel", 1, 1, sceKernelWaitEventFlag); } + } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/threads/event_flag.h b/src/core/libraries/kernel/threads/event_flag.h new file mode 100644 index 000000000..8efbb93fe --- /dev/null +++ b/src/core/libraries/kernel/threads/event_flag.h @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::Kernel { + +void RegisterKernelEventFlag(Core::Loader::SymbolsResolver* sym); + +} // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/threads/thr_attr.cpp b/src/core/libraries/kernel/threads/thr_attr.cpp index c34b8a595..d9f073bab 100644 --- a/src/core/libraries/kernel/threads/thr_attr.cpp +++ b/src/core/libraries/kernel/threads/thr_attr.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma clang optimize off #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/threads/thread_state.h" #include "core/libraries/kernel/threads/threads.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/kernel/threads/thr_cond.cpp b/src/core/libraries/kernel/threads/thr_cond.cpp index f346d2cda..eeedf85f5 100644 --- a/src/core/libraries/kernel/threads/thr_cond.cpp +++ b/src/core/libraries/kernel/threads/thr_cond.cpp @@ -4,7 +4,7 @@ #include #include "common/assert.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/threads/threads.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/kernel/threads/thr_create.cpp b/src/core/libraries/kernel/threads/thr_create.cpp index 845a4b53b..1ef6a7c19 100644 --- a/src/core/libraries/kernel/threads/thr_create.cpp +++ b/src/core/libraries/kernel/threads/thr_create.cpp @@ -5,7 +5,7 @@ #include "common/thread.h" #include "core/debug_state.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/threads/thread_state.h" #include "core/libraries/kernel/threads/threads.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/kernel/threads/thr_mutex.cpp b/src/core/libraries/kernel/threads/thr_mutex.cpp index e12e6ab08..6d2af0c47 100644 --- a/src/core/libraries/kernel/threads/thr_mutex.cpp +++ b/src/core/libraries/kernel/threads/thr_mutex.cpp @@ -5,7 +5,7 @@ #include "common/scope_exit.h" #include "common/types.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/threads/threads.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/kernel/threads/thr_rwlock.cpp b/src/core/libraries/kernel/threads/thr_rwlock.cpp index 5deda72b6..1fca4d9c8 100644 --- a/src/core/libraries/kernel/threads/thr_rwlock.cpp +++ b/src/core/libraries/kernel/threads/thr_rwlock.cpp @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/threads/threads.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/kernel/threads/thr_sem.cpp b/src/core/libraries/kernel/threads/thr_sem.cpp index 6ff26db3e..5c3a8394b 100644 --- a/src/core/libraries/kernel/threads/thr_sem.cpp +++ b/src/core/libraries/kernel/threads/thr_sem.cpp @@ -7,7 +7,7 @@ #include "common/assert.h" #include "common/logging/log.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/time_management.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/kernel/threads/thr_spec.cpp b/src/core/libraries/kernel/threads/thr_spec.cpp index ab000c1b6..487306ad7 100644 --- a/src/core/libraries/kernel/threads/thr_spec.cpp +++ b/src/core/libraries/kernel/threads/thr_spec.cpp @@ -3,7 +3,7 @@ #include "common/assert.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" #include "core/libraries/kernel/threads/threads.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 5816b7872..537862a6c 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -14,7 +14,7 @@ #include "core/libraries/ime/error_dialog.h" #include "core/libraries/ime/ime.h" #include "core/libraries/ime/ime_dialog.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" #include "core/libraries/libc_internal/libc_internal.h" #include "core/libraries/libpng/pngdec.h" #include "core/libraries/libs.h" diff --git a/src/core/libraries/ngs2/ngs2_impl.cpp b/src/core/libraries/ngs2/ngs2_impl.cpp index 793435d83..b358a05f7 100644 --- a/src/core/libraries/ngs2/ngs2_impl.cpp +++ b/src/core/libraries/ngs2/ngs2_impl.cpp @@ -6,7 +6,7 @@ #include "common/logging/log.h" #include "core/libraries/error_codes.h" -#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/kernel.h" using namespace Libraries::Kernel;