[dawn][native] Call ExecutionQueue tasks without lock.

- Move out all the callbacks before calling them in order to
  ensure that we don't have lock inversion issues or deadlocks
  as a result of re-entrancy.

Bug: 417802523
Change-Id: I542f03f6aa0abab9ce7da95cd4f1e4e4b009b1a5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/246534
Auto-Submit: Loko Kung <lokokung@google.com>
Reviewed-by: Shrek Shao <shrekshao@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
diff --git a/src/dawn/native/ExecutionQueue.cpp b/src/dawn/native/ExecutionQueue.cpp
index f131ff2..3fb78aa 100644
--- a/src/dawn/native/ExecutionQueue.cpp
+++ b/src/dawn/native/ExecutionQueue.cpp
@@ -29,6 +29,7 @@
 
 #include <atomic>
 #include <utility>
+#include <vector>
 
 namespace dawn::native {
 
@@ -78,12 +79,17 @@
            !mCompletedSerial.compare_exchange_weak(current, uint64_t(completedSerial),
                                                    std::memory_order_acq_rel)) {
     }
+
+    std::vector<Task> pending;
     mWaitingTasks.Use([&](auto tasks) {
         for (auto task : tasks->IterateUpTo(completedSerial)) {
-            task();
+            pending.push_back(std::move(task));
         }
         tasks->ClearUpTo(completedSerial);
     });
+    for (auto task : pending) {
+        task();
+    }
 }
 
 MaybeError ExecutionQueueBase::EnsureCommandsFlushed(ExecutionSerial serial) {
diff --git a/src/dawn/tests/end2end/BufferTests.cpp b/src/dawn/tests/end2end/BufferTests.cpp
index 379e176..a351ff2 100644
--- a/src/dawn/tests/end2end/BufferTests.cpp
+++ b/src/dawn/tests/end2end/BufferTests.cpp
@@ -62,13 +62,6 @@
                                  GetParam().mFutureCallbackMode == wgpu::CallbackMode::WaitAnyOnly);
     }
 
-    bool IsSpontaneous() const {
-        return GetParam().mFutureCallbackMode == wgpu::CallbackMode::AllowSpontaneous;
-    }
-    bool IsProcessEvents() const {
-        return GetParam().mFutureCallbackMode == wgpu::CallbackMode::AllowProcessEvents;
-    }
-
     void MapAsyncAndWait(const wgpu::Buffer& buffer,
                          wgpu::MapMode mode,
                          size_t offset,
@@ -241,10 +234,6 @@
 
 // Test that GetConstMappedRange works inside map-read callback
 TEST_P(BufferMappingTests, MapRead_InCallback) {
-    // TODO(crbug.com/417802523): There is a Lock inversion bug when processing events in the
-    // callback.
-    DAWN_TEST_UNSUPPORTED_IF(IsSpontaneous() || IsProcessEvents());
-
     constexpr size_t kBufferSize = 12;
     wgpu::Buffer buffer = CreateMapReadBuffer(kBufferSize);
 
@@ -562,10 +551,6 @@
 
 // Test that Get(Const)MappedRange work inside map-write callback.
 TEST_P(BufferMappingTests, MapWrite_InCallbackDefault) {
-    // TODO(crbug.com/417802523): There is a Lock inversion bug when processing events in the
-    // callback.
-    DAWN_TEST_UNSUPPORTED_IF(IsSpontaneous() || IsProcessEvents());
-
     wgpu::Buffer buffer = CreateMapWriteBuffer(4);
 
     static constexpr uint32_t myData = 2934875;
@@ -588,10 +573,6 @@
 
 // Test that Get(Const)MappedRange with range work inside map-write callback.
 TEST_P(BufferMappingTests, MapWrite_InCallbackRange) {
-    // TODO(crbug.com/417802523): There is a Lock inversion bug when processing events in the
-    // callback.
-    DAWN_TEST_UNSUPPORTED_IF(IsSpontaneous() || IsProcessEvents());
-
     wgpu::Buffer buffer = CreateMapWriteBuffer(4);
 
     static constexpr uint32_t myData = 2934875;