diff options
| author | 2015-01-22 23:12:19 -0200 | |
|---|---|---|
| committer | 2015-01-30 11:47:06 -0200 | |
| commit | 882b6fed75b7bf34809493482496e98c498a14e0 (patch) | |
| tree | 7d44259e18b47559774f1d7e159fbd0c235d0318 /src/core/hle/kernel/mutex.cpp | |
| parent | Kernel: Convert AddressArbiter to not use Handles (diff) | |
| download | yuzu-882b6fed75b7bf34809493482496e98c498a14e0.tar.gz yuzu-882b6fed75b7bf34809493482496e98c498a14e0.tar.xz yuzu-882b6fed75b7bf34809493482496e98c498a14e0.zip | |
Kernel: Convert Mutex to not use Handles
Diffstat (limited to 'src/core/hle/kernel/mutex.cpp')
| -rw-r--r-- | src/core/hle/kernel/mutex.cpp | 131 |
1 files changed, 43 insertions, 88 deletions
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index c94c2acc9..acf484659 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -13,59 +13,30 @@ | |||
| 13 | 13 | ||
| 14 | namespace Kernel { | 14 | namespace Kernel { |
| 15 | 15 | ||
| 16 | class Mutex : public WaitObject { | ||
| 17 | public: | ||
| 18 | std::string GetTypeName() const override { return "Mutex"; } | ||
| 19 | std::string GetName() const override { return name; } | ||
| 20 | |||
| 21 | static const HandleType HANDLE_TYPE = HandleType::Mutex; | ||
| 22 | HandleType GetHandleType() const override { return HANDLE_TYPE; } | ||
| 23 | |||
| 24 | bool initial_locked; ///< Initial lock state when mutex was created | ||
| 25 | bool locked; ///< Current locked state | ||
| 26 | std::string name; ///< Name of mutex (optional) | ||
| 27 | SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex | ||
| 28 | |||
| 29 | bool ShouldWait() override; | ||
| 30 | void Acquire() override; | ||
| 31 | }; | ||
| 32 | |||
| 33 | //////////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 34 | |||
| 35 | typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap; | 16 | typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap; |
| 36 | static MutexMap g_mutex_held_locks; | 17 | static MutexMap g_mutex_held_locks; |
| 37 | 18 | ||
| 38 | /** | 19 | /** |
| 39 | * Acquires the specified mutex for the specified thread | ||
| 40 | * @param mutex Mutex that is to be acquired | ||
| 41 | * @param thread Thread that will acquire the mutex | ||
| 42 | */ | ||
| 43 | static void MutexAcquireLock(Mutex* mutex, Thread* thread) { | ||
| 44 | g_mutex_held_locks.insert(std::make_pair(thread, mutex)); | ||
| 45 | mutex->holding_thread = thread; | ||
| 46 | } | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Resumes a thread waiting for the specified mutex | 20 | * Resumes a thread waiting for the specified mutex |
| 50 | * @param mutex The mutex that some thread is waiting on | 21 | * @param mutex The mutex that some thread is waiting on |
| 51 | */ | 22 | */ |
| 52 | static void ResumeWaitingThread(Mutex* mutex) { | 23 | static void ResumeWaitingThread(Mutex* mutex) { |
| 24 | // Reset mutex lock thread handle, nothing is waiting | ||
| 25 | mutex->locked = false; | ||
| 26 | mutex->holding_thread = nullptr; | ||
| 27 | |||
| 53 | // Find the next waiting thread for the mutex... | 28 | // Find the next waiting thread for the mutex... |
| 54 | auto next_thread = mutex->WakeupNextThread(); | 29 | auto next_thread = mutex->WakeupNextThread(); |
| 55 | if (next_thread != nullptr) { | 30 | if (next_thread != nullptr) { |
| 56 | MutexAcquireLock(mutex, next_thread); | 31 | mutex->Acquire(next_thread); |
| 57 | } else { | ||
| 58 | // Reset mutex lock thread handle, nothing is waiting | ||
| 59 | mutex->locked = false; | ||
| 60 | mutex->holding_thread = nullptr; | ||
| 61 | } | 32 | } |
| 62 | } | 33 | } |
| 63 | 34 | ||
| 64 | void ReleaseThreadMutexes(Thread* thread) { | 35 | void ReleaseThreadMutexes(Thread* thread) { |
| 65 | auto locked = g_mutex_held_locks.equal_range(thread); | 36 | auto locked_range = g_mutex_held_locks.equal_range(thread); |
| 66 | 37 | ||
| 67 | // Release every mutex that the thread holds, and resume execution on the waiting threads | 38 | // Release every mutex that the thread holds, and resume execution on the waiting threads |
| 68 | for (auto iter = locked.first; iter != locked.second; ++iter) { | 39 | for (auto iter = locked_range.first; iter != locked_range.second; ++iter) { |
| 69 | ResumeWaitingThread(iter->second.get()); | 40 | ResumeWaitingThread(iter->second.get()); |
| 70 | } | 41 | } |
| 71 | 42 | ||
| @@ -73,62 +44,21 @@ void ReleaseThreadMutexes(Thread* thread) { | |||
| 73 | g_mutex_held_locks.erase(thread); | 44 | g_mutex_held_locks.erase(thread); |
| 74 | } | 45 | } |
| 75 | 46 | ||
| 76 | static bool ReleaseMutex(Mutex* mutex) { | 47 | ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) { |
| 77 | if (mutex->locked) { | 48 | SharedPtr<Mutex> mutex(new Mutex); |
| 78 | auto locked = g_mutex_held_locks.equal_range(mutex->holding_thread); | 49 | // TOOD(yuriks): Don't create Handle (see Thread::Create()) |
| 79 | 50 | CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex)); | |
| 80 | for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { | ||
| 81 | if (iter->second == mutex) { | ||
| 82 | g_mutex_held_locks.erase(iter); | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | ResumeWaitingThread(mutex); | ||
| 88 | } | ||
| 89 | return true; | ||
| 90 | } | ||
| 91 | |||
| 92 | ResultCode ReleaseMutex(Handle handle) { | ||
| 93 | Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle).get(); | ||
| 94 | if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); | ||
| 95 | |||
| 96 | if (!ReleaseMutex(mutex)) { | ||
| 97 | // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure | ||
| 98 | // what error condition this is supposed to be signaling. | ||
| 99 | return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel, | ||
| 100 | ErrorSummary::NothingHappened, ErrorLevel::Temporary); | ||
| 101 | } | ||
| 102 | return RESULT_SUCCESS; | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * Creates a mutex | ||
| 107 | * @param handle Reference to handle for the newly created mutex | ||
| 108 | * @param initial_locked Specifies if the mutex should be locked initially | ||
| 109 | * @param name Optional name of mutex | ||
| 110 | * @return Pointer to new Mutex object | ||
| 111 | */ | ||
| 112 | static Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { | ||
| 113 | Mutex* mutex = new Mutex; | ||
| 114 | // TODO(yuriks): Fix error reporting | ||
| 115 | handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE); | ||
| 116 | 51 | ||
| 117 | mutex->locked = mutex->initial_locked = initial_locked; | 52 | mutex->initial_locked = initial_locked; |
| 118 | mutex->name = name; | 53 | mutex->locked = false; |
| 54 | mutex->name = std::move(name); | ||
| 119 | mutex->holding_thread = nullptr; | 55 | mutex->holding_thread = nullptr; |
| 120 | 56 | ||
| 121 | // Acquire mutex with current thread if initialized as locked... | 57 | // Acquire mutex with current thread if initialized as locked... |
| 122 | if (mutex->locked) | 58 | if (initial_locked) |
| 123 | MutexAcquireLock(mutex, GetCurrentThread()); | 59 | mutex->Acquire(); |
| 124 | 60 | ||
| 125 | return mutex; | 61 | return MakeResult<SharedPtr<Mutex>>(mutex); |
| 126 | } | ||
| 127 | |||
| 128 | Handle CreateMutex(bool initial_locked, const std::string& name) { | ||
| 129 | Handle handle; | ||
| 130 | Mutex* mutex = CreateMutex(handle, initial_locked, name); | ||
| 131 | return handle; | ||
| 132 | } | 62 | } |
| 133 | 63 | ||
| 134 | bool Mutex::ShouldWait() { | 64 | bool Mutex::ShouldWait() { |
| @@ -136,9 +66,34 @@ bool Mutex::ShouldWait() { | |||
| 136 | } | 66 | } |
| 137 | 67 | ||
| 138 | void Mutex::Acquire() { | 68 | void Mutex::Acquire() { |
| 69 | Acquire(GetCurrentThread()); | ||
| 70 | } | ||
| 71 | |||
| 72 | void Mutex::Acquire(Thread* thread) { | ||
| 139 | _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); | 73 | _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); |
| 74 | if (locked) | ||
| 75 | return; | ||
| 76 | |||
| 140 | locked = true; | 77 | locked = true; |
| 141 | MutexAcquireLock(this, GetCurrentThread()); | 78 | |
| 79 | g_mutex_held_locks.insert(std::make_pair(thread, this)); | ||
| 80 | holding_thread = thread; | ||
| 81 | } | ||
| 82 | |||
| 83 | void Mutex::Release() { | ||
| 84 | if (!locked) | ||
| 85 | return; | ||
| 86 | |||
| 87 | auto locked_range = g_mutex_held_locks.equal_range(holding_thread); | ||
| 88 | |||
| 89 | for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) { | ||
| 90 | if (iter->second == this) { | ||
| 91 | g_mutex_held_locks.erase(iter); | ||
| 92 | break; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | ResumeWaitingThread(this); | ||
| 142 | } | 97 | } |
| 143 | 98 | ||
| 144 | } // namespace | 99 | } // namespace |