Default to --allow-shlib-undefined for now.
[deliverable/binutils-gdb.git] / gold / workqueue.cc
index 860484ebdc6282174f156790efbb990da726d754..95c14ce5a8594dd970fa35054f872c1dfb3bef4a 100644 (file)
@@ -1,6 +1,31 @@
 // workqueue.cc -- the workqueue for gold
 
+// Copyright 2006, 2007 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.
+
 #include "gold.h"
+
+#ifdef ENABLE_THREADS
+#include <pthread.h>
+#endif
+
 #include "workqueue.h"
 
 namespace gold
@@ -15,59 +40,59 @@ Task_token::Task_token()
 
 Task_token::~Task_token()
 {
-  assert(this->readers_ == 0 && this->writer_ == NULL);
+  gold_assert(this->readers_ == 0 && this->writer_ == NULL);
 }
 
 bool
 Task_token::is_readable() const
 {
-  assert(!this->is_blocker_);
+  gold_assert(!this->is_blocker_);
   return this->writer_ == NULL;
 }
 
 void
 Task_token::add_reader()
 {
-  assert(!this->is_blocker_);
-  assert(this->is_readable());
+  gold_assert(!this->is_blocker_);
+  gold_assert(this->is_readable());
   ++this->readers_;
 }
 
 void
 Task_token::remove_reader()
 {
-  assert(!this->is_blocker_);
-  assert(this->readers_ > 0);
+  gold_assert(!this->is_blocker_);
+  gold_assert(this->readers_ > 0);
   --this->readers_;
 }
 
 bool
 Task_token::is_writable() const
 {
-  assert(!this->is_blocker_);
+  gold_assert(!this->is_blocker_);
   return this->writer_ == NULL && this->readers_ == 0;
 }
 
 void
 Task_token::add_writer(const Task* t)
 {
-  assert(!this->is_blocker_);
-  assert(this->is_writable());
+  gold_assert(!this->is_blocker_);
+  gold_assert(this->is_writable());
   this->writer_ = t;
 }
 
 void
 Task_token::remove_writer(const Task* t)
 {
-  assert(!this->is_blocker_);
-  assert(this->writer_ == t);
+  gold_assert(!this->is_blocker_);
+  gold_assert(this->writer_ == t);
   this->writer_ = NULL;
 }
 
 bool
 Task_token::has_write_lock(const Task* t)
 {
-  assert(!this->is_blocker_);
+  gold_assert(!this->is_blocker_);
   return this->writer_ == t;
 }
 
@@ -79,14 +104,14 @@ Task_token::add_blocker()
   if (this->readers_ == 0 && this->writer_ == NULL)
     this->is_blocker_ = true;
   else
-    assert(this->is_blocker_);
+    gold_assert(this->is_blocker_);
   ++this->readers_;
 }
 
 bool
 Task_token::remove_blocker()
 {
-  assert(this->is_blocker_ && this->readers_ > 0);
+  gold_assert(this->is_blocker_ && this->readers_ > 0);
   --this->readers_;
   return this->readers_ == 0;
 }
@@ -94,7 +119,8 @@ Task_token::remove_blocker()
 bool
 Task_token::is_blocked() const
 {
-  assert(this->is_blocker_ || (this->readers_ == 0 && this->writer_ == NULL));
+  gold_assert(this->is_blocker_
+             || (this->readers_ == 0 && this->writer_ == NULL));
   return this->readers_ > 0;
 }
 
@@ -106,7 +132,7 @@ Task_block_token::Task_block_token(Task_token& token, Workqueue* workqueue)
   // We must increment the block count when the task is created and
   // put on the queue.  This object is created when the task is run,
   // so we don't increment the block count here.
-  assert(this->token_.is_blocked());
+  gold_assert(this->token_.is_blocked());
 }
 
 Task_block_token::~Task_block_token()
@@ -131,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.
@@ -156,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
@@ -166,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_(),
@@ -177,18 +219,25 @@ 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()
 {
-  assert(this->tasks_.empty());
-  assert(this->completed_.empty());
-  assert(this->running_ == 0);
+  gold_assert(this->tasks_.empty());
+  gold_assert(this->completed_.empty());
+  gold_assert(this->running_ == 0);
 }
 
+// Add a task to the queue.
+
 void
 Workqueue::queue(Task* t)
 {
@@ -196,6 +245,15 @@ Workqueue::queue(Task* t)
   this->tasks_.push_back(t);
 }
 
+// Add a task to the front of the queue.
+
+void
+Workqueue::queue_front(Task* t)
+{
+  Hold_lock hl(this->tasks_lock_);
+  this->tasks_.push_front(t);
+}
+
 // Clear the list of completed tasks.  Return whether we cleared
 // anything.  The completed_lock_ must be held when this is called.
 
@@ -249,7 +307,7 @@ Workqueue::find_runnable(Task_list& tasks, bool* all_blocked)
              {
                // There had better be some tasks running, or we will
                // never find a runnable task.
-               assert(this->running_ > 0);
+               gold_assert(this->running_ > 0);
 
                // We couldn't find any runnable tasks, and we
                // couldn't release any locks.
@@ -308,7 +366,7 @@ Workqueue::process()
 
            // There must be something for us to wait for, or we won't
            // be able to make progress.
-           assert(this->running_ > 0 || !this->completed_.empty());
+           gold_assert(this->running_ > 0 || !this->completed_.empty());
 
            if (all_blocked)
              {
@@ -316,7 +374,7 @@ Workqueue::process()
                this->clear_completed();
                while (this->cleared_blockers_ == 0)
                  {
-                   assert(this->running_ > 0);
+                   gold_assert(this->running_ > 0);
                    this->completed_condvar_.wait();
                    this->clear_completed();
                  }
@@ -371,7 +429,7 @@ Workqueue::completed(Task* t, Task_locker* tl)
 {
   {
     Hold_lock hl(this->completed_lock_);
-    assert(this->running_ > 0);
+    gold_assert(this->running_ > 0);
     --this->running_;
     this->completed_.push_back(tl);
     this->completed_condvar_.signal();
@@ -388,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.
This page took 0.026332 seconds and 4 git commands to generate.