Core: Correct HLE Event Callbacks and other issues.
This commit is contained in:
parent
de5b521c09
commit
75e10578f1
|
@ -21,8 +21,8 @@
|
||||||
#include "core/hle/kernel/object.h"
|
#include "core/hle/kernel/object.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/readable_event.h"
|
#include "core/hle/kernel/readable_event.h"
|
||||||
#include "core/hle/kernel/server_session.h"
|
|
||||||
#include "core/hle/kernel/scheduler.h"
|
#include "core/hle/kernel/scheduler.h"
|
||||||
|
#include "core/hle/kernel/server_session.h"
|
||||||
#include "core/hle/kernel/thread.h"
|
#include "core/hle/kernel/thread.h"
|
||||||
#include "core/hle/kernel/time_manager.h"
|
#include "core/hle/kernel/time_manager.h"
|
||||||
#include "core/hle/kernel/writable_event.h"
|
#include "core/hle/kernel/writable_event.h"
|
||||||
|
@ -49,14 +49,6 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
|
||||||
const std::string& reason, u64 timeout, WakeupCallback&& callback,
|
const std::string& reason, u64 timeout, WakeupCallback&& callback,
|
||||||
std::shared_ptr<WritableEvent> writable_event) {
|
std::shared_ptr<WritableEvent> writable_event) {
|
||||||
// Put the client thread to sleep until the wait event is signaled or the timeout expires.
|
// Put the client thread to sleep until the wait event is signaled or the timeout expires.
|
||||||
thread->SetHLECallback(
|
|
||||||
[context = *this, callback](ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
|
||||||
std::shared_ptr<SynchronizationObject> object,
|
|
||||||
std::size_t index) mutable -> bool {
|
|
||||||
callback(thread, context, reason);
|
|
||||||
context.WriteToOutgoingCommandBuffer(*thread);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!writable_event) {
|
if (!writable_event) {
|
||||||
// Create event if not provided
|
// Create event if not provided
|
||||||
|
@ -67,6 +59,15 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread(
|
||||||
{
|
{
|
||||||
Handle event_handle = InvalidHandle;
|
Handle event_handle = InvalidHandle;
|
||||||
SchedulerLockAndSleep lock(kernel, event_handle, thread.get(), timeout);
|
SchedulerLockAndSleep lock(kernel, event_handle, thread.get(), timeout);
|
||||||
|
thread->SetHLECallback(
|
||||||
|
[context = *this, callback](std::shared_ptr<Thread> thread) mutable -> bool {
|
||||||
|
ThreadWakeupReason reason = thread->GetSignalingResult() == RESULT_TIMEOUT
|
||||||
|
? ThreadWakeupReason::Timeout
|
||||||
|
: ThreadWakeupReason::Signal;
|
||||||
|
callback(thread, context, reason);
|
||||||
|
context.WriteToOutgoingCommandBuffer(*thread);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
const auto readable_event{writable_event->GetReadableEvent()};
|
const auto readable_event{writable_event->GetReadableEvent()};
|
||||||
writable_event->Clear();
|
writable_event->Clear();
|
||||||
thread->SetStatus(ThreadStatus::WaitHLEEvent);
|
thread->SetStatus(ThreadStatus::WaitHLEEvent);
|
||||||
|
|
|
@ -333,17 +333,16 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
||||||
thread->SetStatus(ThreadStatus::WaitIPC);
|
thread->SetStatus(ThreadStatus::WaitIPC);
|
||||||
session->SendSyncRequest(SharedFrom(thread), system.Memory());
|
session->SendSyncRequest(SharedFrom(thread), system.Memory());
|
||||||
}
|
}
|
||||||
ResultCode result = thread->GetSignalingResult();
|
|
||||||
if (thread->HasHLECallback()) {
|
if (thread->HasHLECallback()) {
|
||||||
Handle event_handle = thread->GetHLETimeEvent();
|
Handle event_handle = thread->GetHLETimeEvent();
|
||||||
if (event_handle != InvalidHandle) {
|
if (event_handle != InvalidHandle) {
|
||||||
auto& time_manager = system.Kernel().TimeManager();
|
auto& time_manager = system.Kernel().TimeManager();
|
||||||
time_manager.UnscheduleTimeEvent(event_handle);
|
time_manager.UnscheduleTimeEvent(event_handle);
|
||||||
}
|
}
|
||||||
thread->InvokeHLECallback(ThreadWakeupReason::Timeout, SharedFrom(thread), nullptr, 0);
|
thread->InvokeHLECallback(SharedFrom(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
|
static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ void Synchronization::SignalObject(SynchronizationObject& obj) const {
|
||||||
time_manager.CancelTimeEvent(thread.get());
|
time_manager.CancelTimeEvent(thread.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
obj.ClearWaitingThreads();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,13 +47,13 @@ Thread::Thread(KernelCore& kernel) : SynchronizationObject{kernel} {}
|
||||||
Thread::~Thread() = default;
|
Thread::~Thread() = default;
|
||||||
|
|
||||||
void Thread::Stop() {
|
void Thread::Stop() {
|
||||||
|
{
|
||||||
SchedulerLock lock(kernel);
|
SchedulerLock lock(kernel);
|
||||||
// Cancel any outstanding wakeup events for this thread
|
// Cancel any outstanding wakeup events for this thread
|
||||||
Signal();
|
Signal();
|
||||||
Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(),
|
Core::System::GetInstance().CoreTiming().UnscheduleEvent(
|
||||||
global_handle);
|
kernel.ThreadWakeupCallbackEventType(), global_handle);
|
||||||
kernel.GlobalHandleTable().Close(global_handle);
|
kernel.GlobalHandleTable().Close(global_handle);
|
||||||
global_handle = 0;
|
|
||||||
SetStatus(ThreadStatus::Dead);
|
SetStatus(ThreadStatus::Dead);
|
||||||
|
|
||||||
owner_process->UnregisterThread(this);
|
owner_process->UnregisterThread(this);
|
||||||
|
@ -61,6 +61,8 @@ void Thread::Stop() {
|
||||||
// Mark the TLS slot in the thread's page as free.
|
// Mark the TLS slot in the thread's page as free.
|
||||||
owner_process->FreeTLSRegion(tls_address);
|
owner_process->FreeTLSRegion(tls_address);
|
||||||
}
|
}
|
||||||
|
global_handle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Thread::WakeAfterDelay(s64 nanoseconds) {
|
void Thread::WakeAfterDelay(s64 nanoseconds) {
|
||||||
// Don't schedule a wakeup if the thread wants to wait forever
|
// Don't schedule a wakeup if the thread wants to wait forever
|
||||||
|
@ -112,8 +114,6 @@ void Thread::ResumeFromWait() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hle_callback = nullptr;
|
|
||||||
|
|
||||||
if (activity == ThreadActivity::Paused) {
|
if (activity == ThreadActivity::Paused) {
|
||||||
SetStatus(ThreadStatus::Paused);
|
SetStatus(ThreadStatus::Paused);
|
||||||
return;
|
return;
|
||||||
|
@ -398,14 +398,13 @@ bool Thread::AllSynchronizationObjectsReady() const {
|
||||||
bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
bool Thread::InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||||
std::shared_ptr<SynchronizationObject> object,
|
std::shared_ptr<SynchronizationObject> object,
|
||||||
std::size_t index) {
|
std::size_t index) {
|
||||||
ASSERT(hle_callback);
|
ASSERT(wakeup_callback);
|
||||||
return hle_callback(reason, std::move(thread), std::move(object), index);
|
return wakeup_callback(reason, std::move(thread), std::move(object), index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Thread::InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
bool Thread::InvokeHLECallback(std::shared_ptr<Thread> thread) {
|
||||||
std::shared_ptr<SynchronizationObject> object, std::size_t index) {
|
|
||||||
ASSERT(hle_callback);
|
ASSERT(hle_callback);
|
||||||
return hle_callback(reason, std::move(thread), std::move(object), index);
|
return hle_callback(std::move(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::SetActivity(ThreadActivity value) {
|
void Thread::SetActivity(ThreadActivity value) {
|
||||||
|
|
|
@ -448,7 +448,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasWakeupCallback() const {
|
bool HasWakeupCallback() const {
|
||||||
return hle_callback != nullptr;
|
return wakeup_callback != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasHLECallback() const {
|
bool HasHLECallback() const {
|
||||||
|
@ -456,10 +456,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetWakeupCallback(WakeupCallback callback) {
|
void SetWakeupCallback(WakeupCallback callback) {
|
||||||
hle_callback = std::move(callback);
|
wakeup_callback = std::move(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetHLECallback(WakeupCallback callback) {
|
void SetHLECallback(HLECallback callback) {
|
||||||
hle_callback = std::move(callback);
|
hle_callback = std::move(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,8 +487,7 @@ public:
|
||||||
*/
|
*/
|
||||||
bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
bool InvokeWakeupCallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
||||||
std::shared_ptr<SynchronizationObject> object, std::size_t index);
|
std::shared_ptr<SynchronizationObject> object, std::size_t index);
|
||||||
bool InvokeHLECallback(ThreadWakeupReason reason, std::shared_ptr<Thread> thread,
|
bool InvokeHLECallback(std::shared_ptr<Thread> thread);
|
||||||
std::shared_ptr<SynchronizationObject> object, std::size_t index);
|
|
||||||
|
|
||||||
u32 GetIdealCore() const {
|
u32 GetIdealCore() const {
|
||||||
return ideal_core;
|
return ideal_core;
|
||||||
|
@ -622,8 +621,11 @@ private:
|
||||||
|
|
||||||
/// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
|
/// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
|
||||||
/// was waiting via WaitSynchronization then the object will be the last object that became
|
/// was waiting via WaitSynchronization then the object will be the last object that became
|
||||||
/// available. In case of a timeout, the object will be nullptr.
|
/// available. In case of a timeout, the object will be nullptr. DEPRECATED
|
||||||
WakeupCallback hle_callback;
|
WakeupCallback wakeup_callback;
|
||||||
|
|
||||||
|
/// Callback for HLE Events
|
||||||
|
HLECallback hle_callback;
|
||||||
Handle hle_time_event;
|
Handle hle_time_event;
|
||||||
|
|
||||||
Scheduler* scheduler = nullptr;
|
Scheduler* scheduler = nullptr;
|
||||||
|
|
Loading…
Reference in New Issue