diff options
| author | 2016-09-21 11:29:48 -0700 | |
|---|---|---|
| committer | 2016-09-21 11:29:48 -0700 | |
| commit | d5d2ca8058a0f1c00ab7ca9fe2c058ba47546c0a (patch) | |
| tree | 8a22ca73ff838f3f0090b29a548ae81087fc90ed /src/core/hle/kernel | |
| parent | README: Specify master branch for Travis CI badge (diff) | |
| parent | Fix Travis clang-format check (diff) | |
| download | yuzu-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')
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 | ||
| 30 | ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, | 28 | ResultCode 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 | ||
| 13 | namespace Kernel { | 11 | namespace Kernel { |
| @@ -17,16 +15,22 @@ class ServerPort; | |||
| 17 | class ClientPort : public Object { | 15 | class ClientPort : public Object { |
| 18 | public: | 16 | public: |
| 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 | ||
| 31 | protected: | 35 | protected: |
| 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 | ||
| 15 | namespace Kernel { | 13 | namespace 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 | ||
| 11 | namespace Kernel { | 10 | namespace Kernel { |
| @@ -16,7 +15,6 @@ enum class ResetType { | |||
| 16 | Pulse, | 15 | Pulse, |
| 17 | }; | 16 | }; |
| 18 | 17 | ||
| 19 | |||
| 20 | class Event final : public WaitObject { | 18 | class Event final : public WaitObject { |
| 21 | public: | 19 | public: |
| 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 |
| 25 | const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, | 22 | const 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 |
| 28 | const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, | 25 | const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, |
| 29 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | 26 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); |
| 30 | 27 | ||
| 31 | enum KernelHandle : Handle { | 28 | enum KernelHandle : Handle { |
| 32 | CurrentThread = 0xFFFF8000, | 29 | CurrentThread = 0xFFFF8000, |
| 33 | CurrentProcess = 0xFFFF8001, | 30 | CurrentProcess = 0xFFFF8001, |
| 34 | }; | 31 | }; |
| 35 | 32 | ||
| 36 | enum class HandleType : u32 { | 33 | enum 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 | ||
| 55 | enum { | 52 | enum { |
| 56 | DEFAULT_STACK_SIZE = 0x4000, | 53 | DEFAULT_STACK_SIZE = 0x4000, |
| 57 | }; | 54 | }; |
| 58 | 55 | ||
| 59 | class Object : NonCopyable { | 56 | class 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 |
| 123 | class WaitObject : public Object { | 126 | class WaitObject : public Object { |
| 124 | public: | 127 | public: |
| 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]; | |||
| 31 | static const u32 memory_region_sizes[8][3] = { | 28 | static 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 | ||
| 101 | namespace Memory { | 97 | namespace 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. |
| 112 | static MemoryArea memory_areas[] = { | 108 | static 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 | ||
| 118 | void Init() { | 113 | void 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 | ||
| 13 | namespace Kernel { | 11 | namespace Kernel { |
| @@ -25,7 +23,6 @@ struct MemoryRegionInfo { | |||
| 25 | void MemoryInit(u32 mem_type); | 23 | void MemoryInit(u32 mem_type); |
| 26 | void MemoryShutdown(); | 24 | void MemoryShutdown(); |
| 27 | MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); | 25 | MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); |
| 28 | |||
| 29 | } | 26 | } |
| 30 | 27 | ||
| 31 | namespace Memory { | 28 | namespace 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 | ||
| 13 | namespace Kernel { | 11 | namespace 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) { | |||
| 107 | void Process::Run(s32 main_thread_priority, u32 stack_size) { | 106 | void 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 | ||
| 145 | ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission perms) { | 149 | ResultVal<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 | ||
| 178 | ResultCode Process::HeapFree(VAddr target, u32 size) { | 184 | ResultCode 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() {} | |||
| 272 | Kernel::Process::~Process() {} | 282 | Kernel::Process::~Process() {} |
| 273 | 283 | ||
| 274 | SharedPtr<Process> g_current_process; | 284 | SharedPtr<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 { | |||
| 36 | union ProcessFlags { | 33 | union 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; | |||
| 54 | struct CodeSet final : public Object { | 54 | struct 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 { | |||
| 85 | public: | 91 | public: |
| 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 | ||
| 166 | extern SharedPtr<Process> g_current_process; | 178 | extern 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 | ||
| 11 | namespace Kernel { | 9 | namespace Kernel { |
| @@ -23,70 +21,69 @@ SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { | |||
| 23 | } | 21 | } |
| 24 | 22 | ||
| 25 | SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { | 23 | SharedPtr<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 | ||
| 39 | s32 ResourceLimit::GetCurrentResourceValue(u32 resource) const { | 36 | s32 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 | ||
| 66 | s32 ResourceLimit::GetMaxResourceValue(u32 resource) const { | 63 | s32 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 | ||
| 152 | void ResourceLimitsShutdown() { | 149 | void 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 | ||
| 11 | namespace Kernel { | 10 | namespace Kernel { |
| 12 | 11 | ||
| 13 | enum class ResourceLimitCategory : u8 { | 12 | enum 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 | ||
| 20 | enum ResourceTypes { | 19 | enum 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 | ||
| 33 | class ResourceLimit final : public Object { | 32 | class 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() {} | |||
| 14 | Semaphore::~Semaphore() {} | 13 | Semaphore::~Semaphore() {} |
| 15 | 14 | ||
| 16 | ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, | 15 | ResultVal<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 | ||
| 14 | namespace Kernel { | 12 | namespace 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 | ||
| 28 | std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(u32 max_sessions, std::string name) { | 26 | std::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 | ||
| 14 | namespace Kernel { | 12 | namespace 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 | ||
| 10 | Session::Session() {} | 10 | Session::Session() {} |
| 11 | Session::~Session() {} | 11 | Session::~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 { | |||
| 19 | enum DescriptorType : u32 { | 17 | enum 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 | */ |
| 42 | constexpr u32 MakeHeader(u16 command_id, unsigned int normal_params, unsigned int translate_params_size) { | 43 | constexpr 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 | ||
| 46 | union Header { | 49 | union 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 | ||
| 53 | inline Header ParseHeader(u32 header) { | 56 | inline Header ParseHeader(u32 header) { |
| 54 | return{ header }; | 57 | return {header}; |
| 55 | } | 58 | } |
| 56 | 59 | ||
| 57 | constexpr u32 MoveHandleDesc(u32 num_handles = 1) { | 60 | constexpr u32 MoveHandleDesc(u32 num_handles = 1) { |
| @@ -80,27 +83,29 @@ constexpr u32 StaticBufferDesc(u32 size, u8 buffer_id) { | |||
| 80 | 83 | ||
| 81 | union StaticBufferDescInfo { | 84 | union 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 | ||
| 87 | inline StaticBufferDescInfo ParseStaticBufferDesc(const u32 desc) { | 90 | inline 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 | */ |
| 100 | inline u32 PXIBufferDesc(u32 size, unsigned buffer_id, bool is_read_only) { | 104 | inline 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 | ||
| 106 | enum MappedBufferPermissions { | 111 | enum MappedBufferPermissions { |
| @@ -115,12 +120,12 @@ constexpr u32 MappedBufferDesc(u32 size, MappedBufferPermissions perms) { | |||
| 115 | 120 | ||
| 116 | union MappedBufferDescInfo { | 121 | union 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 | ||
| 122 | inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { | 127 | inline MappedBufferDescInfo ParseMappedBufferDesc(const u32 desc) { |
| 123 | return{ desc }; | 128 | return {desc}; |
| 124 | } | 129 | } |
| 125 | 130 | ||
| 126 | inline DescriptorType GetDescriptorType(u32 descriptor) { | 131 | inline 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 | */ |
| 155 | inline u32* GetCommandBuffer(const int offset = 0) { | 160 | inline 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 | ||
| 13 | namespace Kernel { | 11 | namespace Kernel { |
| 14 | 12 | ||
| 15 | SharedMemory::SharedMemory() {} | 13 | SharedMemory::SharedMemory() {} |
| 16 | SharedMemory::~SharedMemory() {} | 14 | SharedMemory::~SharedMemory() {} |
| 17 | 15 | ||
| 18 | SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions, | 16 | SharedPtr<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 | ||
| 74 | SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, | 78 | SharedPtr<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 | ||
| 90 | ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions, | 97 | ResultCode 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 | ||
| 157 | ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) { | 174 | ResultCode 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 | ||
| 162 | VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) { | 180 | VMAPermission 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 |
| 18 | enum class MemoryPermission : u32 { | 16 | enum 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 | ||
| 30 | class SharedMemory final : public Object { | 28 | class 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; | |||
| 46 | static std::vector<SharedPtr<Thread>> thread_list; | 44 | static std::vector<SharedPtr<Thread>> thread_list; |
| 47 | 45 | ||
| 48 | // Lists only ready thread ids. | 46 | // Lists only ready thread ids. |
| 49 | static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> ready_queue; | 47 | static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST + 1> ready_queue; |
| 50 | 48 | ||
| 51 | static Thread* current_thread; | 49 | static 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 | ||
| 324 | void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all) { | 326 | void 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 | ||
| 373 | void Thread::ResumeFromWait() { | 377 | void 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 | */ |
| 451 | static void ResetThreadContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) { | 456 | static 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 | ||
| 460 | ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, | 466 | ResultVal<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. | ||
| 555 | static void ClampPriority(const Thread* thread, s32* priority) { | 565 | static 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 | ||
| 20 | enum ThreadPriority : s32{ | 16 | enum 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 | ||
| 27 | enum ThreadProcessorId : s32 { | 23 | enum 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 | ||
| 35 | enum ThreadStatus { | 31 | enum 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 | ||
| 45 | namespace Kernel { | 41 | namespace 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 | */ |
| 211 | void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wait_objects, bool wait_set_output, bool wait_all); | 220 | void 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 | ||
| 15 | namespace Kernel { | 13 | namespace Kernel { |
| 16 | 14 | ||
| @@ -41,7 +39,7 @@ bool Timer::ShouldWait() { | |||
| 41 | } | 39 | } |
| 42 | 40 | ||
| 43 | void Timer::Acquire() { | 41 | void 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 |
| 75 | static void TimerCallback(u64 timer_handle, int cycles_late) { | 73 | static 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 | ||
| 103 | void TimersShutdown() { | 102 | void 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 | ||
| 16 | static const char* GetMemoryStateName(MemoryState state) { | 14 | static 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 | ||
| 25 | bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const { | 23 | bool 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 | ||
| 72 | ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, | 69 | ResultVal<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 | ||
| 92 | ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8 * memory, u32 size, MemoryState state) { | 91 | ResultVal<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 | ||
| 109 | ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, Memory::MMIORegionPointer mmio_handler) { | 109 | ResultVal<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) { | |||
| 191 | void VMManager::LogLayout(Log::Level log_level) const { | 193 | void 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 | ||
| 202 | VMManager::VMAIter VMManager::StripIterConstness(const VMAHandle & iter) { | 205 | VMManager::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 | ||
| 16 | namespace Kernel { | 14 | namespace Kernel { |
| 17 | 15 | ||
| 18 | const ResultCode ERR_INVALID_ADDRESS{ // 0xE0E01BF5 | 16 | const 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 | ||
| 22 | const ResultCode ERR_INVALID_ADDRESS_STATE{ // 0xE0A01BF5 | 20 | const 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 | ||
| 26 | enum class VMAType : u8 { | 24 | enum 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 |
| 116 | public: | 114 | public: |
| 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 | } |