libstrat: improve waitable manager cancelsync semantics

This commit is contained in:
Michael Scire 2018-11-07 12:42:06 -08:00
parent 952ee4227d
commit 2894989eb7

View file

@ -60,6 +60,7 @@ class WaitableManager : public SessionManagerBase {
HosMutex process_lock;
HosMutex signal_lock;
HosMutex add_lock;
HosMutex cur_thread_lock;
bool has_new_waitables = false;
IWaitable *next_signaled = nullptr;
@ -97,7 +98,7 @@ class WaitableManager : public SessionManagerBase {
}
virtual void CancelSynchronization() {
svcCancelSynchronization(this->cur_thread_handle);
svcCancelSynchronization(GetProcessingThreadHandle());
}
virtual void NotifySignaled(IWaitable *w) override {
@ -122,6 +123,16 @@ class WaitableManager : public SessionManagerBase {
ProcessLoop(this);
}
private:
void SetProcessingThreadHandle(Handle h) {
std::scoped_lock<HosMutex> lk{this->cur_thread_lock};
this->cur_thread_handle = h;
}
Handle GetProcessingThreadHandle() {
std::scoped_lock<HosMutex> lk{this->cur_thread_lock};
return this->cur_thread_handle;
}
static void ProcessLoop(void *t) {
WaitableManager *this_ptr = (WaitableManager *)t;
while (true) {
@ -141,17 +152,20 @@ class WaitableManager : public SessionManagerBase {
IWaitable *GetWaitable() {
std::scoped_lock lk{this->process_lock};
/* Set processing thread handle while in scope. */
SetProcessingThreadHandle(GetCurrentThreadHandle());
ON_SCOPE_EXIT {
SetProcessingThreadHandle(INVALID_HANDLE);
};
/* Prepare variables for result. */
this->next_signaled = nullptr;
IWaitable *result = nullptr;
/* Add new waitables, if any. */
AddWaitablesInternal();
this->cur_thread_handle = GetCurrentThreadHandle();
ON_SCOPE_EXIT {
this->cur_thread_handle = INVALID_HANDLE;
};
/* First, see if anything's already signaled. */
for (auto &w : this->waitables) {
if (w->IsSignaled()) {