mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-03 07:36:20 +00:00
kernel: File cleanup pt1
This commit is contained in:
parent
d0d8b5eee5
commit
77ff4290d6
27 changed files with 445 additions and 535 deletions
|
@ -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()
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
|
@ -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;
|
|
@ -1,111 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <thread>
|
||||
|
||||
#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::microseconds>(
|
||||
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
|
|
@ -1,44 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
#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
|
|
@ -1,145 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <thread>
|
||||
|
||||
#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::microseconds>(
|
||||
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
|
|
@ -1,122 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#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<boost::asio::steady_timer> 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<uintptr_t>(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<EqueueEvent> m_events;
|
||||
EqueueEvent small_timer_event{};
|
||||
std::condition_variable m_cond;
|
||||
};
|
||||
|
||||
} // namespace Libraries::Kernel
|
|
@ -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::microseconds>(
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "core/libraries/kernel/event_queue.h"
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#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<boost::asio::steady_timer> 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<uintptr_t>(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<EqueueEvent> 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
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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"
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -1,13 +1,157 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
#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::microseconds>(
|
||||
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
|
14
src/core/libraries/kernel/threads/event_flag.h
Normal file
14
src/core/libraries/kernel/threads/event_flag.h
Normal file
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <cstring>
|
||||
#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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue