Skip to content

Commit be7af98

Browse files
committed
Multi-threaded file opening/mapping.
1 parent 41c3e61 commit be7af98

File tree

2 files changed

+34
-18
lines changed

2 files changed

+34
-18
lines changed

lld/MachO/Driver.cpp

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ static void saveThinArchiveToRepro(ArchiveFile const *file) {
292292
struct DeferredFile {
293293
StringRef path;
294294
bool isLazy;
295-
MemoryBufferRef buffer;
295+
std::optional<MemoryBufferRef> buffer;
296296
};
297297
using DeferredFiles = std::vector<DeferredFile>;
298298

@@ -346,8 +346,10 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
346346
std::atomic_int numDeferedFilesAdvised = 0;
347347
auto t0 = high_resolution_clock::now();
348348

349-
auto preloadDeferredFile = [&](const DeferredFile &deferredFile) {
350-
const StringRef &buff = deferredFile.buffer.getBuffer();
349+
auto preloadDeferredFile = [&](DeferredFile &deferredFile) {
350+
if (!deferredFile.buffer.has_value())
351+
deferredFile.buffer = *readFile(deferredFile.path);
352+
const StringRef &buff = (*deferredFile.buffer).getBuffer();
351353
if (buff.size() > largeArchive)
352354
return;
353355

@@ -394,12 +396,9 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
394396
<< duration_cast<milliseconds>(dt).count() / 1000. << "\n";
395397
}
396398

397-
static void multiThreadedPageIn(const DeferredFiles &deferred) {
399+
static void multiThreadedPageIn(DeferredFiles &deferred) {
398400
static SerialBackgroundQueue pageInQueue;
399-
pageInQueue.queueWork([=]() {
400-
DeferredFiles files = deferred;
401-
multiThreadedPageInBackground(files);
402-
});
401+
pageInQueue.queueWork([&]() { multiThreadedPageInBackground(deferred); });
403402
}
404403

405404
static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
@@ -574,13 +573,12 @@ static InputFile *addFile(StringRef path, LoadType loadType,
574573
}
575574

576575
static void deferFile(StringRef path, bool isLazy, DeferredFiles &deferred) {
576+
if (config->readWorkers)
577+
return deferred.push_back({path, isLazy, std::nullopt});
577578
std::optional<MemoryBufferRef> buffer = readFile(path);
578579
if (!buffer)
579580
return;
580-
if (config->readWorkers)
581-
deferred.push_back({path, isLazy, *buffer});
582-
else
583-
processFile(buffer, nullptr, path, LoadType::CommandLine, isLazy);
581+
processFile(buffer, nullptr, path, LoadType::CommandLine, isLazy);
584582
}
585583

586584
static std::vector<StringRef> missingAutolinkWarnings;
@@ -1365,7 +1363,8 @@ static void createFiles(const InputArgList &args) {
13651363
bool isLazy = false;
13661364
// If we've processed an opening --start-lib, without a matching --end-lib
13671365
bool inLib = false;
1368-
DeferredFiles deferredFiles;
1366+
static DeferredFiles deferredFiles;
1367+
deferredFiles.clear();
13691368

13701369
for (const Arg *arg : args) {
13711370
const Option &opt = arg->getOption();
@@ -1444,9 +1443,13 @@ static void createFiles(const InputArgList &args) {
14441443
if (config->readWorkers) {
14451444
multiThreadedPageIn(deferredFiles);
14461445

1447-
DeferredFiles archiveContents;
1446+
static DeferredFiles archiveContents;
14481447
std::vector<ArchiveFile *> archives;
1448+
archiveContents.clear();
1449+
14491450
for (auto &file : deferredFiles) {
1451+
if (!file.buffer.has_value())
1452+
file.buffer = readFile(file.path);
14501453
auto inputFile = processFile(file.buffer, &archiveContents, file.path,
14511454
LoadType::CommandLine, file.isLazy);
14521455
if (ArchiveFile *archive = dyn_cast<ArchiveFile>(inputFile))

lld/MachO/InputFiles.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,15 @@ static bool compatWithTargetArch(const InputFile *file, const Header *hdr) {
212212
DenseMap<CachedHashStringRef, MemoryBufferRef> macho::cachedReads;
213213
// Open a given file path and return it as a memory-mapped file.
214214
std::optional<MemoryBufferRef> macho::readFile(StringRef path) {
215+
static std::mutex mutex;
216+
mutex.lock();
215217
CachedHashStringRef key(path);
216218
auto entry = cachedReads.find(key);
217-
if (entry != cachedReads.end())
219+
if (entry != cachedReads.end()) {
220+
mutex.unlock();
218221
return entry->second;
222+
}
223+
mutex.unlock();
219224

220225
ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr =
221226
MemoryBuffer::getFile(path, false, /*RequiresNullTerminator=*/false);
@@ -224,18 +229,23 @@ std::optional<MemoryBufferRef> macho::readFile(StringRef path) {
224229
return std::nullopt;
225230
}
226231

232+
mutex.lock();
227233
std::unique_ptr<MemoryBuffer> &mb = *mbOrErr;
228234
MemoryBufferRef mbref = mb->getMemBufferRef();
229235
make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); // take mb ownership
236+
mutex.unlock();
230237

231238
// If this is a regular non-fat file, return it.
232239
const char *buf = mbref.getBufferStart();
233240
const auto *hdr = reinterpret_cast<const fat_header *>(buf);
234241
if (mbref.getBufferSize() < sizeof(uint32_t) ||
235242
read32be(&hdr->magic) != FAT_MAGIC) {
243+
mutex.lock();
236244
if (tar)
237245
tar->append(relativeToRoot(path), mbref.getBuffer());
238-
return cachedReads[key] = mbref;
246+
cachedReads[key] = mbref;
247+
mutex.unlock();
248+
return mbref;
239249
}
240250

241251
llvm::BumpPtrAllocator &bAlloc = lld::bAlloc();
@@ -272,10 +282,13 @@ std::optional<MemoryBufferRef> macho::readFile(StringRef path) {
272282
uint32_t size = read32be(&arch[i].size);
273283
if (offset + size > mbref.getBufferSize())
274284
error(path + ": slice extends beyond end of file");
285+
mutex.lock();
275286
if (tar)
276287
tar->append(relativeToRoot(path), mbref.getBuffer());
277-
return cachedReads[key] = MemoryBufferRef(StringRef(buf + offset, size),
278-
path.copy(bAlloc));
288+
mbref = MemoryBufferRef(StringRef(buf + offset, size), path.copy(bAlloc));
289+
cachedReads[key] = mbref;
290+
mutex.unlock();
291+
return mbref;
279292
}
280293

281294
auto targetArchName = getArchName(target->cpuType, target->cpuSubtype);

0 commit comments

Comments
 (0)