Skip to content

Instantly share code, notes, and snippets.

@Subv
Created January 11, 2015 23:31
Show Gist options
  • Save Subv/adb040176a9fcc82f52b to your computer and use it in GitHub Desktop.
Save Subv/adb040176a9fcc82f52b to your computer and use it in GitHub Desktop.
diff --git a/externals/boost b/externals/boost
--- a/externals/boost
+++ b/externals/boost
@@ -1 +1 @@
-Subproject commit a1afc91d3aaa3da06bdbc13c78613e1466653405
+Subproject commit a1afc91d3aaa3da06bdbc13c78613e1466653405-dirty
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 271190d..7a2971a 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -90,7 +90,7 @@ ResultCode SignalEvent(const Handle handle) {
for (size_t i = 0; i < evt->waiting_threads.size(); ++i) {
Thread* thread = Kernel::g_handle_table.Get<Thread>(evt->waiting_threads[i]).get();
if (thread != nullptr)
- thread->ResumeFromWait();
+ thread->ResumeFromWait(evt->GetHandle());
// If any thread is signalled awake by this event, assume the event was "caught" and reset
// the event. This will result in the next thread waiting on the event to block. Otherwise,
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 853a5dd..e7aeaaf 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -54,7 +54,7 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread_handle) {
return false;
}
- thread->ResumeFromWait();
+ thread->ResumeFromWait(mutex->GetHandle());
return true;
}
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 88ec9a1..6151d6f 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -86,7 +86,7 @@ ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) {
Thread* thread = Kernel::g_handle_table.Get<Thread>(semaphore->waiting_threads.front()).get();
if (thread != nullptr)
- thread->ResumeFromWait();
+ thread->ResumeFromWait(semaphore->GetHandle());
semaphore->waiting_threads.pop();
--semaphore->available_count;
}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index bc86a7c..989f555 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -112,7 +112,7 @@ void Thread::Stop(const char* reason) {
status = THREADSTATUS_DORMANT;
for (auto& waiting_thread : waiting_threads) {
if (CheckWaitType(waiting_thread.get(), WAITTYPE_THREADEND, this))
- waiting_thread->ResumeFromWait();
+ waiting_thread->ResumeFromWait(GetHandle());
}
waiting_threads.clear();
@@ -158,7 +158,7 @@ Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address) {
// If a thread was arbitrated, resume it
if (nullptr != highest_priority_thread) {
- highest_priority_thread->ResumeFromWait();
+ highest_priority_thread->ResumeFromWait(arbiter->GetHandle());
}
return highest_priority_thread;
@@ -170,7 +170,7 @@ void ArbitrateAllThreads(Object* arbiter, u32 address) {
// Iterate through threads, find highest priority thread that is waiting to be arbitrated...
for (auto& thread : thread_list) {
if (CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address))
- thread->ResumeFromWait();
+ thread->ResumeFromWait(arbiter->GetHandle());
}
}
@@ -247,7 +247,7 @@ static void ThreadWakeupCallback(u64 parameter, int cycles_late) {
return;
}
- thread->ResumeFromWait();
+ thread->ResumeFromWait(INVALID_HANDLE);
}
@@ -262,10 +262,25 @@ void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds) {
}
/// Resumes a thread from waiting by marking it as "ready"
-void Thread::ResumeFromWait() {
+void Thread::ResumeFromWait(Handle trigger) {
// Cancel any outstanding wakeup events
CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle());
+ if (trigger != INVALID_HANDLE && waiting_n_sync == true && waiting_n_handles != nullptr) {
+ int i;
+ for (i = 0; i < waiting_handles_num; ++i) {
+ if (waiting_n_handles[i] == trigger) {
+ break;
+ }
+ }
+
+ context.cpu_registers[1] = i;
+ HLE::Reschedule(__func__);
+ }
+
+ waiting_n_sync = false;
+ waiting_n_handles = nullptr;
+ waiting_handles_num = 0;
status &= ~THREADSTATUS_WAIT;
wait_object = nullptr;
wait_type = WAITTYPE_NONE;
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 284dec4..01e3608 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -79,7 +79,7 @@ public:
void Stop(const char* reason);
/// Resumes a thread from waiting by marking it as "ready".
- void ResumeFromWait();
+ void ResumeFromWait(Handle trigger);
Core::ThreadContext context;
@@ -106,6 +106,10 @@ public:
/// Whether this thread is intended to never actually be executed, i.e. always idle
bool idle = false;
+ bool waiting_n_sync = false;
+ Handle* waiting_n_handles = nullptr;
+ int waiting_handles_num = 0;
+
private:
Thread() = default;
};
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 3b0452d..70010ee 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -94,7 +94,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
// Resume all waiting threads
for (Handle thread_handle : timer->waiting_threads) {
if (SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(thread_handle))
- thread->ResumeFromWait();
+ thread->ResumeFromWait(timer->GetHandle());
}
timer->waiting_threads.clear();
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index d3b4483..9e660de 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -177,6 +177,10 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
return RESULT_SUCCESS.raw;
}
+ Kernel::GetCurrentThread()->waiting_n_sync = true;
+ Kernel::GetCurrentThread()->waiting_n_handles = handles;
+ Kernel::GetCurrentThread()->waiting_handles_num = handle_count;
+
// Check for next thread to schedule
HLE::Reschedule(__func__);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment