1
0
Fork 0
forked from suyu/suyu

Core: Correct HLE Event Callbacks and other issues.

This commit is contained in:
Fernando Sahmkow 2020-03-03 13:02:50 -04:00
parent de5b521c09
commit 75e10578f1
5 changed files with 40 additions and 38 deletions

View file

@ -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);

View file

@ -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) {

View file

@ -28,6 +28,7 @@ void Synchronization::SignalObject(SynchronizationObject& obj) const {
time_manager.CancelTimeEvent(thread.get()); time_manager.CancelTimeEvent(thread.get());
} }
} }
obj.ClearWaitingThreads();
} }
} }

View file

@ -47,19 +47,21 @@ 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);
// 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) {
@ -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) {

View file

@ -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;