summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2014-05-20 23:03:45 -0400
committerGravatar bunnei2014-05-20 23:03:45 -0400
commit978e1d4653cd12a68d6bfa05af57edb1645da0f5 (patch)
tree75b5c4bbf272453cc9c37b381ef67e5746df0ea8 /src
parentsvc: added some comments (diff)
downloadyuzu-978e1d4653cd12a68d6bfa05af57edb1645da0f5.tar.gz
yuzu-978e1d4653cd12a68d6bfa05af57edb1645da0f5.tar.xz
yuzu-978e1d4653cd12a68d6bfa05af57edb1645da0f5.zip
mutex: initial commit of HLE module
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/core.vcxproj2
-rw-r--r--src/core/core.vcxproj.filters6
-rw-r--r--src/core/hle/kernel/mutex.cpp122
-rw-r--r--src/core/hle/kernel/mutex.h26
-rw-r--r--src/core/hle/service/apt.cpp10
-rw-r--r--src/core/hle/svc.cpp9
7 files changed, 166 insertions, 10 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index e006502da..6ad308798 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -35,6 +35,7 @@ set(SRCS core.cpp
35 hle/coprocessor.cpp 35 hle/coprocessor.cpp
36 hle/svc.cpp 36 hle/svc.cpp
37 hle/kernel/kernel.cpp 37 hle/kernel/kernel.cpp
38 hle/kernel/mutex.cpp
38 hle/kernel/thread.cpp 39 hle/kernel/thread.cpp
39 hle/service/apt.cpp 40 hle/service/apt.cpp
40 hle/service/gsp.cpp 41 hle/service/gsp.cpp
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index 6eb58a636..f271d336e 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -169,6 +169,7 @@
169 <ClCompile Include="hle\coprocessor.cpp" /> 169 <ClCompile Include="hle\coprocessor.cpp" />
170 <ClCompile Include="hle\hle.cpp" /> 170 <ClCompile Include="hle\hle.cpp" />
171 <ClCompile Include="hle\kernel\kernel.cpp" /> 171 <ClCompile Include="hle\kernel\kernel.cpp" />
172 <ClCompile Include="hle\kernel\mutex.cpp" />
172 <ClCompile Include="hle\kernel\thread.cpp" /> 173 <ClCompile Include="hle\kernel\thread.cpp" />
173 <ClCompile Include="hle\service\apt.cpp" /> 174 <ClCompile Include="hle\service\apt.cpp" />
174 <ClCompile Include="hle\service\gsp.cpp" /> 175 <ClCompile Include="hle\service\gsp.cpp" />
@@ -217,6 +218,7 @@
217 <ClInclude Include="hle\function_wrappers.h" /> 218 <ClInclude Include="hle\function_wrappers.h" />
218 <ClInclude Include="hle\hle.h" /> 219 <ClInclude Include="hle\hle.h" />
219 <ClInclude Include="hle\kernel\kernel.h" /> 220 <ClInclude Include="hle\kernel\kernel.h" />
221 <ClInclude Include="hle\kernel\mutex.h" />
220 <ClInclude Include="hle\kernel\thread.h" /> 222 <ClInclude Include="hle\kernel\thread.h" />
221 <ClInclude Include="hle\service\apt.h" /> 223 <ClInclude Include="hle\service\apt.h" />
222 <ClInclude Include="hle\service\gsp.h" /> 224 <ClInclude Include="hle\service\gsp.h" />
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index fc4e35edb..f664debec 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -162,6 +162,9 @@
162 <ClCompile Include="hle\svc.cpp"> 162 <ClCompile Include="hle\svc.cpp">
163 <Filter>hle</Filter> 163 <Filter>hle</Filter>
164 </ClCompile> 164 </ClCompile>
165 <ClCompile Include="hle\kernel\mutex.cpp">
166 <Filter>hle\kernel</Filter>
167 </ClCompile>
165 </ItemGroup> 168 </ItemGroup>
166 <ItemGroup> 169 <ItemGroup>
167 <ClInclude Include="arm\disassembler\arm_disasm.h"> 170 <ClInclude Include="arm\disassembler\arm_disasm.h">
@@ -289,6 +292,9 @@
289 <ClInclude Include="hle\svc.h"> 292 <ClInclude Include="hle\svc.h">
290 <Filter>hle</Filter> 293 <Filter>hle</Filter>
291 </ClInclude> 294 </ClInclude>
295 <ClInclude Include="hle\kernel\mutex.h">
296 <Filter>hle\kernel</Filter>
297 </ClInclude>
292 </ItemGroup> 298 </ItemGroup>
293 <ItemGroup> 299 <ItemGroup>
294 <Text Include="CMakeLists.txt" /> 300 <Text Include="CMakeLists.txt" />
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
new file mode 100644
index 000000000..2b2cff4ea
--- /dev/null
+++ b/src/core/hle/kernel/mutex.cpp
@@ -0,0 +1,122 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <map>
6#include <vector>
7
8#include "common/common.h"
9
10#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/thread.h"
12
13namespace Kernel {
14
15class Mutex : public Object {
16public:
17 const char* GetTypeName() { return "Mutex"; }
18
19 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; }
20 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Mutex; }
21
22 bool initial_locked; ///< Initial lock state when mutex was created
23 bool locked; ///< Current locked state
24 Handle lock_thread; ///< Handle to thread that currently has mutex
25 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex
26};
27
28////////////////////////////////////////////////////////////////////////////////////////////////////
29
30typedef std::multimap<Handle, Handle> MutexMap;
31static MutexMap g_mutex_held_locks;
32
33void __MutexAcquireLock(Mutex* mutex, Handle thread) {
34 g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle()));
35 mutex->lock_thread = thread;
36}
37
38void __MutexAcquireLock(Mutex* mutex) {
39 Handle thread = GetCurrentThread();
40 __MutexAcquireLock(mutex, thread);
41}
42
43void __MutexEraseLock(Mutex* mutex) {
44 Handle handle = mutex->GetHandle();
45 auto locked = g_mutex_held_locks.equal_range(mutex->lock_thread);
46 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
47 if ((*iter).second == handle) {
48 g_mutex_held_locks.erase(iter);
49 break;
50 }
51 }
52 mutex->lock_thread = -1;
53}
54
55bool __LockMutex(Mutex* mutex) {
56 // Mutex alread locked?
57 if (mutex->locked) {
58 return false;
59 }
60 __MutexAcquireLock(mutex);
61 return true;
62}
63
64bool __ReleaseMutexForThread(Mutex* mutex, Handle thread) {
65 __MutexAcquireLock(mutex, thread);
66 Kernel::ResumeThreadFromWait(thread);
67 return true;
68}
69
70bool __ReleaseMutex(Mutex* mutex) {
71 __MutexEraseLock(mutex);
72 bool woke_threads = false;
73 auto iter = mutex->waiting_threads.begin();
74
75 // Find the next waiting thread for the mutex...
76 while (!woke_threads && !mutex->waiting_threads.empty()) {
77 woke_threads |= __ReleaseMutexForThread(mutex, *iter);
78 mutex->waiting_threads.erase(iter);
79 }
80 // Reset mutex lock thread handle, nothing is waiting
81 if (!woke_threads) {
82 mutex->locked = false;
83 mutex->lock_thread = -1;
84 }
85 return woke_threads;
86}
87
88/**
89 * Releases a mutex
90 * @param handle Handle to mutex to release
91 */
92Result ReleaseMutex(Handle handle) {
93 Mutex* mutex = Kernel::g_object_pool.GetFast<Mutex>(handle);
94 if (!__ReleaseMutex(mutex)) {
95 return -1;
96 }
97 return 0;
98}
99
100/**
101 * Creates a mutex
102 * @param handle Reference to handle for the newly created mutex
103 * @param initial_locked Specifies if the mutex should be locked initially
104 */
105Result CreateMutex(Handle& handle, bool initial_locked) {
106 Mutex* mutex = new Mutex;
107 handle = Kernel::g_object_pool.Create(mutex);
108
109 mutex->locked = mutex->initial_locked = initial_locked;
110
111 // Acquire mutex with current thread if initialized as locked...
112 if (mutex->locked) {
113 __MutexAcquireLock(mutex);
114
115 // Otherwise, reset lock thread handle
116 } else {
117 mutex->lock_thread = -1;
118 }
119 return 0;
120}
121
122} // namespace
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
new file mode 100644
index 000000000..1f843e979
--- /dev/null
+++ b/src/core/hle/kernel/mutex.h
@@ -0,0 +1,26 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8
9#include "core/hle/kernel/kernel.h"
10
11namespace Kernel {
12
13/**
14 * Releases a mutex
15 * @param handle Handle to mutex to release
16 */
17Result ReleaseMutex(Handle handle);
18
19/**
20 * Creates a mutex
21 * @param handle Reference to handle for the newly created mutex
22 * @param initial_locked Specifies if the mutex should be locked initially
23 */
24Result CreateMutex(Handle& handle, bool initial_locked);
25
26} // namespace
diff --git a/src/core/hle/service/apt.cpp b/src/core/hle/service/apt.cpp
index 1f6a70eab..ecec4da00 100644
--- a/src/core/hle/service/apt.cpp
+++ b/src/core/hle/service/apt.cpp
@@ -3,9 +3,10 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5 5
6#include "common/log.h" 6#include "common/common.h"
7 7
8#include "core/hle/hle.h" 8#include "core/hle/hle.h"
9#include "core/hle/kernel/mutex.h"
9#include "core/hle/service/apt.h" 10#include "core/hle/service/apt.h"
10 11
11//////////////////////////////////////////////////////////////////////////////////////////////////// 12////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -19,11 +20,8 @@ void Initialize(Service::Interface* self) {
19 20
20void GetLockHandle(Service::Interface* self) { 21void GetLockHandle(Service::Interface* self) {
21 u32* cmd_buff = Service::GetCommandBuffer(); 22 u32* cmd_buff = Service::GetCommandBuffer();
22 u32 flags = cmd_buff[1]; 23 u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
23 24 cmd_buff[1] = Kernel::CreateMutex(cmd_buff[5], false);
24 // TODO: This should be an actual mutex handle. Games will check that this is not non-zero
25 // (NULL), and fail if such. A faked non-zero value will at least enable further booting.
26 cmd_buff[5] = 0x12345678;
27} 25}
28 26
29const Interface::FunctionInfo FunctionTable[] = { 27const Interface::FunctionInfo FunctionTable[] = {
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 3674a08c5..73ab073f5 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -187,15 +187,16 @@ Result CreateThread(void* thread, u32 priority, u32 entry_point, u32 arg, u32 st
187/// Create a mutex 187/// Create a mutex
188Result CreateMutex(void* _mutex, u32 initial_locked) { 188Result CreateMutex(void* _mutex, u32 initial_locked) {
189 Handle* mutex = (Handle*)_mutex; 189 Handle* mutex = (Handle*)_mutex;
190 DEBUG_LOG(SVC, "(UNIMPLEMENTED) CreateMutex called initial_locked=%s", 190 DEBUG_LOG(SVC, "CreateMutex called initial_locked=%s", initial_locked ? "true" : "false");
191 initial_locked ? "true" : "false"); 191 Kernel::CreateMutex(*mutex, (bool)initial_locked);
192 Core::g_app_core->SetReg(1, 0xF00D0BAD); 192 Core::g_app_core->SetReg(1, *mutex);
193 return 0; 193 return 0;
194} 194}
195 195
196/// Release a mutex 196/// Release a mutex
197Result ReleaseMutex(Handle handle) { 197Result ReleaseMutex(Handle handle) {
198 DEBUG_LOG(SVC, "(UNIMPLEMENTED) ReleaseMutex called handle=0x%08X", handle); 198 DEBUG_LOG(SVC, "ReleaseMutex called handle=0x%08X", handle);
199 Kernel::ReleaseMutex(handle);
199 return 0; 200 return 0;
200} 201}
201 202