[DWARFLinkerParallel] Fix incorrect uses of compare_exchange_weak (#138129)
The documentation for compare_exchange_weak says that it is allowed to
spuriously fail. If compare_exchange_weak is called in a loop, spurious
failures usually are benign - but in these cases, a spurious failure
would give incorrect behaviour.
E.g. in TypePool::getOrCreateTypeEntryBody, we assume that if the
compare_exchange call returned false, we had been preempted by another
thread and that DIE is non-null.
This fixes running the dsymutil tests on Windows on aarch64 (built with
a mingw toolchain with libc++).
diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
index fa426d4..38373b2 100644
--- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
+++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
@@ -1433,13 +1433,13 @@
if (IsDeclaration && !DeclarationDie) {
// Alocate declaration DIE.
DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
- if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
- NewDie))
+ if (TypeDescriptor->DeclarationDie.compare_exchange_strong(DeclarationDie,
+ NewDie))
return NewDie;
} else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {
// Overwrite existing declaration DIE if it's parent is also an declaration
// while parent of current declaration DIE is a definition.
- if (TypeDescriptor->ParentIsDeclaration.compare_exchange_weak(
+ if (TypeDescriptor->ParentIsDeclaration.compare_exchange_strong(
OldParentIsDeclaration, false)) {
DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
TypeDescriptor->DeclarationDie = NewDie;
@@ -1449,13 +1449,13 @@
// Alocate declaration DIE since parent of current DIE is marked as
// declaration.
DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
- if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
- NewDie))
+ if (TypeDescriptor->DeclarationDie.compare_exchange_strong(DeclarationDie,
+ NewDie))
return NewDie;
} else if (!IsDeclaration && !IsParentDeclaration) {
// Allocate definition DIE.
DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
- if (TypeDescriptor->Die.compare_exchange_weak(DefinitionDie, NewDie)) {
+ if (TypeDescriptor->Die.compare_exchange_strong(DefinitionDie, NewDie)) {
TypeDescriptor->ParentIsDeclaration = false;
return NewDie;
}
diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h
index 20e2022..90c007e 100644
--- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h
+++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.h
@@ -201,7 +201,7 @@
bool setPlacementIfUnset(DieOutputPlacement Placement) {
auto InputData = Flags.load();
if ((InputData & 0x7) == NotSet)
- if (Flags.compare_exchange_weak(InputData, (InputData | Placement)))
+ if (Flags.compare_exchange_strong(InputData, (InputData | Placement)))
return true;
return false;
diff --git a/llvm/lib/DWARFLinker/Parallel/TypePool.h b/llvm/lib/DWARFLinker/Parallel/TypePool.h
index 5475329..15a6428 100644
--- a/llvm/lib/DWARFLinker/Parallel/TypePool.h
+++ b/llvm/lib/DWARFLinker/Parallel/TypePool.h
@@ -135,7 +135,7 @@
return DIE;
TypeEntryBody *NewDIE = TypeEntryBody::create(Allocator);
- if (Entry->getValue().compare_exchange_weak(DIE, NewDIE)) {
+ if (Entry->getValue().compare_exchange_strong(DIE, NewDIE)) {
ParentEntry->getValue().load()->Children.add(Entry);
return NewDIE;
}