X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gold%2Fgold-threads.h;h=e82bb50b299b809cf5d82ad6bc5966d73ecc88de;hb=1074bc6d41f480e9e7b8f2e68f778225da2559b7;hp=e2a8388ac1361b3baa8050affcb430794095e275;hpb=bae7f79e03d6405f5ceec0e3e24671e6b30f29ed;p=binutils-gdb.git diff --git a/gold/gold-threads.h b/gold/gold-threads.h index e2a8388ac13..e82bb50b299 100644 --- a/gold/gold-threads.h +++ b/gold/gold-threads.h @@ -1,5 +1,25 @@ // gold-threads.h -- thread support for gold -*- C++ -*- +// Copyright (C) 2006-2018 Free Software Foundation, Inc. +// Written by Ian Lance Taylor . + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + // gold can be configured to support threads. If threads are // supported, the user can specify at runtime whether or not to // support them. This provides an interface to manage locking @@ -14,8 +34,28 @@ namespace gold { -class Lock_impl; class Condvar; +class Once_initialize; +class Initialize_lock_once; + +// The interface for the implementation of a Lock. + +class Lock_impl +{ + public: + Lock_impl() + { } + + virtual + ~Lock_impl() + { } + + virtual void + acquire() = 0; + + virtual void + release() = 0; +}; // A simple lock class. @@ -23,15 +63,18 @@ class Lock { public: Lock(); + ~Lock(); // Acquire the lock. void - acquire(); + acquire() + { this->lock_->acquire(); } // Release the lock. void - release(); + release() + { this->lock_->release(); } private: // This class can not be copied. @@ -66,7 +109,50 @@ class Hold_lock Lock& lock_; }; -class Condvar_impl; +class Hold_optional_lock +{ + public: + Hold_optional_lock(Lock* lock) + : lock_(lock) + { + if (this->lock_ != NULL) + this->lock_->acquire(); + } + + ~Hold_optional_lock() + { + if (this->lock_ != NULL) + this->lock_->release(); + } + + private: + Hold_optional_lock(const Hold_optional_lock&); + Hold_optional_lock& operator=(const Hold_optional_lock&); + + Lock* lock_; +}; + +// The interface for the implementation of a condition variable. + +class Condvar_impl +{ + public: + Condvar_impl() + { } + + virtual + ~Condvar_impl() + { } + + virtual void + wait(Lock_impl*) = 0; + + virtual void + signal() = 0; + + virtual void + broadcast() = 0; +}; // A simple condition variable class. It is always associated with a // specific lock. @@ -80,12 +166,22 @@ class Condvar // Wait for the condition variable to be signalled. This should // only be called when the lock is held. void - wait(); + wait() + { this->condvar_->wait(this->lock_.get_impl()); } - // Signal the condition variable. This should only be called when - // the lock is held. + // Signal the condition variable--wake up at least one thread + // waiting on the condition variable. This should only be called + // when the lock is held. void - signal(); + signal() + { this->condvar_->signal(); } + + // Broadcast the condition variable--wake up all threads waiting on + // the condition variable. This should only be called when the lock + // is held. + void + broadcast() + { this->condvar_->broadcast(); } private: // This class can not be copied. @@ -96,6 +192,76 @@ class Condvar Condvar_impl* condvar_; }; +// A class used to do something once. This is an abstract parent +// class; any actual use will involve a child of this. + +class Once +{ + public: + Once(); + + virtual + ~Once() + { } + + // Call this function to do whatever it is. We pass an argument + // even though you have to use a child class because in some uses + // setting the argument would itself require a Once class. + void + run_once(void* arg); + + // This is an internal function, which must be public because it is + // run by an extern "C" function called via pthread_once. + void + internal_run(void* arg); + + protected: + // This must be implemented by the child class. + virtual void + do_run_once(void* arg) = 0; + + private: + // True if we have already run the function. + bool was_run_; +#if defined(ENABLE_THREADS) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) + // Internal compare-and-swap lock on was_run_; + uint32_t was_run_lock_; +#endif + // The lock to run the function only once. + Once_initialize* once_; +}; + +// A class used to initialize a lock exactly once, after the options +// have been read. This is needed because the implementation of locks +// depends on whether we've seen the --threads option. Before the +// options have been read, we know we are single-threaded, so we can +// get by without using a lock. This class should be an instance +// variable of the class which has a lock which needs to be +// initialized. + +class Initialize_lock : public Once +{ + public: + // The class which uses this will have a pointer to a lock. This + // must be constructed with a pointer to that pointer. + Initialize_lock(Lock** pplock) + : pplock_(pplock) + { } + + // Initialize the lock. Return true if the lock is now initialized, + // false if it is not (because the options have not yet been read). + bool + initialize(); + + protected: + void + do_run_once(void*); + + private: + // A pointer to the lock pointer which must be initialized. + Lock** const pplock_; +}; + } // End namespace gold. #endif // !defined(GOLD_THREADS_H)