Example #1
0
void
ACE_RW_Token::notify_new_owner (ACE_TPQ_Entry *old_owner)
{
  ACE_TRACE ("ACE_RW_Token::notify_new_owner");

  if (this->owner () == 0)
    return;

  if (this->owner ()->proxy ()->type () == ACE_RW_Token::READER)
    {
      if (old_owner->proxy ()->type () == ACE_RW_Token::READER)
        // the owners already know that they're owners
        return;

      // The current owner is a reader and the previous owner was a
      // writer, so notify all waiting readers up to the first writer.
      // call back all reader owners.
      ACE_TPQ_Iterator iterator (waiters_);
      for (ACE_TPQ_Entry *temp = 0;
           iterator.next (temp) != 0;
           iterator.advance ())
        {
          if (temp->proxy ()->type () == WRITER)
            // We've gone through all the readers.
            break;

          temp->proxy ()->token_acquired (temp);
        }
    }
  else // writer
    this->owner ()->proxy ()->token_acquired (this->owner ());
}
Example #2
0
int
ACE_Token_Manager::check_deadlock (ACE_Tokens *token, ACE_Token_Proxy *proxy)
{
  ACE_TRACE ("ACE_Token_Manager::check_deadlock");

  if (token->visited ())
    return 0;

  token->visit (1);

  ACE_Tokens::OWNER_STACK owners;

  int is_owner = token->owners (owners, proxy->client_id ());

  switch (is_owner)
    {
    case -1:
      // Error.
      return -1;
    case 1:
      // The caller is an owner, so we have a deadlock situation.
      if (debug_)
        {
          ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("(%t) Deadlock detected.\n")));
          ACE_DEBUG ((LM_DEBUG,  ACE_LIB_TEXT ("%s owns %s and is waiting for %s.\n"),
                      proxy->client_id (),
                      token->name (),
                      proxy->token_->name ()));
        }

      return 1;
    case 0:
    default:
      // Recurse on each owner.
      while (!owners.is_empty ())
        {
          ACE_TPQ_Entry *e;
          owners.pop (e);
          // If the owner is waiting on another token, recurse.
          ACE_Tokens *twf = this->token_waiting_for (e->client_id ());
          if ((twf != 0) &&
              (this->check_deadlock (twf, proxy) == 1))
            {
              if (debug_)
                {
                  ACE_DEBUG ((LM_DEBUG,
                              ACE_LIB_TEXT ("%s owns %s and is waiting for %s.\n"),
                              e->client_id (),
                              token->name (),
                              twf->name ()));
                }
              return 1;
            }
          // else, check the next owner.
        }

      // We've checked all the owners and found no deadlock.
      return 0;
    }
}
Example #3
0
int
ACE_RW_Token::is_owner (const ACE_TCHAR *id)
{
  ACE_TRACE ("ACE_RW_Token::is_owner");
  // If there is no owner, return false.
  if (this->owner () == 0)
    return 0;

  // A writer owns us.
  if (this->owner ()->proxy ()->type () == ACE_RW_Token::WRITER)
    return this->owner ()->equal_client_id (id);

  // Readers own us.
  // Step through each owning reader looking for <id>.
  ACE_TPQ_Iterator iterator (waiters_);
  for (ACE_TPQ_Entry *temp = 0;
       iterator.next (temp) != 0;
       iterator.advance ())
    {
      if (temp->proxy ()->type () != ACE_RW_Token::READER)
        break;

      if (temp->equal_client_id (id))
        return 1;
    }

  return 0;
}
Example #4
0
void
ACE_TPQ_Entry::operator= (const ACE_TPQ_Entry& rhs)
{
  ACE_TRACE ("ACE_TPQ_Entry::operator=");
  if (&rhs == this)
    return;
  this->proxy_ = rhs.proxy ();
  this->nesting_level_ = rhs.nesting_level ();
  this->client_id (rhs.client_id ());
  this->sleep_hook_ = rhs.sleep_hook ();
}
Example #5
0
int
ACE_RW_Token::owners (OWNER_STACK &stack,
                      const ACE_TCHAR *id)
{
  ACE_TRACE ("ACE_RW_Token::owners");

  if (this->owner () == 0)
    return 0;

  int id_is_owner = 0;

  // The first waiter is a writer, so there is only one owner.
  if (this->owner ()->proxy ()->type () == WRITER)
    {
      stack.push (this->owner ());
      // If an <id> is specified, return whether it is the owner being
      // returned.
      if ((id != 0) &&
          (ACE_OS::strcmp (id, this->owner ()->client_id ()) == 0))
        id_is_owner = 1;
    }
  // The first waiter is a reader, so there can be multiple owning
  // readers.
  else
    {
      ACE_TPQ_Iterator iterator (waiters_);
      for (ACE_TPQ_Entry *temp = 0;
           iterator.next (temp) != 0;
           iterator.advance ())
        {
          if (temp->proxy ()->type () == WRITER)
            // We've gone through all the readers.
            break;

          stack.push (temp);

          if (!id_is_owner && (id != 0) &&
              (ACE_OS::strcmp (id, temp->client_id ()) == 0))
            id_is_owner = 1;
        }
    }

  return id_is_owner;
}
Example #6
0
int
ACE_Mutex_Token::is_waiting_for (const ACE_TCHAR *id)
{
  ACE_TRACE ("ACE_Mutex_Token::is_waiting_for");
  // If there is no owner, or <id> is the owner, return false.
  if ((this->owner () == 0) || this->is_owner (id))
    return 0;

  // Step through each waiter looking for <id>.
  ACE_TPQ_Iterator iterator (waiters_);
  iterator.advance ();
  for (ACE_TPQ_Entry *temp = 0;
       iterator.next (temp) != 0;
       iterator.advance ())
    {
      if (temp->equal_client_id (id))
        return 1;
    }

  return 0;
}
Example #7
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);
}