-
Notifications
You must be signed in to change notification settings - Fork 415
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
SyntaxArena: thread safety #807
Conversation
@swift-ci Please test |
Use mutex to guard concurrent mutation to the arena. swiftlang#785 rdar://99812330
@swift-ci Please test |
Thank you, this certainly helps, although TSan now reports an access race in the guard code:
Full report: https://buildkite.com/swiftlint/swiftlint/builds/3411#018354b5-95eb-4c14-ab21-f7d59113f241 |
/// Copies a source buffer in to the memory this arena manages, and returns | ||
/// the interned buffer. | ||
/// | ||
/// The interned buffer is guaranteed to be null-terminated. | ||
/// `contains(address _:)` is faster if the address is inside the memory | ||
/// range this function returned. | ||
public func internSourceBuffer(_ buffer: UnsafeBufferPointer<UInt8>) -> UnsafeBufferPointer<UInt8> { | ||
let allocated = lock.withGuard { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be self.withGuard
?
@@ -114,7 +189,9 @@ public class SyntaxArena { | |||
/// Copies a `RawSyntaxData` to the memory this arena manages, and retuns the | |||
/// pointer to the destination. | |||
func intern(_ value: RawSyntaxData) -> UnsafePointer<RawSyntaxData> { | |||
let allocated = allocator.allocate(RawSyntaxData.self, count: 1).baseAddress! | |||
let allocated = lock.withGuard { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, should this be self.withGuard
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These ScopeGuards are not correct. We cannot use the materialization operator here despite the fact that we're indexing through a heap allocation for the member access - it's still a logical data race even if it's not always a physical data race. These locks need to be allocated out-of-line and the resulting address passed.
Passing `os_unfair_lock` with inout expression is considered "mutation" by thread sanitizer. Instead, keep the lock object with `let UnsafeMutablePointer` form, and pass it.
@jpsim I confirmed the failure locally. And the modified implementation resolves it. Could you check the new implementation? |
@swift-ci Please test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are no more TSan failures in my testing. Thank you!
Use mutex to guard concurrent mutation to the arena.
But make a "single thread" mode so that we don't regress performance too much when we know the arena is not used by other threads.
(non
Darwin
/Glibc
environment e.g. Windows implementation is currently a dummy)#785
rdar://99812330