summaryrefslogtreecommitdiffstats
path: root/src/core/hle/svc.cpp
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2018-01-01 20:02:26 +0100
committerbunnei <bunneidev@gmail.com>2018-01-01 20:02:26 +0100
commitb9950cd4b0cf414ca97daa5f7578f4ca22b2669d (patch)
tree194c711f7f02e68e5137f3f7287dbd21ab834d5b /src/core/hle/svc.cpp
parentkernel: Add ObjectAddressTable class. (diff)
downloadyuzu-b9950cd4b0cf414ca97daa5f7578f4ca22b2669d.tar
yuzu-b9950cd4b0cf414ca97daa5f7578f4ca22b2669d.tar.gz
yuzu-b9950cd4b0cf414ca97daa5f7578f4ca22b2669d.tar.bz2
yuzu-b9950cd4b0cf414ca97daa5f7578f4ca22b2669d.tar.lz
yuzu-b9950cd4b0cf414ca97daa5f7578f4ca22b2669d.tar.xz
yuzu-b9950cd4b0cf414ca97daa5f7578f4ca22b2669d.tar.zst
yuzu-b9950cd4b0cf414ca97daa5f7578f4ca22b2669d.zip
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r--src/core/hle/svc.cpp40
1 files changed, 39 insertions, 1 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 133b868f2..c0e3200d4 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -122,6 +122,44 @@ static ResultCode GetProcessId(u32* process_id, Kernel::Handle process_handle) {
return RESULT_SUCCESS;
}
+/// Attempts to locks a mutex, creating it if it does not already exist
+static ResultCode LockMutex(Handle holding_thread_handle, VAddr mutex_addr,
+ Handle requesting_thread_handle) {
+ LOG_TRACE(Kernel_SVC,
+ "called holding_thread_handle=0x%08X, mutex_addr=0x%llx, "
+ "requesting_current_thread_handle=0x%08X",
+ holding_thread_handle, mutex_addr, requesting_thread_handle);
+
+ SharedPtr<Kernel::Thread> holding_thread =
+ Kernel::g_handle_table.Get<Kernel::Thread>(holding_thread_handle);
+ SharedPtr<Kernel::Thread> requesting_thread =
+ Kernel::g_handle_table.Get<Kernel::Thread>(requesting_thread_handle);
+
+ ASSERT(holding_thread);
+ ASSERT(requesting_thread);
+
+ SharedPtr<Kernel::Mutex> mutex = Kernel::g_object_address_table.Get<Kernel::Mutex>(mutex_addr);
+ if (!mutex) {
+ // Create a new mutex for the specified address if one does not already exist
+ mutex = Kernel::Mutex::Create(holding_thread, mutex_addr);
+ mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
+ }
+
+ if (mutex->ShouldWait(requesting_thread.get())) {
+ // If we cannot lock the mutex, then put the thread too sleep and trigger a reschedule
+ requesting_thread->wait_objects = {mutex};
+ mutex->AddWaitingThread(requesting_thread);
+ requesting_thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
+
+ Core::System::GetInstance().PrepareReschedule();
+ } else {
+ // The mutex is available, lock it
+ mutex->Acquire(requesting_thread.get());
+ }
+
+ return RESULT_SUCCESS;
+}
+
/// Break program execution
static void Break(u64 unk_0, u64 unk_1, u64 unk_2) {
LOG_CRITICAL(Debug_Emulated, "Emulated program broke execution!");
@@ -371,8 +409,8 @@ static const FunctionDef SVC_Table[] = {
{0x17, nullptr, "svcResetSignal"},
{0x18, nullptr, "svcWaitSynchronization"},
{0x19, nullptr, "svcCancelSynchronization"},
- {0x1A, nullptr, "svcLockMutex"},
{0x1B, nullptr, "svcUnlockMutex"},
+ {0x1A, HLE::Wrap<LockMutex>, "svcLockMutex"},
{0x1C, nullptr, "svcWaitProcessWideKeyAtomic"},
{0x1D, HLE::Wrap<SignalProcessWideKey>, "svcSignalProcessWideKey"},
{0x1E, nullptr, "svcGetSystemTick"},