- bool didSomething = false;
- for (std::vector<ld::File*>::const_iterator it=_inputFiles.begin(); it != _inputFiles.end(); ++it) {
- didSomething |= (*it)->forEachAtom(handler);
- }
- if ( didSomething || true ) {
- switch ( _options.outputKind() ) {
- case Options::kStaticExecutable:
- case Options::kDynamicExecutable:
- // add implicit __dso_handle label
- handler.doAtom(DSOHandleAtom::_s_atomExecutable);
- handler.doAtom(DSOHandleAtom::_s_atomAll);
- if ( _options.pageZeroSize() != 0 )
- handler.doAtom(*new PageZeroAtom(_options.pageZeroSize()));
- if ( _options.hasCustomStack() )
- handler.doAtom(*new CustomStackAtom(_options.customStackSize()));
- break;
- case Options::kDynamicLibrary:
- // add implicit __dso_handle label
- handler.doAtom(DSOHandleAtom::_s_atomDylib);
- handler.doAtom(DSOHandleAtom::_s_atomAll);
- break;
- case Options::kDynamicBundle:
- // add implicit __dso_handle label
- handler.doAtom(DSOHandleAtom::_s_atomBundle);
- handler.doAtom(DSOHandleAtom::_s_atomAll);
+ if (_s_logPThreads) printf("starting pipeline listener\n");
+ try {
+ const char *fifo = _options.pipelineFifo();
+ assert(fifo);
+ std::map<const char *, const Options::FileInfo*, strcompclass> fileMap;
+ const std::vector<Options::FileInfo>& files = _options.getInputFiles();
+ for (std::vector<Options::FileInfo>::const_iterator it = files.begin(); it != files.end(); ++it) {
+ const Options::FileInfo& entry = *it;
+ if (entry.fromFileList) {
+ fileMap[entry.path] = &entry;
+ }
+ }
+ FILE *fileStream = fopen(fifo, "r");
+ if (!fileStream)
+ throwf("pipelined linking error - failed to open stream. fopen() returns %s for \"%s\"\n", strerror(errno), fifo);
+ while (fileMap.size() > 0) {
+ char path_buf[PATH_MAX+1];
+ if (fgets(path_buf, PATH_MAX, fileStream) == NULL)
+ throwf("pipelined linking error - %lu missing input files", fileMap.size());
+ int len = strlen(path_buf);
+ if (path_buf[len-1] == '\n')
+ path_buf[len-1] = 0;
+ std::map<const char *, const Options::FileInfo*, strcompclass>::iterator it = fileMap.find(path_buf);
+ if (it == fileMap.end())
+ throwf("pipelined linking error - not in file list: %s\n", path_buf);
+ Options::FileInfo* inputInfo = (Options::FileInfo*)it->second;
+ if (!inputInfo->checkFileExists(_options))
+ throwf("pipelined linking error - file does not exist: %s\n", inputInfo->path);
+ pthread_mutex_lock(&_parseLock);
+ if (_idleWorkers)
+ pthread_cond_signal(&_parseWorkReady);
+ inputInfo->readyToParse = true;
+ if (_parseCursor > inputInfo->inputFileSlot)
+ _parseCursor = inputInfo->inputFileSlot;
+ _availableInputFiles++;
+ if (_s_logPThreads) printf("pipeline listener: %s slot=%d, _parseCursor=%d, _availableInputFiles = %d remaining = %ld\n", path_buf, inputInfo->inputFileSlot, _parseCursor, _availableInputFiles, fileMap.size()-1);
+ pthread_mutex_unlock(&_parseLock);
+ fileMap.erase(it);
+ }
+ } catch (const char *msg) {
+ pthread_mutex_lock(&_parseLock);
+ _exception = msg;
+ pthread_cond_signal(&_newFileAvailable);
+ pthread_mutex_unlock(&_parseLock);
+ }
+}
+
+
+void InputFiles::waitForInputFiles(InputFiles *inputFiles) {
+ inputFiles->waitForInputFiles();
+}
+#endif
+
+
+void InputFiles::forEachInitialAtom(ld::File::AtomHandler& handler, ld::Internal& state)
+{
+ // add all direct object, archives, and dylibs
+ const std::vector<Options::FileInfo>& files = _options.getInputFiles();
+ size_t fileIndex;
+ for (fileIndex=0; fileIndex<_inputFiles.size(); fileIndex++) {
+ ld::File *file;
+#if HAVE_PTHREADS
+ pthread_mutex_lock(&_parseLock);
+
+ // this loop waits for the needed file to be ready (parsed by worker thread)
+ while (_inputFiles[fileIndex] == NULL && _exception == NULL) {
+ // We are starved for input. If there are still files to parse and we have
+ // not maxed out the worker thread count start a new worker thread.
+ if (_availableInputFiles > 0 && _availableWorkers > 0) {
+ if (_s_logPThreads) printf("starting worker\n");
+ startThread(InputFiles::parseWorkerThread);
+ _availableWorkers--;
+ }
+ _neededFileSlot = fileIndex;
+ if (_s_logPThreads) printf("consumer blocking for %lu: %s\n", fileIndex, files[fileIndex].path);
+ pthread_cond_wait(&_newFileAvailable, &_parseLock);
+ }
+
+ if (_exception)
+ throw _exception;
+
+ // The input file is parsed. Assimilate it and call its atom iterator.
+ if (_s_logPThreads) printf("consuming slot %lu\n", fileIndex);
+ file = _inputFiles[fileIndex];
+ pthread_mutex_unlock(&_parseLock);
+#else
+ file = _inputFiles[fileIndex];
+#endif
+ const Options::FileInfo& info = files[fileIndex];
+ switch (file->type()) {
+ case ld::File::Reloc:
+ {
+ ld::relocatable::File* reloc = (ld::relocatable::File*)file;
+ _options.snapshot().recordObjectFile(reloc->path());
+ if ( _options.dumpDependencyInfo() )
+ _options.dumpDependency(Options::depObjectFile, reloc->path());
+ }