From 59653835ebdbce083697cfaf3b8188cb0d699013 Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Wed, 26 Sep 2018 12:25:44 +0300 Subject: [PATCH] Fix bug preventing return from worker value passed in it. (#2135) --- backend.native/tests/build.gradle | 6 +++ .../tests/runtime/workers/worker11.kt | 48 +++++++++++++++++++ runtime/src/main/cpp/Memory.h | 1 + runtime/src/main/cpp/Worker.cpp | 1 + 4 files changed, 56 insertions(+) create mode 100644 backend.native/tests/runtime/workers/worker11.kt diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index ac47869ac5b..f2e233fd950 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -663,6 +663,12 @@ task worker10(type: RunKonanTest) { source = "runtime/workers/worker10.kt" } +task worker11(type: RunKonanTest) { + disabled = (project.testTarget == 'wasm32') // Workers need pthreads. + goldValue = "OK\n" + source = "runtime/workers/worker11.kt" +} + task freeze0(type: RunKonanTest) { disabled = (project.testTarget == 'wasm32') // No workers on WASM. goldValue = "frozen bit is true\n" + diff --git a/backend.native/tests/runtime/workers/worker11.kt b/backend.native/tests/runtime/workers/worker11.kt new file mode 100644 index 00000000000..91527808da3 --- /dev/null +++ b/backend.native/tests/runtime/workers/worker11.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +package runtime.workers.worker11 + +import kotlin.test.* + +import kotlin.native.concurrent.* +import kotlinx.cinterop.convert + +data class Job(val index: Int, var input: Int, var counter: Int) + +fun initJobs(count: Int) = Array(count) { i -> Job(i, i * 2, i)} + +@Test fun runTest() { + val COUNT = 100 + val workers = Array(COUNT, { _ -> Worker.start() }) + val jobs = initJobs(COUNT) + val futures = Array(workers.size, { workerIndex -> + workers[workerIndex].execute(TransferMode.SAFE, { + val job = jobs[workerIndex] + jobs[workerIndex] = null + job!! + }) { job -> + job.counter += job.input + job + } + }) + val futureSet = futures.toSet() + var consumed = 0 + while (consumed < futureSet.size) { + val ready = futureSet.waitForMultipleFutures(10000) + ready.forEach { + it.consume { job -> + assertEquals(job.index * 3, job.counter) + jobs[job.index] = job + } + consumed++ + } + } + assertEquals(consumed, COUNT) + workers.forEach { + it.requestTermination().result + } + println("OK") +} \ No newline at end of file diff --git a/runtime/src/main/cpp/Memory.h b/runtime/src/main/cpp/Memory.h index d530d4b4490..a39984c3399 100644 --- a/runtime/src/main/cpp/Memory.h +++ b/runtime/src/main/cpp/Memory.h @@ -496,6 +496,7 @@ class ObjHolder { ObjHeader* obj() { return obj_; } const ObjHeader* obj() const { return obj_; } ObjHeader** slot() { return &obj_; } + void clear() { ::UpdateRef(&obj_, nullptr); } private: ObjHeader* obj_; diff --git a/runtime/src/main/cpp/Worker.cpp b/runtime/src/main/cpp/Worker.cpp index e4801e2276b..a941525efd9 100644 --- a/runtime/src/main/cpp/Worker.cpp +++ b/runtime/src/main/cpp/Worker.cpp @@ -379,6 +379,7 @@ void* workerRoutine(void* argument) { KNativePtr result = nullptr; try { job.function(argument, &resultRef); + argumentHolder.clear(); // Transfer the result. result = transfer(resultRef, job.transferMode); } catch (ObjHolder& e) {