Skip to content

Commit e267526

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

File tree

1 file changed

+66
-30
lines changed

1 file changed

+66
-30
lines changed

lld/MachO/Driver.cpp

Lines changed: 66 additions & 30 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,20 +335,47 @@ 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 =
360+
new PageInState{deferred, 0, 0, llvm::sys::Process::getPageSizeEstimate(),
361+
pthread_mutex_t()};
362+
363+
pthread_create(
364+
&running, nullptr,
365+
[](void *ptr) -> void * {
366+
PageInState *state = (PageInState *)ptr;
367+
multiThreadedPageInBackground(state);
368+
pthread_mutex_unlock(&busy);
369+
delete state;
370+
return nullptr;
371+
},
372+
state);
373+
}
374+
350375
static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
351-
StringRef path, LoadType loadType,
352-
bool isLazy = false, bool isExplicit = true,
376+
DeferredFiles *archiveContents, StringRef path,
377+
LoadType loadType, bool isLazy = false,
378+
bool isExplicit = true,
353379
bool isBundleLoader = false,
354380
bool isForceHidden = false) {
355381
if (!buffer)
@@ -431,7 +457,6 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
431457
// we already found that it contains an ObjC symbol.
432458
if (readFile(path)) {
433459
Error e = Error::success();
434-
std::vector<DeferredFile> deferredFiles;
435460
for (const object::Archive::Child &c : file->getArchive().children(e)) {
436461
Expected<MemoryBufferRef> mb = c.getMemoryBufferRef();
437462
if (!mb) {
@@ -445,9 +470,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
445470
continue;
446471
}
447472

448-
deferredFiles.push_back({path, isLazy, std::nullopt,
449-
mb->getBuffer().data(),
450-
mb->getBuffer().size()});
473+
if (archiveContents)
474+
archiveContents->push_back({path, isLazy, std::nullopt,
475+
mb->getBuffer().data(),
476+
mb->getBuffer().size()});
451477
if (!hasObjCSection(*mb))
452478
continue;
453479
if (Error e = file->fetch(c, "-ObjC"))
@@ -457,11 +483,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
457483
if (e)
458484
error(toString(file) +
459485
": Archive::children failed: " + toString(std::move(e)));
460-
if (config->readThreads && deferredFiles.size() > 1)
461-
multiThreadedPageIn(deferredFiles);
462486
}
463487
}
464-
file->addLazySymbols();
488+
if (!archiveContents || archiveContents->empty())
489+
file->addLazySymbols();
465490
loadedArchives[path] = ArchiveFileInfo{file, isCommandLineLoad};
466491
newFile = file;
467492
break;
@@ -516,18 +541,17 @@ static InputFile *addFile(StringRef path, LoadType loadType,
516541
bool isLazy = false, bool isExplicit = true,
517542
bool isBundleLoader = false,
518543
bool isForceHidden = false) {
519-
return processFile(readFile(path), path, loadType, isLazy, isExplicit,
520-
isBundleLoader, isForceHidden);
544+
return processFile(readFile(path), nullptr, path, loadType, isLazy,
545+
isExplicit, isBundleLoader, isForceHidden);
521546
}
522547

523-
static void deferFile(StringRef path, bool isLazy,
524-
std::vector<DeferredFile> &deferred) {
548+
static void deferFile(StringRef path, bool isLazy, DeferredFiles &deferred) {
525549
std::optional<MemoryBufferRef> buffer = readFile(path);
526550
if (config->readThreads)
527551
deferred.push_back({path, isLazy, buffer, buffer->getBuffer().data(),
528552
buffer->getBuffer().size()});
529553
else
530-
processFile(buffer, path, LoadType::CommandLine, isLazy);
554+
processFile(buffer, nullptr, path, LoadType::CommandLine, isLazy);
531555
}
532556

533557
static std::vector<StringRef> missingAutolinkWarnings;
@@ -654,7 +678,7 @@ void macho::resolveLCLinkerOptions() {
654678
}
655679

656680
static void addFileList(StringRef path, bool isLazy,
657-
std::vector<DeferredFile> &deferredFiles) {
681+
DeferredFiles &deferredFiles) {
658682
std::optional<MemoryBufferRef> buffer = readFile(path);
659683
if (!buffer)
660684
return;
@@ -1312,7 +1336,7 @@ static void createFiles(const InputArgList &args) {
13121336
bool isLazy = false;
13131337
// If we've processed an opening --start-lib, without a matching --end-lib
13141338
bool inLib = false;
1315-
std::vector<DeferredFile> deferredFiles;
1339+
DeferredFiles deferredFiles;
13161340

13171341
for (const Arg *arg : args) {
13181342
const Option &opt = arg->getOption();
@@ -1390,8 +1414,20 @@ static void createFiles(const InputArgList &args) {
13901414

13911415
if (config->readThreads) {
13921416
multiThreadedPageIn(deferredFiles);
1417+
1418+
DeferredFiles archiveContents;
1419+
std::vector<ArchiveFile *> archives;
13931420
for (auto &file : deferredFiles)
1394-
processFile(file.buffer, file.path, LoadType::CommandLine, file.isLazy);
1421+
if (ArchiveFile *archive = dyn_cast<ArchiveFile>(
1422+
processFile(file.buffer, &archiveContents, file.path,
1423+
LoadType::CommandLine, file.isLazy)))
1424+
archives.push_back(archive);
1425+
1426+
if (!archiveContents.empty()) {
1427+
multiThreadedPageIn(archiveContents);
1428+
for (auto *archive : archives)
1429+
archive->addLazySymbols();
1430+
}
13951431
}
13961432
}
13971433

0 commit comments

Comments
 (0)