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