summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/event.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2015-01-21 21:09:47 -0500
committerGravatar bunnei2015-01-21 21:09:47 -0500
commit24a63662ba6c7816001bba399e85d8c131a89489 (patch)
treea9959e69723b4f19550834171c962ec06c9e34b7 /src/core/hle/kernel/event.cpp
parentMerge pull request #491 from archshift/hidspvr (diff)
parentWaitSynchronization: Added a result code for invalid result, fixed bug. (diff)
downloadyuzu-24a63662ba6c7816001bba399e85d8c131a89489.tar.gz
yuzu-24a63662ba6c7816001bba399e85d8c131a89489.tar.xz
yuzu-24a63662ba6c7816001bba399e85d8c131a89489.zip
Merge pull request #495 from bunnei/fix-waitsynch
Fix WaitSynchronization
Diffstat (limited to 'src/core/hle/kernel/event.cpp')
-rw-r--r--src/core/hle/kernel/event.cpp106
1 files changed, 20 insertions, 86 deletions
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 271190dbe..a48125965 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -14,7 +14,7 @@
14 14
15namespace Kernel { 15namespace Kernel {
16 16
17class Event : public Object { 17class Event : public WaitObject {
18public: 18public:
19 std::string GetTypeName() const override { return "Event"; } 19 std::string GetTypeName() const override { return "Event"; }
20 std::string GetName() const override { return name; } 20 std::string GetName() const override { return name; }
@@ -25,99 +25,40 @@ public:
25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization 25 ResetType intitial_reset_type; ///< ResetType specified at Event initialization
26 ResetType reset_type; ///< Current ResetType 26 ResetType reset_type; ///< Current ResetType
27 27
28 bool locked; ///< Event signal wait 28 bool signaled; ///< Whether the event has already been signaled
29 bool permanent_locked; ///< Hack - to set event permanent state (for easy passthrough)
30 std::vector<Handle> waiting_threads; ///< Threads that are waiting for the event
31 std::string name; ///< Name of event (optional) 29 std::string name; ///< Name of event (optional)
32 30
33 ResultVal<bool> WaitSynchronization() override { 31 bool ShouldWait() override {
34 bool wait = locked; 32 return !signaled;
35 if (locked) {
36 Handle thread = GetCurrentThread()->GetHandle();
37 if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
38 waiting_threads.push_back(thread);
39 }
40 Kernel::WaitCurrentThread(WAITTYPE_EVENT, this);
41 }
42 if (reset_type != RESETTYPE_STICKY && !permanent_locked) {
43 locked = true;
44 }
45 return MakeResult<bool>(wait);
46 } 33 }
47};
48
49/**
50 * Hackish function to set an events permanent lock state, used to pass through synch blocks
51 * @param handle Handle to event to change
52 * @param permanent_locked Boolean permanent locked value to set event
53 * @return Result of operation, 0 on success, otherwise error code
54 */
55ResultCode SetPermanentLock(Handle handle, const bool permanent_locked) {
56 Event* evt = g_handle_table.Get<Event>(handle).get();
57 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
58
59 evt->permanent_locked = permanent_locked;
60 return RESULT_SUCCESS;
61}
62 34
63/** 35 void Acquire() override {
64 * Changes whether an event is locked or not 36 _assert_msg_(Kernel, !ShouldWait(), "object unavailable!");
65 * @param handle Handle to event to change
66 * @param locked Boolean locked value to set event
67 * @return Result of operation, 0 on success, otherwise error code
68 */
69ResultCode SetEventLocked(const Handle handle, const bool locked) {
70 Event* evt = g_handle_table.Get<Event>(handle).get();
71 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
72 37
73 if (!evt->permanent_locked) { 38 // Release the event if it's not sticky...
74 evt->locked = locked; 39 if (reset_type != RESETTYPE_STICKY)
40 signaled = false;
75 } 41 }
76 return RESULT_SUCCESS; 42};
77}
78 43
79/**
80 * Signals an event
81 * @param handle Handle to event to signal
82 * @return Result of operation, 0 on success, otherwise error code
83 */
84ResultCode SignalEvent(const Handle handle) { 44ResultCode SignalEvent(const Handle handle) {
85 Event* evt = g_handle_table.Get<Event>(handle).get(); 45 Event* evt = g_handle_table.Get<Event>(handle).get();
86 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 46 if (evt == nullptr)
87 47 return InvalidHandle(ErrorModule::Kernel);
88 // Resume threads waiting for event to signal 48
89 bool event_caught = false; 49 evt->signaled = true;
90 for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { 50 evt->WakeupAllWaitingThreads();
91 Thread* thread = Kernel::g_handle_table.Get<Thread>(evt->waiting_threads[i]).get();
92 if (thread != nullptr)
93 thread->ResumeFromWait();
94
95 // If any thread is signalled awake by this event, assume the event was "caught" and reset
96 // the event. This will result in the next thread waiting on the event to block. Otherwise,
97 // the event will not be reset, and the next thread to call WaitSynchronization on it will
98 // not block. Not sure if this is correct behavior, but it seems to work.
99 event_caught = true;
100 }
101 evt->waiting_threads.clear();
102 51
103 if (!evt->permanent_locked) {
104 evt->locked = event_caught;
105 }
106 return RESULT_SUCCESS; 52 return RESULT_SUCCESS;
107} 53}
108 54
109/**
110 * Clears an event
111 * @param handle Handle to event to clear
112 * @return Result of operation, 0 on success, otherwise error code
113 */
114ResultCode ClearEvent(Handle handle) { 55ResultCode ClearEvent(Handle handle) {
115 Event* evt = g_handle_table.Get<Event>(handle).get(); 56 Event* evt = g_handle_table.Get<Event>(handle).get();
116 if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel); 57 if (evt == nullptr)
58 return InvalidHandle(ErrorModule::Kernel);
59
60 evt->signaled = false;
117 61
118 if (!evt->permanent_locked) {
119 evt->locked = true;
120 }
121 return RESULT_SUCCESS; 62 return RESULT_SUCCESS;
122} 63}
123 64
@@ -134,20 +75,13 @@ Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string
134 // TOOD(yuriks): Fix error reporting 75 // TOOD(yuriks): Fix error reporting
135 handle = Kernel::g_handle_table.Create(evt).ValueOr(INVALID_HANDLE); 76 handle = Kernel::g_handle_table.Create(evt).ValueOr(INVALID_HANDLE);
136 77
137 evt->locked = true; 78 evt->signaled = false;
138 evt->permanent_locked = false;
139 evt->reset_type = evt->intitial_reset_type = reset_type; 79 evt->reset_type = evt->intitial_reset_type = reset_type;
140 evt->name = name; 80 evt->name = name;
141 81
142 return evt; 82 return evt;
143} 83}
144 84
145/**
146 * Creates an event
147 * @param reset_type ResetType describing how to create event
148 * @param name Optional name of event
149 * @return Handle to newly created Event object
150 */
151Handle CreateEvent(const ResetType reset_type, const std::string& name) { 85Handle CreateEvent(const ResetType reset_type, const std::string& name) {
152 Handle handle; 86 Handle handle;
153 Event* evt = CreateEvent(handle, reset_type, name); 87 Event* evt = CreateEvent(handle, reset_type, name);