summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2015-01-30 15:00:17 +0100
committerGravatar Tony Wasserka2015-01-30 15:00:17 +0100
commit28702cbfeb1fe21109f8b1efa189785594319b78 (patch)
tree64e4b1ec43b7699fe1a6ab1be1c688b6d63c0d75 /src
parentMerge pull request #412 from purpasmart96/svc_table_cleanup (diff)
parentKernel: Mark all appropriate kernel objects as "final" (diff)
downloadyuzu-28702cbfeb1fe21109f8b1efa189785594319b78.tar.gz
yuzu-28702cbfeb1fe21109f8b1efa189785594319b78.tar.xz
yuzu-28702cbfeb1fe21109f8b1efa189785594319b78.zip
Merge pull request #503 from yuriks/kernel-lifetime4
Kernel Lifetime Reform Pt. 4
Diffstat (limited to 'src')
-rw-r--r--src/common/common_funcs.h4
-rw-r--r--src/common/scope_exit.h4
-rw-r--r--src/core/hle/function_wrappers.h79
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp42
-rw-r--r--src/core/hle/kernel/address_arbiter.h27
-rw-r--r--src/core/hle/kernel/event.cpp83
-rw-r--r--src/core/hle/kernel/event.h51
-rw-r--r--src/core/hle/kernel/kernel.h8
-rw-r--r--src/core/hle/kernel/mutex.cpp143
-rw-r--r--src/core/hle/kernel/mutex.h52
-rw-r--r--src/core/hle/kernel/semaphore.cpp65
-rw-r--r--src/core/hle/kernel/semaphore.h57
-rw-r--r--src/core/hle/kernel/shared_memory.cpp73
-rw-r--r--src/core/hle/kernel/shared_memory.h60
-rw-r--r--src/core/hle/kernel/thread.h3
-rw-r--r--src/core/hle/kernel/timer.cpp107
-rw-r--r--src/core/hle/kernel/timer.h69
-rw-r--r--src/core/hle/result.h31
-rw-r--r--src/core/hle/service/apt_s.cpp1
-rw-r--r--src/core/hle/service/apt_u.cpp44
-rw-r--r--src/core/hle/service/dsp_dsp.cpp26
-rw-r--r--src/core/hle/service/fs/archive.cpp23
-rw-r--r--src/core/hle/service/gsp_gpu.cpp31
-rw-r--r--src/core/hle/service/hid/hid.cpp32
-rw-r--r--src/core/hle/service/hid/hid.h17
-rw-r--r--src/core/hle/service/hid/hid_user.cpp15
-rw-r--r--src/core/hle/service/srv.cpp8
-rw-r--r--src/core/hle/svc.cpp296
-rw-r--r--src/core/mem_map.h11
29 files changed, 728 insertions, 734 deletions
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index c2750a63c..229eb74c9 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -31,6 +31,10 @@ template<> struct CompileTimeAssert<true> {};
31 31
32#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 32#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
33 33
34/// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
35#define CONCAT2(x, y) DO_CONCAT2(x, y)
36#define DO_CONCAT2(x, y) x ## y
37
34#ifndef _MSC_VER 38#ifndef _MSC_VER
35 39
36#include <errno.h> 40#include <errno.h>
diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h
index 263beaf0e..77dcbaa22 100644
--- a/src/common/scope_exit.h
+++ b/src/common/scope_exit.h
@@ -4,6 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/common_funcs.h"
8
7namespace detail { 9namespace detail {
8 template <typename Func> 10 template <typename Func>
9 struct ScopeExitHelper { 11 struct ScopeExitHelper {
@@ -34,4 +36,4 @@ namespace detail {
34 * } 36 * }
35 * \endcode 37 * \endcode
36 */ 38 */
37#define SCOPE_EXIT(body) auto scope_exit_helper_##__LINE__ = detail::ScopeExit([&]() body) 39#define SCOPE_EXIT(body) auto CONCAT2(scope_exit_helper_, __LINE__) = detail::ScopeExit([&]() body)
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h
index a2f51b41b..0b6b6f518 100644
--- a/src/core/hle/function_wrappers.h
+++ b/src/core/hle/function_wrappers.h
@@ -33,114 +33,105 @@ static inline void FuncReturn64(u64 res) {
33} 33}
34 34
35//////////////////////////////////////////////////////////////////////////////////////////////////// 35////////////////////////////////////////////////////////////////////////////////////////////////////
36// Function wrappers that return type s32 36// Function wrappers that return type ResultCode
37 37
38template<s32 func(u32, u32, u32, u32)> void Wrap() { 38template<ResultCode func(u32, u32, u32, u32)> void Wrap() {
39 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3))); 39 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)).raw);
40} 40}
41 41
42template<s32 func(u32, u32, u32, u32, u32)> void Wrap() { 42template<ResultCode func(u32*, u32, u32, u32, u32, u32)> void Wrap(){
43 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)));
44}
45
46template<s32 func(u32*, u32, u32, u32, u32, u32)> void Wrap(){
47 u32 param_1 = 0; 43 u32 param_1 = 0;
48 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); 44 u32 retval = func(&param_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
49 Core::g_app_core->SetReg(1, param_1); 45 Core::g_app_core->SetReg(1, param_1);
50 FuncReturn(retval); 46 FuncReturn(retval);
51} 47}
52 48
53template<s32 func(s32*, u32*, s32, bool, s64)> void Wrap() { 49template<ResultCode func(s32*, u32*, s32, bool, s64)> void Wrap() {
54 s32 param_1 = 0; 50 s32 param_1 = 0;
55 s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), 51 s32 retval = func(&param_1, (Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2),
56 (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))); 52 (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))).raw;
57 Core::g_app_core->SetReg(1, (u32)param_1); 53 Core::g_app_core->SetReg(1, (u32)param_1);
58 FuncReturn(retval); 54 FuncReturn(retval);
59} 55}
60 56
61// TODO(bunnei): Is this correct? Probably not - Last parameter looks wrong for ArbitrateAddress 57template<ResultCode func(u32, u32, u32, u32, s64)> void Wrap() {
62template<s32 func(u32, u32, u32, u32, s64)> void Wrap() { 58 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(5) << 32) | PARAM(4))).raw);
63 FuncReturn(func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), (((s64)PARAM(5) << 32) | PARAM(4))));
64} 59}
65 60
66template<s32 func(u32*)> void Wrap(){ 61template<ResultCode func(u32*)> void Wrap(){
67 u32 param_1 = 0; 62 u32 param_1 = 0;
68 u32 retval = func(&param_1); 63 u32 retval = func(&param_1).raw;
69 Core::g_app_core->SetReg(1, param_1); 64 Core::g_app_core->SetReg(1, param_1);
70 FuncReturn(retval); 65 FuncReturn(retval);
71} 66}
72 67
73template<s32 func(u32, s64)> void Wrap() { 68template<ResultCode func(u32, s64)> void Wrap() {
74 FuncReturn(func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2)))); 69 FuncReturn(func(PARAM(0), (((s64)PARAM(3) << 32) | PARAM(2))).raw);
75} 70}
76 71
77template<s32 func(void*, void*, u32)> void Wrap(){ 72template<ResultCode func(void*, void*, u32)> void Wrap(){
78 FuncReturn(func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2))); 73 FuncReturn(func(Memory::GetPointer(PARAM(0)), Memory::GetPointer(PARAM(1)), PARAM(2)).raw);
79} 74}
80 75
81template<s32 func(s32*, u32)> void Wrap(){ 76template<ResultCode func(s32*, u32)> void Wrap(){
82 s32 param_1 = 0; 77 s32 param_1 = 0;
83 u32 retval = func(&param_1, PARAM(1)); 78 u32 retval = func(&param_1, PARAM(1)).raw;
84 Core::g_app_core->SetReg(1, param_1); 79 Core::g_app_core->SetReg(1, param_1);
85 FuncReturn(retval); 80 FuncReturn(retval);
86} 81}
87 82
88template<s32 func(u32, s32)> void Wrap() { 83template<ResultCode func(u32, s32)> void Wrap() {
89 FuncReturn(func(PARAM(0), (s32)PARAM(1))); 84 FuncReturn(func(PARAM(0), (s32)PARAM(1)).raw);
90} 85}
91 86
92template<s32 func(u32*, u32)> void Wrap(){ 87template<ResultCode func(u32*, u32)> void Wrap(){
93 u32 param_1 = 0; 88 u32 param_1 = 0;
94 u32 retval = func(&param_1, PARAM(1)); 89 u32 retval = func(&param_1, PARAM(1)).raw;
95 Core::g_app_core->SetReg(1, param_1); 90 Core::g_app_core->SetReg(1, param_1);
96 FuncReturn(retval); 91 FuncReturn(retval);
97} 92}
98 93
99template<s32 func(u32)> void Wrap() { 94template<ResultCode func(u32)> void Wrap() {
100 FuncReturn(func(PARAM(0))); 95 FuncReturn(func(PARAM(0)).raw);
101}
102
103template<s32 func(void*)> void Wrap() {
104 FuncReturn(func(Memory::GetPointer(PARAM(0))));
105} 96}
106 97
107template<s32 func(s64*, u32, void*, s32)> void Wrap(){ 98template<ResultCode func(s64*, u32, void*, s32)> void Wrap(){
108 FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)), 99 FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), Memory::GetPointer(PARAM(2)),
109 (s32)PARAM(3))); 100 (s32)PARAM(3)).raw);
110} 101}
111 102
112template<s32 func(u32*, const char*)> void Wrap() { 103template<ResultCode func(u32*, const char*)> void Wrap() {
113 u32 param_1 = 0; 104 u32 param_1 = 0;
114 u32 retval = func(&param_1, Memory::GetCharPointer(PARAM(1))); 105 u32 retval = func(&param_1, Memory::GetCharPointer(PARAM(1))).raw;
115 Core::g_app_core->SetReg(1, param_1); 106 Core::g_app_core->SetReg(1, param_1);
116 FuncReturn(retval); 107 FuncReturn(retval);
117} 108}
118 109
119template<s32 func(u32*, s32, s32)> void Wrap() { 110template<ResultCode func(u32*, s32, s32)> void Wrap() {
120 u32 param_1 = 0; 111 u32 param_1 = 0;
121 u32 retval = func(&param_1, PARAM(1), PARAM(2)); 112 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
122 Core::g_app_core->SetReg(1, param_1); 113 Core::g_app_core->SetReg(1, param_1);
123 FuncReturn(retval); 114 FuncReturn(retval);
124} 115}
125 116
126template<s32 func(s32*, u32, s32)> void Wrap() { 117template<ResultCode func(s32*, u32, s32)> void Wrap() {
127 s32 param_1 = 0; 118 s32 param_1 = 0;
128 u32 retval = func(&param_1, PARAM(1), PARAM(2)); 119 u32 retval = func(&param_1, PARAM(1), PARAM(2)).raw;
129 Core::g_app_core->SetReg(1, param_1); 120 Core::g_app_core->SetReg(1, param_1);
130 FuncReturn(retval); 121 FuncReturn(retval);
131} 122}
132 123
133template<s32 func(u32*, u32, u32, u32, u32)> void Wrap() { 124template<ResultCode func(u32*, u32, u32, u32, u32)> void Wrap() {
134 u32 param_1 = 0; 125 u32 param_1 = 0;
135 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3), PARAM(4)); 126 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw;
136 Core::g_app_core->SetReg(1, param_1); 127 Core::g_app_core->SetReg(1, param_1);
137 FuncReturn(retval); 128 FuncReturn(retval);
138} 129}
139 130
140template<s32 func(u32, s64, s64)> void Wrap() { 131template<ResultCode func(u32, s64, s64)> void Wrap() {
141 s64 param1 = ((u64)PARAM(3) << 32) | PARAM(2); 132 s64 param1 = ((u64)PARAM(3) << 32) | PARAM(2);
142 s64 param2 = ((u64)PARAM(4) << 32) | PARAM(1); 133 s64 param2 = ((u64)PARAM(4) << 32) | PARAM(1);
143 FuncReturn(func(PARAM(0), param1, param2)); 134 FuncReturn(func(PARAM(0), param1, param2).raw);
144} 135}
145 136
146//////////////////////////////////////////////////////////////////////////////////////////////////// 137////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 9e855b0bf..2d01e2ef5 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -15,26 +15,18 @@
15 15
16namespace Kernel { 16namespace Kernel {
17 17
18class AddressArbiter : public Object { 18ResultVal<SharedPtr<AddressArbiter>> AddressArbiter::Create(std::string name) {
19public: 19 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter);
20 std::string GetTypeName() const override { return "Arbiter"; } 20 // TOOD(yuriks): Don't create Handle (see Thread::Create())
21 std::string GetName() const override { return name; } 21 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(address_arbiter));
22 22
23 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; 23 address_arbiter->name = std::move(name);
24 HandleType GetHandleType() const override { return HANDLE_TYPE; }
25 24
26 std::string name; ///< Name of address arbiter object (optional) 25 return MakeResult<SharedPtr<AddressArbiter>>(std::move(address_arbiter));
27}; 26}
28
29////////////////////////////////////////////////////////////////////////////////////////////////////
30
31/// Arbitrate an address
32ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds) {
33 AddressArbiter* object = Kernel::g_handle_table.Get<AddressArbiter>(handle).get();
34
35 if (object == nullptr)
36 return InvalidHandle(ErrorModule::Kernel);
37 27
28ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value,
29 u64 nanoseconds) {
38 switch (type) { 30 switch (type) {
39 31
40 // Signal thread(s) waiting for arbitrate address... 32 // Signal thread(s) waiting for arbitrate address...
@@ -92,20 +84,4 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3
92 return RESULT_SUCCESS; 84 return RESULT_SUCCESS;
93} 85}
94 86
95/// Create an address arbiter
96AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) {
97 AddressArbiter* address_arbiter = new AddressArbiter;
98 // TOOD(yuriks): Fix error reporting
99 handle = Kernel::g_handle_table.Create(address_arbiter).ValueOr(INVALID_HANDLE);
100 address_arbiter->name = name;
101 return address_arbiter;
102}
103
104/// Create an address arbiter
105Handle CreateAddressArbiter(const std::string& name) {
106 Handle handle;
107 CreateAddressArbiter(handle, name);
108 return handle;
109}
110
111} // namespace Kernel 87} // namespace Kernel
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 3ffd465a2..638afff9e 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -18,7 +18,6 @@
18 18
19namespace Kernel { 19namespace Kernel {
20 20
21/// Address arbitration types
22enum class ArbitrationType : u32 { 21enum class ArbitrationType : u32 {
23 Signal, 22 Signal,
24 WaitIfLessThan, 23 WaitIfLessThan,
@@ -27,10 +26,28 @@ enum class ArbitrationType : u32 {
27 DecrementAndWaitIfLessThanWithTimeout, 26 DecrementAndWaitIfLessThanWithTimeout,
28}; 27};
29 28
30/// Arbitrate an address 29class AddressArbiter final : public Object {
31ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value, u64 nanoseconds); 30public:
31 /**
32 * Creates an address arbiter.
33 *
34 * @param name Optional name used for debugging.
35 * @returns The created AddressArbiter.
36 */
37 static ResultVal<SharedPtr<AddressArbiter>> Create(std::string name = "Unknown");
32 38
33/// Create an address arbiter 39 std::string GetTypeName() const override { return "Arbiter"; }
34Handle CreateAddressArbiter(const std::string& name = "Unknown"); 40 std::string GetName() const override { return name; }
41
42 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
43 HandleType GetHandleType() const override { return HANDLE_TYPE; }
44
45 std::string name; ///< Name of address arbiter object (optional)
46
47 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds);
48
49private:
50 AddressArbiter() = default;
51};
35 52
36} // namespace FileSys 53} // namespace FileSys
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index a48125965..d9ad40c6a 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -14,78 +14,37 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17class Event : public WaitObject { 17ResultVal<SharedPtr<Event>> Event::Create(ResetType reset_type, std::string name) {
18public: 18 SharedPtr<Event> evt(new Event);
19 std::string GetTypeName() const override { return "Event"; } 19 // TOOD(yuriks): Don't create Handle (see Thread::Create())
20 std::string GetName() const override { return name; } 20 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(evt));
21
22 static const HandleType HANDLE_TYPE = HandleType::Event;
23 HandleType GetHandleType() const override { return HANDLE_TYPE; }
24
25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization
26 ResetType reset_type; ///< Current ResetType
27
28 bool signaled; ///< Whether the event has already been signaled
29 std::string name; ///< Name of event (optional)
30
31 bool ShouldWait() override {
32 return !signaled;
33 }
34
35 void Acquire() override {
36 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
37
38 // Release the event if it's not sticky...
39 if (reset_type != RESETTYPE_STICKY)
40 signaled = false;
41 }
42};
43
44ResultCode SignalEvent(const Handle handle) {
45 Event* evt = g_handle_table.Get<Event>(handle).get();
46 if (evt == nullptr)
47 return InvalidHandle(ErrorModule::Kernel);
48
49 evt->signaled = true;
50 evt->WakeupAllWaitingThreads();
51
52 return RESULT_SUCCESS;
53}
54
55ResultCode ClearEvent(Handle handle) {
56 Event* evt = g_handle_table.Get<Event>(handle).get();
57 if (evt == nullptr)
58 return InvalidHandle(ErrorModule::Kernel);
59 21
60 evt->signaled = false; 22 evt->signaled = false;
23 evt->reset_type = evt->intitial_reset_type = reset_type;
24 evt->name = std::move(name);
61 25
62 return RESULT_SUCCESS; 26 return MakeResult<SharedPtr<Event>>(evt);
63} 27}
64 28
65/** 29bool Event::ShouldWait() {
66 * Creates an event 30 return !signaled;
67 * @param handle Reference to handle for the newly created mutex 31}
68 * @param reset_type ResetType describing how to create event
69 * @param name Optional name of event
70 * @return Newly created Event object
71 */
72Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) {
73 Event* evt = new Event;
74 32
75 // TOOD(yuriks): Fix error reporting 33void Event::Acquire() {
76 handle = Kernel::g_handle_table.Create(evt).ValueOr(INVALID_HANDLE); 34 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
77 35
78 evt->signaled = false; 36 // Release the event if it's not sticky...
79 evt->reset_type = evt->intitial_reset_type = reset_type; 37 if (reset_type != RESETTYPE_STICKY)
80 evt->name = name; 38 signaled = false;
39}
81 40
82 return evt; 41void Event::Signal() {
42 signaled = true;
43 WakeupAllWaitingThreads();
83} 44}
84 45
85Handle CreateEvent(const ResetType reset_type, const std::string& name) { 46void Event::Clear() {
86 Handle handle; 47 signaled = false;
87 Event* evt = CreateEvent(handle, reset_type, name);
88 return handle;
89} 48}
90 49
91} // namespace 50} // namespace
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index c08b12ee1..2c3e6b14e 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -11,26 +11,35 @@
11 11
12namespace Kernel { 12namespace Kernel {
13 13
14/** 14class Event final : public WaitObject {
15 * Signals an event 15public:
16 * @param handle Handle to event to signal 16 /**
17 * @return Result of operation, 0 on success, otherwise error code 17 * Creates an event
18 */ 18 * @param reset_type ResetType describing how to create event
19ResultCode SignalEvent(const Handle handle); 19 * @param name Optional name of event
20 20 */
21/** 21 static ResultVal<SharedPtr<Event>> Create(ResetType reset_type, std::string name = "Unknown");
22 * Clears an event 22
23 * @param handle Handle to event to clear 23 std::string GetTypeName() const override { return "Event"; }
24 * @return Result of operation, 0 on success, otherwise error code 24 std::string GetName() const override { return name; }
25 */ 25
26ResultCode ClearEvent(Handle handle); 26 static const HandleType HANDLE_TYPE = HandleType::Event;
27 27 HandleType GetHandleType() const override { return HANDLE_TYPE; }
28/** 28
29 * Creates an event 29 ResetType intitial_reset_type; ///< ResetType specified at Event initialization
30 * @param reset_type ResetType describing how to create event 30 ResetType reset_type; ///< Current ResetType
31 * @param name Optional name of event 31
32 * @return Handle to newly created Event object 32 bool signaled; ///< Whether the event has already been signaled
33 */ 33 std::string name; ///< Name of event (optional)
34Handle CreateEvent(const ResetType reset_type, const std::string& name="Unknown"); 34
35 bool ShouldWait() override;
36 void Acquire() override;
37
38 void Signal();
39 void Clear();
40
41private:
42 Event() = default;
43};
35 44
36} // namespace 45} // namespace
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 3828efbea..9860479ac 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -16,6 +16,11 @@
16typedef u32 Handle; 16typedef u32 Handle;
17typedef s32 Result; 17typedef s32 Result;
18 18
19// TODO: It would be nice to eventually replace these with strong types that prevent accidental
20// conversion between each other.
21typedef u32 VAddr; ///< Represents a pointer in the userspace virtual address space.
22typedef u32 PAddr; ///< Represents a pointer in the ARM11 physical address space.
23
19const Handle INVALID_HANDLE = 0; 24const Handle INVALID_HANDLE = 0;
20 25
21namespace Kernel { 26namespace Kernel {
@@ -26,7 +31,8 @@ class Thread;
26const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, 31const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
27 ErrorSummary::OutOfResource, ErrorLevel::Temporary); 32 ErrorSummary::OutOfResource, ErrorLevel::Temporary);
28// TOOD: Verify code 33// TOOD: Verify code
29const ResultCode ERR_INVALID_HANDLE = InvalidHandle(ErrorModule::Kernel); 34const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel,
35 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
30 36
31enum KernelHandle : Handle { 37enum KernelHandle : Handle {
32 CurrentThread = 0xFFFF8000, 38 CurrentThread = 0xFFFF8000,
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index cd05a1397..acf484659 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -13,59 +13,30 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16class Mutex : public WaitObject {
17public:
18 std::string GetTypeName() const override { return "Mutex"; }
19 std::string GetName() const override { return name; }
20
21 static const HandleType HANDLE_TYPE = HandleType::Mutex;
22 HandleType GetHandleType() const override { return HANDLE_TYPE; }
23
24 bool initial_locked; ///< Initial lock state when mutex was created
25 bool locked; ///< Current locked state
26 std::string name; ///< Name of mutex (optional)
27 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
28
29 bool ShouldWait() override;
30 void Acquire() override;
31};
32
33////////////////////////////////////////////////////////////////////////////////////////////////////
34
35typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap; 16typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap;
36static MutexMap g_mutex_held_locks; 17static MutexMap g_mutex_held_locks;
37 18
38/** 19/**
39 * Acquires the specified mutex for the specified thread
40 * @param mutex Mutex that is to be acquired
41 * @param thread Thread that will acquire the mutex
42 */
43void MutexAcquireLock(Mutex* mutex, Thread* thread) {
44 g_mutex_held_locks.insert(std::make_pair(thread, mutex));
45 mutex->holding_thread = thread;
46}
47
48/**
49 * Resumes a thread waiting for the specified mutex 20 * Resumes a thread waiting for the specified mutex
50 * @param mutex The mutex that some thread is waiting on 21 * @param mutex The mutex that some thread is waiting on
51 */ 22 */
52void ResumeWaitingThread(Mutex* mutex) { 23static void ResumeWaitingThread(Mutex* mutex) {
24 // Reset mutex lock thread handle, nothing is waiting
25 mutex->locked = false;
26 mutex->holding_thread = nullptr;
27
53 // Find the next waiting thread for the mutex... 28 // Find the next waiting thread for the mutex...
54 auto next_thread = mutex->WakeupNextThread(); 29 auto next_thread = mutex->WakeupNextThread();
55 if (next_thread != nullptr) { 30 if (next_thread != nullptr) {
56 MutexAcquireLock(mutex, next_thread); 31 mutex->Acquire(next_thread);
57 } else {
58 // Reset mutex lock thread handle, nothing is waiting
59 mutex->locked = false;
60 mutex->holding_thread = nullptr;
61 } 32 }
62} 33}
63 34
64void ReleaseThreadMutexes(Thread* thread) { 35void ReleaseThreadMutexes(Thread* thread) {
65 auto locked = g_mutex_held_locks.equal_range(thread); 36 auto locked_range = g_mutex_held_locks.equal_range(thread);
66 37
67 // Release every mutex that the thread holds, and resume execution on the waiting threads 38 // Release every mutex that the thread holds, and resume execution on the waiting threads
68 for (auto iter = locked.first; iter != locked.second; ++iter) { 39 for (auto iter = locked_range.first; iter != locked_range.second; ++iter) {
69 ResumeWaitingThread(iter->second.get()); 40 ResumeWaitingThread(iter->second.get());
70 } 41 }
71 42
@@ -73,72 +44,21 @@ void ReleaseThreadMutexes(Thread* thread) {
73 g_mutex_held_locks.erase(thread); 44 g_mutex_held_locks.erase(thread);
74} 45}
75 46
76bool ReleaseMutex(Mutex* mutex) { 47ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) {
77 if (mutex->locked) { 48 SharedPtr<Mutex> mutex(new Mutex);
78 auto locked = g_mutex_held_locks.equal_range(mutex->holding_thread); 49 // TOOD(yuriks): Don't create Handle (see Thread::Create())
79 50 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex));
80 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
81 if (iter->second == mutex) {
82 g_mutex_held_locks.erase(iter);
83 break;
84 }
85 }
86
87 ResumeWaitingThread(mutex);
88 }
89 return true;
90}
91 51
92/** 52 mutex->initial_locked = initial_locked;
93 * Releases a mutex 53 mutex->locked = false;
94 * @param handle Handle to mutex to release 54 mutex->name = std::move(name);
95 */
96ResultCode ReleaseMutex(Handle handle) {
97 Mutex* mutex = Kernel::g_handle_table.Get<Mutex>(handle).get();
98 if (mutex == nullptr) return InvalidHandle(ErrorModule::Kernel);
99
100 if (!ReleaseMutex(mutex)) {
101 // TODO(yuriks): Verify error code, this one was pulled out of thin air. I'm not even sure
102 // what error condition this is supposed to be signaling.
103 return ResultCode(ErrorDescription::AlreadyDone, ErrorModule::Kernel,
104 ErrorSummary::NothingHappened, ErrorLevel::Temporary);
105 }
106 return RESULT_SUCCESS;
107}
108
109/**
110 * Creates a mutex
111 * @param handle Reference to handle for the newly created mutex
112 * @param initial_locked Specifies if the mutex should be locked initially
113 * @param name Optional name of mutex
114 * @return Pointer to new Mutex object
115 */
116Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) {
117 Mutex* mutex = new Mutex;
118 // TODO(yuriks): Fix error reporting
119 handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE);
120
121 mutex->locked = mutex->initial_locked = initial_locked;
122 mutex->name = name;
123 mutex->holding_thread = nullptr; 55 mutex->holding_thread = nullptr;
124 56
125 // Acquire mutex with current thread if initialized as locked... 57 // Acquire mutex with current thread if initialized as locked...
126 if (mutex->locked) 58 if (initial_locked)
127 MutexAcquireLock(mutex, GetCurrentThread()); 59 mutex->Acquire();
128
129 return mutex;
130}
131 60
132/** 61 return MakeResult<SharedPtr<Mutex>>(mutex);
133 * Creates a mutex
134 * @param initial_locked Specifies if the mutex should be locked initially
135 * @param name Optional name of mutex
136 * @return Handle to newly created object
137 */
138Handle CreateMutex(bool initial_locked, const std::string& name) {
139 Handle handle;
140 Mutex* mutex = CreateMutex(handle, initial_locked, name);
141 return handle;
142} 62}
143 63
144bool Mutex::ShouldWait() { 64bool Mutex::ShouldWait() {
@@ -146,9 +66,34 @@ bool Mutex::ShouldWait() {
146} 66}
147 67
148void Mutex::Acquire() { 68void Mutex::Acquire() {
69 Acquire(GetCurrentThread());
70}
71
72void Mutex::Acquire(Thread* thread) {
149 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); 73 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
74 if (locked)
75 return;
76
150 locked = true; 77 locked = true;
151 MutexAcquireLock(this, GetCurrentThread()); 78
79 g_mutex_held_locks.insert(std::make_pair(thread, this));
80 holding_thread = thread;
81}
82
83void Mutex::Release() {
84 if (!locked)
85 return;
86
87 auto locked_range = g_mutex_held_locks.equal_range(holding_thread);
88
89 for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) {
90 if (iter->second == this) {
91 g_mutex_held_locks.erase(iter);
92 break;
93 }
94 }
95
96 ResumeWaitingThread(this);
152} 97}
153 98
154} // namespace 99} // namespace
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index bb8778c98..1e69528f1 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -4,25 +4,51 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <string>
8
7#include "common/common_types.h" 9#include "common/common_types.h"
8 10
9#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
10 12
11namespace Kernel { 13namespace Kernel {
12 14
13/** 15class Thread;
14 * Releases a mutex 16
15 * @param handle Handle to mutex to release 17class Mutex final : public WaitObject {
16 */ 18public:
17ResultCode ReleaseMutex(Handle handle); 19 /**
18 20 * Creates a mutex.
19/** 21 * @param initial_locked Specifies if the mutex should be locked initially
20 * Creates a mutex 22 * @param name Optional name of mutex
21 * @param initial_locked Specifies if the mutex should be locked initially 23 * @return Pointer to new Mutex object
22 * @param name Optional name of mutex 24 */
23 * @return Handle to newly created object 25 static ResultVal<SharedPtr<Mutex>> Create(bool initial_locked, std::string name = "Unknown");
24 */ 26
25Handle CreateMutex(bool initial_locked, const std::string& name="Unknown"); 27 std::string GetTypeName() const override { return "Mutex"; }
28 std::string GetName() const override { return name; }
29
30 static const HandleType HANDLE_TYPE = HandleType::Mutex;
31 HandleType GetHandleType() const override { return HANDLE_TYPE; }
32
33 bool initial_locked; ///< Initial lock state when mutex was created
34 bool locked; ///< Current locked state
35 std::string name; ///< Name of mutex (optional)
36 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
37
38 bool ShouldWait() override;
39 void Acquire() override;
40
41 /**
42 * Acquires the specified mutex for the specified thread
43 * @param mutex Mutex that is to be acquired
44 * @param thread Thread that will acquire the mutex
45 */
46 void Acquire(Thread* thread);
47 void Release();
48
49private:
50 Mutex() = default;
51};
26 52
27/** 53/**
28 * Releases all the mutexes held by the specified thread 54 * Releases all the mutexes held by the specified thread
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 135d8fb2a..a9e406ef4 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -2,8 +2,6 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <queue>
6
7#include "common/common.h" 5#include "common/common.h"
8 6
9#include "core/hle/kernel/kernel.h" 7#include "core/hle/kernel/kernel.h"
@@ -12,69 +10,50 @@
12 10
13namespace Kernel { 11namespace Kernel {
14 12
15class Semaphore : public WaitObject { 13ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
16public: 14 std::string name) {
17 std::string GetTypeName() const override { return "Semaphore"; }
18 std::string GetName() const override { return name; }
19
20 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
21 HandleType GetHandleType() const override { return HANDLE_TYPE; }
22
23 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
24 s32 available_count; ///< Number of free slots left in the semaphore
25 std::string name; ///< Name of semaphore (optional)
26
27 bool ShouldWait() override {
28 return available_count <= 0;
29 }
30
31 void Acquire() override {
32 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
33 --available_count;
34 }
35};
36
37////////////////////////////////////////////////////////////////////////////////////////////////////
38
39ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
40 s32 max_count, const std::string& name) {
41 15
42 if (initial_count > max_count) 16 if (initial_count > max_count)
43 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, 17 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
44 ErrorSummary::WrongArgument, ErrorLevel::Permanent); 18 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
45 19
46 Semaphore* semaphore = new Semaphore; 20 SharedPtr<Semaphore> semaphore(new Semaphore);
47 // TOOD(yuriks): Fix error reporting 21 // TOOD(yuriks): Don't create Handle (see Thread::Create())
48 *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE); 22 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore));
49 23
50 // When the semaphore is created, some slots are reserved for other threads, 24 // When the semaphore is created, some slots are reserved for other threads,
51 // and the rest is reserved for the caller thread 25 // and the rest is reserved for the caller thread
52 semaphore->max_count = max_count; 26 semaphore->max_count = max_count;
53 semaphore->available_count = initial_count; 27 semaphore->available_count = initial_count;
54 semaphore->name = name; 28 semaphore->name = std::move(name);
55 29
56 return RESULT_SUCCESS; 30 return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore));
57} 31}
58 32
59ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { 33bool Semaphore::ShouldWait() {
60 Semaphore* semaphore = g_handle_table.Get<Semaphore>(handle).get(); 34 return available_count <= 0;
61 if (semaphore == nullptr) 35}
62 return InvalidHandle(ErrorModule::Kernel); 36
37void Semaphore::Acquire() {
38 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
39 --available_count;
40}
63 41
64 if (semaphore->max_count - semaphore->available_count < release_count) 42ResultVal<s32> Semaphore::Release(s32 release_count) {
43 if (max_count - available_count < release_count)
65 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, 44 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,
66 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 45 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
67 46
68 *count = semaphore->available_count; 47 s32 previous_count = available_count;
69 semaphore->available_count += release_count; 48 available_count += release_count;
70 49
71 // Notify some of the threads that the semaphore has been released 50 // Notify some of the threads that the semaphore has been released
72 // stop once the semaphore is full again or there are no more waiting threads 51 // stop once the semaphore is full again or there are no more waiting threads
73 while (!semaphore->ShouldWait() && semaphore->WakeupNextThread() != nullptr) { 52 while (!ShouldWait() && WakeupNextThread() != nullptr) {
74 semaphore->Acquire(); 53 Acquire();
75 } 54 }
76 55
77 return RESULT_SUCCESS; 56 return MakeResult<s32>(previous_count);
78} 57}
79 58
80} // namespace 59} // namespace
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 8644ecf0c..9bb404ab6 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -4,29 +4,50 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <queue>
8#include <string>
9
7#include "common/common_types.h" 10#include "common/common_types.h"
8 11
9#include "core/hle/kernel/kernel.h" 12#include "core/hle/kernel/kernel.h"
10 13
11namespace Kernel { 14namespace Kernel {
12 15
13/** 16class Semaphore final : public WaitObject {
14 * Creates a semaphore. 17public:
15 * @param handle Pointer to the handle of the newly created object 18 /**
16 * @param initial_count Number of slots reserved for other threads 19 * Creates a semaphore.
17 * @param max_count Maximum number of slots the semaphore can have 20 * @param handle Pointer to the handle of the newly created object
18 * @param name Optional name of semaphore 21 * @param initial_count Number of slots reserved for other threads
19 * @return ResultCode of the error 22 * @param max_count Maximum number of slots the semaphore can have
20 */ 23 * @param name Optional name of semaphore
21ResultCode CreateSemaphore(Handle* handle, s32 initial_count, s32 max_count, const std::string& name = "Unknown"); 24 * @return The created semaphore
22 25 */
23/** 26 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count,
24 * Releases a certain number of slots from a semaphore. 27 std::string name = "Unknown");
25 * @param count The number of free slots the semaphore had before this call 28
26 * @param handle The handle of the semaphore to release 29 std::string GetTypeName() const override { return "Semaphore"; }
27 * @param release_count The number of slots to release 30 std::string GetName() const override { return name; }
28 * @return ResultCode of the error 31
29 */ 32 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
30ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count); 33 HandleType GetHandleType() const override { return HANDLE_TYPE; }
34
35 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
36 s32 available_count; ///< Number of free slots left in the semaphore
37 std::string name; ///< Name of semaphore (optional)
38
39 bool ShouldWait() override;
40 void Acquire() override;
41
42 /**
43 * Releases a certain number of slots from a semaphore.
44 * @param release_count The number of slots to release
45 * @return The number of free slots the semaphore had before this call
46 */
47 ResultVal<s32> Release(s32 release_count);
48
49private:
50 Semaphore() = default;
51};
31 52
32} // namespace 53} // namespace
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 5368e4728..536d134b0 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -9,76 +9,39 @@
9 9
10namespace Kernel { 10namespace Kernel {
11 11
12class SharedMemory : public Object { 12ResultVal<SharedPtr<SharedMemory>> SharedMemory::Create(std::string name) {
13public: 13 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
14 std::string GetTypeName() const override { return "SharedMemory"; }
15 14
16 static const HandleType HANDLE_TYPE = HandleType::SharedMemory; 15 // TOOD(yuriks): Don't create Handle (see Thread::Create())
17 HandleType GetHandleType() const override { return HANDLE_TYPE; } 16 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(shared_memory));
18 17
19 u32 base_address; ///< Address of shared memory block in RAM 18 shared_memory->name = std::move(name);
20 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field) 19 return MakeResult<SharedPtr<SharedMemory>>(std::move(shared_memory));
21 MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field)
22 std::string name; ///< Name of shared memory object (optional)
23};
24
25////////////////////////////////////////////////////////////////////////////////////////////////////
26
27/**
28 * Creates a shared memory object
29 * @param handle Handle of newly created shared memory object
30 * @param name Name of shared memory object
31 * @return Pointer to newly created shared memory object
32 */
33SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) {
34 SharedMemory* shared_memory = new SharedMemory;
35 // TOOD(yuriks): Fix error reporting
36 handle = Kernel::g_handle_table.Create(shared_memory).ValueOr(INVALID_HANDLE);
37 shared_memory->name = name;
38 return shared_memory;
39} 20}
40 21
41Handle CreateSharedMemory(const std::string& name) { 22ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions,
42 Handle handle; 23 MemoryPermission other_permissions) {
43 CreateSharedMemory(handle, name);
44 return handle;
45}
46
47/**
48 * Maps a shared memory block to an address in system memory
49 * @param handle Shared memory block handle
50 * @param address Address in system memory to map shared memory block to
51 * @param permissions Memory block map permissions (specified by SVC field)
52 * @param other_permissions Memory block map other permissions (specified by SVC field)
53 * @return Result of operation, 0 on success, otherwise error code
54 */
55ResultCode MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
56 MemoryPermission other_permissions) {
57 24
58 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { 25 if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) {
59 LOG_ERROR(Kernel_SVC, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", 26 LOG_ERROR(Kernel, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
60 handle, address); 27 GetHandle(), address);
28 // TODO: Verify error code with hardware
61 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 29 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
62 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 30 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
63 } 31 }
64 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get();
65 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel);
66 32
67 shared_memory->base_address = address; 33 base_address = address;
68 shared_memory->permissions = permissions; 34 permissions = permissions;
69 shared_memory->other_permissions = other_permissions; 35 other_permissions = other_permissions;
70 36
71 return RESULT_SUCCESS; 37 return RESULT_SUCCESS;
72} 38}
73 39
74ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset) { 40ResultVal<u8*> SharedMemory::GetPointer(u32 offset) {
75 SharedMemory* shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle).get(); 41 if (base_address != 0)
76 if (shared_memory == nullptr) return InvalidHandle(ErrorModule::Kernel); 42 return MakeResult<u8*>(Memory::GetPointer(base_address + offset));
77
78 if (0 != shared_memory->base_address)
79 return MakeResult<u8*>(Memory::GetPointer(shared_memory->base_address + offset));
80 43
81 LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", handle); 44 LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", GetHandle());
82 // TODO(yuriks): Verify error code. 45 // TODO(yuriks): Verify error code.
83 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 46 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
84 ErrorSummary::InvalidState, ErrorLevel::Permanent); 47 ErrorSummary::InvalidState, ErrorLevel::Permanent);
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index bb65c7ccd..f9ae23e93 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -23,29 +23,41 @@ enum class MemoryPermission : u32 {
23 DontCare = (1u << 28) 23 DontCare = (1u << 28)
24}; 24};
25 25
26/** 26class SharedMemory final : public Object {
27 * Creates a shared memory object 27public:
28 * @param name Optional name of shared memory object 28 /**
29 * @return Handle of newly created shared memory object 29 * Creates a shared memory object
30 */ 30 * @param name Optional object name, used only for debugging purposes.
31Handle CreateSharedMemory(const std::string& name="Unknown"); 31 */
32 32 static ResultVal<SharedPtr<SharedMemory>> Create(std::string name = "Unknown");
33/** 33
34 * Maps a shared memory block to an address in system memory 34 std::string GetTypeName() const override { return "SharedMemory"; }
35 * @param handle Shared memory block handle 35
36 * @param address Address in system memory to map shared memory block to 36 static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
37 * @param permissions Memory block map permissions (specified by SVC field) 37 HandleType GetHandleType() const override { return HANDLE_TYPE; }
38 * @param other_permissions Memory block map other permissions (specified by SVC field) 38
39 */ 39 /**
40ResultCode MapSharedMemory(Handle handle, u32 address, MemoryPermission permissions, 40 * Maps a shared memory block to an address in system memory
41 MemoryPermission other_permissions); 41 * @param address Address in system memory to map shared memory block to
42 42 * @param permissions Memory block map permissions (specified by SVC field)
43/** 43 * @param other_permissions Memory block map other permissions (specified by SVC field)
44 * Gets a pointer to the shared memory block 44 */
45 * @param handle Shared memory block handle 45 ResultCode Map(VAddr address, MemoryPermission permissions, MemoryPermission other_permissions);
46 * @param offset Offset from the start of the shared memory block to get pointer 46
47 * @return Pointer to the shared memory block from the specified offset 47 /**
48 */ 48 * Gets a pointer to the shared memory block
49ResultVal<u8*> GetSharedMemoryPointer(Handle handle, u32 offset); 49 * @param offset Offset from the start of the shared memory block to get pointer
50 * @return Pointer to the shared memory block from the specified offset
51 */
52 ResultVal<u8*> GetPointer(u32 offset = 0);
53
54 VAddr base_address; ///< Address of shared memory block in RAM
55 MemoryPermission permissions; ///< Permissions of shared memory block (SVC field)
56 MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field)
57 std::string name; ///< Name of shared memory object (optional)
58
59private:
60 SharedMemory() = default;
61};
50 62
51} // namespace 63} // namespace
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 5fab1ab58..d6299364a 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -40,7 +40,7 @@ enum ThreadStatus {
40 40
41namespace Kernel { 41namespace Kernel {
42 42
43class Thread : public WaitObject { 43class Thread final : public WaitObject {
44public: 44public:
45 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, 45 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
46 u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size); 46 u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size);
@@ -115,7 +115,6 @@ public:
115 bool idle = false; 115 bool idle = false;
116 116
117private: 117private:
118
119 Thread() = default; 118 Thread() = default;
120}; 119};
121 120
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index ec0b2c323..503a5d2ce 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -13,75 +13,54 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16class Timer : public WaitObject { 16/// The event type of the generic timer callback event
17public: 17static int timer_callback_event_type = -1;
18 std::string GetTypeName() const override { return "Timer"; }
19 std::string GetName() const override { return name; }
20
21 static const HandleType HANDLE_TYPE = HandleType::Timer;
22 HandleType GetHandleType() const override { return HANDLE_TYPE; }
23
24 ResetType reset_type; ///< The ResetType of this timer
25
26 bool signaled; ///< Whether the timer has been signaled or not
27 std::string name; ///< Name of timer (optional)
28
29 u64 initial_delay; ///< The delay until the timer fires for the first time
30 u64 interval_delay; ///< The delay until the timer fires after the first time
31
32 bool ShouldWait() override {
33 return !signaled;
34 }
35
36 void Acquire() override {
37 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
38 }
39};
40
41/**
42 * Creates a timer.
43 * @param handle Reference to handle for the newly created timer
44 * @param reset_type ResetType describing how to create timer
45 * @param name Optional name of timer
46 * @return Newly created Timer object
47 */
48Timer* CreateTimer(Handle& handle, const ResetType reset_type, const std::string& name) {
49 Timer* timer = new Timer;
50 18
51 handle = Kernel::g_handle_table.Create(timer).ValueOr(INVALID_HANDLE); 19ResultVal<SharedPtr<Timer>> Timer::Create(ResetType reset_type, std::string name) {
20 SharedPtr<Timer> timer(new Timer);
21 // TOOD(yuriks): Don't create Handle (see Thread::Create())
22 CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(timer));
52 23
53 timer->reset_type = reset_type; 24 timer->reset_type = reset_type;
54 timer->signaled = false; 25 timer->signaled = false;
55 timer->name = name; 26 timer->name = std::move(name);
56 timer->initial_delay = 0; 27 timer->initial_delay = 0;
57 timer->interval_delay = 0; 28 timer->interval_delay = 0;
58 return timer; 29 return MakeResult<SharedPtr<Timer>>(timer);
59} 30}
60 31
61ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name) { 32bool Timer::ShouldWait() {
62 CreateTimer(*handle, reset_type, name); 33 return !signaled;
63 return RESULT_SUCCESS;
64} 34}
65 35
66ResultCode ClearTimer(Handle handle) { 36void Timer::Acquire() {
67 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); 37 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
68 38}
69 if (timer == nullptr)
70 return InvalidHandle(ErrorModule::Kernel);
71 39
72 timer->signaled = false; 40void Timer::Set(s64 initial, s64 interval) {
73 return RESULT_SUCCESS; 41 initial_delay = initial;
42 interval_delay = interval;
43
44 u64 initial_microseconds = initial / 1000;
45 // TODO(yuriks): Figure out a replacement for GetHandle here
46 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
47 GetHandle());
74} 48}
75 49
76/// The event type of the generic timer callback event 50void Timer::Cancel() {
77static int TimerCallbackEventType = -1; 51 CoreTiming::UnscheduleEvent(timer_callback_event_type, GetHandle());
52}
53
54void Timer::Clear() {
55 signaled = false;
56}
78 57
79/// The timer callback event, called when a timer is fired 58/// The timer callback event, called when a timer is fired
80static void TimerCallback(u64 timer_handle, int cycles_late) { 59static void TimerCallback(u64 timer_handle, int cycles_late) {
81 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle); 60 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle);
82 61
83 if (timer == nullptr) { 62 if (timer == nullptr) {
84 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %u", timer_handle); 63 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle);
85 return; 64 return;
86 } 65 }
87 66
@@ -99,36 +78,12 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
99 // Reschedule the timer with the interval delay 78 // Reschedule the timer with the interval delay
100 u64 interval_microseconds = timer->interval_delay / 1000; 79 u64 interval_microseconds = timer->interval_delay / 1000;
101 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, 80 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
102 TimerCallbackEventType, timer_handle); 81 timer_callback_event_type, timer_handle);
103 } 82 }
104} 83}
105 84
106ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
107 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
108
109 if (timer == nullptr)
110 return InvalidHandle(ErrorModule::Kernel);
111
112 timer->initial_delay = initial;
113 timer->interval_delay = interval;
114
115 u64 initial_microseconds = initial / 1000;
116 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), TimerCallbackEventType, handle);
117 return RESULT_SUCCESS;
118}
119
120ResultCode CancelTimer(Handle handle) {
121 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
122
123 if (timer == nullptr)
124 return InvalidHandle(ErrorModule::Kernel);
125
126 CoreTiming::UnscheduleEvent(TimerCallbackEventType, handle);
127 return RESULT_SUCCESS;
128}
129
130void TimersInit() { 85void TimersInit() {
131 TimerCallbackEventType = CoreTiming::RegisterEvent("TimerCallback", TimerCallback); 86 timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
132} 87}
133 88
134void TimersShutdown() { 89void TimersShutdown() {
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index 8170e82d4..c45e79954 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -11,37 +11,50 @@
11 11
12namespace Kernel { 12namespace Kernel {
13 13
14/** 14class Timer final : public WaitObject {
15 * Cancels a timer 15public:
16 * @param handle Handle of the timer to cancel 16 /**
17 */ 17 * Creates a timer
18ResultCode CancelTimer(Handle handle); 18 * @param reset_type ResetType describing how to create the timer
19 19 * @param name Optional name of timer
20/** 20 * @return The created Timer
21 * Starts a timer with the specified initial delay and interval 21 */
22 * @param handle Handle of the timer to start 22 static ResultVal<SharedPtr<Timer>> Create(ResetType reset_type, std::string name = "Unknown");
23 * @param initial Delay until the timer is first fired 23
24 * @param interval Delay until the timer is fired after the first time 24 std::string GetTypeName() const override { return "Timer"; }
25 */ 25 std::string GetName() const override { return name; }
26ResultCode SetTimer(Handle handle, s64 initial, s64 interval); 26
27 27 static const HandleType HANDLE_TYPE = HandleType::Timer;
28/** 28 HandleType GetHandleType() const override { return HANDLE_TYPE; }
29 * Clears a timer 29
30 * @param handle Handle of the timer to clear 30 ResetType reset_type; ///< The ResetType of this timer
31 */ 31
32ResultCode ClearTimer(Handle handle); 32 bool signaled; ///< Whether the timer has been signaled or not
33 33 std::string name; ///< Name of timer (optional)
34/** 34
35 * Creates a timer 35 u64 initial_delay; ///< The delay until the timer fires for the first time
36 * @param handle Handle to the newly created Timer object 36 u64 interval_delay; ///< The delay until the timer fires after the first time
37 * @param reset_type ResetType describing how to create the timer 37
38 * @param name Optional name of timer 38 bool ShouldWait() override;
39 * @return ResultCode of the error 39 void Acquire() override;
40 */ 40
41ResultCode CreateTimer(Handle* handle, const ResetType reset_type, const std::string& name="Unknown"); 41 /**
42 * Starts the timer, with the specified initial delay and interval.
43 * @param initial Delay until the timer is first fired
44 * @param interval Delay until the timer is fired after the first time
45 */
46 void Set(s64 initial, s64 interval);
47
48 void Cancel();
49 void Clear();
50
51private:
52 Timer() = default;
53};
42 54
43/// Initializes the required variables for timers 55/// Initializes the required variables for timers
44void TimersInit(); 56void TimersInit();
45/// Tears down the timer variables 57/// Tears down the timer variables
46void TimersShutdown(); 58void TimersShutdown();
59
47} // namespace 60} // namespace
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 82dcf5bba..948b9e38e 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -9,8 +9,9 @@
9#include <type_traits> 9#include <type_traits>
10#include <utility> 10#include <utility>
11 11
12#include "common/common_types.h"
13#include "common/bit_field.h" 12#include "common/bit_field.h"
13#include "common/common_funcs.h"
14#include "common/common_types.h"
14 15
15// All the constants in this file come from http://3dbrew.org/wiki/Error_codes 16// All the constants in this file come from http://3dbrew.org/wiki/Error_codes
16 17
@@ -226,11 +227,6 @@ inline ResultCode UnimplementedFunction(ErrorModule module) {
226 return ResultCode(ErrorDescription::NotImplemented, module, 227 return ResultCode(ErrorDescription::NotImplemented, module,
227 ErrorSummary::NotSupported, ErrorLevel::Permanent); 228 ErrorSummary::NotSupported, ErrorLevel::Permanent);
228} 229}
229/// Returned when a function is passed an invalid handle.
230inline ResultCode InvalidHandle(ErrorModule module) {
231 return ResultCode(ErrorDescription::InvalidHandle, module,
232 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
233}
234 230
235/** 231/**
236 * This is an optional value type. It holds a `ResultCode` and, if that code is a success code, 232 * This is an optional value type. It holds a `ResultCode` and, if that code is a success code,
@@ -364,6 +360,17 @@ public:
364 return !empty() ? *GetPointer() : std::move(value); 360 return !empty() ? *GetPointer() : std::move(value);
365 } 361 }
366 362
363 /// Asserts that the result succeeded and returns a reference to it.
364 T& Unwrap() {
365 // TODO(yuriks): Should be a release assert
366 _assert_msg_(Common, Succeeded(), "Tried to Unwrap empty ResultVal");
367 return **this;
368 }
369
370 T&& MoveFrom() {
371 return std::move(Unwrap());
372 }
373
367private: 374private:
368 typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type StorageType; 375 typedef typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type StorageType;
369 376
@@ -400,3 +407,15 @@ template <typename T, typename... Args>
400ResultVal<T> MakeResult(Args&&... args) { 407ResultVal<T> MakeResult(Args&&... args) {
401 return ResultVal<T>::WithCode(RESULT_SUCCESS, std::forward<Args>(args)...); 408 return ResultVal<T>::WithCode(RESULT_SUCCESS, std::forward<Args>(args)...);
402} 409}
410
411/**
412 * Check for the success of `source` (which must evaluate to a ResultVal). If it succeeds, unwraps
413 * the contained value and assigns it to `target`, which can be either an l-value expression or a
414 * variable declaration. If it fails the return code is returned from the current function. Thus it
415 * can be used to cascade errors out, achieving something akin to exception handling.
416 */
417#define CASCADE_RESULT(target, source) \
418 auto CONCAT2(check_result_L, __LINE__) = source; \
419 if (CONCAT2(check_result_L, __LINE__).Failed()) \
420 return CONCAT2(check_result_L, __LINE__).Code(); \
421 target = std::move(*CONCAT2(check_result_L, __LINE__))
diff --git a/src/core/hle/service/apt_s.cpp b/src/core/hle/service/apt_s.cpp
index 31e6653ef..7ad428ee7 100644
--- a/src/core/hle/service/apt_s.cpp
+++ b/src/core/hle/service/apt_s.cpp
@@ -10,6 +10,7 @@
10#include "core/hle/kernel/event.h" 10#include "core/hle/kernel/event.h"
11#include "core/hle/kernel/mutex.h" 11#include "core/hle/kernel/mutex.h"
12#include "core/hle/kernel/shared_memory.h" 12#include "core/hle/kernel/shared_memory.h"
13#include "core/hle/kernel/thread.h"
13#include "core/hle/service/apt_s.h" 14#include "core/hle/service/apt_s.h"
14 15
15//////////////////////////////////////////////////////////////////////////////////////////////////// 16////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/apt_u.cpp b/src/core/hle/service/apt_u.cpp
index 001b0d183..629b670ed 100644
--- a/src/core/hle/service/apt_u.cpp
+++ b/src/core/hle/service/apt_u.cpp
@@ -10,6 +10,7 @@
10#include "core/hle/kernel/event.h" 10#include "core/hle/kernel/event.h"
11#include "core/hle/kernel/mutex.h" 11#include "core/hle/kernel/mutex.h"
12#include "core/hle/kernel/shared_memory.h" 12#include "core/hle/kernel/shared_memory.h"
13#include "core/hle/kernel/thread.h"
13#include "core/hle/service/apt_u.h" 14#include "core/hle/service/apt_u.h"
14 15
15//////////////////////////////////////////////////////////////////////////////////////////////////// 16////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -26,11 +27,11 @@ namespace APT_U {
26static const VAddr SHARED_FONT_VADDR = 0x18000000; 27static const VAddr SHARED_FONT_VADDR = 0x18000000;
27 28
28/// Handle to shared memory region designated to for shared system font 29/// Handle to shared memory region designated to for shared system font
29static Handle shared_font_mem = 0; 30static Kernel::SharedPtr<Kernel::SharedMemory> shared_font_mem;
30 31
31static Handle lock_handle = 0; 32static Kernel::SharedPtr<Kernel::Mutex> lock;
32static Handle notification_event_handle = 0; ///< APT notification event handle 33static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event
33static Handle pause_event_handle = 0; ///< APT pause event handle 34static Kernel::SharedPtr<Kernel::Event> pause_event = 0; ///< APT pause event
34static std::vector<u8> shared_font; 35static std::vector<u8> shared_font;
35 36
36/// Signals used by APT functions 37/// Signals used by APT functions
@@ -67,17 +68,19 @@ enum class AppID : u32 {
67void Initialize(Service::Interface* self) { 68void Initialize(Service::Interface* self) {
68 u32* cmd_buff = Kernel::GetCommandBuffer(); 69 u32* cmd_buff = Kernel::GetCommandBuffer();
69 70
70 notification_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Notification"); 71 // TODO(bunnei): Check if these are created in Initialize or on APT process startup.
71 pause_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "APT_U:Pause"); 72 notification_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Notification").MoveFrom();
73 pause_event = Kernel::Event::Create(RESETTYPE_ONESHOT, "APT_U:Pause").MoveFrom();
72 74
73 cmd_buff[3] = notification_event_handle; 75 cmd_buff[3] = Kernel::g_handle_table.Create(notification_event).MoveFrom();
74 cmd_buff[4] = pause_event_handle; 76 cmd_buff[4] = Kernel::g_handle_table.Create(pause_event).MoveFrom();
75 77
76 Kernel::ClearEvent(notification_event_handle); 78 // TODO(bunnei): Check if these events are cleared/signaled every time Initialize is called.
77 Kernel::SignalEvent(pause_event_handle); // Fire start event 79 notification_event->Clear();
80 pause_event->Signal(); // Fire start event
78 81
79 _assert_msg_(KERNEL, (0 != lock_handle), "Cannot initialize without lock"); 82 _assert_msg_(KERNEL, (nullptr != lock), "Cannot initialize without lock");
80 Kernel::ReleaseMutex(lock_handle); 83 lock->Release();
81 84
82 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 85 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
83} 86}
@@ -93,7 +96,7 @@ void NotifyToWait(Service::Interface* self) {
93 u32* cmd_buff = Kernel::GetCommandBuffer(); 96 u32* cmd_buff = Kernel::GetCommandBuffer();
94 u32 app_id = cmd_buff[1]; 97 u32 app_id = cmd_buff[1];
95 // TODO(Subv): Verify this, it seems to get SWKBD and Home Menu further. 98 // TODO(Subv): Verify this, it seems to get SWKBD and Home Menu further.
96 Kernel::SignalEvent(pause_event_handle); 99 pause_event->Signal();
97 100
98 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 101 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
99 LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id); 102 LOG_WARNING(Service_APT, "(STUBBED) app_id=%u", app_id);
@@ -103,11 +106,6 @@ void GetLockHandle(Service::Interface* self) {
103 u32* cmd_buff = Kernel::GetCommandBuffer(); 106 u32* cmd_buff = Kernel::GetCommandBuffer();
104 u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field 107 u32 flags = cmd_buff[1]; // TODO(bunnei): Figure out the purpose of the flag field
105 108
106 if (0 == lock_handle) {
107 // TODO(bunnei): Verify if this is created here or at application boot?
108 lock_handle = Kernel::CreateMutex(false, "APT_U:Lock");
109 Kernel::ReleaseMutex(lock_handle);
110 }
111 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 109 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
112 110
113 // Not sure what these parameters are used for, but retail apps check that they are 0 after 111 // Not sure what these parameters are used for, but retail apps check that they are 0 after
@@ -116,7 +114,7 @@ void GetLockHandle(Service::Interface* self) {
116 cmd_buff[3] = 0; 114 cmd_buff[3] = 0;
117 cmd_buff[4] = 0; 115 cmd_buff[4] = 0;
118 116
119 cmd_buff[5] = lock_handle; 117 cmd_buff[5] = Kernel::g_handle_table.Create(lock).MoveFrom();
120 LOG_TRACE(Service_APT, "called handle=0x%08X", cmd_buff[5]); 118 LOG_TRACE(Service_APT, "called handle=0x%08X", cmd_buff[5]);
121} 119}
122 120
@@ -354,7 +352,7 @@ void GetSharedFont(Service::Interface* self) {
354 cmd_buff[0] = 0x00440082; 352 cmd_buff[0] = 0x00440082;
355 cmd_buff[1] = RESULT_SUCCESS.raw; // No error 353 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
356 cmd_buff[2] = SHARED_FONT_VADDR; 354 cmd_buff[2] = SHARED_FONT_VADDR;
357 cmd_buff[4] = shared_font_mem; 355 cmd_buff[4] = Kernel::g_handle_table.Create(shared_font_mem).MoveFrom();
358 } else { 356 } else {
359 cmd_buff[1] = -1; // Generic error (not really possible to verify this on hardware) 357 cmd_buff[1] = -1; // Generic error (not really possible to verify this on hardware)
360 LOG_ERROR(Kernel_SVC, "called, but %s has not been loaded!", SHARED_FONT); 358 LOG_ERROR(Kernel_SVC, "called, but %s has not been loaded!", SHARED_FONT);
@@ -514,13 +512,13 @@ Interface::Interface() {
514 file.ReadBytes(shared_font.data(), (size_t)file.GetSize()); 512 file.ReadBytes(shared_font.data(), (size_t)file.GetSize());
515 513
516 // Create shared font memory object 514 // Create shared font memory object
517 shared_font_mem = Kernel::CreateSharedMemory("APT_U:shared_font_mem"); 515 shared_font_mem = Kernel::SharedMemory::Create("APT_U:shared_font_mem").MoveFrom();
518 } else { 516 } else {
519 LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str()); 517 LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str());
520 shared_font_mem = 0; 518 shared_font_mem = nullptr;
521 } 519 }
522 520
523 lock_handle = 0; 521 lock = Kernel::Mutex::Create(false, "APT_U:Lock").MoveFrom();
524 522
525 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 523 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
526} 524}
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index d5e39ea4b..9a38be393 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -13,8 +13,8 @@
13namespace DSP_DSP { 13namespace DSP_DSP {
14 14
15static u32 read_pipe_count = 0; 15static u32 read_pipe_count = 0;
16static Handle semaphore_event = 0; 16static Kernel::SharedPtr<Kernel::Event> semaphore_event;
17static Handle interrupt_event = 0; 17static Kernel::SharedPtr<Kernel::Event> interrupt_event;
18 18
19void SignalInterrupt() { 19void SignalInterrupt() {
20 // TODO(bunnei): This is just a stub, it does not do anything other than signal to the emulated 20 // TODO(bunnei): This is just a stub, it does not do anything other than signal to the emulated
@@ -24,7 +24,7 @@ void SignalInterrupt() {
24 // DSP interrupts, and trigger them at the appropriate times. 24 // DSP interrupts, and trigger them at the appropriate times.
25 25
26 if (interrupt_event != 0) 26 if (interrupt_event != 0)
27 Kernel::SignalEvent(interrupt_event); 27 interrupt_event->Signal();
28} 28}
29 29
30/** 30/**
@@ -78,8 +78,8 @@ void LoadComponent(Service::Interface* self) {
78void GetSemaphoreEventHandle(Service::Interface* self) { 78void GetSemaphoreEventHandle(Service::Interface* self) {
79 u32* cmd_buff = Kernel::GetCommandBuffer(); 79 u32* cmd_buff = Kernel::GetCommandBuffer();
80 80
81 cmd_buff[1] = 0; // No error 81 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
82 cmd_buff[3] = semaphore_event; // Event handle 82 cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).MoveFrom(); // Event handle
83 83
84 LOG_WARNING(Service_DSP, "(STUBBED) called"); 84 LOG_WARNING(Service_DSP, "(STUBBED) called");
85} 85}
@@ -96,9 +96,16 @@ void GetSemaphoreEventHandle(Service::Interface* self) {
96void RegisterInterruptEvents(Service::Interface* self) { 96void RegisterInterruptEvents(Service::Interface* self) {
97 u32* cmd_buff = Kernel::GetCommandBuffer(); 97 u32* cmd_buff = Kernel::GetCommandBuffer();
98 98
99 interrupt_event = static_cast<Handle>(cmd_buff[4]); 99 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[4]);
100 if (evt != nullptr) {
101 interrupt_event = evt;
102 cmd_buff[1] = 0; // No error
103 } else {
104 LOG_ERROR(Service_DSP, "called with invalid handle=%08X", cmd_buff[4]);
100 105
101 cmd_buff[1] = 0; // No error 106 // TODO(yuriks): An error should be returned from SendSyncRequest, not in the cmdbuf
107 cmd_buff[1] = -1;
108 }
102 109
103 LOG_WARNING(Service_DSP, "(STUBBED) called"); 110 LOG_WARNING(Service_DSP, "(STUBBED) called");
104} 111}
@@ -194,8 +201,9 @@ const Interface::FunctionInfo FunctionTable[] = {
194// Interface class 201// Interface class
195 202
196Interface::Interface() { 203Interface::Interface() {
197 semaphore_event = Kernel::CreateEvent(RESETTYPE_ONESHOT, "DSP_DSP::semaphore_event"); 204 semaphore_event = Kernel::Event::Create(RESETTYPE_ONESHOT,
198 interrupt_event = 0; 205 "DSP_DSP::semaphore_event").MoveFrom();
206 interrupt_event = nullptr;
199 read_pipe_count = 0; 207 read_pipe_count = 0;
200 208
201 Register(FunctionTable, ARRAY_SIZE(FunctionTable)); 209 Register(FunctionTable, ARRAY_SIZE(FunctionTable));
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 1bb4e4b23..6682f6590 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -43,6 +43,11 @@ const std::string SDCARD_ID = "00000000000000000000000000000000";
43namespace Service { 43namespace Service {
44namespace FS { 44namespace FS {
45 45
46// TODO: Verify code
47/// Returned when a function is passed an invalid handle.
48const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS,
49 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
50
46// Command to access archive file 51// Command to access archive file
47enum class FileCommand : u32 { 52enum class FileCommand : u32 {
48 Dummy1 = 0x000100C6, 53 Dummy1 = 0x000100C6,
@@ -280,7 +285,7 @@ ResultVal<ArchiveHandle> OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi
280 285
281ResultCode CloseArchive(ArchiveHandle handle) { 286ResultCode CloseArchive(ArchiveHandle handle) {
282 if (handle_map.erase(handle) == 0) 287 if (handle_map.erase(handle) == 0)
283 return InvalidHandle(ErrorModule::FS); 288 return ERR_INVALID_HANDLE;
284 else 289 else
285 return RESULT_SUCCESS; 290 return RESULT_SUCCESS;
286} 291}
@@ -301,7 +306,7 @@ ResultCode CreateArchive(std::unique_ptr<FileSys::ArchiveBackend>&& backend, Arc
301ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) { 306ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path, const FileSys::Mode mode) {
302 Archive* archive = GetArchive(archive_handle); 307 Archive* archive = GetArchive(archive_handle);
303 if (archive == nullptr) 308 if (archive == nullptr)
304 return InvalidHandle(ErrorModule::FS); 309 return ERR_INVALID_HANDLE;
305 310
306 std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode); 311 std::unique_ptr<FileSys::FileBackend> backend = archive->backend->OpenFile(path, mode);
307 if (backend == nullptr) { 312 if (backend == nullptr) {
@@ -318,7 +323,7 @@ ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSy
318ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { 323ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
319 Archive* archive = GetArchive(archive_handle); 324 Archive* archive = GetArchive(archive_handle);
320 if (archive == nullptr) 325 if (archive == nullptr)
321 return InvalidHandle(ErrorModule::FS); 326 return ERR_INVALID_HANDLE;
322 327
323 if (archive->backend->DeleteFile(path)) 328 if (archive->backend->DeleteFile(path))
324 return RESULT_SUCCESS; 329 return RESULT_SUCCESS;
@@ -331,7 +336,7 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil
331 Archive* src_archive = GetArchive(src_archive_handle); 336 Archive* src_archive = GetArchive(src_archive_handle);
332 Archive* dest_archive = GetArchive(dest_archive_handle); 337 Archive* dest_archive = GetArchive(dest_archive_handle);
333 if (src_archive == nullptr || dest_archive == nullptr) 338 if (src_archive == nullptr || dest_archive == nullptr)
334 return InvalidHandle(ErrorModule::FS); 339 return ERR_INVALID_HANDLE;
335 340
336 if (src_archive == dest_archive) { 341 if (src_archive == dest_archive) {
337 if (src_archive->backend->RenameFile(src_path, dest_path)) 342 if (src_archive->backend->RenameFile(src_path, dest_path))
@@ -350,7 +355,7 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, const Fil
350ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { 355ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
351 Archive* archive = GetArchive(archive_handle); 356 Archive* archive = GetArchive(archive_handle);
352 if (archive == nullptr) 357 if (archive == nullptr)
353 return InvalidHandle(ErrorModule::FS); 358 return ERR_INVALID_HANDLE;
354 359
355 if (archive->backend->DeleteDirectory(path)) 360 if (archive->backend->DeleteDirectory(path))
356 return RESULT_SUCCESS; 361 return RESULT_SUCCESS;
@@ -361,7 +366,7 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
361ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) { 366ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path, u32 file_size) {
362 Archive* archive = GetArchive(archive_handle); 367 Archive* archive = GetArchive(archive_handle);
363 if (archive == nullptr) 368 if (archive == nullptr)
364 return InvalidHandle(ErrorModule::FS); 369 return ERR_INVALID_HANDLE;
365 370
366 return archive->backend->CreateFile(path, file_size); 371 return archive->backend->CreateFile(path, file_size);
367} 372}
@@ -369,7 +374,7 @@ ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path
369ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { 374ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
370 Archive* archive = GetArchive(archive_handle); 375 Archive* archive = GetArchive(archive_handle);
371 if (archive == nullptr) 376 if (archive == nullptr)
372 return InvalidHandle(ErrorModule::FS); 377 return ERR_INVALID_HANDLE;
373 378
374 if (archive->backend->CreateDirectory(path)) 379 if (archive->backend->CreateDirectory(path))
375 return RESULT_SUCCESS; 380 return RESULT_SUCCESS;
@@ -382,7 +387,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
382 Archive* src_archive = GetArchive(src_archive_handle); 387 Archive* src_archive = GetArchive(src_archive_handle);
383 Archive* dest_archive = GetArchive(dest_archive_handle); 388 Archive* dest_archive = GetArchive(dest_archive_handle);
384 if (src_archive == nullptr || dest_archive == nullptr) 389 if (src_archive == nullptr || dest_archive == nullptr)
385 return InvalidHandle(ErrorModule::FS); 390 return ERR_INVALID_HANDLE;
386 391
387 if (src_archive == dest_archive) { 392 if (src_archive == dest_archive) {
388 if (src_archive->backend->RenameDirectory(src_path, dest_path)) 393 if (src_archive->backend->RenameDirectory(src_path, dest_path))
@@ -407,7 +412,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, cons
407ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { 412ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
408 Archive* archive = GetArchive(archive_handle); 413 Archive* archive = GetArchive(archive_handle);
409 if (archive == nullptr) 414 if (archive == nullptr)
410 return InvalidHandle(ErrorModule::FS); 415 return ERR_INVALID_HANDLE;
411 416
412 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path); 417 std::unique_ptr<FileSys::DirectoryBackend> backend = archive->backend->OpenDirectory(path);
413 if (backend == nullptr) { 418 if (backend == nullptr) {
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 4ca2b9bd0..5b91f17d2 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -22,13 +22,16 @@ GraphicsDebugger g_debugger;
22 22
23namespace GSP_GPU { 23namespace GSP_GPU {
24 24
25Handle g_interrupt_event = 0; ///< Handle to event triggered when GSP interrupt has been signalled 25/// Event triggered when GSP interrupt has been signalled
26Handle g_shared_memory = 0; ///< Handle to GSP shared memorys 26Kernel::SharedPtr<Kernel::Event> g_interrupt_event;
27u32 g_thread_id = 1; ///< Thread index into interrupt relay queue, 1 is arbitrary 27/// GSP shared memoryings
28Kernel::SharedPtr<Kernel::SharedMemory> g_shared_memory;
29/// Thread index into interrupt relay queue, 1 is arbitrary
30u32 g_thread_id = 1;
28 31
29/// Gets a pointer to a thread command buffer in GSP shared memory 32/// Gets a pointer to a thread command buffer in GSP shared memory
30static inline u8* GetCommandBuffer(u32 thread_id) { 33static inline u8* GetCommandBuffer(u32 thread_id) {
31 ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * sizeof(CommandBuffer))); 34 ResultVal<u8*> ptr = g_shared_memory->GetPointer(0x800 + (thread_id * sizeof(CommandBuffer)));
32 return ptr.ValueOr(nullptr); 35 return ptr.ValueOr(nullptr);
33} 36}
34 37
@@ -37,13 +40,13 @@ static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_in
37 40
38 // For each thread there are two FrameBufferUpdate fields 41 // For each thread there are two FrameBufferUpdate fields
39 u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate); 42 u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate);
40 ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, offset); 43 ResultVal<u8*> ptr = g_shared_memory->GetPointer(offset);
41 return reinterpret_cast<FrameBufferUpdate*>(ptr.ValueOr(nullptr)); 44 return reinterpret_cast<FrameBufferUpdate*>(ptr.ValueOr(nullptr));
42} 45}
43 46
44/// Gets a pointer to the interrupt relay queue for a given thread index 47/// Gets a pointer to the interrupt relay queue for a given thread index
45static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { 48static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
46 ResultVal<u8*> ptr = Kernel::GetSharedMemoryPointer(g_shared_memory, sizeof(InterruptRelayQueue) * thread_id); 49 ResultVal<u8*> ptr = g_shared_memory->GetPointer(sizeof(InterruptRelayQueue) * thread_id);
47 return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr)); 50 return reinterpret_cast<InterruptRelayQueue*>(ptr.ValueOr(nullptr));
48} 51}
49 52
@@ -181,16 +184,18 @@ static void FlushDataCache(Service::Interface* self) {
181static void RegisterInterruptRelayQueue(Service::Interface* self) { 184static void RegisterInterruptRelayQueue(Service::Interface* self) {
182 u32* cmd_buff = Kernel::GetCommandBuffer(); 185 u32* cmd_buff = Kernel::GetCommandBuffer();
183 u32 flags = cmd_buff[1]; 186 u32 flags = cmd_buff[1];
184 g_interrupt_event = cmd_buff[3];
185 g_shared_memory = Kernel::CreateSharedMemory("GSPSharedMem");
186 187
187 _assert_msg_(GSP, (g_interrupt_event != 0), "handle is not valid!"); 188 g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]);
189 _assert_msg_(GSP, (g_interrupt_event != nullptr), "handle is not valid!");
190 g_shared_memory = Kernel::SharedMemory::Create("GSPSharedMem").MoveFrom();
191
192 Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom();
188 193
189 cmd_buff[1] = 0x2A07; // Value verified by 3dmoo team, purpose unknown, but needed for GSP init 194 cmd_buff[1] = 0x2A07; // Value verified by 3dmoo team, purpose unknown, but needed for GSP init
190 cmd_buff[2] = g_thread_id++; // Thread ID 195 cmd_buff[2] = g_thread_id++; // Thread ID
191 cmd_buff[4] = g_shared_memory; // GSP shared memory 196 cmd_buff[4] = shmem_handle; // GSP shared memory
192 197
193 Kernel::SignalEvent(g_interrupt_event); // TODO(bunnei): Is this correct? 198 g_interrupt_event->Signal(); // TODO(bunnei): Is this correct?
194} 199}
195 200
196/** 201/**
@@ -204,7 +209,7 @@ void SignalInterrupt(InterruptId interrupt_id) {
204 LOG_WARNING(Service_GSP, "cannot synchronize until GSP event has been created!"); 209 LOG_WARNING(Service_GSP, "cannot synchronize until GSP event has been created!");
205 return; 210 return;
206 } 211 }
207 if (0 == g_shared_memory) { 212 if (nullptr == g_shared_memory) {
208 LOG_WARNING(Service_GSP, "cannot synchronize until GSP shared memory has been created!"); 213 LOG_WARNING(Service_GSP, "cannot synchronize until GSP shared memory has been created!");
209 return; 214 return;
210 } 215 }
@@ -232,7 +237,7 @@ void SignalInterrupt(InterruptId interrupt_id) {
232 info->is_dirty = false; 237 info->is_dirty = false;
233 } 238 }
234 } 239 }
235 Kernel::SignalEvent(g_interrupt_event); 240 g_interrupt_event->Signal();
236} 241}
237 242
238/// Executes the next GSP command 243/// Executes the next GSP command
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 5abcb2596..835055af4 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -12,13 +12,13 @@
12namespace Service { 12namespace Service {
13namespace HID { 13namespace HID {
14 14
15Handle g_shared_mem = 0; 15Kernel::SharedPtr<Kernel::SharedMemory> g_shared_mem = nullptr;
16 16
17Handle g_event_pad_or_touch_1 = 0; 17Kernel::SharedPtr<Kernel::Event> g_event_pad_or_touch_1;
18Handle g_event_pad_or_touch_2 = 0; 18Kernel::SharedPtr<Kernel::Event> g_event_pad_or_touch_2;
19Handle g_event_accelerometer = 0; 19Kernel::SharedPtr<Kernel::Event> g_event_accelerometer;
20Handle g_event_gyroscope = 0; 20Kernel::SharedPtr<Kernel::Event> g_event_gyroscope;
21Handle g_event_debug_pad = 0; 21Kernel::SharedPtr<Kernel::Event> g_event_debug_pad;
22 22
23// Next Pad state update information 23// Next Pad state update information
24static PadState next_state = {{0}}; 24static PadState next_state = {{0}};
@@ -30,7 +30,7 @@ static s16 next_circle_y = 0;
30 * Gets a pointer to the PadData structure inside HID shared memory 30 * Gets a pointer to the PadData structure inside HID shared memory
31 */ 31 */
32static inline PadData* GetPadData() { 32static inline PadData* GetPadData() {
33 return reinterpret_cast<PadData*>(Kernel::GetSharedMemoryPointer(g_shared_mem, 0).ValueOr(nullptr)); 33 return reinterpret_cast<PadData*>(g_shared_mem->GetPointer().ValueOr(nullptr));
34} 34}
35 35
36/** 36/**
@@ -115,19 +115,21 @@ void PadUpdateComplete() {
115 } 115 }
116 116
117 // Signal both handles when there's an update to Pad or touch 117 // Signal both handles when there's an update to Pad or touch
118 Kernel::SignalEvent(g_event_pad_or_touch_1); 118 g_event_pad_or_touch_1->Signal();
119 Kernel::SignalEvent(g_event_pad_or_touch_2); 119 g_event_pad_or_touch_2->Signal();
120} 120}
121 121
122void HIDInit() { 122void HIDInit() {
123 g_shared_mem = Kernel::CreateSharedMemory("HID:SharedMem"); // Create shared memory object 123 using namespace Kernel;
124
125 g_shared_mem = SharedMemory::Create("HID:SharedMem").MoveFrom();
124 126
125 // Create event handles 127 // Create event handles
126 g_event_pad_or_touch_1 = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1"); 128 g_event_pad_or_touch_1 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch1").MoveFrom();
127 g_event_pad_or_touch_2 = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2"); 129 g_event_pad_or_touch_2 = Event::Create(RESETTYPE_ONESHOT, "HID:EventPadOrTouch2").MoveFrom();
128 g_event_accelerometer = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventAccelerometer"); 130 g_event_accelerometer = Event::Create(RESETTYPE_ONESHOT, "HID:EventAccelerometer").MoveFrom();
129 g_event_gyroscope = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventGyroscope"); 131 g_event_gyroscope = Event::Create(RESETTYPE_ONESHOT, "HID:EventGyroscope").MoveFrom();
130 g_event_debug_pad = Kernel::CreateEvent(RESETTYPE_ONESHOT, "HID:EventDebugPad"); 132 g_event_debug_pad = Event::Create(RESETTYPE_ONESHOT, "HID:EventDebugPad").MoveFrom();
131} 133}
132 134
133void HIDShutdown() { 135void HIDShutdown() {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 73cdaa527..2116d2ca3 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -9,18 +9,23 @@
9#include "core/hle/kernel/kernel.h" 9#include "core/hle/kernel/kernel.h"
10#include "common/bit_field.h" 10#include "common/bit_field.h"
11 11
12namespace Kernel {
13 class SharedMemory;
14 class Event;
15}
16
12namespace Service { 17namespace Service {
13namespace HID { 18namespace HID {
14 19
15// Handle to shared memory region designated to HID_User service 20// Handle to shared memory region designated to HID_User service
16extern Handle g_shared_mem; 21extern Kernel::SharedPtr<Kernel::SharedMemory> g_shared_mem;
17 22
18// Event handles 23// Event handles
19extern Handle g_event_pad_or_touch_1; 24extern Kernel::SharedPtr<Kernel::Event> g_event_pad_or_touch_1;
20extern Handle g_event_pad_or_touch_2; 25extern Kernel::SharedPtr<Kernel::Event> g_event_pad_or_touch_2;
21extern Handle g_event_accelerometer; 26extern Kernel::SharedPtr<Kernel::Event> g_event_accelerometer;
22extern Handle g_event_gyroscope; 27extern Kernel::SharedPtr<Kernel::Event> g_event_gyroscope;
23extern Handle g_event_debug_pad; 28extern Kernel::SharedPtr<Kernel::Event> g_event_debug_pad;
24 29
25/** 30/**
26 * Structure of a Pad controller state. 31 * Structure of a Pad controller state.
diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp
index 3a6275707..5444aa5ee 100644
--- a/src/core/hle/service/hid/hid_user.cpp
+++ b/src/core/hle/service/hid/hid_user.cpp
@@ -5,6 +5,8 @@
5#include "common/log.h" 5#include "common/log.h"
6 6
7#include "core/hle/hle.h" 7#include "core/hle/hle.h"
8#include "core/hle/kernel/event.h"
9#include "core/hle/kernel/shared_memory.h"
8#include "core/hle/service/hid/hid.h" 10#include "core/hle/service/hid/hid.h"
9#include "hid_user.h" 11#include "hid_user.h"
10 12
@@ -46,12 +48,13 @@ void GetIPCHandles(Service::Interface* self) {
46 u32* cmd_buff = Kernel::GetCommandBuffer(); 48 u32* cmd_buff = Kernel::GetCommandBuffer();
47 49
48 cmd_buff[1] = 0; // No error 50 cmd_buff[1] = 0; // No error
49 cmd_buff[3] = Service::HID::g_shared_mem; 51 // TODO(yuriks): Return error from SendSyncRequest is this fails (part of IPC marshalling)
50 cmd_buff[4] = Service::HID::g_event_pad_or_touch_1; 52 cmd_buff[3] = Kernel::g_handle_table.Create(Service::HID::g_shared_mem).MoveFrom();
51 cmd_buff[5] = Service::HID::g_event_pad_or_touch_2; 53 cmd_buff[4] = Kernel::g_handle_table.Create(Service::HID::g_event_pad_or_touch_1).MoveFrom();
52 cmd_buff[6] = Service::HID::g_event_accelerometer; 54 cmd_buff[5] = Kernel::g_handle_table.Create(Service::HID::g_event_pad_or_touch_2).MoveFrom();
53 cmd_buff[7] = Service::HID::g_event_gyroscope; 55 cmd_buff[6] = Kernel::g_handle_table.Create(Service::HID::g_event_accelerometer).MoveFrom();
54 cmd_buff[8] = Service::HID::g_event_debug_pad; 56 cmd_buff[7] = Kernel::g_handle_table.Create(Service::HID::g_event_gyroscope).MoveFrom();
57 cmd_buff[8] = Kernel::g_handle_table.Create(Service::HID::g_event_debug_pad).MoveFrom();
55} 58}
56 59
57const Interface::FunctionInfo FunctionTable[] = { 60const Interface::FunctionInfo FunctionTable[] = {
diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp
index 082834cfe..aa0aac3bb 100644
--- a/src/core/hle/service/srv.cpp
+++ b/src/core/hle/service/srv.cpp
@@ -11,7 +11,7 @@
11 11
12namespace SRV { 12namespace SRV {
13 13
14static Handle g_event_handle = 0; 14static Kernel::SharedPtr<Kernel::Event> event_handle;
15 15
16static void Initialize(Service::Interface* self) { 16static void Initialize(Service::Interface* self) {
17 u32* cmd_buff = Kernel::GetCommandBuffer(); 17 u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -23,11 +23,11 @@ static void GetProcSemaphore(Service::Interface* self) {
23 u32* cmd_buff = Kernel::GetCommandBuffer(); 23 u32* cmd_buff = Kernel::GetCommandBuffer();
24 24
25 // TODO(bunnei): Change to a semaphore once these have been implemented 25 // TODO(bunnei): Change to a semaphore once these have been implemented
26 g_event_handle = Kernel::CreateEvent(RESETTYPE_ONESHOT, "SRV:Event"); 26 event_handle = Kernel::Event::Create(RESETTYPE_ONESHOT, "SRV:Event").MoveFrom();
27 Kernel::ClearEvent(g_event_handle); 27 event_handle->Clear();
28 28
29 cmd_buff[1] = 0; // No error 29 cmd_buff[1] = 0; // No error
30 cmd_buff[3] = g_event_handle; 30 cmd_buff[3] = Kernel::g_handle_table.Create(event_handle).MoveFrom();
31} 31}
32 32
33static void GetServiceHandle(Service::Interface* self) { 33static void GetServiceHandle(Service::Interface* self) {
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 3d743f125..88813c2ce 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -26,6 +26,7 @@
26// Namespace SVC 26// Namespace SVC
27 27
28using Kernel::SharedPtr; 28using Kernel::SharedPtr;
29using Kernel::ERR_INVALID_HANDLE;
29 30
30namespace SVC { 31namespace SVC {
31 32
@@ -38,7 +39,7 @@ enum ControlMemoryOperation {
38}; 39};
39 40
40/// Map application or GSP heap memory 41/// Map application or GSP heap memory
41static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { 42static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
42 LOG_TRACE(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", 43 LOG_TRACE(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X",
43 operation, addr0, addr1, size, permissions); 44 operation, addr0, addr1, size, permissions);
44 45
@@ -58,35 +59,42 @@ static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1,
58 default: 59 default:
59 LOG_ERROR(Kernel_SVC, "unknown operation=0x%08X", operation); 60 LOG_ERROR(Kernel_SVC, "unknown operation=0x%08X", operation);
60 } 61 }
61 return 0; 62 return RESULT_SUCCESS;
62} 63}
63 64
64/// Maps a memory block to specified address 65/// Maps a memory block to specified address
65static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { 66static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) {
67 using Kernel::SharedMemory;
68 using Kernel::MemoryPermission;
69
66 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 70 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
67 handle, addr, permissions, other_permissions); 71 handle, addr, permissions, other_permissions);
68 72
69 Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions); 73 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
74 if (shared_memory == nullptr)
75 return ERR_INVALID_HANDLE;
76
77 MemoryPermission permissions_type = static_cast<MemoryPermission>(permissions);
70 switch (permissions_type) { 78 switch (permissions_type) {
71 case Kernel::MemoryPermission::Read: 79 case MemoryPermission::Read:
72 case Kernel::MemoryPermission::Write: 80 case MemoryPermission::Write:
73 case Kernel::MemoryPermission::ReadWrite: 81 case MemoryPermission::ReadWrite:
74 case Kernel::MemoryPermission::Execute: 82 case MemoryPermission::Execute:
75 case Kernel::MemoryPermission::ReadExecute: 83 case MemoryPermission::ReadExecute:
76 case Kernel::MemoryPermission::WriteExecute: 84 case MemoryPermission::WriteExecute:
77 case Kernel::MemoryPermission::ReadWriteExecute: 85 case MemoryPermission::ReadWriteExecute:
78 case Kernel::MemoryPermission::DontCare: 86 case MemoryPermission::DontCare:
79 Kernel::MapSharedMemory(handle, addr, permissions_type, 87 shared_memory->Map(addr, permissions_type,
80 static_cast<Kernel::MemoryPermission>(other_permissions)); 88 static_cast<MemoryPermission>(other_permissions));
81 break; 89 break;
82 default: 90 default:
83 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); 91 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
84 } 92 }
85 return 0; 93 return RESULT_SUCCESS;
86} 94}
87 95
88/// Connect to an OS service given the port name, returns the handle to the port to out 96/// Connect to an OS service given the port name, returns the handle to the port to out
89static Result ConnectToPort(Handle* out, const char* port_name) { 97static ResultCode ConnectToPort(Handle* out, const char* port_name) {
90 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); 98 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
91 99
92 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); 100 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name);
@@ -94,33 +102,33 @@ static Result ConnectToPort(Handle* out, const char* port_name) {
94 102
95 *out = service->GetHandle(); 103 *out = service->GetHandle();
96 104
97 return 0; 105 return RESULT_SUCCESS;
98} 106}
99 107
100/// Synchronize to an OS service 108/// Synchronize to an OS service
101static Result SendSyncRequest(Handle handle) { 109static ResultCode SendSyncRequest(Handle handle) {
102 SharedPtr<Kernel::Session> session = Kernel::g_handle_table.Get<Kernel::Session>(handle); 110 SharedPtr<Kernel::Session> session = Kernel::g_handle_table.Get<Kernel::Session>(handle);
103 if (session == nullptr) { 111 if (session == nullptr) {
104 return InvalidHandle(ErrorModule::Kernel).raw; 112 return ERR_INVALID_HANDLE;
105 } 113 }
106 114
107 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); 115 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str());
108 116
109 return session->SyncRequest().Code().raw; 117 return session->SyncRequest().Code();
110} 118}
111 119
112/// Close a handle 120/// Close a handle
113static Result CloseHandle(Handle handle) { 121static ResultCode CloseHandle(Handle handle) {
114 // ImplementMe 122 // ImplementMe
115 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); 123 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle);
116 return 0; 124 return RESULT_SUCCESS;
117} 125}
118 126
119/// Wait for a handle to synchronize, timeout after the specified nanoseconds 127/// Wait for a handle to synchronize, timeout after the specified nanoseconds
120static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { 128static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
121 auto object = Kernel::g_handle_table.GetWaitObject(handle); 129 auto object = Kernel::g_handle_table.GetWaitObject(handle);
122 if (object == nullptr) 130 if (object == nullptr)
123 return InvalidHandle(ErrorModule::Kernel).raw; 131 return ERR_INVALID_HANDLE;
124 132
125 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, 133 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle,
126 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); 134 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds);
@@ -137,22 +145,22 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
137 HLE::Reschedule(__func__); 145 HLE::Reschedule(__func__);
138 146
139 // NOTE: output of this SVC will be set later depending on how the thread resumes 147 // NOTE: output of this SVC will be set later depending on how the thread resumes
140 return RESULT_INVALID.raw; 148 return RESULT_INVALID;
141 } 149 }
142 150
143 object->Acquire(); 151 object->Acquire();
144 152
145 return RESULT_SUCCESS.raw; 153 return RESULT_SUCCESS;
146} 154}
147 155
148/// Wait for the given handles to synchronize, timeout after the specified nanoseconds 156/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
149static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { 157static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) {
150 bool wait_thread = !wait_all; 158 bool wait_thread = !wait_all;
151 int handle_index = 0; 159 int handle_index = 0;
152 160
153 // Check if 'handles' is invalid 161 // Check if 'handles' is invalid
154 if (handles == nullptr) 162 if (handles == nullptr)
155 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent).raw; 163 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
156 164
157 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If 165 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
158 // this happens, the running application will crash. 166 // this happens, the running application will crash.
@@ -160,7 +168,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
160 168
161 // Check if 'handle_count' is invalid 169 // Check if 'handle_count' is invalid
162 if (handle_count < 0) 170 if (handle_count < 0)
163 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage).raw; 171 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
164 172
165 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if 173 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if
166 // necessary 174 // necessary
@@ -169,7 +177,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
169 for (int i = 0; i < handle_count; ++i) { 177 for (int i = 0; i < handle_count; ++i) {
170 auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); 178 auto object = Kernel::g_handle_table.GetWaitObject(handles[i]);
171 if (object == nullptr) 179 if (object == nullptr)
172 return InvalidHandle(ErrorModule::Kernel).raw; 180 return ERR_INVALID_HANDLE;
173 181
174 // Check if the current thread should wait on this object... 182 // Check if the current thread should wait on this object...
175 if (object->ShouldWait()) { 183 if (object->ShouldWait()) {
@@ -213,7 +221,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
213 HLE::Reschedule(__func__); 221 HLE::Reschedule(__func__);
214 222
215 // NOTE: output of this SVC will be set later depending on how the thread resumes 223 // NOTE: output of this SVC will be set later depending on how the thread resumes
216 return RESULT_INVALID.raw; 224 return RESULT_INVALID;
217 } 225 }
218 226
219 // Acquire objects if we did not wait... 227 // Acquire objects if we did not wait...
@@ -235,22 +243,32 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
235 // not seem to set it to any meaningful value. 243 // not seem to set it to any meaningful value.
236 *out = wait_all ? 0 : handle_index; 244 *out = wait_all ? 0 : handle_index;
237 245
238 return RESULT_SUCCESS.raw; 246 return RESULT_SUCCESS;
239} 247}
240 248
241/// Create an address arbiter (to allocate access to shared resources) 249/// Create an address arbiter (to allocate access to shared resources)
242static Result CreateAddressArbiter(u32* arbiter) { 250static ResultCode CreateAddressArbiter(Handle* out_handle) {
243 Handle handle = Kernel::CreateAddressArbiter(); 251 using Kernel::AddressArbiter;
244 *arbiter = handle; 252
245 return 0; 253 CASCADE_RESULT(SharedPtr<AddressArbiter> arbiter, AddressArbiter::Create());
254 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(arbiter)));
255 LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *out_handle);
256 return RESULT_SUCCESS;
246} 257}
247 258
248/// Arbitrate address 259/// Arbitrate address
249static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { 260static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) {
250 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter, 261 using Kernel::AddressArbiter;
262
263 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle,
251 address, type, value); 264 address, type, value);
252 return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), 265
253 address, value, nanoseconds).raw; 266 SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle);
267 if (arbiter == nullptr)
268 return ERR_INVALID_HANDLE;
269
270 return arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type),
271 address, value, nanoseconds);
254} 272}
255 273
256/// Used to output a message on a debug hardware unit - does nothing on a retail unit 274/// Used to output a message on a debug hardware unit - does nothing on a retail unit
@@ -259,26 +277,26 @@ static void OutputDebugString(const char* string) {
259} 277}
260 278
261/// Get resource limit 279/// Get resource limit
262static Result GetResourceLimit(Handle* resource_limit, Handle process) { 280static ResultCode GetResourceLimit(Handle* resource_limit, Handle process) {
263 // With regards to proceess values: 281 // With regards to proceess values:
264 // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for 282 // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for
265 // the current KThread. 283 // the current KThread.
266 *resource_limit = 0xDEADBEEF; 284 *resource_limit = 0xDEADBEEF;
267 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process); 285 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process);
268 return 0; 286 return RESULT_SUCCESS;
269} 287}
270 288
271/// Get resource limit current values 289/// Get resource limit current values
272static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, 290static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names,
273 s32 name_count) { 291 s32 name_count) {
274 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", 292 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d",
275 resource_limit, names, name_count); 293 resource_limit, names, name_count);
276 Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now 294 Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now
277 return 0; 295 return RESULT_SUCCESS;
278} 296}
279 297
280/// Creates a new thread 298/// Creates a new thread
281static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { 299static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) {
282 using Kernel::Thread; 300 using Kernel::Thread;
283 301
284 std::string name; 302 std::string name;
@@ -289,25 +307,20 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top
289 name = Common::StringFromFormat("unknown-%08x", entry_point); 307 name = Common::StringFromFormat("unknown-%08x", entry_point);
290 } 308 }
291 309
292 ResultVal<SharedPtr<Thread>> thread_res = Kernel::Thread::Create( 310 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create(
293 name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE); 311 name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE));
294 if (thread_res.Failed()) 312 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread)));
295 return thread_res.Code().raw;
296 SharedPtr<Thread> thread = std::move(*thread_res);
297
298 // TODO(yuriks): Create new handle instead of using built-in
299 Core::g_app_core->SetReg(1, thread->GetHandle());
300 313
301 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " 314 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
302 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, 315 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point,
303 name.c_str(), arg, stack_top, priority, processor_id, thread->GetHandle()); 316 name.c_str(), arg, stack_top, priority, processor_id, *out_handle);
304 317
305 if (THREADPROCESSORID_1 == processor_id) { 318 if (THREADPROCESSORID_1 == processor_id) {
306 LOG_WARNING(Kernel_SVC, 319 LOG_WARNING(Kernel_SVC,
307 "thread designated for system CPU core (UNIMPLEMENTED) will be run with app core scheduling"); 320 "thread designated for system CPU core (UNIMPLEMENTED) will be run with app core scheduling");
308 } 321 }
309 322
310 return 0; 323 return RESULT_SUCCESS;
311} 324}
312 325
313/// Called when a thread exits 326/// Called when a thread exits
@@ -319,128 +332,192 @@ static void ExitThread() {
319} 332}
320 333
321/// Gets the priority for the specified thread 334/// Gets the priority for the specified thread
322static Result GetThreadPriority(s32* priority, Handle handle) { 335static ResultCode GetThreadPriority(s32* priority, Handle handle) {
323 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); 336 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
324 if (thread == nullptr) 337 if (thread == nullptr)
325 return InvalidHandle(ErrorModule::Kernel).raw; 338 return ERR_INVALID_HANDLE;
326 339
327 *priority = thread->GetPriority(); 340 *priority = thread->GetPriority();
328 return RESULT_SUCCESS.raw; 341 return RESULT_SUCCESS;
329} 342}
330 343
331/// Sets the priority for the specified thread 344/// Sets the priority for the specified thread
332static Result SetThreadPriority(Handle handle, s32 priority) { 345static ResultCode SetThreadPriority(Handle handle, s32 priority) {
333 SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); 346 SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
334 if (thread == nullptr) 347 if (thread == nullptr)
335 return InvalidHandle(ErrorModule::Kernel).raw; 348 return ERR_INVALID_HANDLE;
336 349
337 thread->SetPriority(priority); 350 thread->SetPriority(priority);
338 return RESULT_SUCCESS.raw; 351 return RESULT_SUCCESS;
339} 352}
340 353
341/// Create a mutex 354/// Create a mutex
342static Result CreateMutex(Handle* mutex, u32 initial_locked) { 355static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
343 *mutex = Kernel::CreateMutex((initial_locked != 0)); 356 using Kernel::Mutex;
357
358 CASCADE_RESULT(SharedPtr<Mutex> mutex, Mutex::Create(initial_locked != 0));
359 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
360
344 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 361 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
345 initial_locked ? "true" : "false", *mutex); 362 initial_locked ? "true" : "false", *out_handle);
346 return 0; 363 return RESULT_SUCCESS;
347} 364}
348 365
349/// Release a mutex 366/// Release a mutex
350static Result ReleaseMutex(Handle handle) { 367static ResultCode ReleaseMutex(Handle handle) {
368 using Kernel::Mutex;
369
351 LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle); 370 LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle);
352 ResultCode res = Kernel::ReleaseMutex(handle); 371
353 return res.raw; 372 SharedPtr<Mutex> mutex = Kernel::g_handle_table.Get<Mutex>(handle);
373 if (mutex == nullptr)
374 return ERR_INVALID_HANDLE;
375
376 mutex->Release();
377 return RESULT_SUCCESS;
354} 378}
355 379
356/// Get the ID for the specified thread. 380/// Get the ID for the specified thread.
357static Result GetThreadId(u32* thread_id, Handle handle) { 381static ResultCode GetThreadId(u32* thread_id, Handle handle) {
358 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); 382 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle);
359 383
360 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); 384 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
361 if (thread == nullptr) 385 if (thread == nullptr)
362 return InvalidHandle(ErrorModule::Kernel).raw; 386 return ERR_INVALID_HANDLE;
363 387
364 *thread_id = thread->GetThreadId(); 388 *thread_id = thread->GetThreadId();
365 return RESULT_SUCCESS.raw; 389 return RESULT_SUCCESS;
366} 390}
367 391
368/// Creates a semaphore 392/// Creates a semaphore
369static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { 393static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) {
370 ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count); 394 using Kernel::Semaphore;
395
396 CASCADE_RESULT(SharedPtr<Semaphore> semaphore, Semaphore::Create(initial_count, max_count));
397 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore)));
398
371 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", 399 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
372 initial_count, max_count, *semaphore); 400 initial_count, max_count, *out_handle);
373 return res.raw; 401 return RESULT_SUCCESS;
374} 402}
375 403
376/// Releases a certain number of slots in a semaphore 404/// Releases a certain number of slots in a semaphore
377static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { 405static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
378 LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); 406 using Kernel::Semaphore;
379 ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); 407
380 return res.raw; 408 LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle);
409
410 SharedPtr<Semaphore> semaphore = Kernel::g_handle_table.Get<Semaphore>(handle);
411 if (semaphore == nullptr)
412 return ERR_INVALID_HANDLE;
413
414 CASCADE_RESULT(*count, semaphore->Release(release_count));
415 return RESULT_SUCCESS;
381} 416}
382 417
383/// Query memory 418/// Query memory
384static Result QueryMemory(void* info, void* out, u32 addr) { 419static ResultCode QueryMemory(void* info, void* out, u32 addr) {
385 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); 420 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr);
386 return 0; 421 return RESULT_SUCCESS;
387} 422}
388 423
389/// Create an event 424/// Create an event
390static Result CreateEvent(Handle* evt, u32 reset_type) { 425static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
391 *evt = Kernel::CreateEvent((ResetType)reset_type); 426 CASCADE_RESULT(auto evt, Kernel::Event::Create(static_cast<ResetType>(reset_type)));
427 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
428
392 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 429 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
393 reset_type, *evt); 430 reset_type, *out_handle);
394 return 0; 431 return RESULT_SUCCESS;
395} 432}
396 433
397/// Duplicates a kernel handle 434/// Duplicates a kernel handle
398static Result DuplicateHandle(Handle* out, Handle handle) { 435static ResultCode DuplicateHandle(Handle* out, Handle handle) {
399 ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle); 436 ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle);
400 if (out_h.Succeeded()) { 437 if (out_h.Succeeded()) {
401 *out = *out_h; 438 *out = *out_h;
402 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out); 439 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
403 } 440 }
404 return out_h.Code().raw; 441 return out_h.Code();
405} 442}
406 443
407/// Signals an event 444/// Signals an event
408static Result SignalEvent(Handle evt) { 445static ResultCode SignalEvent(Handle handle) {
409 LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); 446 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
447
448 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
449 if (evt == nullptr)
450 return ERR_INVALID_HANDLE;
451
452 evt->Signal();
410 HLE::Reschedule(__func__); 453 HLE::Reschedule(__func__);
411 return Kernel::SignalEvent(evt).raw; 454 return RESULT_SUCCESS;
412} 455}
413 456
414/// Clears an event 457/// Clears an event
415static Result ClearEvent(Handle evt) { 458static ResultCode ClearEvent(Handle handle) {
416 LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); 459 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
417 return Kernel::ClearEvent(evt).raw; 460
461 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
462 if (evt == nullptr)
463 return ERR_INVALID_HANDLE;
464
465 evt->Clear();
466 return RESULT_SUCCESS;
418} 467}
419 468
420/// Creates a timer 469/// Creates a timer
421static Result CreateTimer(Handle* handle, u32 reset_type) { 470static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
422 ResultCode res = Kernel::CreateTimer(handle, static_cast<ResetType>(reset_type)); 471 using Kernel::Timer;
472
473 CASCADE_RESULT(auto timer, Timer::Create(static_cast<ResetType>(reset_type)));
474 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
475
423 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 476 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
424 reset_type, *handle); 477 reset_type, *out_handle);
425 return res.raw; 478 return RESULT_SUCCESS;
426} 479}
427 480
428/// Clears a timer 481/// Clears a timer
429static Result ClearTimer(Handle handle) { 482static ResultCode ClearTimer(Handle handle) {
483 using Kernel::Timer;
484
430 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); 485 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
431 return Kernel::ClearTimer(handle).raw; 486
487 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
488 if (timer == nullptr)
489 return ERR_INVALID_HANDLE;
490
491 timer->Clear();
492 return RESULT_SUCCESS;
432} 493}
433 494
434/// Starts a timer 495/// Starts a timer
435static Result SetTimer(Handle handle, s64 initial, s64 interval) { 496static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
497 using Kernel::Timer;
498
436 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); 499 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
437 return Kernel::SetTimer(handle, initial, interval).raw; 500
501 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
502 if (timer == nullptr)
503 return ERR_INVALID_HANDLE;
504
505 timer->Set(initial, interval);
506 return RESULT_SUCCESS;
438} 507}
439 508
440/// Cancels a timer 509/// Cancels a timer
441static Result CancelTimer(Handle handle) { 510static ResultCode CancelTimer(Handle handle) {
511 using Kernel::Timer;
512
442 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); 513 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
443 return Kernel::CancelTimer(handle).raw; 514
515 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
516 if (timer == nullptr)
517 return ERR_INVALID_HANDLE;
518
519 timer->Cancel();
520 return RESULT_SUCCESS;
444} 521}
445 522
446/// Sleep the current thread 523/// Sleep the current thread
@@ -462,15 +539,16 @@ static s64 GetSystemTick() {
462} 539}
463 540
464/// Creates a memory block at the specified address with the specified permissions and size 541/// Creates a memory block at the specified address with the specified permissions and size
465static Result CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, u32 my_permission, 542static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission,
466 u32 other_permission) { 543 u32 other_permission) {
467 544 using Kernel::SharedMemory;
468 // TODO(Subv): Implement this function 545 // TODO(Subv): Implement this function
469 546
470 Handle shared_memory = Kernel::CreateSharedMemory(); 547 CASCADE_RESULT(auto shared_memory, SharedMemory::Create());
471 *memblock = shared_memory; 548 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
549
472 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); 550 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr);
473 return 0; 551 return RESULT_SUCCESS;
474} 552}
475 553
476const HLE::FunctionDef SVC_Table[] = { 554const HLE::FunctionDef SVC_Table[] = {
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index fad40ae0c..8f4f21fec 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -7,12 +7,9 @@
7#include "common/common.h" 7#include "common/common.h"
8#include "common/common_types.h" 8#include "common/common_types.h"
9 9
10namespace Memory { 10#include "core/hle/kernel/kernel.h"
11 11
12// TODO: It would be nice to eventually replace these with strong types that prevent accidental 12namespace Memory {
13// conversion between each other.
14typedef u32 VAddr; ///< Represents a pointer in the ARM11 virtual address space.
15typedef u32 PAddr; ///< Represents a pointer in the physical address space.
16 13
17//////////////////////////////////////////////////////////////////////////////////////////////////// 14////////////////////////////////////////////////////////////////////////////////////////////////////
18 15
@@ -190,7 +187,3 @@ VAddr PhysicalToVirtualAddress(PAddr addr);
190PAddr VirtualToPhysicalAddress(VAddr addr); 187PAddr VirtualToPhysicalAddress(VAddr addr);
191 188
192} // namespace 189} // namespace
193
194// These are used often, so re-export then on the root namespace
195using Memory::VAddr;
196using Memory::PAddr;