Skip to content

Commit 1a6ec75

Browse files
committed
Multi-thread i/o in background.
1 parent 02fb145 commit 1a6ec75

File tree

1 file changed

+69
-28
lines changed

1 file changed

+69
-28
lines changed

lld/MachO/Driver.cpp

Lines changed: 69 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -290,27 +290,26 @@ typedef struct {
290290
const char *start;
291291
size_t size;
292292
} DeferredFile;
293+
typedef std::vector<DeferredFile> DeferredFiles;
294+
295+
typedef struct {
296+
DeferredFiles deferred;
297+
size_t counter, total, pageSize;
298+
pthread_mutex_t mutex;
299+
} PageInState;
293300

294301
// Most input files have been mapped but not yet paged in.
295302
// This code forces the page-ins on multiple threads so
296303
// the process is not stalled waiting on disk buffer i/o.
297-
static void multiThreadedPageIn(std::vector<DeferredFile> &deferred) {
304+
static void multiThreadedPageInBackground(PageInState *state) {
298305
#ifndef _WIN32
299306
#define MaxReadThreads 200
300-
typedef struct {
301-
std::vector<DeferredFile> &deferred;
302-
size_t counter, total, pageSize;
303-
pthread_mutex_t mutex;
304-
} PageInState;
305-
PageInState state = {deferred, 0, 0,
306-
llvm::sys::Process::getPageSizeEstimate(),
307-
pthread_mutex_t()};
308307
static size_t totalBytes;
309308

310309
pthread_t running[MaxReadThreads];
311310
if (config->readThreads > MaxReadThreads)
312311
config->readThreads = MaxReadThreads;
313-
pthread_mutex_init(&state.mutex, NULL);
312+
pthread_mutex_init(&state->mutex, nullptr);
314313

315314
for (int t = 0; t < config->readThreads; t++)
316315
pthread_create(
@@ -336,18 +335,46 @@ static void multiThreadedPageIn(std::vector<DeferredFile> &deferred) {
336335
state.total += t; // Avoids the loop being optimised out.
337336
}
338337
},
339-
&state);
338+
state);
340339

341340
for (int t = 0; t < config->readThreads; t++)
342341
pthread_join(running[t], nullptr);
343342

344-
pthread_mutex_destroy(&state.mutex);
343+
pthread_mutex_destroy(&state->mutex);
345344
if (getenv("LLD_MULTI_THREAD_PAGE"))
346-
printf("multiThreadedPageIn %ld/%ld\n", totalBytes, deferred.size());
345+
printf("multiThreadedPageIn %ld/%ld\n", totalBytes, state->deferred.size());
347346
#endif
348347
}
349348

349+
static void multiThreadedPageIn(DeferredFiles deferred) {
350+
static pthread_t running;
351+
static pthread_mutex_t busy;
352+
353+
if (running)
354+
pthread_join(running, nullptr);
355+
else
356+
pthread_mutex_init(&busy, nullptr);
357+
358+
pthread_mutex_lock(&busy);
359+
PageInState *state = new PageInState {
360+
deferred, 0, 0,
361+
llvm::sys::Process::getPageSizeEstimate(),
362+
pthread_mutex_t()};
363+
364+
pthread_create(
365+
&running, nullptr,
366+
[](void *ptr) -> void * {
367+
PageInState *state = (PageInState *)ptr;
368+
multiThreadedPageInBackground(state);
369+
pthread_mutex_unlock(&busy);
370+
delete state;
371+
return nullptr;
372+
},
373+
state);
374+
}
375+
350376
static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
377+
DeferredFiles *archiveContents,
351378
StringRef path, LoadType loadType,
352379
bool isLazy = false, bool isExplicit = true,
353380
bool isBundleLoader = false,
@@ -431,7 +458,6 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
431458
// we already found that it contains an ObjC symbol.
432459
if (readFile(path)) {
433460
Error e = Error::success();
434-
std::vector<DeferredFile> deferredFiles;
435461
for (const object::Archive::Child &c : file->getArchive().children(e)) {
436462
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef();
437463
if (!mb) {
@@ -445,9 +471,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
445471
continue;
446472
}
447473

448-
deferredFiles.push_back({path, isLazy, std::nullopt,
449-
mb->getBuffer().data(),
450-
mb->getBuffer().size()});
474+
if (archiveContents)
475+
archiveContents->push_back({path, isLazy, std::nullopt,
476+
mb->getBuffer().data(),
477+
mb->getBuffer().size()});
451478
if (!hasObjCSection(*mb))
452479
continue;
453480
if (Error e = file->fetch(c, "-ObjC"))
@@ -457,11 +484,14 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
457484
if (e)
458485
error(toString(file) +
459486
": Archive::children failed: " + toString(std::move(e)));
460-
if (config->readThreads && deferredFiles.size() > 1)
461-
multiThreadedPageIn(deferredFiles);
487+
// if (archiveContents && !archiveContents->empty()) {
488+
// multiThreadedPageIn(*archiveContents);
489+
// archiveContents->clear();
490+
// }
462491
}
463492
}
464-
file->addLazySymbols();
493+
if (!archiveContents || archiveContents->empty())
494+
file->addLazySymbols();
465495
loadedArchives[path] = ArchiveFileInfo{file, isCommandLineLoad};
466496
newFile = file;
467497
break;
@@ -516,18 +546,17 @@ static InputFile *addFile(StringRef path, LoadType loadType,
516546
bool isLazy = false, bool isExplicit = true,
517547
bool isBundleLoader = false,
518548
bool isForceHidden = false) {
519-
return processFile(readFile(path), path, loadType, isLazy, isExplicit,
520-
isBundleLoader, isForceHidden);
549+
return processFile(readFile(path), nullptr, path, loadType, isLazy,
550+
isExplicit, isBundleLoader, isForceHidden);
521551
}
522552

523-
static void deferFile(StringRef path, bool isLazy,
524-
std::vector<DeferredFile> &deferred) {
553+
static void deferFile(StringRef path, bool isLazy, DeferredFiles &deferred) {
525554
std::optional<MemoryBufferRef> buffer = readFile(path);
526555
if (config->readThreads)
527556
deferred.push_back({path, isLazy, buffer, buffer->getBuffer().data(),
528557
buffer->getBuffer().size()});
529558
else
530-
processFile(buffer, path, LoadType::CommandLine, isLazy);
559+
processFile(buffer, nullptr, path, LoadType::CommandLine, isLazy);
531560
}
532561

533562
static std::vector<StringRef> missingAutolinkWarnings;
@@ -654,7 +683,7 @@ void macho::resolveLCLinkerOptions() {
654683
}
655684

656685
static void addFileList(StringRef path, bool isLazy,
657-
std::vector<DeferredFile> &deferredFiles) {
686+
DeferredFiles &deferredFiles) {
658687
std::optional<MemoryBufferRef> buffer = readFile(path);
659688
if (!buffer)
660689
return;
@@ -1312,7 +1341,7 @@ static void createFiles(const InputArgList &args) {
13121341
bool isLazy = false;
13131342
// If we've processed an opening --start-lib, without a matching --end-lib
13141343
bool inLib = false;
1315-
std::vector<DeferredFile> deferredFiles;
1344+
DeferredFiles deferredFiles;
13161345

13171346
for (const Arg *arg : args) {
13181347
const Option &opt = arg->getOption();
@@ -1390,8 +1419,20 @@ static void createFiles(const InputArgList &args) {
13901419

13911420
if (config->readThreads) {
13921421
multiThreadedPageIn(deferredFiles);
1422+
1423+
DeferredFiles archiveContents;
1424+
std::vector<ArchiveFile *> archives;
13931425
for (auto &file : deferredFiles)
1394-
processFile(file.buffer, file.path, LoadType::CommandLine, file.isLazy);
1426+
if (ArchiveFile *archive = dyn_cast<ArchiveFile>
1427+
(processFile(file.buffer, &archiveContents, file.path,
1428+
LoadType::CommandLine, file.isLazy)))
1429+
archives.push_back(archive);
1430+
1431+
if (!archiveContents.empty()) {
1432+
multiThreadedPageIn(archiveContents);
1433+
for (auto *archive : archives)
1434+
archive->addLazySymbols();
1435+
}
13951436
}
13961437
}
13971438

0 commit comments

Comments
 (0)