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