From fe9a4c1201a3e0867cbc0324c55cfe90dce9415b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 17 Oct 2007 06:24:50 +0000 Subject: [PATCH] Add infrastructure for threading support. --- gold/Makefile.am | 6 ++- gold/Makefile.in | 8 +++- gold/config.in | 3 ++ gold/configure | 41 +++++++++++++++++++- gold/configure.ac | 15 ++++++++ gold/gold-threads.cc | 25 +++++++------ gold/gold.cc | 27 +++++++++++++ gold/object.h | 5 +++ gold/options.cc | 25 ++++++++++++- gold/options.h | 77 ++++++++++++++++++++++++++++++++++++++ gold/testsuite/Makefile.am | 7 +++- gold/testsuite/Makefile.in | 34 ++++++++++++----- gold/workqueue.cc | 46 ++++++++++++++++++++--- gold/workqueue.h | 6 ++- 14 files changed, 292 insertions(+), 33 deletions(-) diff --git a/gold/Makefile.am b/gold/Makefile.am index 1c549867811..d05979e3cff 100644 --- a/gold/Makefile.am +++ b/gold/Makefile.am @@ -18,6 +18,10 @@ INCLUDES = -D_GNU_SOURCE \ LIBIBERTY = ../libiberty/libiberty.a +if THREADS +THREADSLIB = -lpthread +endif + AM_YFLAGS = -d noinst_PROGRAMS = ld-new @@ -95,7 +99,7 @@ libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) sources_var = main.cc deps_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL_DEP) -ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) +ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) $(THREADSLIB) ld_new_SOURCES = $(sources_var) ld_new_DEPENDENCIES = $(deps_var) $(LIBOBJS) diff --git a/gold/Makefile.in b/gold/Makefile.in index 5f0bac3b05c..4b1b9e2a969 100644 --- a/gold/Makefile.in +++ b/gold/Makefile.in @@ -91,7 +91,8 @@ ld_new_OBJECTS = $(am_ld_new_OBJECTS) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = ../libiberty/libiberty.a am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1) libgold.a \ - $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) am__DEPENDENCIES_4 = @LIBOBJS@ am__ld1_SOURCES_DIST = main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld1_OBJECTS = $(am__objects_4) @@ -210,6 +211,8 @@ STATIC_TLS_FALSE = @STATIC_TLS_FALSE@ STATIC_TLS_TRUE = @STATIC_TLS_TRUE@ STRIP = @STRIP@ TARGETOBJS = @TARGETOBJS@ +THREADS_FALSE = @THREADS_FALSE@ +THREADS_TRUE = @THREADS_TRUE@ TLS_FALSE = @TLS_FALSE@ TLS_TRUE = @TLS_TRUE@ USE_NLS = @USE_NLS@ @@ -275,6 +278,7 @@ INCLUDES = -D_GNU_SOURCE \ @INCINTL@ LIBIBERTY = ../libiberty/libiberty.a +@THREADS_TRUE@THREADSLIB = -lpthread AM_YFLAGS = -d noinst_LIBRARIES = libgold.a CCFILES = \ @@ -347,7 +351,7 @@ ALL_TARGETOBJS = \ libgold_a_SOURCES = $(CCFILES) $(HFILES) $(YFILES) sources_var = main.cc deps_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL_DEP) -ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) +ldadd_var = $(TARGETOBJS) libgold.a $(LIBIBERTY) $(LIBINTL) $(THREADSLIB) ld_new_SOURCES = $(sources_var) ld_new_DEPENDENCIES = $(deps_var) $(LIBOBJS) ld_new_LDADD = $(ldadd_var) $(LIBOBJS) diff --git a/gold/config.in b/gold/config.in index 9d1eba2e4b9..f46745d20d0 100644 --- a/gold/config.in +++ b/gold/config.in @@ -4,6 +4,9 @@ language is requested. */ #undef ENABLE_NLS +/* Define to do multi-threaded linking */ +#undef ENABLE_THREADS + /* Define to 1 if you have the header file. */ #undef HAVE_EXT_HASH_MAP diff --git a/gold/configure b/gold/configure index 1da2adf6c11..2490e255f2e 100755 --- a/gold/configure +++ b/gold/configure @@ -309,7 +309,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar TARGETOBJS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE YACC RANLIB ac_ct_RANLIB LN_S USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE NATIVE_LINKER_TRUE NATIVE_LINKER_FALSE GCC_TRUE GCC_FALSE FN_PTRS_IN_SO_WITHOUT_PIC_TRUE FN_PTRS_IN_SO_WITHOUT_PIC_FALSE TLS_TRUE TLS_FALSE STATIC_TLS_TRUE STATIC_TLS_FALSE WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS LIBOBJS CXXCPP EGREP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar THREADS_TRUE THREADS_FALSE TARGETOBJS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE YACC RANLIB ac_ct_RANLIB LN_S USE_NLS LIBINTL LIBINTL_DEP INCINTL XGETTEXT GMSGFMT POSUB CATALOGS DATADIRNAME INSTOBJEXT GENCAT CATOBJEXT MKINSTALLDIRS MSGFMT MSGMERGE NATIVE_LINKER_TRUE NATIVE_LINKER_FALSE GCC_TRUE GCC_FALSE FN_PTRS_IN_SO_WITHOUT_PIC_TRUE FN_PTRS_IN_SO_WITHOUT_PIC_FALSE TLS_TRUE TLS_FALSE STATIC_TLS_TRUE STATIC_TLS_FALSE WARN_CFLAGS NO_WERROR WARN_CXXFLAGS LFS_CXXFLAGS LIBOBJS CXXCPP EGREP MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -860,6 +860,7 @@ if test -n "$ac_init_help"; then Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-threads multi-threaded linking --enable-targets alternative target configurations --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors @@ -1897,6 +1898,35 @@ cat >>confdefs.h <<_ACEOF _ACEOF +# Check whether --enable-threads or --disable-threads was given. +if test "${enable_threads+set}" = set; then + enableval="$enable_threads" + case "${enableval}" in + yes | "") threads=yes ;; + no) threads=no ;; + *) threads=yes ;; + esac +else + threads=no +fi; +if test "$threads" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define ENABLE_THREADS 1 +_ACEOF + +fi + + +if test "$threads" = "yes"; then + THREADS_TRUE= + THREADS_FALSE='#' +else + THREADS_TRUE='#' + THREADS_FALSE= +fi + + # Check whether --enable-targets or --disable-targets was given. if test "${enable_targets+set}" = set; then enableval="$enable_targets" @@ -5791,6 +5821,13 @@ LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs +if test -z "${THREADS_TRUE}" && test -z "${THREADS_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"THREADS\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"THREADS\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 @@ -6430,6 +6467,8 @@ s,@am__leading_dot@,$am__leading_dot,;t t s,@AMTAR@,$AMTAR,;t t s,@am__tar@,$am__tar,;t t s,@am__untar@,$am__untar,;t t +s,@THREADS_TRUE@,$THREADS_TRUE,;t t +s,@THREADS_FALSE@,$THREADS_FALSE,;t t s,@TARGETOBJS@,$TARGETOBJS,;t t s,@CC@,$CC,;t t s,@CFLAGS@,$CFLAGS,;t t diff --git a/gold/configure.ac b/gold/configure.ac index aefd617470a..d8f71dfcb65 100644 --- a/gold/configure.ac +++ b/gold/configure.ac @@ -38,6 +38,21 @@ AC_DEFINE_UNQUOTED(TARGET_SYSTEM_ROOT, "$sysroot", AC_DEFINE_UNQUOTED(TARGET_SYSTEM_ROOT_RELOCATABLE, $sysroot_relocatable, [Whether the system root can be relocated]) +dnl For now threads are a configure time option. +AC_ARG_ENABLE([threads], +[ --enable-threads multi-threaded linking], +[case "${enableval}" in + yes | "") threads=yes ;; + no) threads=no ;; + *) threads=yes ;; + esac], +[threads=no]) +if test "$threads" = "yes"; then + AC_DEFINE(ENABLE_THREADS, 1, + [Define to do multi-threaded linking]) +fi +AM_CONDITIONAL(THREADS, test "$threads" = "yes") + AC_ARG_ENABLE([targets], [ --enable-targets alternative target configurations], [case "${enableval}" in diff --git a/gold/gold-threads.cc b/gold/gold-threads.cc index ad9506cc994..396e6c10631 100644 --- a/gold/gold-threads.cc +++ b/gold/gold-threads.cc @@ -22,6 +22,9 @@ #include "gold.h" +#include +#include + #ifdef ENABLE_THREADS #include #endif @@ -63,37 +66,37 @@ Lock_impl::Lock_impl() { pthread_mutexattr_t attr; if (pthread_mutexattr_init(&attr) != 0) - gold_fatal(_("pthead_mutextattr_init failed"), true); + gold_fatal(_("pthead_mutextattr_init failed: %s"), strerror(errno)); #ifdef PTHREAD_MUTEXT_ADAPTIVE_NP if (pthread_mutextattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP) != 0) - gold_fatal(_("pthread_mutextattr_settype failed"), true); + gold_fatal(_("pthread_mutextattr_settype failed: %s"), strerror(errno)); #endif if (pthread_mutex_init (&this->mutex_, &attr) != 0) - gold_fatal(_("pthread_mutex_init failed"), true); + gold_fatal(_("pthread_mutex_init failed: %s"), strerror(errno)); if (pthread_mutexattr_destroy(&attr) != 0) - gold_fatal(_("pthread_mutexattr_destroy failed"), true); + gold_fatal(_("pthread_mutexattr_destroy failed: %s"), strerror(errno)); } Lock_impl::~Lock_impl() { if (pthread_mutex_destroy(&this->mutex_) != 0) - gold_fatal(_("pthread_mutex_destroy failed"), true); + gold_fatal(_("pthread_mutex_destroy failed: %s"), strerror(errno)); } void Lock_impl::acquire() { if (pthread_mutex_lock(&this->mutex_) != 0) - gold_fatal(_("pthread_mutex_lock failed"), true); + gold_fatal(_("pthread_mutex_lock failed: %s"), strerror(errno)); } void Lock_impl::release() { if (pthread_mutex_unlock(&this->mutex_) != 0) - gold_fatal(_("pthread_mutex_unlock failed"), true); + gold_fatal(_("pthread_mutex_unlock failed: %s"), strerror(errno)); } #else // !defined(ENABLE_THREADS) @@ -174,27 +177,27 @@ class Condvar_impl Condvar_impl::Condvar_impl() { if (pthread_cond_init(&this->cond_, NULL) != 0) - gold_fatal(_("pthread_cond_init failed"), true); + gold_fatal(_("pthread_cond_init failed: %s"), strerror(errno)); } Condvar_impl::~Condvar_impl() { if (pthread_cond_destroy(&this->cond_) != 0) - gold_fatal(_("pthread_cond_destroy failed"), true); + gold_fatal(_("pthread_cond_destroy failed: %s"), strerror(errno)); } void Condvar_impl::wait(Lock_impl* li) { if (pthread_cond_wait(&this->cond_, &li->mutex_) != 0) - gold_fatal(_("pthread_cond_wait failed"), true); + gold_fatal(_("pthread_cond_wait failed: %s"), strerror(errno)); } void Condvar_impl::signal() { if (pthread_cond_signal(&this->cond_) != 0) - gold_fatal(_("pthread_cond_signal failed"), true); + gold_fatal(_("pthread_cond_signal failed: %s"), strerror(errno)); } #else // !defined(ENABLE_THREADS) diff --git a/gold/gold.cc b/gold/gold.cc index 8c86b9ed72e..86fc8e6847c 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -114,6 +114,15 @@ queue_initial_tasks(const General_options& options, Workqueue* workqueue, Input_objects* input_objects, Symbol_table* symtab, Layout* layout) { + int thread_count = options.thread_count_initial(); + if (thread_count == 0) + { + thread_count = cmdline.number_of_input_files(); + if (thread_count == 0) + thread_count = 1; + } + workqueue->set_thread_count(thread_count); + if (cmdline.begin() == cmdline.end()) gold_fatal(_("no input files")); @@ -152,6 +161,15 @@ queue_middle_tasks(const General_options& options, Layout* layout, Workqueue* workqueue) { + int thread_count = options.thread_count_middle(); + if (thread_count == 0) + { + thread_count = input_objects->number_of_input_objects(); + if (thread_count == 0) + thread_count = 1; + } + workqueue->set_thread_count(thread_count); + // Now we have seen all the input files. const bool doing_static_link = (!input_objects->any_dynamic() && !parameters->output_is_shared()); @@ -228,6 +246,15 @@ queue_final_tasks(const General_options& options, Workqueue* workqueue, Output_file* of) { + int thread_count = options.thread_count_final(); + if (thread_count == 0) + { + thread_count = input_objects->number_of_input_objects(); + if (thread_count == 0) + thread_count = 1; + } + workqueue->set_thread_count(thread_count); + // Use a blocker to block the final cleanup task. Task_token* final_blocker = new Task_token(); diff --git a/gold/object.h b/gold/object.h index 1b8c1e2440d..46e332f5051 100644 --- a/gold/object.h +++ b/gold/object.h @@ -828,6 +828,11 @@ class Input_objects any_dynamic() const { return !this->dynobj_list_.empty(); } + // Return the number of input objects. + int + number_of_input_objects() const + { return this->relobj_list_.size() + this->dynobj_list_.size(); } + private: Input_objects(const Input_objects&); Input_objects& operator=(const Input_objects&); diff --git a/gold/options.cc b/gold/options.cc index c01d947de53..6911e032a33 100644 --- a/gold/options.cc +++ b/gold/options.cc @@ -357,6 +357,25 @@ options::Command_line_options::options[] = GENERAL_ARG('\0', "Ttext", N_("Set the address of the .text section"), N_("-Ttext ADDRESS"), ONE_DASH, &General_options::set_text_segment_address), + GENERAL_NOARG('\0', "threads", N_("Run the linker multi-threaded"), + NULL, TWO_DASHES, &General_options::set_threads), + GENERAL_NOARG('\0', "no-threads", N_("Do not run the linker multi-threaded"), + NULL, TWO_DASHES, &General_options::clear_threads), + GENERAL_ARG('\0', "thread-count", N_("Number of threads to use"), + N_("--thread-count COUNT"), TWO_DASHES, + &General_options::set_thread_count), + GENERAL_ARG('\0', "thread-count-initial", + N_("Number of threads to use in initial pass"), + N_("--thread-count-initial COUNT"), TWO_DASHES, + &General_options::set_thread_count_initial), + GENERAL_ARG('\0', "thread-count-middle", + N_("Number of threads to use in middle pass"), + N_("--thread-count-middle COUNT"), TWO_DASHES, + &General_options::set_thread_count_middle), + GENERAL_ARG('\0', "thread-count-final", + N_("Number of threads to use in final pass"), + N_("--thread-count-final COUNT"), TWO_DASHES, + &General_options::set_thread_count_final), POSDEP_NOARG('\0', "whole-archive", N_("Include all archive contents"), NULL, TWO_DASHES, @@ -395,7 +414,11 @@ General_options::General_options() is_static_(false), print_stats_(false), sysroot_(), - text_segment_address_(-1U) // -1 indicates value not set by user + text_segment_address_(-1U), // -1 indicates value not set by user + threads_(false), + thread_count_initial_(0), + thread_count_middle_(0), + thread_count_final_(0) { } diff --git a/gold/options.h b/gold/options.h index d32dd4a5354..fd43de3daab 100644 --- a/gold/options.h +++ b/gold/options.h @@ -189,6 +189,26 @@ class General_options user_set_text_segment_address() const { return this->text_segment_address_ != -1U; } + // --threads: Whether to use threads. + bool + threads() const + { return this->threads_; } + + // --thread-count-initial: Threads to use in initial pass. + int + thread_count_initial() const + { return this->thread_count_initial_; } + + // --thread-count-middle: Threads to use in middle pass. + int + thread_count_middle() const + { return this->thread_count_middle_; } + + // --thread-count-final: Threads to use in final pass. + int + thread_count_final() const + { return this->thread_count_final_; } + private: // Don't copy this structure. General_options(const General_options&); @@ -288,6 +308,49 @@ class General_options } } + int + parse_thread_count(const char* arg) + { + char* endptr; + int count = strtol(arg, &endptr, 0); + if (*endptr != '\0' || count < 0) + { + fprintf(stderr, _("%s: invalid thread count: %s\n"), + program_name, arg); + ::exit(1); + } + return count; + } + + void + set_threads() + { this->threads_ = true; } + + void + clear_threads() + { this->threads_ = false; } + + void + set_thread_count(const char* arg) + { + int count = this->parse_thread_count(arg); + this->thread_count_initial_ = count; + this->thread_count_middle_ = count; + this->thread_count_final_ = count; + } + + void + set_thread_count_initial(const char* arg) + { this->thread_count_initial_ = this->parse_thread_count(arg); } + + void + set_thread_count_middle(const char* arg) + { this->thread_count_initial_ = this->parse_thread_count(arg); } + + void + set_thread_count_final(const char* arg) + { this->thread_count_initial_ = this->parse_thread_count(arg); } + void ignore(const char*) { } @@ -311,6 +374,10 @@ class General_options bool print_stats_; std::string sysroot_; uint64_t text_segment_address_; + bool threads_; + int thread_count_initial_; + int thread_count_middle_; + int thread_count_final_; }; // The current state of the position dependent options. @@ -543,6 +610,11 @@ class Input_arguments in_group() const { return this->in_group_; } + // The number of entries in the list. + int + size() const + { return this->input_argument_list_.size(); } + // Iterators to iterate over the list of input files. const_iterator @@ -594,6 +666,11 @@ class Command_line options() const { return this->options_; } + // The number of input files. + int + number_of_input_files() const + { return this->inputs_.size(); } + // Iterators to iterate over the list of input files. const_iterator diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index cfa2f1c54f7..bcbdcc34015 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -17,6 +17,10 @@ INCLUDES = -D_GNU_SOURCE \ -DLOCALEDIR="\"$(datadir)/locale\"" \ @INCINTL@ +if THREADS +THREADSLIB = -lpthread +endif + TESTS = object_unittest check_SCRIPTS = @@ -95,7 +99,8 @@ libgoldtest_a_SOURCES = test.cc testmain.cc testfile.cc DEPENDENCIES = \ libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL_DEP) -LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) +LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ + $(THREADSLIB) check_PROGRAMS = object_unittest $(NATIVE_PROGS) diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 302e2030b3c..b8ab3e5553b 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -63,40 +63,49 @@ target_triplet = @target@ check_PROGRAMS = object_unittest$(EXEEXT) $(am__EXEEXT_5) @GCC_FALSE@constructor_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) @NATIVE_LINKER_FALSE@constructor_test_DEPENDENCIES = libgoldtest.a \ @NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ @NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) @GCC_FALSE@constructor_static_test_DEPENDENCIES = libgoldtest.a \ @GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @NATIVE_LINKER_FALSE@constructor_static_test_DEPENDENCIES = \ @NATIVE_LINKER_FALSE@ libgoldtest.a ../libgold.a \ @NATIVE_LINKER_FALSE@ ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ @NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) @GCC_FALSE@two_file_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) @NATIVE_LINKER_FALSE@two_file_test_DEPENDENCIES = libgoldtest.a \ @NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ @NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) @GCC_FALSE@two_file_static_test_DEPENDENCIES = libgoldtest.a \ @GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @NATIVE_LINKER_FALSE@two_file_static_test_DEPENDENCIES = \ @NATIVE_LINKER_FALSE@ libgoldtest.a ../libgold.a \ @NATIVE_LINKER_FALSE@ ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ @NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) @GCC_FALSE@exception_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ -@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) +@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ +@GCC_FALSE@ $(am__DEPENDENCIES_1) @NATIVE_LINKER_FALSE@exception_test_DEPENDENCIES = libgoldtest.a \ @NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ @NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) @GCC_FALSE@exception_static_test_DEPENDENCIES = libgoldtest.a \ @GCC_FALSE@ ../libgold.a ../../libiberty/libiberty.a \ -@GCC_FALSE@ $(am__DEPENDENCIES_1) +@GCC_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) @NATIVE_LINKER_FALSE@exception_static_test_DEPENDENCIES = \ @NATIVE_LINKER_FALSE@ libgoldtest.a ../libgold.a \ @NATIVE_LINKER_FALSE@ ../../libiberty/libiberty.a \ +@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \ @NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) @GCC_FALSE@tls_test_DEPENDENCIES = @NATIVE_LINKER_FALSE@tls_test_DEPENDENCIES = @@ -221,7 +230,8 @@ am_object_unittest_OBJECTS = object_unittest.$(OBJEXT) object_unittest_OBJECTS = $(am_object_unittest_OBJECTS) object_unittest_LDADD = $(LDADD) object_unittest_DEPENDENCIES = libgoldtest.a ../libgold.a \ - ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) am__tls_pic_test_SOURCES_DIST = tls_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@@TLS_TRUE@am_tls_pic_test_OBJECTS = tls_test_main.$(OBJEXT) tls_pic_test_OBJECTS = $(am_tls_pic_test_OBJECTS) @@ -330,7 +340,8 @@ am__weak_test_SOURCES_DIST = weak_test.cc weak_test_OBJECTS = $(am_weak_test_OBJECTS) weak_test_LDADD = $(LDADD) weak_test_DEPENDENCIES = libgoldtest.a ../libgold.a \ - ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) + ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/../depcomp am__depfiles_maybe = depfiles @@ -473,6 +484,8 @@ STATIC_TLS_FALSE = @STATIC_TLS_FALSE@ STATIC_TLS_TRUE = @STATIC_TLS_TRUE@ STRIP = @STRIP@ TARGETOBJS = @TARGETOBJS@ +THREADS_FALSE = @THREADS_FALSE@ +THREADS_TRUE = @THREADS_TRUE@ TLS_FALSE = @TLS_FALSE@ TLS_TRUE = @TLS_TRUE@ USE_NLS = @USE_NLS@ @@ -538,6 +551,7 @@ INCLUDES = -D_GNU_SOURCE \ -DLOCALEDIR="\"$(datadir)/locale\"" \ @INCINTL@ +@THREADS_TRUE@THREADSLIB = -lpthread TESTS = object_unittest $(NATIVE_TESTING) check_SCRIPTS = @GCC_TRUE@@NATIVE_LINKER_TRUE@NATIVE_PROGS = constructor_test \ @@ -572,7 +586,9 @@ libgoldtest_a_SOURCES = test.cc testmain.cc testfile.cc DEPENDENCIES = \ libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL_DEP) -LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) +LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \ + $(THREADSLIB) + object_unittest_SOURCES = object_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_SOURCES = constructor_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@constructor_test_DEPENDENCIES = gcctestdir/ld diff --git a/gold/workqueue.cc b/gold/workqueue.cc index 2c7e8803207..95c14ce5a85 100644 --- a/gold/workqueue.cc +++ b/gold/workqueue.cc @@ -22,6 +22,10 @@ #include "gold.h" +#ifdef ENABLE_THREADS +#include +#endif + #include "workqueue.h" namespace gold @@ -153,7 +157,13 @@ class Workqueue_runner { } // Run a task. This is always called in the main thread. - virtual void run(Task*, Task_locker*) = 0; + virtual void + run(Task*, Task_locker*) = 0; + + // Set the number of threads to use. This is ignored when not using + // threads. + virtual void + set_thread_count(int) = 0; protected: // This is called by an implementation when a task is completed. @@ -178,7 +188,11 @@ class Workqueue_runner_single : public Workqueue_runner ~Workqueue_runner_single() { } - void run(Task*, Task_locker*); + void + run(Task*, Task_locker*); + + void + set_thread_count(int); }; void @@ -188,9 +202,15 @@ Workqueue_runner_single::run(Task* t, Task_locker* tl) this->completed(t, tl); } +void +Workqueue_runner_single::set_thread_count(int thread_count) +{ + gold_assert(thread_count > 0); +} + // Workqueue methods. -Workqueue::Workqueue(const General_options&) +Workqueue::Workqueue(const General_options& options) : tasks_lock_(), tasks_(), completed_lock_(), @@ -199,9 +219,14 @@ Workqueue::Workqueue(const General_options&) completed_condvar_(this->completed_lock_), cleared_blockers_(0) { - // At some point we will select the specific implementation of - // Workqueue_runner to use based on the command line options. - this->runner_ = new Workqueue_runner_single(this); + bool threads = options.threads(); +#ifndef ENABLE_THREADS + threads = false; +#endif + if (!threads) + this->runner_ = new Workqueue_runner_single(this); + else + gold_unreachable(); } Workqueue::~Workqueue() @@ -421,4 +446,13 @@ Workqueue::cleared_blocker() ++this->cleared_blockers_; } +// Set the number of threads to use for the workqueue, if we are using +// threads. + +void +Workqueue::set_thread_count(int threads) +{ + this->runner_->set_thread_count(threads); +} + } // End namespace gold. diff --git a/gold/workqueue.h b/gold/workqueue.h index 0b88f9411f0..777b3aa0918 100644 --- a/gold/workqueue.h +++ b/gold/workqueue.h @@ -47,7 +47,7 @@ class Task; class Workqueue; // Some tasks require access to shared data structures, such as the -// symbol table. Some tasks must be executed in a particular error, +// symbol table. Some tasks must be executed in a particular order, // such as reading input file symbol tables--if we see foo.o -llib, we // have to read the symbols for foo.o before we read the ones for // -llib. To implement this safely and efficiently, we use tokens. @@ -391,6 +391,10 @@ class Workqueue void cleared_blocker(); + // Set the thread count. + void + set_thread_count(int); + private: // This class can not be copied. Workqueue(const Workqueue&); -- 2.30.2