summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Emmanuel Gil Peyrot2016-09-18 09:38:01 +0900
committerGravatar Emmanuel Gil Peyrot2016-09-18 09:38:01 +0900
commitdc8479928c5aee4c6ad6fe4f59006fb604cee701 (patch)
tree569a7f13128450bbab973236615587ff00bced5f /src/core/hle/kernel
parentTravis: Import Dolphin’s clang-format hook. (diff)
downloadyuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.gz
yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.xz
yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.zip
Sources: Run clang-format on everything.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp26
-rw-r--r--src/core/hle/kernel/address_arbiter.h14
-rw-r--r--src/core/hle/kernel/client_port.cpp6
-rw-r--r--src/core/hle/kernel/client_port.h22
-rw-r--r--src/core/hle/kernel/event.cpp10
-rw-r--r--src/core/hle/kernel/event.h19
-rw-r--r--src/core/hle/kernel/kernel.cpp3
-rw-r--r--src/core/hle/kernel/kernel.h66
-rw-r--r--src/core/hle/kernel/memory.cpp22
-rw-r--r--src/core/hle/kernel/memory.h1
-rw-r--r--src/core/hle/kernel/mutex.cpp6
-rw-r--r--src/core/hle/kernel/mutex.h18
-rw-r--r--src/core/hle/kernel/process.cpp65
-rw-r--r--src/core/hle/kernel/process.h50
-rw-r--r--src/core/hle/kernel/resource_limit.cpp114
-rw-r--r--src/core/hle/kernel/resource_limit.h44
-rw-r--r--src/core/hle/kernel/semaphore.cpp8
-rw-r--r--src/core/hle/kernel/semaphore.h20
-rw-r--r--src/core/hle/kernel/server_port.cpp9
-rw-r--r--src/core/hle/kernel/server_port.h20
-rw-r--r--src/core/hle/kernel/session.cpp7
-rw-r--r--src/core/hle/kernel/session.h61
-rw-r--r--src/core/hle/kernel/shared_memory.cpp75
-rw-r--r--src/core/hle/kernel/shared_memory.h59
-rw-r--r--src/core/hle/kernel/thread.cpp114
-rw-r--r--src/core/hle/kernel/thread.h78
-rw-r--r--src/core/hle/kernel/timer.cpp19
-rw-r--r--src/core/hle/kernel/timer.h22
-rw-r--r--src/core/hle/kernel/vm_manager.cpp36
-rw-r--r--src/core/hle/kernel/vm_manager.h21
30 files changed, 616 insertions, 419 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index 5c3c47acf..2ff652f13 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -16,8 +16,10 @@
16 16
17namespace Kernel { 17namespace Kernel {
18 18
19AddressArbiter::AddressArbiter() {} 19AddressArbiter::AddressArbiter() {
20AddressArbiter::~AddressArbiter() {} 20}
21AddressArbiter::~AddressArbiter() {
22}
21 23
22SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { 24SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) {
23 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); 25 SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter);
@@ -28,7 +30,7 @@ SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) {
28} 30}
29 31
30ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, 32ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value,
31 u64 nanoseconds) { 33 u64 nanoseconds) {
32 switch (type) { 34 switch (type) {
33 35
34 // Signal thread(s) waiting for arbitrate address... 36 // Signal thread(s) waiting for arbitrate address...
@@ -38,7 +40,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
38 ArbitrateAllThreads(address); 40 ArbitrateAllThreads(address);
39 } else { 41 } else {
40 // Resume first N threads 42 // Resume first N threads
41 for(int i = 0; i < value; i++) 43 for (int i = 0; i < value; i++)
42 ArbitrateHighestPriorityThread(address); 44 ArbitrateHighestPriorityThread(address);
43 } 45 }
44 break; 46 break;
@@ -55,8 +57,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
55 GetCurrentThread()->WakeAfterDelay(nanoseconds); 57 GetCurrentThread()->WakeAfterDelay(nanoseconds);
56 } 58 }
57 break; 59 break;
58 case ArbitrationType::DecrementAndWaitIfLessThan: 60 case ArbitrationType::DecrementAndWaitIfLessThan: {
59 {
60 s32 memory_value = Memory::Read32(address); 61 s32 memory_value = Memory::Read32(address);
61 if (memory_value < value) { 62 if (memory_value < value) {
62 // Only change the memory value if the thread should wait 63 // Only change the memory value if the thread should wait
@@ -65,8 +66,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
65 } 66 }
66 break; 67 break;
67 } 68 }
68 case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: 69 case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: {
69 {
70 s32 memory_value = Memory::Read32(address); 70 s32 memory_value = Memory::Read32(address);
71 if (memory_value < value) { 71 if (memory_value < value) {
72 // Only change the memory value if the thread should wait 72 // Only change the memory value if the thread should wait
@@ -79,17 +79,19 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address,
79 79
80 default: 80 default:
81 LOG_ERROR(Kernel, "unknown type=%d", type); 81 LOG_ERROR(Kernel, "unknown type=%d", type);
82 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage); 82 return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
83 ErrorSummary::WrongArgument, ErrorLevel::Usage);
83 } 84 }
84 85
85 HLE::Reschedule(__func__); 86 HLE::Reschedule(__func__);
86 87
87 // The calls that use a timeout seem to always return a Timeout error even if they did not put the thread to sleep 88 // The calls that use a timeout seem to always return a Timeout error even if they did not put
89 // the thread to sleep
88 if (type == ArbitrationType::WaitIfLessThanWithTimeout || 90 if (type == ArbitrationType::WaitIfLessThanWithTimeout ||
89 type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { 91 type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) {
90 92
91 return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, 93 return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, ErrorSummary::StatusChanged,
92 ErrorSummary::StatusChanged, ErrorLevel::Info); 94 ErrorLevel::Info);
93 } 95 }
94 return RESULT_SUCCESS; 96 return RESULT_SUCCESS;
95} 97}
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index 8f6a1a8df..1a03993b2 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -36,13 +36,19 @@ public:
36 */ 36 */
37 static SharedPtr<AddressArbiter> Create(std::string name = "Unknown"); 37 static SharedPtr<AddressArbiter> Create(std::string name = "Unknown");
38 38
39 std::string GetTypeName() const override { return "Arbiter"; } 39 std::string GetTypeName() const override {
40 std::string GetName() const override { return name; } 40 return "Arbiter";
41 }
42 std::string GetName() const override {
43 return name;
44 }
41 45
42 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; 46 static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
43 HandleType GetHandleType() const override { return HANDLE_TYPE; } 47 HandleType GetHandleType() const override {
48 return HANDLE_TYPE;
49 }
44 50
45 std::string name; ///< Name of address arbiter object (optional) 51 std::string name; ///< Name of address arbiter object (optional)
46 52
47 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); 53 ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds);
48 54
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 444ce8d45..5df769c6a 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -10,7 +10,9 @@
10 10
11namespace Kernel { 11namespace Kernel {
12 12
13ClientPort::ClientPort() {} 13ClientPort::ClientPort() {
14ClientPort::~ClientPort() {} 14}
15ClientPort::~ClientPort() {
16}
15 17
16} // namespace 18} // namespace
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index 480b6ddae..70e0d56cc 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -17,16 +17,22 @@ class ServerPort;
17class ClientPort : public Object { 17class ClientPort : public Object {
18public: 18public:
19 friend class ServerPort; 19 friend class ServerPort;
20 std::string GetTypeName() const override { return "ClientPort"; } 20 std::string GetTypeName() const override {
21 std::string GetName() const override { return name; } 21 return "ClientPort";
22 }
23 std::string GetName() const override {
24 return name;
25 }
22 26
23 static const HandleType HANDLE_TYPE = HandleType::ClientPort; 27 static const HandleType HANDLE_TYPE = HandleType::ClientPort;
24 HandleType GetHandleType() const override { return HANDLE_TYPE; } 28 HandleType GetHandleType() const override {
25 29 return HANDLE_TYPE;
26 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. 30 }
27 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have 31
28 u32 active_sessions; ///< Number of currently open sessions to this port 32 SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
29 std::string name; ///< Name of client port (optional) 33 u32 max_sessions; ///< Maximum number of simultaneous sessions the port can have
34 u32 active_sessions; ///< Number of currently open sessions to this port
35 std::string name; ///< Name of client port (optional)
30 36
31protected: 37protected:
32 ClientPort(); 38 ClientPort();
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 2b7c6992a..63375818d 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -2,20 +2,22 @@
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 <map>
6#include <algorithm> 5#include <algorithm>
6#include <map>
7#include <vector> 7#include <vector>
8 8
9#include "common/assert.h" 9#include "common/assert.h"
10 10
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/event.h" 11#include "core/hle/kernel/event.h"
12#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/thread.h" 13#include "core/hle/kernel/thread.h"
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17Event::Event() {} 17Event::Event() {
18Event::~Event() {} 18}
19Event::~Event() {
20}
19 21
20SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { 22SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {
21 SharedPtr<Event> evt(new Event); 23 SharedPtr<Event> evt(new Event);
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 73d0da419..e333a46ce 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -16,7 +16,6 @@ enum class ResetType {
16 Pulse, 16 Pulse,
17}; 17};
18 18
19
20class Event final : public WaitObject { 19class Event final : public WaitObject {
21public: 20public:
22 /** 21 /**
@@ -26,16 +25,22 @@ public:
26 */ 25 */
27 static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown"); 26 static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown");
28 27
29 std::string GetTypeName() const override { return "Event"; } 28 std::string GetTypeName() const override {
30 std::string GetName() const override { return name; } 29 return "Event";
30 }
31 std::string GetName() const override {
32 return name;
33 }
31 34
32 static const HandleType HANDLE_TYPE = HandleType::Event; 35 static const HandleType HANDLE_TYPE = HandleType::Event;
33 HandleType GetHandleType() const override { return HANDLE_TYPE; } 36 HandleType GetHandleType() const override {
37 return HANDLE_TYPE;
38 }
34 39
35 ResetType reset_type; ///< Current ResetType 40 ResetType reset_type; ///< Current ResetType
36 41
37 bool signaled; ///< Whether the event has already been signaled 42 bool signaled; ///< Whether the event has already been signaled
38 std::string name; ///< Name of event (optional) 43 std::string name; ///< Name of event (optional)
39 44
40 bool ShouldWait() override; 45 bool ShouldWait() override;
41 void Acquire() override; 46 void Acquire() override;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 7a401a965..1fd7c0326 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -61,7 +61,8 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
61 61
62 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. 62 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
63 // CTR-OS doesn't use generation 0, so skip straight to 1. 63 // CTR-OS doesn't use generation 0, so skip straight to 1.
64 if (next_generation >= (1 << 15)) next_generation = 1; 64 if (next_generation >= (1 << 15))
65 next_generation = 1;
65 66
66 generations[slot] = generation; 67 generations[slot] = generation;
67 objects[slot] = std::move(obj); 68 objects[slot] = std::move(obj);
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 27ba3f912..cc39652d5 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -23,48 +23,55 @@ class Thread;
23 23
24// TODO: Verify code 24// TODO: Verify code
25const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, 25const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
26 ErrorSummary::OutOfResource, ErrorLevel::Temporary); 26 ErrorSummary::OutOfResource, ErrorLevel::Temporary);
27// TOOD: Verify code 27// TOOD: Verify code
28const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, 28const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel,
29 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 29 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
30 30
31enum KernelHandle : Handle { 31enum KernelHandle : Handle {
32 CurrentThread = 0xFFFF8000, 32 CurrentThread = 0xFFFF8000,
33 CurrentProcess = 0xFFFF8001, 33 CurrentProcess = 0xFFFF8001,
34}; 34};
35 35
36enum class HandleType : u32 { 36enum class HandleType : u32 {
37 Unknown = 0, 37 Unknown = 0,
38 38
39 Session = 2, 39 Session = 2,
40 Event = 3, 40 Event = 3,
41 Mutex = 4, 41 Mutex = 4,
42 SharedMemory = 5, 42 SharedMemory = 5,
43 Redirection = 6, 43 Redirection = 6,
44 Thread = 7, 44 Thread = 7,
45 Process = 8, 45 Process = 8,
46 AddressArbiter = 9, 46 AddressArbiter = 9,
47 Semaphore = 10, 47 Semaphore = 10,
48 Timer = 11, 48 Timer = 11,
49 ResourceLimit = 12, 49 ResourceLimit = 12,
50 CodeSet = 13, 50 CodeSet = 13,
51 ClientPort = 14, 51 ClientPort = 14,
52 ServerPort = 15, 52 ServerPort = 15,
53}; 53};
54 54
55enum { 55enum {
56 DEFAULT_STACK_SIZE = 0x4000, 56 DEFAULT_STACK_SIZE = 0x4000,
57}; 57};
58 58
59class Object : NonCopyable { 59class Object : NonCopyable {
60public: 60public:
61 virtual ~Object() {} 61 virtual ~Object() {
62 }
62 63
63 /// Returns a unique identifier for the object. For debugging purposes only. 64 /// Returns a unique identifier for the object. For debugging purposes only.
64 unsigned int GetObjectId() const { return object_id; } 65 unsigned int GetObjectId() const {
66 return object_id;
67 }
65 68
66 virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } 69 virtual std::string GetTypeName() const {
67 virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } 70 return "[BAD KERNEL OBJECT TYPE]";
71 }
72 virtual std::string GetName() const {
73 return "[UNKNOWN KERNEL OBJECT]";
74 }
68 virtual Kernel::HandleType GetHandleType() const = 0; 75 virtual Kernel::HandleType GetHandleType() const = 0;
69 76
70 /** 77 /**
@@ -122,7 +129,6 @@ using SharedPtr = boost::intrusive_ptr<T>;
122/// Class that represents a Kernel object that a thread can be waiting on 129/// Class that represents a Kernel object that a thread can be waiting on
123class WaitObject : public Object { 130class WaitObject : public Object {
124public: 131public:
125
126 /** 132 /**
127 * Check if the current thread should wait until the object is available 133 * Check if the current thread should wait until the object is available
128 * @return True if the current thread should wait due to this object being unavailable 134 * @return True if the current thread should wait due to this object being unavailable
@@ -247,8 +253,12 @@ private:
247 */ 253 */
248 static const size_t MAX_COUNT = 4096; 254 static const size_t MAX_COUNT = 4096;
249 255
250 static u16 GetSlot(Handle handle) { return handle >> 15; } 256 static u16 GetSlot(Handle handle) {
251 static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; } 257 return handle >> 15;
258 }
259 static u16 GetGeneration(Handle handle) {
260 return handle & 0x7FFF;
261 }
252 262
253 /// Stores the Object referenced by the handle or null if the slot is empty. 263 /// Stores the Object referenced by the handle or null if the slot is empty.
254 std::array<SharedPtr<Object>, MAX_COUNT> objects; 264 std::array<SharedPtr<Object>, MAX_COUNT> objects;
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
index 17ae87aef..89a72808a 100644
--- a/src/core/hle/kernel/memory.cpp
+++ b/src/core/hle/kernel/memory.cpp
@@ -31,7 +31,7 @@ static MemoryRegionInfo memory_regions[3];
31static const u32 memory_region_sizes[8][3] = { 31static const u32 memory_region_sizes[8][3] = {
32 // Old 3DS layouts 32 // Old 3DS layouts
33 {0x04000000, 0x02C00000, 0x01400000}, // 0 33 {0x04000000, 0x02C00000, 0x01400000}, // 0
34 { /* This appears to be unused. */ }, // 1 34 {/* This appears to be unused. */}, // 1
35 {0x06000000, 0x00C00000, 0x01400000}, // 2 35 {0x06000000, 0x00C00000, 0x01400000}, // 2
36 {0x05000000, 0x01C00000, 0x01400000}, // 3 36 {0x05000000, 0x01C00000, 0x01400000}, // 3
37 {0x04800000, 0x02400000, 0x01400000}, // 4 37 {0x04800000, 0x02400000, 0x01400000}, // 4
@@ -95,7 +95,6 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) {
95 UNREACHABLE(); 95 UNREACHABLE();
96 } 96 }
97} 97}
98
99} 98}
100 99
101namespace Memory { 100namespace Memory {
@@ -110,9 +109,8 @@ struct MemoryArea {
110 109
111// We don't declare the IO regions in here since its handled by other means. 110// We don't declare the IO regions in here since its handled by other means.
112static MemoryArea memory_areas[] = { 111static MemoryArea memory_areas[] = {
113 {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM) 112 {VRAM_VADDR, VRAM_SIZE, "VRAM"}, // Video memory (VRAM)
114}; 113};
115
116} 114}
117 115
118void Init() { 116void Init() {
@@ -125,15 +123,21 @@ void InitLegacyAddressSpace(Kernel::VMManager& address_space) {
125 123
126 for (MemoryArea& area : memory_areas) { 124 for (MemoryArea& area : memory_areas) {
127 auto block = std::make_shared<std::vector<u8>>(area.size); 125 auto block = std::make_shared<std::vector<u8>>(area.size);
128 address_space.MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private).Unwrap(); 126 address_space
127 .MapMemoryBlock(area.base, std::move(block), 0, area.size, MemoryState::Private)
128 .Unwrap();
129 } 129 }
130 130
131 auto cfg_mem_vma = address_space.MapBackingMemory(CONFIG_MEMORY_VADDR, 131 auto cfg_mem_vma = address_space
132 (u8*)&ConfigMem::config_mem, CONFIG_MEMORY_SIZE, MemoryState::Shared).MoveFrom(); 132 .MapBackingMemory(CONFIG_MEMORY_VADDR, (u8*)&ConfigMem::config_mem,
133 CONFIG_MEMORY_SIZE, MemoryState::Shared)
134 .MoveFrom();
133 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read); 135 address_space.Reprotect(cfg_mem_vma, VMAPermission::Read);
134 136
135 auto shared_page_vma = address_space.MapBackingMemory(SHARED_PAGE_VADDR, 137 auto shared_page_vma = address_space
136 (u8*)&SharedPage::shared_page, SHARED_PAGE_SIZE, MemoryState::Shared).MoveFrom(); 138 .MapBackingMemory(SHARED_PAGE_VADDR, (u8*)&SharedPage::shared_page,
139 SHARED_PAGE_SIZE, MemoryState::Shared)
140 .MoveFrom();
137 address_space.Reprotect(shared_page_vma, VMAPermission::Read); 141 address_space.Reprotect(shared_page_vma, VMAPermission::Read);
138 142
139 AudioCore::AddAddressSpace(address_space); 143 AudioCore::AddAddressSpace(address_space);
diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h
index 091c1f89f..b941c24b6 100644
--- a/src/core/hle/kernel/memory.h
+++ b/src/core/hle/kernel/memory.h
@@ -25,7 +25,6 @@ struct MemoryRegionInfo {
25void MemoryInit(u32 mem_type); 25void MemoryInit(u32 mem_type);
26void MemoryShutdown(); 26void MemoryShutdown();
27MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); 27MemoryRegionInfo* GetMemoryRegion(MemoryRegion region);
28
29} 28}
30 29
31namespace Memory { 30namespace Memory {
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index edb97d324..f92810804 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -33,8 +33,10 @@ void ReleaseThreadMutexes(Thread* thread) {
33 thread->held_mutexes.clear(); 33 thread->held_mutexes.clear();
34} 34}
35 35
36Mutex::Mutex() {} 36Mutex::Mutex() {
37Mutex::~Mutex() {} 37}
38Mutex::~Mutex() {
39}
38 40
39SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) { 41SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
40 SharedPtr<Mutex> mutex(new Mutex); 42 SharedPtr<Mutex> mutex(new Mutex);
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 1746360e4..cf6a51fdf 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -24,15 +24,21 @@ public:
24 */ 24 */
25 static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown"); 25 static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown");
26 26
27 std::string GetTypeName() const override { return "Mutex"; } 27 std::string GetTypeName() const override {
28 std::string GetName() const override { return name; } 28 return "Mutex";
29 }
30 std::string GetName() const override {
31 return name;
32 }
29 33
30 static const HandleType HANDLE_TYPE = HandleType::Mutex; 34 static const HandleType HANDLE_TYPE = HandleType::Mutex;
31 HandleType GetHandleType() const override { return HANDLE_TYPE; } 35 HandleType GetHandleType() const override {
36 return HANDLE_TYPE;
37 }
32 38
33 int lock_count; ///< Number of times the mutex has been acquired 39 int lock_count; ///< Number of times the mutex has been acquired
34 std::string name; ///< Name of mutex (optional) 40 std::string name; ///< Name of mutex (optional)
35 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex 41 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
36 42
37 bool ShouldWait() override; 43 bool ShouldWait() override;
38 void Acquire() override; 44 void Acquire() override;
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 69302cc82..cc37e574c 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -26,8 +26,10 @@ SharedPtr<CodeSet> CodeSet::Create(std::string name, u64 program_id) {
26 return codeset; 26 return codeset;
27} 27}
28 28
29CodeSet::CodeSet() {} 29CodeSet::CodeSet() {
30CodeSet::~CodeSet() {} 30}
31CodeSet::~CodeSet() {
32}
31 33
32u32 Process::next_process_id; 34u32 Process::next_process_id;
33 35
@@ -60,7 +62,8 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
60 62
61 while (bits && index < svc_access_mask.size()) { 63 while (bits && index < svc_access_mask.size()) {
62 svc_access_mask.set(index, bits & 1); 64 svc_access_mask.set(index, bits & 1);
63 ++index; bits >>= 1; 65 ++index;
66 bits >>= 1;
64 } 67 }
65 } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF 68 } else if ((type & 0xFF0) == 0xFE0) { // 0x00FF
66 // Handle table size 69 // Handle table size
@@ -70,11 +73,11 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
70 flags.raw = descriptor & 0xFFFF; 73 flags.raw = descriptor & 0xFFFF;
71 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F 74 } else if ((type & 0xFFE) == 0xFF8) { // 0x001F
72 // Mapped memory range 75 // Mapped memory range
73 if (i+1 >= len || ((kernel_caps[i+1] >> 20) & 0xFFE) != 0xFF8) { 76 if (i + 1 >= len || ((kernel_caps[i + 1] >> 20) & 0xFFE) != 0xFF8) {
74 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored."); 77 LOG_WARNING(Loader, "Incomplete exheader memory range descriptor ignored.");
75 continue; 78 continue;
76 } 79 }
77 u32 end_desc = kernel_caps[i+1]; 80 u32 end_desc = kernel_caps[i + 1];
78 ++i; // Skip over the second descriptor on the next iteration 81 ++i; // Skip over the second descriptor on the next iteration
79 82
80 AddressMapping mapping; 83 AddressMapping mapping;
@@ -107,23 +110,28 @@ void Process::ParseKernelCaps(const u32* kernel_caps, size_t len) {
107void Process::Run(s32 main_thread_priority, u32 stack_size) { 110void Process::Run(s32 main_thread_priority, u32 stack_size) {
108 memory_region = GetMemoryRegion(flags.memory_region); 111 memory_region = GetMemoryRegion(flags.memory_region);
109 112
110 auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { 113 auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
111 auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory, 114 MemoryState memory_state) {
112 segment.offset, segment.size, memory_state).Unwrap(); 115 auto vma = vm_manager
116 .MapMemoryBlock(segment.addr, codeset->memory, segment.offset, segment.size,
117 memory_state)
118 .Unwrap();
113 vm_manager.Reprotect(vma, permissions); 119 vm_manager.Reprotect(vma, permissions);
114 misc_memory_used += segment.size; 120 misc_memory_used += segment.size;
115 memory_region->used += segment.size; 121 memory_region->used += segment.size;
116 }; 122 };
117 123
118 // Map CodeSet segments 124 // Map CodeSet segments
119 MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code); 125 MapSegment(codeset->code, VMAPermission::ReadExecute, MemoryState::Code);
120 MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code); 126 MapSegment(codeset->rodata, VMAPermission::Read, MemoryState::Code);
121 MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private); 127 MapSegment(codeset->data, VMAPermission::ReadWrite, MemoryState::Private);
122 128
123 // Allocate and map stack 129 // Allocate and map stack
124 vm_manager.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, 130 vm_manager
125 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked 131 .MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size,
126 ).Unwrap(); 132 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size,
133 MemoryState::Locked)
134 .Unwrap();
127 misc_memory_used += stack_size; 135 misc_memory_used += stack_size;
128 memory_region->used += stack_size; 136 memory_region->used += stack_size;
129 137
@@ -143,7 +151,8 @@ VAddr Process::GetLinearHeapLimit() const {
143} 151}
144 152
145ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) { 153ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) {
146 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { 154 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
155 target + size < target) {
147 return ERR_INVALID_ADDRESS; 156 return ERR_INVALID_ADDRESS;
148 } 157 }
149 158
@@ -166,7 +175,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
166 } 175 }
167 ASSERT(heap_end - heap_start == heap_memory->size()); 176 ASSERT(heap_end - heap_start == heap_memory->size());
168 177
169 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, size, MemoryState::Private)); 178 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start,
179 size, MemoryState::Private));
170 vm_manager.Reprotect(vma, perms); 180 vm_manager.Reprotect(vma, perms);
171 181
172 heap_used += size; 182 heap_used += size;
@@ -176,7 +186,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
176} 186}
177 187
178ResultCode Process::HeapFree(VAddr target, u32 size) { 188ResultCode Process::HeapFree(VAddr target, u32 size) {
179 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || target + size < target) { 189 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
190 target + size < target) {
180 return ERR_INVALID_ADDRESS; 191 return ERR_INVALID_ADDRESS;
181 } 192 }
182 193
@@ -185,7 +196,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
185 } 196 }
186 197
187 ResultCode result = vm_manager.UnmapRange(target, size); 198 ResultCode result = vm_manager.UnmapRange(target, size);
188 if (result.IsError()) return result; 199 if (result.IsError())
200 return result;
189 201
190 heap_used -= size; 202 heap_used -= size;
191 memory_region->used -= size; 203 memory_region->used -= size;
@@ -203,8 +215,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
203 target = heap_end; 215 target = heap_end;
204 } 216 }
205 217
206 if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || 218 if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() || target > heap_end ||
207 target > heap_end || target + size < target) { 219 target + size < target) {
208 220
209 return ERR_INVALID_ADDRESS; 221 return ERR_INVALID_ADDRESS;
210 } 222 }
@@ -220,7 +232,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
220 // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the 232 // TODO(yuriks): As is, this lets processes map memory allocated by other processes from the
221 // same region. It is unknown if or how the 3DS kernel checks against this. 233 // same region. It is unknown if or how the 3DS kernel checks against this.
222 size_t offset = target - GetLinearHeapBase(); 234 size_t offset = target - GetLinearHeapBase();
223 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous)); 235 CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size,
236 MemoryState::Continuous));
224 vm_manager.Reprotect(vma, perms); 237 vm_manager.Reprotect(vma, perms);
225 238
226 linear_heap_used += size; 239 linear_heap_used += size;
@@ -248,7 +261,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
248 } 261 }
249 262
250 ResultCode result = vm_manager.UnmapRange(target, size); 263 ResultCode result = vm_manager.UnmapRange(target, size);
251 if (result.IsError()) return result; 264 if (result.IsError())
265 return result;
252 266
253 linear_heap_used -= size; 267 linear_heap_used -= size;
254 memory_region->used -= size; 268 memory_region->used -= size;
@@ -268,9 +282,10 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
268 return RESULT_SUCCESS; 282 return RESULT_SUCCESS;
269} 283}
270 284
271Kernel::Process::Process() {} 285Kernel::Process::Process() {
272Kernel::Process::~Process() {} 286}
287Kernel::Process::~Process() {
288}
273 289
274SharedPtr<Process> g_current_process; 290SharedPtr<Process> g_current_process;
275
276} 291}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index d781ef32c..070b2b558 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -36,15 +36,18 @@ enum class MemoryRegion : u16 {
36union ProcessFlags { 36union ProcessFlags {
37 u16 raw; 37 u16 raw;
38 38
39 BitField< 0, 1, u16> allow_debug; ///< Allows other processes to attach to and debug this process. 39 BitField<0, 1, u16>
40 BitField< 1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they don't have allow_debug set. 40 allow_debug; ///< Allows other processes to attach to and debug this process.
41 BitField< 2, 1, u16> allow_nonalphanum; 41 BitField<1, 1, u16> force_debug; ///< Allows this process to attach to processes even if they
42 BitField< 3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions. 42 /// don't have allow_debug set.
43 BitField< 4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24. 43 BitField<2, 1, u16> allow_nonalphanum;
44 BitField< 5, 1, u16> allow_main_args; 44 BitField<3, 1, u16> shared_page_writable; ///< Shared page is mapped with write permissions.
45 BitField< 6, 1, u16> shared_device_mem; 45 BitField<4, 1, u16> privileged_priority; ///< Can use priority levels higher than 24.
46 BitField< 7, 1, u16> runnable_on_sleep; 46 BitField<5, 1, u16> allow_main_args;
47 BitField< 8, 4, MemoryRegion> memory_region; ///< Default region for memory allocations for this process 47 BitField<6, 1, u16> shared_device_mem;
48 BitField<7, 1, u16> runnable_on_sleep;
49 BitField<8, 4, MemoryRegion>
50 memory_region; ///< Default region for memory allocations for this process
48 BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000). 51 BitField<12, 1, u16> loaded_high; ///< Application loaded high (not at 0x00100000).
49}; 52};
50 53
@@ -54,11 +57,17 @@ struct MemoryRegionInfo;
54struct CodeSet final : public Object { 57struct CodeSet final : public Object {
55 static SharedPtr<CodeSet> Create(std::string name, u64 program_id); 58 static SharedPtr<CodeSet> Create(std::string name, u64 program_id);
56 59
57 std::string GetTypeName() const override { return "CodeSet"; } 60 std::string GetTypeName() const override {
58 std::string GetName() const override { return name; } 61 return "CodeSet";
62 }
63 std::string GetName() const override {
64 return name;
65 }
59 66
60 static const HandleType HANDLE_TYPE = HandleType::CodeSet; 67 static const HandleType HANDLE_TYPE = HandleType::CodeSet;
61 HandleType GetHandleType() const override { return HANDLE_TYPE; } 68 HandleType GetHandleType() const override {
69 return HANDLE_TYPE;
70 }
62 71
63 /// Name of the process 72 /// Name of the process
64 std::string name; 73 std::string name;
@@ -85,11 +94,17 @@ class Process final : public Object {
85public: 94public:
86 static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set); 95 static SharedPtr<Process> Create(SharedPtr<CodeSet> code_set);
87 96
88 std::string GetTypeName() const override { return "Process"; } 97 std::string GetTypeName() const override {
89 std::string GetName() const override { return codeset->name; } 98 return "Process";
99 }
100 std::string GetName() const override {
101 return codeset->name;
102 }
90 103
91 static const HandleType HANDLE_TYPE = HandleType::Process; 104 static const HandleType HANDLE_TYPE = HandleType::Process;
92 HandleType GetHandleType() const override { return HANDLE_TYPE; } 105 HandleType GetHandleType() const override {
106 return HANDLE_TYPE;
107 }
93 108
94 static u32 next_process_id; 109 static u32 next_process_id;
95 110
@@ -124,7 +139,6 @@ public:
124 */ 139 */
125 void Run(s32 main_thread_priority, u32 stack_size); 140 void Run(s32 main_thread_priority, u32 stack_size);
126 141
127
128 /////////////////////////////////////////////////////////////////////////////////////////////// 142 ///////////////////////////////////////////////////////////////////////////////////////////////
129 // Memory Management 143 // Memory Management
130 144
@@ -144,7 +158,8 @@ public:
144 158
145 /// The Thread Local Storage area is allocated as processes create threads, 159 /// The Thread Local Storage area is allocated as processes create threads,
146 /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part 160 /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part
147 /// holds the TLS for a specific thread. This vector contains which parts are in use for each page as a bitmask. 161 /// holds the TLS for a specific thread. This vector contains which parts are in use for each
162 /// page as a bitmask.
148 /// This vector will grow as more pages are allocated for new threads. 163 /// This vector will grow as more pages are allocated for new threads.
149 std::vector<std::bitset<8>> tls_slots; 164 std::vector<std::bitset<8>> tls_slots;
150 165
@@ -164,5 +179,4 @@ private:
164}; 179};
165 180
166extern SharedPtr<Process> g_current_process; 181extern SharedPtr<Process> g_current_process;
167
168} 182}
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index 67dde08c2..7bd1c1e08 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -12,8 +12,10 @@ namespace Kernel {
12 12
13static SharedPtr<ResourceLimit> resource_limits[4]; 13static SharedPtr<ResourceLimit> resource_limits[4];
14 14
15ResourceLimit::ResourceLimit() {} 15ResourceLimit::ResourceLimit() {
16ResourceLimit::~ResourceLimit() {} 16}
17ResourceLimit::~ResourceLimit() {
18}
17 19
18SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { 20SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
19 SharedPtr<ResourceLimit> resource_limit(new ResourceLimit); 21 SharedPtr<ResourceLimit> resource_limit(new ResourceLimit);
@@ -23,70 +25,69 @@ SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
23} 25}
24 26
25SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { 27SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) {
26 switch (category) 28 switch (category) {
27 { 29 case ResourceLimitCategory::APPLICATION:
28 case ResourceLimitCategory::APPLICATION: 30 case ResourceLimitCategory::SYS_APPLET:
29 case ResourceLimitCategory::SYS_APPLET: 31 case ResourceLimitCategory::LIB_APPLET:
30 case ResourceLimitCategory::LIB_APPLET: 32 case ResourceLimitCategory::OTHER:
31 case ResourceLimitCategory::OTHER: 33 return resource_limits[static_cast<u8>(category)];
32 return resource_limits[static_cast<u8>(category)]; 34 default:
33 default: 35 LOG_CRITICAL(Kernel, "Unknown resource limit category");
34 LOG_CRITICAL(Kernel, "Unknown resource limit category"); 36 UNREACHABLE();
35 UNREACHABLE();
36 } 37 }
37} 38}
38 39
39s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { 40s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const {
40 switch (resource) { 41 switch (resource) {
41 case COMMIT: 42 case COMMIT:
42 return current_commit; 43 return current_commit;
43 case THREAD: 44 case THREAD:
44 return current_threads; 45 return current_threads;
45 case EVENT: 46 case EVENT:
46 return current_events; 47 return current_events;
47 case MUTEX: 48 case MUTEX:
48 return current_mutexes; 49 return current_mutexes;
49 case SEMAPHORE: 50 case SEMAPHORE:
50 return current_semaphores; 51 return current_semaphores;
51 case TIMER: 52 case TIMER:
52 return current_timers; 53 return current_timers;
53 case SHARED_MEMORY: 54 case SHARED_MEMORY:
54 return current_shared_mems; 55 return current_shared_mems;
55 case ADDRESS_ARBITER: 56 case ADDRESS_ARBITER:
56 return current_address_arbiters; 57 return current_address_arbiters;
57 case CPU_TIME: 58 case CPU_TIME:
58 return current_cpu_time; 59 return current_cpu_time;
59 default: 60 default:
60 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); 61 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
61 UNIMPLEMENTED(); 62 UNIMPLEMENTED();
62 return 0; 63 return 0;
63 } 64 }
64} 65}
65 66
66s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { 67s32 ResourceLimit::GetMaxResourceValue(u32 resource) const {
67 switch (resource) { 68 switch (resource) {
68 case COMMIT: 69 case COMMIT:
69 return max_commit; 70 return max_commit;
70 case THREAD: 71 case THREAD:
71 return max_threads; 72 return max_threads;
72 case EVENT: 73 case EVENT:
73 return max_events; 74 return max_events;
74 case MUTEX: 75 case MUTEX:
75 return max_mutexes; 76 return max_mutexes;
76 case SEMAPHORE: 77 case SEMAPHORE:
77 return max_semaphores; 78 return max_semaphores;
78 case TIMER: 79 case TIMER:
79 return max_timers; 80 return max_timers;
80 case SHARED_MEMORY: 81 case SHARED_MEMORY:
81 return max_shared_mems; 82 return max_shared_mems;
82 case ADDRESS_ARBITER: 83 case ADDRESS_ARBITER:
83 return max_address_arbiters; 84 return max_address_arbiters;
84 case CPU_TIME: 85 case CPU_TIME:
85 return max_cpu_time; 86 return max_cpu_time;
86 default: 87 default:
87 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource); 88 LOG_ERROR(Kernel, "Unknown resource type=%08X", resource);
88 UNIMPLEMENTED(); 89 UNIMPLEMENTED();
89 return 0; 90 return 0;
90 } 91 }
91} 92}
92 93
@@ -150,7 +151,6 @@ void ResourceLimitsInit() {
150} 151}
151 152
152void ResourceLimitsShutdown() { 153void ResourceLimitsShutdown() {
153
154} 154}
155 155
156} // namespace 156} // namespace
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index 1b8249c74..c08e744e6 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -12,22 +12,22 @@ namespace Kernel {
12 12
13enum class ResourceLimitCategory : u8 { 13enum class ResourceLimitCategory : u8 {
14 APPLICATION = 0, 14 APPLICATION = 0,
15 SYS_APPLET = 1, 15 SYS_APPLET = 1,
16 LIB_APPLET = 2, 16 LIB_APPLET = 2,
17 OTHER = 3 17 OTHER = 3
18}; 18};
19 19
20enum ResourceTypes { 20enum ResourceTypes {
21 PRIORITY = 0, 21 PRIORITY = 0,
22 COMMIT = 1, 22 COMMIT = 1,
23 THREAD = 2, 23 THREAD = 2,
24 EVENT = 3, 24 EVENT = 3,
25 MUTEX = 4, 25 MUTEX = 4,
26 SEMAPHORE = 5, 26 SEMAPHORE = 5,
27 TIMER = 6, 27 TIMER = 6,
28 SHARED_MEMORY = 7, 28 SHARED_MEMORY = 7,
29 ADDRESS_ARBITER = 8, 29 ADDRESS_ARBITER = 8,
30 CPU_TIME = 9, 30 CPU_TIME = 9,
31}; 31};
32 32
33class ResourceLimit final : public Object { 33class ResourceLimit final : public Object {
@@ -44,11 +44,17 @@ public:
44 */ 44 */
45 static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); 45 static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
46 46
47 std::string GetTypeName() const override { return "ResourceLimit"; } 47 std::string GetTypeName() const override {
48 std::string GetName() const override { return name; } 48 return "ResourceLimit";
49 }
50 std::string GetName() const override {
51 return name;
52 }
49 53
50 static const HandleType HANDLE_TYPE = HandleType::ResourceLimit; 54 static const HandleType HANDLE_TYPE = HandleType::ResourceLimit;
51 HandleType GetHandleType() const override { return HANDLE_TYPE; } 55 HandleType GetHandleType() const override {
56 return HANDLE_TYPE;
57 }
52 58
53 /** 59 /**
54 * Gets the current value for the specified resource. 60 * Gets the current value for the specified resource.
@@ -85,10 +91,12 @@ public:
85 /// Max CPU time that the processes in this category can utilize 91 /// Max CPU time that the processes in this category can utilize
86 s32 max_cpu_time = 0; 92 s32 max_cpu_time = 0;
87 93
88 // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind that 94 // TODO(Subv): Increment these in their respective Kernel::T::Create functions, keeping in mind
95 // that
89 // APPLICATION resource limits should not be affected by the objects created by service modules. 96 // APPLICATION resource limits should not be affected by the objects created by service modules.
90 // Currently we have no way of distinguishing if a Create was called by the running application, 97 // Currently we have no way of distinguishing if a Create was called by the running application,
91 // or by a service module. Approach this once we have separated the service modules into their own processes 98 // or by a service module. Approach this once we have separated the service modules into their
99 // own processes
92 100
93 /// Current memory that the processes in this category are using 101 /// Current memory that the processes in this category are using
94 s32 current_commit = 0; 102 s32 current_commit = 0;
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 4b359ed07..71e41079b 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -10,11 +10,13 @@
10 10
11namespace Kernel { 11namespace Kernel {
12 12
13Semaphore::Semaphore() {} 13Semaphore::Semaphore() {
14Semaphore::~Semaphore() {} 14}
15Semaphore::~Semaphore() {
16}
15 17
16ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, 18ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count,
17 std::string name) { 19 std::string name) {
18 20
19 if (initial_count > max_count) 21 if (initial_count > max_count)
20 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, 22 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel,
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index 390f5e495..ed7d9a85c 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -23,17 +23,23 @@ public:
23 * @return The created semaphore 23 * @return The created semaphore
24 */ 24 */
25 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count, 25 static ResultVal<SharedPtr<Semaphore>> Create(s32 initial_count, s32 max_count,
26 std::string name = "Unknown"); 26 std::string name = "Unknown");
27 27
28 std::string GetTypeName() const override { return "Semaphore"; } 28 std::string GetTypeName() const override {
29 std::string GetName() const override { return name; } 29 return "Semaphore";
30 }
31 std::string GetName() const override {
32 return name;
33 }
30 34
31 static const HandleType HANDLE_TYPE = HandleType::Semaphore; 35 static const HandleType HANDLE_TYPE = HandleType::Semaphore;
32 HandleType GetHandleType() const override { return HANDLE_TYPE; } 36 HandleType GetHandleType() const override {
37 return HANDLE_TYPE;
38 }
33 39
34 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have 40 s32 max_count; ///< Maximum number of simultaneous holders the semaphore can have
35 s32 available_count; ///< Number of free slots left in the semaphore 41 s32 available_count; ///< Number of free slots left in the semaphore
36 std::string name; ///< Name of semaphore (optional) 42 std::string name; ///< Name of semaphore (optional)
37 43
38 bool ShouldWait() override; 44 bool ShouldWait() override;
39 void Acquire() override; 45 void Acquire() override;
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index fcc684a20..7c690fa7f 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -13,8 +13,10 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16ServerPort::ServerPort() {} 16ServerPort::ServerPort() {
17ServerPort::~ServerPort() {} 17}
18ServerPort::~ServerPort() {
19}
18 20
19bool ServerPort::ShouldWait() { 21bool ServerPort::ShouldWait() {
20 // If there are no pending sessions, we wait until a new one is added. 22 // If there are no pending sessions, we wait until a new one is added.
@@ -25,7 +27,8 @@ void ServerPort::Acquire() {
25 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 27 ASSERT_MSG(!ShouldWait(), "object unavailable!");
26} 28}
27 29
28std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(u32 max_sessions, std::string name) { 30std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>>
31ServerPort::CreatePortPair(u32 max_sessions, std::string name) {
29 SharedPtr<ServerPort> server_port(new ServerPort); 32 SharedPtr<ServerPort> server_port(new ServerPort);
30 SharedPtr<ClientPort> client_port(new ClientPort); 33 SharedPtr<ClientPort> client_port(new ClientPort);
31 34
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index e9c972ce6..e43d48674 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -23,17 +23,25 @@ public:
23 * @param name Optional name of the ports 23 * @param name Optional name of the ports
24 * @return The created port tuple 24 * @return The created port tuple
25 */ 25 */
26 static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(u32 max_sessions, std::string name = "UnknownPort"); 26 static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>>
27 CreatePortPair(u32 max_sessions, std::string name = "UnknownPort");
27 28
28 std::string GetTypeName() const override { return "ServerPort"; } 29 std::string GetTypeName() const override {
29 std::string GetName() const override { return name; } 30 return "ServerPort";
31 }
32 std::string GetName() const override {
33 return name;
34 }
30 35
31 static const HandleType HANDLE_TYPE = HandleType::ServerPort; 36 static const HandleType HANDLE_TYPE = HandleType::ServerPort;
32 HandleType GetHandleType() const override { return HANDLE_TYPE; } 37 HandleType GetHandleType() const override {
38 return HANDLE_TYPE;
39 }
33 40
34 std::string name; ///< Name of port (optional) 41 std::string name; ///< Name of port (optional)
35 42
36 std::vector<SharedPtr<WaitObject>> pending_sessions; ///< ServerSessions waiting to be accepted by the port 43 std::vector<SharedPtr<WaitObject>>
44 pending_sessions; ///< ServerSessions waiting to be accepted by the port
37 45
38 bool ShouldWait() override; 46 bool ShouldWait() override;
39 void Acquire() override; 47 void Acquire() override;
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp
index 0594967f8..61457845a 100644
--- a/src/core/hle/kernel/session.cpp
+++ b/src/core/hle/kernel/session.cpp
@@ -7,7 +7,8 @@
7 7
8namespace Kernel { 8namespace Kernel {
9 9
10Session::Session() {} 10Session::Session() {
11Session::~Session() {} 11}
12 12Session::~Session() {
13}
13} 14}
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h
index 8ec889967..8e4e010b8 100644
--- a/src/core/hle/kernel/session.h
+++ b/src/core/hle/kernel/session.h
@@ -19,12 +19,13 @@ namespace IPC {
19enum DescriptorType : u32 { 19enum DescriptorType : u32 {
20 // Buffer related desciptors types (mask : 0x0F) 20 // Buffer related desciptors types (mask : 0x0F)
21 StaticBuffer = 0x02, 21 StaticBuffer = 0x02,
22 PXIBuffer = 0x04, 22 PXIBuffer = 0x04,
23 MappedBuffer = 0x08, 23 MappedBuffer = 0x08,
24 // Handle related descriptors types (mask : 0x30, but need to check for buffer related descriptors first ) 24 // Handle related descriptors types (mask : 0x30, but need to check for buffer related
25 CopyHandle = 0x00, 25 // descriptors first )
26 MoveHandle = 0x10, 26 CopyHandle = 0x00,
27 CallingPid = 0x20, 27 MoveHandle = 0x10,
28 CallingPid = 0x20,
28}; 29};
29 30
30/** 31/**
@@ -34,24 +35,28 @@ enum DescriptorType : u32 {
34 * @param translate_params_size Size of the translate parameters in words. Up to 63. 35 * @param translate_params_size Size of the translate parameters in words. Up to 63.
35 * @return The created IPC header. 36 * @return The created IPC header.
36 * 37 *
37 * Normal parameters are sent directly to the process while the translate parameters might go through modifications and checks by the kernel. 38 * Normal parameters are sent directly to the process while the translate parameters might go
39 * through modifications and checks by the kernel.
38 * The translate parameters are described by headers generated with the IPC::*Desc functions. 40 * The translate parameters are described by headers generated with the IPC::*Desc functions.
39 * 41 *
40 * @note While #normal_params is equivalent to the number of normal parameters, #translate_params_size includes the size occupied by the translate parameters headers. 42 * @note While #normal_params is equivalent to the number of normal parameters,
43 * #translate_params_size includes the size occupied by the translate parameters headers.
41 */ 44 */
42constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, unsigned int translate_params_size) { 45constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params,
43 return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) | (u32(translate_params_size) & 0x3F); 46 unsigned int translate_params_size) {
47 return (u32(command_id) << 16) | ((u32(normal_params) & 0x3F) << 6) |
48 (u32(translate_params_size) & 0x3F);
44} 49}
45 50
46union Header { 51union Header {
47 u32 raw; 52 u32 raw;
48 BitField< 0, 6, u32> translate_params_size; 53 BitField<0, 6, u32> translate_params_size;
49 BitField< 6, 6, u32> normal_params; 54 BitField<6, 6, u32> normal_params;
50 BitField<16, 16, u32> command_id; 55 BitField<16, 16, u32> command_id;
51}; 56};
52 57
53inline Header ParseHeader(u32 header) { 58inline Header ParseHeader(u32 header) {
54 return{ header }; 59 return {header};
55} 60}
56 61
57constexpr u32 MoveHandleDesc(u32 num_handles = 1) { 62constexpr u32 MoveHandleDesc(u32 num_handles = 1) {
@@ -80,27 +85,29 @@ constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) {
80 85
81union StaticBufferDescInfo { 86union StaticBufferDescInfo {
82 u32 raw; 87 u32 raw;
83 BitField< 10, 4, u32> buffer_id; 88 BitField<10, 4, u32> buffer_id;
84 BitField< 14, 18, u32> size; 89 BitField<14, 18, u32> size;
85}; 90};
86 91
87inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { 92inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) {
88 return{ desc }; 93 return {desc};
89} 94}
90 95
91/** 96/**
92 * @brief Creates a header describing a buffer to be sent over PXI. 97 * @brief Creates a header describing a buffer to be sent over PXI.
93 * @param size Size of the buffer. Max 0x00FFFFFF. 98 * @param size Size of the buffer. Max 0x00FFFFFF.
94 * @param buffer_id The Id of the buffer. Max 0xF. 99 * @param buffer_id The Id of the buffer. Max 0xF.
95 * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have read-write access. 100 * @param is_read_only true if the buffer is read-only. If false, the buffer is considered to have
101 * read-write access.
96 * @return The created PXI buffer header. 102 * @return The created PXI buffer header.
97 * 103 *
98 * The next value is a phys-address of a table located in the BASE memregion. 104 * The next value is a phys-address of a table located in the BASE memregion.
99 */ 105 */
100inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { 106inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) {
101 u32 type = PXIBuffer; 107 u32 type = PXIBuffer;
102 if (is_read_only) type |= 0x2; 108 if (is_read_only)
103 return type | (size << 8) | ((buffer_id & 0xF) << 4); 109 type |= 0x2;
110 return type | (size << 8) | ((buffer_id & 0xF) << 4);
104} 111}
105 112
106enum MappedBufferPermissions { 113enum MappedBufferPermissions {
@@ -115,12 +122,12 @@ constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) {
115 122
116union MappedBufferDescInfo { 123union MappedBufferDescInfo {
117 u32 raw; 124 u32 raw;
118 BitField< 4, 28, u32> size; 125 BitField<4, 28, u32> size;
119 BitField< 1, 2, MappedBufferPermissions> perms; 126 BitField<1, 2, MappedBufferPermissions> perms;
120}; 127};
121 128
122inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { 129inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) {
123 return{ desc }; 130 return {desc};
124} 131}
125 132
126inline DescriptorType GetDescriptorType(u32 descriptor) { 133inline DescriptorType GetDescriptorType(u32 descriptor) {
@@ -153,7 +160,8 @@ static const int kCommandHeaderOffset = 0x80; ///< Offset into command buffer of
153 * @return Pointer to command buffer 160 * @return Pointer to command buffer
154 */ 161 */
155inline u32* GetCommandBuffer(const int offset = 0) { 162inline u32* GetCommandBuffer(const int offset = 0) {
156 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset + offset); 163 return (u32*)Memory::GetPointer(GetCurrentThread()->GetTLSAddress() + kCommandHeaderOffset +
164 offset);
157} 165}
158 166
159/** 167/**
@@ -183,10 +191,14 @@ public:
183 Session(); 191 Session();
184 ~Session() override; 192 ~Session() override;
185 193
186 std::string GetTypeName() const override { return "Session"; } 194 std::string GetTypeName() const override {
195 return "Session";
196 }
187 197
188 static const HandleType HANDLE_TYPE = HandleType::Session; 198 static const HandleType HANDLE_TYPE = HandleType::Session;
189 HandleType GetHandleType() const override { return HANDLE_TYPE; } 199 HandleType GetHandleType() const override {
200 return HANDLE_TYPE;
201 }
190 202
191 /** 203 /**
192 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls 204 * Handles a synchronous call to this session using HLE emulation. Emulated <-> emulated calls
@@ -205,5 +217,4 @@ public:
205 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 217 ASSERT_MSG(!ShouldWait(), "object unavailable!");
206 } 218 }
207}; 219};
208
209} 220}
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 6a22c8986..74f40930c 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -6,17 +6,21 @@
6 6
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8 8
9#include "core/memory.h"
10#include "core/hle/kernel/memory.h" 9#include "core/hle/kernel/memory.h"
11#include "core/hle/kernel/shared_memory.h" 10#include "core/hle/kernel/shared_memory.h"
11#include "core/memory.h"
12 12
13namespace Kernel { 13namespace Kernel {
14 14
15SharedMemory::SharedMemory() {} 15SharedMemory::SharedMemory() {
16SharedMemory::~SharedMemory() {} 16}
17SharedMemory::~SharedMemory() {
18}
17 19
18SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, 20SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size,
19 MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) { 21 MemoryPermission permissions,
22 MemoryPermission other_permissions, VAddr address,
23 MemoryRegion region, std::string name) {
20 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 24 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
21 25
22 shared_memory->owner_process = owner_process; 26 shared_memory->owner_process = owner_process;
@@ -31,7 +35,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
31 MemoryRegionInfo* memory_region = GetMemoryRegion(region); 35 MemoryRegionInfo* memory_region = GetMemoryRegion(region);
32 auto& linheap_memory = memory_region->linear_heap_memory; 36 auto& linheap_memory = memory_region->linear_heap_memory;
33 37
34 ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, "Not enough space in region to allocate shared memory!"); 38 ASSERT_MSG(linheap_memory->size() + size <= memory_region->size,
39 "Not enough space in region to allocate shared memory!");
35 40
36 shared_memory->backing_block = linheap_memory; 41 shared_memory->backing_block = linheap_memory;
37 shared_memory->backing_block_offset = linheap_memory->size(); 42 shared_memory->backing_block_offset = linheap_memory->size();
@@ -39,7 +44,8 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
39 linheap_memory->insert(linheap_memory->end(), size, 0); 44 linheap_memory->insert(linheap_memory->end(), size, 0);
40 memory_region->used += size; 45 memory_region->used += size;
41 46
42 shared_memory->linear_heap_phys_address = Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset; 47 shared_memory->linear_heap_phys_address =
48 Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset;
43 49
44 // Increase the amount of used linear heap memory for the owner process. 50 // Increase the amount of used linear heap memory for the owner process.
45 if (shared_memory->owner_process != nullptr) { 51 if (shared_memory->owner_process != nullptr) {
@@ -51,18 +57,20 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
51 Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get()); 57 Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
52 } 58 }
53 } else { 59 } else {
54 // TODO(Subv): What happens if an application tries to create multiple memory blocks pointing to the same address? 60 // TODO(Subv): What happens if an application tries to create multiple memory blocks
61 // pointing to the same address?
55 auto& vm_manager = shared_memory->owner_process->vm_manager; 62 auto& vm_manager = shared_memory->owner_process->vm_manager;
56 // The memory is already available and mapped in the owner process. 63 // The memory is already available and mapped in the owner process.
57 auto vma = vm_manager.FindVMA(address)->second; 64 auto vma = vm_manager.FindVMA(address)->second;
58 // Copy it over to our own storage 65 // Copy it over to our own storage
59 shared_memory->backing_block = std::make_shared<std::vector<u8>>(vma.backing_block->data() + vma.offset, 66 shared_memory->backing_block = std::make_shared<std::vector<u8>>(
60 vma.backing_block->data() + vma.offset + size); 67 vma.backing_block->data() + vma.offset, vma.backing_block->data() + vma.offset + size);
61 shared_memory->backing_block_offset = 0; 68 shared_memory->backing_block_offset = 0;
62 // Unmap the existing pages 69 // Unmap the existing pages
63 vm_manager.UnmapRange(address, size); 70 vm_manager.UnmapRange(address, size);
64 // Map our own block into the address space 71 // Map our own block into the address space
65 vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size, MemoryState::Shared); 72 vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size,
73 MemoryState::Shared);
66 // Reprotect the block with the new permissions 74 // Reprotect the block with the new permissions
67 vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions)); 75 vm_manager.ReprotectRange(address, size, ConvertPermissions(permissions));
68 } 76 }
@@ -71,8 +79,11 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
71 return shared_memory; 79 return shared_memory;
72} 80}
73 81
74SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, 82SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
75 MemoryPermission permissions, MemoryPermission other_permissions, std::string name) { 83 u32 offset, u32 size,
84 MemoryPermission permissions,
85 MemoryPermission other_permissions,
86 std::string name) {
76 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 87 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
77 88
78 shared_memory->owner_process = nullptr; 89 shared_memory->owner_process = nullptr;
@@ -88,27 +99,31 @@ SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vecto
88} 99}
89 100
90ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions, 101ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions,
91 MemoryPermission other_permissions) { 102 MemoryPermission other_permissions) {
92 103
93 MemoryPermission own_other_permissions = target_process == owner_process ? this->permissions : this->other_permissions; 104 MemoryPermission own_other_permissions =
105 target_process == owner_process ? this->permissions : this->other_permissions;
94 106
95 // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare 107 // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare
96 if (base_address == 0 && other_permissions != MemoryPermission::DontCare) { 108 if (base_address == 0 && other_permissions != MemoryPermission::DontCare) {
97 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 109 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
110 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
98 } 111 }
99 112
100 // Error out if the requested permissions don't match what the creator process allows. 113 // Error out if the requested permissions don't match what the creator process allows.
101 if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) { 114 if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) {
102 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", 115 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
103 GetObjectId(), address, name.c_str()); 116 GetObjectId(), address, name.c_str());
104 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 117 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
118 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
105 } 119 }
106 120
107 // Heap-backed memory blocks can not be mapped with other_permissions = DontCare 121 // Heap-backed memory blocks can not be mapped with other_permissions = DontCare
108 if (base_address != 0 && other_permissions == MemoryPermission::DontCare) { 122 if (base_address != 0 && other_permissions == MemoryPermission::DontCare) {
109 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", 123 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
110 GetObjectId(), address, name.c_str()); 124 GetObjectId(), address, name.c_str());
111 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 125 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
126 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
112 } 127 }
113 128
114 // Error out if the provided permissions are not compatible with what the creator process needs. 129 // Error out if the provided permissions are not compatible with what the creator process needs.
@@ -116,12 +131,14 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
116 static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) { 131 static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) {
117 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", 132 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match",
118 GetObjectId(), address, name.c_str()); 133 GetObjectId(), address, name.c_str());
119 return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); 134 return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS,
135 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
120 } 136 }
121 137
122 // TODO(Subv): Check for the Shared Device Mem flag in the creator process. 138 // TODO(Subv): Check for the Shared Device Mem flag in the creator process.
123 /*if (was_created_with_shared_device_mem && address != 0) { 139 /*if (was_created_with_shared_device_mem && address != 0) {
124 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 140 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
141 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
125 }*/ 142 }*/
126 143
127 // TODO(Subv): The same process that created a SharedMemory object 144 // TODO(Subv): The same process that created a SharedMemory object
@@ -144,23 +161,29 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
144 } 161 }
145 162
146 // Map the memory block into the target process 163 // Map the memory block into the target process
147 auto result = target_process->vm_manager.MapMemoryBlock(target_address, backing_block, backing_block_offset, size, MemoryState::Shared); 164 auto result = target_process->vm_manager.MapMemoryBlock(
165 target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
148 if (result.Failed()) { 166 if (result.Failed()) {
149 LOG_ERROR(Kernel, "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory", 167 LOG_ERROR(
150 GetObjectId(), target_address, name.c_str()); 168 Kernel,
169 "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory",
170 GetObjectId(), target_address, name.c_str());
151 return result.Code(); 171 return result.Code();
152 } 172 }
153 173
154 return target_process->vm_manager.ReprotectRange(target_address, size, ConvertPermissions(permissions)); 174 return target_process->vm_manager.ReprotectRange(target_address, size,
175 ConvertPermissions(permissions));
155} 176}
156 177
157ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) { 178ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) {
158 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not mapped to a SharedMemory. 179 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not
180 // mapped to a SharedMemory.
159 return target_process->vm_manager.UnmapRange(address, size); 181 return target_process->vm_manager.UnmapRange(address, size);
160} 182}
161 183
162VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) { 184VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
163 u32 masked_permissions = static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute); 185 u32 masked_permissions =
186 static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute);
164 return static_cast<VMAPermission>(masked_permissions); 187 return static_cast<VMAPermission>(masked_permissions);
165}; 188};
166 189
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 0c404a9f8..afb142380 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -16,15 +16,15 @@ namespace Kernel {
16 16
17/// Permissions for mapped shared memory blocks 17/// Permissions for mapped shared memory blocks
18enum class MemoryPermission : u32 { 18enum class MemoryPermission : u32 {
19 None = 0, 19 None = 0,
20 Read = (1u << 0), 20 Read = (1u << 0),
21 Write = (1u << 1), 21 Write = (1u << 1),
22 ReadWrite = (Read | Write), 22 ReadWrite = (Read | Write),
23 Execute = (1u << 2), 23 Execute = (1u << 2),
24 ReadExecute = (Read | Execute), 24 ReadExecute = (Read | Execute),
25 WriteExecute = (Write | Execute), 25 WriteExecute = (Write | Execute),
26 ReadWriteExecute = (Read | Write | Execute), 26 ReadWriteExecute = (Read | Write | Execute),
27 DontCare = (1u << 28) 27 DontCare = (1u << 28)
28}; 28};
29 29
30class SharedMemory final : public Object { 30class SharedMemory final : public Object {
@@ -34,13 +34,18 @@ public:
34 * @param owner_process Process that created this shared memory object. 34 * @param owner_process Process that created this shared memory object.
35 * @param size Size of the memory block. Must be page-aligned. 35 * @param size Size of the memory block. Must be page-aligned.
36 * @param permissions Permission restrictions applied to the process which created the block. 36 * @param permissions Permission restrictions applied to the process which created the block.
37 * @param other_permissions Permission restrictions applied to other processes mapping the block. 37 * @param other_permissions Permission restrictions applied to other processes mapping the
38 * block.
38 * @param address The address from which to map the Shared Memory. 39 * @param address The address from which to map the Shared Memory.
39 * @param region If the address is 0, the shared memory will be allocated in this region of the linear heap. 40 * @param region If the address is 0, the shared memory will be allocated in this region of the
41 * linear heap.
40 * @param name Optional object name, used for debugging purposes. 42 * @param name Optional object name, used for debugging purposes.
41 */ 43 */
42 static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, 44 static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size,
43 MemoryPermission other_permissions, VAddr address = 0, MemoryRegion region = MemoryRegion::BASE, std::string name = "Unknown"); 45 MemoryPermission permissions,
46 MemoryPermission other_permissions, VAddr address = 0,
47 MemoryRegion region = MemoryRegion::BASE,
48 std::string name = "Unknown");
44 49
45 /** 50 /**
46 * Creates a shared memory object from a block of memory managed by an HLE applet. 51 * Creates a shared memory object from a block of memory managed by an HLE applet.
@@ -48,17 +53,27 @@ public:
48 * @param offset The offset into the heap block that the SharedMemory will map. 53 * @param offset The offset into the heap block that the SharedMemory will map.
49 * @param size Size of the memory block. Must be page-aligned. 54 * @param size Size of the memory block. Must be page-aligned.
50 * @param permissions Permission restrictions applied to the process which created the block. 55 * @param permissions Permission restrictions applied to the process which created the block.
51 * @param other_permissions Permission restrictions applied to other processes mapping the block. 56 * @param other_permissions Permission restrictions applied to other processes mapping the
57 * block.
52 * @param name Optional object name, used for debugging purposes. 58 * @param name Optional object name, used for debugging purposes.
53 */ 59 */
54 static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, 60 static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
55 MemoryPermission permissions, MemoryPermission other_permissions, std::string name = "Unknown Applet"); 61 u32 offset, u32 size,
56 62 MemoryPermission permissions,
57 std::string GetTypeName() const override { return "SharedMemory"; } 63 MemoryPermission other_permissions,
58 std::string GetName() const override { return name; } 64 std::string name = "Unknown Applet");
65
66 std::string GetTypeName() const override {
67 return "SharedMemory";
68 }
69 std::string GetName() const override {
70 return name;
71 }
59 72
60 static const HandleType HANDLE_TYPE = HandleType::SharedMemory; 73 static const HandleType HANDLE_TYPE = HandleType::SharedMemory;
61 HandleType GetHandleType() const override { return HANDLE_TYPE; } 74 HandleType GetHandleType() const override {
75 return HANDLE_TYPE;
76 }
62 77
63 /** 78 /**
64 * Converts the specified MemoryPermission into the equivalent VMAPermission. 79 * Converts the specified MemoryPermission into the equivalent VMAPermission.
@@ -73,7 +88,8 @@ public:
73 * @param permissions Memory block map permissions (specified by SVC field) 88 * @param permissions Memory block map permissions (specified by SVC field)
74 * @param other_permissions Memory block map other permissions (specified by SVC field) 89 * @param other_permissions Memory block map other permissions (specified by SVC field)
75 */ 90 */
76 ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions, MemoryPermission other_permissions); 91 ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions,
92 MemoryPermission other_permissions);
77 93
78 /** 94 /**
79 * Unmaps a shared memory block from the specified address in system memory 95 * Unmaps a shared memory block from the specified address in system memory
@@ -94,7 +110,8 @@ public:
94 SharedPtr<Process> owner_process; 110 SharedPtr<Process> owner_process;
95 /// Address of shared memory block in the owner process if specified. 111 /// Address of shared memory block in the owner process if specified.
96 VAddr base_address; 112 VAddr base_address;
97 /// Physical address of the shared memory block in the linear heap if no address was specified during creation. 113 /// Physical address of the shared memory block in the linear heap if no address was specified
114 /// during creation.
98 PAddr linear_heap_phys_address; 115 PAddr linear_heap_phys_address;
99 /// Backing memory for this shared memory block. 116 /// Backing memory for this shared memory block.
100 std::shared_ptr<std::vector<u8>> backing_block; 117 std::shared_ptr<std::vector<u8>> backing_block;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index f1e5cf3cb..59272715f 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -18,10 +18,10 @@
18#include "core/core_timing.h" 18#include "core/core_timing.h"
19#include "core/hle/hle.h" 19#include "core/hle/hle.h"
20#include "core/hle/kernel/kernel.h" 20#include "core/hle/kernel/kernel.h"
21#include "core/hle/kernel/process.h"
22#include "core/hle/kernel/thread.h"
23#include "core/hle/kernel/memory.h" 21#include "core/hle/kernel/memory.h"
24#include "core/hle/kernel/mutex.h" 22#include "core/hle/kernel/mutex.h"
23#include "core/hle/kernel/process.h"
24#include "core/hle/kernel/thread.h"
25#include "core/hle/result.h" 25#include "core/hle/result.h"
26#include "core/memory.h" 26#include "core/memory.h"
27 27
@@ -46,7 +46,7 @@ static Kernel::HandleTable wakeup_callback_handle_table;
46static std::vector<SharedPtr<Thread>> thread_list; 46static std::vector<SharedPtr<Thread>> thread_list;
47 47
48// Lists only ready thread ids. 48// Lists only ready thread ids.
49static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> ready_queue; 49static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST + 1> ready_queue;
50 50
51static Thread* current_thread; 51static Thread* current_thread;
52 52
@@ -61,8 +61,10 @@ inline static u32 const NewThreadId() {
61 return next_thread_id++; 61 return next_thread_id++;
62} 62}
63 63
64Thread::Thread() {} 64Thread::Thread() {
65Thread::~Thread() {} 65}
66Thread::~Thread() {
67}
66 68
67Thread* GetCurrentThread() { 69Thread* GetCurrentThread() {
68 return current_thread; 70 return current_thread;
@@ -103,7 +105,7 @@ void Thread::Stop() {
103 105
104 // Clean up thread from ready queue 106 // Clean up thread from ready queue
105 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) 107 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
106 if (status == THREADSTATUS_READY){ 108 if (status == THREADSTATUS_READY) {
107 ready_queue.remove(current_priority, this); 109 ready_queue.remove(current_priority, this);
108 } 110 }
109 111
@@ -119,7 +121,8 @@ void Thread::Stop() {
119 121
120 // Mark the TLS slot in the thread's page as free. 122 // Mark the TLS slot in the thread's page as free.
121 u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; 123 u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
122 u32 tls_slot = ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; 124 u32 tls_slot =
125 ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE;
123 Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot); 126 Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot);
124 127
125 HLE::Reschedule(__func__); 128 HLE::Reschedule(__func__);
@@ -137,7 +140,7 @@ Thread* ArbitrateHighestPriorityThread(u32 address) {
137 if (thread == nullptr) 140 if (thread == nullptr)
138 continue; 141 continue;
139 142
140 if(thread->current_priority <= priority) { 143 if (thread->current_priority <= priority) {
141 highest_priority_thread = thread.get(); 144 highest_priority_thread = thread.get();
142 priority = thread->current_priority; 145 priority = thread->current_priority;
143 } 146 }
@@ -170,7 +173,7 @@ static void PriorityBoostStarvedThreads() {
170 // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler 173 // on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler
171 // should probably be reversed to verify this. 174 // should probably be reversed to verify this.
172 175
173 const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long 176 const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long
174 177
175 u64 delta = current_ticks - thread->last_running_ticks; 178 u64 delta = current_ticks - thread->last_running_ticks;
176 179
@@ -193,10 +196,12 @@ static std::tuple<u32*, u32*> GetWaitSynchTimeoutParameterRegister(Thread* threa
193 196
194 if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) { 197 if ((thumb_mode && thumb_inst == 0xDF24) || (!thumb_mode && inst == 0x0F000024)) {
195 // svc #0x24 (WaitSynchronization1) 198 // svc #0x24 (WaitSynchronization1)
196 return std::make_tuple(&thread->context.cpu_registers[2], &thread->context.cpu_registers[3]); 199 return std::make_tuple(&thread->context.cpu_registers[2],
200 &thread->context.cpu_registers[3]);
197 } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) { 201 } else if ((thumb_mode && thumb_inst == 0xDF25) || (!thumb_mode && inst == 0x0F000025)) {
198 // svc #0x25 (WaitSynchronizationN) 202 // svc #0x25 (WaitSynchronizationN)
199 return std::make_tuple(&thread->context.cpu_registers[0], &thread->context.cpu_registers[4]); 203 return std::make_tuple(&thread->context.cpu_registers[0],
204 &thread->context.cpu_registers[4]);
200 } 205 }
201 206
202 UNREACHABLE(); 207 UNREACHABLE();
@@ -245,7 +250,8 @@ static void SwitchContext(Thread* new_thread) {
245 250
246 // Load context of new thread 251 // Load context of new thread
247 if (new_thread) { 252 if (new_thread) {
248 DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); 253 DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY,
254 "Thread must be ready to become running.");
249 255
250 // Cancel any outstanding wakeup events for this thread 256 // Cancel any outstanding wakeup events for this thread
251 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle); 257 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle);
@@ -263,7 +269,7 @@ static void SwitchContext(Thread* new_thread) {
263 new_thread->context.pc -= thumb_mode ? 2 : 4; 269 new_thread->context.pc -= thumb_mode ? 2 : 4;
264 270
265 // Get the register for timeout parameter 271 // Get the register for timeout parameter
266 u32* timeout_low, *timeout_high; 272 u32 *timeout_low, *timeout_high;
267 std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread); 273 std::tie(timeout_low, timeout_high) = GetWaitSynchTimeoutParameterRegister(new_thread);
268 274
269 // Update the timeout parameter 275 // Update the timeout parameter
@@ -307,7 +313,7 @@ static Thread* PopNextReadyThread() {
307 // Otherwise just keep going with the current thread 313 // Otherwise just keep going with the current thread
308 next = thread; 314 next = thread;
309 } 315 }
310 } else { 316 } else {
311 next = ready_queue.pop_first(); 317 next = ready_queue.pop_first();
312 } 318 }
313 319
@@ -321,7 +327,8 @@ void WaitCurrentThread_Sleep() {
321 HLE::Reschedule(__func__); 327 HLE::Reschedule(__func__);
322} 328}
323 329
324void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all) { 330void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects,
331 bool wait_set_output, bool wait_all) {
325 Thread* thread = GetCurrentThread(); 332 Thread* thread = GetCurrentThread();
326 thread->wait_set_output = wait_set_output; 333 thread->wait_set_output = wait_set_output;
327 thread->wait_all = wait_all; 334 thread->wait_all = wait_all;
@@ -352,7 +359,8 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
352 359
353 if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) { 360 if (thread->status == THREADSTATUS_WAIT_SYNCH || thread->status == THREADSTATUS_WAIT_ARB) {
354 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, 361 thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS,
355 ErrorSummary::StatusChanged, ErrorLevel::Info)); 362 ErrorSummary::StatusChanged,
363 ErrorLevel::Info));
356 364
357 if (thread->wait_set_output) 365 if (thread->wait_set_output)
358 thread->SetWaitSynchronizationOutput(-1); 366 thread->SetWaitSynchronizationOutput(-1);
@@ -372,25 +380,25 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
372 380
373void Thread::ResumeFromWait() { 381void Thread::ResumeFromWait() {
374 switch (status) { 382 switch (status) {
375 case THREADSTATUS_WAIT_SYNCH: 383 case THREADSTATUS_WAIT_SYNCH:
376 case THREADSTATUS_WAIT_ARB: 384 case THREADSTATUS_WAIT_ARB:
377 case THREADSTATUS_WAIT_SLEEP: 385 case THREADSTATUS_WAIT_SLEEP:
378 break; 386 break;
379 387
380 case THREADSTATUS_READY: 388 case THREADSTATUS_READY:
381 // If the thread is waiting on multiple wait objects, it might be awoken more than once 389 // If the thread is waiting on multiple wait objects, it might be awoken more than once
382 // before actually resuming. We can ignore subsequent wakeups if the thread status has 390 // before actually resuming. We can ignore subsequent wakeups if the thread status has
383 // already been set to THREADSTATUS_READY. 391 // already been set to THREADSTATUS_READY.
384 return; 392 return;
385 393
386 case THREADSTATUS_RUNNING: 394 case THREADSTATUS_RUNNING:
387 DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId()); 395 DEBUG_ASSERT_MSG(false, "Thread with object id %u has already resumed.", GetObjectId());
388 return; 396 return;
389 case THREADSTATUS_DEAD: 397 case THREADSTATUS_DEAD:
390 // This should never happen, as threads must complete before being stopped. 398 // This should never happen, as threads must complete before being stopped.
391 DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.", 399 DEBUG_ASSERT_MSG(false, "Thread with object id %u cannot be resumed because it's DEAD.",
392 GetObjectId()); 400 GetObjectId());
393 return; 401 return;
394 } 402 }
395 403
396 ready_queue.push_back(current_priority, this); 404 ready_queue.push_back(current_priority, this);
@@ -405,7 +413,8 @@ static void DebugThreadQueue() {
405 if (!thread) { 413 if (!thread) {
406 LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD"); 414 LOG_DEBUG(Kernel, "Current: NO CURRENT THREAD");
407 } else { 415 } else {
408 LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId()); 416 LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority,
417 GetCurrentThread()->GetObjectId());
409 } 418 }
410 419
411 for (auto& t : thread_list) { 420 for (auto& t : thread_list) {
@@ -448,7 +457,8 @@ std::tuple<u32, u32, bool> GetFreeThreadLocalSlot(std::vector<std::bitset<8>>& t
448 * @param entry_point Address of entry point for execution 457 * @param entry_point Address of entry point for execution
449 * @param arg User argument for thread 458 * @param arg User argument for thread
450 */ 459 */
451static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) { 460static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point,
461 u32 arg) {
452 memset(&context, 0, sizeof(Core::ThreadContext)); 462 memset(&context, 0, sizeof(Core::ThreadContext));
453 463
454 context.cpu_registers[0] = arg; 464 context.cpu_registers[0] = arg;
@@ -458,11 +468,11 @@ static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32
458} 468}
459 469
460ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, 470ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority,
461 u32 arg, s32 processor_id, VAddr stack_top) { 471 u32 arg, s32 processor_id, VAddr stack_top) {
462 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { 472 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
463 s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 473 s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
464 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 474 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", name.c_str(),
465 name.c_str(), priority, new_priority); 475 priority, new_priority);
466 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm 476 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
467 // validity of this 477 // validity of this
468 priority = new_priority; 478 priority = new_priority;
@@ -472,7 +482,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
472 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); 482 LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point);
473 // TODO: Verify error 483 // TODO: Verify error
474 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 484 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
475 ErrorSummary::InvalidArgument, ErrorLevel::Permanent); 485 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
476 } 486 }
477 487
478 SharedPtr<Thread> thread(new Thread); 488 SharedPtr<Thread> thread(new Thread);
@@ -511,8 +521,10 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
511 auto& linheap_memory = memory_region->linear_heap_memory; 521 auto& linheap_memory = memory_region->linear_heap_memory;
512 522
513 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { 523 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) {
514 LOG_ERROR(Kernel_SVC, "Not enough space in region to allocate a new TLS page for thread"); 524 LOG_ERROR(Kernel_SVC,
515 return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel, ErrorSummary::OutOfResource, ErrorLevel::Permanent); 525 "Not enough space in region to allocate a new TLS page for thread");
526 return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
527 ErrorSummary::OutOfResource, ErrorLevel::Permanent);
516 } 528 }
517 529
518 u32 offset = linheap_memory->size(); 530 u32 offset = linheap_memory->size();
@@ -537,7 +549,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
537 549
538 // Mark the slot as used 550 // Mark the slot as used
539 tls_slots[available_page].set(available_slot); 551 tls_slots[available_page].set(available_slot);
540 thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + available_slot * Memory::TLS_ENTRY_SIZE; 552 thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE +
553 available_slot * Memory::TLS_ENTRY_SIZE;
541 554
542 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used 555 // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
543 // to initialize the context 556 // to initialize the context
@@ -551,10 +564,12 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
551 return MakeResult<SharedPtr<Thread>>(std::move(thread)); 564 return MakeResult<SharedPtr<Thread>>(std::move(thread));
552} 565}
553 566
554// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be returned. 567// TODO(peachum): Remove this. Range checking should be done, and an appropriate error should be
568// returned.
555static void ClampPriority(const Thread* thread, s32* priority) { 569static void ClampPriority(const Thread* thread, s32* priority) {
556 if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) { 570 if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) {
557 DEBUG_ASSERT_MSG(false, "Application passed an out of range priority. An error should be returned."); 571 DEBUG_ASSERT_MSG(
572 false, "Application passed an out of range priority. An error should be returned.");
558 573
559 s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 574 s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
560 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", 575 LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d",
@@ -586,12 +601,13 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
586 DEBUG_ASSERT(!GetCurrentThread()); 601 DEBUG_ASSERT(!GetCurrentThread());
587 602
588 // Initialize new "main" thread 603 // Initialize new "main" thread
589 auto thread_res = Thread::Create("main", entry_point, priority, 0, 604 auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0,
590 THREADPROCESSORID_0, Memory::HEAP_VADDR_END); 605 Memory::HEAP_VADDR_END);
591 606
592 SharedPtr<Thread> thread = thread_res.MoveFrom(); 607 SharedPtr<Thread> thread = thread_res.MoveFrom();
593 608
594 thread->context.fpscr = FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010 609 thread->context.fpscr =
610 FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO | FPSCR_ROUND_TOZERO | FPSCR_IXC; // 0x03C00010
595 611
596 // Run new "main" thread 612 // Run new "main" thread
597 SwitchContext(thread.get()); 613 SwitchContext(thread.get());
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index deab5d5a6..2ed5cf74e 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -17,29 +17,29 @@
17#include "core/hle/kernel/kernel.h" 17#include "core/hle/kernel/kernel.h"
18#include "core/hle/result.h" 18#include "core/hle/result.h"
19 19
20enum ThreadPriority : s32{ 20enum ThreadPriority : s32 {
21 THREADPRIO_HIGHEST = 0, ///< Highest thread priority 21 THREADPRIO_HIGHEST = 0, ///< Highest thread priority
22 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps 22 THREADPRIO_USERLAND_MAX = 24, ///< Highest thread priority for userland apps
23 THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps 23 THREADPRIO_DEFAULT = 48, ///< Default thread priority for userland apps
24 THREADPRIO_LOWEST = 63, ///< Lowest thread priority 24 THREADPRIO_LOWEST = 63, ///< Lowest thread priority
25}; 25};
26 26
27enum ThreadProcessorId : s32 { 27enum ThreadProcessorId : s32 {
28 THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader 28 THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader
29 THREADPROCESSORID_ALL = -1, ///< Run thread on either core 29 THREADPROCESSORID_ALL = -1, ///< Run thread on either core
30 THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore) 30 THREADPROCESSORID_0 = 0, ///< Run thread on core 0 (AppCore)
31 THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore) 31 THREADPROCESSORID_1 = 1, ///< Run thread on core 1 (SysCore)
32 THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this 32 THREADPROCESSORID_MAX = 2, ///< Processor ID must be less than this
33}; 33};
34 34
35enum ThreadStatus { 35enum ThreadStatus {
36 THREADSTATUS_RUNNING, ///< Currently running 36 THREADSTATUS_RUNNING, ///< Currently running
37 THREADSTATUS_READY, ///< Ready to run 37 THREADSTATUS_READY, ///< Ready to run
38 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter 38 THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter
39 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC 39 THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC
40 THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC 40 THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC
41 THREADSTATUS_DORMANT, ///< Created but not yet made ready 41 THREADSTATUS_DORMANT, ///< Created but not yet made ready
42 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated 42 THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated
43}; 43};
44 44
45namespace Kernel { 45namespace Kernel {
@@ -60,13 +60,19 @@ public:
60 * @return A shared pointer to the newly created thread 60 * @return A shared pointer to the newly created thread
61 */ 61 */
62 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, 62 static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
63 u32 arg, s32 processor_id, VAddr stack_top); 63 u32 arg, s32 processor_id, VAddr stack_top);
64 64
65 std::string GetName() const override { return name; } 65 std::string GetName() const override {
66 std::string GetTypeName() const override { return "Thread"; } 66 return name;
67 }
68 std::string GetTypeName() const override {
69 return "Thread";
70 }
67 71
68 static const HandleType HANDLE_TYPE = HandleType::Thread; 72 static const HandleType HANDLE_TYPE = HandleType::Thread;
69 HandleType GetHandleType() const override { return HANDLE_TYPE; } 73 HandleType GetHandleType() const override {
74 return HANDLE_TYPE;
75 }
70 76
71 bool ShouldWait() override; 77 bool ShouldWait() override;
72 void Acquire() override; 78 void Acquire() override;
@@ -75,7 +81,9 @@ public:
75 * Gets the thread's current priority 81 * Gets the thread's current priority
76 * @return The current thread's priority 82 * @return The current thread's priority
77 */ 83 */
78 s32 GetPriority() const { return current_priority; } 84 s32 GetPriority() const {
85 return current_priority;
86 }
79 87
80 /** 88 /**
81 * Sets the thread's current priority 89 * Sets the thread's current priority
@@ -93,7 +101,9 @@ public:
93 * Gets the thread's thread ID 101 * Gets the thread's thread ID
94 * @return The thread's ID 102 * @return The thread's ID
95 */ 103 */
96 u32 GetThreadId() const { return thread_id; } 104 u32 GetThreadId() const {
105 return thread_id;
106 }
97 107
98 /** 108 /**
99 * Resumes a thread from waiting 109 * Resumes a thread from waiting
@@ -127,7 +137,9 @@ public:
127 * Returns the Thread Local Storage address of the current thread 137 * Returns the Thread Local Storage address of the current thread
128 * @returns VAddr of the thread's TLS 138 * @returns VAddr of the thread's TLS
129 */ 139 */
130 VAddr GetTLSAddress() const { return tls_address; } 140 VAddr GetTLSAddress() const {
141 return tls_address;
142 }
131 143
132 Core::ThreadContext context; 144 Core::ThreadContext context;
133 145
@@ -137,8 +149,8 @@ public:
137 u32 entry_point; 149 u32 entry_point;
138 u32 stack_top; 150 u32 stack_top;
139 151
140 s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application 152 s32 nominal_priority; ///< Nominal thread priority, as set by the emulated application
141 s32 current_priority; ///< Current thread priority, can be temporarily changed 153 s32 current_priority; ///< Current thread priority, can be temporarily changed
142 154
143 u64 last_running_ticks; ///< CPU tick when thread was last running 155 u64 last_running_ticks; ///< CPU tick when thread was last running
144 156
@@ -151,11 +163,11 @@ public:
151 /// Mutexes currently held by this thread, which will be released when it exits. 163 /// Mutexes currently held by this thread, which will be released when it exits.
152 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes; 164 boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;
153 165
154 SharedPtr<Process> owner_process; ///< Process that owns this thread 166 SharedPtr<Process> owner_process; ///< Process that owns this thread
155 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on 167 std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on
156 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address 168 VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address
157 bool wait_all; ///< True if the thread is waiting on all objects before resuming 169 bool wait_all; ///< True if the thread is waiting on all objects before resuming
158 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup 170 bool wait_set_output; ///< True if the output parameter should be set on thread wakeup
159 171
160 std::string name; 172 std::string name;
161 173
@@ -205,10 +217,12 @@ void WaitCurrentThread_Sleep();
205/** 217/**
206 * Waits the current thread from a WaitSynchronization call 218 * Waits the current thread from a WaitSynchronization call
207 * @param wait_objects Kernel objects that we are waiting on 219 * @param wait_objects Kernel objects that we are waiting on
208 * @param wait_set_output If true, set the output parameter on thread wakeup (for WaitSynchronizationN only) 220 * @param wait_set_output If true, set the output parameter on thread wakeup (for
221 * WaitSynchronizationN only)
209 * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only) 222 * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only)
210 */ 223 */
211void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all); 224void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects,
225 bool wait_set_output, bool wait_all);
212 226
213/** 227/**
214 * Waits the current thread from an ArbitrateAddress call 228 * Waits the current thread from an ArbitrateAddress call
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index b8daaeede..255cb1aca 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -9,8 +9,8 @@
9 9
10#include "core/core_timing.h" 10#include "core/core_timing.h"
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/timer.h"
13#include "core/hle/kernel/thread.h" 12#include "core/hle/kernel/thread.h"
13#include "core/hle/kernel/timer.h"
14 14
15namespace Kernel { 15namespace Kernel {
16 16
@@ -20,8 +20,10 @@ static int timer_callback_event_type;
20// us to simply use a pool index or similar. 20// us to simply use a pool index or similar.
21static Kernel::HandleTable timer_callback_handle_table; 21static Kernel::HandleTable timer_callback_handle_table;
22 22
23Timer::Timer() {} 23Timer::Timer() {
24Timer::~Timer() {} 24}
25Timer::~Timer() {
26}
25 27
26SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) { 28SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
27 SharedPtr<Timer> timer(new Timer); 29 SharedPtr<Timer> timer(new Timer);
@@ -41,7 +43,7 @@ bool Timer::ShouldWait() {
41} 43}
42 44
43void Timer::Acquire() { 45void Timer::Acquire() {
44 ASSERT_MSG( !ShouldWait(), "object unavailable!"); 46 ASSERT_MSG(!ShouldWait(), "object unavailable!");
45 47
46 if (reset_type == ResetType::OneShot) 48 if (reset_type == ResetType::OneShot)
47 signaled = false; 49 signaled = false;
@@ -55,8 +57,8 @@ void Timer::Set(s64 initial, s64 interval) {
55 interval_delay = interval; 57 interval_delay = interval;
56 58
57 u64 initial_microseconds = initial / 1000; 59 u64 initial_microseconds = initial / 1000;
58 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), 60 CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
59 timer_callback_event_type, callback_handle); 61 callback_handle);
60 62
61 HLE::Reschedule(__func__); 63 HLE::Reschedule(__func__);
62} 64}
@@ -73,7 +75,8 @@ void Timer::Clear() {
73 75
74/// The timer callback event, called when a timer is fired 76/// The timer callback event, called when a timer is fired
75static void TimerCallback(u64 timer_handle, int cycles_late) { 77static void TimerCallback(u64 timer_handle, int cycles_late) {
76 SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); 78 SharedPtr<Timer> timer =
79 timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle));
77 80
78 if (timer == nullptr) { 81 if (timer == nullptr) {
79 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle); 82 LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08" PRIx64, timer_handle);
@@ -91,7 +94,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
91 // Reschedule the timer with the interval delay 94 // Reschedule the timer with the interval delay
92 u64 interval_microseconds = timer->interval_delay / 1000; 95 u64 interval_microseconds = timer->interval_delay / 1000;
93 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late, 96 CoreTiming::ScheduleEvent(usToCycles(interval_microseconds) - cycles_late,
94 timer_callback_event_type, timer_handle); 97 timer_callback_event_type, timer_handle);
95 } 98 }
96} 99}
97 100
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index b1db60e8f..97cd0d63c 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -21,19 +21,25 @@ public:
21 */ 21 */
22 static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown"); 22 static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown");
23 23
24 std::string GetTypeName() const override { return "Timer"; } 24 std::string GetTypeName() const override {
25 std::string GetName() const override { return name; } 25 return "Timer";
26 }
27 std::string GetName() const override {
28 return name;
29 }
26 30
27 static const HandleType HANDLE_TYPE = HandleType::Timer; 31 static const HandleType HANDLE_TYPE = HandleType::Timer;
28 HandleType GetHandleType() const override { return HANDLE_TYPE; } 32 HandleType GetHandleType() const override {
33 return HANDLE_TYPE;
34 }
29 35
30 ResetType reset_type; ///< The ResetType of this timer 36 ResetType reset_type; ///< The ResetType of this timer
31 37
32 bool signaled; ///< Whether the timer has been signaled or not 38 bool signaled; ///< Whether the timer has been signaled or not
33 std::string name; ///< Name of timer (optional) 39 std::string name; ///< Name of timer (optional)
34 40
35 u64 initial_delay; ///< The delay until the timer fires for the first time 41 u64 initial_delay; ///< The delay until the timer fires for the first time
36 u64 interval_delay; ///< The delay until the timer fires after the first time 42 u64 interval_delay; ///< The delay until the timer fires after the first time
37 43
38 bool ShouldWait() override; 44 bool ShouldWait() override;
39 void Acquire() override; 45 void Acquire() override;
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 066146cff..4ad86cf48 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -15,8 +15,8 @@ namespace Kernel {
15 15
16static const char* GetMemoryStateName(MemoryState state) { 16static const char* GetMemoryStateName(MemoryState state) {
17 static const char* names[] = { 17 static const char* names[] = {
18 "Free", "Reserved", "IO", "Static", "Code", "Private", "Shared", "Continuous", "Aliased", 18 "Free", "Reserved", "IO", "Static", "Code", "Private",
19 "Alias", "AliasCode", "Locked", 19 "Shared", "Continuous", "Aliased", "Alias", "AliasCode", "Locked",
20 }; 20 };
21 21
22 return names[(int)state]; 22 return names[(int)state];
@@ -24,13 +24,12 @@ static const char* GetMemoryStateName(MemoryState state) {
24 24
25bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { 25bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
26 ASSERT(base + size == next.base); 26 ASSERT(base + size == next.base);
27 if (permissions != next.permissions || 27 if (permissions != next.permissions || meminfo_state != next.meminfo_state ||
28 meminfo_state != next.meminfo_state || 28 type != next.type) {
29 type != next.type) {
30 return false; 29 return false;
31 } 30 }
32 if (type == VMAType::AllocatedMemoryBlock && 31 if (type == VMAType::AllocatedMemoryBlock &&
33 (backing_block != next.backing_block || offset + size != next.offset)) { 32 (backing_block != next.backing_block || offset + size != next.offset)) {
34 return false; 33 return false;
35 } 34 }
36 if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) { 35 if (type == VMAType::BackingMemory && backing_memory + size != next.backing_memory) {
@@ -70,7 +69,9 @@ VMManager::VMAHandle VMManager::FindVMA(VAddr target) const {
70} 69}
71 70
72ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, 71ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
73 std::shared_ptr<std::vector<u8>> block, size_t offset, u32 size, MemoryState state) { 72 std::shared_ptr<std::vector<u8>> block,
73 size_t offset, u32 size,
74 MemoryState state) {
74 ASSERT(block != nullptr); 75 ASSERT(block != nullptr);
75 ASSERT(offset + size <= block->size()); 76 ASSERT(offset + size <= block->size());
76 77
@@ -89,7 +90,8 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
89 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); 90 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
90} 91}
91 92
92ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * memory, u32 size, MemoryState state) { 93ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* memory, u32 size,
94 MemoryState state) {
93 ASSERT(memory != nullptr); 95 ASSERT(memory != nullptr);
94 96
95 // This is the appropriately sized VMA that will turn into our allocation. 97 // This is the appropriately sized VMA that will turn into our allocation.
@@ -106,7 +108,9 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * m
106 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); 108 return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
107} 109}
108 110
109ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler) { 111ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size,
112 MemoryState state,
113 Memory::MMIORegionPointer mmio_handler) {
110 // This is the appropriately sized VMA that will turn into our allocation. 114 // This is the appropriately sized VMA that will turn into our allocation.
111 CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size)); 115 CASCADE_RESULT(VMAIter vma_handle, CarveVMA(target, size));
112 VirtualMemoryArea& final_vma = vma_handle->second; 116 VirtualMemoryArea& final_vma = vma_handle->second;
@@ -191,15 +195,16 @@ void VMManager::RefreshMemoryBlockMappings(const std::vector<u8>* block) {
191void VMManager::LogLayout(Log::Level log_level) const { 195void VMManager::LogLayout(Log::Level log_level) const {
192 for (const auto& p : vma_map) { 196 for (const auto& p : vma_map) {
193 const VirtualMemoryArea& vma = p.second; 197 const VirtualMemoryArea& vma = p.second;
194 LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", 198 LOG_GENERIC(Log::Class::Kernel, log_level, "%08X - %08X size: %8X %c%c%c %s", vma.base,
195 vma.base, vma.base + vma.size, vma.size, 199 vma.base + vma.size, vma.size,
196 (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-', 200 (u8)vma.permissions & (u8)VMAPermission::Read ? 'R' : '-',
197 (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-', 201 (u8)vma.permissions & (u8)VMAPermission::Write ? 'W' : '-',
198 (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-', GetMemoryStateName(vma.meminfo_state)); 202 (u8)vma.permissions & (u8)VMAPermission::Execute ? 'X' : '-',
203 GetMemoryStateName(vma.meminfo_state));
199 } 204 }
200} 205}
201 206
202VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { 207VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle& iter) {
203 // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given 208 // This uses a neat C++ trick to convert a const_iterator to a regular iterator, given
204 // non-const access to its container. 209 // non-const access to its container.
205 return vma_map.erase(iter, iter); // Erases an empty range of elements 210 return vma_map.erase(iter, iter); // Erases an empty range of elements
@@ -337,5 +342,4 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
337 break; 342 break;
338 } 343 }
339} 344}
340
341} 345}
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 91d40655b..fbcd9870f 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -15,13 +15,13 @@
15 15
16namespace Kernel { 16namespace Kernel {
17 17
18const ResultCode ERR_INVALID_ADDRESS{ // 0xE0E01BF5 18const ResultCode ERR_INVALID_ADDRESS{// 0xE0E01BF5
19 ErrorDescription::InvalidAddress, ErrorModule::OS, 19 ErrorDescription::InvalidAddress, ErrorModule::OS,
20 ErrorSummary::InvalidArgument, ErrorLevel::Usage}; 20 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
21 21
22const ResultCode ERR_INVALID_ADDRESS_STATE{ // 0xE0A01BF5 22const ResultCode ERR_INVALID_ADDRESS_STATE{// 0xE0A01BF5
23 ErrorDescription::InvalidAddress, ErrorModule::OS, 23 ErrorDescription::InvalidAddress, ErrorModule::OS,
24 ErrorSummary::InvalidState, ErrorLevel::Usage}; 24 ErrorSummary::InvalidState, ErrorLevel::Usage};
25 25
26enum class VMAType : u8 { 26enum class VMAType : u8 {
27 /// VMA represents an unmapped region of the address space. 27 /// VMA represents an unmapped region of the address space.
@@ -115,7 +115,8 @@ class VMManager final {
115 // TODO(yuriks): Make page tables switchable to support multiple VMManagers 115 // TODO(yuriks): Make page tables switchable to support multiple VMManagers
116public: 116public:
117 /** 117 /**
118 * The maximum amount of address space managed by the kernel. Addresses above this are never used. 118 * The maximum amount of address space managed by the kernel. Addresses above this are never
119 * used.
119 * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000. 120 * @note This is the limit used by the New 3DS kernel. Old 3DS used 0x20000000.
120 */ 121 */
121 static const u32 MAX_ADDRESS = 0x40000000; 122 static const u32 MAX_ADDRESS = 0x40000000;
@@ -151,7 +152,7 @@ public:
151 * @param state MemoryState tag to attach to the VMA. 152 * @param state MemoryState tag to attach to the VMA.
152 */ 153 */
153 ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block, 154 ResultVal<VMAHandle> MapMemoryBlock(VAddr target, std::shared_ptr<std::vector<u8>> block,
154 size_t offset, u32 size, MemoryState state); 155 size_t offset, u32 size, MemoryState state);
155 156
156 /** 157 /**
157 * Maps an unmanaged host memory pointer at a given address. 158 * Maps an unmanaged host memory pointer at a given address.
@@ -172,7 +173,8 @@ public:
172 * @param state MemoryState tag to attach to the VMA. 173 * @param state MemoryState tag to attach to the VMA.
173 * @param mmio_handler The handler that will implement read and write for this MMIO region. 174 * @param mmio_handler The handler that will implement read and write for this MMIO region.
174 */ 175 */
175 ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler); 176 ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state,
177 Memory::MMIORegionPointer mmio_handler);
176 178
177 /// Unmaps a range of addresses, splitting VMAs as necessary. 179 /// Unmaps a range of addresses, splitting VMAs as necessary.
178 ResultCode UnmapRange(VAddr target, u32 size); 180 ResultCode UnmapRange(VAddr target, u32 size);
@@ -228,5 +230,4 @@ private:
228 /// Updates the pages corresponding to this VMA so they match the VMA's attributes. 230 /// Updates the pages corresponding to this VMA so they match the VMA's attributes.
229 void UpdatePageTableForVMA(const VirtualMemoryArea& vma); 231 void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
230}; 232};
231
232} 233}