Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apple QoS support via donation #499

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from

Conversation

stefanhaustein
Copy link

Addressing issue #462

@stefanhaustein
Copy link
Author

@qwwdfsad qwwdfsad self-requested a review January 27, 2025 14:27
@qwwdfsad qwwdfsad changed the base branch from master to develop January 27, 2025 14:27
Copy link
Collaborator

@qwwdfsad qwwdfsad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job!

I have a few essential comments on Apple-related implementation, and it's good to go. To avoid extra-round trips please take a look at new warnings produced by ./gradlew build.

I would also kindly ask (but I'll accept the CR without it) to align non-apple SynchronizedObject with the current implementation as well -- you can copy-paste it but remove QoS mentions, or you can make this code part of nativeMain with expect DonatingMonitor, whatever is easier. Having two different implementations going to be real PITA here



@ThreadLocal
var currentThreadId = 0L
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var currentThreadId = 0L
internal var currentThreadId = 0L

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

public actual open class SynchronizedObject {

companion object {
private const val NO_OWNER = 0L
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move it close to currentThreadId, it does not have to be in its own companion, does it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if (lockOwner == NO_OWNER) {
return
}
val ourQosClass = qos_class_self() as UInt
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cast might be redundant

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed


private val owner: AtomicLong = atomic(NO_OWNER)
private var reEnterCount: Int = 0
private val waiters: AtomicInt = atomic(0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling this waiters is semantically confusing: if there exists only a single thread that locks the lock, waiters fluctuates between 0 and 1.

Have you considered renaming it? (e.g. threadsOnLock or something like that) and dropping a comment?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed as suggested

private const val NO_OWNER = 0L
}

private val owner: AtomicLong = atomic(NO_OWNER)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please consider naming it ownerThreadId -- generally owner means Any in our lingua

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed as suggested

} else {
// No existing override, check if we need to set one up.
memScoped {
val lockOwnerQosClass = alloc<UIntVar>()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's pretty much likely that this allocation will be happen on each contention and it's a real malloc.

Is it possible to extract this alloc into DonatingMonitor level and free it within cleaner?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this just be a stack allocation (via memScoped)? It's just used short-lived for getting the values back, perhaps I am holding it wrong?

val lockOwnerRelPrio = alloc<IntVar>()
pthread_get_qos_class_np(lockOwner.toCPointer(), lockOwnerQosClass.ptr, lockOwnerRelPrio.ptr)
if (ourQosClass > lockOwnerQosClass.value) {
qosOverride = pthread_override_qos_class_start_np(lockOwner.toCPointer(), qos_class_self(), 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can reuse ourQosClass here instead of calling qos_class_self, can't we?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@stefanhaustein
Copy link
Author

I have a few essential comments on Apple-related implementation, and it's good to go. To avoid extra-round trips please take a look at new warnings produced by ./gradlew build.

I checked the IDE for warnings and fixed the threadlocal package. Not sure about the redundant "public" modifiers? For some bits (forked from the compose implementation) I was not sure to which extent they were outdated or intended for some reason. Unfortunately, gradlew build is full of gazillions of expect / actual warnins. I did a quick search for the flag in combination with gradlew but did not see anything obvious....

I would also kindly ask (but I'll accept the CR without it) to align non-apple SynchronizedObject with the current implementation as well -- you can copy-paste it but remove QoS mentions, or you can make this code part of nativeMain with expect DonatingMonitor, whatever is easier. Having two different implementations going to be real PITA here

SGTM but let me do this in a followup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants