kernel: event_queue: initial `sceKernelAddHRTimerEvent` added
This commit is contained in:
parent
a5d22b8151
commit
53dd407ae3
|
@ -8,15 +8,19 @@ namespace Libraries::Kernel {
|
||||||
|
|
||||||
EqueueInternal::~EqueueInternal() = default;
|
EqueueInternal::~EqueueInternal() = default;
|
||||||
|
|
||||||
int EqueueInternal::addEvent(const EqueueEvent& event) {
|
int EqueueInternal::addEvent(EqueueEvent& event) {
|
||||||
std::scoped_lock lock{m_mutex};
|
std::scoped_lock lock{m_mutex};
|
||||||
|
|
||||||
ASSERT(!event.IsTriggered());
|
const auto start_clock = std::chrono::high_resolution_clock::now();
|
||||||
|
event.filter.added_time_us =
|
||||||
|
std::chrono::time_point_cast<std::chrono::microseconds>(start_clock);
|
||||||
|
|
||||||
const auto& it = std::ranges::find(m_events, event);
|
const auto& it = std::ranges::find(m_events, event);
|
||||||
ASSERT(it == m_events.cend()); // TODO: update event if found
|
if (it != m_events.cend()) {
|
||||||
|
*it = event;
|
||||||
|
} else {
|
||||||
m_events.push_back(event);
|
m_events.push_back(event);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ struct SceKernelEvent {
|
||||||
|
|
||||||
struct Filter {
|
struct Filter {
|
||||||
void* data = nullptr;
|
void* data = nullptr;
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock, std::chrono::microseconds> added_time_us;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EqueueEvent {
|
struct EqueueEvent {
|
||||||
|
@ -89,6 +90,15 @@ struct EqueueEvent {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsTriggered() const {
|
bool IsTriggered() const {
|
||||||
|
if (event.filter == Kernel::EVFILT_HRTIMER) {
|
||||||
|
// For HR timers we don't want to waste time on spawning waiters. Instead, we will check
|
||||||
|
// for time out condition every time caller fetches the event status.
|
||||||
|
const auto now_clock = std::chrono::high_resolution_clock::now();
|
||||||
|
const auto now_time_us =
|
||||||
|
std::chrono::time_point_cast<std::chrono::microseconds>(now_clock);
|
||||||
|
const auto delta = (now_time_us - filter.added_time_us).count();
|
||||||
|
return (s64(event.data) - delta) <= 0;
|
||||||
|
}
|
||||||
return is_triggered;
|
return is_triggered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,6 +113,28 @@ int PS4_SYSV_ABI sceKernelAddUserEventEdge(SceKernelEqueue eq, int id) {
|
||||||
return eq->addEvent(event);
|
return eq->addEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceKernelAddHRTimerEvent(SceKernelEqueue eq, int id, timespec* ts, void* udata) {
|
||||||
|
if (eq == nullptr) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ts->tv_sec > 100 || ts->tv_nsec < 100'000) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
ASSERT(ts->tv_nsec > 1000); // assume 1us granularity
|
||||||
|
const auto total_us = ts->tv_sec * 1000'000 + ts->tv_nsec / 1000;
|
||||||
|
|
||||||
|
Kernel::EqueueEvent event{};
|
||||||
|
event.event.ident = id;
|
||||||
|
event.event.filter = Kernel::EVFILT_HRTIMER;
|
||||||
|
event.event.flags = 0x11;
|
||||||
|
event.event.fflags = 0;
|
||||||
|
event.event.data = total_us;
|
||||||
|
event.event.udata = udata;
|
||||||
|
|
||||||
|
return eq->addEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
void* PS4_SYSV_ABI sceKernelGetEventUserData(const SceKernelEvent* ev) {
|
void* PS4_SYSV_ABI sceKernelGetEventUserData(const SceKernelEvent* ev) {
|
||||||
if (!ev) {
|
if (!ev) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -19,5 +19,6 @@ int PS4_SYSV_ABI sceKernelTriggerUserEvent(SceKernelEqueue eq, int id, void* uda
|
||||||
int PS4_SYSV_ABI sceKernelDeleteUserEvent(SceKernelEqueue eq, int id);
|
int PS4_SYSV_ABI sceKernelDeleteUserEvent(SceKernelEqueue eq, int id);
|
||||||
int PS4_SYSV_ABI sceKernelAddUserEvent(SceKernelEqueue eq, int id);
|
int PS4_SYSV_ABI sceKernelAddUserEvent(SceKernelEqueue eq, int id);
|
||||||
int PS4_SYSV_ABI sceKernelAddUserEventEdge(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);
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
|
|
@ -324,6 +324,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("vz+pg2zdopI", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventUserData);
|
LIB_FUNCTION("vz+pg2zdopI", "libkernel", 1, "libkernel", 1, 1, sceKernelGetEventUserData);
|
||||||
LIB_FUNCTION("4R6-OvI2cEA", "libkernel", 1, "libkernel", 1, 1, sceKernelAddUserEvent);
|
LIB_FUNCTION("4R6-OvI2cEA", "libkernel", 1, "libkernel", 1, 1, sceKernelAddUserEvent);
|
||||||
LIB_FUNCTION("WDszmSbWuDk", "libkernel", 1, "libkernel", 1, 1, sceKernelAddUserEventEdge);
|
LIB_FUNCTION("WDszmSbWuDk", "libkernel", 1, "libkernel", 1, 1, sceKernelAddUserEventEdge);
|
||||||
|
LIB_FUNCTION("R74tt43xP6k", "libkernel", 1, "libkernel", 1, 1, sceKernelAddHRTimerEvent);
|
||||||
LIB_FUNCTION("F6e0kwo4cnk", "libkernel", 1, "libkernel", 1, 1, sceKernelTriggerUserEvent);
|
LIB_FUNCTION("F6e0kwo4cnk", "libkernel", 1, "libkernel", 1, 1, sceKernelTriggerUserEvent);
|
||||||
LIB_FUNCTION("LJDwdSNTnDg", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteUserEvent);
|
LIB_FUNCTION("LJDwdSNTnDg", "libkernel", 1, "libkernel", 1, 1, sceKernelDeleteUserEvent);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue