123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- // workqueue-threads.cc -- the threaded workqueue for gold
- // Copyright (C) 2007-2022 Free Software Foundation, Inc.
- // Written by Ian Lance Taylor <iant@google.com>.
- // 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.
- // This file holds the workqueue implementation which may be used when
- // using threads.
- #include "gold.h"
- #ifdef ENABLE_THREADS
- #include <cstring>
- #include <pthread.h>
- #include "debug.h"
- #include "gold-threads.h"
- #include "workqueue.h"
- #include "workqueue-internal.h"
- namespace gold
- {
- // Class Workqueue_thread represents a single thread. Creating an
- // instance of this spawns a new thread.
- class Workqueue_thread
- {
- public:
- Workqueue_thread(Workqueue_threader_threadpool*, int thread_number);
- ~Workqueue_thread();
- private:
- // This class can not be copied.
- Workqueue_thread(const Workqueue_thread&);
- Workqueue_thread& operator=(const Workqueue_thread&);
- // Check for error from a pthread function.
- void
- check(const char* function, int err) const;
- // A function to pass to pthread_create. This is called with a
- // pointer to an instance of this object.
- static void*
- thread_body(void*);
- // A pointer to the threadpool that this thread is part of.
- Workqueue_threader_threadpool* threadpool_;
- // The thread number.
- int thread_number_;
- // The thread ID.
- pthread_t tid_;
- };
- // Create the thread in the constructor.
- Workqueue_thread::Workqueue_thread(Workqueue_threader_threadpool* threadpool,
- int thread_number)
- : threadpool_(threadpool), thread_number_(thread_number)
- {
- pthread_attr_t attr;
- int err = pthread_attr_init(&attr);
- this->check("pthread_attr_init", err);
- err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- this->check("pthread_attr_setdetachstate", err);
- err = pthread_create(&this->tid_, &attr, &Workqueue_thread::thread_body,
- reinterpret_cast<void*>(this));
- this->check("pthread_create", err);
- err = pthread_attr_destroy(&attr);
- this->check("pthread_attr_destroy", err);
- }
- // The destructor will be called when the thread is exiting.
- Workqueue_thread::~Workqueue_thread()
- {
- }
- // Check for an error.
- void
- Workqueue_thread::check(const char* function, int err) const
- {
- if (err != 0)
- gold_fatal(_("%s failed: %s"), function, strerror(err));
- }
- // Passed to pthread_create.
- extern "C"
- void*
- Workqueue_thread::thread_body(void* arg)
- {
- Workqueue_thread* pwt = reinterpret_cast<Workqueue_thread*>(arg);
- pwt->threadpool_->process(pwt->thread_number_);
- // Delete the thread object as we exit.
- delete pwt;
- return NULL;
- }
- // Class Workqueue_threader_threadpool.
- // Constructor.
- Workqueue_threader_threadpool::Workqueue_threader_threadpool(
- Workqueue* workqueue)
- : Workqueue_threader(workqueue),
- check_thread_count_(0),
- lock_(),
- desired_thread_count_(1),
- threads_(1)
- {
- }
- // Destructor.
- Workqueue_threader_threadpool::~Workqueue_threader_threadpool()
- {
- // Tell the threads to exit.
- this->get_workqueue()->set_thread_count(0);
- }
- // Set the thread count.
- void
- Workqueue_threader_threadpool::set_thread_count(int thread_count)
- {
- int create;
- {
- Hold_lock hl(this->lock_);
- this->desired_thread_count_ = thread_count;
- create = this->desired_thread_count_ - this->threads_;
- if (create < 0)
- this->check_thread_count_ = 1;
- }
- if (create > 0)
- {
- for (int i = 0; i < create; ++i)
- {
- // Note that threads delete themselves when they exit, so we
- // don't keep pointers to them.
- new Workqueue_thread(this, this->threads_);
- ++this->threads_;
- }
- }
- }
- // Return whether the current thread should be cancelled.
- bool
- Workqueue_threader_threadpool::should_cancel_thread(int thread_number)
- {
- // Fast exit without taking a lock.
- if (!this->check_thread_count_)
- return false;
- {
- Hold_lock hl(this->lock_);
- if (thread_number > this->desired_thread_count_)
- {
- --this->threads_;
- if (this->threads_ <= this->desired_thread_count_)
- this->check_thread_count_ = 0;
- return true;
- }
- }
- return false;
- }
- } // End namespace gold.
- #endif // defined(ENABLE_THREADS)
|