Skip to content

Commit 1d9a104

Browse files
committed
fixup: revert to synchronized allocator
1 parent b0bfc02 commit 1d9a104

File tree

7 files changed

+17
-137
lines changed

7 files changed

+17
-137
lines changed

mlir/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ list(INSERT CMAKE_MODULE_PATH 0
6969

7070
include(AddMLIR)
7171
include(IRDLToCpp)
72-
include(CheckAtomic)
7372

7473
# -BSymbolic is incompatible with TypeID
7574
if("${CMAKE_SHARED_LINKER_FLAGS}" MATCHES "-Bsymbolic[^-]")

mlir/include/mlir/IR/MLIRContext.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,6 @@ class MLIRContext {
153153
disableMultithreading(!enable);
154154
}
155155

156-
/// Set the flag specifying if thread-local storage should be used by
157-
/// attribute storage allocators in this context.
158-
void disableThreadLocalStorage(bool disable = true);
159-
void enableThreadLocalStorage(bool enable = true) {
160-
disableThreadLocalStorage(!enable);
161-
}
162-
163156
/// Set a new thread pool to be used in this context. This method requires
164157
/// that multithreading is disabled for this context prior to the call. This
165158
/// allows to share a thread pool across multiple contexts, as well as

mlir/lib/IR/AttributeDetail.h

Lines changed: 11 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,8 @@
1919
#include "mlir/IR/BuiltinTypes.h"
2020
#include "mlir/IR/IntegerSet.h"
2121
#include "mlir/IR/MLIRContext.h"
22-
#include "mlir/Support/StorageUniquer.h"
23-
#include "mlir/Support/ThreadLocalCache.h"
2422
#include "llvm/ADT/APFloat.h"
2523
#include "llvm/Support/Allocator.h"
26-
#include <atomic>
27-
#include <cstdint>
2824
#include <mutex>
2925

3026
namespace mlir {
@@ -398,112 +394,30 @@ class DistinctAttributeUniquer {
398394
Attribute referencedAttr);
399395
};
400396

401-
/// An allocator for distinct attribute storage instances. It uses thread-local
402-
/// bump pointer allocators stored in a thread-local cache to ensure the storage
403-
/// is freed after the destruction of the distinct attribute allocator. The way
404-
/// in which storage is allocated may be changed from a thread-local allocator
405-
/// to a shared, locked allocator. This can be used to prevent use-after-free
406-
/// errors if storage is allocated on a thread that has a lifetime less than the
407-
/// lifetime of the storage.
397+
/// An allocator for distinct attribute storage instances. Uses a synchronized
398+
/// BumpPtrAllocator to ensure allocated storage is deleted when the
399+
/// DistinctAttributeAllocator is destroyed
408400
class DistinctAttributeAllocator final {
409401
public:
410-
/// The allocation strategy for DistinctAttribute storage.
411-
enum class AllocationMode : uint8_t {
412-
/// Use a thread-local allocator. Lock-free, but storage lifetime is tied to
413-
/// a thread, which may have shorter lifetime than the storage allocated
414-
/// here.
415-
ThreadLocal,
416-
/// Use a single, shared allocator protected by a mutex. Slower due to
417-
/// locking, but storage persists for the lifetime of the MLIR context.
418-
SharedLocked,
419-
};
420-
421-
DistinctAttributeAllocator() {
422-
setAllocationMode(AllocationMode::ThreadLocal);
423-
};
424-
402+
DistinctAttributeAllocator() = default;
425403
DistinctAttributeAllocator(DistinctAttributeAllocator &&) = delete;
426404
DistinctAttributeAllocator(const DistinctAttributeAllocator &) = delete;
427405
DistinctAttributeAllocator &
428406
operator=(const DistinctAttributeAllocator &) = delete;
429407

430-
/// Allocates a distinct attribute storage. In most cases this will be
431-
/// using a thread-local allocator for synchronization free parallel accesses,
432-
/// however if the PassManager's crash recovery is enabled this will incur
433-
/// synchronization cost in exchange for persisting the storage.
434408
DistinctAttrStorage *allocate(Attribute referencedAttr) {
435-
return std::invoke(allocatorFn.load(), *this, referencedAttr);
436-
}
437-
438-
/// Sets the allocation mode. This is used by the MLIRContext to switch
439-
/// allocation strategies, for example, during crash recovery.
440-
void setAllocationMode(AllocationMode mode) {
441-
switch (mode) {
442-
case AllocationMode::ThreadLocal:
443-
allocatorFn.store(&DistinctAttributeAllocator::allocateThreadLocalWrapper,
444-
std::memory_order_release);
445-
break;
446-
case AllocationMode::SharedLocked:
447-
allocatorFn.store(
448-
&DistinctAttributeAllocator::allocateLockedSharedWrapper,
449-
std::memory_order_release);
450-
break;
451-
}
452-
}
453-
454-
private:
455-
// Define some static wrappers for allocating using either the thread-local
456-
// allocator or the shared locked allocator. We use these static wrappers to
457-
// ensure that the width of the function pointer to these functions is the
458-
// size of regular pointer on the platform (which is not always the case for
459-
// pointer-to-member-function), and so should be handled by atomic
460-
// instructions.
461-
static DistinctAttrStorage *
462-
allocateThreadLocalWrapper(DistinctAttributeAllocator &self,
463-
Attribute referencedAttr) {
464-
return self.allocateUsingThreadLocal(referencedAttr);
465-
}
466-
467-
static DistinctAttrStorage *
468-
allocateLockedSharedWrapper(DistinctAttributeAllocator &self,
469-
Attribute referencedAttr) {
470-
return self.allocateUsingLockedShared(referencedAttr);
471-
}
472-
473-
DistinctAttrStorage *allocateUsingLockedShared(Attribute referencedAttr) {
474-
std::scoped_lock<std::mutex> guard(sharedAllocatorMutex);
475-
return doAllocate(sharedAllocator, referencedAttr);
476-
}
477-
478-
DistinctAttrStorage *allocateUsingThreadLocal(Attribute referencedAttr) {
479-
return doAllocate(allocatorCache.get(), referencedAttr);
480-
};
481-
482-
DistinctAttrStorage *doAllocate(llvm::BumpPtrAllocator &allocator,
483-
Attribute referencedAttr) {
409+
std::scoped_lock<std::mutex> guard(allocatorMutex);
484410
return new (allocator.Allocate<DistinctAttrStorage>())
485411
DistinctAttrStorage(referencedAttr);
486412
};
487413

488-
/// Used to allocate Distinct Attribute storage without synchronization
489-
ThreadLocalCache<llvm::BumpPtrAllocator> allocatorCache;
490-
491-
/// Used to allocate Distict Attribute storage with synchronization,
492-
/// but without bounding the lifetime of the allocated memory to the
493-
/// lifetime of a thread.
494-
llvm::BumpPtrAllocator sharedAllocator;
495-
496-
/// Used to lock access to the shared allocator
497-
std::mutex sharedAllocatorMutex;
498-
499-
using AllocatorFuncPtr =
500-
DistinctAttrStorage *(*)(DistinctAttributeAllocator &, Attribute);
414+
private:
415+
/// Used to allocate Distict Attribute storage. When this allocator destroyed
416+
/// in till also dealllocate any storage instances
417+
llvm::BumpPtrAllocator allocator;
501418

502-
/// Atomic function pointer for the allocation strategy. Using a pointer to a
503-
/// static member function as opposed to a non-static one should guarantee
504-
/// that the function pointer fits into a standard pointer size, and so will
505-
/// atomic instruction support for the corresponding width.
506-
std::atomic<AllocatorFuncPtr> allocatorFn;
419+
/// Used to lock access to the allocator
420+
std::mutex allocatorMutex;
507421
};
508422
} // namespace detail
509423
} // namespace mlir

mlir/lib/IR/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,5 @@ add_mlir_library(MLIRIR
6868

6969
LINK_LIBS PUBLIC
7070
MLIRSupport
71-
PRIVATE
72-
${LLVM_ATOMIC_LIB}
7371
)
7472

mlir/lib/IR/MLIRContext.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "llvm/Support/CommandLine.h"
3232
#include "llvm/Support/Compiler.h"
3333
#include "llvm/Support/Debug.h"
34+
#include "llvm/Support/ManagedStatic.h"
3435
#include "llvm/Support/Mutex.h"
3536
#include "llvm/Support/RWMutex.h"
3637
#include "llvm/Support/ThreadPool.h"
@@ -711,13 +712,6 @@ bool MLIRContext::isOperationRegistered(StringRef name) {
711712
return RegisteredOperationName::lookup(name, this).has_value();
712713
}
713714

714-
void MLIRContext::disableThreadLocalStorage(bool disable) {
715-
const auto mode =
716-
disable ? DistinctAttributeAllocator::AllocationMode::SharedLocked
717-
: DistinctAttributeAllocator::AllocationMode::ThreadLocal;
718-
getImpl().distinctAttributeAllocator.setAllocationMode(mode);
719-
}
720-
721715
void Dialect::addType(TypeID typeID, AbstractType &&typeInfo) {
722716
auto &impl = context->getImpl();
723717
assert(impl.multiThreadedExecutionContext == 0 &&

mlir/lib/Pass/PassCrashRecovery.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -418,15 +418,6 @@ LogicalResult PassManager::runWithCrashRecovery(Operation *op,
418418
// thread-local storage during passes beyond the lifetime of the recovery
419419
// context thread.
420420
const bool threadingEnabled = getContext()->isMultithreadingEnabled();
421-
if (threadingEnabled) {
422-
crashRecoveryLock.lock();
423-
getContext()->disableThreadLocalStorage();
424-
}
425-
auto guard = llvm::make_scope_exit([this]() {
426-
getContext()->enableThreadLocalStorage();
427-
crashRecoveryLock.unlock();
428-
});
429-
430421
crashReproGenerator->initialize(getPasses(), op, verifyPasses);
431422

432423
// Safely invoke the passes within a recovery context.
@@ -439,8 +430,6 @@ LogicalResult PassManager::runWithCrashRecovery(Operation *op,
439430
recoveryContext.RunSafely(runPassesFn);
440431
crashReproGenerator->finalize(op, passManagerResult);
441432

442-
if (!threadingEnabled)
443-
guard.release();
444433
return passManagerResult;
445434
}
446435

mlir/unittests/IR/DistinctAttributeAllocatorTest.cpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include "mlir/IR/Builders.h"
1313
#include "mlir/IR/BuiltinAttributes.h"
1414
#include "mlir/IR/MLIRContext.h"
15-
#include "llvm/ADT/ScopeExit.h"
1615
#include "llvm/Support/CrashRecoveryContext.h"
1716
#include <thread>
1817

@@ -28,17 +27,11 @@ TEST(DistinctAttributeAllocatorTest, TestAttributeWellFormedAfterThreadJoin) {
2827
OpBuilder builder(&ctx);
2928
DistinctAttr attr;
3029

31-
{
32-
ctx.disableThreadLocalStorage();
33-
auto guard =
34-
llvm::make_scope_exit([&ctx]() { ctx.enableThreadLocalStorage(); });
35-
36-
std::thread t([&ctx, &attr]() {
37-
attr = DistinctAttr::create(UnitAttr::get(&ctx));
38-
ASSERT_TRUE(attr);
39-
});
40-
t.join();
41-
}
30+
std::thread t([&ctx, &attr]() {
31+
attr = DistinctAttr::create(UnitAttr::get(&ctx));
32+
ASSERT_TRUE(attr);
33+
});
34+
t.join();
4235

4336
// If the attribute storage got deleted after the thread joins (which we don't
4437
// want) then trying to access it triggers an assert in Debug mode, and a

0 commit comments

Comments
 (0)