Esempio n. 1
0
int
ACE_Mutex_Token::renew (ACE_TPQ_Entry *caller,
                        int requeue_position)
{
  ACE_TRACE ("ACE_Mutex_Token::renew");
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);

  // Verify that the caller is the owner.
  if (this->is_owner (caller->client_id ()) == 0)
    {
      errno = EACCES;
      ACE_RETURN (-1);
    }

  // The caller is the owner, so check to see if there are any
  // waiters.  If not, we just keep the token.  == 1 means that there
  // is only the owner.
  if (this->waiters_.size () == 1 || requeue_position == 0)
    return 0;

  // Requeue the caller.
  this->waiters_.dequeue ();

  this->waiters_.enqueue (caller, requeue_position);

  // Notify new owner.
  if (this->owner () != 0)
    this->owner ()->proxy ()->token_acquired (this->owner ());

  // Tell the caller that the operation would block.
  errno = EWOULDBLOCK;
  ACE_RETURN (-1);

  ACE_NOTREACHED (return -1);
}
Esempio n. 2
0
int
ACE_Mutex_Token::acquire (ACE_TPQ_Entry *caller,
                          int ignore_deadlock,
                          int notify)
{
  ACE_TRACE ("ACE_Mutex_Token::acquire");
  // We need to acquire two locks. This one to ensure that only one
  // thread uses this token at a time.
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
  // This one to ensure an atomic transaction across all tokens.  Note
  // that this order is crucial too.  It's resource coloring for other
  // threads which may be calling this same token.
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);

  // Does _anyone_ own the token?
  if (this->owner () == 0)
    {
      // there are no waiters, so queue as the first waiter (the owner.)
      this->waiters_.enqueue (caller, -1);
      return 0;  // success
    }

  // Does the caller already own it?
  if (this->is_owner (caller->client_id ()))
    {
      // Recursive acquisition.
      caller->nesting_level (1);
      return 0; // success
    }

  // Check for deadlock.
  if (!ignore_deadlock
      && ACE_Token_Manager::instance ()->check_deadlock (caller->proxy ()) == 1)
    {
      errno = EDEADLK;
      ACE_RETURN (-1);
    }

  // Someone owns it. Sorry, you're getting queued up at the end of
  // the waiter queue.
  this->waiters_.enqueue (caller, -1);

  if (notify)
    this->owner ()->call_sleep_hook ();

  errno = EWOULDBLOCK;
  ACE_RETURN (-1);

  ACE_NOTREACHED (return -1);
}
Esempio n. 3
0
int
ACE_Token_Collection::acquire (int notify,
                               void (*sleep_hook)(void *),
                               ACE_Synch_Options &options)
{
  ACE_TRACE ("ACE_Token_Collection::acquire");

  COLLECTION::ITERATOR iterator (collection_);

  for (COLLECTION::ENTRY *temp = 0;
       iterator.next (temp) != 0;
       iterator.advance ())
    {
      if (debug_)
        ACE_DEBUG ((LM_DEBUG,
                    ACE_TEXT ("collection acquiring %s\n"),
                    temp->int_id_->name ()));
      if (temp->int_id_->acquire (notify,
                                  sleep_hook,
                                  options) == -1)
        {
          // Save/restore errno.
          ACE_Errno_Guard error (errno);
          this->release ();
          ACE_RETURN (-1);
        }
    }

  return 0;
}
Esempio n. 4
0
int
ACE_RW_Token::release (ACE_TPQ_Entry *caller)
{
  ACE_TRACE ("ACE_RW_Token::release");
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);

  // Check for errors.
  if ((this->owner () == 0) ||
      (this->is_owner (caller->client_id ()) == 0))
    {
      errno = EACCES;
      ACE_RETURN (-1);
    }

  if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
    num_writers_--;

  // Recursive release.
  if (caller->nesting_level () > 0)
    {
      caller->nesting_level (-1);
      return 0;
    }

  // Remove the caller and notify the new owner(s).
  this->remove (caller);
  this->notify_new_owner (caller);

  return 0;
}
Esempio n. 5
0
int
ACE_Mutex_Token::release (ACE_TPQ_Entry *caller)
{
  ACE_TRACE ("ACE_Mutex_Token::release");
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);

  // Does anyone own the token?
  if (this->owner () == 0)
    {
      errno = EACCES;
      ACE_RETURN (-1);
    }

  // Is the caller the owner.
  if (this->is_owner (caller->client_id ()))
    {
      // Check the nesting level.
      if (caller->nesting_level () > 0)
        caller->nesting_level (-1);
      else
        {
          this->waiters_.dequeue ();
          // Notify new owner.
          if (this->owner () != 0)
            this->owner ()->proxy ()->token_acquired (this->owner ());
        }
    }
  else
    this->remove (caller);

  return 0;
}
Esempio n. 6
0
int
ACE_Mutex_Token::tryacquire (ACE_TPQ_Entry *caller)
{
  ACE_TRACE ("ACE_Mutex_Token::tryacquire");
  // We need to acquire two locks. This one to ensure that only one
  // thread uses this token at a time.
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
  // This one to ensure an atomic transaction across all tokens.  Note
  // that this order is crucial too.  It's resource coloring for other
  // threads which may be calling this same token.
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);

  // Does _anyone_ own the token?
  if (this->owner () == 0)
    {
      this->waiters_.enqueue (caller, -1);
      return 0;  // success
    }
  // Does the caller already own it?
  if (this->is_owner (caller->client_id ()))
    {
      // recursive acquisition
      caller->nesting_level (1);
      return 0;  // success
    }
  else
    // Someone owns it.  Fail.
    {
      errno = EWOULDBLOCK;
      ACE_RETURN (-1);
    }

  ACE_NOTREACHED (return -1);
}
Esempio n. 7
0
int
ACE_Token_Proxy::release (ACE_Synch_Options &)
{
  ACE_TRACE ("ACE_Token_Proxy::release");

  if (this->token_ == 0)
    {
      errno = ENOENT;
      if (debug_)
        ACELIB_DEBUG ((LM_DEBUG,  ACE_TEXT ("Must open before releasing.\n")));
      ACE_RETURN (-1);
    }

  if (this->token_->release (waiter_) != 0)
    {
      // Release failed.
      this->token_->remove (this->waiter_);
      if (debug_)
        ACELIB_DEBUG ((LM_DEBUG,  ACE_TEXT ("(%t) %p.\n"), ACE_TEXT ("release failed")));
      return -1;
    }
  else
    {
      if (this->debug_)
        ACELIB_DEBUG ((LM_DEBUG,  ACE_TEXT ("(%t) released %s, owner is %s\n"),
                    this->name (),
                    token_->owner_id ()));

      return 0;
    }
}
Esempio n. 8
0
int
ACE_RW_Token::renew (ACE_TPQ_Entry *caller,
                     int requeue_position)
{
  ACE_TRACE ("ACE_RW_Token::renew");
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon, this->lock_, -1);

  // Werify that the caller is the owner
  if (this->is_owner (caller->client_id ()) == 0)
    {
      errno = EACCES;
      ACE_RETURN (-1);
    }

  // The caller is the owner, so check to see if there are any
  // waiters.  If not, we just keep the token.
  if (this->waiters_.size () == 1 || requeue_position == 0)
    return 0;

  // There are waiters, so remove the caller.
  this->remove (caller);

  // Requeue the caller.
  this->waiters_.enqueue (caller, requeue_position);

  if (caller->proxy ()->type () == ACE_RW_Token::READER)
    {
      // If the caller got queued before any writers, the caller is
      // still the owner.
      if (this->is_owner (caller->client_id ()))
        return 0; // success
      // else fallthrough and return would block.
    }
  // Writers will always have to block since waiters_.size () == 1 or
  // requeue_position == 0.

  // Get a new owner.
  this->notify_new_owner (caller);

  // Tell the caller that the operation would block.
  errno = EWOULDBLOCK;
  ACE_RETURN (-1);

  ACE_NOTREACHED (return -1);
}
Esempio n. 9
0
int
ACE_RW_Token::tryacquire (ACE_TPQ_Entry *caller)
{
  ACE_TRACE ("ACE_RW_Token::tryacquire");
  // We need to acquire two locks. This one to ensure that only one
  // thread uses this token at a time.
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
  // This one to ensure an atomic transaction across all tokens.  Note
  // that this order is crucial too.  It's resource coloring for other
  // threads which may be calling this same token.
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);

  if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
    {
      this->num_writers_++;
    }

  // Does _anyone_ own the token?
  if (this->owner () == 0)
    {
      // There are no waiters, so queue as the first waiter (the owner).
      this->waiters_.enqueue (caller, -1);
      return 0;
    }

  // Check for recursive acquisition.
  if (this->is_owner (caller->client_id ()))
    {
      caller->nesting_level (1);
      return 0;  // Success.
    }

  // Reader.
  if (caller->proxy ()->type () == ACE_RW_Token::READER)
    {
      // Are there any writers?
      if (this->num_writers_ == 0)
        {
          // queue the caller at the end of the queue.
          this->waiters_.enqueue (caller, -1);
          return 0;
        }
      // Else, fail.
    }
  else // Writer.
    // We're going to fail, so decrement the num_writers.
    {
      this->num_writers_--;
    }


  errno = EWOULDBLOCK;
  ACE_RETURN (-1);

  ACE_NOTREACHED (return -1);
}
Esempio n. 10
0
int
ACE_Token_Proxy::handle_options (ACE_Synch_Options &options,
                                 ACE_TOKEN_CONST::COND_VAR &cv)
{
  // Some operation failed with EWOULDBLOCK.
  ACE_TRACE ("ACE_Token_Proxy::handle_options");

  if (options[ACE_Synch_Options::USE_REACTOR] == 1)
    // Asynchronous.
    {
      // Save/restore errno.
      ACE_Errno_Guard error (errno);
      cv.mutex ().release ();
      ACE_RETURN (-1);
    }
  else
    // Synchronous.
    {
      // Block on condition variable.
      while (cv.wait ((ACE_Time_Value *) options.time_value ()) == -1)
        {
          // Note, this should obey whatever thread-specific
          // interrupt policy is currently in place...
          if (errno == EINTR)
            continue;
          // We come here if a timeout occurs or some serious
          // ACE_Condition object error.
          cv.mutex ().release ();
          ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("condition variable wait")
                             ACE_TEXT (" bombed.")), -1);
        }

      if (this->debug_)
        ACELIB_DEBUG ((LM_DEBUG,  ACE_TEXT ("(%t) unblocking %s.\n"),
                    this->client_id ()));
      cv.mutex ().release ();
      return 0;       // operation succeeded
    }
}
Esempio n. 11
0
int
ACE_Remote_Token_Proxy::acquire (int notify,
                                 void (*sleep_hook)(void *),
                                 ACE_Synch_Options &options)
{
  ACE_TRACE ("ACE_Remote_Token_Proxy::acquire");

  // First grab the local shadow mutex.
  if (ACE_Token_Proxy::acquire (notify,
                                sleep_hook,
                                ACE_Synch_Options::asynch) == -1)
    {
      // Acquire failed, deal with it...
      switch (errno)
        {
        case EWOULDBLOCK :
          // Whoah, we detected wouldblock via the shadow mutex!
          if (debug_)
            ACE_DEBUG ((LM_DEBUG,  ACE_TEXT ("(%t) shadow: acquire will block, owner is %s\n"),
                        this->token_->owner_id ()));
          // No error, but would block,
          break;

        case EDEADLK :
          if (debug_)
            ACE_DEBUG ((LM_DEBUG,  ACE_TEXT ("(%t) shadow: deadlock detected\n")));

          if (ignore_shadow_deadlock_)
            break;
          else
            {
              errno = EDEADLK;
              ACE_RETURN (-1);
            }

        default :
          ACE_ERROR_RETURN ((LM_ERROR,
                             ACE_TEXT ("(%t) %p shadow acquire failed\n"),
                             ACE_TEXT ("ACE_Remote_Token_Proxy")),
                            -1);
        }
    }

  ACE_Token_Request request (token_->type (),
                             this->type (),
                             ACE_Token_Request::ACQUIRE,
                             this->name (),
                             this->client_id (),
                             options);

  request.notify (notify);

  int result = this->request_reply (request, options);

  if (result == -1)
    {
      // Update the local shadow copy.
      ACE_DEBUG ((LM_DEBUG,  ACE_TEXT ("error on remote acquire, releasing shadow mutex.\n")));
      ACE_Token_Proxy::release ();
    }
  else
    {
      ACE_DEBUG ((LM_DEBUG,  ACE_TEXT ("(%t) acquired %s remotely.\n"), this->name ()));
      // Our shadow call may have failed.  However, it's still a race
      // to the remote server.  If we beat the client which holds the
      // local token, we need to fix things locally to reflect the
      // actual ownership.  All that should happen is that our waiter
      // is moved to the front of the waiter list.
      token_->make_owner (waiter_);
    }

  return result;
}
Esempio n. 12
0
int
ACE_RW_Token::acquire (ACE_TPQ_Entry *caller,
                       int ignore_deadlock,
                       int notify)
{
  ACE_TRACE ("ACE_RW_Token::acquire");
  // We need to acquire two locks. This one to ensure that only one
  // thread uses this token at a time.
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon1, this->lock_, -1);
  // This one to ensure an atomic transaction across all tokens.  Note
  // that this order is crucial too.  It's resource coloring for other
  // threads which may be calling this same token.
  ACE_GUARD_RETURN (ACE_TOKEN_CONST::MUTEX, ace_mon2, ACE_Token_Manager::instance ()->mutex (), -1);

  if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
    this->num_writers_++;

  // Does _anyone_ own the token?
  if (this->owner () == 0)
    {
      // There are no waiters, so queue as the first waiter (the owner).
      this->waiters_.enqueue (caller, -1);
      return 0;
    }

  // Check for recursive acquisition.
  if (this->is_owner (caller->client_id ()))
    {
      caller->nesting_level (1);
      return 0;  // Success.
    }

  // Reader.
  if (caller->proxy ()->type () == ACE_RW_Token::READER)
    {
      // Are there any writers?
      if (this->num_writers_ == 0)
        {
          // Queue the caller at the end of the queue.
          this->waiters_.enqueue (caller, -1);
          return 0;
        }
      // Else failure.
    }

  // Failure code.

  // Check for deadlock.
  if (!ignore_deadlock &&
      ACE_Token_Manager::instance ()->check_deadlock (caller->proxy ()) == 1)
    {
      if (caller->proxy ()->type () == ACE_RW_Token::WRITER)
        this->num_writers_--;
      errno = EDEADLK;
      ACE_RETURN (-1);
    }

  // Queue the caller at the end of the queue.
  this->waiters_.enqueue (caller, -1);

  if (notify)
    {
      // If it's a writer, just notify it.
      if (this->owner ()->proxy ()->type () == ACE_RW_Token::WRITER)
        this->owner ()->call_sleep_hook ();
      else
        {
          // Call back all reader owners.
          ACE_TPQ_Entry *temp = this->owner ();
          do
            {
              temp->call_sleep_hook ();
              temp = temp->next_;
            }
          while (temp != 0 &&
                 temp->proxy ()->type () == ACE_RW_Token::READER);
        }
    }

  errno = EWOULDBLOCK;
  ACE_RETURN (-1);

  ACE_NOTREACHED (return -1);
}
Esempio n. 13
0
int
ACE_Token_Proxy::acquire (int notify,
                          void (*sleep_hook)(void *),
                          ACE_Synch_Options &options)
{
  ACE_TRACE ("ACE_Token_Proxy::acquire");
  if (this->token_ == 0)
    {
      errno = ENOENT;
      ACELIB_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Not open.\n")), -1);
    }

  // Make sure no one calls our token_acquired until we have a chance
  // to sleep first!  If after we call an EWOULDBLOCK
  // mutex_->acquire() below, but before we enter handle_options to
  // wait on the cond_var, a thread tries to give take us off the
  // waiter queue and signal us, IT WILL FIRST HAVE TO ACQUIRE THIS
  // cond_var.mutex ().  _This_ is why we acquire it.
  this->waiter_->cond_var_.mutex ().acquire ();

  this->waiter_->sleep_hook (sleep_hook);

  if (this->token_->acquire (this->waiter_, this->ignore_deadlock_, notify) == -1)
    // acquire failed
    {
      switch (errno)
        {
        case EDEADLK :
          if (!ignore_deadlock_)
            {
              waiter_->cond_var_.mutex ().release ();
              errno = EDEADLK;
              ACE_RETURN (-1);
            }
          // Else, fallthrough and block!

        case EWOULDBLOCK :
          if (this->debug_)
            ACELIB_DEBUG ((LM_DEBUG,
                        ACE_TEXT ("(%t) waiting for %s, owner is %s, ")
                        ACE_TEXT ("total waiters == %d\n"),
                        this->name (),
                        this->token_->owner_id (),
                        token_->no_of_waiters ()));

          // no error, but would block, if error, return error (-1),
          // otherwise, return whether we called the holder or not.
          int return_value;
          if (this->handle_options (options,
                                    waiter_->cond_var_) == -1)
            return_value = -1;
          else
            return_value = notify == 1;

          errno = EWOULDBLOCK;
          ACE_RETURN (return_value);

        default :
          waiter_->cond_var_.mutex ().release ();
          ACELIB_ERROR_RETURN ((LM_ERROR,
                             ACE_TEXT ("%p\n"),
                             ACE_TEXT ("Token Proxy acquire.")),
                            -1);
        }
    }
  else
    // we have the token
    {
      if (debug_)
        ACELIB_DEBUG ((LM_DEBUG,
                    ACE_TEXT ("(%t) acquired %s\n"),
                    this->name ()));
      waiter_->cond_var_.mutex ().release ();
    }

  return 0;
}