summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-01-22 23:12:19 -0200
committerGravatar Yuri Kunde Schlesner2015-01-30 11:47:06 -0200
commit882b6fed75b7bf34809493482496e98c498a14e0 (patch)
tree7d44259e18b47559774f1d7e159fbd0c235d0318 /src/core
parentKernel: Convert AddressArbiter to not use Handles (diff)
downloadyuzu-882b6fed75b7bf34809493482496e98c498a14e0.tar.gz
yuzu-882b6fed75b7bf34809493482496e98c498a14e0.tar.xz
yuzu-882b6fed75b7bf34809493482496e98c498a14e0.zip
Kernel: Convert Mutex to not use Handles
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/kernel/mutex.cpp131
-rw-r--r--src/core/hle/kernel/mutex.h52
-rw-r--r--src/core/hle/service/apt_s.cpp1
-rw-r--r--src/core/hle/service/apt_u.cpp16
-rw-r--r--src/core/hle/svc.cpp24
5 files changed, 110 insertions, 114 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
14namespace Kernel { 14namespace Kernel {
15 15
16class Mutex : public WaitObject {
17public:
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
35typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap; 16typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
36static MutexMap g_mutex_held_locks; 17static 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 */
43static 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 */
52static void ResumeWaitingThread(Mutex* mutex) { 23static 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
64void ReleaseThreadMutexes(Thread* thread) { 35void 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
76static bool ReleaseMutex(Mutex* mutex) { 47ResultVal<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
92ResultCode 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 */
112static 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
128Handle 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
134bool Mutex::ShouldWait() { 64bool Mutex::ShouldWait() {
@@ -136,9 +66,34 @@ bool Mutex::ShouldWait() {
136} 66}
137 67
138void Mutex::Acquire() { 68void Mutex::Acquire() {
69 Acquire(GetCurrentThread());
70}
71
72void 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
83void 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
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index bb8778c98..a6d822e60 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -4,25 +4,51 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <string>
8
7#include "common/common_types.h" 9#include "common/common_types.h"
8 10
9#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
10 12
11namespace Kernel { 13namespace Kernel {
12 14
13/** 15class Thread;
14 * Releases a mutex 16
15 * @param handle Handle to mutex to release 17class Mutex : public WaitObject {
16 */ 18public:
17ResultCode ReleaseMutex(Handle handle); 19 /**
18 20 * Creates a mutex.
19/** 21 * @param initial_locked Specifies if the mutex should be locked initially
20 * Creates a mutex 22 * @param name Optional name of mutex
21 * @param initial_locked Specifies if the mutex should be locked initially 23 * @return Pointer to new Mutex object
22 * @param name Optional name of mutex 24 */
23 * @return Handle to newly created object 25 static ResultVal<SharedPtr<Mutex>> Create(bool initial_locked, std::string name = "Unknown");
24 */ 26
25Handle CreateMutex(bool initial_locked, const std::string& name="Unknown"); 27 std::string GetTypeName() const override { return "Mutex"; }
28 std::string GetName() const override { return name; }
29
30 static const HandleType HANDLE_TYPE = HandleType::Mutex;
31 HandleType GetHandleType() const override { return HANDLE_TYPE; }
32
33 bool initial_locked; ///< Initial lock state when mutex was created
34 bool locked; ///< Current locked state
35 std::string name; ///< Name of mutex (optional)
36 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
37
38 bool ShouldWait() override;
39 void Acquire() override;
40
41 /**
42 * Acquires the specified mutex for the specified thread
43 * @param mutex Mutex that is to be acquired
44 * @param thread Thread that will acquire the mutex
45 */
46 void Acquire(Thread* thread);
47 void Release();
48
49private:
50 Mutex() = default;
51};
26 52
27/** 53/**
28 * Releases all the mutexes held by the specified thread 54 * Releases all the mutexes held by the specified thread
diff --git a/src/core/hle/service/apt_s.cpp b/src/core/hle/service/apt_s.cpp
index 31e6653ef..7ad428ee7 100644
--- a/src/core/hle/service/apt_s.cpp
+++ b/src/core/hle/service/apt_s.cpp
@@ -10,6 +10,7 @@
10#include "core/hle/kernel/event.h" 10#include "core/hle/kernel/event.h"
11#include "core/hle/kernel/mutex.h" 11#include "core/hle/kernel/mutex.h"
12#include "core/hle/kernel/shared_memory.h" 12#include "core/hle/kernel/shared_memory.h"
13#include "core/hle/kernel/thread.h"
13#include "core/hle/service/apt_s.h" 14#include "core/hle/service/apt_s.h"
14 15
15//////////////////////////////////////////////////////////////////////////////////////////////////// 16////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index 1f6b148e8..5d7a6e060 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -10,6 +10,7 @@
10#include "core/hle/kernel/event.h" 10#include "core/hle/kernel/event.h"
11#include "core/hle/kernel/mutex.h" 11#include "core/hle/kernel/mutex.h"
12#include "core/hle/kernel/shared_memory.h" 12#include "core/hle/kernel/shared_memory.h"
13#include "core/hle/kernel/thread.h"
13#include "core/hle/service/apt_u.h" 14#include "core/hle/service/apt_u.h"
14 15
15//////////////////////////////////////////////////////////////////////////////////////////////////// 16////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -28,7 +29,7 @@ static const VAddr SHARED_FONT_VADDR = 0x18000000;
28/// Handle to shared memory region designated to for shared system font 29/// Handle to shared memory region designated to for shared system font
29static Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem; 30static Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem;
30 31
31static Handle lock_handle = 0; 32static Kernel::SharedPtr<Kernel::Mutex> lock;
32static Handle notification_event_handle = 0; ///< APT notification event handle 33static Handle notification_event_handle = 0; ///< APT notification event handle
33static Handle pause_event_handle = 0; ///< APT pause event handle 34static Handle pause_event_handle = 0; ///< APT pause event handle
34static std::vector<u8> shared_font; 35static std::vector<u8> shared_font;
@@ -76,8 +77,8 @@ void Initialize(Service::Interface* self) {
76 Kernel::ClearEvent(notification_event_handle); 77 Kernel::ClearEvent(notification_event_handle);
77 Kernel::SignalEvent(pause_event_handle); // Fire start event 78 Kernel::SignalEvent(pause_event_handle); // Fire start event
78 79
79 _assert_msg_(KERNEL, (0 != lock_handle), "Cannot initialize without lock"); 80 _assert_msg_(KERNEL, (nullptr != lock), "Cannot initialize without lock");
80 Kernel::ReleaseMutex(lock_handle); 81 lock->Release();
81 82
82 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 83 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
83} 84}
@@ -103,10 +104,9 @@ void GetLockHandle(Service::Interface* self) {
103 u32* cmd_buff = Kernel::GetCommandBuffer(); 104 u32* cmd_buff = Kernel::GetCommandBuffer();
104 u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field 105 u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
105 106
106 if (0 == lock_handle) { 107 if (nullptr == lock) {
107 // TODO(bunnei): Verify if this is created here or at application boot? 108 // TODO(bunnei): Verify if this is created here or at application boot?
108 lock_handle = Kernel::CreateMutex(false, "APT_U:Lock"); 109 lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom();
109 Kernel::ReleaseMutex(lock_handle);
110 } 110 }
111 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 111 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
112 112
@@ -116,7 +116,7 @@ void GetLockHandle(Service::Interface* self) {
116 cmd_buff[3] = 0; 116 cmd_buff[3] = 0;
117 cmd_buff[4] = 0; 117 cmd_buff[4] = 0;
118 118
119 cmd_buff[5] = lock_handle; 119 cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom();
120 LOG_TRACE(Service_APT, "called handle=0x%08X", cmd_buff[5]); 120 LOG_TRACE(Service_APT, "called handle=0x%08X", cmd_buff[5]);
121} 121}
122 122
@@ -520,7 +520,7 @@ Interface::Interface() {
520 shared_font_mem = nullptr; 520 shared_font_mem = nullptr;
521 } 521 }
522 522
523 lock_handle = 0; 523 lock = nullptr;
524 524
525 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 525 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
526} 526}
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index b093d0368..76ce59b29 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -364,18 +364,32 @@ static Result SetThreadPriority(Handle handle, s32 priority) {
364} 364}
365 365
366/// Create a mutex 366/// Create a mutex
367static Result CreateMutex(Handle* mutex, u32 initial_locked) { 367static Result CreateMutex(Handle* handle, u32 initial_locked) {
368 *mutex = Kernel::CreateMutex((initial_locked != 0)); 368 using Kernel::Mutex;
369
370 auto mutex_res = Mutex::Create(initial_locked != 0);
371 if (mutex_res.Failed())
372 return mutex_res.Code().raw;
373 SharedPtr<Mutex> mutex = mutex_res.MoveFrom();
374
375 *handle = Kernel::g_handle_table.Create(mutex).MoveFrom();
369 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 376 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
370 initial_locked ? "true" : "false", *mutex); 377 initial_locked ? "true" : "false", *handle);
371 return 0; 378 return 0;
372} 379}
373 380
374/// Release a mutex 381/// Release a mutex
375static Result ReleaseMutex(Handle handle) { 382static Result ReleaseMutex(Handle handle) {
383 using Kernel::Mutex;
384
376 LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle); 385 LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle);
377 ResultCode res = Kernel::ReleaseMutex(handle); 386
378 return res.raw; 387 SharedPtr<Mutex> mutex = Kernel::g_handle_table.Get<Mutex>(handle);
388 if (mutex == nullptr)
389 return InvalidHandle(ErrorModule::Kernel).raw;
390
391 mutex->Release();
392 return RESULT_SUCCESS.raw;
379} 393}
380 394
381/// Get the ID for the specified thread. 395/// Get the ID for the specified thread.