summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-01-31 23:26:16 -0200
committerGravatar Yuri Kunde Schlesner2015-02-02 15:37:08 -0200
commit52f58e64efbf43c114f701eb8f39fb463138ffb8 (patch)
treeeb40cc649b524febe841e463d6de7bce025a8105 /src
parentExplicitly instantiate constructors/destructors for Kernel objects (diff)
downloadyuzu-52f58e64efbf43c114f701eb8f39fb463138ffb8.tar.gz
yuzu-52f58e64efbf43c114f701eb8f39fb463138ffb8.tar.xz
yuzu-52f58e64efbf43c114f701eb8f39fb463138ffb8.zip
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 a24c2f69f..7e0b9542e 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;
20HandleTable g_handle_table; 20HandleTable g_handle_table;
21u64 g_program_id = 0; 21u64 g_program_id = 0;
22 22
23void WaitObject::AddWaitingThread(Thread* thread) { 23void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
24 auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); 24 auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
25 if (itr == waiting_threads.end()) 25 if (itr == waiting_threads.end())
26 waiting_threads.push_back(thread); 26 waiting_threads.push_back(std::move(thread));
27} 27}
28 28
29void WaitObject::RemoveWaitingThread(Thread* thread) { 29void WaitObject::RemoveWaitingThread(Thread* thread) {
@@ -32,11 +32,11 @@ void WaitObject::RemoveWaitingThread(Thread* thread) {
32 waiting_threads.erase(itr); 32 waiting_threads.erase(itr);
33} 33}
34 34
35Thread* WaitObject::WakeupNextThread() { 35SharedPtr<Thread> WaitObject::WakeupNextThread() {
36 if (waiting_threads.empty()) 36 if (waiting_threads.empty())
37 return nullptr; 37 return nullptr;
38 38
39 auto next_thread = waiting_threads.front(); 39 auto next_thread = std::move(waiting_threads.front());
40 waiting_threads.erase(waiting_threads.begin()); 40 waiting_threads.erase(waiting_threads.begin());
41 41
42 next_thread->ReleaseWaitObject(this); 42 next_thread->ReleaseWaitObject(this);
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index bf5b47a61..4d8e388b6 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -136,25 +136,26 @@ public:
136 * Add a thread to wait on this object 136 * Add a thread to wait on this object
137 * @param thread Pointer to thread to add 137 * @param thread Pointer to thread to add
138 */ 138 */
139 void AddWaitingThread(Thread* thread); 139 void AddWaitingThread(SharedPtr<Thread> thread);
140 140
141 /** 141 /**
142 * Removes a thread from waiting on this object (e.g. if it was resumed already) 142 * Removes a thread from waiting on this object (e.g. if it was resumed already)
143 * @param thread Pointer to thread to remove 143 * @param thread Pointer to thread to remove
144 */ 144 */
145 void RemoveWaitingThread(Thread* thead); 145 void RemoveWaitingThread(Thread* thread);
146 146
147 /** 147 /**
148 * Wake up the next thread waiting on this object 148 * Wake up the next thread waiting on this object
149 * @return Pointer to the thread that was resumed, nullptr if no threads are waiting 149 * @return Pointer to the thread that was resumed, nullptr if no threads are waiting
150 */ 150 */
151 Thread* WakeupNextThread(); 151 SharedPtr<Thread> WakeupNextThread();
152 152
153 /// Wake up all threads waiting on this object 153 /// Wake up all threads waiting on this object
154 void WakeupAllWaitingThreads(); 154 void WakeupAllWaitingThreads();
155 155
156private: 156private:
157 std::vector<Thread*> waiting_threads; ///< Threads waiting for this object to become available 157 /// Threads waiting for this object to become available
158 std::vector<SharedPtr<Thread>> waiting_threads;
158}; 159};
159 160
160/** 161/**
@@ -275,7 +276,6 @@ private:
275}; 276};
276 277
277extern HandleTable g_handle_table; 278extern HandleTable g_handle_table;
278extern SharedPtr<Thread> g_main_thread;
279 279
280/// The ID code of the currently running game 280/// The ID code of the currently running game
281/// TODO(Subv): This variable should not be here, 281/// 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 c6ad5ca91..7c634f9bd 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -66,7 +66,7 @@ void Mutex::Acquire() {
66 Acquire(GetCurrentThread()); 66 Acquire(GetCurrentThread());
67} 67}
68 68
69void Mutex::Acquire(Thread* thread) { 69void Mutex::Acquire(SharedPtr<Thread> thread) {
70 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); 70 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
71 if (locked) 71 if (locked)
72 return; 72 return;
@@ -74,7 +74,7 @@ void Mutex::Acquire(Thread* thread) {
74 locked = true; 74 locked = true;
75 75
76 thread->held_mutexes.insert(this); 76 thread->held_mutexes.insert(this);
77 holding_thread = thread; 77 holding_thread = std::move(thread);
78} 78}
79 79
80void Mutex::Release() { 80void Mutex::Release() {
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 21fd26e56..cdd79e265 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -43,7 +43,7 @@ public:
43 * @param mutex Mutex that is to be acquired 43 * @param mutex Mutex that is to be acquired
44 * @param thread Thread that will acquire the mutex 44 * @param thread Thread that will acquire the mutex
45 */ 45 */
46 void Acquire(Thread* thread); 46 void Acquire(SharedPtr<Thread> thread);
47 void Release(); 47 void Release();
48 48
49private: 49private:
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 9ad53b8cf..f092916dd 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) {
110 WakeupAllWaitingThreads(); 110 WakeupAllWaitingThreads();
111 111
112 // Stopped threads are never waiting. 112 // Stopped threads are never waiting.
113 for (auto& wait_object : wait_objects) {
114 wait_object->RemoveWaitingThread(this);
115 }
113 wait_objects.clear(); 116 wait_objects.clear();
114 wait_address = 0; 117 wait_address = 0;
115} 118}
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 980c2613a..633bb7c98 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -134,6 +134,8 @@ private:
134 Handle callback_handle; 134 Handle callback_handle;
135}; 135};
136 136
137extern SharedPtr<Thread> g_main_thread;
138
137/// Sets up the primary application thread 139/// Sets up the primary application thread
138SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size); 140SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size);
139 141