diff options
| author | 2014-06-05 22:35:36 -0400 | |
|---|---|---|
| committer | 2014-06-13 09:51:02 -0400 | |
| commit | f5c7c1543434e25a215286e6db5e71c055ba48cf (patch) | |
| tree | 488a3fd0c01051453c6f8ccc4867f6b6ea3f2843 /src/core/hle/kernel/event.cpp | |
| parent | qt: updated disassembler to show 2X as many instructions (diff) | |
| download | yuzu-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.cpp | 71 |
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 | ||
| 13 | namespace Kernel { | 15 | namespace 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 | */ | ||
| 71 | Result 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 | */ |
| 80 | Result SetPermanentLock(Handle handle, const bool permanent_locked) { | 104 | Result 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 | */ |
| 95 | Result ClearEvent(Handle handle) { | 134 | Result 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 | /** |