7 changed files with 166 additions and 10 deletions
-
1src/core/CMakeLists.txt
-
2src/core/core.vcxproj
-
6src/core/core.vcxproj.filters
-
122src/core/hle/kernel/mutex.cpp
-
26src/core/hle/kernel/mutex.h
-
10src/core/hle/service/apt.cpp
-
9src/core/hle/svc.cpp
@ -0,0 +1,122 @@ |
|||
// Copyright 2014 Citra Emulator Project
|
|||
// Licensed under GPLv2
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include <map>
|
|||
#include <vector>
|
|||
|
|||
#include "common/common.h"
|
|||
|
|||
#include "core/hle/kernel/kernel.h"
|
|||
#include "core/hle/kernel/thread.h"
|
|||
|
|||
namespace Kernel { |
|||
|
|||
class Mutex : public Object { |
|||
public: |
|||
const char* GetTypeName() { return "Mutex"; } |
|||
|
|||
static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } |
|||
Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Mutex; } |
|||
|
|||
bool initial_locked; ///< Initial lock state when mutex was created
|
|||
bool locked; ///< Current locked state
|
|||
Handle lock_thread; ///< Handle to thread that currently has mutex
|
|||
std::vector<Handle> waiting_threads; ///< Threads that are waiting for the mutex
|
|||
}; |
|||
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|||
typedef std::multimap<Handle, Handle> MutexMap; |
|||
static MutexMap g_mutex_held_locks; |
|||
|
|||
void __MutexAcquireLock(Mutex* mutex, Handle thread) { |
|||
g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle())); |
|||
mutex->lock_thread = thread; |
|||
} |
|||
|
|||
void __MutexAcquireLock(Mutex* mutex) { |
|||
Handle thread = GetCurrentThread(); |
|||
__MutexAcquireLock(mutex, thread); |
|||
} |
|||
|
|||
void __MutexEraseLock(Mutex* mutex) { |
|||
Handle handle = mutex->GetHandle(); |
|||
auto locked = g_mutex_held_locks.equal_range(mutex->lock_thread); |
|||
for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { |
|||
if ((*iter).second == handle) { |
|||
g_mutex_held_locks.erase(iter); |
|||
break; |
|||
} |
|||
} |
|||
mutex->lock_thread = -1; |
|||
} |
|||
|
|||
bool __LockMutex(Mutex* mutex) { |
|||
// Mutex alread locked?
|
|||
if (mutex->locked) { |
|||
return false; |
|||
} |
|||
__MutexAcquireLock(mutex); |
|||
return true; |
|||
} |
|||
|
|||
bool __ReleaseMutexForThread(Mutex* mutex, Handle thread) { |
|||
__MutexAcquireLock(mutex, thread); |
|||
Kernel::ResumeThreadFromWait(thread); |
|||
return true; |
|||
} |
|||
|
|||
bool __ReleaseMutex(Mutex* mutex) { |
|||
__MutexEraseLock(mutex); |
|||
bool woke_threads = false; |
|||
auto iter = mutex->waiting_threads.begin(); |
|||
|
|||
// Find the next waiting thread for the mutex...
|
|||
while (!woke_threads && !mutex->waiting_threads.empty()) { |
|||
woke_threads |= __ReleaseMutexForThread(mutex, *iter); |
|||
mutex->waiting_threads.erase(iter); |
|||
} |
|||
// Reset mutex lock thread handle, nothing is waiting
|
|||
if (!woke_threads) { |
|||
mutex->locked = false; |
|||
mutex->lock_thread = -1; |
|||
} |
|||
return woke_threads; |
|||
} |
|||
|
|||
/**
|
|||
* Releases a mutex |
|||
* @param handle Handle to mutex to release |
|||
*/ |
|||
Result ReleaseMutex(Handle handle) { |
|||
Mutex* mutex = Kernel::g_object_pool.GetFast<Mutex>(handle); |
|||
if (!__ReleaseMutex(mutex)) { |
|||
return -1; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
/**
|
|||
* Creates a mutex |
|||
* @param handle Reference to handle for the newly created mutex |
|||
* @param initial_locked Specifies if the mutex should be locked initially |
|||
*/ |
|||
Result CreateMutex(Handle& handle, bool initial_locked) { |
|||
Mutex* mutex = new Mutex; |
|||
handle = Kernel::g_object_pool.Create(mutex); |
|||
|
|||
mutex->locked = mutex->initial_locked = initial_locked; |
|||
|
|||
// Acquire mutex with current thread if initialized as locked...
|
|||
if (mutex->locked) { |
|||
__MutexAcquireLock(mutex); |
|||
|
|||
// Otherwise, reset lock thread handle
|
|||
} else { |
|||
mutex->lock_thread = -1; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
} // namespace
|
|||
@ -0,0 +1,26 @@ |
|||
// Copyright 2014 Citra Emulator Project |
|||
// Licensed under GPLv2 |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include "common/common_types.h" |
|||
|
|||
#include "core/hle/kernel/kernel.h" |
|||
|
|||
namespace Kernel { |
|||
|
|||
/** |
|||
* Releases a mutex |
|||
* @param handle Handle to mutex to release |
|||
*/ |
|||
Result ReleaseMutex(Handle handle); |
|||
|
|||
/** |
|||
* Creates a mutex |
|||
* @param handle Reference to handle for the newly created mutex |
|||
* @param initial_locked Specifies if the mutex should be locked initially |
|||
*/ |
|||
Result CreateMutex(Handle& handle, bool initial_locked); |
|||
|
|||
} // namespace |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue