From d73d782ba7ea6f3f2dd9c4f70d34c1004397dacb Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 21:01:27 -0400 Subject: kernel: add a SyncRequest method to KernelObject for use with svcSendSyncRequest --- src/core/hle/kernel/kernel.h | 1 + src/core/hle/kernel/mutex.cpp | 5 +++++ src/core/hle/kernel/thread.cpp | 5 +++++ 3 files changed, 11 insertions(+) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 7cd79c2c4..046d583cb 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -42,6 +42,7 @@ public: virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } virtual const char *GetName() { return "[UNKNOWN KERNEL OBJECT]"; } virtual Kernel::HandleType GetHandleType() const = 0; + virtual Result SyncRequest() = 0; }; class ObjectPool : NonCopyable { diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 019efbc78..fa924404d 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -23,6 +23,11 @@ public: bool locked; ///< Current locked state Handle lock_thread; ///< Handle to thread that currently has mutex std::vector waiting_threads; ///< Threads that are waiting for the mutex + + /// Synchronize kernel object + Result SyncRequest() { + return 0; + } }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index bf4c8353c..b9dd9fac4 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -36,6 +36,11 @@ public: inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } + /// Synchronize kernel object + Result SyncRequest() { + return 0; + } + ThreadContext context; u32 status; -- cgit v1.2.3 From 3d7693f75f4a599d0da4a23dea0ec1a0578da0e1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 21:56:23 -0400 Subject: kernel: added enum for known CurrentThread and CurrentProcess handles --- src/core/hle/kernel/kernel.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 046d583cb..786d3abf3 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -11,6 +11,11 @@ typedef s32 Result; namespace Kernel { +enum KernelHandle { + CurrentThread = 0xFFFF8000, + CurrentProcess = 0xFFFF8001, +}; + enum class HandleType : u32 { Unknown = 0, Port = 1, -- cgit v1.2.3 From 58a3adcdd2eed9d31cd441186af872a0a8924e73 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 22:12:46 -0400 Subject: kernel: updated SyncRequest to take boolean thread wait result as a parameter --- src/core/hle/kernel/kernel.h | 9 ++++++++- src/core/hle/kernel/mutex.cpp | 8 ++++++-- src/core/hle/kernel/thread.cpp | 8 ++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 786d3abf3..4acc9f220 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -47,7 +47,14 @@ public: virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } virtual const char *GetName() { return "[UNKNOWN KERNEL OBJECT]"; } virtual Kernel::HandleType GetHandleType() const = 0; - virtual Result SyncRequest() = 0; + + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + virtual Result SyncRequest(bool* wait) = 0; + }; class ObjectPool : NonCopyable { diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index fa924404d..5465b7a3c 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -24,8 +24,12 @@ public: Handle lock_thread; ///< Handle to thread that currently has mutex std::vector waiting_threads; ///< Threads that are waiting for the mutex - /// Synchronize kernel object - Result SyncRequest() { + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result SyncRequest(bool* wait) { return 0; } }; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index b9dd9fac4..56c7755cf 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -36,8 +36,12 @@ public: inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } - /// Synchronize kernel object - Result SyncRequest() { + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result SyncRequest(bool* wait) { return 0; } -- cgit v1.2.3 From a432dc8f39a866b7b523235d6d94531f93bb4aa1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 22:17:49 -0400 Subject: kernel: added WaitSynchronization method to Kernel::Object --- src/core/hle/kernel/kernel.h | 7 +++++++ src/core/hle/kernel/mutex.cpp | 11 +++++++++++ src/core/hle/kernel/thread.cpp | 11 +++++++++++ 3 files changed, 29 insertions(+) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 4acc9f220..620cd2d73 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -55,6 +55,13 @@ public: */ virtual Result SyncRequest(bool* wait) = 0; + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + virtual Result WaitSynchronization(bool* wait) = 0; + }; class ObjectPool : NonCopyable { diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 5465b7a3c..17fd40acd 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -30,6 +30,17 @@ public: * @return Result of operation, 0 on success, otherwise error code */ Result SyncRequest(bool* wait) { + // TODO(bunnei): ImplementMe + return 0; + } + + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result WaitSynchronization(bool* wait) { + // TODO(bunnei): ImplementMe return 0; } }; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 56c7755cf..6e8b53eb1 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -42,6 +42,17 @@ public: * @return Result of operation, 0 on success, otherwise error code */ Result SyncRequest(bool* wait) { + // TODO(bunnei): ImplementMe + return 0; + } + + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result WaitSynchronization(bool* wait) { + // TODO(bunnei): ImplementMe return 0; } -- cgit v1.2.3 From 93cd5a069122e86605ce2c15347e9498ceda2cc4 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 22:47:47 -0400 Subject: mutex: added additional docstrings --- src/core/hle/kernel/mutex.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 871e2e562..8a9309069 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -13,6 +13,7 @@ namespace Kernel { /** * Releases a mutex * @param handle Handle to mutex to release + * @return Result of operation, 0 on success, otherwise error code */ Result ReleaseMutex(Handle handle); @@ -20,6 +21,7 @@ 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 + * @return Handle to newly created object */ Handle CreateMutex(bool initial_locked); -- cgit v1.2.3 From d493d725acfc431fcbed729bb28d9b8a19250f96 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 26 May 2014 22:49:11 -0400 Subject: mutex: removed docstring comment that is no longer relevant --- src/core/hle/kernel/mutex.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 8a9309069..4cd266725 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -19,7 +19,6 @@ 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 * @return Handle to newly created object */ -- cgit v1.2.3 From fd69fd03259b71be521aeb69d3f73761b598be8a Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 20:16:13 -0400 Subject: kernel: added event module to support creation of CTR "Event" objects --- src/core/hle/kernel/event.cpp | 91 +++++++++++++++++++++++++++++++++++++++++++ src/core/hle/kernel/event.h | 28 +++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 src/core/hle/kernel/event.cpp create mode 100644 src/core/hle/kernel/event.h (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp new file mode 100644 index 000000000..cc15ba9bc --- /dev/null +++ b/src/core/hle/kernel/event.cpp @@ -0,0 +1,91 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include + +#include "common/common.h" + +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/event.h" + +namespace Kernel { + +class Event : public Object { +public: + const char* GetTypeName() { return "Event"; } + + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } + Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } + + ResetType intitial_reset_type; ///< ResetType specified at Event initialization + ResetType reset_type; ///< Current ResetType + + bool locked; ///< Current locked state + + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result SyncRequest(bool* wait) { + // TODO(bunnei): ImplementMe + ERROR_LOG(KERNEL, "Unimplemented function Event::SyncRequest"); + return 0; + } + + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result WaitSynchronization(bool* wait) { + // TODO(bunnei): ImplementMe + *wait = locked; + if (reset_type != RESETTYPE_STICKY) { + locked = true; + } + return 0; + } +}; + +/** + * Clears an event + * @param handle Handle to event to clear + * @return Result of operation, 0 on success, otherwise error code + */ +Result ClearEvent(Handle handle) { + ERROR_LOG(KERNEL, "Unimplemented function ClearEvent"); + return 0; +} + +/** + * Creates an event + * @param handle Reference to handle for the newly created mutex + * @param reset_type ResetType describing how to create event + * @return Handle to newly created object + */ +Event* CreateEvent(Handle& handle, const ResetType reset_type) { + Event* evt = new Event; + + handle = Kernel::g_object_pool.Create(evt); + + evt->reset_type = evt->intitial_reset_type = reset_type; + evt->locked = false; + + return evt; +} + +/** + * Creates an event + * @param reset_type ResetType describing how to create event + * @return Handle to newly created object + */ +Handle CreateEvent(const ResetType reset_type) { + Handle handle; + Event* evt = CreateEvent(handle, reset_type); + return handle; +} + +} // namespace diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h new file mode 100644 index 000000000..2ef1bd65b --- /dev/null +++ b/src/core/hle/kernel/event.h @@ -0,0 +1,28 @@ +// 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" +#include "core/hle/svc.h" + +namespace Kernel { + +/** + * Clears an event + * @param handle Handle to event to clear + * @return Result of operation, 0 on success, otherwise error code + */ +Result ClearEvent(Handle handle); + +/** + * Creates an event + * @param reset_type ResetType describing how to create event + * @return Handle to newly created object + */ +Handle CreateEvent(const ResetType reset_type); + +} // namespace -- cgit v1.2.3 From beea6f054ae0bd40d1a564aa586735b81f2bf662 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 22:14:00 -0400 Subject: event: added SetEventLocked method to change status an events lock --- src/core/hle/kernel/event.cpp | 11 +++++++++++ src/core/hle/kernel/event.h | 7 +++++++ 2 files changed, 18 insertions(+) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index cc15ba9bc..e85f39f0d 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -50,6 +50,17 @@ public: } }; +/** + * Changes whether an event is locked or not + * @param handle Handle to event to change + * @param locked Boolean locked value to set event + */ +void SetEventLocked(const Handle handle, const bool locked) { + Event* evt = g_object_pool.GetFast(handle); + evt->locked = locked; + return; +} + /** * Clears an event * @param handle Handle to event to clear diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 2ef1bd65b..0bcfe00b7 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -11,6 +11,13 @@ namespace Kernel { +/** + * Changes whether an event is locked or not + * @param handle Handle to event to change + * @param locked Boolean locked value to set event + */ +void SetEventLocked(const Handle handle, const bool locked) + /** * Clears an event * @param handle Handle to event to clear -- cgit v1.2.3 From ea8627d5360eedaa10c979854ad9b4dd3b85f800 Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 22:14:38 -0400 Subject: event: fixed typos and updated CMakeLists --- src/core/hle/kernel/event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 0bcfe00b7..c1842cb88 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -16,7 +16,7 @@ namespace Kernel { * @param handle Handle to event to change * @param locked Boolean locked value to set event */ -void SetEventLocked(const Handle handle, const bool locked) +void SetEventLocked(const Handle handle, const bool locked); /** * Clears an event -- cgit v1.2.3 From 2ed6652f100fdbc5ad7d72a0602dc2c99ef79cce Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 27 May 2014 22:42:16 -0400 Subject: mutex: added preliminary SyncRequest/WaitSynchronization, added some comments/assertions --- src/core/hle/kernel/mutex.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 17fd40acd..23c064571 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -31,6 +31,7 @@ public: */ Result SyncRequest(bool* wait) { // TODO(bunnei): ImplementMe + locked = true; return 0; } @@ -41,6 +42,7 @@ public: */ Result WaitSynchronization(bool* wait) { // TODO(bunnei): ImplementMe + *wait = locked; return 0; } }; @@ -111,6 +113,9 @@ bool ReleaseMutex(Mutex* mutex) { */ Result ReleaseMutex(Handle handle) { Mutex* mutex = Kernel::g_object_pool.GetFast(handle); + + _assert_msg_(KERNEL, mutex, "ReleaseMutex tried to release a NULL mutex!"); + if (!ReleaseMutex(mutex)) { return -1; } @@ -121,6 +126,7 @@ 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 + * @return Pointer to new Mutex object */ Mutex* CreateMutex(Handle& handle, bool initial_locked) { Mutex* mutex = new Mutex; -- cgit v1.2.3 From d51c84dde22549c7413e52a682158e6da3ff1fdc Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 20:00:44 -0400 Subject: event: added support for ClearEvent, fixed a bug with CreateEvent, fixed some comments --- src/core/hle/kernel/event.cpp | 18 +++++++++++------- src/core/hle/kernel/event.h | 5 +++-- 2 files changed, 14 insertions(+), 9 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index e85f39f0d..7cb8c5142 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -54,11 +54,16 @@ public: * Changes whether an event is locked or not * @param handle Handle to event to change * @param locked Boolean locked value to set event + * @return Result of operation, 0 on success, otherwise error code */ -void SetEventLocked(const Handle handle, const bool locked) { +Result SetEventLocked(const Handle handle, const bool locked) { Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "SetEventLocked called with unknown handle=0x%08X", handle); + return -1; + } evt->locked = locked; - return; + return 0; } /** @@ -67,23 +72,22 @@ void SetEventLocked(const Handle handle, const bool locked) { * @return Result of operation, 0 on success, otherwise error code */ Result ClearEvent(Handle handle) { - ERROR_LOG(KERNEL, "Unimplemented function ClearEvent"); - return 0; + return SetEventLocked(handle, true); } /** * Creates an event * @param handle Reference to handle for the newly created mutex * @param reset_type ResetType describing how to create event - * @return Handle to newly created object + * @return Newly created Event object */ Event* CreateEvent(Handle& handle, const ResetType reset_type) { Event* evt = new Event; handle = Kernel::g_object_pool.Create(evt); + evt->locked = true; evt->reset_type = evt->intitial_reset_type = reset_type; - evt->locked = false; return evt; } @@ -91,7 +95,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { /** * Creates an event * @param reset_type ResetType describing how to create event - * @return Handle to newly created object + * @return Handle to newly created Event object */ Handle CreateEvent(const ResetType reset_type) { Handle handle; diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index c1842cb88..b1d2c6ad1 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -15,8 +15,9 @@ namespace Kernel { * Changes whether an event is locked or not * @param handle Handle to event to change * @param locked Boolean locked value to set event + * @return Result of operation, 0 on success, otherwise error code */ -void SetEventLocked(const Handle handle, const bool locked); +Result SetEventLocked(const Handle handle, const bool locked); /** * Clears an event @@ -28,7 +29,7 @@ Result ClearEvent(Handle handle); /** * Creates an event * @param reset_type ResetType describing how to create event - * @return Handle to newly created object + * @return Handle to newly created Event object */ Handle CreateEvent(const ResetType reset_type); -- cgit v1.2.3 From d8a2c8c6579b78d9c61abe544cfaea651238130c Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 29 May 2014 23:31:01 -0400 Subject: mutex: fixed typo in ReleaseMutex --- src/core/hle/kernel/mutex.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 23c064571..5ac88cd85 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -8,6 +8,7 @@ #include "common/common.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/mutex.h" #include "core/hle/kernel/thread.h" namespace Kernel { @@ -92,10 +93,11 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread) { bool ReleaseMutex(Mutex* mutex) { MutexEraseLock(mutex); bool woke_threads = false; - auto iter = mutex->waiting_threads.begin(); + std::vector::iterator iter; // Find the next waiting thread for the mutex... while (!woke_threads && !mutex->waiting_threads.empty()) { + iter = mutex->waiting_threads.begin(); woke_threads |= ReleaseMutexForThread(mutex, *iter); mutex->waiting_threads.erase(iter); } -- cgit v1.2.3 From f7cececc5ca82f97a9fb1ab50c62fd9e3a49ccdc Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 10:33:55 -0400 Subject: event: added a hackish ability to set an event as "locked" to its current state, cleaned up some comments --- src/core/hle/kernel/event.cpp | 28 ++++++++++++++++++++++++---- src/core/hle/kernel/event.h | 8 ++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 7cb8c5142..e84d0b49e 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -23,6 +23,7 @@ public: ResetType reset_type; ///< Current ResetType bool locked; ///< Current locked state + bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) /** * Synchronize kernel object @@ -31,7 +32,7 @@ public: */ Result SyncRequest(bool* wait) { // TODO(bunnei): ImplementMe - ERROR_LOG(KERNEL, "Unimplemented function Event::SyncRequest"); + ERROR_LOG(KERNEL, "(UMIMPLEMENTED) call"); return 0; } @@ -43,7 +44,7 @@ public: Result WaitSynchronization(bool* wait) { // TODO(bunnei): ImplementMe *wait = locked; - if (reset_type != RESETTYPE_STICKY) { + if (reset_type != RESETTYPE_STICKY && !permanent_locked) { locked = true; } return 0; @@ -59,10 +60,28 @@ public: Result SetEventLocked(const Handle handle, const bool locked) { Event* evt = g_object_pool.GetFast(handle); if (!evt) { - ERROR_LOG(KERNEL, "SetEventLocked called with unknown handle=0x%08X", handle); + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); return -1; } - evt->locked = locked; + if (!evt->permanent_locked) { + evt->locked = locked; + } + return 0; +} + +/** + * Hackish function to set an events permanent lock state, used to pass through synch blocks + * @param handle Handle to event to change + * @param permanent_locked Boolean permanent locked value to set event + * @return Result of operation, 0 on success, otherwise error code + */ +Result SetPermanentLock(Handle handle, const bool permanent_locked) { + Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); + return -1; + } + evt->permanent_locked = permanent_locked; return 0; } @@ -87,6 +106,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { handle = Kernel::g_object_pool.Create(evt); evt->locked = true; + evt->permanent_locked = false; evt->reset_type = evt->intitial_reset_type = reset_type; return evt; diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index b1d2c6ad1..f91a72c1c 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -19,6 +19,14 @@ namespace Kernel { */ Result SetEventLocked(const Handle handle, const bool locked); +/** + * Hackish function to set an events permanent lock state, used to pass through synch blocks + * @param handle Handle to event to change + * @param permanent_locked Boolean permanent locked value to set event + * @return Result of operation, 0 on success, otherwise error code + */ +Result SetPermanentLock(Handle handle, const bool permanent_locked); + /** * Clears an event * @param handle Handle to event to clear -- cgit v1.2.3 From ba98e25e979b1aedaa9b917a7db8f710c83c073c Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 10:35:42 -0400 Subject: thread: updated Reschedule to sit at a synchronization barrier when no other threads are ready for execution --- src/core/hle/kernel/thread.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 6e8b53eb1..d1e13c949 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -323,11 +323,29 @@ void Reschedule() { Thread* prev = GetCurrentThread(); Thread* next = NextThread(); if (next > 0) { + INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); + SwitchContext(next); // Hack - automatically change previous thread (which would have been in "wait" state) to // "ready" state, so that we can immediately resume to it when new thread yields. FixMe to // actually wait for whatever event it is supposed to be waiting on. + + ChangeReadyState(prev, true); + } else { + INFO_LOG(KERNEL, "no ready threads, staying on 0x%08X", prev->GetHandle()); + + // Hack - no other threads are available, so decrement current PC to the last instruction, + // and then resume current thread. This should always be called on a blocking instruction + // (e.g. svcWaitSynchronization), and the result should be that the instruction is repeated + // until it no longer blocks. + + // TODO(bunnei): A better solution: Have the CPU switch to an idle thread + + ThreadContext ctx; + SaveContext(ctx); + ctx.pc -= 4; + LoadContext(ctx); ChangeReadyState(prev, true); } } -- cgit v1.2.3 From 10447d1f4831b495d7bef7711681ddd548f847a6 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 21:42:50 -0400 Subject: kernel: changed main thread priority to default, updated Kernel::Reschedule to use PrepareReschedule --- src/core/hle/kernel/kernel.cpp | 3 ++- src/core/hle/kernel/kernel.h | 1 + src/core/hle/kernel/thread.cpp | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index de80de893..c0c0fa177 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -14,6 +14,7 @@ namespace Kernel { +Handle g_main_thread = 0; ObjectPool g_object_pool; ObjectPool::ObjectPool() { @@ -150,7 +151,7 @@ bool LoadExec(u32 entry_point) { Core::g_app_core->SetPC(entry_point); // 0x30 is the typical main thread priority I've seen used so far - Handle thread = Kernel::SetupMainThread(0x30); + g_main_thread = Kernel::SetupMainThread(THREADPRIO_DEFAULT); return true; } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 620cd2d73..2192df16f 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -163,6 +163,7 @@ private: }; extern ObjectPool g_object_pool; +extern Handle g_main_thread; /** * Loads executable stored at specified address diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index d1e13c949..f2094f7a7 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -285,11 +285,11 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 HLE::EatCycles(32000); + CallThread(t); + // This won't schedule to the new thread, but it may to one woken from eating cycles. // Technically, this should not eat all at once, and reschedule in the middle, but that's hard. - HLE::ReSchedule("thread created"); - - CallThread(t); + //HLE::Reschedule("thread created"); return handle; } -- cgit v1.2.3 From 3fb31fbc57fd1d537db79af898ef26c92b0e0867 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 22:12:54 -0400 Subject: svc: added GetThreadPriority and SetThreadPriority, added (incomplete) DuplicateHandle support --- src/core/hle/kernel/thread.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++ src/core/hle/kernel/thread.h | 6 ++++++ 2 files changed, 51 insertions(+) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index f2094f7a7..c84fdf91d 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -294,6 +294,51 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 return handle; } +/// Get the priority of the thread specified by handle +u32 GetThreadPriority(const Handle handle) { + Thread* thread = g_object_pool.GetFast(handle); + _assert_msg_(KERNEL, thread, "called, but thread is NULL!"); + return thread->current_priority; +} + +/// Set the priority of the thread specified by handle +Result SetThreadPriority(Handle handle, s32 priority) { + Thread* thread = NULL; + if (!handle) { + thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? + } else { + thread = g_object_pool.GetFast(handle); + } + _assert_msg_(KERNEL, thread, "called, but thread is NULL!"); + + // If priority is invalid, clamp to valid range + if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { + s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); + WARN_LOG(KERNEL, "invalid priority=0x%08X, clamping to %08X", priority, new_priority); + // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm + // validity of this + priority = new_priority; + } + + // Change thread priority + s32 old = thread->current_priority; + g_thread_ready_queue.remove(old, handle); + thread->current_priority = priority; + g_thread_ready_queue.prepare(thread->current_priority); + + // Change thread status to "ready" and push to ready queue + if (thread->IsRunning()) { + thread->status = (thread->status & ~THREADSTATUS_RUNNING) | THREADSTATUS_READY; + } + if (thread->IsReady()) { + g_thread_ready_queue.push_back(thread->current_priority, handle); + } + + HLE::EatCycles(450); + + return 0; +} + /// Sets up the primary application thread Handle SetupMainThread(s32 priority, int stack_size) { Handle handle; diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 9628f165d..094c8d43e 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -65,6 +65,12 @@ Handle GetCurrentThreadHandle(); /// Put current thread in a wait state - on WaitSynchronization void WaitThread_Synchronization(); +/// Get the priority of the thread specified by handle +u32 GetThreadPriority(const Handle handle); + +/// Set the priority of the thread specified by handle +Result SetThreadPriority(Handle handle, s32 priority); + /// Initialize threading void ThreadingInit(); -- cgit v1.2.3 From 8c0f02a70cfb3eb9a7a334f3f93345bc64e383b6 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 2 Jun 2014 20:36:58 -0400 Subject: kernel: moved position of * for GetTypeName and GetName --- src/core/hle/kernel/kernel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 2192df16f..c26071276 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -44,8 +44,8 @@ class Object : NonCopyable { public: virtual ~Object() {} Handle GetHandle() const { return handle; } - virtual const char *GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } - virtual const char *GetName() { return "[UNKNOWN KERNEL OBJECT]"; } + virtual const char* GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } + virtual const char* GetName() { return "[UNKNOWN KERNEL OBJECT]"; } virtual Kernel::HandleType GetHandleType() const = 0; /** -- cgit v1.2.3 From b78aff85857a3a356fdf11e1dbc4e5f52490676e Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 2 Jun 2014 20:38:34 -0400 Subject: svc: added optional name field to Event and Mutex (used for debugging) --- src/core/hle/kernel/event.cpp | 11 ++++++++--- src/core/hle/kernel/event.h | 3 ++- src/core/hle/kernel/mutex.cpp | 12 +++++++++--- src/core/hle/kernel/mutex.h | 3 ++- 4 files changed, 21 insertions(+), 8 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index e84d0b49e..70e50115d 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -15,6 +15,7 @@ namespace Kernel { class Event : public Object { public: const char* GetTypeName() { return "Event"; } + const char* GetName() { return name.c_str(); } static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } @@ -24,6 +25,7 @@ public: bool locked; ///< Current locked state bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) + std::string name; ///< Name of event (optional) /** * Synchronize kernel object @@ -98,9 +100,10 @@ Result ClearEvent(Handle handle) { * Creates an event * @param handle Reference to handle for the newly created mutex * @param reset_type ResetType describing how to create event + * @param name Optional name of event * @return Newly created Event object */ -Event* CreateEvent(Handle& handle, const ResetType reset_type) { +Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string name) { Event* evt = new Event; handle = Kernel::g_object_pool.Create(evt); @@ -108,6 +111,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { evt->locked = true; evt->permanent_locked = false; evt->reset_type = evt->intitial_reset_type = reset_type; + evt->name = name; return evt; } @@ -115,11 +119,12 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type) { /** * Creates an event * @param reset_type ResetType describing how to create event + * @param name Optional name of event * @return Handle to newly created Event object */ -Handle CreateEvent(const ResetType reset_type) { +Handle CreateEvent(const ResetType reset_type, const std::string name) { Handle handle; - Event* evt = CreateEvent(handle, reset_type); + Event* evt = CreateEvent(handle, reset_type, name); return handle; } diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index f91a72c1c..eed09f0e3 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -37,8 +37,9 @@ Result ClearEvent(Handle handle); /** * Creates an event * @param reset_type ResetType describing how to create event + * @param name Optional name of event * @return Handle to newly created Event object */ -Handle CreateEvent(const ResetType reset_type); +Handle CreateEvent(const ResetType reset_type, const std::string name="Unknown"); } // namespace diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 5ac88cd85..7e60fbfe0 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -16,6 +16,7 @@ namespace Kernel { class Mutex : public Object { public: const char* GetTypeName() { return "Mutex"; } + const char* GetName() { return name.c_str(); } static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Mutex; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Mutex; } @@ -24,6 +25,7 @@ public: bool locked; ///< Current locked state Handle lock_thread; ///< Handle to thread that currently has mutex std::vector waiting_threads; ///< Threads that are waiting for the mutex + std::string name; ///< Name of mutex (optional) /** * Synchronize kernel object @@ -128,13 +130,15 @@ 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 + * @param name Optional name of mutex * @return Pointer to new Mutex object */ -Mutex* CreateMutex(Handle& handle, bool initial_locked) { +Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string name) { Mutex* mutex = new Mutex; handle = Kernel::g_object_pool.Create(mutex); mutex->locked = mutex->initial_locked = initial_locked; + mutex->name = name; // Acquire mutex with current thread if initialized as locked... if (mutex->locked) { @@ -150,10 +154,12 @@ Mutex* CreateMutex(Handle& handle, bool initial_locked) { /** * Creates a mutex * @param initial_locked Specifies if the mutex should be locked initially + * @param name Optional name of mutex + * @return Handle to newly created object */ -Handle CreateMutex(bool initial_locked) { +Handle CreateMutex(bool initial_locked, std::string name) { Handle handle; - Mutex* mutex = CreateMutex(handle, initial_locked); + Mutex* mutex = CreateMutex(handle, initial_locked, name); return handle; } diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 4cd266725..fde5549fa 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -20,8 +20,9 @@ Result ReleaseMutex(Handle handle); /** * Creates a mutex * @param initial_locked Specifies if the mutex should be locked initially + * @param name Optional name of mutex * @return Handle to newly created object */ -Handle CreateMutex(bool initial_locked); +Handle CreateMutex(bool initial_locked, const std::string name="Unknown"); } // namespace -- cgit v1.2.3 From ce1c56127886fa746b2bda95bf162bf67878e482 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 00:20:58 -0400 Subject: kernel: changed current default thread priority back to 0x30 - I think this is more correct --- src/core/hle/kernel/kernel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index c0c0fa177..9d5991c37 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -151,7 +151,7 @@ bool LoadExec(u32 entry_point) { Core::g_app_core->SetPC(entry_point); // 0x30 is the typical main thread priority I've seen used so far - g_main_thread = Kernel::SetupMainThread(THREADPRIO_DEFAULT); + g_main_thread = Kernel::SetupMainThread(0x30); return true; } -- cgit v1.2.3 From f5c7c1543434e25a215286e6db5e71c055ba48cf Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 22:35:36 -0400 Subject: 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. --- src/core/hle/kernel/event.cpp | 71 ++++++++++++++++++++---- src/core/hle/kernel/event.h | 7 +++ src/core/hle/kernel/mutex.cpp | 5 ++ src/core/hle/kernel/thread.cpp | 121 ++++++++++++++++++++++++++++++----------- src/core/hle/kernel/thread.h | 9 ++- 5 files changed, 165 insertions(+), 48 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 70e50115d..787e9f5fd 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -3,12 +3,14 @@ // Refer to the license.txt file included. #include +#include #include #include "common/common.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/event.h" +#include "core/hle/kernel/thread.h" namespace Kernel { @@ -20,12 +22,13 @@ public: static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } - ResetType intitial_reset_type; ///< ResetType specified at Event initialization - ResetType reset_type; ///< Current ResetType + ResetType intitial_reset_type; ///< ResetType specified at Event initialization + ResetType reset_type; ///< Current ResetType - bool locked; ///< Current locked state - bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) - std::string name; ///< Name of event (optional) + bool locked; ///< Event signal wait + bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) + std::vector waiting_threads; ///< Threads that are waiting for the event + std::string name; ///< Name of event (optional) /** * Synchronize kernel object @@ -44,8 +47,14 @@ public: * @return Result of operation, 0 on success, otherwise error code */ Result WaitSynchronization(bool* wait) { - // TODO(bunnei): ImplementMe *wait = locked; + if (locked) { + Handle thread = GetCurrentThreadHandle(); + if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { + waiting_threads.push_back(thread); + } + Kernel::WaitCurrentThread(WAITTYPE_EVENT); + } if (reset_type != RESETTYPE_STICKY && !permanent_locked) { locked = true; } @@ -53,6 +62,22 @@ public: } }; +/** + * Hackish function to set an events permanent lock state, used to pass through synch blocks + * @param handle Handle to event to change + * @param permanent_locked Boolean permanent locked value to set event + * @return Result of operation, 0 on success, otherwise error code + */ +Result SetPermanentLock(Handle handle, const bool permanent_locked) { + Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); + return -1; + } + evt->permanent_locked = permanent_locked; + return 0; +} + /** * Changes whether an event is locked or not * @param handle Handle to event to change @@ -72,18 +97,32 @@ Result SetEventLocked(const Handle handle, const bool locked) { } /** - * Hackish function to set an events permanent lock state, used to pass through synch blocks - * @param handle Handle to event to change - * @param permanent_locked Boolean permanent locked value to set event + * Signals an event + * @param handle Handle to event to signal * @return Result of operation, 0 on success, otherwise error code */ -Result SetPermanentLock(Handle handle, const bool permanent_locked) { +Result SignalEvent(const Handle handle) { Event* evt = g_object_pool.GetFast(handle); if (!evt) { ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); return -1; } - evt->permanent_locked = permanent_locked; + // Resume threads waiting for event to signal + bool event_caught = false; + for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { + ResumeThreadFromWait( evt->waiting_threads[i]); + + // If any thread is signalled awake by this event, assume the event was "caught" and reset + // the event. This will result in the next thread waiting on the event to block. Otherwise, + // the event will not be reset, and the next thread to call WaitSynchronization on it will + // not block. Not sure if this is correct behavior, but it seems to work. + event_caught = true; + } + evt->waiting_threads.clear(); + + if (!evt->permanent_locked) { + evt->locked = event_caught; + } return 0; } @@ -93,7 +132,15 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) { * @return Result of operation, 0 on success, otherwise error code */ Result ClearEvent(Handle handle) { - return SetEventLocked(handle, true); + Event* evt = g_object_pool.GetFast(handle); + if (!evt) { + ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); + return -1; + } + if (!evt->permanent_locked) { + evt->locked = true; + } + return 0; } /** diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index eed09f0e3..3527b01fd 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -27,6 +27,13 @@ Result SetEventLocked(const Handle handle, const bool locked); */ Result SetPermanentLock(Handle handle, const bool permanent_locked); +/** + * Signals an event + * @param handle Handle to event to signal + * @return Result of operation, 0 on success, otherwise error code + */ +Result SignalEvent(const Handle handle); + /** * Clears an event * @param handle Handle to event to clear diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 7e60fbfe0..133c43079 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -46,6 +46,11 @@ public: Result WaitSynchronization(bool* wait) { // TODO(bunnei): ImplementMe *wait = locked; + + if (locked) { + Kernel::WaitCurrentThread(WAITTYPE_MUTEX); + } + return 0; } }; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index c84fdf91d..d372df709 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -52,7 +53,14 @@ public: * @return Result of operation, 0 on success, otherwise error code */ Result WaitSynchronization(bool* wait) { - // TODO(bunnei): ImplementMe + if (status != THREADSTATUS_DORMANT) { + Handle thread = GetCurrentThreadHandle(); + if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { + waiting_threads.push_back(thread); + } + WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); + *wait = true; + } return 0; } @@ -69,6 +77,9 @@ public: s32 processor_id; WaitType wait_type; + Handle wait_handle; + + std::vector waiting_threads; char name[Kernel::MAX_NAME_LENGTH + 1]; }; @@ -82,7 +93,6 @@ Common::ThreadQueueList g_thread_ready_queue; Handle g_current_thread_handle; Thread* g_current_thread; - /// Gets the current thread inline Thread* GetCurrentThread() { return g_current_thread; @@ -114,15 +124,15 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { memset(&t->context, 0, sizeof(ThreadContext)); t->context.cpu_registers[0] = arg; - t->context.pc = t->entry_point; + t->context.pc = t->context.cpu_registers[15] = t->entry_point; t->context.sp = t->stack_top; t->context.cpsr = 0x1F; // Usermode if (t->current_priority < lowest_priority) { t->current_priority = t->initial_priority; } - t->wait_type = WAITTYPE_NONE; + t->wait_handle = 0; } /// Change a thread to "ready" state @@ -142,6 +152,43 @@ void ChangeReadyState(Thread* t, bool ready) { } } +/// Verify that a thread has not been released from waiting +inline bool VerifyWait(const Handle& thread, WaitType type, Handle handle) { + Handle wait_id = 0; + Thread *t = g_object_pool.GetFast(thread); + if (t) { + if (type == t->wait_type && handle == t->wait_handle) { + return true; + } + } else { + ERROR_LOG(KERNEL, "thread 0x%08X does not exist", thread); + } + return false; +} + +/// Stops the current thread +void StopThread(Handle thread, const char* reason) { + u32 error; + Thread *t = g_object_pool.Get(thread, error); + if (t) { + ChangeReadyState(t, false); + t->status = THREADSTATUS_DORMANT; + for (size_t i = 0; i < t->waiting_threads.size(); ++i) { + const Handle waiting_thread = t->waiting_threads[i]; + if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, thread)) { + ResumeThreadFromWait(waiting_thread); + } + } + t->waiting_threads.clear(); + + // Stopped threads are never waiting. + t->wait_type = WAITTYPE_NONE; + t->wait_handle = 0; + } else { + ERROR_LOG(KERNEL, "thread 0x%08X does not exist", thread); + } +} + /// Changes a threads state void ChangeThreadState(Thread* t, ThreadStatus new_status) { if (!t || t->status == new_status) { @@ -152,7 +199,7 @@ void ChangeThreadState(Thread* t, ThreadStatus new_status) { if (new_status == THREADSTATUS_WAIT) { if (t->wait_type == WAITTYPE_NONE) { - printf("ERROR: Waittype none not allowed here\n"); + ERROR_LOG(KERNEL, "Waittype none not allowed"); } } } @@ -207,9 +254,10 @@ Thread* NextThread() { } /// Puts the current thread in the wait state for the given type -void WaitCurrentThread(WaitType wait_type) { +void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { Thread* t = GetCurrentThread(); t->wait_type = wait_type; + t->wait_handle = wait_handle; ChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND))); } @@ -225,6 +273,22 @@ void ResumeThreadFromWait(Handle handle) { } } +/// Prints the thread queue for debugging purposes +void DebugThreadQueue() { + Thread* thread = GetCurrentThread(); + if (!thread) { + return; + } + INFO_LOG(KERNEL, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThreadHandle()); + for (u32 i = 0; i < g_thread_queue.size(); i++) { + Handle handle = g_thread_queue[i]; + s32 priority = g_thread_ready_queue.contains(handle); + if (priority != -1) { + INFO_LOG(KERNEL, "0x%02X 0x%08X", priority, handle); + } + } +} + /// Creates a new thread Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority, s32 processor_id, u32 stack_top, int stack_size) { @@ -233,12 +297,12 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio "CreateThread priority=%d, outside of allowable range!", priority) Thread* t = new Thread; - + handle = Kernel::g_object_pool.Create(t); - + g_thread_queue.push_back(handle); g_thread_ready_queue.prepare(priority); - + t->status = THREADSTATUS_DORMANT; t->entry_point = entry_point; t->stack_top = stack_top; @@ -246,16 +310,18 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio t->initial_priority = t->current_priority = priority; t->processor_id = processor_id; t->wait_type = WAITTYPE_NONE; - + t->wait_handle = 0; + strncpy(t->name, name, Kernel::MAX_NAME_LENGTH); t->name[Kernel::MAX_NAME_LENGTH] = '\0'; - + return t; } /// Creates a new thread - wrapper for external user Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s32 processor_id, u32 stack_top, int stack_size) { + if (name == NULL) { ERROR_LOG(KERNEL, "CreateThread(): NULL name"); return -1; @@ -289,7 +355,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 // This won't schedule to the new thread, but it may to one woken from eating cycles. // Technically, this should not eat all at once, and reschedule in the middle, but that's hard. - //HLE::Reschedule("thread created"); + //HLE::Reschedule(__func__); return handle; } @@ -363,35 +429,24 @@ Handle SetupMainThread(s32 priority, int stack_size) { return handle; } + /// Reschedules to the next available thread (call after current thread is suspended) void Reschedule() { Thread* prev = GetCurrentThread(); Thread* next = NextThread(); + HLE::g_reschedule = false; if (next > 0) { INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); - + SwitchContext(next); - // Hack - automatically change previous thread (which would have been in "wait" state) to - // "ready" state, so that we can immediately resume to it when new thread yields. FixMe to - // actually wait for whatever event it is supposed to be waiting on. - - ChangeReadyState(prev, true); - } else { - INFO_LOG(KERNEL, "no ready threads, staying on 0x%08X", prev->GetHandle()); - - // Hack - no other threads are available, so decrement current PC to the last instruction, - // and then resume current thread. This should always be called on a blocking instruction - // (e.g. svcWaitSynchronization), and the result should be that the instruction is repeated - // until it no longer blocks. - - // TODO(bunnei): A better solution: Have the CPU switch to an idle thread - - ThreadContext ctx; - SaveContext(ctx); - ctx.pc -= 4; - LoadContext(ctx); - ChangeReadyState(prev, true); + // Hack - There is no mechanism yet to waken the primary thread if it has been put to sleep + // by a simulated VBLANK thread switch. So, we'll just immediately set it to "ready" again. + // This results in the current thread yielding on a VBLANK once, and then it will be + // immediately placed back in the queue for execution. + if (prev->wait_type == WAITTYPE_VBLANK) { + ResumeThreadFromWait(prev->GetHandle()); + } } } diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 094c8d43e..04914ba90 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -34,7 +34,7 @@ enum WaitType { WAITTYPE_NONE, WAITTYPE_SLEEP, WAITTYPE_SEMA, - WAITTYPE_EVENTFLAG, + WAITTYPE_EVENT, WAITTYPE_THREADEND, WAITTYPE_VBLANK, WAITTYPE_MUTEX, @@ -53,8 +53,8 @@ Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); /// Reschedules to the next available thread (call after current thread is suspended) void Reschedule(); -/// Puts the current thread in the wait state for the given type -void WaitCurrentThread(WaitType wait_type); +/// Stops the current thread +void StopThread(Handle thread, const char* reason); /// Resumes a thread from waiting by marking it as "ready" void ResumeThreadFromWait(Handle handle); @@ -62,6 +62,9 @@ void ResumeThreadFromWait(Handle handle); /// Gets the current thread handle Handle GetCurrentThreadHandle(); +/// Puts the current thread in the wait state for the given type +void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle()); + /// Put current thread in a wait state - on WaitSynchronization void WaitThread_Synchronization(); -- cgit v1.2.3 From aae9fcf4a4071a408af10ca1c72180cdc04687b8 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 23:13:28 -0400 Subject: Kernel: Made SyncRequest not pure virtual, with a default implementation of error (as this is not required for all kernel objects) --- src/core/hle/kernel/event.cpp | 11 ----------- src/core/hle/kernel/kernel.h | 6 ++++-- src/core/hle/kernel/thread.cpp | 10 ---------- 3 files changed, 4 insertions(+), 23 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 787e9f5fd..36c7dcbc8 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -30,17 +30,6 @@ public: std::vector waiting_threads; ///< Threads that are waiting for the event std::string name; ///< Name of event (optional) - /** - * Synchronize kernel object - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result SyncRequest(bool* wait) { - // TODO(bunnei): ImplementMe - ERROR_LOG(KERNEL, "(UMIMPLEMENTED) call"); - return 0; - } - /** * Wait for kernel object to synchronize * @param wait Boolean wait set if current thread should wait as a result of sync operation diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index c26071276..f1bb78801 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -53,7 +53,10 @@ public: * @param wait Boolean wait set if current thread should wait as a result of sync operation * @return Result of operation, 0 on success, otherwise error code */ - virtual Result SyncRequest(bool* wait) = 0; + virtual Result SyncRequest(bool* wait) { + ERROR_LOG(KERNEL, "(UNIMPLEMENTED)"); + return -1; + } /** * Wait for kernel object to synchronize @@ -61,7 +64,6 @@ public: * @return Result of operation, 0 on success, otherwise error code */ virtual Result WaitSynchronization(bool* wait) = 0; - }; class ObjectPool : NonCopyable { diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index d372df709..180c14928 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -37,16 +37,6 @@ public: inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } - /** - * Synchronize kernel object - * @param wait Boolean wait set if current thread should wait as a result of sync operation - * @return Result of operation, 0 on success, otherwise error code - */ - Result SyncRequest(bool* wait) { - // TODO(bunnei): ImplementMe - return 0; - } - /** * Wait for kernel object to synchronize * @param wait Boolean wait set if current thread should wait as a result of sync operation -- cgit v1.2.3 From b774b8b04e50ad709381506a80e881a1a1471b0f Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 5 Jun 2014 23:19:55 -0400 Subject: Thread: Fixed bug with ResetThread where cpu_registers[15] was being incorrectly set --- src/core/hle/kernel/thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 180c14928..6196c352c 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -114,7 +114,7 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { memset(&t->context, 0, sizeof(ThreadContext)); t->context.cpu_registers[0] = arg; - t->context.pc = t->context.cpu_registers[15] = t->entry_point; + t->context.pc = t->context.reg_15 = t->entry_point; t->context.sp = t->stack_top; t->context.cpsr = 0x1F; // Usermode -- cgit v1.2.3 From 8cac527c943253a9471849d17b1520f4762fbb5c Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:10:50 -0400 Subject: Kernel: Updated several member functions to be const --- src/core/hle/kernel/event.cpp | 6 +++--- src/core/hle/kernel/kernel.h | 4 ++-- src/core/hle/kernel/mutex.cpp | 6 +++--- src/core/hle/kernel/thread.cpp | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 36c7dcbc8..72a190f8c 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -16,10 +16,10 @@ namespace Kernel { class Event : public Object { public: - const char* GetTypeName() { return "Event"; } - const char* GetName() { return name.c_str(); } + const char* GetTypeName() const { return "Event"; } + const char* GetName() const { return name.c_str(); } - static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } ResetType intitial_reset_type; ///< ResetType specified at Event initialization diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index f1bb78801..d2d624f6d 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -44,8 +44,8 @@ class Object : NonCopyable { public: virtual ~Object() {} Handle GetHandle() const { return handle; } - virtual const char* GetTypeName() { return "[BAD KERNEL OBJECT TYPE]"; } - virtual const char* GetName() { return "[UNKNOWN KERNEL OBJECT]"; } + virtual const char* GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } + virtual const char* GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } virtual Kernel::HandleType GetHandleType() const = 0; /** diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 133c43079..9d909ea01 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -15,10 +15,10 @@ namespace Kernel { class Mutex : public Object { public: - const char* GetTypeName() { return "Mutex"; } - const char* GetName() { return name.c_str(); } + const char* GetTypeName() const { return "Mutex"; } + const char* GetName() const { return name.c_str(); } - static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::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 diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 6196c352c..da93e006c 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -25,10 +25,10 @@ namespace Kernel { class Thread : public Kernel::Object { public: - const char* GetName() { return name; } - const char* GetTypeName() { return "Thread"; } + const char* GetName() const { return name; } + const char* GetTypeName() const { return "Thread"; } - static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; } + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Thread; } Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Thread; } inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; } -- cgit v1.2.3 From 780a443b08454b4bf0eb7f5416e361ce95cc7584 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:13:50 -0400 Subject: Mutex: Moved ReleaseMutex iterator declaration to be inside while loop. --- src/core/hle/kernel/mutex.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 9d909ea01..eee7c4935 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -100,11 +100,10 @@ bool ReleaseMutexForThread(Mutex* mutex, Handle thread) { bool ReleaseMutex(Mutex* mutex) { MutexEraseLock(mutex); bool woke_threads = false; - std::vector::iterator iter; // Find the next waiting thread for the mutex... while (!woke_threads && !mutex->waiting_threads.empty()) { - iter = mutex->waiting_threads.begin(); + std::vector::iterator iter = mutex->waiting_threads.begin(); woke_threads |= ReleaseMutexForThread(mutex, *iter); mutex->waiting_threads.erase(iter); } -- cgit v1.2.3 From d7363322c79d6e7598e0d80cf1af9c05b652cecb Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:19:40 -0400 Subject: HLE: Updated various handle debug assertions to be more clear. --- src/core/hle/kernel/mutex.cpp | 2 +- src/core/hle/kernel/thread.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index eee7c4935..ee7507edf 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -122,7 +122,7 @@ bool ReleaseMutex(Mutex* mutex) { Result ReleaseMutex(Handle handle) { Mutex* mutex = Kernel::g_object_pool.GetFast(handle); - _assert_msg_(KERNEL, mutex, "ReleaseMutex tried to release a NULL mutex!"); + _assert_msg_(KERNEL, (mutex != NULL), "ReleaseMutex tried to release a NULL mutex!"); if (!ReleaseMutex(mutex)) { return -1; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index da93e006c..5fdb4fbe6 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -353,7 +353,7 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 /// Get the priority of the thread specified by handle u32 GetThreadPriority(const Handle handle) { Thread* thread = g_object_pool.GetFast(handle); - _assert_msg_(KERNEL, thread, "called, but thread is NULL!"); + _assert_msg_(KERNEL, (thread != NULL), "called, but thread is NULL!"); return thread->current_priority; } @@ -365,7 +365,7 @@ Result SetThreadPriority(Handle handle, s32 priority) { } else { thread = g_object_pool.GetFast(handle); } - _assert_msg_(KERNEL, thread, "called, but thread is NULL!"); + _assert_msg_(KERNEL, (thread != NULL), "called, but thread is NULL!"); // If priority is invalid, clamp to valid range if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { -- cgit v1.2.3 From 5365ca157d5cb81c5cba3922036839f3c58e85ba Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:23:33 -0400 Subject: Kernel: Updated various kernel function "name" arguments to be const references. --- src/core/hle/kernel/event.cpp | 4 ++-- src/core/hle/kernel/event.h | 2 +- src/core/hle/kernel/mutex.cpp | 4 ++-- src/core/hle/kernel/mutex.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 72a190f8c..3a522c190 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -139,7 +139,7 @@ Result ClearEvent(Handle handle) { * @param name Optional name of event * @return Newly created Event object */ -Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string name) { +Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) { Event* evt = new Event; handle = Kernel::g_object_pool.Create(evt); @@ -158,7 +158,7 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string * @param name Optional name of event * @return Handle to newly created Event object */ -Handle CreateEvent(const ResetType reset_type, const std::string name) { +Handle CreateEvent(const ResetType reset_type, const std::string& name) { Handle handle; Event* evt = CreateEvent(handle, reset_type, name); return handle; diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 3527b01fd..c39b33180 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -47,6 +47,6 @@ Result ClearEvent(Handle handle); * @param name Optional name of event * @return Handle to newly created Event object */ -Handle CreateEvent(const ResetType reset_type, const std::string name="Unknown"); +Handle CreateEvent(const ResetType reset_type, const std::string& name="Unknown"); } // namespace diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index ee7507edf..a76c8de03 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -137,7 +137,7 @@ Result ReleaseMutex(Handle handle) { * @param name Optional name of mutex * @return Pointer to new Mutex object */ -Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string name) { +Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { Mutex* mutex = new Mutex; handle = Kernel::g_object_pool.Create(mutex); @@ -161,7 +161,7 @@ Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string name) * @param name Optional name of mutex * @return Handle to newly created object */ -Handle CreateMutex(bool initial_locked, std::string name) { +Handle CreateMutex(bool initial_locked, const std::string& name) { Handle handle; Mutex* mutex = CreateMutex(handle, initial_locked, name); return handle; diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index fde5549fa..7d7b5137e 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -23,6 +23,6 @@ Result ReleaseMutex(Handle handle); * @param name Optional name of mutex * @return Handle to newly created object */ -Handle CreateMutex(bool initial_locked, const std::string name="Unknown"); +Handle CreateMutex(bool initial_locked, const std::string& name="Unknown"); } // namespace -- cgit v1.2.3 From c95972275e276abe3afcac79d956ea29a0879c8e Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 00:35:49 -0400 Subject: HLE: Updated all uses of NULL to nullptr (to be C++11 compliant) --- src/core/hle/kernel/kernel.cpp | 2 +- src/core/hle/kernel/mutex.cpp | 2 +- src/core/hle/kernel/thread.cpp | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 9d5991c37..e51a9d45a 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -128,7 +128,7 @@ Object* ObjectPool::CreateByIDType(int type) { default: ERROR_LOG(COMMON, "Unable to load state: could not find object type %d.", type); - return NULL; + return nullptr; } } diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index a76c8de03..1ccf1eb73 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -122,7 +122,7 @@ bool ReleaseMutex(Mutex* mutex) { Result ReleaseMutex(Handle handle) { Mutex* mutex = Kernel::g_object_pool.GetFast(handle); - _assert_msg_(KERNEL, (mutex != NULL), "ReleaseMutex tried to release a NULL mutex!"); + _assert_msg_(KERNEL, (mutex != nullptr), "ReleaseMutex tried to release a nullptr mutex!"); if (!ReleaseMutex(mutex)) { return -1; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 5fdb4fbe6..700f4ea7c 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -223,7 +223,7 @@ void SwitchContext(Thread* t) { t->wait_type = WAITTYPE_NONE; LoadContext(t->context); } else { - SetCurrentThread(NULL); + SetCurrentThread(nullptr); } } @@ -238,7 +238,7 @@ Thread* NextThread() { next = g_thread_ready_queue.pop_first(); } if (next == 0) { - return NULL; + return nullptr; } return Kernel::g_object_pool.GetFast(next); } @@ -312,8 +312,8 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s32 processor_id, u32 stack_top, int stack_size) { - if (name == NULL) { - ERROR_LOG(KERNEL, "CreateThread(): NULL name"); + if (name == nullptr) { + ERROR_LOG(KERNEL, "CreateThread(): nullptr name"); return -1; } if ((u32)stack_size < 0x200) { @@ -353,19 +353,19 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 /// Get the priority of the thread specified by handle u32 GetThreadPriority(const Handle handle) { Thread* thread = g_object_pool.GetFast(handle); - _assert_msg_(KERNEL, (thread != NULL), "called, but thread is NULL!"); + _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); return thread->current_priority; } /// Set the priority of the thread specified by handle Result SetThreadPriority(Handle handle, s32 priority) { - Thread* thread = NULL; + Thread* thread = nullptr; if (!handle) { thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? } else { thread = g_object_pool.GetFast(handle); } - _assert_msg_(KERNEL, (thread != NULL), "called, but thread is NULL!"); + _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); // If priority is invalid, clamp to valid range if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { -- cgit v1.2.3 From 12e2a59565520382e76c641896b594fdafebd244 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 17:57:52 -0400 Subject: Thread: Updated VerifyWait to be more readable (but functionally the same). --- src/core/hle/kernel/thread.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 700f4ea7c..0385a64fd 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -146,12 +146,11 @@ void ChangeReadyState(Thread* t, bool ready) { inline bool VerifyWait(const Handle& thread, WaitType type, Handle handle) { Handle wait_id = 0; Thread *t = g_object_pool.GetFast(thread); - if (t) { - if (type == t->wait_type && handle == t->wait_handle) { - return true; - } + if (t != nullptr && type == t->wait_type && handle == t->wait_handle) { + return true; } else { ERROR_LOG(KERNEL, "thread 0x%08X does not exist", thread); + return false; } return false; } -- cgit v1.2.3 From bfdd874b1f3a7af9ec540105ed1d52edc0d72472 Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 20:05:16 -0400 Subject: Thread: Moved position of * in arguments. --- src/core/hle/kernel/thread.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 0385a64fd..cb5b89379 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -145,7 +145,7 @@ void ChangeReadyState(Thread* t, bool ready) { /// Verify that a thread has not been released from waiting inline bool VerifyWait(const Handle& thread, WaitType type, Handle handle) { Handle wait_id = 0; - Thread *t = g_object_pool.GetFast(thread); + Thread* t = g_object_pool.GetFast(thread); if (t != nullptr && type == t->wait_type && handle == t->wait_handle) { return true; } else { @@ -158,7 +158,7 @@ inline bool VerifyWait(const Handle& thread, WaitType type, Handle handle) { /// Stops the current thread void StopThread(Handle thread, const char* reason) { u32 error; - Thread *t = g_object_pool.Get(thread, error); + Thread* t = g_object_pool.Get(thread, error); if (t) { ChangeReadyState(t, false); t->status = THREADSTATUS_DORMANT; -- cgit v1.2.3 From 4620e2a741735a18f3a331037f86b3aae0f9fc6d Mon Sep 17 00:00:00 2001 From: bunnei Date: Fri, 6 Jun 2014 23:34:49 -0400 Subject: HLE: Removed usnused EatCycles function. --- src/core/hle/kernel/thread.cpp | 9 --------- 1 file changed, 9 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index cb5b89379..ebe308a93 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -337,15 +337,8 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 stack_size); ResetThread(t, arg, 0); - - HLE::EatCycles(32000); - CallThread(t); - // This won't schedule to the new thread, but it may to one woken from eating cycles. - // Technically, this should not eat all at once, and reschedule in the middle, but that's hard. - //HLE::Reschedule(__func__); - return handle; } @@ -389,8 +382,6 @@ Result SetThreadPriority(Handle handle, s32 priority) { g_thread_ready_queue.push_back(thread->current_priority, handle); } - HLE::EatCycles(450); - return 0; } -- cgit v1.2.3 From 5b7cf50a7760ea1d4202ac3890cefc8934ac841f Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Jun 2014 22:08:49 -0400 Subject: Thread: Cleaned up VerifyWait, fixed issue where nullptr msg could unnecessarily be logged. --- src/core/hle/kernel/thread.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index ebe308a93..baa9687cb 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -143,16 +143,14 @@ void ChangeReadyState(Thread* t, bool ready) { } /// Verify that a thread has not been released from waiting -inline bool VerifyWait(const Handle& thread, WaitType type, Handle handle) { - Handle wait_id = 0; - Thread* t = g_object_pool.GetFast(thread); - if (t != nullptr && type == t->wait_type && handle == t->wait_handle) { - return true; - } else { - ERROR_LOG(KERNEL, "thread 0x%08X does not exist", thread); +inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) { + Thread* thread = g_object_pool.GetFast(handle); + _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); + + if (type != thread->wait_type || wait_handle != thread->wait_handle) return false; - } - return false; + + return true; } /// Stops the current thread -- cgit v1.2.3 From b62ef4bbd2f415b6a193ce53e87decb56bacb3e1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Jun 2014 22:14:03 -0400 Subject: Thread: Renamed occurrences of "t" to "thread" to improve readability. --- src/core/hle/kernel/thread.cpp | 93 ++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 48 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index baa9687cb..ab5a5559e 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -154,26 +154,23 @@ inline bool VerifyWait(const Handle& handle, WaitType type, Handle wait_handle) } /// Stops the current thread -void StopThread(Handle thread, const char* reason) { - u32 error; - Thread* t = g_object_pool.Get(thread, error); - if (t) { - ChangeReadyState(t, false); - t->status = THREADSTATUS_DORMANT; - for (size_t i = 0; i < t->waiting_threads.size(); ++i) { - const Handle waiting_thread = t->waiting_threads[i]; - if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, thread)) { - ResumeThreadFromWait(waiting_thread); - } +void StopThread(Handle handle, const char* reason) { + Thread* thread = g_object_pool.GetFast(handle); + _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); + + ChangeReadyState(thread, false); + thread->status = THREADSTATUS_DORMANT; + for (size_t i = 0; i < thread->waiting_threads.size(); ++i) { + const Handle waiting_thread = thread->waiting_threads[i]; + if (VerifyWait(waiting_thread, WAITTYPE_THREADEND, handle)) { + ResumeThreadFromWait(waiting_thread); } - t->waiting_threads.clear(); - - // Stopped threads are never waiting. - t->wait_type = WAITTYPE_NONE; - t->wait_handle = 0; - } else { - ERROR_LOG(KERNEL, "thread 0x%08X does not exist", thread); } + thread->waiting_threads.clear(); + + // Stopped threads are never waiting. + thread->wait_type = WAITTYPE_NONE; + thread->wait_handle = 0; } /// Changes a threads state @@ -242,20 +239,20 @@ Thread* NextThread() { /// Puts the current thread in the wait state for the given type void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { - Thread* t = GetCurrentThread(); - t->wait_type = wait_type; - t->wait_handle = wait_handle; - ChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND))); + Thread* thread = GetCurrentThread(); + thread->wait_type = wait_type; + thread->wait_handle = wait_handle; + ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); } /// Resumes a thread from waiting by marking it as "ready" void ResumeThreadFromWait(Handle handle) { u32 error; - Thread* t = Kernel::g_object_pool.Get(handle, error); - if (t) { - t->status &= ~THREADSTATUS_WAIT; - if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { - ChangeReadyState(t, true); + Thread* thread = Kernel::g_object_pool.Get(handle, error); + if (thread) { + thread->status &= ~THREADSTATUS_WAIT; + if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { + ChangeReadyState(thread, true); } } } @@ -283,26 +280,26 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio _assert_msg_(KERNEL, (priority >= THREADPRIO_HIGHEST && priority <= THREADPRIO_LOWEST), "CreateThread priority=%d, outside of allowable range!", priority) - Thread* t = new Thread; + Thread* thread = new Thread; - handle = Kernel::g_object_pool.Create(t); + handle = Kernel::g_object_pool.Create(thread); g_thread_queue.push_back(handle); g_thread_ready_queue.prepare(priority); - t->status = THREADSTATUS_DORMANT; - t->entry_point = entry_point; - t->stack_top = stack_top; - t->stack_size = stack_size; - t->initial_priority = t->current_priority = priority; - t->processor_id = processor_id; - t->wait_type = WAITTYPE_NONE; - t->wait_handle = 0; + thread->status = THREADSTATUS_DORMANT; + thread->entry_point = entry_point; + thread->stack_top = stack_top; + thread->stack_size = stack_size; + thread->initial_priority = thread->current_priority = priority; + thread->processor_id = processor_id; + thread->wait_type = WAITTYPE_NONE; + thread->wait_handle = 0; - strncpy(t->name, name, Kernel::MAX_NAME_LENGTH); - t->name[Kernel::MAX_NAME_LENGTH] = '\0'; + strncpy(thread->name, name, Kernel::MAX_NAME_LENGTH); + thread->name[Kernel::MAX_NAME_LENGTH] = '\0'; - return t; + return thread; } /// Creates a new thread - wrapper for external user @@ -331,11 +328,11 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3 return -1; } Handle handle; - Thread* t = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, + Thread* thread = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, stack_size); - ResetThread(t, arg, 0); - CallThread(t); + ResetThread(thread, arg, 0); + CallThread(thread); return handle; } @@ -388,10 +385,10 @@ Handle SetupMainThread(s32 priority, int stack_size) { Handle handle; // Initialize new "main" thread - Thread* t = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, + Thread* thread = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); - ResetThread(t, 0, 0); + ResetThread(thread, 0, 0); // If running another thread already, set it to "ready" state Thread* cur = GetCurrentThread(); @@ -400,9 +397,9 @@ Handle SetupMainThread(s32 priority, int stack_size) { } // Run new "main" thread - SetCurrentThread(t); - t->status = THREADSTATUS_RUNNING; - LoadContext(t->context); + SetCurrentThread(thread); + thread->status = THREADSTATUS_RUNNING; + LoadContext(thread->context); return handle; } -- cgit v1.2.3 From 83a4ad28854f6c90f688e3d4523708c2d06267de Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 9 Jun 2014 22:46:54 -0400 Subject: Event: Updated several log messages to be assertions. --- src/core/hle/kernel/event.cpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 3a522c190..127c0cfc6 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -59,10 +59,8 @@ public: */ Result SetPermanentLock(Handle handle, const bool permanent_locked) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + evt->permanent_locked = permanent_locked; return 0; } @@ -75,10 +73,8 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) { */ Result SetEventLocked(const Handle handle, const bool locked) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + if (!evt->permanent_locked) { evt->locked = locked; } @@ -92,10 +88,8 @@ Result SetEventLocked(const Handle handle, const bool locked) { */ Result SignalEvent(const Handle handle) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + // Resume threads waiting for event to signal bool event_caught = false; for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { @@ -122,10 +116,8 @@ Result SignalEvent(const Handle handle) { */ Result ClearEvent(Handle handle) { Event* evt = g_object_pool.GetFast(handle); - if (!evt) { - ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); - return -1; - } + _assert_msg_(KERNEL, (evt != nullptr), "called, but event is nullptr!"); + if (!evt->permanent_locked) { evt->locked = true; } -- cgit v1.2.3 From f49ac3a2d71f06d603b8401817a6dfd9dbc3c4bc Mon Sep 17 00:00:00 2001 From: bunnei Date: Tue, 10 Jun 2014 22:43:50 -0400 Subject: Kernel: Added freeing of kernel objects on emulator shutdown. --- src/core/hle/kernel/kernel.cpp | 4 ++++ src/core/hle/kernel/kernel.h | 6 ++++++ 2 files changed, 10 insertions(+) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index e51a9d45a..739ddd4ef 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -132,12 +132,16 @@ Object* ObjectPool::CreateByIDType(int type) { } } +/// Initialize the kernel void Init() { Kernel::ThreadingInit(); } +/// Shutdown the kernel void Shutdown() { Kernel::ThreadingShutdown(); + + g_object_pool.Clear(); // Free all kernel objects } /** diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index d2d624f6d..3f15da0ac 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -167,6 +167,12 @@ private: extern ObjectPool g_object_pool; extern Handle g_main_thread; +/// Initialize the kernel +void Init(); + +/// Shutdown the kernel +void Shutdown(); + /** * Loads executable stored at specified address * @entry_point Entry point in memory of loaded executable -- cgit v1.2.3 From b45a38f55794e47b0429a8667441a20433e19e42 Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 12 Jun 2014 16:57:18 -0400 Subject: Kernel: Removed unnecessary "#pragma once". --- src/core/hle/kernel/kernel.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 739ddd4ef..cda183add 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#pragma once - #include #include "common/common.h" -- cgit v1.2.3