mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 20:40:15 +00:00
Implement Event signaling delay
This commit is contained in:
parent
cc7f1155a8
commit
e8cc3c816c
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user