diff options
28 files changed, 151 insertions, 160 deletions
diff --git a/.travis-deps.sh b/.travis-deps.sh index 2a0f6b284..bd09da0d0 100644 --- a/.travis-deps.sh +++ b/.travis-deps.sh @@ -24,8 +24,6 @@ if [ "$TRAVIS_OS_NAME" = linux -o -z "$TRAVIS_OS_NAME" ]; then curl http://www.cmake.org/files/v2.8/cmake-2.8.11-Linux-i386.tar.gz \ | sudo tar -xz -C /usr/local --strip-components=1 elif [ "$TRAVIS_OS_NAME" = osx ]; then - export HOMEBREW_CACHE="$PWD/.homebrew-cache" - mkdir -p "$HOMEBREW_CACHE" brew tap homebrew/versions brew install qt5 glfw3 pkgconfig fi diff --git a/.travis.yml b/.travis.yml index 8c5aceb7c..1cb369d5b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,11 +4,6 @@ os: language: cpp -cache: - apt: true - directories: - - .homebrew-cache - before_install: - sh .travis-deps.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 2711336fb..20a5a011a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ else() # /GR- - Disable RTTI # /GS- - No stack buffer overflow checks # /EHsc - C++-only exception handling semantics - set(optimization_flags "/MP /MD /Ox /Oy- /DNDEBUG /GR- /GS- /EHsc") + set(optimization_flags "/MP /MD /Ox /Oy- /GR- /GS- /EHsc") # /Zi - Output debugging information # /Zo - enahnced debug info for optimized builds set(CMAKE_C_FLAGS_RELEASE "${optimization_flags} /Zi" CACHE STRING "" FORCE) @@ -32,7 +32,11 @@ else() set(CMAKE_C_FLAGS_RELWITHDEBINFO "${optimization_flags} /Zi /Zo" CACHE STRING "" FORCE) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${optimization_flags} /Zi /Zo" CACHE STRING "" FORCE) endif() + add_definitions(-DSINGLETHREADED) +# CMake seems to only define _DEBUG on Windows +set_property(DIRECTORY APPEND PROPERTY + COMPILE_DEFINITIONS $<$<CONFIG:Debug>:_DEBUG> $<$<NOT:$<CONFIG:Debug>>:NDEBUG>) find_package(PNG QUIET) if (PNG_FOUND) diff --git a/externals/boost b/externals/boost -Subproject 97052c28acb141dbf3c5e14114af99045344b69 +Subproject a1afc91d3aaa3da06bdbc13c78613e146665340 diff --git a/src/common/common.h b/src/common/common.h index bf48ae667..3246c7797 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -11,13 +11,6 @@ #include <cstdio> #include <cstring> -// Force enable logging in the right modes. For some reason, something had changed -// so that debugfast no longer logged. -#if defined(_DEBUG) || defined(DEBUGFAST) -#undef LOGGING -#define LOGGING 1 -#endif - #define STACKALIGN // An inheritable class to disallow the copy constructor and operator= functions diff --git a/src/common/log.h b/src/common/log.h index 667f2fbb9..b397cf14d 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -14,7 +14,7 @@ #endif #endif -#if _DEBUG +#ifdef _DEBUG #define _dbg_assert_(_t_, _a_) \ if (!(_a_)) {\ LOG_CRITICAL(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \ diff --git a/src/common/logging/log.h b/src/common/logging/log.h index bda3d633a..3d94bf0d9 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -74,17 +74,6 @@ enum class Class : ClassType { }; /** - * Level below which messages are simply discarded without buffering regardless of the display - * settings. - */ -const Level MINIMUM_LEVEL = -#ifdef _DEBUG - Level::Trace; -#else - Level::Debug; -#endif - -/** * Logs a message to the global logger. This proxy exists to avoid exposing the details of the * Logger class, including the ConcurrentRingBuffer template, to all files that desire to log * messages, reducing unecessary recompilations. @@ -103,13 +92,15 @@ void LogMessage(Class log_class, Level log_level, } // namespace Log #define LOG_GENERIC(log_class, log_level, ...) \ - do { \ - if (::Log::Level::log_level >= ::Log::MINIMUM_LEVEL) \ - ::Log::LogMessage(::Log::Class::log_class, ::Log::Level::log_level, \ - __FILE__, __LINE__, __func__, __VA_ARGS__); \ - } while (0) + ::Log::LogMessage(::Log::Class::log_class, ::Log::Level::log_level, \ + __FILE__, __LINE__, __func__, __VA_ARGS__) +#ifdef _DEBUG #define LOG_TRACE( log_class, ...) LOG_GENERIC(log_class, Trace, __VA_ARGS__) +#else +#define LOG_TRACE( log_class, ...) (void(0)) +#endif + #define LOG_DEBUG( log_class, ...) LOG_GENERIC(log_class, Debug, __VA_ARGS__) #define LOG_INFO( log_class, ...) LOG_GENERIC(log_class, Info, __VA_ARGS__) #define LOG_WARNING( log_class, ...) LOG_GENERIC(log_class, Warning, __VA_ARGS__) diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 28adc5500..62e3460e1 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -30,7 +30,7 @@ public: /// Arbitrate an address ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) { - Object* object = Kernel::g_handle_table.GetGeneric(handle); + Object* object = Kernel::g_handle_table.GetGeneric(handle).get(); if (object == nullptr) return InvalidHandle(ErrorModule::Kernel); diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 697e08681..271190dbe 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -53,7 +53,7 @@ public: * @return Result of operation, 0 on success, otherwise error code */ ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) { - Event* evt = g_handle_table.Get<Event>(handle); + Event* evt = g_handle_table.Get<Event>(handle).get(); if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); evt->permanent_locked = permanent_locked; @@ -67,7 +67,7 @@ ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) { * @return Result of operation, 0 on success, otherwise error code */ ResultCode SetEventLocked(const Handle handle, const bool locked) { - Event* evt = g_handle_table.Get<Event>(handle); + Event* evt = g_handle_table.Get<Event>(handle).get(); if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); if (!evt->permanent_locked) { @@ -82,13 +82,13 @@ ResultCode SetEventLocked(const Handle handle, const bool locked) { * @return Result of operation, 0 on success, otherwise error code */ ResultCode SignalEvent(const Handle handle) { - Event* evt = g_handle_table.Get<Event>(handle); + Event* evt = g_handle_table.Get<Event>(handle).get(); if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); // Resume threads waiting for event to signal bool event_caught = false; for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { - Thread* thread = Kernel::g_handle_table.Get<Thread>(evt->waiting_threads[i]); + Thread* thread = Kernel::g_handle_table.Get<Thread>(evt->waiting_threads[i]).get(); if (thread != nullptr) thread->ResumeFromWait(); @@ -112,7 +112,7 @@ ResultCode SignalEvent(const Handle handle) { * @return Result of operation, 0 on success, otherwise error code */ ResultCode ClearEvent(Handle handle) { - Event* evt = g_handle_table.Get<Event>(handle); + Event* evt = g_handle_table.Get<Event>(handle).get(); if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); if (!evt->permanent_locked) { diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index a1bc6c5d8..d3684896f 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -14,7 +14,7 @@ namespace Kernel { -Thread* g_main_thread = nullptr; +SharedPtr<Thread> g_main_thread = nullptr; HandleTable g_handle_table; u64 g_program_id = 0; @@ -23,7 +23,7 @@ HandleTable::HandleTable() { Clear(); } -ResultVal<Handle> HandleTable::Create(Object* obj) { +ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { _dbg_assert_(Kernel, obj != nullptr); u16 slot = next_free_slot; @@ -39,22 +39,23 @@ ResultVal<Handle> HandleTable::Create(Object* obj) { // CTR-OS doesn't use generation 0, so skip straight to 1. if (next_generation >= (1 << 15)) next_generation = 1; + Handle handle = generation | (slot << 15); + if (obj->handle == INVALID_HANDLE) + obj->handle = handle; + generations[slot] = generation; - intrusive_ptr_add_ref(obj); - objects[slot] = obj; + objects[slot] = std::move(obj); - Handle handle = generation | (slot << 15); - obj->handle = handle; return MakeResult<Handle>(handle); } ResultVal<Handle> HandleTable::Duplicate(Handle handle) { - Object* object = GetGeneric(handle); + SharedPtr<Object> object = GetGeneric(handle); if (object == nullptr) { LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle); return ERR_INVALID_HANDLE; } - return Create(object); + return Create(std::move(object)); } ResultCode HandleTable::Close(Handle handle) { @@ -64,7 +65,6 @@ ResultCode HandleTable::Close(Handle handle) { size_t slot = GetSlot(handle); u16 generation = GetGeneration(handle); - intrusive_ptr_release(objects[slot]); objects[slot] = nullptr; generations[generation] = next_free_slot; @@ -79,7 +79,7 @@ bool HandleTable::IsValid(Handle handle) const { return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation; } -Object* HandleTable::GetGeneric(Handle handle) const { +SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const { if (handle == CurrentThread) { return GetCurrentThread(); } else if (handle == CurrentProcess) { @@ -96,8 +96,6 @@ Object* HandleTable::GetGeneric(Handle handle) const { void HandleTable::Clear() { for (size_t i = 0; i < MAX_COUNT; ++i) { generations[i] = i + 1; - if (objects[i] != nullptr) - intrusive_ptr_release(objects[i]); objects[i] = nullptr; } next_free_slot = 0; @@ -125,7 +123,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(0x30); + g_main_thread = Kernel::SetupMainThread(0x30, Kernel::DEFAULT_STACK_SIZE); // Setup the idle thread Kernel::SetupIdleThread(); diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 31d80c7ac..5e5217b78 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -4,6 +4,8 @@ #pragma once +#include <boost/intrusive_ptr.hpp> + #include <array> #include <string> #include "common/common.h" @@ -52,7 +54,7 @@ class HandleTable; class Object : NonCopyable { friend class HandleTable; - u32 handle; + u32 handle = INVALID_HANDLE; public: virtual ~Object() {} Handle GetHandle() const { return handle; } @@ -76,7 +78,7 @@ private: unsigned int ref_count = 0; }; -// Special functions that will later be used by boost::instrusive_ptr to do automatic ref-counting +// Special functions used by boost::instrusive_ptr to do automatic ref-counting inline void intrusive_ptr_add_ref(Object* object) { ++object->ref_count; } @@ -87,6 +89,9 @@ inline void intrusive_ptr_release(Object* object) { } } +template <typename T> +using SharedPtr = boost::intrusive_ptr<T>; + /** * This class allows the creation of Handles, which are references to objects that can be tested * for validity and looked up. Here they are used to pass references to kernel objects to/from the @@ -119,7 +124,7 @@ public: * @return The created Handle or one of the following errors: * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded. */ - ResultVal<Handle> Create(Object* obj); + ResultVal<Handle> Create(SharedPtr<Object> obj); /** * Returns a new handle that points to the same object as the passed in handle. @@ -143,7 +148,7 @@ public: * Looks up a handle. * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid. */ - Object* GetGeneric(Handle handle) const; + SharedPtr<Object> GetGeneric(Handle handle) const; /** * Looks up a handle while verifying its type. @@ -151,10 +156,10 @@ public: * type differs from the handle type `T::HANDLE_TYPE`. */ template <class T> - T* Get(Handle handle) const { - Object* object = GetGeneric(handle); + SharedPtr<T> Get(Handle handle) const { + SharedPtr<Object> object = GetGeneric(handle); if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) { - return static_cast<T*>(object); + return boost::static_pointer_cast<T>(std::move(object)); } return nullptr; } @@ -173,7 +178,7 @@ private: static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; } /// Stores the Object referenced by the handle or null if the slot is empty. - std::array<Object*, MAX_COUNT> objects; + std::array<SharedPtr<Object>, MAX_COUNT> objects; /** * The value of `next_generation` when the handle was created, used to check for validity. For @@ -192,7 +197,7 @@ private: }; extern HandleTable g_handle_table; -extern Thread* g_main_thread; +extern SharedPtr<Thread> g_main_thread; /// The ID code of the currently running game /// TODO(Subv): This variable should not be here, diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 7d008f6cc..853a5dd74 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -48,7 +48,7 @@ void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThread()->GetHandl bool ReleaseMutexForThread(Mutex* mutex, Handle thread_handle) { MutexAcquireLock(mutex, thread_handle); - Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle); + Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle).get(); if (thread == nullptr) { LOG_ERROR(Kernel, "Called with invalid handle: %08X", thread_handle); return false; @@ -94,7 +94,7 @@ void ReleaseThreadMutexes(Handle thread) { // Release every mutex that the thread holds, and resume execution on the waiting threads for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { - Mutex* mutex = g_handle_table.Get<Mutex>(iter->second); + Mutex* mutex = g_handle_table.Get<Mutex>(iter->second).get(); ResumeWaitingThread(mutex); } @@ -122,7 +122,7 @@ bool ReleaseMutex(Mutex* mutex) { * @param handle Handle to mutex to release */ ResultCode ReleaseMutex(Handle handle) { - Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle); + Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle).get(); if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); if (!ReleaseMutex(mutex)) { diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index d7eeaa3da..88ec9a104 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -70,7 +70,7 @@ ResultCode CreateSemaphore(Handle* handle, s32 initial_count, } ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { - Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle); + Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get(); if (semaphore == nullptr) return InvalidHandle(ErrorModule::Kernel); @@ -84,7 +84,7 @@ ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { // Notify some of the threads that the semaphore has been released // stop once the semaphore is full again or there are no more waiting threads while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) { - Thread* thread = Kernel::g_handle_table.Get<Thread>(semaphore->waiting_threads.front()); + Thread* thread = Kernel::g_handle_table.Get<Thread>(semaphore->waiting_threads.front()).get(); if (thread != nullptr) thread->ResumeFromWait(); semaphore->waiting_threads.pop(); diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index cea1f6fa1..5368e4728 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -61,7 +61,7 @@ ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); } - SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); + SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get(); if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); shared_memory->base_address = address; @@ -72,7 +72,7 @@ ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions } ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) { - SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); + SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get(); if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); if (0 != shared_memory->base_address) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 0ae1a21df..dd20ca30e 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -36,7 +36,7 @@ ResultVal<bool> Thread::WaitSynchronization() { } // Lists all thread ids that aren't deleted/etc. -static std::vector<Thread*> thread_list; // TODO(yuriks): Owned +static std::vector<SharedPtr<Thread>> thread_list; // Lists only ready thread ids. static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> thread_ready_queue; @@ -110,8 +110,8 @@ void Thread::Stop(const char* reason) { ChangeReadyState(this, false); status = THREADSTATUS_DORMANT; - for (Thread* waiting_thread : waiting_threads) { - if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, this)) + for (auto& waiting_thread : waiting_threads) { + if (CheckWaitType(waiting_thread.get(), WAITTYPE_THREADEND, this)) waiting_thread->ResumeFromWait(); } waiting_threads.clear(); @@ -143,15 +143,15 @@ Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address) { s32 priority = THREADPRIO_LOWEST; // Iterate through threads, find highest priority thread that is waiting to be arbitrated... - for (Thread* thread : thread_list) { - if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) + for (auto& thread : thread_list) { + if (!CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address)) continue; if (thread == nullptr) continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up. if(thread->current_priority <= priority) { - highest_priority_thread = thread; + highest_priority_thread = thread.get(); priority = thread->current_priority; } } @@ -168,8 +168,8 @@ Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address) { void ArbitrateAllThreads(Object* arbiter, u32 address) { // Iterate through threads, find highest priority thread that is waiting to be arbitrated... - for (Thread* thread : thread_list) { - if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) + for (auto& thread : thread_list) { + if (CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address)) thread->ResumeFromWait(); } } @@ -241,7 +241,7 @@ static int ThreadWakeupEventType = -1; /// Callback that will wake up the thread it was scheduled for static void ThreadWakeupCallback(u64 parameter, int cycles_late) { Handle handle = static_cast<Handle>(parameter); - Thread* thread = Kernel::g_handle_table.Get<Thread>(handle); + SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(handle); if (thread == nullptr) { LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); return; @@ -278,20 +278,18 @@ static void DebugThreadQueue() { return; } LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle()); - for (Thread* t : thread_list) { - s32 priority = thread_ready_queue.contains(t); + for (auto& t : thread_list) { + s32 priority = thread_ready_queue.contains(t.get()); if (priority != -1) { LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle()); } } } -ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priority, u32 arg, - s32 processor_id, u32 stack_top, int stack_size) { - _dbg_assert_(Kernel, name != nullptr); - - if ((u32)stack_size < 0x200) { - LOG_ERROR(Kernel, "(name=%s): invalid stack_size=0x%08X", name, stack_size); +ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, + u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size) { + if (stack_size < 0x200) { + LOG_ERROR(Kernel, "(name=%s): invalid stack_size=0x%08X", name.c_str(), stack_size); // TODO: Verify error return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); @@ -300,27 +298,26 @@ ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priorit if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", - name, priority, new_priority); + name.c_str(), priority, new_priority); // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm // validity of this priority = new_priority; } if (!Memory::GetPointer(entry_point)) { - LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name, entry_point); + LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); // TODO: Verify error return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); } - Thread* thread = new Thread; + SharedPtr<Thread> thread(new Thread); // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for // the time being. Create a handle here, it will be copied to the handle field in // the object and use by the rest of the code. This should be removed when other // code doesn't rely on the handle anymore. ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread); - // TODO(yuriks): Plug memory leak if (handle.Failed()) return handle.Code(); @@ -337,12 +334,12 @@ ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priorit thread->wait_type = WAITTYPE_NONE; thread->wait_object = nullptr; thread->wait_address = 0; - thread->name = name; + thread->name = std::move(name); - ResetThread(thread, arg, 0); - CallThread(thread); + ResetThread(thread.get(), arg, 0); + CallThread(thread.get()); - return MakeResult<Thread*>(thread); + return MakeResult<SharedPtr<Thread>>(std::move(thread)); } /// Set the priority of the thread specified by handle @@ -376,20 +373,20 @@ Handle SetupIdleThread() { auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0, THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE); _dbg_assert_(Kernel, thread_res.Succeeded()); - Thread* thread = *thread_res; + SharedPtr<Thread> thread = std::move(*thread_res); thread->idle = true; - CallThread(thread); + CallThread(thread.get()); return thread->GetHandle(); } -Thread* SetupMainThread(s32 priority, int stack_size) { +SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) { // Initialize new "main" thread - ResultVal<Thread*> thread_res = Thread::Create("main", Core::g_app_core->GetPC(), priority, 0, - THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); + auto thread_res = Thread::Create("main", Core::g_app_core->GetPC(), priority, 0, + THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); // TODO(yuriks): Propagate error _dbg_assert_(Kernel, thread_res.Succeeded()); - Thread* thread = *thread_res; + SharedPtr<Thread> thread = std::move(*thread_res); // If running another thread already, set it to "ready" state Thread* cur = GetCurrentThread(); @@ -398,7 +395,7 @@ Thread* SetupMainThread(s32 priority, int stack_size) { } // Run new "main" thread - current_thread = thread; + current_thread = thread.get(); thread->status = THREADSTATUS_RUNNING; Core::g_app_core->LoadContext(thread->context); @@ -418,7 +415,7 @@ void Reschedule() { } else { LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); - for (Thread* thread : thread_list) { + for (auto& thread : thread_list) { LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X", thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, (thread->wait_object ? thread->wait_object->GetHandle() : INVALID_HANDLE)); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 24450379c..284dec400 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -54,8 +54,8 @@ namespace Kernel { class Thread : public Kernel::Object { public: - static ResultVal<Thread*> Create(const char* name, u32 entry_point, s32 priority, u32 arg, - s32 processor_id, u32 stack_top, int stack_size = Kernel::DEFAULT_STACK_SIZE); + static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, + u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size); std::string GetName() const override { return name; } std::string GetTypeName() const override { return "Thread"; } @@ -99,7 +99,7 @@ public: Object* wait_object; VAddr wait_address; - std::vector<Thread*> waiting_threads; // TODO(yuriks): Owned + std::vector<SharedPtr<Thread>> waiting_threads; std::string name; @@ -111,7 +111,7 @@ private: }; /// Sets up the primary application thread -Thread* SetupMainThread(s32 priority, int stack_size = Kernel::DEFAULT_STACK_SIZE); +SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size); /// Reschedules to the next available thread (call after current thread is suspended) void Reschedule(); diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index 685a202c0..3b0452d4d 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -66,7 +66,7 @@ ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::st } ResultCode ClearTimer(Handle handle) { - Timer* timer = Kernel::g_handle_table.Get<Timer>(handle); + SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); if (timer == nullptr) return InvalidHandle(ErrorModule::Kernel); @@ -80,7 +80,7 @@ static int TimerCallbackEventType = -1; /// The timer callback event, called when a timer is fired static void TimerCallback(u64 timer_handle, int cycles_late) { - Timer* timer = Kernel::g_handle_table.Get<Timer>(timer_handle); + SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle); if (timer == nullptr) { LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle); @@ -93,7 +93,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) { // Resume all waiting threads for (Handle thread_handle : timer->waiting_threads) { - if (Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle)) + if (SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(thread_handle)) thread->ResumeFromWait(); } @@ -111,7 +111,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) { } ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { - Timer* timer = Kernel::g_handle_table.Get<Timer>(handle); + SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); if (timer == nullptr) return InvalidHandle(ErrorModule::Kernel); @@ -125,7 +125,7 @@ ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { } ResultCode CancelTimer(Handle handle) { - Timer* timer = Kernel::g_handle_table.Get<Timer>(handle); + SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); if (timer == nullptr) return InvalidHandle(ErrorModule::Kernel); diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 0e9c213e0..82dcf5bba 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -369,14 +369,14 @@ private: StorageType storage; ResultCode result_code; -#if _DEBUG +#ifdef _DEBUG // The purpose of this pointer is to aid inspecting the type with a debugger, eliminating the // need to cast `storage` to a pointer or pay attention to `result_code`. const T* debug_ptr; #endif void UpdateDebugPtr() { -#if _DEBUG +#ifdef _DEBUG debug_ptr = empty() ? nullptr : static_cast<const T*>(static_cast<const void*>(&storage)); #endif } diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp index d8b261ba7..d0ff4e585 100644 --- a/src/core/hle/service/apt_u.cpp +++ b/src/core/hle/service/apt_u.cpp @@ -52,8 +52,6 @@ void Initialize(Service::Interface* self) { Kernel::ReleaseMutex(lock_handle); cmd_buff[1] = 0; // No error - - LOG_DEBUG(Service_APT, "called"); } void GetLockHandle(Service::Interface* self) { @@ -194,8 +192,6 @@ void AppletUtility(Service::Interface* self) { * 4 : Handle to shared font memory */ void GetSharedFont(Service::Interface* self) { - LOG_TRACE(Kernel_SVC, "called"); - u32* cmd_buff = Kernel::GetCommandBuffer(); if (!shared_font.empty()) { diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 7eb32146d..56f3117f4 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -27,8 +27,6 @@ static void Initialize(Service::Interface* self) { // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per // http://3dbrew.org/wiki/FS:Initialize#Request cmd_buff[1] = RESULT_SUCCESS.raw; - - LOG_DEBUG(Service_FS, "called"); } /** @@ -104,8 +102,8 @@ static void OpenFileDirectly(Service::Interface* self) { FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); FileSys::Path file_path(filename_type, filename_size, filename_ptr); - LOG_DEBUG(Service_FS, "archive_path=%s file_path=%s, mode=%u attributes=%d", - archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes); + LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s file_path=%s, mode=%u attributes=%d", + archive_id, archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes); ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path); if (archive_handle.Failed()) { @@ -367,7 +365,7 @@ static void OpenArchive(Service::Interface* self) { u32 archivename_ptr = cmd_buff[5]; FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); - LOG_DEBUG(Service_FS, "archive_path=%s", archive_path.DebugStr().c_str()); + LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id, archive_path.DebugStr().c_str()); ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path); cmd_buff[1] = handle.Code().raw; @@ -408,8 +406,6 @@ static void IsSdmcDetected(Service::Interface* self) { cmd_buff[1] = 0; cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0; - - LOG_DEBUG(Service_FS, "called"); } /** diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 26a43217e..2b115240f 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -331,9 +331,6 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { /// This triggers handling of the GX command written to the command buffer in shared memory. static void TriggerCmdReqQueue(Service::Interface* self) { - - LOG_TRACE(Service_GSP, "called"); - // Iterate through each thread's command queue... for (unsigned thread_id = 0; thread_id < 0x4; ++thread_id) { CommandBuffer* command_buffer = (CommandBuffer*)GetCommandBuffer(thread_id); diff --git a/src/core/hle/service/hid_user.cpp b/src/core/hle/service/hid_user.cpp index 8ef9af9d2..1403b1de9 100644 --- a/src/core/hle/service/hid_user.cpp +++ b/src/core/hle/service/hid_user.cpp @@ -163,8 +163,6 @@ static void GetIPCHandles(Service::Interface* self) { cmd_buff[6] = event_accelerometer; cmd_buff[7] = event_gyroscope; cmd_buff[8] = event_debug_pad; - - LOG_TRACE(Service_HID, "called"); } const Interface::FunctionInfo FunctionTable[] = { diff --git a/src/core/hle/service/ptm_u.cpp b/src/core/hle/service/ptm_u.cpp index fd79cd8ab..753180add 100644 --- a/src/core/hle/service/ptm_u.cpp +++ b/src/core/hle/service/ptm_u.cpp @@ -76,8 +76,6 @@ static void GetShellState(Service::Interface* self) { cmd_buff[1] = 0; cmd_buff[2] = shell_open ? 1 : 0; - - LOG_TRACE(Service_PTM, "PTM_U::GetShellState called"); } /** diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 0c5597283..33c29a4a0 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -59,7 +59,8 @@ void Manager::DeleteService(const std::string& port_name) { } Interface* Manager::FetchFromHandle(Handle handle) { - return Kernel::g_handle_table.Get<Interface>(handle); + // TODO(yuriks): This function is very suspicious and should probably be exterminated. + return Kernel::g_handle_table.Get<Interface>(handle).get(); } Interface* Manager::FetchFromPortName(const std::string& port_name) { diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h index 41ba1e554..e75d5008b 100644 --- a/src/core/hle/service/service.h +++ b/src/core/hle/service/service.h @@ -33,6 +33,22 @@ class Interface : public Kernel::Session { // processes. friend class Manager; + + /** + * Creates a function string for logging, complete with the name (or header code, depending + * on what's passed in) the port name, and all the cmd_buff arguments. + */ + std::string MakeFunctionString(const std::string& name, const std::string& port_name, const u32* cmd_buff) { + // Number of params == bits 0-5 + bits 6-11 + int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); + + std::string function_string = Common::StringFromFormat("function '%s': port=%s", name.c_str(), port_name.c_str()); + for (int i = 1; i <= num_params; ++i) { + function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]); + } + return function_string; + } + public: std::string GetName() const override { return GetPortName(); } @@ -72,21 +88,14 @@ public: auto itr = m_functions.find(cmd_buff[0]); if (itr == m_functions.end() || itr->second.func == nullptr) { - // Number of params == bits 0-5 + bits 6-11 - int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); - - std::string error = "unknown/unimplemented function '%s': port=%s"; - for (int i = 1; i <= num_params; ++i) { - error += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]); - } - - std::string name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name; - - LOG_ERROR(Service, error.c_str(), name.c_str(), GetPortName().c_str()); + std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name; + LOG_ERROR(Service, "%s %s", "unknown/unimplemented", MakeFunctionString(function_name, GetPortName(), cmd_buff).c_str()); // TODO(bunnei): Hack - ignore error cmd_buff[1] = 0; return MakeResult<bool>(false); + } else { + LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName(), cmd_buff).c_str()); } itr->second.func(this); diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 912b52adf..ac5f30a28 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -14,16 +14,12 @@ namespace SRV { static Handle g_event_handle = 0; static void Initialize(Service::Interface* self) { - LOG_DEBUG(Service_SRV, "called"); - u32* cmd_buff = Kernel::GetCommandBuffer(); cmd_buff[1] = 0; // No error } static void GetProcSemaphore(Service::Interface* self) { - LOG_TRACE(Service_SRV, "called"); - u32* cmd_buff = Kernel::GetCommandBuffer(); // TODO(bunnei): Change to a semaphore once these have been implemented diff --git a/src/core/hle/service/y2r_u.cpp b/src/core/hle/service/y2r_u.cpp index f9e3619dd..b3d873ef0 100644 --- a/src/core/hle/service/y2r_u.cpp +++ b/src/core/hle/service/y2r_u.cpp @@ -12,6 +12,21 @@ namespace Y2R_U { +/** + * Y2R_U::IsBusyConversion service function + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Whether the current conversion is of type busy conversion (?) + */ +static void IsBusyConversion(Service::Interface* self) { + u32* cmd_buff = Kernel::GetCommandBuffer(); + + cmd_buff[1] = RESULT_SUCCESS.raw;; + cmd_buff[2] = 0; + + LOG_WARNING(Service, "(STUBBED) called"); +} + const Interface::FunctionInfo FunctionTable[] = { {0x00010040, nullptr, "SetInputFormat"}, {0x00030040, nullptr, "SetOutputFormat"}, @@ -29,7 +44,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00220040, nullptr, "SetAlpha"}, {0x00260000, nullptr, "StartConversion"}, {0x00270000, nullptr, "StopConversion"}, - {0x00280000, nullptr, "IsBusyConversion"}, + {0x00280000, IsBusyConversion, "IsBusyConversion"}, {0x002A0000, nullptr, "PingProcess"}, {0x002B0000, nullptr, "DriverInitialize"}, {0x002C0000, nullptr, "DriverFinalize"} diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 8ac1c7350..d3b4483ca 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -25,6 +25,8 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace SVC +using Kernel::SharedPtr; + namespace SVC { enum ControlMemoryOperation { @@ -94,7 +96,7 @@ static Result ConnectToPort(Handle* out, const char* port_name) { /// Synchronize to an OS service static Result SendSyncRequest(Handle handle) { - Kernel::Session* session = Kernel::g_handle_table.Get<Kernel::Session>(handle); + SharedPtr<Kernel::Session> session = Kernel::g_handle_table.Get<Kernel::Session>(handle); if (session == nullptr) { return InvalidHandle(ErrorModule::Kernel).raw; } @@ -121,12 +123,12 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { // TODO(bunnei): Do something with nano_seconds, currently ignoring this bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated - Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handle); + SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handle); if (object == nullptr) return InvalidHandle(ErrorModule::Kernel).raw; - LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), - object->GetName().c_str(), nano_seconds); + LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, + object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); ResultVal<bool> wait = object->WaitSynchronization(); @@ -151,12 +153,12 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, // Iterate through each handle, synchronize kernel object for (s32 i = 0; i < handle_count; i++) { - Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handles[i]); + SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handles[i]); if (object == nullptr) return InvalidHandle(ErrorModule::Kernel).raw; - LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), - object->GetName().c_str()); + LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], + object->GetTypeName().c_str(), object->GetName().c_str()); // TODO(yuriks): Verify how the real function behaves when an error happens here ResultVal<bool> wait_result = object->WaitSynchronization(); @@ -183,7 +185,6 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, /// Create an address arbiter (to allocate access to shared resources) static Result CreateAddressArbiter(u32* arbiter) { - LOG_TRACE(Kernel_SVC, "called"); Handle handle = Kernel::CreateAddressArbiter(); *arbiter = handle; return 0; @@ -223,6 +224,8 @@ static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, /// Creates a new thread static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { + using Kernel::Thread; + std::string name; if (Symbols::HasSymbol(entry_point)) { TSymbol symbol = Symbols::GetSymbol(entry_point); @@ -231,12 +234,13 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top name = Common::StringFromFormat("unknown-%08x", entry_point); } - ResultVal<Kernel::Thread*> thread_res = Kernel::Thread::Create(name.c_str(), entry_point, priority, arg, - processor_id, stack_top); + ResultVal<SharedPtr<Thread>> thread_res = Kernel::Thread::Create( + name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE); if (thread_res.Failed()) return thread_res.Code().raw; - Kernel::Thread* thread = *thread_res; + SharedPtr<Thread> thread = std::move(*thread_res); + // TODO(yuriks): Create new handle instead of using built-in Core::g_app_core->SetReg(1, thread->GetHandle()); LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " @@ -261,7 +265,7 @@ static void ExitThread() { /// Gets the priority for the specified thread static Result GetThreadPriority(s32* priority, Handle handle) { - const Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); + const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel).raw; @@ -271,7 +275,7 @@ static Result GetThreadPriority(s32* priority, Handle handle) { /// Sets the priority for the specified thread static Result SetThreadPriority(Handle handle, s32 priority) { - Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); + SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel).raw; @@ -298,7 +302,7 @@ static Result ReleaseMutex(Handle handle) { static Result GetThreadId(u32* thread_id, Handle handle) { LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); - const Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); + const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel).raw; |