diff options
| author | 2015-02-02 13:04:04 -0500 | |
|---|---|---|
| committer | 2015-02-02 13:04:04 -0500 | |
| commit | 7f730ed158bc9bba064100b9644b318134ef0bb3 (patch) | |
| tree | c4181a69ff882e1af1b7d65bf3596a6cb3dd88b9 /src/core/hle/kernel | |
| parent | Merge pull request #517 from bunnei/blend-factors (diff) | |
| parent | Kernel: Stop creating useless Handles during object creation (diff) | |
| download | yuzu-7f730ed158bc9bba064100b9644b318134ef0bb3.tar.gz yuzu-7f730ed158bc9bba064100b9644b318134ef0bb3.tar.xz yuzu-7f730ed158bc9bba064100b9644b318134ef0bb3.zip | |
Merge pull request #523 from yuriks/kernel-lifetime5
Kernel Lifetime Reform Pt. 5: The Reckoning
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 13 | ||||
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/event.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/event.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 17 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 21 | ||||
| -rw-r--r-- | src/core/hle/kernel/mutex.cpp | 41 | ||||
| -rw-r--r-- | src/core/hle/kernel/mutex.h | 7 | ||||
| -rw-r--r-- | src/core/hle/kernel/semaphore.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/semaphore.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/session.cpp | 13 | ||||
| -rw-r--r-- | src/core/hle/kernel/session.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/shared_memory.cpp | 17 | ||||
| -rw-r--r-- | src/core/hle/kernel/shared_memory.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 53 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 31 | ||||
| -rw-r--r-- | src/core/hle/kernel/timer.cpp | 28 | ||||
| -rw-r--r-- | src/core/hle/kernel/timer.h | 8 |
18 files changed, 158 insertions, 127 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 2d01e2ef5..42f8ce2d9 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -15,14 +15,15 @@ | |||
| 15 | 15 | ||
| 16 | namespace Kernel { | 16 | namespace Kernel { |
| 17 | 17 | ||
| 18 | ResultVal<SharedPtr<AddressArbiter>> AddressArbiter::Create(std::string name) { | 18 | AddressArbiter::AddressArbiter() {} |
| 19 | AddressArbiter::~AddressArbiter() {} | ||
| 20 | |||
| 21 | SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { | ||
| 19 | SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); | 22 | SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); |
| 20 | // TOOD(yuriks): Don't create Handle (see Thread::Create()) | ||
| 21 | CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(address_arbiter)); | ||
| 22 | 23 | ||
| 23 | address_arbiter->name = std::move(name); | 24 | address_arbiter->name = std::move(name); |
| 24 | 25 | ||
| 25 | return MakeResult<SharedPtr<AddressArbiter>>(std::move(address_arbiter)); | 26 | return address_arbiter; |
| 26 | } | 27 | } |
| 27 | 28 | ||
| 28 | ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, | 29 | ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, |
| @@ -51,7 +52,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, | |||
| 51 | case ArbitrationType::WaitIfLessThanWithTimeout: | 52 | case ArbitrationType::WaitIfLessThanWithTimeout: |
| 52 | if ((s32)Memory::Read32(address) <= value) { | 53 | if ((s32)Memory::Read32(address) <= value) { |
| 53 | Kernel::WaitCurrentThread_ArbitrateAddress(address); | 54 | Kernel::WaitCurrentThread_ArbitrateAddress(address); |
| 54 | Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds); | 55 | GetCurrentThread()->WakeAfterDelay(nanoseconds); |
| 55 | HLE::Reschedule(__func__); | 56 | HLE::Reschedule(__func__); |
| 56 | } | 57 | } |
| 57 | break; | 58 | break; |
| @@ -71,7 +72,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, | |||
| 71 | Memory::Write32(address, memory_value); | 72 | Memory::Write32(address, memory_value); |
| 72 | if (memory_value <= value) { | 73 | if (memory_value <= value) { |
| 73 | Kernel::WaitCurrentThread_ArbitrateAddress(address); | 74 | Kernel::WaitCurrentThread_ArbitrateAddress(address); |
| 74 | Kernel::WakeThreadAfterDelay(GetCurrentThread(), nanoseconds); | 75 | GetCurrentThread()->WakeAfterDelay(nanoseconds); |
| 75 | HLE::Reschedule(__func__); | 76 | HLE::Reschedule(__func__); |
| 76 | } | 77 | } |
| 77 | break; | 78 | break; |
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 638afff9e..8f6a1a8df 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h | |||
| @@ -34,7 +34,7 @@ public: | |||
| 34 | * @param name Optional name used for debugging. | 34 | * @param name Optional name used for debugging. |
| 35 | * @returns The created AddressArbiter. | 35 | * @returns The created AddressArbiter. |
| 36 | */ | 36 | */ |
| 37 | static ResultVal<SharedPtr<AddressArbiter>> Create(std::string name = "Unknown"); | 37 | static SharedPtr<AddressArbiter> Create(std::string name = "Unknown"); |
| 38 | 38 | ||
| 39 | std::string GetTypeName() const override { return "Arbiter"; } | 39 | std::string GetTypeName() const override { return "Arbiter"; } |
| 40 | std::string GetName() const override { return name; } | 40 | std::string GetName() const override { return name; } |
| @@ -47,7 +47,8 @@ public: | |||
| 47 | ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); | 47 | ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); |
| 48 | 48 | ||
| 49 | private: | 49 | private: |
| 50 | AddressArbiter() = default; | 50 | AddressArbiter(); |
| 51 | ~AddressArbiter() override; | ||
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | } // namespace FileSys | 54 | } // namespace FileSys |
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index d9ad40c6a..898e1c98f 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp | |||
| @@ -14,16 +14,17 @@ | |||
| 14 | 14 | ||
| 15 | namespace Kernel { | 15 | namespace Kernel { |
| 16 | 16 | ||
| 17 | ResultVal<SharedPtr<Event>> Event::Create(ResetType reset_type, std::string name) { | 17 | Event::Event() {} |
| 18 | Event::~Event() {} | ||
| 19 | |||
| 20 | SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { | ||
| 18 | SharedPtr<Event> evt(new Event); | 21 | SharedPtr<Event> evt(new Event); |
| 19 | // TOOD(yuriks): Don't create Handle (see Thread::Create()) | ||
| 20 | CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(evt)); | ||
| 21 | 22 | ||
| 22 | evt->signaled = false; | 23 | evt->signaled = false; |
| 23 | evt->reset_type = evt->intitial_reset_type = reset_type; | 24 | evt->reset_type = evt->intitial_reset_type = reset_type; |
| 24 | evt->name = std::move(name); | 25 | evt->name = std::move(name); |
| 25 | 26 | ||
| 26 | return MakeResult<SharedPtr<Event>>(evt); | 27 | return evt; |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | bool Event::ShouldWait() { | 30 | bool Event::ShouldWait() { |
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 2c3e6b14e..fba960d2a 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h | |||
| @@ -18,7 +18,7 @@ public: | |||
| 18 | * @param reset_type ResetType describing how to create event | 18 | * @param reset_type ResetType describing how to create event |
| 19 | * @param name Optional name of event | 19 | * @param name Optional name of event |
| 20 | */ | 20 | */ |
| 21 | static ResultVal<SharedPtr<Event>> Create(ResetType reset_type, std::string name = "Unknown"); | 21 | static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown"); |
| 22 | 22 | ||
| 23 | std::string GetTypeName() const override { return "Event"; } | 23 | std::string GetTypeName() const override { return "Event"; } |
| 24 | std::string GetName() const override { return name; } | 24 | std::string GetName() const override { return name; } |
| @@ -39,7 +39,8 @@ public: | |||
| 39 | void Clear(); | 39 | void Clear(); |
| 40 | 40 | ||
| 41 | private: | 41 | private: |
| 42 | Event() = default; | 42 | Event(); |
| 43 | ~Event() override; | ||
| 43 | }; | 44 | }; |
| 44 | 45 | ||
| 45 | } // namespace | 46 | } // namespace |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index d7fa4dcea..7e0b9542e 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -14,14 +14,16 @@ | |||
| 14 | 14 | ||
| 15 | namespace Kernel { | 15 | namespace Kernel { |
| 16 | 16 | ||
| 17 | unsigned int Object::next_object_id = 0; | ||
| 18 | |||
| 17 | SharedPtr<Thread> g_main_thread = nullptr; | 19 | SharedPtr<Thread> g_main_thread = nullptr; |
| 18 | HandleTable g_handle_table; | 20 | HandleTable g_handle_table; |
| 19 | u64 g_program_id = 0; | 21 | u64 g_program_id = 0; |
| 20 | 22 | ||
| 21 | void WaitObject::AddWaitingThread(Thread* thread) { | 23 | void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) { |
| 22 | auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); | 24 | auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread); |
| 23 | if (itr == waiting_threads.end()) | 25 | if (itr == waiting_threads.end()) |
| 24 | waiting_threads.push_back(thread); | 26 | waiting_threads.push_back(std::move(thread)); |
| 25 | } | 27 | } |
| 26 | 28 | ||
| 27 | void WaitObject::RemoveWaitingThread(Thread* thread) { | 29 | void WaitObject::RemoveWaitingThread(Thread* thread) { |
| @@ -30,11 +32,11 @@ void WaitObject::RemoveWaitingThread(Thread* thread) { | |||
| 30 | waiting_threads.erase(itr); | 32 | waiting_threads.erase(itr); |
| 31 | } | 33 | } |
| 32 | 34 | ||
| 33 | Thread* WaitObject::WakeupNextThread() { | 35 | SharedPtr<Thread> WaitObject::WakeupNextThread() { |
| 34 | if (waiting_threads.empty()) | 36 | if (waiting_threads.empty()) |
| 35 | return nullptr; | 37 | return nullptr; |
| 36 | 38 | ||
| 37 | auto next_thread = waiting_threads.front(); | 39 | auto next_thread = std::move(waiting_threads.front()); |
| 38 | waiting_threads.erase(waiting_threads.begin()); | 40 | waiting_threads.erase(waiting_threads.begin()); |
| 39 | 41 | ||
| 40 | next_thread->ReleaseWaitObject(this); | 42 | next_thread->ReleaseWaitObject(this); |
| @@ -74,13 +76,10 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { | |||
| 74 | // CTR-OS doesn't use generation 0, so skip straight to 1. | 76 | // CTR-OS doesn't use generation 0, so skip straight to 1. |
| 75 | if (next_generation >= (1 << 15)) next_generation = 1; | 77 | if (next_generation >= (1 << 15)) next_generation = 1; |
| 76 | 78 | ||
| 77 | Handle handle = generation | (slot << 15); | ||
| 78 | if (obj->handle == INVALID_HANDLE) | ||
| 79 | obj->handle = handle; | ||
| 80 | |||
| 81 | generations[slot] = generation; | 79 | generations[slot] = generation; |
| 82 | objects[slot] = std::move(obj); | 80 | objects[slot] = std::move(obj); |
| 83 | 81 | ||
| 82 | Handle handle = generation | (slot << 15); | ||
| 84 | return MakeResult<Handle>(handle); | 83 | return MakeResult<Handle>(handle); |
| 85 | } | 84 | } |
| 86 | 85 | ||
| @@ -102,7 +101,7 @@ ResultCode HandleTable::Close(Handle handle) { | |||
| 102 | 101 | ||
| 103 | objects[slot] = nullptr; | 102 | objects[slot] = nullptr; |
| 104 | 103 | ||
| 105 | generations[generation] = next_free_slot; | 104 | generations[slot] = next_free_slot; |
| 106 | next_free_slot = slot; | 105 | next_free_slot = slot; |
| 107 | return RESULT_SUCCESS; | 106 | return RESULT_SUCCESS; |
| 108 | } | 107 | } |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 9860479ac..4d8e388b6 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -58,14 +58,12 @@ enum { | |||
| 58 | DEFAULT_STACK_SIZE = 0x4000, | 58 | DEFAULT_STACK_SIZE = 0x4000, |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | class HandleTable; | ||
| 62 | |||
| 63 | class Object : NonCopyable { | 61 | class Object : NonCopyable { |
| 64 | friend class HandleTable; | ||
| 65 | u32 handle = INVALID_HANDLE; | ||
| 66 | public: | 62 | public: |
| 67 | virtual ~Object() {} | 63 | virtual ~Object() {} |
| 68 | Handle GetHandle() const { return handle; } | 64 | |
| 65 | /// Returns a unique identifier for the object. For debugging purposes only. | ||
| 66 | unsigned int GetObjectId() const { return object_id; } | ||
| 69 | 67 | ||
| 70 | virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } | 68 | virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; } |
| 71 | virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } | 69 | virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; } |
| @@ -101,7 +99,10 @@ private: | |||
| 101 | friend void intrusive_ptr_add_ref(Object*); | 99 | friend void intrusive_ptr_add_ref(Object*); |
| 102 | friend void intrusive_ptr_release(Object*); | 100 | friend void intrusive_ptr_release(Object*); |
| 103 | 101 | ||
| 102 | static unsigned int next_object_id; | ||
| 103 | |||
| 104 | unsigned int ref_count = 0; | 104 | unsigned int ref_count = 0; |
| 105 | unsigned int object_id = next_object_id++; | ||
| 105 | }; | 106 | }; |
| 106 | 107 | ||
| 107 | // Special functions used by boost::instrusive_ptr to do automatic ref-counting | 108 | // Special functions used by boost::instrusive_ptr to do automatic ref-counting |
| @@ -135,25 +136,26 @@ public: | |||
| 135 | * Add a thread to wait on this object | 136 | * Add a thread to wait on this object |
| 136 | * @param thread Pointer to thread to add | 137 | * @param thread Pointer to thread to add |
| 137 | */ | 138 | */ |
| 138 | void AddWaitingThread(Thread* thread); | 139 | void AddWaitingThread(SharedPtr<Thread> thread); |
| 139 | 140 | ||
| 140 | /** | 141 | /** |
| 141 | * Removes a thread from waiting on this object (e.g. if it was resumed already) | 142 | * Removes a thread from waiting on this object (e.g. if it was resumed already) |
| 142 | * @param thread Pointer to thread to remove | 143 | * @param thread Pointer to thread to remove |
| 143 | */ | 144 | */ |
| 144 | void RemoveWaitingThread(Thread* thead); | 145 | void RemoveWaitingThread(Thread* thread); |
| 145 | 146 | ||
| 146 | /** | 147 | /** |
| 147 | * Wake up the next thread waiting on this object | 148 | * Wake up the next thread waiting on this object |
| 148 | * @return Pointer to the thread that was resumed, nullptr if no threads are waiting | 149 | * @return Pointer to the thread that was resumed, nullptr if no threads are waiting |
| 149 | */ | 150 | */ |
| 150 | Thread* WakeupNextThread(); | 151 | SharedPtr<Thread> WakeupNextThread(); |
| 151 | 152 | ||
| 152 | /// Wake up all threads waiting on this object | 153 | /// Wake up all threads waiting on this object |
| 153 | void WakeupAllWaitingThreads(); | 154 | void WakeupAllWaitingThreads(); |
| 154 | 155 | ||
| 155 | private: | 156 | private: |
| 156 | std::vector<Thread*> waiting_threads; ///< Threads waiting for this object to become available | 157 | /// Threads waiting for this object to become available |
| 158 | std::vector<SharedPtr<Thread>> waiting_threads; | ||
| 157 | }; | 159 | }; |
| 158 | 160 | ||
| 159 | /** | 161 | /** |
| @@ -274,7 +276,6 @@ private: | |||
| 274 | }; | 276 | }; |
| 275 | 277 | ||
| 276 | extern HandleTable g_handle_table; | 278 | extern HandleTable g_handle_table; |
| 277 | extern SharedPtr<Thread> g_main_thread; | ||
| 278 | 279 | ||
| 279 | /// The ID code of the currently running game | 280 | /// The ID code of the currently running game |
| 280 | /// TODO(Subv): This variable should not be here, | 281 | /// TODO(Subv): This variable should not be here, |
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index acf484659..9f7166ca4 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | #include <map> | 5 | #include <map> |
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | 7 | ||
| 8 | #include <boost/range/algorithm_ext/erase.hpp> | ||
| 9 | |||
| 8 | #include "common/common.h" | 10 | #include "common/common.h" |
| 9 | 11 | ||
| 10 | #include "core/hle/kernel/kernel.h" | 12 | #include "core/hle/kernel/kernel.h" |
| @@ -13,9 +15,6 @@ | |||
| 13 | 15 | ||
| 14 | namespace Kernel { | 16 | namespace Kernel { |
| 15 | 17 | ||
| 16 | typedef std::multimap<SharedPtr<Thread>, SharedPtr<Mutex>> MutexMap; | ||
| 17 | static MutexMap g_mutex_held_locks; | ||
| 18 | |||
| 19 | /** | 18 | /** |
| 20 | * Resumes a thread waiting for the specified mutex | 19 | * Resumes a thread waiting for the specified mutex |
| 21 | * @param mutex The mutex that some thread is waiting on | 20 | * @param mutex The mutex that some thread is waiting on |
| @@ -33,21 +32,17 @@ static void ResumeWaitingThread(Mutex* mutex) { | |||
| 33 | } | 32 | } |
| 34 | 33 | ||
| 35 | void ReleaseThreadMutexes(Thread* thread) { | 34 | void ReleaseThreadMutexes(Thread* thread) { |
| 36 | auto locked_range = g_mutex_held_locks.equal_range(thread); | 35 | for (auto& mtx : thread->held_mutexes) { |
| 37 | 36 | ResumeWaitingThread(mtx.get()); | |
| 38 | // Release every mutex that the thread holds, and resume execution on the waiting threads | ||
| 39 | for (auto iter = locked_range.first; iter != locked_range.second; ++iter) { | ||
| 40 | ResumeWaitingThread(iter->second.get()); | ||
| 41 | } | 37 | } |
| 42 | 38 | thread->held_mutexes.clear(); | |
| 43 | // Erase all the locks that this thread holds | ||
| 44 | g_mutex_held_locks.erase(thread); | ||
| 45 | } | 39 | } |
| 46 | 40 | ||
| 47 | ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) { | 41 | Mutex::Mutex() {} |
| 42 | Mutex::~Mutex() {} | ||
| 43 | |||
| 44 | SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) { | ||
| 48 | SharedPtr<Mutex> mutex(new Mutex); | 45 | SharedPtr<Mutex> mutex(new Mutex); |
| 49 | // TOOD(yuriks): Don't create Handle (see Thread::Create()) | ||
| 50 | CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(mutex)); | ||
| 51 | 46 | ||
| 52 | mutex->initial_locked = initial_locked; | 47 | mutex->initial_locked = initial_locked; |
| 53 | mutex->locked = false; | 48 | mutex->locked = false; |
| @@ -58,7 +53,7 @@ ResultVal<SharedPtr<Mutex>> Mutex::Create(bool initial_locked, std::string name) | |||
| 58 | if (initial_locked) | 53 | if (initial_locked) |
| 59 | mutex->Acquire(); | 54 | mutex->Acquire(); |
| 60 | 55 | ||
| 61 | return MakeResult<SharedPtr<Mutex>>(mutex); | 56 | return mutex; |
| 62 | } | 57 | } |
| 63 | 58 | ||
| 64 | bool Mutex::ShouldWait() { | 59 | bool Mutex::ShouldWait() { |
| @@ -69,30 +64,22 @@ void Mutex::Acquire() { | |||
| 69 | Acquire(GetCurrentThread()); | 64 | Acquire(GetCurrentThread()); |
| 70 | } | 65 | } |
| 71 | 66 | ||
| 72 | void Mutex::Acquire(Thread* thread) { | 67 | void Mutex::Acquire(SharedPtr<Thread> thread) { |
| 73 | _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); | 68 | _assert_msg_(Kernel, !ShouldWait(), "object unavailable!"); |
| 74 | if (locked) | 69 | if (locked) |
| 75 | return; | 70 | return; |
| 76 | 71 | ||
| 77 | locked = true; | 72 | locked = true; |
| 78 | 73 | ||
| 79 | g_mutex_held_locks.insert(std::make_pair(thread, this)); | 74 | thread->held_mutexes.insert(this); |
| 80 | holding_thread = thread; | 75 | holding_thread = std::move(thread); |
| 81 | } | 76 | } |
| 82 | 77 | ||
| 83 | void Mutex::Release() { | 78 | void Mutex::Release() { |
| 84 | if (!locked) | 79 | if (!locked) |
| 85 | return; | 80 | return; |
| 86 | 81 | ||
| 87 | auto locked_range = g_mutex_held_locks.equal_range(holding_thread); | 82 | holding_thread->held_mutexes.erase(this); |
| 88 | |||
| 89 | for (MutexMap::iterator iter = locked_range.first; iter != locked_range.second; ++iter) { | ||
| 90 | if (iter->second == this) { | ||
| 91 | g_mutex_held_locks.erase(iter); | ||
| 92 | break; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | ResumeWaitingThread(this); | 83 | ResumeWaitingThread(this); |
| 97 | } | 84 | } |
| 98 | 85 | ||
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 1e69528f1..548403614 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h | |||
| @@ -22,7 +22,7 @@ public: | |||
| 22 | * @param name Optional name of mutex | 22 | * @param name Optional name of mutex |
| 23 | * @return Pointer to new Mutex object | 23 | * @return Pointer to new Mutex object |
| 24 | */ | 24 | */ |
| 25 | static ResultVal<SharedPtr<Mutex>> Create(bool initial_locked, std::string name = "Unknown"); | 25 | static SharedPtr<Mutex> Create(bool initial_locked, std::string name = "Unknown"); |
| 26 | 26 | ||
| 27 | std::string GetTypeName() const override { return "Mutex"; } | 27 | std::string GetTypeName() const override { return "Mutex"; } |
| 28 | std::string GetName() const override { return name; } | 28 | std::string GetName() const override { return name; } |
| @@ -43,11 +43,12 @@ public: | |||
| 43 | * @param mutex Mutex that is to be acquired | 43 | * @param mutex Mutex that is to be acquired |
| 44 | * @param thread Thread that will acquire the mutex | 44 | * @param thread Thread that will acquire the mutex |
| 45 | */ | 45 | */ |
| 46 | void Acquire(Thread* thread); | 46 | void Acquire(SharedPtr<Thread> thread); |
| 47 | void Release(); | 47 | void Release(); |
| 48 | 48 | ||
| 49 | private: | 49 | private: |
| 50 | Mutex() = default; | 50 | Mutex(); |
| 51 | ~Mutex() override; | ||
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | /** | 54 | /** |
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index a9e406ef4..c8cf8b9a2 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp | |||
| @@ -10,6 +10,9 @@ | |||
| 10 | 10 | ||
| 11 | namespace Kernel { | 11 | namespace Kernel { |
| 12 | 12 | ||
| 13 | Semaphore::Semaphore() {} | ||
| 14 | Semaphore::~Semaphore() {} | ||
| 15 | |||
| 13 | ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, | 16 | ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_count, |
| 14 | std::string name) { | 17 | std::string name) { |
| 15 | 18 | ||
| @@ -18,8 +21,6 @@ ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_cou | |||
| 18 | ErrorSummary::WrongArgument, ErrorLevel::Permanent); | 21 | ErrorSummary::WrongArgument, ErrorLevel::Permanent); |
| 19 | 22 | ||
| 20 | SharedPtr<Semaphore> semaphore(new Semaphore); | 23 | SharedPtr<Semaphore> semaphore(new Semaphore); |
| 21 | // TOOD(yuriks): Don't create Handle (see Thread::Create()) | ||
| 22 | CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(semaphore)); | ||
| 23 | 24 | ||
| 24 | // When the semaphore is created, some slots are reserved for other threads, | 25 | // When the semaphore is created, some slots are reserved for other threads, |
| 25 | // and the rest is reserved for the caller thread | 26 | // and the rest is reserved for the caller thread |
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index 9bb404ab6..d8dc1fd78 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h | |||
| @@ -47,7 +47,8 @@ public: | |||
| 47 | ResultVal<s32> Release(s32 release_count); | 47 | ResultVal<s32> Release(s32 release_count); |
| 48 | 48 | ||
| 49 | private: | 49 | private: |
| 50 | Semaphore() = default; | 50 | Semaphore(); |
| 51 | ~Semaphore() override; | ||
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | } // namespace | 54 | } // namespace |
diff --git a/src/core/hle/kernel/session.cpp b/src/core/hle/kernel/session.cpp new file mode 100644 index 000000000..0594967f8 --- /dev/null +++ b/src/core/hle/kernel/session.cpp | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | // Copyright 2015 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/kernel/session.h" | ||
| 6 | #include "core/hle/kernel/thread.h" | ||
| 7 | |||
| 8 | namespace Kernel { | ||
| 9 | |||
| 10 | Session::Session() {} | ||
| 11 | Session::~Session() {} | ||
| 12 | |||
| 13 | } | ||
diff --git a/src/core/hle/kernel/session.h b/src/core/hle/kernel/session.h index 1788e4375..7cc9332c9 100644 --- a/src/core/hle/kernel/session.h +++ b/src/core/hle/kernel/session.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/kernel/kernel.h" | 7 | #include "core/hle/kernel/kernel.h" |
| 8 | #include "core/mem_map.h" | ||
| 8 | 9 | ||
| 9 | namespace Kernel { | 10 | namespace Kernel { |
| 10 | 11 | ||
| @@ -43,6 +44,9 @@ inline static u32* GetCommandBuffer(const int offset=0) { | |||
| 43 | */ | 44 | */ |
| 44 | class Session : public WaitObject { | 45 | class Session : public WaitObject { |
| 45 | public: | 46 | public: |
| 47 | Session(); | ||
| 48 | ~Session() override; | ||
| 49 | |||
| 46 | std::string GetTypeName() const override { return "Session"; } | 50 | std::string GetTypeName() const override { return "Session"; } |
| 47 | 51 | ||
| 48 | static const HandleType HANDLE_TYPE = HandleType::Session; | 52 | static const HandleType HANDLE_TYPE = HandleType::Session; |
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index eff68d481..4211fcf04 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp | |||
| @@ -9,22 +9,23 @@ | |||
| 9 | 9 | ||
| 10 | namespace Kernel { | 10 | namespace Kernel { |
| 11 | 11 | ||
| 12 | ResultVal<SharedPtr<SharedMemory>> SharedMemory::Create(std::string name) { | 12 | SharedMemory::SharedMemory() {} |
| 13 | SharedPtr<SharedMemory> shared_memory(new SharedMemory); | 13 | SharedMemory::~SharedMemory() {} |
| 14 | 14 | ||
| 15 | // TOOD(yuriks): Don't create Handle (see Thread::Create()) | 15 | SharedPtr<SharedMemory> SharedMemory::Create(std::string name) { |
| 16 | CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(shared_memory)); | 16 | SharedPtr<SharedMemory> shared_memory(new SharedMemory); |
| 17 | 17 | ||
| 18 | shared_memory->name = std::move(name); | 18 | shared_memory->name = std::move(name); |
| 19 | return MakeResult<SharedPtr<SharedMemory>>(std::move(shared_memory)); | 19 | |
| 20 | return shared_memory; | ||
| 20 | } | 21 | } |
| 21 | 22 | ||
| 22 | ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions, | 23 | ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions, |
| 23 | MemoryPermission other_permissions) { | 24 | MemoryPermission other_permissions) { |
| 24 | 25 | ||
| 25 | if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { | 26 | if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) { |
| 26 | LOG_ERROR(Kernel, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!", | 27 | LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X outside of shared mem bounds!", |
| 27 | GetHandle(), address); | 28 | GetObjectId(), address); |
| 28 | // TODO: Verify error code with hardware | 29 | // TODO: Verify error code with hardware |
| 29 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, | 30 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, |
| 30 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | 31 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); |
| @@ -41,7 +42,7 @@ ResultVal<u8*> SharedMemory::GetPointer(u32 offset) { | |||
| 41 | if (base_address != 0) | 42 | if (base_address != 0) |
| 42 | return MakeResult<u8*>(Memory::GetPointer(base_address + offset)); | 43 | return MakeResult<u8*>(Memory::GetPointer(base_address + offset)); |
| 43 | 44 | ||
| 44 | LOG_ERROR(Kernel_SVC, "memory block handle=0x%08X not mapped!", GetHandle()); | 45 | LOG_ERROR(Kernel_SVC, "memory block id=%u not mapped!", GetObjectId()); |
| 45 | // TODO(yuriks): Verify error code. | 46 | // TODO(yuriks): Verify error code. |
| 46 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, | 47 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, |
| 47 | ErrorSummary::InvalidState, ErrorLevel::Permanent); | 48 | ErrorSummary::InvalidState, ErrorLevel::Permanent); |
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index d393e8175..5833b411c 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h | |||
| @@ -29,7 +29,7 @@ public: | |||
| 29 | * Creates a shared memory object | 29 | * Creates a shared memory object |
| 30 | * @param name Optional object name, used only for debugging purposes. | 30 | * @param name Optional object name, used only for debugging purposes. |
| 31 | */ | 31 | */ |
| 32 | static ResultVal<SharedPtr<SharedMemory>> Create(std::string name = "Unknown"); | 32 | static SharedPtr<SharedMemory> Create(std::string name = "Unknown"); |
| 33 | 33 | ||
| 34 | std::string GetTypeName() const override { return "SharedMemory"; } | 34 | std::string GetTypeName() const override { return "SharedMemory"; } |
| 35 | 35 | ||
| @@ -57,7 +57,8 @@ public: | |||
| 57 | std::string name; ///< Name of shared memory object (optional) | 57 | std::string name; ///< Name of shared memory object (optional) |
| 58 | 58 | ||
| 59 | private: | 59 | private: |
| 60 | SharedMemory() = default; | 60 | SharedMemory(); |
| 61 | ~SharedMemory() override; | ||
| 61 | }; | 62 | }; |
| 62 | 63 | ||
| 63 | } // namespace | 64 | } // namespace |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 56950ebd4..3987f9608 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <list> | 6 | #include <list> |
| 7 | #include <map> | ||
| 8 | #include <vector> | 7 | #include <vector> |
| 9 | 8 | ||
| 10 | #include "common/common.h" | 9 | #include "common/common.h" |
| @@ -41,6 +40,9 @@ static Thread* current_thread; | |||
| 41 | static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup | 40 | static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup |
| 42 | static u32 next_thread_id; ///< The next available thread id | 41 | static u32 next_thread_id; ///< The next available thread id |
| 43 | 42 | ||
| 43 | Thread::Thread() {} | ||
| 44 | Thread::~Thread() {} | ||
| 45 | |||
| 44 | Thread* GetCurrentThread() { | 46 | Thread* GetCurrentThread() { |
| 45 | return current_thread; | 47 | return current_thread; |
| 46 | } | 48 | } |
| @@ -108,6 +110,9 @@ void Thread::Stop(const char* reason) { | |||
| 108 | WakeupAllWaitingThreads(); | 110 | WakeupAllWaitingThreads(); |
| 109 | 111 | ||
| 110 | // Stopped threads are never waiting. | 112 | // Stopped threads are never waiting. |
| 113 | for (auto& wait_object : wait_objects) { | ||
| 114 | wait_object->RemoveWaitingThread(this); | ||
| 115 | } | ||
| 111 | wait_objects.clear(); | 116 | wait_objects.clear(); |
| 112 | wait_address = 0; | 117 | wait_address = 0; |
| 113 | } | 118 | } |
| @@ -228,13 +233,15 @@ void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) { | |||
| 228 | 233 | ||
| 229 | /// Event type for the thread wake up event | 234 | /// Event type for the thread wake up event |
| 230 | static int ThreadWakeupEventType = -1; | 235 | static int ThreadWakeupEventType = -1; |
| 236 | // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing | ||
| 237 | // us to simply use a pool index or similar. | ||
| 238 | static Kernel::HandleTable wakeup_callback_handle_table; | ||
| 231 | 239 | ||
| 232 | /// Callback that will wake up the thread it was scheduled for | 240 | /// Callback that will wake up the thread it was scheduled for |
| 233 | static void ThreadWakeupCallback(u64 parameter, int cycles_late) { | 241 | static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { |
| 234 | Handle handle = static_cast<Handle>(parameter); | 242 | SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle); |
| 235 | SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(handle); | ||
| 236 | if (thread == nullptr) { | 243 | if (thread == nullptr) { |
| 237 | LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); | 244 | LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", thread_handle); |
| 238 | return; | 245 | return; |
| 239 | } | 246 | } |
| 240 | 247 | ||
| @@ -248,14 +255,13 @@ static void ThreadWakeupCallback(u64 parameter, int cycles_late) { | |||
| 248 | } | 255 | } |
| 249 | 256 | ||
| 250 | 257 | ||
| 251 | void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds) { | 258 | void Thread::WakeAfterDelay(s64 nanoseconds) { |
| 252 | // Don't schedule a wakeup if the thread wants to wait forever | 259 | // Don't schedule a wakeup if the thread wants to wait forever |
| 253 | if (nanoseconds == -1) | 260 | if (nanoseconds == -1) |
| 254 | return; | 261 | return; |
| 255 | _dbg_assert_(Kernel, thread != nullptr); | ||
| 256 | 262 | ||
| 257 | u64 microseconds = nanoseconds / 1000; | 263 | u64 microseconds = nanoseconds / 1000; |
| 258 | CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, thread->GetHandle()); | 264 | CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, callback_handle); |
| 259 | } | 265 | } |
| 260 | 266 | ||
| 261 | void Thread::ReleaseWaitObject(WaitObject* wait_object) { | 267 | void Thread::ReleaseWaitObject(WaitObject* wait_object) { |
| @@ -302,7 +308,7 @@ void Thread::ReleaseWaitObject(WaitObject* wait_object) { | |||
| 302 | 308 | ||
| 303 | void Thread::ResumeFromWait() { | 309 | void Thread::ResumeFromWait() { |
| 304 | // Cancel any outstanding wakeup events | 310 | // Cancel any outstanding wakeup events |
| 305 | CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle()); | 311 | CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle); |
| 306 | 312 | ||
| 307 | status &= ~THREADSTATUS_WAIT; | 313 | status &= ~THREADSTATUS_WAIT; |
| 308 | 314 | ||
| @@ -326,11 +332,11 @@ static void DebugThreadQueue() { | |||
| 326 | if (!thread) { | 332 | if (!thread) { |
| 327 | return; | 333 | return; |
| 328 | } | 334 | } |
| 329 | LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle()); | 335 | LOG_DEBUG(Kernel, "0x%02X %u (current)", thread->current_priority, GetCurrentThread()->GetObjectId()); |
| 330 | for (auto& t : thread_list) { | 336 | for (auto& t : thread_list) { |
| 331 | s32 priority = thread_ready_queue.contains(t.get()); | 337 | s32 priority = thread_ready_queue.contains(t.get()); |
| 332 | if (priority != -1) { | 338 | if (priority != -1) { |
| 333 | LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle()); | 339 | LOG_DEBUG(Kernel, "0x%02X %u", priority, t->GetObjectId()); |
| 334 | } | 340 | } |
| 335 | } | 341 | } |
| 336 | } | 342 | } |
| @@ -362,14 +368,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 362 | 368 | ||
| 363 | SharedPtr<Thread> thread(new Thread); | 369 | SharedPtr<Thread> thread(new Thread); |
| 364 | 370 | ||
| 365 | // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for | ||
| 366 | // the time being. Create a handle here, it will be copied to the handle field in | ||
| 367 | // the object and use by the rest of the code. This should be removed when other | ||
| 368 | // code doesn't rely on the handle anymore. | ||
| 369 | ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread); | ||
| 370 | if (handle.Failed()) | ||
| 371 | return handle.Code(); | ||
| 372 | |||
| 373 | thread_list.push_back(thread); | 371 | thread_list.push_back(thread); |
| 374 | thread_ready_queue.prepare(priority); | 372 | thread_ready_queue.prepare(priority); |
| 375 | 373 | ||
| @@ -385,6 +383,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 385 | thread->wait_objects.clear(); | 383 | thread->wait_objects.clear(); |
| 386 | thread->wait_address = 0; | 384 | thread->wait_address = 0; |
| 387 | thread->name = std::move(name); | 385 | thread->name = std::move(name); |
| 386 | thread->callback_handle = wakeup_callback_handle_table.Create(thread).MoveFrom(); | ||
| 388 | 387 | ||
| 389 | ResetThread(thread.get(), arg, 0); | 388 | ResetThread(thread.get(), arg, 0); |
| 390 | CallThread(thread.get()); | 389 | CallThread(thread.get()); |
| @@ -418,16 +417,14 @@ void Thread::SetPriority(s32 priority) { | |||
| 418 | } | 417 | } |
| 419 | } | 418 | } |
| 420 | 419 | ||
| 421 | Handle SetupIdleThread() { | 420 | SharedPtr<Thread> SetupIdleThread() { |
| 422 | // We need to pass a few valid values to get around parameter checking in Thread::Create. | 421 | // We need to pass a few valid values to get around parameter checking in Thread::Create. |
| 423 | auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0, | 422 | auto thread = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0, |
| 424 | THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE); | 423 | THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE).MoveFrom(); |
| 425 | _dbg_assert_(Kernel, thread_res.Succeeded()); | ||
| 426 | SharedPtr<Thread> thread = std::move(*thread_res); | ||
| 427 | 424 | ||
| 428 | thread->idle = true; | 425 | thread->idle = true; |
| 429 | CallThread(thread.get()); | 426 | CallThread(thread.get()); |
| 430 | return thread->GetHandle(); | 427 | return thread; |
| 431 | } | 428 | } |
| 432 | 429 | ||
| 433 | SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) { | 430 | SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size) { |
| @@ -460,13 +457,13 @@ void Reschedule() { | |||
| 460 | HLE::g_reschedule = false; | 457 | HLE::g_reschedule = false; |
| 461 | 458 | ||
| 462 | if (next != nullptr) { | 459 | if (next != nullptr) { |
| 463 | LOG_TRACE(Kernel, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); | 460 | LOG_TRACE(Kernel, "context switch %u -> %u", prev->GetObjectId(), next->GetObjectId()); |
| 464 | SwitchContext(next); | 461 | SwitchContext(next); |
| 465 | } else { | 462 | } else { |
| 466 | LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); | 463 | LOG_TRACE(Kernel, "cannot context switch from %u, no higher priority thread!", prev->GetObjectId()); |
| 467 | 464 | ||
| 468 | for (auto& thread : thread_list) { | 465 | for (auto& thread : thread_list) { |
| 469 | LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X", thread->GetHandle(), | 466 | LOG_TRACE(Kernel, "\tid=%u prio=0x%02X, status=0x%08X", thread->GetObjectId(), |
| 470 | thread->current_priority, thread->status); | 467 | thread->current_priority, thread->status); |
| 471 | } | 468 | } |
| 472 | } | 469 | } |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index d6299364a..633bb7c98 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | #include <string> | 7 | #include <string> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include <boost/container/flat_set.hpp> | ||
| 11 | |||
| 10 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 11 | 13 | ||
| 12 | #include "core/core.h" | 14 | #include "core/core.h" |
| @@ -40,6 +42,8 @@ enum ThreadStatus { | |||
| 40 | 42 | ||
| 41 | namespace Kernel { | 43 | namespace Kernel { |
| 42 | 44 | ||
| 45 | class Mutex; | ||
| 46 | |||
| 43 | class Thread final : public WaitObject { | 47 | class Thread final : public WaitObject { |
| 44 | public: | 48 | public: |
| 45 | static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, | 49 | static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority, |
| @@ -78,6 +82,12 @@ public: | |||
| 78 | void ResumeFromWait(); | 82 | void ResumeFromWait(); |
| 79 | 83 | ||
| 80 | /** | 84 | /** |
| 85 | * Schedules an event to wake up the specified thread after the specified delay. | ||
| 86 | * @param nanoseconds The time this thread will be allowed to sleep for. | ||
| 87 | */ | ||
| 88 | void WakeAfterDelay(s64 nanoseconds); | ||
| 89 | |||
| 90 | /** | ||
| 81 | * Sets the result after the thread awakens (from either WaitSynchronization SVC) | 91 | * Sets the result after the thread awakens (from either WaitSynchronization SVC) |
| 82 | * @param result Value to set to the returned result | 92 | * @param result Value to set to the returned result |
| 83 | */ | 93 | */ |
| @@ -103,8 +113,10 @@ public: | |||
| 103 | 113 | ||
| 104 | s32 processor_id; | 114 | s32 processor_id; |
| 105 | 115 | ||
| 106 | std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on | 116 | /// Mutexes currently held by this thread, which will be released when it exits. |
| 117 | boost::container::flat_set<SharedPtr<Mutex>> held_mutexes; | ||
| 107 | 118 | ||
| 119 | std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on | ||
| 108 | VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address | 120 | VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address |
| 109 | bool wait_all; ///< True if the thread is waiting on all objects before resuming | 121 | bool wait_all; ///< True if the thread is waiting on all objects before resuming |
| 110 | bool wait_set_output; ///< True if the output parameter should be set on thread wakeup | 122 | bool wait_set_output; ///< True if the output parameter should be set on thread wakeup |
| @@ -115,9 +127,15 @@ public: | |||
| 115 | bool idle = false; | 127 | bool idle = false; |
| 116 | 128 | ||
| 117 | private: | 129 | private: |
| 118 | Thread() = default; | 130 | Thread(); |
| 131 | ~Thread() override; | ||
| 132 | |||
| 133 | /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. | ||
| 134 | Handle callback_handle; | ||
| 119 | }; | 135 | }; |
| 120 | 136 | ||
| 137 | extern SharedPtr<Thread> g_main_thread; | ||
| 138 | |||
| 121 | /// Sets up the primary application thread | 139 | /// Sets up the primary application thread |
| 122 | SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size); | 140 | SharedPtr<Thread> SetupMainThread(s32 priority, u32 stack_size); |
| 123 | 141 | ||
| @@ -151,19 +169,12 @@ void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bo | |||
| 151 | void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); | 169 | void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); |
| 152 | 170 | ||
| 153 | /** | 171 | /** |
| 154 | * Schedules an event to wake up the specified thread after the specified delay. | ||
| 155 | * @param handle The thread handle. | ||
| 156 | * @param nanoseconds The time this thread will be allowed to sleep for. | ||
| 157 | */ | ||
| 158 | void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds); | ||
| 159 | |||
| 160 | /** | ||
| 161 | * Sets up the idle thread, this is a thread that is intended to never execute instructions, | 172 | * Sets up the idle thread, this is a thread that is intended to never execute instructions, |
| 162 | * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue | 173 | * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue |
| 163 | * and will try to yield on every call. | 174 | * and will try to yield on every call. |
| 164 | * @returns The handle of the idle thread | 175 | * @returns The handle of the idle thread |
| 165 | */ | 176 | */ |
| 166 | Handle SetupIdleThread(); | 177 | SharedPtr<Thread> SetupIdleThread(); |
| 167 | 178 | ||
| 168 | /// Initialize threading | 179 | /// Initialize threading |
| 169 | void ThreadingInit(); | 180 | void ThreadingInit(); |
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index 503a5d2ce..4352fc99c 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp | |||
| @@ -2,8 +2,6 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <set> | ||
| 6 | |||
| 7 | #include "common/common.h" | 5 | #include "common/common.h" |
| 8 | 6 | ||
| 9 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| @@ -15,18 +13,24 @@ namespace Kernel { | |||
| 15 | 13 | ||
| 16 | /// The event type of the generic timer callback event | 14 | /// The event type of the generic timer callback event |
| 17 | static int timer_callback_event_type = -1; | 15 | static int timer_callback_event_type = -1; |
| 16 | // TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future, allowing | ||
| 17 | // us to simply use a pool index or similar. | ||
| 18 | static Kernel::HandleTable timer_callback_handle_table; | ||
| 19 | |||
| 20 | Timer::Timer() {} | ||
| 21 | Timer::~Timer() {} | ||
| 18 | 22 | ||
| 19 | ResultVal<SharedPtr<Timer>> Timer::Create(ResetType reset_type, std::string name) { | 23 | SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) { |
| 20 | SharedPtr<Timer> timer(new Timer); | 24 | SharedPtr<Timer> timer(new Timer); |
| 21 | // TOOD(yuriks): Don't create Handle (see Thread::Create()) | ||
| 22 | CASCADE_RESULT(auto unused, Kernel::g_handle_table.Create(timer)); | ||
| 23 | 25 | ||
| 24 | timer->reset_type = reset_type; | 26 | timer->reset_type = reset_type; |
| 25 | timer->signaled = false; | 27 | timer->signaled = false; |
| 26 | timer->name = std::move(name); | 28 | timer->name = std::move(name); |
| 27 | timer->initial_delay = 0; | 29 | timer->initial_delay = 0; |
| 28 | timer->interval_delay = 0; | 30 | timer->interval_delay = 0; |
| 29 | return MakeResult<SharedPtr<Timer>>(timer); | 31 | timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom(); |
| 32 | |||
| 33 | return timer; | ||
| 30 | } | 34 | } |
| 31 | 35 | ||
| 32 | bool Timer::ShouldWait() { | 36 | bool Timer::ShouldWait() { |
| @@ -38,17 +42,19 @@ void Timer::Acquire() { | |||
| 38 | } | 42 | } |
| 39 | 43 | ||
| 40 | void Timer::Set(s64 initial, s64 interval) { | 44 | void Timer::Set(s64 initial, s64 interval) { |
| 45 | // Ensure we get rid of any previous scheduled event | ||
| 46 | Cancel(); | ||
| 47 | |||
| 41 | initial_delay = initial; | 48 | initial_delay = initial; |
| 42 | interval_delay = interval; | 49 | interval_delay = interval; |
| 43 | 50 | ||
| 44 | u64 initial_microseconds = initial / 1000; | 51 | u64 initial_microseconds = initial / 1000; |
| 45 | // TODO(yuriks): Figure out a replacement for GetHandle here | 52 | CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), |
| 46 | CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type, | 53 | timer_callback_event_type, callback_handle); |
| 47 | GetHandle()); | ||
| 48 | } | 54 | } |
| 49 | 55 | ||
| 50 | void Timer::Cancel() { | 56 | void Timer::Cancel() { |
| 51 | CoreTiming::UnscheduleEvent(timer_callback_event_type, GetHandle()); | 57 | CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle); |
| 52 | } | 58 | } |
| 53 | 59 | ||
| 54 | void Timer::Clear() { | 60 | void Timer::Clear() { |
| @@ -57,7 +63,7 @@ void Timer::Clear() { | |||
| 57 | 63 | ||
| 58 | /// The timer callback event, called when a timer is fired | 64 | /// The timer callback event, called when a timer is fired |
| 59 | static void TimerCallback(u64 timer_handle, int cycles_late) { | 65 | static void TimerCallback(u64 timer_handle, int cycles_late) { |
| 60 | SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle); | 66 | SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(timer_handle); |
| 61 | 67 | ||
| 62 | if (timer == nullptr) { | 68 | if (timer == nullptr) { |
| 63 | LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle); | 69 | LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle); |
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index c45e79954..540e4e187 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h | |||
| @@ -19,7 +19,7 @@ public: | |||
| 19 | * @param name Optional name of timer | 19 | * @param name Optional name of timer |
| 20 | * @return The created Timer | 20 | * @return The created Timer |
| 21 | */ | 21 | */ |
| 22 | static ResultVal<SharedPtr<Timer>> Create(ResetType reset_type, std::string name = "Unknown"); | 22 | static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown"); |
| 23 | 23 | ||
| 24 | std::string GetTypeName() const override { return "Timer"; } | 24 | std::string GetTypeName() const override { return "Timer"; } |
| 25 | std::string GetName() const override { return name; } | 25 | std::string GetName() const override { return name; } |
| @@ -49,7 +49,11 @@ public: | |||
| 49 | void Clear(); | 49 | void Clear(); |
| 50 | 50 | ||
| 51 | private: | 51 | private: |
| 52 | Timer() = default; | 52 | Timer(); |
| 53 | ~Timer() override; | ||
| 54 | |||
| 55 | /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. | ||
| 56 | Handle callback_handle; | ||
| 53 | }; | 57 | }; |
| 54 | 58 | ||
| 55 | /// Initializes the required variables for timers | 59 | /// Initializes the required variables for timers |