From a70defe3a74c6dd56ffc94be05a0855c44388917 Mon Sep 17 00:00:00 2001 From: mvicsokolova <82594708+mvicsokolova@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:29:44 +0200 Subject: [PATCH] Remove posix interop (#440) Fixes #324 --- atomicfu/build.gradle | 106 ++++++++++++------ .../kotlinx/atomicfu/locks/NativeMutexNode.kt | 31 +++++ .../kotlinx/atomicfu/locks/NativeMutexNode.kt | 31 +++++ .../kotlinx/atomicfu/locks/NativeMutexNode.kt | 31 +++++ .../src/nativeInterop/cinterop/interop.def | 33 ------ .../kotlinx/atomicfu/locks/NativeMutexNode.kt | 9 ++ .../atomicfu/locks/PosixLockSupport.kt | 51 --------- .../kotlinx/atomicfu/locks/Synchronized.kt | 2 +- .../kotlinx/atomicfu/locks/NativeMutexNode.kt | 31 +++++ 9 files changed, 205 insertions(+), 120 deletions(-) create mode 100644 atomicfu/src/androidNative32BitMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt create mode 100644 atomicfu/src/androidNative64BitMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt create mode 100644 atomicfu/src/mingwMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt create mode 100644 atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt delete mode 100644 atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/PosixLockSupport.kt create mode 100644 atomicfu/src/nativeUnixLikeMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt diff --git a/atomicfu/build.gradle b/atomicfu/build.gradle index cf7c5246..3f950c10 100644 --- a/atomicfu/build.gradle +++ b/atomicfu/build.gradle @@ -2,6 +2,7 @@ * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile plugins { @@ -12,12 +13,10 @@ plugins { ext { nativeMainSets = [] nativeTestSets = [] - nativeCompilations = [] addNative = { preset -> nativeMainSets.add(preset.compilations['main'].kotlinSourceSets.first()) nativeTestSets.add(preset.compilations['test'].kotlinSourceSets.first()) - nativeCompilations.add(preset.compilations['main']) } } @@ -124,36 +123,52 @@ kotlin { } } +// Support of all non-deprecated targets from official tier list: https://kotlinlang.org/docs/native-target-support.html kotlin { - targets { - // Support of all non-deprecated targets from official tier list: https://kotlinlang.org/docs/native-target-support.html - - // Tier #1 - addTarget(presets.linuxX64) - addTarget(presets.macosX64) - addTarget(presets.macosArm64) - addTarget(presets.iosSimulatorArm64) - addTarget(presets.iosX64) - - // Tier #2 - addTarget(presets.linuxArm64) - addTarget(presets.watchosSimulatorArm64) - addTarget(presets.watchosX64) - addTarget(presets.watchosArm32) - addTarget(presets.watchosArm64) - addTarget(presets.tvosSimulatorArm64) - addTarget(presets.tvosX64) - addTarget(presets.tvosArm64) - addTarget(presets.iosArm64) - - - // Tier #3 - addTarget(presets.androidNativeArm32) - addTarget(presets.androidNativeArm64) - addTarget(presets.androidNativeX86) - addTarget(presets.androidNativeX64) - addTarget(presets.mingwX64) - addTarget(presets.watchosDeviceArm64) + // Tier 1 + macosX64() + macosArm64() + iosSimulatorArm64() + iosX64() + + // Tier 2 + linuxX64() + linuxArm64() + watchosSimulatorArm64() + watchosX64() + watchosArm32() + watchosArm64() + tvosSimulatorArm64() + tvosX64() + tvosArm64() + iosArm64() + + // Tier 3 + androidNativeArm32() + androidNativeArm64() + androidNativeX86() + androidNativeX64() + mingwX64() + watchosDeviceArm64() + + applyDefaultHierarchyTemplate { target -> + target.group("native") { nativeTargets -> + nativeTargets.group("nativeUnixLike") { + it.withLinux() + it.withApple() + } + nativeTargets.group("androidNative32Bit") { + it.withAndroidNativeX86() + // This is a WA: in KotlinHierarchyBuilderImpl.withAndroidNativeArm32 the KonanTarget equals ANDROID_X86 instead of ANDROID_ARM32 + it.withCompilations { compilation -> + compilation.target instanceof KotlinNativeTarget && (compilation.target as KotlinNativeTarget).konanTarget.name == "android_arm32" + } + } + nativeTargets.group("androidNative64Bit") { + it.withAndroidNativeArm64() + it.withAndroidNativeX64() + } + } } sourceSets { @@ -161,6 +176,23 @@ kotlin { nativeTest {} + nativeUnixLikeMain { + kotlin.srcDir("src/nativeUnixLikeMain/kotlin") + dependsOn nativeMain + } + + androidNative32BitMain { + kotlin.srcDir("src/androidNative32BitMain/kotlin") + dependsOn nativeMain + } + + androidNative64BitMain { + kotlin.srcDir("src/androidNative64BitMain/kotlin") + dependsOn nativeMain + } + + mingwX64Main { dependsOn nativeMain } + configure(nativeMainSets) { dependsOn nativeMain } @@ -170,10 +202,14 @@ kotlin { } } - configure(nativeCompilations) { - cinterops { - interop { - defFile 'src/nativeInterop/cinterop/interop.def' + // atomicfu-cinterop-interop.klib with an empty interop.def file will still be published for compatibility reasons (see KT-68411) + // This block can be removed when this issue in K/N compiler is resolved: KT-60874 + targets.withType(KotlinNativeTarget).configureEach { nativeTarget -> + nativeTarget.compilations.configureEach { nativeCompilation -> + nativeCompilation.cinterops { + interop { + defFile file('src/nativeInterop/cinterop/interop.def') + } } } } diff --git a/atomicfu/src/androidNative32BitMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt b/atomicfu/src/androidNative32BitMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt new file mode 100644 index 00000000..5b6ff7cf --- /dev/null +++ b/atomicfu/src/androidNative32BitMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt @@ -0,0 +1,31 @@ +package kotlinx.atomicfu.locks + +import kotlinx.cinterop.* +import platform.posix.* +import kotlin.concurrent.Volatile + +public actual class NativeMutexNode { + + @Volatile + private var isLocked = false + private val pMutex = nativeHeap.alloc().apply { pthread_mutex_init(ptr, null) } + private val pCond = nativeHeap.alloc().apply { pthread_cond_init(ptr, null) } + + internal actual var next: NativeMutexNode? = null + + actual fun lock() { + pthread_mutex_lock(pMutex.ptr) + while (isLocked) { // wait till locked are available + pthread_cond_wait(pCond.ptr, pMutex.ptr) + } + isLocked = true + pthread_mutex_unlock(pMutex.ptr) + } + + actual fun unlock() { + pthread_mutex_lock(pMutex.ptr) + isLocked = false + pthread_cond_broadcast(pCond.ptr) + pthread_mutex_unlock(pMutex.ptr) + } +} \ No newline at end of file diff --git a/atomicfu/src/androidNative64BitMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt b/atomicfu/src/androidNative64BitMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt new file mode 100644 index 00000000..5b6ff7cf --- /dev/null +++ b/atomicfu/src/androidNative64BitMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt @@ -0,0 +1,31 @@ +package kotlinx.atomicfu.locks + +import kotlinx.cinterop.* +import platform.posix.* +import kotlin.concurrent.Volatile + +public actual class NativeMutexNode { + + @Volatile + private var isLocked = false + private val pMutex = nativeHeap.alloc().apply { pthread_mutex_init(ptr, null) } + private val pCond = nativeHeap.alloc().apply { pthread_cond_init(ptr, null) } + + internal actual var next: NativeMutexNode? = null + + actual fun lock() { + pthread_mutex_lock(pMutex.ptr) + while (isLocked) { // wait till locked are available + pthread_cond_wait(pCond.ptr, pMutex.ptr) + } + isLocked = true + pthread_mutex_unlock(pMutex.ptr) + } + + actual fun unlock() { + pthread_mutex_lock(pMutex.ptr) + isLocked = false + pthread_cond_broadcast(pCond.ptr) + pthread_mutex_unlock(pMutex.ptr) + } +} \ No newline at end of file diff --git a/atomicfu/src/mingwMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt b/atomicfu/src/mingwMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt new file mode 100644 index 00000000..4c23f564 --- /dev/null +++ b/atomicfu/src/mingwMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt @@ -0,0 +1,31 @@ +package kotlinx.atomicfu.locks + +import kotlinx.cinterop.* +import platform.posix.* +import kotlin.concurrent.Volatile + +public actual class NativeMutexNode { + + @Volatile + private var isLocked = false + private val pMutex = nativeHeap.alloc().apply { pthread_mutex_init(ptr, null) } + private val pCond = nativeHeap.alloc().apply { pthread_cond_init(ptr, null) } + + internal actual var next: NativeMutexNode? = null + + actual fun lock() { + pthread_mutex_lock(pMutex.ptr) + while (isLocked) { // wait till locked are available + pthread_cond_wait(pCond.ptr, pMutex.ptr) + } + isLocked = true + pthread_mutex_unlock(pMutex.ptr) + } + + actual fun unlock() { + pthread_mutex_lock(pMutex.ptr) + isLocked = false + pthread_cond_broadcast(pCond.ptr) + pthread_mutex_unlock(pMutex.ptr) + } +} \ No newline at end of file diff --git a/atomicfu/src/nativeInterop/cinterop/interop.def b/atomicfu/src/nativeInterop/cinterop/interop.def index 7e98de55..e69de29b 100644 --- a/atomicfu/src/nativeInterop/cinterop/interop.def +++ b/atomicfu/src/nativeInterop/cinterop/interop.def @@ -1,33 +0,0 @@ ---- -#include -#include -#include - -typedef struct lock_support { - volatile int locked; - pthread_mutex_t mutex; - pthread_cond_t cond; -} lock_support_t; - -lock_support_t* lock_support_init() { - lock_support_t * ls = (lock_support_t *) malloc(sizeof(lock_support_t)); - ls->locked = 0; - pthread_mutex_init(&ls->mutex, NULL); - pthread_cond_init(&ls->cond, NULL); - return ls; -} -void lock(lock_support_t* ls) { - pthread_mutex_lock(&ls->mutex); - while (ls->locked == 1) { // wait till locked are available - pthread_cond_wait(&ls->cond, &ls->mutex); - } - ls->locked = 1; - pthread_mutex_unlock(&ls->mutex); -} - -void unlock(lock_support_t* ls) { - pthread_mutex_lock(&ls->mutex); - ls->locked = 0; - pthread_cond_broadcast(&ls->cond); - pthread_mutex_unlock(&ls->mutex); -} \ No newline at end of file diff --git a/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt b/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt new file mode 100644 index 00000000..f2c72e16 --- /dev/null +++ b/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt @@ -0,0 +1,9 @@ +package kotlinx.atomicfu.locks + +public expect class NativeMutexNode() { + internal var next: NativeMutexNode? + + public fun lock() + + public fun unlock() +} \ No newline at end of file diff --git a/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/PosixLockSupport.kt b/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/PosixLockSupport.kt deleted file mode 100644 index 3843948d..00000000 --- a/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/PosixLockSupport.kt +++ /dev/null @@ -1,51 +0,0 @@ -package kotlinx.atomicfu.locks - -import interop.* -import kotlinx.cinterop.* -import platform.posix.* -import kotlin.concurrent.* - -public class NativeMutexNode { - private val mutex: CPointer = lock_support_init()!! - - internal var next: NativeMutexNode? = null - - fun lock() { - interop.lock(mutex) - } - - fun unlock() { - interop.unlock(mutex) - } -} - -/** - * This is a trivial counter-part of NativeMutexNode that does not rely on interop.def - * The problem is, commonizer cannot commonize pthreads, thus this declaration should be duplicated - * over multiple Native source-sets to work properly - */ -//public class NativeMutexNode { -// -// @Volatile -// private var isLocked = false -// private val pMutex = nativeHeap.alloc().apply { pthread_mutex_init(ptr, null) } -// private val pCond = nativeHeap.alloc().apply { pthread_cond_init(ptr, null) } -// -// internal var next: NativeMutexNode? = null -// -// fun lock() { -// pthread_mutex_lock(pMutex.ptr) -// while (isLocked) { // wait till locked are available -// pthread_cond_wait(pCond.ptr, pMutex.ptr) -// } -// isLocked = true -// pthread_mutex_unlock(pMutex.ptr) -// } -// -// fun unlock() { -// pthread_mutex_lock(pMutex.ptr) -// isLocked = false -// pthread_cond_broadcast(pCond.ptr) -// pthread_mutex_unlock(pMutex.ptr) -// } -//} \ No newline at end of file diff --git a/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/Synchronized.kt b/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/Synchronized.kt index f42b69b7..3fdfc38c 100644 --- a/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/Synchronized.kt +++ b/atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/locks/Synchronized.kt @@ -185,7 +185,7 @@ private val mutexPool by lazy { MutexPool(INITIAL_POOL_CAPACITY) } class MutexPool(capacity: Int) { private val top = AtomicReference(null) - private val mutexes = Array(capacity) { NativeMutexNode() } + private val mutexes = Array(capacity) { NativeMutexNode() } init { // Immediately form a stack diff --git a/atomicfu/src/nativeUnixLikeMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt b/atomicfu/src/nativeUnixLikeMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt new file mode 100644 index 00000000..032e6768 --- /dev/null +++ b/atomicfu/src/nativeUnixLikeMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt @@ -0,0 +1,31 @@ +package kotlinx.atomicfu.locks + +import kotlinx.cinterop.* +import platform.posix.* +import kotlin.concurrent.* + +public actual class NativeMutexNode { + + @Volatile + private var isLocked = false + private val pMutex = nativeHeap.alloc().apply { pthread_mutex_init(ptr, null) } + private val pCond = nativeHeap.alloc().apply { pthread_cond_init(ptr, null) } + + internal actual var next: NativeMutexNode? = null + + actual fun lock() { + pthread_mutex_lock(pMutex.ptr) + while (isLocked) { // wait till locked are available + pthread_cond_wait(pCond.ptr, pMutex.ptr) + } + isLocked = true + pthread_mutex_unlock(pMutex.ptr) + } + + actual fun unlock() { + pthread_mutex_lock(pMutex.ptr) + isLocked = false + pthread_cond_broadcast(pCond.ptr) + pthread_mutex_unlock(pMutex.ptr) + } +} \ No newline at end of file