aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/test/wasm-api-tests/threads.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/wasm-api-tests/threads.cc')
-rw-r--r--deps/v8/test/wasm-api-tests/threads.cc105
1 files changed, 105 insertions, 0 deletions
diff --git a/deps/v8/test/wasm-api-tests/threads.cc b/deps/v8/test/wasm-api-tests/threads.cc
new file mode 100644
index 0000000000..c93afc4a89
--- /dev/null
+++ b/deps/v8/test/wasm-api-tests/threads.cc
@@ -0,0 +1,105 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "test/wasm-api-tests/wasm-api-test.h"
+
+#include <mutex>
+#include <thread>
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+using ::wasm::Shared;
+
+namespace {
+
+const int kNumThreads = 10;
+const int kIterationsPerThread = 3;
+int g_traces;
+
+own<Trap*> Callback(void* env, const Val args[], Val results[]) {
+ std::lock_guard<std::mutex> lock(*reinterpret_cast<std::mutex*>(env));
+ g_traces += args[0].i32();
+ return nullptr;
+}
+
+void Main(Engine* engine, Shared<Module>* shared, std::mutex* mutex, int id) {
+ own<Store*> store = Store::make(engine);
+ own<Module*> module = Module::obtain(store.get(), shared);
+ EXPECT_NE(nullptr, module.get());
+ for (int i = 0; i < kIterationsPerThread; i++) {
+ std::this_thread::sleep_for(std::chrono::microseconds(100));
+
+ // Create imports.
+ own<FuncType*> func_type = FuncType::make(
+ vec<ValType*>::make(ValType::make(::wasm::I32)), vec<ValType*>::make());
+ own<Func*> func = Func::make(store.get(), func_type.get(), Callback, mutex);
+ own<::wasm::GlobalType*> global_type =
+ ::wasm::GlobalType::make(ValType::make(::wasm::I32), ::wasm::CONST);
+ own<Global*> global =
+ Global::make(store.get(), global_type.get(), Val::i32(id));
+
+ // Instantiate and run.
+ // With the current implementation of the WasmModuleBuilder, global
+ // imports always come before function imports, regardless of the
+ // order of builder()->Add*Import() calls below.
+ Extern* imports[] = {global.get(), func.get()};
+ own<Instance*> instance =
+ Instance::make(store.get(), module.get(), imports);
+ vec<Extern*> exports = instance->exports();
+ Func* run_func = exports[0]->func();
+ run_func->call();
+ }
+}
+
+} // namespace
+
+TEST_F(WasmCapiTest, Threads) {
+ // Create module.
+ ValueType i32_type[] = {kWasmI32};
+ FunctionSig param_i32(0, 1, i32_type);
+ uint32_t callback_index =
+ builder()->AddImport(CStrVector("callback"), &param_i32);
+ uint32_t global_index =
+ builder()->AddGlobalImport(CStrVector("id"), kWasmI32, false);
+
+ byte code[] = {
+ WASM_CALL_FUNCTION(callback_index, WASM_GET_GLOBAL(global_index))};
+ FunctionSig empty_sig(0, 0, nullptr);
+ AddExportedFunction(CStrVector("run"), code, sizeof(code), &empty_sig);
+ Compile();
+ own<Shared<Module>*> shared = module()->share();
+
+ // Spawn threads.
+ g_traces = 0;
+ std::mutex mutex;
+ std::thread threads[kNumThreads];
+ for (int i = 0; i < kNumThreads; i++) {
+ threads[i] = std::thread(Main, engine(), shared.get(), &mutex, i);
+ }
+ for (int i = 0; i < kNumThreads; i++) {
+ threads[i].join();
+ }
+ // Each thread in each iteration adds its ID to {traces}, so in the end
+ // we expect kIterationsPerThread * sum([0, ..., kNumThreads-1]).
+ // Per Gauss:
+ const int kExpected =
+ kIterationsPerThread * (kNumThreads - 1) * kNumThreads / 2;
+ EXPECT_EQ(kExpected, g_traces);
+}
+
+TEST_F(WasmCapiTest, MultiStoresOneThread) {
+ // These Stores intentionally have overlapping, but non-nested lifetimes.
+ own<Store*> store1 = Store::make(engine());
+ own<Store*> store2 = Store::make(engine());
+ own<Store*> store3 = Store::make(engine());
+ store1.reset();
+ store2.reset();
+ store3.reset();
+}
+
+} // namespace wasm
+} // namespace internal
+} // namespace v8