From 7f055c204a4371154123a1816fbec9855ee60ad5 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 24 Mar 2009 04:50:32 +0000 Subject: 2009-03-23 Ian Lance Taylor * gold-threads.h (class Initialize_lock): Define. * gold-threads.cc (class Initialize_lock_once): Define. (initialize_lock_control): New static variable. (initialize_lock_pointer): New static variable. (initialize_lock_once): New static function. (Initialize_lock::Initialize_lock): Define. (Initialize_lock::initialize): Define. * target-select.h: Include "gold-threads.h". (class Target_selector): Add lock_ and initialize_lock_ fields. Don't define instantiate_target, just declare it. * target-select.cc (Target_selector::Target_selector): Initialize new fields. (Target_selector::instantiate_target): Define. * descriptors.h: Include "gold-threads.h". (class Descriptors): Add initialize_lock_ field. * descriptors.cc (Descriptors::Descriptors): Initialize new field. (Descriptors::open): Use initialize_lock_ field * errors.h (class Errors): Add initialize_lock_ field. * errors.cc (Errors::Errors): Initialize new field. (Errors::initialize_lock): Use initialize_lock_ field. * powerpc.cc (class Target_selector_powerpc): Remove instantiated_target_ field. In do_recognize call instantiate_target rather than do_instantiate_target. In do_instantiate_target just allocate a new target. * sparc.cc (class Target_selector_sparc): Likewise. --- gold/gold-threads.cc | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) (limited to 'gold/gold-threads.cc') diff --git a/gold/gold-threads.cc b/gold/gold-threads.cc index 9aa883d6cc..347170814d 100644 --- a/gold/gold-threads.cc +++ b/gold/gold-threads.cc @@ -276,4 +276,128 @@ Condvar::~Condvar() delete this->condvar_; } +#ifdef ENABLE_THREADS + +// Class Initialize_lock_once. This exists to hold a pthread_once_t +// structure for Initialize_lock. + +class Initialize_lock_once +{ + public: + Initialize_lock_once() + : once_(PTHREAD_ONCE_INIT) + { } + + // Return a pointer to the pthread_once_t variable. + pthread_once_t* + once_control() + { return &this->once_; } + + private: + pthread_once_t once_; +}; + +#endif // !defined(ENABLE_THREADS) + +#ifdef ENABLE_THREADS + +// A single lock which controls access to initialize_lock_pointer. +// This is used because we can't pass parameters to functions passed +// to pthread_once. + +static pthread_mutex_t initialize_lock_control = PTHREAD_MUTEX_INITIALIZER; + +// A pointer to a pointer to the lock which we need to initialize +// once. Access to this is controlled by initialize_lock_pointer. + +static Lock** initialize_lock_pointer; + +// A routine passed to pthread_once which initializes the lock which +// initialize_lock_pointer points to. + +extern "C" +{ + +static void +initialize_lock_once() +{ + *initialize_lock_pointer = new Lock(); +} + +} + +#endif // !defined(ENABLE_THREADS) + +// Class Initialize_lock. + +Initialize_lock::Initialize_lock(Lock** pplock) + : pplock_(pplock) +{ +#ifndef ENABLE_THREADS + this->once_ = NULL; +#else + this->once_ = new Initialize_lock_once(); +#endif +} + +// Initialize the lock. + +bool +Initialize_lock::initialize() +{ + // If the lock has already been initialized, we don't need to do + // anything. Note that this assumes that the pointer value will be + // set completely or not at all. I hope this is always safe. We + // want to do this for efficiency. + if (*this->pplock_ != NULL) + return true; + + // We can't initialize the lock until we have read the options. + if (!parameters->options_valid()) + return false; + + // If the user did not use --threads, then we can initialize + // directly. + if (!parameters->options().threads()) + { + *this->pplock_ = new Lock(); + return true; + } + +#ifndef ENABLE_THREADS + + // If there is no threads support, we don't need to use + // pthread_once. + *this->pplock_ = new Lock(); + +#else // !defined(ENABLE_THREADS) + + // Since we can't pass parameters to routines called by + // pthread_once, we use a static variable: initialize_lock_pointer. + // That in turns means that we need to use a mutex to control access + // to initialize_lock_pointer. + + int err = pthread_mutex_lock(&initialize_lock_control); + if (err != 0) + gold_fatal(_("pthread_mutex_lock failed: %s"), strerror(err)); + + initialize_lock_pointer = this->pplock_; + + err = pthread_once(this->once_->once_control(), initialize_lock_once); + if (err != 0) + gold_fatal(_("pthread_once failed: %s"), strerror(err)); + + initialize_lock_pointer = NULL; + + err = pthread_mutex_unlock(&initialize_lock_control); + if (err != 0) + gold_fatal(_("pthread_mutex_unlock failed: %s"), strerror(err)); + + gold_assert(*this->pplock_ != NULL); + +#endif // !defined(ENABLE_THREADS) + + return true; +} + } // End namespace gold. -- cgit v1.2.3