Implement Event signaling delay

This commit is contained in:
mailwl 2016-10-11 11:01:47 +03:00
parent cc7f1155a8
commit e8cc3c816c
4 changed files with 65 additions and 2 deletions

View File

@ -3,15 +3,23 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <algorithm> #include <algorithm>
#include <cinttypes>
#include <map> #include <map>
#include <vector> #include <vector>
#include "common/assert.h" #include "common/assert.h"
#include "core/core_timing.h"
#include "core/hle/kernel/event.h" #include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/thread.h" #include "core/hle/kernel/thread.h"
namespace Kernel { namespace Kernel {
/// The event type of the generic event callback
static int event_callback_event_type;
// TODO(yuriks): This can be removed if Event objects are explicitly pooled in the future, allowing
// us to simply use a pool index or similar.
static Kernel::HandleTable event_callback_handle_table;
Event::Event() {} Event::Event() {}
Event::~Event() {} Event::~Event() {}
@ -21,6 +29,7 @@ SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {
evt->signaled = false; evt->signaled = false;
evt->reset_type = reset_type; evt->reset_type = reset_type;
evt->name = std::move(name); evt->name = std::move(name);
evt->callback_handle = event_callback_handle_table.Create(evt).MoveFrom();
return evt; return evt;
} }
@ -37,6 +46,16 @@ void Event::Acquire() {
signaled = false; signaled = false;
} }
void Event::Delay(u64 delay) {
// Ensure we get rid of any previous scheduled event
Cancel();
u64 microseconds = delay / 1000;
CoreTiming::ScheduleEvent(usToCycles(microseconds), event_callback_event_type, callback_handle);
HLE::Reschedule(__func__);
}
void Event::Signal() { void Event::Signal() {
signaled = true; signaled = true;
WakeupAllWaitingThreads(); WakeupAllWaitingThreads();
@ -46,4 +65,35 @@ void Event::Clear() {
signaled = false; signaled = false;
} }
void Event::Cancel() {
CoreTiming::UnscheduleEvent(event_callback_event_type, callback_handle);
HLE::Reschedule(__func__);
}
/// The event callback event
static void EventCallback(u64 event_handle, int /*cycles_late*/) {
SharedPtr<Event> event =
event_callback_handle_table.Get<Event>(static_cast<Handle>(event_handle));
if (event == nullptr) {
LOG_CRITICAL(Kernel, "Callback fired for invalid event %08" PRIx64, event_handle);
return;
}
LOG_TRACE(Kernel, "Event %08" PRIx64 " signaled", event_handle);
event->signaled = true;
// Resume all waiting threads
event->WakeupAllWaitingThreads();
}
void EventsInit() {
event_callback_handle_table.Clear();
event_callback_event_type = CoreTiming::RegisterEvent("EventCallback", EventCallback);
}
void EventsShutdown() {}
} // namespace } // namespace

View File

@ -38,12 +38,22 @@ public:
bool ShouldWait() override; bool ShouldWait() override;
void Acquire() override; void Acquire() override;
void Delay(u64 delay);
void Signal(); void Signal();
void Clear(); void Clear();
void Cancel();
private: private:
Event(); Event();
~Event() override; ~Event() override;
/// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
Handle callback_handle;
}; };
/// Initializes the required variables for events
void EventsInit();
/// Tears down the event variables
void EventsShutdown();
} // namespace } // namespace

View File

@ -6,6 +6,7 @@
#include "common/assert.h" #include "common/assert.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/hle/config_mem.h" #include "core/hle/config_mem.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/memory.h" #include "core/hle/kernel/memory.h"
#include "core/hle/kernel/process.h" #include "core/hle/kernel/process.h"
@ -135,6 +136,7 @@ void Init() {
Kernel::ResourceLimitsInit(); Kernel::ResourceLimitsInit();
Kernel::ThreadingInit(); Kernel::ThreadingInit();
Kernel::TimersInit(); Kernel::TimersInit();
Kernel::EventsInit();
Object::next_object_id = 0; Object::next_object_id = 0;
// TODO(Subv): Start the process ids from 10 for now, as lower PIDs are // TODO(Subv): Start the process ids from 10 for now, as lower PIDs are
@ -149,6 +151,7 @@ void Shutdown() {
Kernel::ThreadingShutdown(); Kernel::ThreadingShutdown();
g_current_process = nullptr; g_current_process = nullptr;
Kernel::EventsShutdown();
Kernel::TimersShutdown(); Kernel::TimersShutdown();
Kernel::ResourceLimitsShutdown(); Kernel::ResourceLimitsShutdown();
Kernel::MemoryShutdown(); Kernel::MemoryShutdown();

View File

@ -247,7 +247,7 @@ static void SetTransferEndInterrupt(Service::Interface* self) {
cmd_buff[0] = IPC::MakeHeader(0xD, 1, 0); cmd_buff[0] = IPC::MakeHeader(0xD, 1, 0);
cmd_buff[1] = RESULT_SUCCESS.raw; cmd_buff[1] = RESULT_SUCCESS.raw;
LOG_WARNING(Service_Y2R, "(STUBBED) called"); LOG_WARNING(Service_Y2R, "(STUBBED) called, enabled = %u", transfer_end_interrupt_enabled);
} }
/** /**
@ -591,7 +591,7 @@ static void StartConversion(Service::Interface* self) {
HW::Y2R::PerformConversion(conversion); HW::Y2R::PerformConversion(conversion);
completion_event->Signal(); completion_event->Delay(1000);
cmd_buff[0] = IPC::MakeHeader(0x26, 1, 0); cmd_buff[0] = IPC::MakeHeader(0x26, 1, 0);
cmd_buff[1] = RESULT_SUCCESS.raw; cmd_buff[1] = RESULT_SUCCESS.raw;