summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis-deps.sh2
-rw-r--r--.travis.yml5
-rw-r--r--CMakeLists.txt6
m---------externals/boost0
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.cpp8
-rw-r--r--src/citra_qt/debugger/graphics_framebuffer.h4
-rw-r--r--src/common/common.h7
-rw-r--r--src/common/log.h2
-rw-r--r--src/common/logging/log.h23
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp2
-rw-r--r--src/core/hle/kernel/event.cpp10
-rw-r--r--src/core/hle/kernel/kernel.cpp24
-rw-r--r--src/core/hle/kernel/kernel.h23
-rw-r--r--src/core/hle/kernel/mutex.cpp6
-rw-r--r--src/core/hle/kernel/semaphore.cpp4
-rw-r--r--src/core/hle/kernel/shared_memory.cpp4
-rw-r--r--src/core/hle/kernel/thread.cpp63
-rw-r--r--src/core/hle/kernel/thread.h8
-rw-r--r--src/core/hle/kernel/timer.cpp10
-rw-r--r--src/core/hle/result.h4
-rw-r--r--src/core/hle/service/apt_u.cpp4
-rw-r--r--src/core/hle/service/fs/fs_user.cpp10
-rw-r--r--src/core/hle/service/gsp_gpu.cpp3
-rw-r--r--src/core/hle/service/hid_user.cpp2
-rw-r--r--src/core/hle/service/ptm_u.cpp2
-rw-r--r--src/core/hle/service/service.cpp3
-rw-r--r--src/core/hle/service/service.h31
-rw-r--r--src/core/hle/service/srv.cpp4
-rw-r--r--src/core/hle/service/y2r_u.cpp17
-rw-r--r--src/core/hle/svc.cpp32
30 files changed, 157 insertions, 166 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
24 curl http://www.cmake.org/files/v2.8/cmake-2.8.11-Linux-i386.tar.gz \ 24 curl http://www.cmake.org/files/v2.8/cmake-2.8.11-Linux-i386.tar.gz \
25 | sudo tar -xz -C /usr/local --strip-components=1 25 | sudo tar -xz -C /usr/local --strip-components=1
26elif [ "$TRAVIS_OS_NAME" = osx ]; then 26elif [ "$TRAVIS_OS_NAME" = osx ]; then
27 export HOMEBREW_CACHE="$PWD/.homebrew-cache"
28 mkdir -p "$HOMEBREW_CACHE"
29 brew tap homebrew/versions 27 brew tap homebrew/versions
30 brew install qt5 glfw3 pkgconfig 28 brew install qt5 glfw3 pkgconfig
31fi 29fi
diff --git a/.travis.yml b/.travis.yml
index 8c5aceb7c..1cb369d5b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,11 +4,6 @@ os:
4 4
5language: cpp 5language: cpp
6 6
7cache:
8 apt: true
9 directories:
10 - .homebrew-cache
11
12before_install: 7before_install:
13 - sh .travis-deps.sh 8 - sh .travis-deps.sh
14 9
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2711336fb..20a5a011a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,7 +24,7 @@ else()
24 # /GR- - Disable RTTI 24 # /GR- - Disable RTTI
25 # /GS- - No stack buffer overflow checks 25 # /GS- - No stack buffer overflow checks
26 # /EHsc - C++-only exception handling semantics 26 # /EHsc - C++-only exception handling semantics
27 set(optimization_flags "/MP /MD /Ox /Oy- /DNDEBUG /GR- /GS- /EHsc") 27 set(optimization_flags "/MP /MD /Ox /Oy- /GR- /GS- /EHsc")
28 # /Zi - Output debugging information 28 # /Zi - Output debugging information
29 # /Zo - enahnced debug info for optimized builds 29 # /Zo - enahnced debug info for optimized builds
30 set(CMAKE_C_FLAGS_RELEASE "${optimization_flags} /Zi" CACHE STRING "" FORCE) 30 set(CMAKE_C_FLAGS_RELEASE "${optimization_flags} /Zi" CACHE STRING "" FORCE)
@@ -32,7 +32,11 @@ else()
32 set(CMAKE_C_FLAGS_RELWITHDEBINFO "${optimization_flags} /Zi /Zo" CACHE STRING "" FORCE) 32 set(CMAKE_C_FLAGS_RELWITHDEBINFO "${optimization_flags} /Zi /Zo" CACHE STRING "" FORCE)
33 set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${optimization_flags} /Zi /Zo" CACHE STRING "" FORCE) 33 set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${optimization_flags} /Zi /Zo" CACHE STRING "" FORCE)
34endif() 34endif()
35
35add_definitions(-DSINGLETHREADED) 36add_definitions(-DSINGLETHREADED)
37# CMake seems to only define _DEBUG on Windows
38set_property(DIRECTORY APPEND PROPERTY
39 COMPILE_DEFINITIONS $<$<CONFIG:Debug>:_DEBUG> $<$<NOT:$<CONFIG:Debug>>:NDEBUG>)
36 40
37find_package(PNG QUIET) 41find_package(PNG QUIET)
38if (PNG_FOUND) 42if (PNG_FOUND)
diff --git a/externals/boost b/externals/boost
Subproject 97052c28acb141dbf3c5e14114af99045344b69 Subproject a1afc91d3aaa3da06bdbc13c78613e146665340
diff --git a/src/citra_qt/debugger/graphics_framebuffer.cpp b/src/citra_qt/debugger/graphics_framebuffer.cpp
index caa6896f9..a9423d6c7 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.cpp
+++ b/src/citra_qt/debugger/graphics_framebuffer.cpp
@@ -158,17 +158,17 @@ void GraphicsFramebufferWidget::OnFramebufferAddressChanged(qint64 new_value)
158 } 158 }
159} 159}
160 160
161void GraphicsFramebufferWidget::OnFramebufferWidthChanged(unsigned int new_value) 161void GraphicsFramebufferWidget::OnFramebufferWidthChanged(int new_value)
162{ 162{
163 if (framebuffer_width != new_value) { 163 if (framebuffer_width != static_cast<unsigned>(new_value)) {
164 framebuffer_width = new_value; 164 framebuffer_width = static_cast<unsigned>(new_value);
165 165
166 framebuffer_source_list->setCurrentIndex(static_cast<int>(Source::Custom)); 166 framebuffer_source_list->setCurrentIndex(static_cast<int>(Source::Custom));
167 emit Update(); 167 emit Update();
168 } 168 }
169} 169}
170 170
171void GraphicsFramebufferWidget::OnFramebufferHeightChanged(unsigned int new_value) 171void GraphicsFramebufferWidget::OnFramebufferHeightChanged(int new_value)
172{ 172{
173 if (framebuffer_height != new_value) { 173 if (framebuffer_height != new_value) {
174 framebuffer_height = new_value; 174 framebuffer_height = new_value;
diff --git a/src/citra_qt/debugger/graphics_framebuffer.h b/src/citra_qt/debugger/graphics_framebuffer.h
index 02813525c..56215761e 100644
--- a/src/citra_qt/debugger/graphics_framebuffer.h
+++ b/src/citra_qt/debugger/graphics_framebuffer.h
@@ -62,8 +62,8 @@ public:
62public slots: 62public slots:
63 void OnFramebufferSourceChanged(int new_value); 63 void OnFramebufferSourceChanged(int new_value);
64 void OnFramebufferAddressChanged(qint64 new_value); 64 void OnFramebufferAddressChanged(qint64 new_value);
65 void OnFramebufferWidthChanged(unsigned int new_value); 65 void OnFramebufferWidthChanged(int new_value);
66 void OnFramebufferHeightChanged(unsigned int new_value); 66 void OnFramebufferHeightChanged(int new_value);
67 void OnFramebufferFormatChanged(int new_value); 67 void OnFramebufferFormatChanged(int new_value);
68 void OnUpdate(); 68 void OnUpdate();
69 69
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 @@
11#include <cstdio> 11#include <cstdio>
12#include <cstring> 12#include <cstring>
13 13
14// Force enable logging in the right modes. For some reason, something had changed
15// so that debugfast no longer logged.
16#if defined(_DEBUG) || defined(DEBUGFAST)
17#undef LOGGING
18#define LOGGING 1
19#endif
20
21#define STACKALIGN 14#define STACKALIGN
22 15
23// An inheritable class to disallow the copy constructor and operator= functions 16// 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 @@
14#endif 14#endif
15#endif 15#endif
16 16
17#if _DEBUG 17#ifdef _DEBUG
18#define _dbg_assert_(_t_, _a_) \ 18#define _dbg_assert_(_t_, _a_) \
19 if (!(_a_)) {\ 19 if (!(_a_)) {\
20 LOG_CRITICAL(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \ 20 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 {
74}; 74};
75 75
76/** 76/**
77 * Level below which messages are simply discarded without buffering regardless of the display
78 * settings.
79 */
80const Level MINIMUM_LEVEL =
81#ifdef _DEBUG
82 Level::Trace;
83#else
84 Level::Debug;
85#endif
86
87/**
88 * Logs a message to the global logger. This proxy exists to avoid exposing the details of the 77 * Logs a message to the global logger. This proxy exists to avoid exposing the details of the
89 * Logger class, including the ConcurrentRingBuffer template, to all files that desire to log 78 * Logger class, including the ConcurrentRingBuffer template, to all files that desire to log
90 * messages, reducing unecessary recompilations. 79 * messages, reducing unecessary recompilations.
@@ -103,13 +92,15 @@ void LogMessage(Class log_class, Level log_level,
103} // namespace Log 92} // namespace Log
104 93
105#define LOG_GENERIC(log_class, log_level, ...) \ 94#define LOG_GENERIC(log_class, log_level, ...) \
106 do { \ 95 ::Log::LogMessage(::Log::Class::log_class, ::Log::Level::log_level, \
107 if (::Log::Level::log_level >= ::Log::MINIMUM_LEVEL) \ 96 __FILE__, __LINE__, __func__, __VA_ARGS__)
108 ::Log::LogMessage(::Log::Class::log_class, ::Log::Level::log_level, \
109 __FILE__, __LINE__, __func__, __VA_ARGS__); \
110 } while (0)
111 97
98#ifdef _DEBUG
112#define LOG_TRACE( log_class, ...) LOG_GENERIC(log_class, Trace, __VA_ARGS__) 99#define LOG_TRACE( log_class, ...) LOG_GENERIC(log_class, Trace, __VA_ARGS__)
100#else
101#define LOG_TRACE( log_class, ...) (void(0))
102#endif
103
113#define LOG_DEBUG( log_class, ...) LOG_GENERIC(log_class, Debug, __VA_ARGS__) 104#define LOG_DEBUG( log_class, ...) LOG_GENERIC(log_class, Debug, __VA_ARGS__)
114#define LOG_INFO( log_class, ...) LOG_GENERIC(log_class, Info, __VA_ARGS__) 105#define LOG_INFO( log_class, ...) LOG_GENERIC(log_class, Info, __VA_ARGS__)
115#define LOG_WARNING( log_class, ...) LOG_GENERIC(log_class, Warning, __VA_ARGS__) 106#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:
30 30
31/// Arbitrate an address 31/// Arbitrate an address
32ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) { 32ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) {
33 Object* object = Kernel::g_handle_table.GetGeneric(handle); 33 Object* object = Kernel::g_handle_table.GetGeneric(handle).get();
34 if (object == nullptr) 34 if (object == nullptr)
35 return InvalidHandle(ErrorModule::Kernel); 35 return InvalidHandle(ErrorModule::Kernel);
36 36
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:
53 * @return Result of operation, 0 on success, otherwise error code 53 * @return Result of operation, 0 on success, otherwise error code
54 */ 54 */
55ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) { 55ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) {
56 Event* evt = g_handle_table.Get<Event>(handle); 56 Event* evt = g_handle_table.Get<Event>(handle).get();
57 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 57 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
58 58
59 evt->permanent_locked = permanent_locked; 59 evt->permanent_locked = permanent_locked;
@@ -67,7 +67,7 @@ ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) {
67 * @return Result of operation, 0 on success, otherwise error code 67 * @return Result of operation, 0 on success, otherwise error code
68 */ 68 */
69ResultCode SetEventLocked(const Handle handle, const bool locked) { 69ResultCode SetEventLocked(const Handle handle, const bool locked) {
70 Event* evt = g_handle_table.Get<Event>(handle); 70 Event* evt = g_handle_table.Get<Event>(handle).get();
71 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 71 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
72 72
73 if (!evt->permanent_locked) { 73 if (!evt->permanent_locked) {
@@ -82,13 +82,13 @@ ResultCode SetEventLocked(const Handle handle, const bool locked) {
82 * @return Result of operation, 0 on success, otherwise error code 82 * @return Result of operation, 0 on success, otherwise error code
83 */ 83 */
84ResultCode SignalEvent(const Handle handle) { 84ResultCode SignalEvent(const Handle handle) {
85 Event* evt = g_handle_table.Get<Event>(handle); 85 Event* evt = g_handle_table.Get<Event>(handle).get();
86 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 86 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
87 87
88 // Resume threads waiting for event to signal 88 // Resume threads waiting for event to signal
89 bool event_caught = false; 89 bool event_caught = false;
90 for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { 90 for (size_t i = 0; i < evt->waiting_threads.size(); ++i) {
91 Thread* thread = Kernel::g_handle_table.Get<Thread>(evt->waiting_threads[i]); 91 Thread* thread = Kernel::g_handle_table.Get<Thread>(evt->waiting_threads[i]).get();
92 if (thread != nullptr) 92 if (thread != nullptr)
93 thread->ResumeFromWait(); 93 thread->ResumeFromWait();
94 94
@@ -112,7 +112,7 @@ ResultCode SignalEvent(const Handle handle) {
112 * @return Result of operation, 0 on success, otherwise error code 112 * @return Result of operation, 0 on success, otherwise error code
113 */ 113 */
114ResultCode ClearEvent(Handle handle) { 114ResultCode ClearEvent(Handle handle) {
115 Event* evt = g_handle_table.Get<Event>(handle); 115 Event* evt = g_handle_table.Get<Event>(handle).get();
116 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 116 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
117 117
118 if (!evt->permanent_locked) { 118 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 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17Thread* g_main_thread = nullptr; 17SharedPtr<Thread> g_main_thread = nullptr;
18HandleTable g_handle_table; 18HandleTable g_handle_table;
19u64 g_program_id = 0; 19u64 g_program_id = 0;
20 20
@@ -23,7 +23,7 @@ HandleTable::HandleTable() {
23 Clear(); 23 Clear();
24} 24}
25 25
26ResultVal<Handle> HandleTable::Create(Object* obj) { 26ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
27 _dbg_assert_(Kernel, obj != nullptr); 27 _dbg_assert_(Kernel, obj != nullptr);
28 28
29 u16 slot = next_free_slot; 29 u16 slot = next_free_slot;
@@ -39,22 +39,23 @@ ResultVal<Handle> HandleTable::Create(Object* obj) {
39 // CTR-OS doesn't use generation 0, so skip straight to 1. 39 // CTR-OS doesn't use generation 0, so skip straight to 1.
40 if (next_generation >= (1 << 15)) next_generation = 1; 40 if (next_generation >= (1 << 15)) next_generation = 1;
41 41
42 Handle handle = generation | (slot << 15);
43 if (obj->handle == INVALID_HANDLE)
44 obj->handle = handle;
45
42 generations[slot] = generation; 46 generations[slot] = generation;
43 intrusive_ptr_add_ref(obj); 47 objects[slot] = std::move(obj);
44 objects[slot] = obj;
45 48
46 Handle handle = generation | (slot << 15);
47 obj->handle = handle;
48 return MakeResult<Handle>(handle); 49 return MakeResult<Handle>(handle);
49} 50}
50 51
51ResultVal<Handle> HandleTable::Duplicate(Handle handle) { 52ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
52 Object* object = GetGeneric(handle); 53 SharedPtr<Object> object = GetGeneric(handle);
53 if (object == nullptr) { 54 if (object == nullptr) {
54 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle); 55 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
55 return ERR_INVALID_HANDLE; 56 return ERR_INVALID_HANDLE;
56 } 57 }
57 return Create(object); 58 return Create(std::move(object));
58} 59}
59 60
60ResultCode HandleTable::Close(Handle handle) { 61ResultCode HandleTable::Close(Handle handle) {
@@ -64,7 +65,6 @@ ResultCode HandleTable::Close(Handle handle) {
64 size_t slot = GetSlot(handle); 65 size_t slot = GetSlot(handle);
65 u16 generation = GetGeneration(handle); 66 u16 generation = GetGeneration(handle);
66 67
67 intrusive_ptr_release(objects[slot]);
68 objects[slot] = nullptr; 68 objects[slot] = nullptr;
69 69
70 generations[generation] = next_free_slot; 70 generations[generation] = next_free_slot;
@@ -79,7 +79,7 @@ bool HandleTable::IsValid(Handle handle) const {
79 return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation; 79 return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
80} 80}
81 81
82Object* HandleTable::GetGeneric(Handle handle) const { 82SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
83 if (handle == CurrentThread) { 83 if (handle == CurrentThread) {
84 return GetCurrentThread(); 84 return GetCurrentThread();
85 } else if (handle == CurrentProcess) { 85 } else if (handle == CurrentProcess) {
@@ -96,8 +96,6 @@ Object* HandleTable::GetGeneric(Handle handle) const {
96void HandleTable::Clear() { 96void HandleTable::Clear() {
97 for (size_t i = 0; i < MAX_COUNT; ++i) { 97 for (size_t i = 0; i < MAX_COUNT; ++i) {
98 generations[i] = i + 1; 98 generations[i] = i + 1;
99 if (objects[i] != nullptr)
100 intrusive_ptr_release(objects[i]);
101 objects[i] = nullptr; 99 objects[i] = nullptr;
102 } 100 }
103 next_free_slot = 0; 101 next_free_slot = 0;
@@ -125,7 +123,7 @@ bool LoadExec(u32 entry_point) {
125 Core::g_app_core->SetPC(entry_point); 123 Core::g_app_core->SetPC(entry_point);
126 124
127 // 0x30 is the typical main thread priority I've seen used so far 125 // 0x30 is the typical main thread priority I've seen used so far
128 g_main_thread = Kernel::SetupMainThread(0x30); 126 g_main_thread = Kernel::SetupMainThread(0x30, Kernel::DEFAULT_STACK_SIZE);
129 // Setup the idle thread 127 // Setup the idle thread
130 Kernel::SetupIdleThread(); 128 Kernel::SetupIdleThread();
131 129
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 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <boost/intrusive_ptr.hpp>
8
7#include <array> 9#include <array>
8#include <string> 10#include <string>
9#include "common/common.h" 11#include "common/common.h"
@@ -52,7 +54,7 @@ class HandleTable;
52 54
53class Object : NonCopyable { 55class Object : NonCopyable {
54 friend class HandleTable; 56 friend class HandleTable;
55 u32 handle; 57 u32 handle = INVALID_HANDLE;
56public: 58public:
57 virtual ~Object() {} 59 virtual ~Object() {}
58 Handle GetHandle() const { return handle; } 60 Handle GetHandle() const { return handle; }
@@ -76,7 +78,7 @@ private:
76 unsigned int ref_count = 0; 78 unsigned int ref_count = 0;
77}; 79};
78 80
79// Special functions that will later be used by boost::instrusive_ptr to do automatic ref-counting 81// Special functions used by boost::instrusive_ptr to do automatic ref-counting
80inline void intrusive_ptr_add_ref(Object* object) { 82inline void intrusive_ptr_add_ref(Object* object) {
81 ++object->ref_count; 83 ++object->ref_count;
82} 84}
@@ -87,6 +89,9 @@ inline void intrusive_ptr_release(Object* object) {
87 } 89 }
88} 90}
89 91
92template <typename T>
93using SharedPtr = boost::intrusive_ptr<T>;
94
90/** 95/**
91 * This class allows the creation of Handles, which are references to objects that can be tested 96 * This class allows the creation of Handles, which are references to objects that can be tested
92 * for validity and looked up. Here they are used to pass references to kernel objects to/from the 97 * for validity and looked up. Here they are used to pass references to kernel objects to/from the
@@ -119,7 +124,7 @@ public:
119 * @return The created Handle or one of the following errors: 124 * @return The created Handle or one of the following errors:
120 * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded. 125 * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
121 */ 126 */
122 ResultVal<Handle> Create(Object* obj); 127 ResultVal<Handle> Create(SharedPtr<Object> obj);
123 128
124 /** 129 /**
125 * Returns a new handle that points to the same object as the passed in handle. 130 * Returns a new handle that points to the same object as the passed in handle.
@@ -143,7 +148,7 @@ public:
143 * Looks up a handle. 148 * Looks up a handle.
144 * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid. 149 * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid.
145 */ 150 */
146 Object* GetGeneric(Handle handle) const; 151 SharedPtr<Object> GetGeneric(Handle handle) const;
147 152
148 /** 153 /**
149 * Looks up a handle while verifying its type. 154 * Looks up a handle while verifying its type.
@@ -151,10 +156,10 @@ public:
151 * type differs from the handle type `T::HANDLE_TYPE`. 156 * type differs from the handle type `T::HANDLE_TYPE`.
152 */ 157 */
153 template <class T> 158 template <class T>
154 T* Get(Handle handle) const { 159 SharedPtr<T> Get(Handle handle) const {
155 Object* object = GetGeneric(handle); 160 SharedPtr<Object> object = GetGeneric(handle);
156 if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) { 161 if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
157 return static_cast<T*>(object); 162 return boost::static_pointer_cast<T>(std::move(object));
158 } 163 }
159 return nullptr; 164 return nullptr;
160 } 165 }
@@ -173,7 +178,7 @@ private:
173 static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; } 178 static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; }
174 179
175 /// Stores the Object referenced by the handle or null if the slot is empty. 180 /// Stores the Object referenced by the handle or null if the slot is empty.
176 std::array<Object*, MAX_COUNT> objects; 181 std::array<SharedPtr<Object>, MAX_COUNT> objects;
177 182
178 /** 183 /**
179 * The value of `next_generation` when the handle was created, used to check for validity. For 184 * The value of `next_generation` when the handle was created, used to check for validity. For
@@ -192,7 +197,7 @@ private:
192}; 197};
193 198
194extern HandleTable g_handle_table; 199extern HandleTable g_handle_table;
195extern Thread* g_main_thread; 200extern SharedPtr<Thread> g_main_thread;
196 201
197/// The ID code of the currently running game 202/// The ID code of the currently running game
198/// TODO(Subv): This variable should not be here, 203/// 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
48bool ReleaseMutexForThread(Mutex* mutex, Handle thread_handle) { 48bool ReleaseMutexForThread(Mutex* mutex, Handle thread_handle) {
49 MutexAcquireLock(mutex, thread_handle); 49 MutexAcquireLock(mutex, thread_handle);
50 50
51 Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle); 51 Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle).get();
52 if (thread == nullptr) { 52 if (thread == nullptr) {
53 LOG_ERROR(Kernel, "Called with invalid handle: %08X", thread_handle); 53 LOG_ERROR(Kernel, "Called with invalid handle: %08X", thread_handle);
54 return false; 54 return false;
@@ -94,7 +94,7 @@ void ReleaseThreadMutexes(Handle thread) {
94 94
95 // Release every mutex that the thread holds, and resume execution on the waiting threads 95 // Release every mutex that the thread holds, and resume execution on the waiting threads
96 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { 96 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
97 Mutex* mutex = g_handle_table.Get<Mutex>(iter->second); 97 Mutex* mutex = g_handle_table.Get<Mutex>(iter->second).get();
98 ResumeWaitingThread(mutex); 98 ResumeWaitingThread(mutex);
99 } 99 }
100 100
@@ -122,7 +122,7 @@ bool ReleaseMutex(Mutex* mutex) {
122 * @param handle Handle to mutex to release 122 * @param handle Handle to mutex to release
123 */ 123 */
124ResultCode ReleaseMutex(Handle handle) { 124ResultCode ReleaseMutex(Handle handle) {
125 Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle); 125 Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle).get();
126 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel); 126 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
127 127
128 if (!ReleaseMutex(mutex)) { 128 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,
70} 70}
71 71
72ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { 72ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
73 Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle); 73 Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get();
74 if (semaphore == nullptr) 74 if (semaphore == nullptr)
75 return InvalidHandle(ErrorModule::Kernel); 75 return InvalidHandle(ErrorModule::Kernel);
76 76
@@ -84,7 +84,7 @@ ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
84 // Notify some of the threads that the semaphore has been released 84 // Notify some of the threads that the semaphore has been released
85 // stop once the semaphore is full again or there are no more waiting threads 85 // stop once the semaphore is full again or there are no more waiting threads
86 while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) { 86 while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) {
87 Thread* thread = Kernel::g_handle_table.Get<Thread>(semaphore->waiting_threads.front()); 87 Thread* thread = Kernel::g_handle_table.Get<Thread>(semaphore->waiting_threads.front()).get();
88 if (thread != nullptr) 88 if (thread != nullptr)
89 thread->ResumeFromWait(); 89 thread->ResumeFromWait();
90 semaphore->waiting_threads.pop(); 90 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
61 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 61 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
62 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 62 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
63 } 63 }
64 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); 64 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get();
65 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); 65 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
66 66
67 shared_memory->base_address = address; 67 shared_memory->base_address = address;
@@ -72,7 +72,7 @@ ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions
72} 72}
73 73
74ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) { 74ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) {
75 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); 75 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get();
76 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); 76 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
77 77
78 if (0 != shared_memory->base_address) 78 if (0 != shared_memory->base_address)
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 6d126099b..bc86a7c59 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -36,7 +36,7 @@ ResultVal<bool> Thread::WaitSynchronization() {
36} 36}
37 37
38// Lists all thread ids that aren't deleted/etc. 38// Lists all thread ids that aren't deleted/etc.
39static std::vector<Thread*> thread_list; // TODO(yuriks): Owned 39static std::vector<SharedPtr<Thread>> thread_list;
40 40
41// Lists only ready thread ids. 41// Lists only ready thread ids.
42static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> thread_ready_queue; 42static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> thread_ready_queue;
@@ -110,8 +110,8 @@ void Thread::Stop(const char* reason) {
110 110
111 ChangeReadyState(this, false); 111 ChangeReadyState(this, false);
112 status = THREADSTATUS_DORMANT; 112 status = THREADSTATUS_DORMANT;
113 for (Thread* waiting_thread : waiting_threads) { 113 for (auto& waiting_thread : waiting_threads) {
114 if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, this)) 114 if (CheckWaitType(waiting_thread.get(), WAITTYPE_THREADEND, this))
115 waiting_thread->ResumeFromWait(); 115 waiting_thread->ResumeFromWait();
116 } 116 }
117 waiting_threads.clear(); 117 waiting_threads.clear();
@@ -143,15 +143,15 @@ Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address) {
143 s32 priority = THREADPRIO_LOWEST; 143 s32 priority = THREADPRIO_LOWEST;
144 144
145 // Iterate through threads, find highest priority thread that is waiting to be arbitrated... 145 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
146 for (Thread* thread : thread_list) { 146 for (auto& thread : thread_list) {
147 if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) 147 if (!CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address))
148 continue; 148 continue;
149 149
150 if (thread == nullptr) 150 if (thread == nullptr)
151 continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up. 151 continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up.
152 152
153 if(thread->current_priority <= priority) { 153 if(thread->current_priority <= priority) {
154 highest_priority_thread = thread; 154 highest_priority_thread = thread.get();
155 priority = thread->current_priority; 155 priority = thread->current_priority;
156 } 156 }
157 } 157 }
@@ -168,8 +168,8 @@ Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address) {
168void ArbitrateAllThreads(Object* arbiter, u32 address) { 168void ArbitrateAllThreads(Object* arbiter, u32 address) {
169 169
170 // Iterate through threads, find highest priority thread that is waiting to be arbitrated... 170 // Iterate through threads, find highest priority thread that is waiting to be arbitrated...
171 for (Thread* thread : thread_list) { 171 for (auto& thread : thread_list) {
172 if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) 172 if (CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address))
173 thread->ResumeFromWait(); 173 thread->ResumeFromWait();
174 } 174 }
175} 175}
@@ -241,7 +241,7 @@ static int ThreadWakeupEventType = -1;
241/// Callback that will wake up the thread it was scheduled for 241/// Callback that will wake up the thread it was scheduled for
242static void ThreadWakeupCallback(u64 parameter, int cycles_late) { 242static void ThreadWakeupCallback(u64 parameter, int cycles_late) {
243 Handle handle = static_cast<Handle>(parameter); 243 Handle handle = static_cast<Handle>(parameter);
244 Thread* thread = Kernel::g_handle_table.Get<Thread>(handle); 244 SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(handle);
245 if (thread == nullptr) { 245 if (thread == nullptr) {
246 LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); 246 LOG_ERROR(Kernel, "Thread doesn't exist %u", handle);
247 return; 247 return;
@@ -281,20 +281,18 @@ static void DebugThreadQueue() {
281 return; 281 return;
282 } 282 }
283 LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle()); 283 LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle());
284 for (Thread* t : thread_list) { 284 for (auto& t : thread_list) {
285 s32 priority = thread_ready_queue.contains(t); 285 s32 priority = thread_ready_queue.contains(t.get());
286 if (priority != -1) { 286 if (priority != -1) {
287 LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle()); 287 LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle());
288 } 288 }
289 } 289 }
290} 290}
291 291
292ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priority, u32 arg, 292ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority,
293 s32 processor_id, u32 stack_top, int stack_size) { 293 u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size) {
294 _dbg_assert_(Kernel, name != nullptr); 294 if (stack_size < 0x200) {
295 295 LOG_ERROR(Kernel, "(name=%s): invalid stack_size=0x%08X", name.c_str(), stack_size);
296 if ((u32)stack_size < 0x200) {
297 LOG_ERROR(Kernel, "(name=%s): invalid stack_size=0x%08X", name, stack_size);
298 // TODO: Verify error 296 // TODO: Verify error
299 return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Kernel, 297 return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Kernel,
300 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 298 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
@@ -303,27 +301,26 @@ ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priorit
303 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { 301 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
304 s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 302 s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
305 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 303 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d",
306 name, priority, new_priority); 304 name.c_str(), priority, new_priority);
307 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm 305 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
308 // validity of this 306 // validity of this
309 priority = new_priority; 307 priority = new_priority;
310 } 308 }
311 309
312 if (!Memory::GetPointer(entry_point)) { 310 if (!Memory::GetPointer(entry_point)) {
313 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name, entry_point); 311 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point);
314 // TODO: Verify error 312 // TODO: Verify error
315 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 313 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
316 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 314 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
317 } 315 }
318 316
319 Thread* thread = new Thread; 317 SharedPtr<Thread> thread(new Thread);
320 318
321 // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for 319 // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for
322 // the time being. Create a handle here, it will be copied to the handle field in 320 // the time being. Create a handle here, it will be copied to the handle field in
323 // the object and use by the rest of the code. This should be removed when other 321 // the object and use by the rest of the code. This should be removed when other
324 // code doesn't rely on the handle anymore. 322 // code doesn't rely on the handle anymore.
325 ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread); 323 ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread);
326 // TODO(yuriks): Plug memory leak
327 if (handle.Failed()) 324 if (handle.Failed())
328 return handle.Code(); 325 return handle.Code();
329 326
@@ -340,12 +337,12 @@ ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priorit
340 thread->wait_type = WAITTYPE_NONE; 337 thread->wait_type = WAITTYPE_NONE;
341 thread->wait_object = nullptr; 338 thread->wait_object = nullptr;
342 thread->wait_address = 0; 339 thread->wait_address = 0;
343 thread->name = name; 340 thread->name = std::move(name);
344 341
345 ResetThread(thread, arg, 0); 342 ResetThread(thread.get(), arg, 0);
346 CallThread(thread); 343 CallThread(thread.get());
347 344
348 return MakeResult<Thread*>(thread); 345 return MakeResult<SharedPtr<Thread>>(std::move(thread));
349} 346}
350 347
351/// Set the priority of the thread specified by handle 348/// Set the priority of the thread specified by handle
@@ -379,20 +376,20 @@ Handle SetupIdleThread() {
379 auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0, 376 auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0,
380 THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE); 377 THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE);
381 _dbg_assert_(Kernel, thread_res.Succeeded()); 378 _dbg_assert_(Kernel, thread_res.Succeeded());
382 Thread* thread = *thread_res; 379 SharedPtr<Thread> thread = std::move(*thread_res);
383 380
384 thread->idle = true; 381 thread->idle = true;
385 CallThread(thread); 382 CallThread(thread.get());
386 return thread->GetHandle(); 383 return thread->GetHandle();
387} 384}
388 385
389Thread* SetupMainThread(s32 priority, int stack_size) { 386SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) {
390 // Initialize new "main" thread 387 // Initialize new "main" thread
391 ResultVal<Thread*> thread_res = Thread::Create("main", Core::g_app_core->GetPC(), priority, 0, 388 auto thread_res = Thread::Create("main", Core::g_app_core->GetPC(), priority, 0,
392 THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); 389 THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size);
393 // TODO(yuriks): Propagate error 390 // TODO(yuriks): Propagate error
394 _dbg_assert_(Kernel, thread_res.Succeeded()); 391 _dbg_assert_(Kernel, thread_res.Succeeded());
395 Thread* thread = *thread_res; 392 SharedPtr<Thread> thread = std::move(*thread_res);
396 393
397 // If running another thread already, set it to "ready" state 394 // If running another thread already, set it to "ready" state
398 Thread* cur = GetCurrentThread(); 395 Thread* cur = GetCurrentThread();
@@ -401,7 +398,7 @@ Thread* SetupMainThread(s32 priority, int stack_size) {
401 } 398 }
402 399
403 // Run new "main" thread 400 // Run new "main" thread
404 current_thread = thread; 401 current_thread = thread.get();
405 thread->status = THREADSTATUS_RUNNING; 402 thread->status = THREADSTATUS_RUNNING;
406 Core::g_app_core->LoadContext(thread->context); 403 Core::g_app_core->LoadContext(thread->context);
407 404
@@ -421,7 +418,7 @@ void Reschedule() {
421 } else { 418 } else {
422 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); 419 LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle());
423 420
424 for (Thread* thread : thread_list) { 421 for (auto& thread : thread_list) {
425 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X", 422 LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X",
426 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, 423 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type,
427 (thread->wait_object ? thread->wait_object->GetHandle() : INVALID_HANDLE)); 424 (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 {
54 54
55class Thread : public Kernel::Object { 55class Thread : public Kernel::Object {
56public: 56public:
57 static ResultVal<Thread*> Create(const char* name, u32 entry_point, s32 priority, u32 arg, 57 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
58 s32 processor_id, u32 stack_top, int stack_size = Kernel::DEFAULT_STACK_SIZE); 58 u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size);
59 59
60 std::string GetName() const override { return name; } 60 std::string GetName() const override { return name; }
61 std::string GetTypeName() const override { return "Thread"; } 61 std::string GetTypeName() const override { return "Thread"; }
@@ -99,7 +99,7 @@ public:
99 Object* wait_object; 99 Object* wait_object;
100 VAddr wait_address; 100 VAddr wait_address;
101 101
102 std::vector<Thread*> waiting_threads; // TODO(yuriks): Owned 102 std::vector<SharedPtr<Thread>> waiting_threads;
103 103
104 std::string name; 104 std::string name;
105 105
@@ -111,7 +111,7 @@ private:
111}; 111};
112 112
113/// Sets up the primary application thread 113/// Sets up the primary application thread
114Thread* SetupMainThread(s32 priority, int stack_size = Kernel::DEFAULT_STACK_SIZE); 114SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size);
115 115
116/// Reschedules to the next available thread (call after current thread is suspended) 116/// Reschedules to the next available thread (call after current thread is suspended)
117void Reschedule(); 117void 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
66} 66}
67 67
68ResultCode ClearTimer(Handle handle) { 68ResultCode ClearTimer(Handle handle) {
69 Timer* timer = Kernel::g_handle_table.Get<Timer>(handle); 69 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
70 70
71 if (timer == nullptr) 71 if (timer == nullptr)
72 return InvalidHandle(ErrorModule::Kernel); 72 return InvalidHandle(ErrorModule::Kernel);
@@ -80,7 +80,7 @@ static int TimerCallbackEventType = -1;
80 80
81/// The timer callback event, called when a timer is fired 81/// The timer callback event, called when a timer is fired
82static void TimerCallback(u64 timer_handle, int cycles_late) { 82static void TimerCallback(u64 timer_handle, int cycles_late) {
83 Timer* timer = Kernel::g_handle_table.Get<Timer>(timer_handle); 83 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle);
84 84
85 if (timer == nullptr) { 85 if (timer == nullptr) {
86 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle); 86 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle);
@@ -93,7 +93,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
93 93
94 // Resume all waiting threads 94 // Resume all waiting threads
95 for (Handle thread_handle : timer->waiting_threads) { 95 for (Handle thread_handle : timer->waiting_threads) {
96 if (Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle)) 96 if (SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(thread_handle))
97 thread->ResumeFromWait(); 97 thread->ResumeFromWait();
98 } 98 }
99 99
@@ -111,7 +111,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
111} 111}
112 112
113ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { 113ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
114 Timer* timer = Kernel::g_handle_table.Get<Timer>(handle); 114 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
115 115
116 if (timer == nullptr) 116 if (timer == nullptr)
117 return InvalidHandle(ErrorModule::Kernel); 117 return InvalidHandle(ErrorModule::Kernel);
@@ -125,7 +125,7 @@ ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
125} 125}
126 126
127ResultCode CancelTimer(Handle handle) { 127ResultCode CancelTimer(Handle handle) {
128 Timer* timer = Kernel::g_handle_table.Get<Timer>(handle); 128 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
129 129
130 if (timer == nullptr) 130 if (timer == nullptr)
131 return InvalidHandle(ErrorModule::Kernel); 131 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:
369 369
370 StorageType storage; 370 StorageType storage;
371 ResultCode result_code; 371 ResultCode result_code;
372#if _DEBUG 372#ifdef _DEBUG
373 // The purpose of this pointer is to aid inspecting the type with a debugger, eliminating the 373 // The purpose of this pointer is to aid inspecting the type with a debugger, eliminating the
374 // need to cast `storage` to a pointer or pay attention to `result_code`. 374 // need to cast `storage` to a pointer or pay attention to `result_code`.
375 const T* debug_ptr; 375 const T* debug_ptr;
376#endif 376#endif
377 377
378 void UpdateDebugPtr() { 378 void UpdateDebugPtr() {
379#if _DEBUG 379#ifdef _DEBUG
380 debug_ptr = empty() ? nullptr : static_cast<const T*>(static_cast<const void*>(&storage)); 380 debug_ptr = empty() ? nullptr : static_cast<const T*>(static_cast<const void*>(&storage));
381#endif 381#endif
382 } 382 }
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) {
52 Kernel::ReleaseMutex(lock_handle); 52 Kernel::ReleaseMutex(lock_handle);
53 53
54 cmd_buff[1] = 0; // No error 54 cmd_buff[1] = 0; // No error
55
56 LOG_DEBUG(Service_APT, "called");
57} 55}
58 56
59void GetLockHandle(Service::Interface* self) { 57void GetLockHandle(Service::Interface* self) {
@@ -194,8 +192,6 @@ void AppletUtility(Service::Interface* self) {
194 * 4 : Handle to shared font memory 192 * 4 : Handle to shared font memory
195 */ 193 */
196void GetSharedFont(Service::Interface* self) { 194void GetSharedFont(Service::Interface* self) {
197 LOG_TRACE(Kernel_SVC, "called");
198
199 u32* cmd_buff = Kernel::GetCommandBuffer(); 195 u32* cmd_buff = Kernel::GetCommandBuffer();
200 196
201 if (!shared_font.empty()) { 197 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) {
27 // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per 27 // TODO(Link Mauve): check the behavior when cmd_buff[1] isn't 32, as per
28 // http://3dbrew.org/wiki/FS:Initialize#Request 28 // http://3dbrew.org/wiki/FS:Initialize#Request
29 cmd_buff[1] = RESULT_SUCCESS.raw; 29 cmd_buff[1] = RESULT_SUCCESS.raw;
30
31 LOG_DEBUG(Service_FS, "called");
32} 30}
33 31
34/** 32/**
@@ -104,8 +102,8 @@ static void OpenFileDirectly(Service::Interface* self) {
104 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); 102 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
105 FileSys::Path file_path(filename_type, filename_size, filename_ptr); 103 FileSys::Path file_path(filename_type, filename_size, filename_ptr);
106 104
107 LOG_DEBUG(Service_FS, "archive_path=%s file_path=%s, mode=%u attributes=%d", 105 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s file_path=%s, mode=%u attributes=%d",
108 archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes); 106 archive_id, archive_path.DebugStr().c_str(), file_path.DebugStr().c_str(), mode.hex, attributes);
109 107
110 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path); 108 ResultVal<ArchiveHandle> archive_handle = OpenArchive(archive_id, archive_path);
111 if (archive_handle.Failed()) { 109 if (archive_handle.Failed()) {
@@ -367,7 +365,7 @@ static void OpenArchive(Service::Interface* self) {
367 u32 archivename_ptr = cmd_buff[5]; 365 u32 archivename_ptr = cmd_buff[5];
368 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr); 366 FileSys::Path archive_path(archivename_type, archivename_size, archivename_ptr);
369 367
370 LOG_DEBUG(Service_FS, "archive_path=%s", archive_path.DebugStr().c_str()); 368 LOG_DEBUG(Service_FS, "archive_id=0x%08X archive_path=%s", archive_id, archive_path.DebugStr().c_str());
371 369
372 ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path); 370 ResultVal<ArchiveHandle> handle = OpenArchive(archive_id, archive_path);
373 cmd_buff[1] = handle.Code().raw; 371 cmd_buff[1] = handle.Code().raw;
@@ -408,8 +406,6 @@ static void IsSdmcDetected(Service::Interface* self) {
408 406
409 cmd_buff[1] = 0; 407 cmd_buff[1] = 0;
410 cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0; 408 cmd_buff[2] = Settings::values.use_virtual_sd ? 1 : 0;
411
412 LOG_DEBUG(Service_FS, "called");
413} 409}
414 410
415/** 411/**
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) {
331 331
332/// This triggers handling of the GX command written to the command buffer in shared memory. 332/// This triggers handling of the GX command written to the command buffer in shared memory.
333static void TriggerCmdReqQueue(Service::Interface* self) { 333static void TriggerCmdReqQueue(Service::Interface* self) {
334
335 LOG_TRACE(Service_GSP, "called");
336
337 // Iterate through each thread's command queue... 334 // Iterate through each thread's command queue...
338 for (unsigned thread_id = 0; thread_id < 0x4; ++thread_id) { 335 for (unsigned thread_id = 0; thread_id < 0x4; ++thread_id) {
339 CommandBuffer* command_buffer = (CommandBuffer*)GetCommandBuffer(thread_id); 336 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) {
163 cmd_buff[6] = event_accelerometer; 163 cmd_buff[6] = event_accelerometer;
164 cmd_buff[7] = event_gyroscope; 164 cmd_buff[7] = event_gyroscope;
165 cmd_buff[8] = event_debug_pad; 165 cmd_buff[8] = event_debug_pad;
166
167 LOG_TRACE(Service_HID, "called");
168} 166}
169 167
170const Interface::FunctionInfo FunctionTable[] = { 168const 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) {
76 76
77 cmd_buff[1] = 0; 77 cmd_buff[1] = 0;
78 cmd_buff[2] = shell_open ? 1 : 0; 78 cmd_buff[2] = shell_open ? 1 : 0;
79
80 LOG_TRACE(Service_PTM, "PTM_U::GetShellState called");
81} 79}
82 80
83/** 81/**
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) {
59} 59}
60 60
61Interface* Manager::FetchFromHandle(Handle handle) { 61Interface* Manager::FetchFromHandle(Handle handle) {
62 return Kernel::g_handle_table.Get<Interface>(handle); 62 // TODO(yuriks): This function is very suspicious and should probably be exterminated.
63 return Kernel::g_handle_table.Get<Interface>(handle).get();
63} 64}
64 65
65Interface* Manager::FetchFromPortName(const std::string& port_name) { 66Interface* 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 {
33 // processes. 33 // processes.
34 34
35 friend class Manager; 35 friend class Manager;
36
37 /**
38 * Creates a function string for logging, complete with the name (or header code, depending
39 * on what's passed in) the port name, and all the cmd_buff arguments.
40 */
41 std::string MakeFunctionString(const std::string& name, const std::string& port_name, const u32* cmd_buff) {
42 // Number of params == bits 0-5 + bits 6-11
43 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F);
44
45 std::string function_string = Common::StringFromFormat("function '%s': port=%s", name.c_str(), port_name.c_str());
46 for (int i = 1; i <= num_params; ++i) {
47 function_string += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]);
48 }
49 return function_string;
50 }
51
36public: 52public:
37 std::string GetName() const override { return GetPortName(); } 53 std::string GetName() const override { return GetPortName(); }
38 54
@@ -72,21 +88,14 @@ public:
72 auto itr = m_functions.find(cmd_buff[0]); 88 auto itr = m_functions.find(cmd_buff[0]);
73 89
74 if (itr == m_functions.end() || itr->second.func == nullptr) { 90 if (itr == m_functions.end() || itr->second.func == nullptr) {
75 // Number of params == bits 0-5 + bits 6-11 91 std::string function_name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name;
76 int num_params = (cmd_buff[0] & 0x3F) + ((cmd_buff[0] >> 6) & 0x3F); 92 LOG_ERROR(Service, "%s %s", "unknown/unimplemented", MakeFunctionString(function_name, GetPortName(), cmd_buff).c_str());
77
78 std::string error = "unknown/unimplemented function '%s': port=%s";
79 for (int i = 1; i <= num_params; ++i) {
80 error += Common::StringFromFormat(", cmd_buff[%i]=%u", i, cmd_buff[i]);
81 }
82
83 std::string name = (itr == m_functions.end()) ? Common::StringFromFormat("0x%08X", cmd_buff[0]) : itr->second.name;
84
85 LOG_ERROR(Service, error.c_str(), name.c_str(), GetPortName().c_str());
86 93
87 // TODO(bunnei): Hack - ignore error 94 // TODO(bunnei): Hack - ignore error
88 cmd_buff[1] = 0; 95 cmd_buff[1] = 0;
89 return MakeResult<bool>(false); 96 return MakeResult<bool>(false);
97 } else {
98 LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName(), cmd_buff).c_str());
90 } 99 }
91 100
92 itr->second.func(this); 101 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 {
14static Handle g_event_handle = 0; 14static Handle g_event_handle = 0;
15 15
16static void Initialize(Service::Interface* self) { 16static void Initialize(Service::Interface* self) {
17 LOG_DEBUG(Service_SRV, "called");
18
19 u32* cmd_buff = Kernel::GetCommandBuffer(); 17 u32* cmd_buff = Kernel::GetCommandBuffer();
20 18
21 cmd_buff[1] = 0; // No error 19 cmd_buff[1] = 0; // No error
22} 20}
23 21
24static void GetProcSemaphore(Service::Interface* self) { 22static void GetProcSemaphore(Service::Interface* self) {
25 LOG_TRACE(Service_SRV, "called");
26
27 u32* cmd_buff = Kernel::GetCommandBuffer(); 23 u32* cmd_buff = Kernel::GetCommandBuffer();
28 24
29 // TODO(bunnei): Change to a semaphore once these have been implemented 25 // 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 @@
12 12
13namespace Y2R_U { 13namespace Y2R_U {
14 14
15/**
16 * Y2R_U::IsBusyConversion service function
17 * Outputs:
18 * 1 : Result of function, 0 on success, otherwise error code
19 * 2 : Whether the current conversion is of type busy conversion (?)
20 */
21static void IsBusyConversion(Service::Interface* self) {
22 u32* cmd_buff = Kernel::GetCommandBuffer();
23
24 cmd_buff[1] = RESULT_SUCCESS.raw;;
25 cmd_buff[2] = 0;
26
27 LOG_WARNING(Service, "(STUBBED) called");
28}
29
15const Interface::FunctionInfo FunctionTable[] = { 30const Interface::FunctionInfo FunctionTable[] = {
16 {0x00010040, nullptr, "SetInputFormat"}, 31 {0x00010040, nullptr, "SetInputFormat"},
17 {0x00030040, nullptr, "SetOutputFormat"}, 32 {0x00030040, nullptr, "SetOutputFormat"},
@@ -29,7 +44,7 @@ const Interface::FunctionInfo FunctionTable[] = {
29 {0x00220040, nullptr, "SetAlpha"}, 44 {0x00220040, nullptr, "SetAlpha"},
30 {0x00260000, nullptr, "StartConversion"}, 45 {0x00260000, nullptr, "StartConversion"},
31 {0x00270000, nullptr, "StopConversion"}, 46 {0x00270000, nullptr, "StopConversion"},
32 {0x00280000, nullptr, "IsBusyConversion"}, 47 {0x00280000, IsBusyConversion, "IsBusyConversion"},
33 {0x002A0000, nullptr, "PingProcess"}, 48 {0x002A0000, nullptr, "PingProcess"},
34 {0x002B0000, nullptr, "DriverInitialize"}, 49 {0x002B0000, nullptr, "DriverInitialize"},
35 {0x002C0000, nullptr, "DriverFinalize"} 50 {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 @@
25//////////////////////////////////////////////////////////////////////////////////////////////////// 25////////////////////////////////////////////////////////////////////////////////////////////////////
26// Namespace SVC 26// Namespace SVC
27 27
28using Kernel::SharedPtr;
29
28namespace SVC { 30namespace SVC {
29 31
30enum ControlMemoryOperation { 32enum ControlMemoryOperation {
@@ -94,7 +96,7 @@ static Result ConnectToPort(Handle* out, const char* port_name) {
94 96
95/// Synchronize to an OS service 97/// Synchronize to an OS service
96static Result SendSyncRequest(Handle handle) { 98static Result SendSyncRequest(Handle handle) {
97 Kernel::Session* session = Kernel::g_handle_table.Get<Kernel::Session>(handle); 99 SharedPtr<Kernel::Session> session = Kernel::g_handle_table.Get<Kernel::Session>(handle);
98 if (session == nullptr) { 100 if (session == nullptr) {
99 return InvalidHandle(ErrorModule::Kernel).raw; 101 return InvalidHandle(ErrorModule::Kernel).raw;
100 } 102 }
@@ -121,12 +123,12 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
121 // TODO(bunnei): Do something with nano_seconds, currently ignoring this 123 // TODO(bunnei): Do something with nano_seconds, currently ignoring this
122 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated 124 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
123 125
124 Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handle); 126 SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handle);
125 if (object == nullptr) 127 if (object == nullptr)
126 return InvalidHandle(ErrorModule::Kernel).raw; 128 return InvalidHandle(ErrorModule::Kernel).raw;
127 129
128 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), 130 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle,
129 object->GetName().c_str(), nano_seconds); 131 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds);
130 132
131 ResultVal<bool> wait = object->WaitSynchronization(); 133 ResultVal<bool> wait = object->WaitSynchronization();
132 134
@@ -151,12 +153,12 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
151 153
152 // Iterate through each handle, synchronize kernel object 154 // Iterate through each handle, synchronize kernel object
153 for (s32 i = 0; i < handle_count; i++) { 155 for (s32 i = 0; i < handle_count; i++) {
154 Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handles[i]); 156 SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handles[i]);
155 if (object == nullptr) 157 if (object == nullptr)
156 return InvalidHandle(ErrorModule::Kernel).raw; 158 return InvalidHandle(ErrorModule::Kernel).raw;
157 159
158 LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), 160 LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i],
159 object->GetName().c_str()); 161 object->GetTypeName().c_str(), object->GetName().c_str());
160 162
161 // TODO(yuriks): Verify how the real function behaves when an error happens here 163 // TODO(yuriks): Verify how the real function behaves when an error happens here
162 ResultVal<bool> wait_result = object->WaitSynchronization(); 164 ResultVal<bool> wait_result = object->WaitSynchronization();
@@ -183,7 +185,6 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
183 185
184/// Create an address arbiter (to allocate access to shared resources) 186/// Create an address arbiter (to allocate access to shared resources)
185static Result CreateAddressArbiter(u32* arbiter) { 187static Result CreateAddressArbiter(u32* arbiter) {
186 LOG_TRACE(Kernel_SVC, "called");
187 Handle handle = Kernel::CreateAddressArbiter(); 188 Handle handle = Kernel::CreateAddressArbiter();
188 *arbiter = handle; 189 *arbiter = handle;
189 return 0; 190 return 0;
@@ -223,6 +224,8 @@ static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit,
223 224
224/// Creates a new thread 225/// Creates a new thread
225static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { 226static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) {
227 using Kernel::Thread;
228
226 std::string name; 229 std::string name;
227 if (Symbols::HasSymbol(entry_point)) { 230 if (Symbols::HasSymbol(entry_point)) {
228 TSymbol symbol = Symbols::GetSymbol(entry_point); 231 TSymbol symbol = Symbols::GetSymbol(entry_point);
@@ -231,12 +234,13 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top
231 name = Common::StringFromFormat("unknown-%08x", entry_point); 234 name = Common::StringFromFormat("unknown-%08x", entry_point);
232 } 235 }
233 236
234 ResultVal<Kernel::Thread*> thread_res = Kernel::Thread::Create(name.c_str(), entry_point, priority, arg, 237 ResultVal<SharedPtr<Thread>> thread_res = Kernel::Thread::Create(
235 processor_id, stack_top); 238 name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE);
236 if (thread_res.Failed()) 239 if (thread_res.Failed())
237 return thread_res.Code().raw; 240 return thread_res.Code().raw;
238 Kernel::Thread* thread = *thread_res; 241 SharedPtr<Thread> thread = std::move(*thread_res);
239 242
243 // TODO(yuriks): Create new handle instead of using built-in
240 Core::g_app_core->SetReg(1, thread->GetHandle()); 244 Core::g_app_core->SetReg(1, thread->GetHandle());
241 245
242 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " 246 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
@@ -261,7 +265,7 @@ static void ExitThread() {
261 265
262/// Gets the priority for the specified thread 266/// Gets the priority for the specified thread
263static Result GetThreadPriority(s32* priority, Handle handle) { 267static Result GetThreadPriority(s32* priority, Handle handle) {
264 const Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); 268 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
265 if (thread == nullptr) 269 if (thread == nullptr)
266 return InvalidHandle(ErrorModule::Kernel).raw; 270 return InvalidHandle(ErrorModule::Kernel).raw;
267 271
@@ -271,7 +275,7 @@ static Result GetThreadPriority(s32* priority, Handle handle) {
271 275
272/// Sets the priority for the specified thread 276/// Sets the priority for the specified thread
273static Result SetThreadPriority(Handle handle, s32 priority) { 277static Result SetThreadPriority(Handle handle, s32 priority) {
274 Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); 278 SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
275 if (thread == nullptr) 279 if (thread == nullptr)
276 return InvalidHandle(ErrorModule::Kernel).raw; 280 return InvalidHandle(ErrorModule::Kernel).raw;
277 281
@@ -298,7 +302,7 @@ static Result ReleaseMutex(Handle handle) {
298static Result GetThreadId(u32* thread_id, Handle handle) { 302static Result GetThreadId(u32* thread_id, Handle handle) {
299 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); 303 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle);
300 304
301 const Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); 305 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
302 if (thread == nullptr) 306 if (thread == nullptr)
303 return InvalidHandle(ErrorModule::Kernel).raw; 307 return InvalidHandle(ErrorModule::Kernel).raw;
304 308