summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/event.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2014-06-05 22:35:36 -0400
committerGravatar bunnei2014-06-13 09:51:02 -0400
commitf5c7c1543434e25a215286e6db5e71c055ba48cf (patch)
tree488a3fd0c01051453c6f8ccc4867f6b6ea3f2843 /src/core/hle/kernel/event.cpp
parentqt: updated disassembler to show 2X as many instructions (diff)
downloadyuzu-f5c7c1543434e25a215286e6db5e71c055ba48cf.tar.gz
yuzu-f5c7c1543434e25a215286e6db5e71c055ba48cf.tar.xz
yuzu-f5c7c1543434e25a215286e6db5e71c055ba48cf.zip
Kernel: Added real support for thread and event blocking
- SVC: Added ExitThread support - SVC: Added SignalEvent support - Thread: Added WAITTYPE_EVENT for waiting threads for event signals - Thread: Added support for blocking on other threads to finish (e.g. Thread::Join) - Thread: Added debug function for printing current threads ready for execution - Thread: Removed hack/broken thread ready state code from Kernel::Reschedule - Mutex: Moved WaitCurrentThread from SVC to Mutex::WaitSynchronization - Event: Added support for blocking threads on event signalling Kernel: Added missing algorithm #include for use of std::find on non-Windows platforms.
Diffstat (limited to 'src/core/hle/kernel/event.cpp')
-rw-r--r--src/core/hle/kernel/event.cpp71
1 files changed, 59 insertions, 12 deletions
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 70e50115d..787e9f5fd 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -3,12 +3,14 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <map> 5#include <map>
6#include <algorithm>
6#include <vector> 7#include <vector>
7 8
8#include "common/common.h" 9#include "common/common.h"
9 10
10#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
11#include "core/hle/kernel/event.h" 12#include "core/hle/kernel/event.h"
13#include "core/hle/kernel/thread.h"
12 14
13namespace Kernel { 15namespace Kernel {
14 16
@@ -20,12 +22,13 @@ public:
20 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; } 22 static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Event; }
21 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; } 23 Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Event; }
22 24
23 ResetType intitial_reset_type; ///< ResetType specified at Event initialization 25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization
24 ResetType reset_type; ///< Current ResetType 26 ResetType reset_type; ///< Current ResetType
25 27
26 bool locked; ///< Current locked state 28 bool locked; ///< Event signal wait
27 bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough) 29 bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough)
28 std::string name; ///< Name of event (optional) 30 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the event
31 std::string name; ///< Name of event (optional)
29 32
30 /** 33 /**
31 * Synchronize kernel object 34 * Synchronize kernel object
@@ -44,8 +47,14 @@ public:
44 * @return Result of operation, 0 on success, otherwise error code 47 * @return Result of operation, 0 on success, otherwise error code
45 */ 48 */
46 Result WaitSynchronization(bool* wait) { 49 Result WaitSynchronization(bool* wait) {
47 // TODO(bunnei): ImplementMe
48 *wait = locked; 50 *wait = locked;
51 if (locked) {
52 Handle thread = GetCurrentThreadHandle();
53 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
54 waiting_threads.push_back(thread);
55 }
56 Kernel::WaitCurrentThread(WAITTYPE_EVENT);
57 }
49 if (reset_type != RESETTYPE_STICKY && !permanent_locked) { 58 if (reset_type != RESETTYPE_STICKY && !permanent_locked) {
50 locked = true; 59 locked = true;
51 } 60 }
@@ -54,6 +63,22 @@ public:
54}; 63};
55 64
56/** 65/**
66 * Hackish function to set an events permanent lock state, used to pass through synch blocks
67 * @param handle Handle to event to change
68 * @param permanent_locked Boolean permanent locked value to set event
69 * @return Result of operation, 0 on success, otherwise error code
70 */
71Result SetPermanentLock(Handle handle, const bool permanent_locked) {
72 Event* evt = g_object_pool.GetFast<Event>(handle);
73 if (!evt) {
74 ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle);
75 return -1;
76 }
77 evt->permanent_locked = permanent_locked;
78 return 0;
79}
80
81/**
57 * Changes whether an event is locked or not 82 * Changes whether an event is locked or not
58 * @param handle Handle to event to change 83 * @param handle Handle to event to change
59 * @param locked Boolean locked value to set event 84 * @param locked Boolean locked value to set event
@@ -72,18 +97,32 @@ Result SetEventLocked(const Handle handle, const bool locked) {
72} 97}
73 98
74/** 99/**
75 * Hackish function to set an events permanent lock state, used to pass through synch blocks 100 * Signals an event
76 * @param handle Handle to event to change 101 * @param handle Handle to event to signal
77 * @param permanent_locked Boolean permanent locked value to set event
78 * @return Result of operation, 0 on success, otherwise error code 102 * @return Result of operation, 0 on success, otherwise error code
79 */ 103 */
80Result SetPermanentLock(Handle handle, const bool permanent_locked) { 104Result SignalEvent(const Handle handle) {
81 Event* evt = g_object_pool.GetFast<Event>(handle); 105 Event* evt = g_object_pool.GetFast<Event>(handle);
82 if (!evt) { 106 if (!evt) {
83 ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle); 107 ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle);
84 return -1; 108 return -1;
85 } 109 }
86 evt->permanent_locked = permanent_locked; 110 // Resume threads waiting for event to signal
111 bool event_caught = false;
112 for (size_t i = 0; i < evt->waiting_threads.size(); ++i) {
113 ResumeThreadFromWait( evt->waiting_threads[i]);
114
115 // If any thread is signalled awake by this event, assume the event was "caught" and reset
116 // the event. This will result in the next thread waiting on the event to block. Otherwise,
117 // the event will not be reset, and the next thread to call WaitSynchronization on it will
118 // not block. Not sure if this is correct behavior, but it seems to work.
119 event_caught = true;
120 }
121 evt->waiting_threads.clear();
122
123 if (!evt->permanent_locked) {
124 evt->locked = event_caught;
125 }
87 return 0; 126 return 0;
88} 127}
89 128
@@ -93,7 +132,15 @@ Result SetPermanentLock(Handle handle, const bool permanent_locked) {
93 * @return Result of operation, 0 on success, otherwise error code 132 * @return Result of operation, 0 on success, otherwise error code
94 */ 133 */
95Result ClearEvent(Handle handle) { 134Result ClearEvent(Handle handle) {
96 return SetEventLocked(handle, true); 135 Event* evt = g_object_pool.GetFast<Event>(handle);
136 if (!evt) {
137 ERROR_LOG(KERNEL, "called with unknown handle=0x%08X", handle);
138 return -1;
139 }
140 if (!evt->permanent_locked) {
141 evt->locked = true;
142 }
143 return 0;
97} 144}
98 145
99/** 146/**