citra-emu
/
citra-canary
Archived
1
0
Fork 0

Mutex: Replace g_mutex_held_locks with a set inside Thread

This commit is contained in:
Yuri Kunde Schlesner 2015-01-31 19:22:40 -02:00
parent 0f69668fc6
commit 4e84df8be3
3 changed files with 18 additions and 23 deletions

View File

@ -5,6 +5,8 @@
#include <map> #include <map>
#include <vector> #include <vector>
#include <boost/range/algorithm_ext/erase.hpp>
#include "common/common.h" #include "common/common.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
@ -13,9 +15,6 @@
namespace Kernel { namespace Kernel {
typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
static MutexMap g_mutex_held_locks;
/** /**
* Resumes a thread waiting for the specified mutex * Resumes a thread waiting for the specified mutex
* @param mutex The mutex that some thread is waiting on * @param mutex The mutex that some thread is waiting on
@ -33,15 +32,10 @@ static void ResumeWaitingThread(Mutex* mutex) {
} }
void ReleaseThreadMutexes(Thread* thread) { void ReleaseThreadMutexes(Thread* thread) {
auto locked_range = g_mutex_held_locks.equal_range(thread); for (auto& mtx : thread->held_mutexes) {
ResumeWaitingThread(mtx.get());
// Release every mutex that the thread holds, and resume execution on the waiting threads
for (auto iter = locked_range.first; iter != locked_range.second; ++iter) {
ResumeWaitingThread(iter->second.get());
} }
thread->held_mutexes.clear();
// Erase all the locks that this thread holds
g_mutex_held_locks.erase(thread);
} }
ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) { ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) {
@ -76,7 +70,7 @@ void Mutex::Acquire(Thread* thread) {
locked = true; locked = true;
g_mutex_held_locks.insert(std::make_pair(thread, this)); thread->held_mutexes.insert(this);
holding_thread = thread; holding_thread = thread;
} }
@ -84,15 +78,7 @@ void Mutex::Release() {
if (!locked) if (!locked)
return; return;
auto locked_range = g_mutex_held_locks.equal_range(holding_thread); holding_thread->held_mutexes.erase(this);
for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) {
if (iter->second == this) {
g_mutex_held_locks.erase(iter);
break;
}
}
ResumeWaitingThread(this); ResumeWaitingThread(this);
} }

View File

@ -40,6 +40,9 @@ static Thread* current_thread;
static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup
static u32 next_thread_id; ///< The next available thread id static u32 next_thread_id; ///< The next available thread id
Thread::Thread() {
}
Thread* GetCurrentThread() { Thread* GetCurrentThread() {
return current_thread; return current_thread;
} }

View File

@ -7,6 +7,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <boost/container/flat_set.hpp>
#include "common/common_types.h" #include "common/common_types.h"
#include "core/core.h" #include "core/core.h"
@ -40,6 +42,8 @@ enum ThreadStatus {
namespace Kernel { namespace Kernel {
class Mutex;
class Thread final : public WaitObject { class Thread final : public WaitObject {
public: public:
static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
@ -109,8 +113,10 @@ public:
s32 processor_id; s32 processor_id;
std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on /// Mutexes currently held by this thread, which will be released when it exits.
boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on
VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
bool wait_all; ///< True if the thread is waiting on all objects before resuming bool wait_all; ///< True if the thread is waiting on all objects before resuming
bool wait_set_output; ///< True if the output parameter should be set on thread wakeup bool wait_set_output; ///< True if the output parameter should be set on thread wakeup
@ -121,7 +127,7 @@ public:
bool idle = false; bool idle = false;
private: private:
Thread() = default; Thread();
/// Handle used as userdata to reference this object when inserting into the CoreTiming queue. /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
Handle callback_handle; Handle callback_handle;