Пример #1
0
void Mutex::acquire(const char* debug_info)
{
  if(unlikely(system_state != RUNNING))
    return;
  //debug(LOCK, "Mutex::acquire:  Mutex: %s (%p), currentThread: %s (%p).\n",
  //         getName(), this, currentThread->getName(), currentThread);
  while(ArchThreads::testSetLock(mutex_, 1))
  {
    checkCurrentThreadStillWaitingOnAnotherLock(debug_info);
    lockWaitersList();
    // Here we have to check for the lock again, in case some one released it in between, we might sleep forever.
    if(!ArchThreads::testSetLock(mutex_, 1))
    {
      unlockWaitersList();
      break;
    }
    // check for deadlocks, interrupts...
    doChecksBeforeWaiting(debug_info);
    Scheduler::instance()->sleepAndRelease(*(Lock*)this);
    // We have been waken up again.
    currentThread->lock_waiting_on_ = 0;
  }

  assert(held_by_ == 0);
  pushFrontToCurrentThreadHoldingList();
  held_by_ = currentThread;
}
Пример #2
0
void Mutex::release(pointer called_by)
{
  if(unlikely(system_state != RUNNING))
    return;
  if(!called_by)
    called_by = getCalledBefore(1);
//  debug(LOCK, "Mutex::release:  Mutex: %s (%p), currentThread: %s (%p).\n",
//           getName(), this, currentThread->getName(), currentThread);
//  if(kernel_debug_info)
//  {
//    debug(LOCK, "The release is called by: ");
//    kernel_debug_info->printCallInformation(called_by);
//  }
  checkInvalidRelease("Mutex::release");
  removeFromCurrentThreadHoldingList();
  last_accessed_at_ = called_by;
  held_by_ = 0;
  mutex_ = 0;
  // Wake up a sleeping thread. It is okay that the mutex is not held by the current thread any longer.
  // In worst case a new thread is woken up. Otherwise (first wake up, then release),
  // it could happen that a thread is going to sleep after the this one is trying to wake up one.
  // Then we are dead... (the thread may sleep forever, in case no other thread is going to acquire this mutex again).
  lockWaitersList();
  Thread* thread_to_be_woken_up = popBackThreadFromWaitersList();
  unlockWaitersList();
  if(thread_to_be_woken_up)
  {
    Scheduler::instance()->wake(thread_to_be_woken_up);
  }
}
Пример #3
0
void Mutex::acquire(pointer called_by)
{
  if(unlikely(system_state != RUNNING))
    return;
  if(!called_by)
    called_by = getCalledBefore(1);
//  debug(LOCK, "Mutex::acquire:  Mutex: %s (%p), currentThread: %s (%p).\n",
//           getName(), this, currentThread->getName(), currentThread);
//  if(kernel_debug_info)
//  {
//    debug(LOCK, "The acquire is called by: ");
//    kernel_debug_info->printCallInformation(called_by);
//  }
  while(ArchThreads::testSetLock(mutex_, 1))
  {
    checkCurrentThreadStillWaitingOnAnotherLock();
    lockWaitersList();
    // Here we have to check for the lock again, in case some one released it in between, we might sleep forever.
    if(!ArchThreads::testSetLock(mutex_, 1))
    {
      unlockWaitersList();
      break;
    }
    // check for deadlocks, interrupts...
    doChecksBeforeWaiting();
    Scheduler::instance()->sleepAndRelease(*(Lock*)this);
    // We have been waken up again.
    currentThread->lock_waiting_on_ = 0;
  }

  assert(held_by_ == 0);
  pushFrontToCurrentThreadHoldingList();
  last_accessed_at_ = called_by;
  held_by_ = currentThread;
}
Пример #4
0
void Mutex::release(const char* debug_info)
{
  if(unlikely(system_state != RUNNING))
    return;
  //debug(LOCK, "Mutex::release:  Mutex: %s (%p), currentThread: %s (%p).\n",
  //         getName(), this, currentThread->getName(), currentThread);
  checkInvalidRelease("Mutex::release", debug_info);
  removeFromCurrentThreadHoldingList();
  held_by_ = 0;
  mutex_ = 0;
  // Wake up a sleeping thread. It is okay that the mutex is not held by the current thread any longer.
  // In worst case a new thread is woken up. Otherwise (first wake up, then release),
  // it could happen that a thread is going to sleep after the this one is trying to wake up one.
  // Then we are dead... (the thread may sleep forever, in case no other thread is going to acquire this mutex again).
  lockWaitersList();
  Thread* thread_to_be_woken_up = popBackThreadFromWaitersList();
  unlockWaitersList();
  if(thread_to_be_woken_up)
  {
    Scheduler::instance()->wake(thread_to_be_woken_up);
  }
}
Пример #5
0
void Condition::signal(pointer called_by)
{
  if(unlikely(system_state != RUNNING))
    return;
  if(!called_by)
    called_by = getCalledBefore(1);
//  debug(LOCK, "Condition::signal: Thread %s (%p) is signaling condition %s (%p).\n",
//        currentThread->getName(), currentThread, getName(), this);
//  debug(LOCK, "The signal is called by: ");
//  kernel_debug_info->printCallInformation(called_by);

  assert(mutex_->isHeldBy(currentThread));
  checkInterrupts("Condition::signal");
  lockWaitersList();
  last_accessed_at_ = called_by;
  Thread* thread_to_be_woken_up = popBackThreadFromWaitersList();
  unlockWaitersList();

  if(thread_to_be_woken_up)
  {
    if(likely(thread_to_be_woken_up->state_ == Sleeping))
    {
      // In this case we can access the pointer of the other thread without locking,
      // because we can ensure that the thread is sleeping.

      //debug(LOCK, "Condition: Thread %s (%p) being signaled for condition %s (%p).\n",
      //      thread_to_be_woken_up->getName(), thread_to_be_woken_up, getName(), this);
      thread_to_be_woken_up->lock_waiting_on_ = 0;
      Scheduler::instance()->wake(thread_to_be_woken_up);
    }
    else
    {
      debug(LOCK, "ERROR: Condition %s (%p): Thread %s (%p) is in state %s AND waiting on the condition!\n",
            getName(), this, thread_to_be_woken_up->getName(), thread_to_be_woken_up,
            Thread::threadStatePrintable[thread_to_be_woken_up->state_]);
      assert(false);
    }
  }
}
Пример #6
0
void Condition::wait(bool re_acquire_mutex, pointer called_by)
{
  if(unlikely(system_state != RUNNING))
    return;
  if(!called_by)
    called_by = getCalledBefore(1);
//  debug(LOCK, "Condition::wait: Thread %s (%p) is waiting on condition %s (%p).\n",
//        currentThread->getName(), currentThread, getName(), this);
//  if(kernel_debug_info)
//  {
//    debug(LOCK, "The wait is called by: ");
//    kernel_debug_info->printCallInformation(called_by);
//  }

  assert(mutex_->isHeldBy(currentThread));
  // check if the interrupts are enabled and the thread is not waiting for some other locks
  checkInterrupts("Condition::wait");
  checkCurrentThreadStillWaitingOnAnotherLock();

  assert(currentThread->holding_lock_list_);
  if(currentThread->holding_lock_list_->hasNextOnHoldingList())
  {
    debug(LOCK, "Condition::wait: Warning: The thread %s (%p) is holding some locks when going to sleep on condition %s (%p).\n"
          "This may lower the performance of the system, and cause undetectable deadlocks!\n",
          currentThread->getName(), currentThread, getName(), this);
    printHoldingList(currentThread);
  }
  lockWaitersList();
  last_accessed_at_ = called_by;
  // The mutex can be released here, because for waking up another thread, the list lock is needed, which is still held by the thread.
  mutex_->release(called_by);
  Scheduler::instance()->sleepAndRelease(*(Lock*)this);
  if(re_acquire_mutex)
  {
    assert(mutex_);
    mutex_->acquire(called_by);
  }
}
Пример #7
0
Lock::~Lock()
{
  if(unlikely(system_state != RUNNING))
    return;
  // copy the pointers to the stack because it may be reseted before printing the element out.
  Thread* waiter = waiters_list_;
  Thread* held_by = held_by_;
  if(waiter)
  {
    debug(LOCK, "ERROR: Lock::~Lock %s (%p): At least thread %p is still waiting on this lock,\n"
        "currentThread is: %p, the thread holding this lock is: %p\n",
        name_, this, waiter, currentThread, held_by);
    lockWaitersList();
    printWaitersList();
    // The waiters list does not has to be unlocked here, because the kernel is going to die.
    assert(false);
  }
  if(held_by)
  {
    debug(LOCK, "Warning: Lock::~Lock %s (%p): Thread %p is still holding this lock, currentThread is: %p\n",
        name_, this, held_by, currentThread);
  }
}