[mlir:async] Fix deadlock in async runtime await-and-execute functions
authorEugene Zhulenev <ezhulenev@google.com>
Wed, 27 Jan 2021 12:27:21 +0000 (04:27 -0800)
committerEugene Zhulenev <ezhulenev@google.com>
Wed, 27 Jan 2021 13:08:53 +0000 (05:08 -0800)
`emplace???` functions running concurrently can set the ready flag and then pending awaiter will never be executed

Differential Revision: https://reviews.llvm.org/D95517

mlir/lib/ExecutionEngine/AsyncRuntime.cpp

index e38ebf9..c5978eb 100644 (file)
@@ -320,10 +320,11 @@ extern "C" void mlirAsyncRuntimeAwaitTokenAndExecute(AsyncToken *token,
                                                      CoroHandle handle,
                                                      CoroResume resume) {
   auto execute = [handle, resume]() { (*resume)(handle); };
+  std::unique_lock<std::mutex> lock(token->mu);
   if (token->ready) {
+    lock.unlock();
     execute();
   } else {
-    std::unique_lock<std::mutex> lock(token->mu);
     token->awaiters.push_back([execute]() { execute(); });
   }
 }
@@ -332,10 +333,11 @@ extern "C" void mlirAsyncRuntimeAwaitValueAndExecute(AsyncValue *value,
                                                      CoroHandle handle,
                                                      CoroResume resume) {
   auto execute = [handle, resume]() { (*resume)(handle); };
+  std::unique_lock<std::mutex> lock(value->mu);
   if (value->ready) {
+    lock.unlock();
     execute();
   } else {
-    std::unique_lock<std::mutex> lock(value->mu);
     value->awaiters.push_back([execute]() { execute(); });
   }
 }
@@ -344,10 +346,11 @@ extern "C" void mlirAsyncRuntimeAwaitAllInGroupAndExecute(AsyncGroup *group,
                                                           CoroHandle handle,
                                                           CoroResume resume) {
   auto execute = [handle, resume]() { (*resume)(handle); };
+  std::unique_lock<std::mutex> lock(group->mu);
   if (group->pendingTokens == 0) {
+    lock.unlock();
     execute();
   } else {
-    std::unique_lock<std::mutex> lock(group->mu);
     group->awaiters.push_back([execute]() { execute(); });
   }
 }