summaryrefslogtreecommitdiff
path: root/src/core/hle/svc.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2014-06-05 22:35:36 -0400
committerGravatar bunnei2014-06-13 09:51:02 -0400
commitf5c7c1543434e25a215286e6db5e71c055ba48cf (patch)
tree488a3fd0c01051453c6f8ccc4867f6b6ea3f2843 /src/core/hle/svc.cpp
parentqt: updated disassembler to show 2X as many instructions (diff)
downloadyuzu-f5c7c1543434e25a215286e6db5e71c055ba48cf.tar.gz
yuzu-f5c7c1543434e25a215286e6db5e71c055ba48cf.tar.xz
yuzu-f5c7c1543434e25a215286e6db5e71c055ba48cf.zip
Kernel: Added real support for thread and event blocking
- SVC: Added ExitThread support - SVC: Added SignalEvent support - Thread: Added WAITTYPE_EVENT for waiting threads for event signals - Thread: Added support for blocking on other threads to finish (e.g. Thread::Join) - Thread: Added debug function for printing current threads ready for execution - Thread: Removed hack/broken thread ready state code from Kernel::Reschedule - Mutex: Moved WaitCurrentThread from SVC to Mutex::WaitSynchronization - Event: Added support for blocking threads on event signalling Kernel: Added missing algorithm #include for use of std::find on non-Windows platforms.
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r--src/core/hle/svc.cpp59
1 files changed, 31 insertions, 28 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index c8eb8ea80..0ce831103 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -93,8 +93,8 @@ Result SendSyncRequest(Handle handle) {
93 bool wait = false; 93 bool wait = false;
94 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); 94 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
95 95
96 DEBUG_LOG(SVC, "called handle=0x%08X", handle);
97 _assert_msg_(KERNEL, object, "called, but kernel object is NULL!"); 96 _assert_msg_(KERNEL, object, "called, but kernel object is NULL!");
97 DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName());
98 98
99 Result res = object->SyncRequest(&wait); 99 Result res = object->SyncRequest(&wait);
100 if (wait) { 100 if (wait) {
@@ -115,29 +115,21 @@ Result CloseHandle(Handle handle) {
115Result WaitSynchronization1(Handle handle, s64 nano_seconds) { 115Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
116 // TODO(bunnei): Do something with nano_seconds, currently ignoring this 116 // TODO(bunnei): Do something with nano_seconds, currently ignoring this
117 bool wait = false; 117 bool wait = false;
118 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
118 119
119 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); 120 Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle);
120 121
121 DEBUG_LOG(SVC, "called handle=0x%08X, nanoseconds=%d", handle, 122 DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%d", handle, object->GetTypeName(),
122 nano_seconds); 123 object->GetName(), nano_seconds);
124
123 _assert_msg_(KERNEL, object, "called, but kernel object is NULL!"); 125 _assert_msg_(KERNEL, object, "called, but kernel object is NULL!");
124 126
125 Result res = object->WaitSynchronization(&wait); 127 Result res = object->WaitSynchronization(&wait);
126 128
129 // Check for next thread to schedule
127 if (wait) { 130 if (wait) {
128 // Set current thread to wait state if handle was not unlocked
129 Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
130
131 // Check for next thread to schedule
132 HLE::Reschedule(__func__); 131 HLE::Reschedule(__func__);
133 132 return 0;
134 // Context switch - Function blocked, is not actually returning (will be "called" again)
135
136 // TODO(bunnei): This saves handle to R0 so that it's correctly reloaded on context switch
137 // (otherwise R0 will be set to whatever is returned, and handle will be invalid when this
138 // thread is resumed). There is probably a better way of keeping track of state so that we
139 // don't necessarily have to do this.
140 return (Result)PARAM(0);
141 } 133 }
142 134
143 return res; 135 return res;
@@ -150,6 +142,7 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa
150 s32* out = (s32*)_out; 142 s32* out = (s32*)_out;
151 Handle* handles = (Handle*)_handles; 143 Handle* handles = (Handle*)_handles;
152 bool unlock_all = true; 144 bool unlock_all = true;
145 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
153 146
154 DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%d", 147 DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%d",
155 handle_count, (wait_all ? "true" : "false"), nano_seconds); 148 handle_count, (wait_all ? "true" : "false"), nano_seconds);
@@ -162,7 +155,8 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa
162 _assert_msg_(KERNEL, object, "called handle=0x%08X, but kernel object " 155 _assert_msg_(KERNEL, object, "called handle=0x%08X, but kernel object "
163 "is NULL!", handles[i]); 156 "is NULL!", handles[i]);
164 157
165 DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X", i, handles[i]); 158 DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName(),
159 object->GetName());
166 160
167 Result res = object->WaitSynchronization(&wait); 161 Result res = object->WaitSynchronization(&wait);
168 162
@@ -179,19 +173,10 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa
179 return 0; 173 return 0;
180 } 174 }
181 175
182 // Set current thread to wait state if not all handles were unlocked
183 Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct?
184
185 // Check for next thread to schedule 176 // Check for next thread to schedule
186 HLE::Reschedule(__func__); 177 HLE::Reschedule(__func__);
187 178
188 // Context switch - Function blocked, is not actually returning (will be "called" again) 179 return 0;
189
190 // TODO(bunnei): This saves handle to R0 so that it's correctly reloaded on context switch
191 // (otherwise R0 will be set to whatever is returned, and handle will be invalid when this
192 // thread is resumed). There is probably a better way of keeping track of state so that we
193 // don't necessarily have to do this.
194 return (Result)PARAM(0);
195} 180}
196 181
197/// Create an address arbiter (to allocate access to shared resources) 182/// Create an address arbiter (to allocate access to shared resources)
@@ -258,6 +243,17 @@ Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 p
258 return 0; 243 return 0;
259} 244}
260 245
246/// Called when a thread exits
247u32 ExitThread() {
248 Handle thread = Kernel::GetCurrentThreadHandle();
249
250 DEBUG_LOG(SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C
251
252 Kernel::StopThread(thread, __func__);
253 HLE::Reschedule(__func__);
254 return 0;
255}
256
261/// Gets the priority for the specified thread 257/// Gets the priority for the specified thread
262Result GetThreadPriority(void* _priority, Handle handle) { 258Result GetThreadPriority(void* _priority, Handle handle) {
263 s32* priority = (s32*)_priority; 259 s32* priority = (s32*)_priority;
@@ -326,6 +322,13 @@ Result DuplicateHandle(void* _out, Handle handle) {
326 return 0; 322 return 0;
327} 323}
328 324
325/// Signals an event
326Result SignalEvent(Handle evt) {
327 Result res = Kernel::SignalEvent(evt);
328 DEBUG_LOG(SVC, "called event=0x%08X", evt);
329 return res;
330}
331
329/// Clears an event 332/// Clears an event
330Result ClearEvent(Handle evt) { 333Result ClearEvent(Handle evt) {
331 Result res = Kernel::ClearEvent(evt); 334 Result res = Kernel::ClearEvent(evt);
@@ -348,7 +351,7 @@ const HLE::FunctionDef SVC_Table[] = {
348 {0x06, NULL, "GetProcessIdealProcessor"}, 351 {0x06, NULL, "GetProcessIdealProcessor"},
349 {0x07, NULL, "SetProcessIdealProcessor"}, 352 {0x07, NULL, "SetProcessIdealProcessor"},
350 {0x08, WrapI_UUUUU<CreateThread>, "CreateThread"}, 353 {0x08, WrapI_UUUUU<CreateThread>, "CreateThread"},
351 {0x09, NULL, "ExitThread"}, 354 {0x09, WrapU_V<ExitThread>, "ExitThread"},
352 {0x0A, WrapV_S64<SleepThread>, "SleepThread"}, 355 {0x0A, WrapV_S64<SleepThread>, "SleepThread"},
353 {0x0B, WrapI_VU<GetThreadPriority>, "GetThreadPriority"}, 356 {0x0B, WrapI_VU<GetThreadPriority>, "GetThreadPriority"},
354 {0x0C, WrapI_UI<SetThreadPriority>, "SetThreadPriority"}, 357 {0x0C, WrapI_UI<SetThreadPriority>, "SetThreadPriority"},
@@ -363,7 +366,7 @@ const HLE::FunctionDef SVC_Table[] = {
363 {0x15, NULL, "CreateSemaphore"}, 366 {0x15, NULL, "CreateSemaphore"},
364 {0x16, NULL, "ReleaseSemaphore"}, 367 {0x16, NULL, "ReleaseSemaphore"},
365 {0x17, WrapI_VU<CreateEvent>, "CreateEvent"}, 368 {0x17, WrapI_VU<CreateEvent>, "CreateEvent"},
366 {0x18, NULL, "SignalEvent"}, 369 {0x18, WrapI_U<SignalEvent>, "SignalEvent"},
367 {0x19, WrapI_U<ClearEvent>, "ClearEvent"}, 370 {0x19, WrapI_U<ClearEvent>, "ClearEvent"},
368 {0x1A, NULL, "CreateTimer"}, 371 {0x1A, NULL, "CreateTimer"},
369 {0x1B, NULL, "SetTimer"}, 372 {0x1B, NULL, "SetTimer"},