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; }
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; }
void Lock::doChecksBeforeWaiting() { // Check if the interrupts are set. Else, we maybe wait forever checkInterrupts("Lock::doChecksBeforeWaiting"); // Check if the thread has been waken up even if he is already waiting on another lock. checkCurrentThreadStillWaitingOnAnotherLock(); // Check if locking this lock would result in a deadlock. checkForDeadLock(); }
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); } }