Merge pull request #160 from bunnei/svc-improvements

Several SVC fixes and improvements
This commit is contained in:
bunnei 2018-02-04 13:25:05 -08:00 committed by GitHub
commit 1ddc18454e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 24 deletions

View file

@ -15,13 +15,12 @@ ConditionVariable::ConditionVariable() {}
ConditionVariable::~ConditionVariable() {} ConditionVariable::~ConditionVariable() {}
ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr, ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr,
VAddr mutex_addr,
std::string name) { std::string name) {
SharedPtr<ConditionVariable> condition_variable(new ConditionVariable); SharedPtr<ConditionVariable> condition_variable(new ConditionVariable);
condition_variable->name = std::move(name); condition_variable->name = std::move(name);
condition_variable->guest_addr = guest_addr; condition_variable->guest_addr = guest_addr;
condition_variable->mutex_addr = mutex_addr; condition_variable->mutex_addr = 0;
// Condition variables are referenced by guest address, so track this in the kernel // Condition variables are referenced by guest address, so track this in the kernel
g_object_address_table.Insert(guest_addr, condition_variable); g_object_address_table.Insert(guest_addr, condition_variable);

View file

@ -19,12 +19,10 @@ public:
* Creates a condition variable. * Creates a condition variable.
* @param guest_addr Address of the object tracking the condition variable in guest memory. If * @param guest_addr Address of the object tracking the condition variable in guest memory. If
* specified, this condition variable will update the guest object when its state changes. * specified, this condition variable will update the guest object when its state changes.
* @param mutex_addr Optional address of a guest mutex associated with this condition variable,
* used by the OS for implementing events.
* @param name Optional name of condition variable. * @param name Optional name of condition variable.
* @return The created condition variable. * @return The created condition variable.
*/ */
static ResultVal<SharedPtr<ConditionVariable>> Create(VAddr guest_addr, VAddr mutex_addr = 0, static ResultVal<SharedPtr<ConditionVariable>> Create(VAddr guest_addr,
std::string name = "Unknown"); std::string name = "Unknown");
std::string GetTypeName() const override { std::string GetTypeName() const override {

View file

@ -14,7 +14,7 @@ namespace Kernel {
SharedMemory::SharedMemory() {} SharedMemory::SharedMemory() {}
SharedMemory::~SharedMemory() {} SharedMemory::~SharedMemory() {}
SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u64 size,
MemoryPermission permissions, MemoryPermission permissions,
MemoryPermission other_permissions, VAddr address, MemoryPermission other_permissions, VAddr address,
MemoryRegion region, std::string name) { MemoryRegion region, std::string name) {

View file

@ -39,7 +39,7 @@ public:
* linear heap. * linear heap.
* @param name Optional object name, used for debugging purposes. * @param name Optional object name, used for debugging purposes.
*/ */
static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size, static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u64 size,
MemoryPermission permissions, MemoryPermission permissions,
MemoryPermission other_permissions, VAddr address = 0, MemoryPermission other_permissions, VAddr address = 0,
MemoryRegion region = MemoryRegion::BASE, MemoryRegion region = MemoryRegion::BASE,
@ -116,7 +116,7 @@ public:
/// Offset into the backing block for this shared memory. /// Offset into the backing block for this shared memory.
size_t backing_block_offset; size_t backing_block_offset;
/// Size of the memory block. Page-aligned. /// Size of the memory block. Page-aligned.
u32 size; u64 size;
/// Permission restrictions applied to the process which created the block. /// Permission restrictions applied to the process which created the block.
MemoryPermission permissions; MemoryPermission permissions;
/// Permission restrictions applied to other processes mapping the block. /// Permission restrictions applied to other processes mapping the block.

View file

@ -263,6 +263,7 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle); SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
ASSERT(requesting_thread); ASSERT(requesting_thread);
ASSERT(requesting_thread == GetCurrentThread());
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr); SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(mutex_addr);
if (!mutex) { if (!mutex) {
@ -331,6 +332,9 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
case GetInfoType::TotalHeapUsage: case GetInfoType::TotalHeapUsage:
*result = vm_manager.GetTotalHeapUsage(); *result = vm_manager.GetTotalHeapUsage();
break; break;
case GetInfoType::IsCurrentProcessBeingDebugged:
*result = 0;
break;
case GetInfoType::RandomEntropy: case GetInfoType::RandomEntropy:
*result = 0; *result = 0;
break; break;
@ -415,8 +419,7 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
"called, shared_memory_handle=0x%08X, addr=0x%llx, size=0x%llx, permissions=0x%08X", "called, shared_memory_handle=0x%08X, addr=0x%llx, size=0x%llx, permissions=0x%08X",
shared_memory_handle, addr, size, permissions); shared_memory_handle, addr, size, permissions);
SharedPtr<SharedMemory> shared_memory = SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
Kernel::g_handle_table.Get<SharedMemory>(shared_memory_handle);
if (!shared_memory) { if (!shared_memory) {
return ERR_INVALID_HANDLE; return ERR_INVALID_HANDLE;
} }
@ -431,7 +434,7 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
case MemoryPermission::WriteExecute: case MemoryPermission::WriteExecute:
case MemoryPermission::ReadWriteExecute: case MemoryPermission::ReadWriteExecute:
case MemoryPermission::DontCare: case MemoryPermission::DontCare:
return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type, return shared_memory->Map(g_current_process.get(), addr, permissions_type,
MemoryPermission::DontCare); MemoryPermission::DontCare);
default: default:
LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
@ -612,20 +615,29 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr); mutex->name = Common::StringFromFormat("mutex-%llx", mutex_addr);
} }
ASSERT(mutex->GetOwnerHandle() == thread_handle);
SharedPtr<ConditionVariable> condition_variable = SharedPtr<ConditionVariable> condition_variable =
g_object_address_table.Get<ConditionVariable>(condition_variable_addr); g_object_address_table.Get<ConditionVariable>(condition_variable_addr);
if (!condition_variable) { if (!condition_variable) {
// Create a new condition_variable for the specified address if one does not already exist // Create a new condition_variable for the specified address if one does not already exist
condition_variable = condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap();
ConditionVariable::Create(condition_variable_addr, mutex_addr).Unwrap();
condition_variable->name = condition_variable->name =
Common::StringFromFormat("condition-variable-%llx", condition_variable_addr); Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
} }
ASSERT(condition_variable->GetAvailableCount() == 0); if (condition_variable->mutex_addr) {
ASSERT(condition_variable->mutex_addr == mutex_addr); // Previously created the ConditionVariable using WaitProcessWideKeyAtomic, verify
// everything is correct
ASSERT(condition_variable->mutex_addr == mutex_addr);
} else {
// Previously created the ConditionVariable using SignalProcessWideKey, set the mutex
// associated with it
condition_variable->mutex_addr = mutex_addr;
}
if (mutex->GetOwnerHandle()) {
// Release the mutex if the current thread is holding it
mutex->Release(thread.get());
}
auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason, auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason,
SharedPtr<Thread> thread, SharedPtr<Thread> thread,
@ -667,8 +679,6 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
CASCADE_CODE( CASCADE_CODE(
WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback)); WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback));
mutex->Release(thread.get());
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -738,13 +748,14 @@ static ResultCode SetThreadCoreMask(u64, u64, u64) {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static ResultCode CreateSharedMemory(Handle* handle, u64 sz, u32 local_permissions, static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permissions,
u32 remote_permissions) { u32 remote_permissions) {
LOG_TRACE(Kernel_SVC, "called, sz=0x%llx, localPerms=0x%08x, remotePerms=0x%08x", sz, LOG_TRACE(Kernel_SVC, "called, size=0x%llx, localPerms=0x%08x, remotePerms=0x%08x", size,
local_permissions, remote_permissions); local_permissions, remote_permissions);
auto sharedMemHandle = SharedMemory::Create( auto sharedMemHandle =
g_handle_table.Get<Process>(KernelHandle::CurrentProcess), sz, SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
(Kernel::MemoryPermission)local_permissions, (Kernel::MemoryPermission)remote_permissions); static_cast<MemoryPermission>(local_permissions),
static_cast<MemoryPermission>(remote_permissions));
CASCADE_RESULT(*handle, g_handle_table.Create(sharedMemHandle)); CASCADE_RESULT(*handle, g_handle_table.Create(sharedMemHandle));
return RESULT_SUCCESS; return RESULT_SUCCESS;