// descriptors.cc -- manage file descriptors for gold

// Copyright 2008, 2009 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 <cerrno>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>

#include "parameters.h"
#include "options.h"
#include "gold-threads.h"
#include "descriptors.h"

// Very old systems may not define FD_CLOEXEC.
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif

// O_CLOEXEC is only available on newer systems.
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif

namespace gold
{

// Class Descriptors.

// The default for limit_ is meant to simply be large.  It gets
// adjusted downward if we run out of file descriptors.

Descriptors::Descriptors()
  : lock_(NULL), initialize_lock_(&this->lock_), open_descriptors_(),
    stack_top_(-1), current_(0), limit_(8192 - 16)
{
  this->open_descriptors_.reserve(128);
}

// Open a file.

int
Descriptors::open(int descriptor, const char* name, int flags, int mode)
{
  // We don't initialize this until we are called, because we can't
  // initialize a Lock until we have parsed the options to find out
  // whether we are running with threads.  We can be called before
  // options are valid when reading a linker script.
  bool lock_initialized = this->initialize_lock_.initialize();

  gold_assert(lock_initialized || descriptor < 0);

  if (descriptor >= 0)
    {
      Hold_lock hl(*this->lock_);

      gold_assert(static_cast<size_t>(descriptor)
		  < this->open_descriptors_.size());
      Open_descriptor* pod = &this->open_descriptors_[descriptor];
      if (pod->name == name
	  || (pod->name != NULL && strcmp(pod->name, name) == 0))
	{
	  gold_assert(!pod->inuse);
	  pod->inuse = true;
	  if (descriptor == this->stack_top_)
	    {
	      this->stack_top_ = pod->stack_next;
	      pod->stack_next = -1;
	      pod->is_on_stack = false;
	    }
	  return descriptor;
	}
    }

  while (true)
    {
      // We always want to set the close-on-exec flag; we don't
      // require callers to pass it.
      flags |= O_CLOEXEC;

      int new_descriptor = ::open(name, flags, mode);
      if (new_descriptor < 0
	  && errno != ENFILE
	  && errno != EMFILE)
	{
	  if (descriptor >= 0 && errno == ENOENT)
	    {
	      {
		Hold_lock hl(*this->lock_);

		gold_error(_("file %s was removed during the link"),
			   this->open_descriptors_[descriptor].name);
	      }

	      errno = ENOENT;
	    }

	  return new_descriptor;
	}

      if (new_descriptor >= 0)
	{
	  // If we have any plugins, we really do need to set the
	  // close-on-exec flag, even if O_CLOEXEC is not defined.
	  // FIXME: In some cases O_CLOEXEC may be defined in the
	  // header file but not supported by the kernel.
	  // Unfortunately there doesn't seem to be any obvious way to
	  // detect that, as unknown flags passed to open are ignored.
	  if (O_CLOEXEC == 0
	      && parameters->options_valid()
	      && parameters->options().has_plugins())
	    fcntl(new_descriptor, F_SETFD, FD_CLOEXEC);

	  {
	    Hold_optional_lock hl(this->lock_);

	    if (static_cast<size_t>(new_descriptor)
		>= this->open_descriptors_.size())
	      this->open_descriptors_.resize(new_descriptor + 64);

	    Open_descriptor* pod = &this->open_descriptors_[new_descriptor];
	    pod->name = name;
	    pod->stack_next = -1;
	    pod->inuse = true;
	    pod->is_write = (flags & O_ACCMODE) != O_RDONLY;
	    pod->is_on_stack = false;

	    ++this->current_;
	    if (this->current_ >= this->limit_)
	      this->close_some_descriptor();

	    return new_descriptor;
	  }
	}

      // We ran out of file descriptors.
      {
	Hold_optional_lock hl(this->lock_);

	this->limit_ = this->current_ - 16;
	if (this->limit_ < 8)
	  this->limit_ = 8;
	if (!this->close_some_descriptor())
	  gold_fatal(_("out of file descriptors and couldn't close any"));
      }
    }
}

// Release a descriptor.

void
Descriptors::release(int descriptor, bool permanent)
{
  Hold_optional_lock hl(this->lock_);

  gold_assert(descriptor >= 0
	      && (static_cast<size_t>(descriptor)
		  < this->open_descriptors_.size()));
  Open_descriptor* pod = &this->open_descriptors_[descriptor];

  if (permanent
      || (this->current_ > this->limit_ && !pod->is_write))
    {
      if (::close(descriptor) < 0)
	gold_warning(_("while closing %s: %s"), pod->name, strerror(errno));
      pod->name = NULL;
      --this->current_;
    }
  else
    {
      pod->inuse = false;
      if (!pod->is_write && !pod->is_on_stack)
	{
	  pod->stack_next = this->stack_top_;
	  this->stack_top_ = descriptor;
	  pod->is_on_stack = true;
	}
    }
}

// Close some descriptor.  The lock is held when this is called.  We
// close the descriptor on the top of the free stack.  Note that this
// is the opposite of an LRU algorithm--we close the most recently
// used descriptor.  That is because the linker tends to cycle through
// all the files; after we release a file, we are unlikely to need it
// again until we have looked at all the other files.  Return true if
// we closed a descriptor.

bool
Descriptors::close_some_descriptor()
{
  int last = -1;
  int i = this->stack_top_;
  while (i >= 0)
    {
      gold_assert(static_cast<size_t>(i) < this->open_descriptors_.size());
      Open_descriptor* pod = &this->open_descriptors_[i];
      if (!pod->inuse && !pod->is_write)
	{
	  if (::close(i) < 0)
	    gold_warning(_("while closing %s: %s"), pod->name, strerror(errno));
	  --this->current_;
	  pod->name = NULL;
	  if (last < 0)
	    this->stack_top_ = pod->stack_next;
	  else
	    this->open_descriptors_[last].stack_next = pod->stack_next;
	  pod->stack_next = -1;
	  pod->is_on_stack = false;
	  return true;
	}
      last = i;
      i = pod->stack_next;
    }

  // We couldn't find any descriptors to close.  This is weird but not
  // necessarily an error.
  return false;
}

// The single global variable which manages descriptors.

Descriptors descriptors;

} // End namespace gold.
