Skip to content

Commit 7935e64

Browse files
committed
Report errno on native call error.
1 parent 60e56a6 commit 7935e64

File tree

4 files changed

+53
-44
lines changed

4 files changed

+53
-44
lines changed

atomicfu/src/androidNativeMain/kotlin/kotlinx/atomicfu/parking/PosixParkingDelegator.kt

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,46 +11,49 @@ internal actual object ParkingDelegator {
1111
actual fun createRef(): ParkingData {
1212
val mut = nativeHeap.alloc<pthread_mutex_t>().ptr
1313
val cond = nativeHeap.alloc<pthread_cond_t>().ptr
14-
callAndVerifyNative(0) { pthread_mutex_init(mut, null) }
15-
callAndVerifyNative(0) { pthread_cond_init(cond, null) }
14+
callAndVerify(0) { pthread_mutex_init(mut, null) }
15+
callAndVerify(0) { pthread_cond_init(cond, null) }
1616
return ParkingData(mut, cond)
1717
}
1818

1919
actual inline fun wait(ref: ParkingData, shouldWait: () -> Boolean){
20-
callAndVerifyNative(0) { pthread_mutex_lock(ref.mut) }
21-
if (shouldWait()) callAndVerifyNative(0) { pthread_cond_wait(ref.cond, ref.mut) }
22-
callAndVerifyNative(0) { pthread_mutex_unlock(ref.mut) }
20+
callAndVerify(0) { pthread_mutex_lock(ref.mut) }
21+
if (shouldWait()) callAndVerify(0) { pthread_cond_wait(ref.cond, ref.mut) }
22+
callAndVerify(0) { pthread_mutex_unlock(ref.mut) }
2323
}
2424

2525
actual inline fun timedWait(ref: ParkingData, nanos: Long, shouldWait: () -> Boolean): Unit = memScoped {
2626
val ts = alloc<timespec>().ptr
2727

2828
// Add nanos to current time
29-
callAndVerifyNative(0) { clock_gettime(CLOCK_REALTIME.convert(), ts) }
29+
callAndVerify(0) { clock_gettime(CLOCK_REALTIME.convert(), ts) }
3030
ts.pointed.tv_sec = ts.pointed.tv_sec.addNanosToSeconds(nanos)
3131
ts.pointed.tv_nsec = (ts.pointed.tv_nsec + nanos % 1_000_000_000).convert()
3232
//Fix overflow
3333
if (ts.pointed.tv_nsec >= 1_000_000_000) {
3434
ts.pointed.tv_sec = ts.pointed.tv_sec.addNanosToSeconds(1_000_000_000)
3535
ts.pointed.tv_nsec -= 1_000_000_000
3636
}
37-
callAndVerifyNative(0) { pthread_mutex_lock(ref.mut) }
38-
if (shouldWait()) callAndVerifyNative(0, ETIMEDOUT) { pthread_cond_timedwait(ref.cond, ref.mut, ts) }
39-
callAndVerifyNative(0) { pthread_mutex_unlock(ref.mut) }
37+
callAndVerify(0) { pthread_mutex_lock(ref.mut) }
38+
if (shouldWait()) callAndVerify(0, ETIMEDOUT) { pthread_cond_timedwait(ref.cond, ref.mut, ts) }
39+
callAndVerify(0) { pthread_mutex_unlock(ref.mut) }
4040
}
4141

4242
actual fun wake(ref: ParkingData) {
43-
callAndVerifyNative(0) { pthread_mutex_lock(ref.mut) }
44-
callAndVerifyNative(0) { pthread_cond_signal(ref.cond) }
45-
callAndVerifyNative(0) { pthread_mutex_unlock(ref.mut) }
43+
callAndVerify(0) { pthread_mutex_lock(ref.mut) }
44+
callAndVerify(0) { pthread_cond_signal(ref.cond) }
45+
callAndVerify(0) { pthread_mutex_unlock(ref.mut) }
4646
}
4747

4848
actual fun destroyRef(ref: ParkingData) {
49-
callAndVerifyNative(0) { pthread_mutex_destroy(ref.mut) }
50-
callAndVerifyNative(0) { pthread_cond_destroy(ref.cond) }
49+
callAndVerify(0) { pthread_mutex_destroy(ref.mut) }
50+
callAndVerify(0) { pthread_cond_destroy(ref.cond) }
5151
nativeHeap.free(ref.mut)
5252
nativeHeap.free(ref.cond)
5353
}
54+
55+
private inline fun callAndVerify(vararg expectedReturn: Int, block: () -> Int) =
56+
callAndVerifyNative(*expectedReturn, getErrno = { errno }, block = block)
5457

5558
}
5659
internal actual class ParkingData(val mut: CPointer<pthread_mutex_t>, val cond: CPointer<pthread_cond_t>)

atomicfu/src/mingwMain/kotlin/kotlinx/atomicfu/parking/PosixParkingDelegator.kt

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@ internal actual object ParkingDelegator {
1111
actual fun createRef(): ParkingData {
1212
val mut = nativeHeap.alloc<pthread_mutex_tVar>().ptr
1313
val cond = nativeHeap.alloc<pthread_cond_tVar>().ptr
14-
callAndVerifyNative(0) { pthread_mutex_init(mut, null) }
15-
callAndVerifyNative(0) { pthread_cond_init(cond, null) }
14+
callAndVerify(0) { pthread_mutex_init(mut, null) }
15+
callAndVerify(0) { pthread_cond_init(cond, null) }
1616
return ParkingData(mut, cond)
1717
}
1818

1919
actual inline fun wait(ref: ParkingData, shouldWait: () -> Boolean) {
20-
callAndVerifyNative(0) { pthread_mutex_lock(ref.mut) }
21-
if (shouldWait()) callAndVerifyNative(0) { pthread_cond_wait(ref.cond, ref.mut) }
22-
callAndVerifyNative(0) { pthread_mutex_unlock(ref.mut) }
20+
callAndVerify(0) { pthread_mutex_lock(ref.mut) }
21+
if (shouldWait()) callAndVerify(0) { pthread_cond_wait(ref.cond, ref.mut) }
22+
callAndVerify(0) { pthread_mutex_unlock(ref.mut) }
2323
}
2424

2525
actual inline fun timedWait(ref: ParkingData, nanos: Long, shouldWait: () -> Boolean): Unit = memScoped {
2626
val ts = alloc<timespec>().ptr
2727

2828
// Add nanos to current time
29-
callAndVerifyNative(0) { clock_gettime(CLOCK_REALTIME.toInt(), ts) }
29+
callAndVerify(0) { clock_gettime(CLOCK_REALTIME.toInt(), ts) }
3030
// According to https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime
3131
// the maximum year on windows is 30827.
3232
// Adding Long.MAX_VALUE / 1_000_000_000 should not be able to overflow.
@@ -38,23 +38,26 @@ internal actual object ParkingDelegator {
3838
ts.pointed.tv_sec += 1
3939
ts.pointed.tv_nsec -= 1_000_000_000
4040
}
41-
callAndVerifyNative(0) { pthread_mutex_lock(ref.mut) }
42-
if (shouldWait()) callAndVerifyNative(0, ETIMEDOUT) { pthread_cond_timedwait(ref.cond, ref.mut, ts) }
43-
callAndVerifyNative(0) { pthread_mutex_unlock(ref.mut) }
41+
callAndVerify(0) { pthread_mutex_lock(ref.mut) }
42+
if (shouldWait()) callAndVerify(0, ETIMEDOUT) { pthread_cond_timedwait(ref.cond, ref.mut, ts) }
43+
callAndVerify(0) { pthread_mutex_unlock(ref.mut) }
4444
}
4545

4646
actual fun wake(ref: ParkingData) {
47-
callAndVerifyNative(0) { pthread_mutex_lock(ref.mut) }
48-
callAndVerifyNative(0) { pthread_cond_signal(ref.cond) }
49-
callAndVerifyNative(0) { pthread_mutex_unlock(ref.mut) }
47+
callAndVerify(0) { pthread_mutex_lock(ref.mut) }
48+
callAndVerify(0) { pthread_cond_signal(ref.cond) }
49+
callAndVerify(0) { pthread_mutex_unlock(ref.mut) }
5050
}
5151

5252
actual fun destroyRef(ref: ParkingData) {
53-
callAndVerifyNative(0) { pthread_mutex_destroy(ref.mut) }
54-
callAndVerifyNative(0) { pthread_cond_destroy(ref.cond) }
53+
callAndVerify(0) { pthread_mutex_destroy(ref.mut) }
54+
callAndVerify(0) { pthread_cond_destroy(ref.cond) }
5555
nativeHeap.free(ref.mut)
5656
nativeHeap.free(ref.cond)
5757
}
58+
59+
private inline fun callAndVerify(vararg expectedReturn: Int, block: () -> Int) =
60+
callAndVerifyNative(*expectedReturn, getErrno = { errno }, block = block)
5861

5962
}
6063
internal actual class ParkingData(val mut: CPointer<pthread_mutex_tVar>, val cond: CPointer<pthread_cond_tVar>)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package kotlinx.atomicfu.parking
22

3-
internal inline fun callAndVerifyNative(vararg expectedReturn: Int, block: () -> Int): Int = block().also {
3+
internal inline fun callAndVerifyNative(vararg expectedReturn: Int, getErrno: () -> Int, block: () -> Int): Int = block().also {
44
check(expectedReturn.contains(it)) {
5-
"Calling native, expected one return status of ${expectedReturn.joinToString(", ")}, but was $it"
5+
"Calling native, expected one return status of ${expectedReturn.joinToString(", ")}, but was $it. With errno: ${getErrno()}"
66
}
77
}

atomicfu/src/nativeUnixLikeMain/kotlin/kotlinx/atomicfu/parking/PosixParkingDelegator.kt

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,46 +11,49 @@ internal actual object ParkingDelegator {
1111
actual fun createRef(): ParkingData {
1212
val mut = nativeHeap.alloc<pthread_mutex_t>().ptr
1313
val cond = nativeHeap.alloc<pthread_cond_t>().ptr
14-
callAndVerifyNative(0) { pthread_mutex_init(mut, null) }
15-
callAndVerifyNative(0) { pthread_cond_init(cond, null) }
14+
callAndVerify(0) { pthread_mutex_init(mut, null) }
15+
callAndVerify(0) { pthread_cond_init(cond, null) }
1616
return ParkingData(mut, cond)
1717
}
1818

1919
actual inline fun wait(ref: ParkingData, shouldWait: () -> Boolean){
20-
callAndVerifyNative(0) { pthread_mutex_lock(ref.mut) }
21-
if (shouldWait()) callAndVerifyNative(0) { pthread_cond_wait(ref.cond, ref.mut) }
22-
callAndVerifyNative(0) { pthread_mutex_unlock(ref.mut) }
20+
callAndVerify(0) { pthread_mutex_lock(ref.mut) }
21+
if (shouldWait()) callAndVerify(0) { pthread_cond_wait(ref.cond, ref.mut) }
22+
callAndVerify(0) { pthread_mutex_unlock(ref.mut) }
2323
}
2424

2525
actual inline fun timedWait(ref: ParkingData, nanos: Long, shouldWait: () -> Boolean): Unit = memScoped {
2626
val ts = alloc<timespec>().ptr
2727

2828
// Add nanos to current time
29-
callAndVerifyNative(0) { clock_gettime(CLOCK_REALTIME.convert(), ts) }
29+
callAndVerify(0) { clock_gettime(CLOCK_REALTIME.convert(), ts) }
3030
ts.pointed.tv_sec = ts.pointed.tv_sec.addNanosToSeconds(nanos)
3131
ts.pointed.tv_nsec = (ts.pointed.tv_nsec + nanos % 1_000_000_000).convert()
3232
//Fix overflow
3333
if (ts.pointed.tv_nsec >= 1_000_000_000) {
3434
ts.pointed.tv_sec = ts.pointed.tv_sec.addNanosToSeconds(1_000_000_000)
3535
ts.pointed.tv_nsec -= 1_000_000_000
3636
}
37-
callAndVerifyNative(0) { pthread_mutex_lock(ref.mut) }
38-
if (shouldWait()) callAndVerifyNative(0, ETIMEDOUT) { pthread_cond_timedwait(ref.cond, ref.mut, ts) }
39-
callAndVerifyNative(0) { pthread_mutex_unlock(ref.mut) }
37+
callAndVerify(0) { pthread_mutex_lock(ref.mut) }
38+
if (shouldWait()) callAndVerify(0, ETIMEDOUT) { pthread_cond_timedwait(ref.cond, ref.mut, ts) }
39+
callAndVerify(0) { pthread_mutex_unlock(ref.mut) }
4040
}
4141

4242
actual fun wake(ref: ParkingData) {
43-
callAndVerifyNative(0) { pthread_mutex_lock(ref.mut) }
44-
callAndVerifyNative(0) { pthread_cond_signal(ref.cond) }
45-
callAndVerifyNative(0) { pthread_mutex_unlock(ref.mut) }
43+
callAndVerify(0) { pthread_mutex_lock(ref.mut) }
44+
callAndVerify(0) { pthread_cond_signal(ref.cond) }
45+
callAndVerify(0) { pthread_mutex_unlock(ref.mut) }
4646
}
4747

4848
actual fun destroyRef(ref: ParkingData) {
49-
callAndVerifyNative(0) { pthread_mutex_destroy(ref.mut) }
50-
callAndVerifyNative(0) { pthread_cond_destroy(ref.cond) }
49+
callAndVerify(0) { pthread_mutex_destroy(ref.mut) }
50+
callAndVerify(0) { pthread_cond_destroy(ref.cond) }
5151
nativeHeap.free(ref.mut)
5252
nativeHeap.free(ref.cond)
5353
}
54+
55+
private inline fun callAndVerify(vararg expectedReturn: Int, block: () -> Int) =
56+
callAndVerifyNative(*expectedReturn, getErrno = { errno }, block = block)
5457

5558
}
5659
internal actual class ParkingData(val mut: CPointer<pthread_mutex_t>, val cond: CPointer<pthread_cond_t>)

0 commit comments

Comments
 (0)