Skip to content

[mlir] DistinctAttributeAllocator: fix race #132935

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

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions mlir/lib/IR/AttributeDetail.h
Original file line number Diff line number Diff line change
Expand Up @@ -413,16 +413,17 @@ class DistinctAttributeAllocator {
/// Allocates a distinct attribute storage using a thread local bump pointer
/// allocator to enable synchronization free parallel allocations.
DistinctAttrStorage *allocate(Attribute referencedAttr) {
std::unique_lock<std::mutex> lock(allocatorMutex);
if (!useThreadLocalAllocator && threadingIsEnabled) {
std::scoped_lock<std::mutex> lock(allocatorMutex);
return allocateImpl(referencedAttr);
return allocateImpl(referencedAttr, lock);
}
return allocateImpl(referencedAttr);
return allocateImpl(referencedAttr, lock);
}

/// Sets a flag that stores if multithreading is enabled. The flag is used to
/// decide if locking is needed when using a non thread-safe allocator.
void disableMultiThreading(bool disable = true) {
std::scoped_lock<std::mutex> lock(allocatorMutex);
threadingIsEnabled = !disable;
}

Expand All @@ -431,20 +432,25 @@ class DistinctAttributeAllocator {
/// beyond the lifetime of a child thread calling this function while ensuring
/// thread-safe allocation.
void disableThreadLocalStorage(bool disable = true) {
std::scoped_lock<std::mutex> lock(allocatorMutex);
useThreadLocalAllocator = !disable;
}

private:
DistinctAttrStorage *allocateImpl(Attribute referencedAttr) {
return new (getAllocatorInUse().Allocate<DistinctAttrStorage>())
DistinctAttrStorage *allocateImpl(Attribute referencedAttr,
const std::unique_lock<std::mutex> &lock) {
assert(lock.owns_lock());
return new (getAllocatorInUse(lock).Allocate<DistinctAttrStorage>())
DistinctAttrStorage(referencedAttr);
}

/// If threading is disabled on the owning MLIR context, a normal non
/// thread-local, non-thread safe bump pointer allocator is used instead to
/// prevent use-after-free errors whenever attribute storage created on a
/// crash recover thread is accessed after the thread joins.
llvm::BumpPtrAllocator &getAllocatorInUse() {
llvm::BumpPtrAllocator &
getAllocatorInUse(const std::unique_lock<std::mutex> &lock) {
assert(lock.owns_lock());
if (useThreadLocalAllocator)
return allocatorCache.get();
return allocator;
Expand Down