@@ -290,18 +290,22 @@ static void saveThinArchiveToRepro(ArchiveFile const *file) {
290
290
}
291
291
292
292
struct DeferredFile {
293
+ #if LLVM_ENABLE_THREADS
293
294
StringRef path;
294
295
bool isLazy;
295
296
MemoryBufferRef buffer;
297
+ #endif
296
298
};
297
299
using DeferredFiles = std::vector<DeferredFile>;
298
300
301
+ #if LLVM_ENABLE_THREADS
299
302
class SerialBackgroundQueue {
300
303
std::deque<std::function<void ()>> queue;
301
304
std::thread *running;
302
305
std::mutex mutex;
303
306
304
307
public:
308
+ bool stopAllWork = false ;
305
309
void queueWork (std::function<void ()> work) {
306
310
mutex.lock ();
307
311
if (running && queue.empty ()) {
@@ -316,7 +320,7 @@ class SerialBackgroundQueue {
316
320
queue.emplace_back (std::move (work));
317
321
if (!running)
318
322
running = new std::thread ([&]() {
319
- while (true ) {
323
+ while (!stopAllWork ) {
320
324
mutex.lock ();
321
325
if (queue.empty ()) {
322
326
mutex.unlock ();
@@ -335,6 +339,8 @@ class SerialBackgroundQueue {
335
339
}
336
340
};
337
341
342
+ static SerialBackgroundQueue pageInQueue;
343
+
338
344
// Most input files have been mapped but not yet paged in.
339
345
// This code forces the page-ins on multiple threads so
340
346
// the process is not stalled waiting on disk buffer i/o.
@@ -356,8 +362,8 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
356
362
357
363
#if _WIN32
358
364
// 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) {
361
367
LLVM_ATTRIBUTE_UNUSED volatile char t = *page;
362
368
(void )t;
363
369
}
@@ -370,24 +376,19 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
370
376
#endif
371
377
};
372
378
373
- #if LLVM_ENABLE_THREADS
374
379
{ // Create scope for waiting for the taskGroup
375
380
std::atomic_size_t index = 0 ;
376
381
llvm::parallel::TaskGroup taskGroup;
377
382
for (int w = 0 ; w < config->readWorkers ; w++)
378
383
taskGroup.spawn ([&index, &preloadDeferredFile, &deferred]() {
379
- while (true ) {
384
+ while (!pageInQueue. stopAllWork ) {
380
385
size_t localIndex = index.fetch_add (1 );
381
386
if (localIndex >= deferred.size ())
382
387
break ;
383
388
preloadDeferredFile (deferred[localIndex]);
384
389
}
385
390
});
386
391
}
387
- #else
388
- for (const auto &file : deferred)
389
- preloadDeferredFile (file);
390
- #endif
391
392
392
393
auto dt = high_resolution_clock::now () - t0;
393
394
if (Process::GetEnv (" LLD_MULTI_THREAD_PAGE" ))
@@ -397,12 +398,12 @@ void multiThreadedPageInBackground(DeferredFiles &deferred) {
397
398
}
398
399
399
400
static void multiThreadedPageIn (const DeferredFiles &deferred) {
400
- static SerialBackgroundQueue pageInQueue;
401
401
pageInQueue.queueWork ([=]() {
402
402
DeferredFiles files = deferred;
403
403
multiThreadedPageInBackground (files);
404
404
});
405
405
}
406
+ #endif
406
407
407
408
static InputFile *processFile (std::optional<MemoryBufferRef> buffer,
408
409
DeferredFiles *archiveContents, StringRef path,
@@ -502,8 +503,10 @@ static InputFile *processFile(std::optional<MemoryBufferRef> buffer,
502
503
continue ;
503
504
}
504
505
506
+ #if LLVM_ENABLE_THREADS
505
507
if (archiveContents)
506
508
archiveContents->push_back ({path, isLazy, *mb});
509
+ #endif
507
510
if (!hasObjCSection (*mb))
508
511
continue ;
509
512
if (Error e = file->fetch (c, " -ObjC" ))
@@ -579,9 +582,11 @@ static void deferFile(StringRef path, bool isLazy, DeferredFiles &deferred) {
579
582
std::optional<MemoryBufferRef> buffer = readFile (path);
580
583
if (!buffer)
581
584
return ;
585
+ #if LLVM_ENABLE_THREADS
582
586
if (config->readWorkers )
583
587
deferred.push_back ({path, isLazy, *buffer});
584
588
else
589
+ #endif
585
590
processFile (buffer, nullptr , path, LoadType::CommandLine, isLazy);
586
591
}
587
592
@@ -1443,6 +1448,7 @@ static void createFiles(const InputArgList &args) {
1443
1448
}
1444
1449
}
1445
1450
1451
+ #if LLVM_ENABLE_THREADS
1446
1452
if (config->readWorkers ) {
1447
1453
multiThreadedPageIn (deferredFiles);
1448
1454
@@ -1459,7 +1465,10 @@ static void createFiles(const InputArgList &args) {
1459
1465
multiThreadedPageIn (archiveContents);
1460
1466
for (auto *archive : archives)
1461
1467
archive->addLazySymbols ();
1468
+
1469
+ pageInQueue.stopAllWork = true ;
1462
1470
}
1471
+ #endif
1463
1472
}
1464
1473
1465
1474
static void gatherInputSections () {
@@ -1847,13 +1856,17 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
1847
1856
}
1848
1857
1849
1858
if (auto *arg = args.getLastArg (OPT_read_workers)) {
1859
+ #if LLVM_ENABLE_THREADS
1850
1860
StringRef v (arg->getValue ());
1851
1861
unsigned workers = 0 ;
1852
1862
if (!llvm::to_integer (v, workers, 0 ))
1853
1863
error (arg->getSpelling () +
1854
1864
" : expected a non-negative integer, but got '" + arg->getValue () +
1855
1865
" '" );
1856
1866
config->readWorkers = workers;
1867
+ #else
1868
+ error (arg->getSpelling () + " : option unavailable" );
1869
+ #endif
1857
1870
}
1858
1871
if (auto *arg = args.getLastArg (OPT_threads_eq)) {
1859
1872
StringRef v (arg->getValue ());
0 commit comments