Skip to content

Commit d4ebd0d

Browse files
committed
Pre-empt read-worker threads.
1 parent 13dcdec commit d4ebd0d

File tree

1 file changed

+23
-10
lines changed

1 file changed

+23
-10
lines changed

lld/MachO/Driver.cpp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -290,18 +290,22 @@ static void saveThinArchiveToRepro(ArchiveFile const *file) {
290290
}
291291

292292
struct DeferredFile {
293+
#if LLVM_ENABLE_THREADS
293294
StringRef path;
294295
bool isLazy;
295296
MemoryBufferRef buffer;
297+
#endif
296298
};
297299
using DeferredFiles = std::vector<DeferredFile>;
298300

301+
#if LLVM_ENABLE_THREADS
299302
class SerialBackgroundQueue {
300303
std::deque<std::function<void()>> queue;
301304
std::thread *running;
302305
std::mutex mutex;
303306

304307
public:
308+
bool stopAllWork = false;
305309
void queueWork(std::function<void()> work) {
306310
mutex.lock();
307311
if (running && queue.empty()) {
@@ -316,7 +320,7 @@ class SerialBackgroundQueue {
316320
queue.emplace_back(std::move(work));
317321
if (!running)
318322
running = new std::thread([&]() {
319-
while (true) {
323+
while (!stopAllWork) {
320324
mutex.lock();
321325
if (queue.empty()) {
322326
mutex.unlock();
@@ -335,6 +339,8 @@ class SerialBackgroundQueue {
335339
}
336340
};
337341

342+
static SerialBackgroundQueue pageInQueue;
343+
338344
// Most input files have been mapped but not yet paged in.
339345
// This code forces the page-ins on multiple threads so
340346
// the process is not stalled waiting on disk buffer i/o.
@@ -356,8 +362,8 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
356362

357363
#if _WIN32
358364
// Reference all file's mmap'd pages to load them into memory.
359-
for (const char *page = buff.data(), *end = page + buff.size(); page < end;
360-
page += pageSize) {
365+
for (const char *page = buff.data(), *end = page + buff.size();
366+
page < end && !pageInQueue.stopAllWork; page += pageSize) {
361367
LLVM_ATTRIBUTE_UNUSED volatile char t = *page;
362368
(void)t;
363369
}
@@ -370,24 +376,19 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
370376
#endif
371377
};
372378

373-
#if LLVM_ENABLE_THREADS
374379
{ // Create scope for waiting for the taskGroup
375380
std::atomic_size_t index = 0;
376381
llvm::parallel::TaskGroup taskGroup;
377382
for (int w = 0; w < config->readWorkers; w++)
378383
taskGroup.spawn([&index, &preloadDeferredFile, &deferred]() {
379-
while (true) {
384+
while (!pageInQueue.stopAllWork) {
380385
size_t localIndex = index.fetch_add(1);
381386
if (localIndex >= deferred.size())
382387
break;
383388
preloadDeferredFile(deferred[localIndex]);
384389
}
385390
});
386391
}
387-
#else
388-
for (const auto &file : deferred)
389-
preloadDeferredFile(file);
390-
#endif
391392

392393
auto dt = high_resolution_clock::now() - t0;
393394
if (Process::GetEnv("LLD_MULTI_THREAD_PAGE"))
@@ -397,12 +398,12 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
397398
}
398399

399400
static void multiThreadedPageIn(const DeferredFiles &deferred) {
400-
static SerialBackgroundQueue pageInQueue;
401401
pageInQueue.queueWork([=]() {
402402
DeferredFiles files = deferred;
403403
multiThreadedPageInBackground(files);
404404
});
405405
}
406+
#endif
406407

407408
static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
408409
DeferredFiles *archiveContents, StringRef path,
@@ -502,8 +503,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
502503
continue;
503504
}
504505

506+
#if LLVM_ENABLE_THREADS
505507
if (archiveContents)
506508
archiveContents->push_back({path, isLazy, *mb});
509+
#endif
507510
if (!hasObjCSection(*mb))
508511
continue;
509512
if (Error e = file->fetch(c, "-ObjC"))
@@ -579,9 +582,11 @@ static void deferFile(StringRef path, bool isLazy, DeferredFiles &deferred) {
579582
std::optional<MemoryBufferRef> buffer = readFile(path);
580583
if (!buffer)
581584
return;
585+
#if LLVM_ENABLE_THREADS
582586
if (config->readWorkers)
583587
deferred.push_back({path, isLazy, *buffer});
584588
else
589+
#endif
585590
processFile(buffer, nullptr, path, LoadType::CommandLine, isLazy);
586591
}
587592

@@ -1443,6 +1448,7 @@ static void createFiles(const InputArgList &args) {
14431448
}
14441449
}
14451450

1451+
#if LLVM_ENABLE_THREADS
14461452
if (config->readWorkers) {
14471453
multiThreadedPageIn(deferredFiles);
14481454

@@ -1459,7 +1465,10 @@ static void createFiles(const InputArgList &args) {
14591465
multiThreadedPageIn(archiveContents);
14601466
for (auto *archive : archives)
14611467
archive->addLazySymbols();
1468+
1469+
pageInQueue.stopAllWork = true;
14621470
}
1471+
#endif
14631472
}
14641473

14651474
static void gatherInputSections() {
@@ -1847,13 +1856,17 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
18471856
}
18481857

18491858
if (auto *arg = args.getLastArg(OPT_read_workers)) {
1859+
#if LLVM_ENABLE_THREADS
18501860
StringRef v(arg->getValue());
18511861
unsigned workers = 0;
18521862
if (!llvm::to_integer(v, workers, 0))
18531863
error(arg->getSpelling() +
18541864
": expected a non-negative integer, but got '" + arg->getValue() +
18551865
"'");
18561866
config->readWorkers = workers;
1867+
#else
1868+
error(arg->getSpelling() + ": option unavailable");
1869+
#endif
18571870
}
18581871
if (auto *arg = args.getLastArg(OPT_threads_eq)) {
18591872
StringRef v(arg->getValue());

0 commit comments

Comments
 (0)