summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Subv2017-01-01 16:53:22 -0500
committerGravatar Subv2017-01-04 15:58:45 -0500
commite6a7723f2f4b62279cd4f6d4b48eb02a9b60ffb6 (patch)
treeb56862bb64fcf57727149de90318671ffd8afe4d /src/core
parentKernel/Synch: Do not attempt a reschedule on every syscall. (diff)
downloadyuzu-e6a7723f2f4b62279cd4f6d4b48eb02a9b60ffb6.tar.gz
yuzu-e6a7723f2f4b62279cd4f6d4b48eb02a9b60ffb6.tar.xz
yuzu-e6a7723f2f4b62279cd4f6d4b48eb02a9b60ffb6.zip
Kernel: Object ShouldWait and Acquire calls now take a thread as a parameter.
This will be useful when implementing mutex priority inheritance.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/kernel/event.cpp6
-rw-r--r--src/core/hle/kernel/event.h4
-rw-r--r--src/core/hle/kernel/kernel.cpp14
-rw-r--r--src/core/hle/kernel/kernel.h9
-rw-r--r--src/core/hle/kernel/mutex.cpp24
-rw-r--r--src/core/hle/kernel/mutex.h5
-rw-r--r--src/core/hle/kernel/semaphore.cpp6
-rw-r--r--src/core/hle/kernel/semaphore.h4
-rw-r--r--src/core/hle/kernel/server_port.cpp6
-rw-r--r--src/core/hle/kernel/server_port.h4
-rw-r--r--src/core/hle/kernel/server_session.cpp6
-rw-r--r--src/core/hle/kernel/server_session.h4
-rw-r--r--src/core/hle/kernel/thread.cpp6
-rw-r--r--src/core/hle/kernel/thread.h4
-rw-r--r--src/core/hle/kernel/timer.cpp6
-rw-r--r--src/core/hle/kernel/timer.h4
-rw-r--r--src/core/hle/svc.cpp12
17 files changed, 56 insertions, 68 deletions
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 3e116e3df..e1f42af05 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -30,12 +30,12 @@ SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {
30 return evt; 30 return evt;
31} 31}
32 32
33bool Event::ShouldWait() { 33bool Event::ShouldWait(Thread* thread) const {
34 return !signaled; 34 return !signaled;
35} 35}
36 36
37void Event::Acquire() { 37void Event::Acquire(Thread* thread) {
38 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 38 ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
39 39
40 // Release the event if it's not sticky... 40 // Release the event if it's not sticky...
41 if (reset_type != ResetType::Sticky) 41 if (reset_type != ResetType::Sticky)
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 8dcd23edb..39452bf33 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -35,8 +35,8 @@ public:
35 bool signaled; ///< Whether the event has already been signaled 35 bool signaled; ///< Whether the event has already been signaled
36 std::string name; ///< Name of event (optional) 36 std::string name; ///< Name of event (optional)
37 37
38 bool ShouldWait() override; 38 bool ShouldWait(Thread* thread) const override;
39 void Acquire() override; 39 void Acquire(Thread* thread) override;
40 40
41 void Signal(); 41 void Signal();
42 void Clear(); 42 void Clear();
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1db8e102f..ef9dbafa5 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -39,11 +39,6 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
39 thread->status == THREADSTATUS_DEAD; 39 thread->status == THREADSTATUS_DEAD;
40 }); 40 });
41 41
42 // TODO(Subv): This call should be performed inside the loop below to check if an object can be
43 // acquired by a particular thread. This is useful for things like recursive locking of Mutexes.
44 if (ShouldWait())
45 return nullptr;
46
47 Thread* candidate = nullptr; 42 Thread* candidate = nullptr;
48 s32 candidate_priority = THREADPRIO_LOWEST + 1; 43 s32 candidate_priority = THREADPRIO_LOWEST + 1;
49 44
@@ -51,9 +46,12 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
51 if (thread->current_priority >= candidate_priority) 46 if (thread->current_priority >= candidate_priority)
52 continue; 47 continue;
53 48
49 if (ShouldWait(thread.get()))
50 continue;
51
54 bool ready_to_run = 52 bool ready_to_run =
55 std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(), 53 std::none_of(thread->wait_objects.begin(), thread->wait_objects.end(),
56 [](const SharedPtr<WaitObject>& object) { return object->ShouldWait(); }); 54 [&thread](const SharedPtr<WaitObject>& object) { return object->ShouldWait(thread.get()); });
57 if (ready_to_run) { 55 if (ready_to_run) {
58 candidate = thread.get(); 56 candidate = thread.get();
59 candidate_priority = thread->current_priority; 57 candidate_priority = thread->current_priority;
@@ -66,7 +64,7 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() {
66void WaitObject::WakeupAllWaitingThreads() { 64void WaitObject::WakeupAllWaitingThreads() {
67 while (auto thread = GetHighestPriorityReadyThread()) { 65 while (auto thread = GetHighestPriorityReadyThread()) {
68 if (!thread->IsSleepingOnWaitAll()) { 66 if (!thread->IsSleepingOnWaitAll()) {
69 Acquire(); 67 Acquire(thread.get());
70 // Set the output index of the WaitSynchronizationN call to the index of this object. 68 // Set the output index of the WaitSynchronizationN call to the index of this object.
71 if (thread->wait_set_output) { 69 if (thread->wait_set_output) {
72 thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(this)); 70 thread->SetWaitSynchronizationOutput(thread->GetWaitObjectIndex(this));
@@ -74,7 +72,7 @@ void WaitObject::WakeupAllWaitingThreads() {
74 } 72 }
75 } else { 73 } else {
76 for (auto& object : thread->wait_objects) { 74 for (auto& object : thread->wait_objects) {
77 object->Acquire(); 75 object->Acquire(thread.get());
78 object->RemoveWaitingThread(thread.get()); 76 object->RemoveWaitingThread(thread.get());
79 } 77 }
80 // Note: This case doesn't update the output index of WaitSynchronizationN. 78 // Note: This case doesn't update the output index of WaitSynchronizationN.
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 9503e7d04..67eae93f2 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -132,13 +132,14 @@ using SharedPtr = boost::intrusive_ptr<T>;
132class WaitObject : public Object { 132class WaitObject : public Object {
133public: 133public:
134 /** 134 /**
135 * Check if the current thread should wait until the object is available 135 * Check if the specified thread should wait until the object is available
136 * @param thread The thread about which we're deciding.
136 * @return True if the current thread should wait due to this object being unavailable 137 * @return True if the current thread should wait due to this object being unavailable
137 */ 138 */
138 virtual bool ShouldWait() = 0; 139 virtual bool ShouldWait(Thread* thread) const = 0;
139 140
140 /// Acquire/lock the object if it is available 141 /// Acquire/lock the object for the specified thread if it is available
141 virtual void Acquire() = 0; 142 virtual void Acquire(Thread* thread) = 0;
142 143
143 /** 144 /**
144 * Add a thread to wait on this object 145 * Add a thread to wait on this object
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 8d92a9b8e..072e4e7c1 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -40,31 +40,19 @@ SharedPtr<Mutex> Mutex::Create(bool initial_locked, std::string name) {
40 mutex->name = std::move(name); 40 mutex->name = std::move(name);
41 mutex->holding_thread = nullptr; 41 mutex->holding_thread = nullptr;
42 42
43 // Acquire mutex with current thread if initialized as locked... 43 // Acquire mutex with current thread if initialized as locked
44 if (initial_locked) 44 if (initial_locked)
45 mutex->Acquire(); 45 mutex->Acquire(GetCurrentThread());
46 46
47 return mutex; 47 return mutex;
48} 48}
49 49
50bool Mutex::ShouldWait() { 50bool Mutex::ShouldWait(Thread* thread) const {
51 auto thread = GetCurrentThread(); 51 return lock_count > 0 && thread != holding_thread;
52 bool wait = lock_count > 0 && holding_thread != thread;
53
54 // If the holding thread of the mutex is lower priority than this thread, that thread should
55 // temporarily inherit this thread's priority
56 if (wait && thread->current_priority < holding_thread->current_priority)
57 holding_thread->BoostPriority(thread->current_priority);
58
59 return wait;
60}
61
62void Mutex::Acquire() {
63 Acquire(GetCurrentThread());
64} 52}
65 53
66void Mutex::Acquire(SharedPtr<Thread> thread) { 54void Mutex::Acquire(Thread* thread) {
67 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 55 ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
68 56
69 // Actually "acquire" the mutex only if we don't already have it... 57 // Actually "acquire" the mutex only if we don't already have it...
70 if (lock_count == 0) { 58 if (lock_count == 0) {
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 53c3dc1f1..98b3d40b5 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -38,8 +38,9 @@ public:
38 std::string name; ///< Name of mutex (optional) 38 std::string name; ///< Name of mutex (optional)
39 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex 39 SharedPtr<Thread> holding_thread; ///< Thread that has acquired the mutex
40 40
41 bool ShouldWait() override; 41 bool ShouldWait(Thread* thread) const override;
42 void Acquire() override; 42 void Acquire(Thread* thread) override;
43
43 44
44 /** 45 /**
45 * Acquires the specified mutex for the specified thread 46 * Acquires the specified mutex for the specified thread
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index bf7600780..5e6139265 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -30,12 +30,12 @@ ResultVal<SharedPtr<Semaphore>> Semaphore::Create(s32 initial_count, s32 max_cou
30 return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore)); 30 return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore));
31} 31}
32 32
33bool Semaphore::ShouldWait() { 33bool Semaphore::ShouldWait(Thread* thread) const {
34 return available_count <= 0; 34 return available_count <= 0;
35} 35}
36 36
37void Semaphore::Acquire() { 37void Semaphore::Acquire(Thread* thread) {
38 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 38 ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
39 --available_count; 39 --available_count;
40} 40}
41 41
diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h
index e01908a25..cde94f7cc 100644
--- a/src/core/hle/kernel/semaphore.h
+++ b/src/core/hle/kernel/semaphore.h
@@ -39,8 +39,8 @@ public:
39 s32 available_count; ///< Number of free slots left in the semaphore 39 s32 available_count; ///< Number of free slots left in the semaphore
40 std::string name; ///< Name of semaphore (optional) 40 std::string name; ///< Name of semaphore (optional)
41 41
42 bool ShouldWait() override; 42 bool ShouldWait(Thread* thread) const override;
43 void Acquire() override; 43 void Acquire(Thread* thread) override;
44 44
45 /** 45 /**
46 * Releases a certain number of slots from a semaphore. 46 * Releases a certain number of slots from a semaphore.
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index 6c19aa7c0..fd3bbbcad 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -14,13 +14,13 @@ namespace Kernel {
14ServerPort::ServerPort() {} 14ServerPort::ServerPort() {}
15ServerPort::~ServerPort() {} 15ServerPort::~ServerPort() {}
16 16
17bool ServerPort::ShouldWait() { 17bool ServerPort::ShouldWait(Thread* thread) const {
18 // If there are no pending sessions, we wait until a new one is added. 18 // If there are no pending sessions, we wait until a new one is added.
19 return pending_sessions.size() == 0; 19 return pending_sessions.size() == 0;
20} 20}
21 21
22void ServerPort::Acquire() { 22void ServerPort::Acquire(Thread* thread) {
23 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 23 ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
24} 24}
25 25
26std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair( 26std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index b0f8df62c..6f8bdb6a9 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -53,8 +53,8 @@ public:
53 /// ServerSessions created from this port inherit a reference to this handler. 53 /// ServerSessions created from this port inherit a reference to this handler.
54 std::shared_ptr<Service::SessionRequestHandler> hle_handler; 54 std::shared_ptr<Service::SessionRequestHandler> hle_handler;
55 55
56 bool ShouldWait() override; 56 bool ShouldWait(Thread* thread) const override;
57 void Acquire() override; 57 void Acquire(Thread* thread) override;
58 58
59private: 59private:
60 ServerPort(); 60 ServerPort();
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 146458c1c..9447ff236 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -29,12 +29,12 @@ ResultVal<SharedPtr<ServerSession>> ServerSession::Create(
29 return MakeResult<SharedPtr<ServerSession>>(std::move(server_session)); 29 return MakeResult<SharedPtr<ServerSession>>(std::move(server_session));
30} 30}
31 31
32bool ServerSession::ShouldWait() { 32bool ServerSession::ShouldWait(Thread* thread) const {
33 return !signaled; 33 return !signaled;
34} 34}
35 35
36void ServerSession::Acquire() { 36void ServerSession::Acquire(Thread* thread) {
37 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 37 ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
38 signaled = false; 38 signaled = false;
39} 39}
40 40
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index 458284a5d..c088b9a19 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -57,9 +57,9 @@ public:
57 */ 57 */
58 ResultCode HandleSyncRequest(); 58 ResultCode HandleSyncRequest();
59 59
60 bool ShouldWait() override; 60 bool ShouldWait(Thread* thread) const override;
61 61
62 void Acquire() override; 62 void Acquire(Thread* thread) override;
63 63
64 std::string name; ///< The name of this session (optional) 64 std::string name; ///< The name of this session (optional)
65 bool signaled; ///< Whether there's new data available to this ServerSession 65 bool signaled; ///< Whether there's new data available to this ServerSession
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 5fb95dada..7d03a2cf7 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -27,12 +27,12 @@ namespace Kernel {
27/// Event type for the thread wake up event 27/// Event type for the thread wake up event
28static int ThreadWakeupEventType; 28static int ThreadWakeupEventType;
29 29
30bool Thread::ShouldWait() { 30bool Thread::ShouldWait(Thread* thread) const {
31 return status != THREADSTATUS_DEAD; 31 return status != THREADSTATUS_DEAD;
32} 32}
33 33
34void Thread::Acquire() { 34void Thread::Acquire(Thread* thread) {
35 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 35 ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
36} 36}
37 37
38// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing 38// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index c77ac644d..f2bc1ec9c 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -72,8 +72,8 @@ public:
72 return HANDLE_TYPE; 72 return HANDLE_TYPE;
73 } 73 }
74 74
75 bool ShouldWait() override; 75 bool ShouldWait(Thread* thread) const override;
76 void Acquire() override; 76 void Acquire(Thread* thread) override;
77 77
78 /** 78 /**
79 * Gets the thread's current priority 79 * Gets the thread's current priority
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index b50cf520d..8f2bc4c7f 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -39,12 +39,12 @@ SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
39 return timer; 39 return timer;
40} 40}
41 41
42bool Timer::ShouldWait() { 42bool Timer::ShouldWait(Thread* thread) const {
43 return !signaled; 43 return !signaled;
44} 44}
45 45
46void Timer::Acquire() { 46void Timer::Acquire(Thread* thread) {
47 ASSERT_MSG(!ShouldWait(), "object unavailable!"); 47 ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
48 48
49 if (reset_type == ResetType::OneShot) 49 if (reset_type == ResetType::OneShot)
50 signaled = false; 50 signaled = false;
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index 18ea0236b..2e3b31b23 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -39,8 +39,8 @@ public:
39 u64 initial_delay; ///< The delay until the timer fires for the first time 39 u64 initial_delay; ///< The delay until the timer fires for the first time
40 u64 interval_delay; ///< The delay until the timer fires after the first time 40 u64 interval_delay; ///< The delay until the timer fires after the first time
41 41
42 bool ShouldWait() override; 42 bool ShouldWait(Thread* thread) const override;
43 void Acquire() override; 43 void Acquire(Thread* thread) override;
44 44
45 /** 45 /**
46 * Starts the timer, with the specified initial delay and interval. 46 * Starts the timer, with the specified initial delay and interval.
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 5b538be22..159ac0bf6 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -272,7 +272,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds)
272 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, 272 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle,
273 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); 273 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds);
274 274
275 if (object->ShouldWait()) { 275 if (object->ShouldWait(thread)) {
276 276
277 if (nano_seconds == 0) 277 if (nano_seconds == 0)
278 return ERR_SYNC_TIMEOUT; 278 return ERR_SYNC_TIMEOUT;
@@ -294,7 +294,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds)
294 return ERR_SYNC_TIMEOUT; 294 return ERR_SYNC_TIMEOUT;
295 } 295 }
296 296
297 object->Acquire(); 297 object->Acquire(thread);
298 298
299 return RESULT_SUCCESS; 299 return RESULT_SUCCESS;
300} 300}
@@ -336,11 +336,11 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
336 if (wait_all) { 336 if (wait_all) {
337 bool all_available = 337 bool all_available =
338 std::all_of(objects.begin(), objects.end(), 338 std::all_of(objects.begin(), objects.end(),
339 [](const ObjectPtr& object) { return !object->ShouldWait(); }); 339 [thread](const ObjectPtr& object) { return !object->ShouldWait(thread); });
340 if (all_available) { 340 if (all_available) {
341 // We can acquire all objects right now, do so. 341 // We can acquire all objects right now, do so.
342 for (auto& object : objects) 342 for (auto& object : objects)
343 object->Acquire(); 343 object->Acquire(thread);
344 // Note: In this case, the `out` parameter is not set, 344 // Note: In this case, the `out` parameter is not set,
345 // and retains whatever value it had before. 345 // and retains whatever value it had before.
346 return RESULT_SUCCESS; 346 return RESULT_SUCCESS;
@@ -380,12 +380,12 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
380 } else { 380 } else {
381 // Find the first object that is acquirable in the provided list of objects 381 // Find the first object that is acquirable in the provided list of objects
382 auto itr = std::find_if(objects.begin(), objects.end(), 382 auto itr = std::find_if(objects.begin(), objects.end(),
383 [](const ObjectPtr& object) { return !object->ShouldWait(); }); 383 [thread](const ObjectPtr& object) { return !object->ShouldWait(thread); });
384 384
385 if (itr != objects.end()) { 385 if (itr != objects.end()) {
386 // We found a ready object, acquire it and set the result value 386 // We found a ready object, acquire it and set the result value
387 Kernel::WaitObject* object = itr->get(); 387 Kernel::WaitObject* object = itr->get();
388 object->Acquire(); 388 object->Acquire(thread);
389 *out = std::distance(objects.begin(), itr); 389 *out = std::distance(objects.begin(), itr);
390 return RESULT_SUCCESS; 390 return RESULT_SUCCESS;
391 } 391 }