// workqueue.cc -- the workqueue for gold

// Copyright 2006, 2007, 2008 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"

#include "debug.h"
#include "options.h"
#include "timer.h"
#include "workqueue.h"
#include "workqueue-internal.h"

namespace gold
{

// Class Task_list.

// Add T to the end of the list.

inline void
Task_list::push_back(Task* t)
{
  gold_assert(t->list_next() == NULL);
  if (this->head_ == NULL)
    {
      this->head_ = t;
      this->tail_ = t;
    }
  else
    {
      this->tail_->set_list_next(t);
      this->tail_ = t;
    }
}

// Add T to the front of the list.

inline void
Task_list::push_front(Task* t)
{
  gold_assert(t->list_next() == NULL);
  if (this->head_ == NULL)
    {
      this->head_ = t;
      this->tail_ = t;
    }
  else
    {
      t->set_list_next(this->head_);
      this->head_ = t;
    }
}

// Remove and return the first Task waiting for this lock to be
// released.

inline Task*
Task_list::pop_front()
{
  Task* ret = this->head_;
  if (ret != NULL)
    {
      if (ret == this->tail_)
	{
	  gold_assert(ret->list_next() == NULL);
	  this->head_ = NULL;
	  this->tail_ = NULL;
	}
      else
	{
	  this->head_ = ret->list_next();
	  gold_assert(this->head_ != NULL);
	  ret->clear_list_next();
	}
    }
  return ret;
}

// The simple single-threaded implementation of Workqueue_threader.

class Workqueue_threader_single : public Workqueue_threader
{
 public:
  Workqueue_threader_single(Workqueue* workqueue)
    : Workqueue_threader(workqueue)
  { }
  ~Workqueue_threader_single()
  { }

  void
  set_thread_count(int thread_count)
  { gold_assert(thread_count > 0); }

  bool
  should_cancel_thread()
  { return false; }
};

// Workqueue methods.

Workqueue::Workqueue(const General_options& options)
  : lock_(),
    first_tasks_(),
    tasks_(),
    running_(0),
    waiting_(0),
    condvar_(this->lock_),
    threader_(NULL)
{
  bool threads = options.threads();
#ifndef ENABLE_THREADS
  threads = false;
#endif
  if (!threads)
    this->threader_ = new Workqueue_threader_single(this);
  else
    {
#ifdef ENABLE_THREADS
      this->threader_ = new Workqueue_threader_threadpool(this);
#else
      gold_unreachable();
#endif
    }
}

Workqueue::~Workqueue()
{
}

// Add a task to the end of a specific queue, or put it on the list
// waiting for a Token.

void
Workqueue::add_to_queue(Task_list* queue, Task* t, bool front)
{
  Hold_lock hl(this->lock_);

  Task_token* token = t->is_runnable();
  if (token != NULL)
    {
      if (front)
	token->add_waiting_front(t);
      else
	token->add_waiting(t);
      ++this->waiting_;
    }
  else
    {
      if (front)
	queue->push_front(t);
      else
	queue->push_back(t);
      // Tell any waiting thread that there is work to do.
      this->condvar_.signal();
    }
}

// Add a task to the queue.

void
Workqueue::queue(Task* t)
{
  this->add_to_queue(&this->tasks_, t, false);
}

// Queue a task which should run soon.

void
Workqueue::queue_soon(Task* t)
{
  t->set_should_run_soon();
  this->add_to_queue(&this->first_tasks_, t, false);
}

// Queue a task which should run next.

void
Workqueue::queue_next(Task* t)
{
  t->set_should_run_soon();
  this->add_to_queue(&this->first_tasks_, t, true);
}

// Return whether to cancel the current thread.

inline bool
Workqueue::should_cancel_thread()
{
  return this->threader_->should_cancel_thread();
}

// Find a runnable task in TASKS.  Return NULL if none could be found.
// If we find a Task waiting for a Token, add it to the list for that
// Token.  The workqueue lock must be held when this is called.

Task*
Workqueue::find_runnable_in_list(Task_list* tasks)
{
  Task* t;
  while ((t = tasks->pop_front()) != NULL)
    {
      Task_token* token = t->is_runnable();

      if (token == NULL)
	return t;

      token->add_waiting(t);
      ++this->waiting_;
    }

  // We couldn't find any runnable task.
  return NULL;
}

// Find a runnable task.  Return NULL if none could be found.  The
// workqueue lock must be held when this is called.

Task*
Workqueue::find_runnable()
{
  Task* t = this->find_runnable_in_list(&this->first_tasks_);
  if (t == NULL)
    t = this->find_runnable_in_list(&this->tasks_);
  return t;
}

// Find a runnable a task, and wait until we find one.  Return NULL if
// we should exit.  The workqueue lock must be held when this is
// called.

Task*
Workqueue::find_runnable_or_wait(int thread_number)
{
  Task* t = this->find_runnable();

  while (t == NULL)
    {
      if (this->running_ == 0
	  && this->first_tasks_.empty()
	  && this->tasks_.empty())
	{
	  // Kick all the threads to make them exit.
	  this->condvar_.broadcast();

	  gold_assert(this->waiting_ == 0);
	  return NULL;
	}

      if (this->should_cancel_thread())
	return NULL;

      gold_debug(DEBUG_TASK, "%3d sleeping", thread_number);

      this->condvar_.wait();

      gold_debug(DEBUG_TASK, "%3d awake", thread_number);

      t = this->find_runnable();
    }

  return t;
}

// Find and run tasks.  If we can't find a runnable task, wait for one
// to become available.  If we run a task, and it frees up another
// runnable task, then run that one too.  This returns true if we
// should look for another task, false if we are cancelling this
// thread.

bool
Workqueue::find_and_run_task(int thread_number)
{
  Task* t;
  Task_locker tl;

  {
    Hold_lock hl(this->lock_);

    // Find a runnable task.
    t = this->find_runnable_or_wait(thread_number);

    if (t == NULL)
      return false;

    // Get the locks for the task.  This must be called while we are
    // still holding the Workqueue lock.
    t->locks(&tl);

    ++this->running_;
  }

  while (t != NULL)
    {
      gold_debug(DEBUG_TASK, "%3d running   task %s", thread_number,
		 t->name().c_str());

      Timer timer;
      if (is_debugging_enabled(DEBUG_TASK))
        timer.start();

      t->run(this);

      if (is_debugging_enabled(DEBUG_TASK))
        {
          Timer::TimeStats elapsed = timer.get_elapsed_time();

          gold_debug(DEBUG_TASK,
                     "%3d completed task %s "
                     "(user: %ld.%06ld sys: %ld.%06ld wall: %ld.%06ld)",
                     thread_number,  t->name().c_str(),
                     elapsed.user / 1000, (elapsed.user % 1000) * 1000,
                     elapsed.sys / 1000, (elapsed.user % 1000) * 1000,
                     elapsed.wall / 1000, (elapsed.wall % 1000) * 1000);
        }

      Task* next;
      {
	Hold_lock hl(this->lock_);

	--this->running_;

	// Release the locks for the task.  This must be done with the
	// workqueue lock held.  Get the next Task to run if any.
	next = this->release_locks(t, &tl);

	if (next == NULL)
	  next = this->find_runnable();

	// If we have another Task to run, get the Locks.  This must
	// be called while we are still holding the Workqueue lock.
	if (next != NULL)
	  {
	    tl.clear();
	    next->locks(&tl);

	    ++this->running_;
	  }
      }

      // We are done with this task.
      delete t;

      t = next;
    }

  return true;
}

// Handle the return value of release_locks, and get tasks ready to
// run.

// 1) If T is not runnable, queue it on the appropriate token.

// 2) Otherwise, T is runnable.  If *PRET is not NULL, then we have
// already decided which Task to run next.  Add T to the list of
// runnable tasks, and signal another thread.

// 3) Otherwise, *PRET is NULL.  If IS_BLOCKER is false, then T was
// waiting on a write lock.  We can grab that lock now, so we run T
// now.

// 4) Otherwise, IS_BLOCKER is true.  If we should run T soon, then
// run it now.

// 5) Otherwise, check whether there are other tasks to run.  If there
// are, then we generally get a better ordering if we run those tasks
// now, before T.  A typical example is tasks waiting on the Dirsearch
// blocker.  We don't want to run those tasks right away just because
// the Dirsearch was unblocked.

// 6) Otherwise, there are no other tasks to run, so we might as well
// run this one now.

// This function must be called with the Workqueue lock held.

// Return true if we set *PRET to T, false otherwise.

bool
Workqueue::return_or_queue(Task* t, bool is_blocker, Task** pret)
{
  Task_token* token = t->is_runnable();

  if (token != NULL)
    {
      token->add_waiting(t);
      ++this->waiting_;
      return false;
    }

  bool should_queue = false;
  bool should_return = false;

  if (*pret != NULL)
    should_queue = true;
  else if (!is_blocker)
    should_return = true;
  else if (t->should_run_soon())
    should_return = true;
  else if (!this->first_tasks_.empty() || !this->tasks_.empty())
    should_queue = true;
  else
    should_return = true;

  if (should_return)
    {
      gold_assert(*pret == NULL);
      *pret = t;
      return true;
    }
  else if (should_queue)
    {
      if (t->should_run_soon())
	this->first_tasks_.push_back(t);
      else
	this->tasks_.push_back(t);
      this->condvar_.signal();
      return false;
    }

  gold_unreachable();
}

// Release the locks associated with a Task.  Return the first
// runnable Task that we find.  If we find more runnable tasks, add
// them to the run queue and signal any other threads.  This must be
// called with the Workqueue lock held.

Task*
Workqueue::release_locks(Task* t, Task_locker* tl)
{
  Task* ret = NULL;
  for (Task_locker::iterator p = tl->begin(); p != tl->end(); ++p)
    {
      Task_token* token = *p;
      if (token->is_blocker())
	{
	  if (token->remove_blocker())
	    {
	      // The token has been unblocked.  Every waiting Task may
	      // now be runnable.
	      Task* t;
	      while ((t = token->remove_first_waiting()) != NULL)
		{
		  --this->waiting_;
		  this->return_or_queue(t, true, &ret);
		}
	    }
	}
      else
	{
	  token->remove_writer(t);

	  // One more waiting Task may now be runnable.  If we are
	  // going to run it next, we can stop.  Otherwise we need to
	  // move all the Tasks to the runnable queue, to avoid a
	  // potential deadlock if the locking status changes before
	  // we run the next thread.
	  Task* t;
	  while ((t = token->remove_first_waiting()) != NULL)
	    {
	      --this->waiting_;
	      if (this->return_or_queue(t, false, &ret))
		break;
	    }
	}
    }
  return ret;
}

// Process all the tasks on the workqueue.  Keep going until the
// workqueue is empty, or until we have been told to exit.  This
// function is called by all threads.

void
Workqueue::process(int thread_number)
{
  while (this->find_and_run_task(thread_number))
    ;
}

// Set the number of threads to use for the workqueue, if we are using
// threads.

void
Workqueue::set_thread_count(int threads)
{
  Hold_lock hl(this->lock_);

  this->threader_->set_thread_count(threads);
  // Wake up all the threads, since something has changed.
  this->condvar_.broadcast();
}

// Add a new blocker to an existing Task_token.

void
Workqueue::add_blocker(Task_token* token)
{
  Hold_lock hl(this->lock_);
  token->add_blocker();
}

} // End namespace gold.
