Skip to content

Commit 9ae27d7

Browse files
Merge pull request #82859 from cachemeifyoucan/eng/PR-lock-output-cas-output-backend
[CAS] Protect the CASOutputBackend from multi-threaded updates
2 parents 044e97b + a816444 commit 9ae27d7

File tree

1 file changed

+27
-12
lines changed

1 file changed

+27
-12
lines changed

lib/Frontend/CASOutputBackends.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/CAS/HierarchicalTreeBuilder.h"
2323
#include "llvm/CAS/ObjectStore.h"
2424
#include "llvm/Support/Debug.h"
25+
#include "llvm/Support/Mutex.h"
2526
#include <optional>
2627

2728
#define DEBUG_TYPE "swift-cas-backend"
@@ -112,6 +113,9 @@ class SwiftCASOutputBackend::Implementation {
112113
Error storeImpl(StringRef Path, StringRef Bytes, unsigned InputIndex,
113114
file_types::ID OutputKind);
114115

116+
// Return true if all the outputs are produced for the given index.
117+
bool addProducedOutput(unsigned InputIndex, file_types::ID OutputKind,
118+
ObjectRef BytesRef);
115119
Error finalizeCacheKeysFor(unsigned InputIndex);
116120

117121
private:
@@ -123,6 +127,9 @@ class SwiftCASOutputBackend::Implementation {
123127
const FrontendOptions &Opts;
124128
FrontendOptions::ActionType Action;
125129

130+
// Lock for updating output file status.
131+
llvm::sys::SmartMutex<true> OutputLock;
132+
126133
// Map from output path to the input index and output kind.
127134
StringMap<std::pair<unsigned, file_types::ID>> OutputToInputMap;
128135

@@ -197,8 +204,10 @@ Error SwiftCASOutputBackend::storeMCCASObjectID(StringRef OutputFilename,
197204
return createStringError("Invalid CASID: " + ID.toString() +
198205
". No associated ObjectRef found!");
199206

200-
Impl.OutputRefs[InputIndex].insert({file_types::TY_Object, *MCRef});
201-
return Impl.finalizeCacheKeysFor(InputIndex);
207+
if (Impl.addProducedOutput(InputIndex, file_types::TY_Object, *MCRef))
208+
return Impl.finalizeCacheKeysFor(InputIndex);
209+
210+
return Error::success();
202211
}
203212

204213
void SwiftCASOutputBackend::Implementation::initBackend(
@@ -249,23 +258,29 @@ Error SwiftCASOutputBackend::Implementation::storeImpl(
249258
<< "\' for input \'" << InputIndex << "\': \'"
250259
<< CAS.getID(*BytesRef).toString() << "\'\n";);
251260

252-
OutputRefs[InputIndex].insert({OutputKind, *BytesRef});
261+
if (addProducedOutput(InputIndex, OutputKind, *BytesRef))
262+
return finalizeCacheKeysFor(InputIndex);
263+
return Error::success();
264+
}
265+
266+
bool SwiftCASOutputBackend::Implementation::addProducedOutput(
267+
unsigned InputIndex, file_types::ID OutputKind,
268+
ObjectRef BytesRef) {
269+
llvm::sys::SmartScopedLock<true> LockOutput(OutputLock);
270+
auto &ProducedOutputs = OutputRefs[InputIndex];
271+
ProducedOutputs.insert({OutputKind, BytesRef});
253272

254-
return finalizeCacheKeysFor(InputIndex);
273+
return llvm::all_of(OutputToInputMap, [&](auto &E) {
274+
return (E.second.first != InputIndex ||
275+
ProducedOutputs.count(E.second.second));
276+
});
255277
}
256278

257279
Error SwiftCASOutputBackend::Implementation::finalizeCacheKeysFor(
258280
unsigned InputIndex) {
259-
auto ProducedOutputs = OutputRefs[InputIndex];
281+
const auto &ProducedOutputs = OutputRefs[InputIndex];
260282
assert(!ProducedOutputs.empty() && "Expect outputs for this input");
261283

262-
// If not all outputs for the input are emitted, return.
263-
if (!llvm::all_of(OutputToInputMap, [&](auto &E) {
264-
return (E.second.first != InputIndex ||
265-
ProducedOutputs.count(E.second.second));
266-
}))
267-
return Error::success();
268-
269284
std::vector<std::pair<file_types::ID, ObjectRef>> OutputsForInput;
270285
llvm::for_each(ProducedOutputs, [&OutputsForInput](auto E) {
271286
OutputsForInput.emplace_back(E.first, E.second);

0 commit comments

Comments
 (0)