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::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); } }
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 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); } }
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); } } }
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); } }
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); } }