diff options
| author | 2015-01-21 21:09:47 -0500 | |
|---|---|---|
| committer | 2015-01-21 21:09:47 -0500 | |
| commit | 24a63662ba6c7816001bba399e85d8c131a89489 (patch) | |
| tree | a9959e69723b4f19550834171c962ec06c9e34b7 /src/core/hle/kernel/event.cpp | |
| parent | Merge pull request #491 from archshift/hidspvr (diff) | |
| parent | WaitSynchronization: Added a result code for invalid result, fixed bug. (diff) | |
| download | yuzu-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.cpp | 106 |
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 | ||
| 15 | namespace Kernel { | 15 | namespace Kernel { |
| 16 | 16 | ||
| 17 | class Event : public Object { | 17 | class Event : public WaitObject { |
| 18 | public: | 18 | public: |
| 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 | */ | ||
| 55 | ResultCode 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 | */ | ||
| 69 | ResultCode 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 | */ | ||
| 84 | ResultCode SignalEvent(const Handle handle) { | 44 | ResultCode 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 | */ | ||
| 114 | ResultCode ClearEvent(Handle handle) { | 55 | ResultCode 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 | */ | ||
| 151 | Handle CreateEvent(const ResetType reset_type, const std::string& name) { | 85 | Handle 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); |