aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYuri Kunde Schlesner <yuriks@yuriks.net>2015-01-31 23:26:16 -0200
committerYuri Kunde Schlesner <yuriks@yuriks.net>2015-02-02 15:37:08 -0200
commit52f58e64efbf43c114f701eb8f39fb463138ffb8 (patch)
treeeb40cc649b524febe841e463d6de7bce025a8105 /src
parent7725256f649719dcce2c50ea84e79d6199dd9a50 (diff)
Kernel: Make WaitObjects share ownership of Threads waiting on them
During normal operation, a thread waiting on an WaitObject and the object hold mutual references to each other for the duration of the wait. If a process is forcefully terminated (The CTR kernel has a SVC to do this, TerminateProcess, though no equivalent exists for threads.) its threads would also be stopped and destroyed, leaving dangling pointers in the WaitObjects. The solution is to simply have the Thread remove itself from WaitObjects when it is stopped. The vector of Threads in WaitObject has also been changed to hold SharedPtrs, just in case. (Better to have a reference cycle than a crash.)
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/kernel.cpp8
-rw-r--r--src/core/hle/kernel/kernel.h10
-rw-r--r--src/core/hle/kernel/mutex.cpp4
-rw-r--r--src/core/hle/kernel/mutex.h2
-rw-r--r--src/core/hle/kernel/thread.cpp3
-rw-r--r--src/core/hle/kernel/thread.h2
6 files changed, 17 insertions, 12 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index a24c2f69f6..7e0b9542eb 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -20,10 +20,10 @@ SharedPtr<Thread> g_main_thread = nullptr;
HandleTable g_handle_table;
u64 g_program_id = 0;
-void WaitObject::AddWaitingThread(Thread* thread) {
+void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
if (itr == waiting_threads.end())
- waiting_threads.push_back(thread);
+ waiting_threads.push_back(std::move(thread));
}
void WaitObject::RemoveWaitingThread(Thread* thread) {
@@ -32,11 +32,11 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
waiting_threads.erase(itr);
}
-Thread* WaitObject::WakeupNextThread() {
+SharedPtr<Thread> WaitObject::WakeupNextThread() {
if (waiting_threads.empty())
return nullptr;
- auto next_thread = waiting_threads.front();
+ auto next_thread = std::move(waiting_threads.front());
waiting_threads.erase(waiting_threads.begin());
next_thread->ReleaseWaitObject(this);
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index bf5b47a618..4d8e388b64 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -136,25 +136,26 @@ public:
* Add a thread to wait on this object
* @param thread Pointer to thread to add
*/
- void AddWaitingThread(Thread* thread);
+ void AddWaitingThread(SharedPtr<Thread> thread);
/**
* Removes a thread from waiting on this object (e.g. if it was resumed already)
* @param thread Pointer to thread to remove
*/
- void RemoveWaitingThread(Thread* thead);
+ void RemoveWaitingThread(Thread* thread);
/**
* Wake up the next thread waiting on this object
* @return Pointer to the thread that was resumed, nullptr if no threads are waiting
*/
- Thread* WakeupNextThread();
+ SharedPtr<Thread> WakeupNextThread();
/// Wake up all threads waiting on this object
void WakeupAllWaitingThreads();
private:
- std::vector<Thread*> waiting_threads; ///< Threads waiting for this object to become available
+ /// Threads waiting for this object to become available
+ std::vector<SharedPtr<Thread>> waiting_threads;
};
/**
@@ -275,7 +276,6 @@ private:
};
extern HandleTable g_handle_table;
-extern SharedPtr<Thread> g_main_thread;
/// The ID code of the currently running game
/// TODO(Subv): This variable should not be here,
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index c6ad5ca91d..7c634f9bd0 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -66,7 +66,7 @@ void Mutex::Acquire() {
Acquire(GetCurrentThread());
}
-void Mutex::Acquire(Thread* thread) {
+void Mutex::Acquire(SharedPtr<Thread> thread) {
_assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
if (locked)
return;
@@ -74,7 +74,7 @@ void Mutex::Acquire(Thread* thread) {
locked = true;
thread->held_mutexes.insert(this);
- holding_thread = thread;
+ holding_thread = std::move(thread);
}
void Mutex::Release() {
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 21fd26e56f..cdd79e265a 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -43,7 +43,7 @@ public:
* @param mutex Mutex that is to be acquired
* @param thread Thread that will acquire the mutex
*/
- void Acquire(Thread* thread);
+ void Acquire(SharedPtr<Thread> thread);
void Release();
private:
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 9ad53b8cff..f092916dde 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -110,6 +110,9 @@ void Thread::Stop(const char* reason) {
WakeupAllWaitingThreads();
// Stopped threads are never waiting.
+ for (auto& wait_object : wait_objects) {
+ wait_object->RemoveWaitingThread(this);
+ }
wait_objects.clear();
wait_address = 0;
}
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 980c2613af..633bb7c983 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -134,6 +134,8 @@ private:
Handle callback_handle;
};
+extern SharedPtr<Thread> g_main_thread;
+
/// Sets up the primary application thread
SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size);