diff options
Diffstat (limited to 'lldb/tools/debugserver/source/PThreadEvent.cpp')
-rw-r--r-- | lldb/tools/debugserver/source/PThreadEvent.cpp | 323 |
1 files changed, 148 insertions, 175 deletions
diff --git a/lldb/tools/debugserver/source/PThreadEvent.cpp b/lldb/tools/debugserver/source/PThreadEvent.cpp index 47e7275..1b0900ca 100644 --- a/lldb/tools/debugserver/source/PThreadEvent.cpp +++ b/lldb/tools/debugserver/source/PThreadEvent.cpp @@ -12,117 +12,98 @@ //===----------------------------------------------------------------------===// #include "PThreadEvent.h" -#include "errno.h" #include "DNBLog.h" +#include "errno.h" -PThreadEvent::PThreadEvent(uint32_t bits, uint32_t validBits) : - m_mutex(), - m_set_condition(), - m_reset_condition(), - m_bits(bits), - m_validBits(validBits), - m_reset_ack_mask(0) -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, 0x%8.8x)", this, __FUNCTION__, bits, validBits); +PThreadEvent::PThreadEvent(uint32_t bits, uint32_t validBits) + : m_mutex(), m_set_condition(), m_reset_condition(), m_bits(bits), + m_validBits(validBits), m_reset_ack_mask(0) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, 0x%8.8x)", + // this, __FUNCTION__, bits, validBits); } -PThreadEvent::~PThreadEvent() -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); +PThreadEvent::~PThreadEvent() { + // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); } - -uint32_t -PThreadEvent::NewEventBit() -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - uint32_t mask = 1; - while (mask & m_validBits) - mask <<= 1; - m_validBits |= mask; - return mask; +uint32_t PThreadEvent::NewEventBit() { + // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + uint32_t mask = 1; + while (mask & m_validBits) + mask <<= 1; + m_validBits |= mask; + return mask; } -void -PThreadEvent::FreeEventBits(const uint32_t mask) -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask); - if (mask) - { - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - m_bits &= ~mask; - m_validBits &= ~mask; - } +void PThreadEvent::FreeEventBits(const uint32_t mask) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, + // __FUNCTION__, mask); + if (mask) { + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + m_bits &= ~mask; + m_validBits &= ~mask; + } } - -uint32_t -PThreadEvent::GetEventBits() const -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - uint32_t bits = m_bits; - return bits; +uint32_t PThreadEvent::GetEventBits() const { + // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION); + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + uint32_t bits = m_bits; + return bits; } // Replace the event bits with a new bitmask value -void -PThreadEvent::ReplaceEventBits(const uint32_t bits) -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, bits); - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - // Make sure we have some bits and that they aren't already set... - if (m_bits != bits) - { - // Figure out which bits are changing - uint32_t changed_bits = m_bits ^ bits; - // Set the new bit values - m_bits = bits; - // If any new bits are set, then broadcast - if (changed_bits & m_bits) - m_set_condition.Broadcast(); - } +void PThreadEvent::ReplaceEventBits(const uint32_t bits) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, + // __FUNCTION__, bits); + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + // Make sure we have some bits and that they aren't already set... + if (m_bits != bits) { + // Figure out which bits are changing + uint32_t changed_bits = m_bits ^ bits; + // Set the new bit values + m_bits = bits; + // If any new bits are set, then broadcast + if (changed_bits & m_bits) + m_set_condition.Broadcast(); + } } // Set one or more event bits and broadcast if any new event bits get set // that weren't already set. -void -PThreadEvent::SetEvents(const uint32_t mask) -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask); - // Make sure we have some bits to set - if (mask) - { - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - // Save the old event bit state so we can tell if things change - uint32_t old = m_bits; - // Set the all event bits that are set in 'mask' - m_bits |= mask; - // Broadcast only if any extra bits got set. - if (old != m_bits) - m_set_condition.Broadcast(); - } +void PThreadEvent::SetEvents(const uint32_t mask) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, + // __FUNCTION__, mask); + // Make sure we have some bits to set + if (mask) { + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + // Save the old event bit state so we can tell if things change + uint32_t old = m_bits; + // Set the all event bits that are set in 'mask' + m_bits |= mask; + // Broadcast only if any extra bits got set. + if (old != m_bits) + m_set_condition.Broadcast(); + } } // Reset one or more event bits -void -PThreadEvent::ResetEvents(const uint32_t mask) -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask); - if (mask) - { - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - - // Save the old event bit state so we can tell if things change - uint32_t old = m_bits; - // Clear the all event bits that are set in 'mask' - m_bits &= ~mask; - // Broadcast only if any extra bits got reset. - if (old != m_bits) - m_reset_condition.Broadcast(); - } +void PThreadEvent::ResetEvents(const uint32_t mask) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, + // __FUNCTION__, mask); + if (mask) { + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + + // Save the old event bit state so we can tell if things change + uint32_t old = m_bits; + // Clear the all event bits that are set in 'mask' + m_bits &= ~mask; + // Broadcast only if any extra bits got reset. + if (old != m_bits) + m_reset_condition.Broadcast(); + } } //---------------------------------------------------------------------- @@ -130,98 +111,90 @@ PThreadEvent::ResetEvents(const uint32_t mask) // 'mask'. If 'timeout_abstime' is NULL, then wait forever. //---------------------------------------------------------------------- uint32_t -PThreadEvent::WaitForSetEvents(const uint32_t mask, const struct timespec *timeout_abstime) const -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime); - int err = 0; - // pthread_cond_timedwait() or pthread_cond_wait() will atomically - // unlock the mutex and wait for the condition to be set. When either - // function returns, they will re-lock the mutex. We use an auto lock/unlock - // class (PThreadMutex::Locker) to allow us to return at any point in this - // function and not have to worry about unlocking the mutex. - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - do - { - // Check our predicate (event bits) in case any are already set - if (mask & m_bits) - { - uint32_t bits_set = mask & m_bits; - // Our PThreadMutex::Locker will automatically unlock our mutex - return bits_set; - } - if (timeout_abstime) - { - // Wait for condition to get broadcast, or for a timeout. If we get - // a timeout we will drop out of the do loop and return false which - // is what we want. - err = ::pthread_cond_timedwait (m_set_condition.Condition(), m_mutex.Mutex(), timeout_abstime); - // Retest our predicate in case of a race condition right at the end - // of the timeout. - if (err == ETIMEDOUT) - { - uint32_t bits_set = mask & m_bits; - return bits_set; - } - } - else - { - // Wait for condition to get broadcast. The only error this function - // should return is if - err = ::pthread_cond_wait (m_set_condition.Condition(), m_mutex.Mutex()); - } - } while (err == 0); - return 0; +PThreadEvent::WaitForSetEvents(const uint32_t mask, + const struct timespec *timeout_abstime) const { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, + // __FUNCTION__, mask, timeout_abstime); + int err = 0; + // pthread_cond_timedwait() or pthread_cond_wait() will atomically + // unlock the mutex and wait for the condition to be set. When either + // function returns, they will re-lock the mutex. We use an auto lock/unlock + // class (PThreadMutex::Locker) to allow us to return at any point in this + // function and not have to worry about unlocking the mutex. + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + do { + // Check our predicate (event bits) in case any are already set + if (mask & m_bits) { + uint32_t bits_set = mask & m_bits; + // Our PThreadMutex::Locker will automatically unlock our mutex + return bits_set; + } + if (timeout_abstime) { + // Wait for condition to get broadcast, or for a timeout. If we get + // a timeout we will drop out of the do loop and return false which + // is what we want. + err = ::pthread_cond_timedwait(m_set_condition.Condition(), + m_mutex.Mutex(), timeout_abstime); + // Retest our predicate in case of a race condition right at the end + // of the timeout. + if (err == ETIMEDOUT) { + uint32_t bits_set = mask & m_bits; + return bits_set; + } + } else { + // Wait for condition to get broadcast. The only error this function + // should return is if + err = ::pthread_cond_wait(m_set_condition.Condition(), m_mutex.Mutex()); + } + } while (err == 0); + return 0; } //---------------------------------------------------------------------- // Wait until 'timeout_abstime' for any events in 'mask' to reset. // If 'timeout_abstime' is NULL, then wait forever. //---------------------------------------------------------------------- -uint32_t -PThreadEvent::WaitForEventsToReset(const uint32_t mask, const struct timespec *timeout_abstime) const -{ - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime); - int err = 0; - // pthread_cond_timedwait() or pthread_cond_wait() will atomically - // unlock the mutex and wait for the condition to be set. When either - // function returns, they will re-lock the mutex. We use an auto lock/unlock - // class (PThreadMutex::Locker) to allow us to return at any point in this - // function and not have to worry about unlocking the mutex. - PTHREAD_MUTEX_LOCKER (locker, m_mutex); - do - { - // Check our predicate (event bits) each time through this do loop - if ((mask & m_bits) == 0) - { - // All the bits requested have been reset, return zero indicating - // which bits from the mask were still set (none of them) - return 0; - } - if (timeout_abstime) - { - // Wait for condition to get broadcast, or for a timeout. If we get - // a timeout we will drop out of the do loop and return false which - // is what we want. - err = ::pthread_cond_timedwait (m_reset_condition.Condition(), m_mutex.Mutex(), timeout_abstime); - } - else - { - // Wait for condition to get broadcast. The only error this function - // should return is if - err = ::pthread_cond_wait (m_reset_condition.Condition(), m_mutex.Mutex()); - } - } while (err == 0); - // Return a mask indicating which bits (if any) were still set - return mask & m_bits; +uint32_t PThreadEvent::WaitForEventsToReset( + const uint32_t mask, const struct timespec *timeout_abstime) const { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, + // __FUNCTION__, mask, timeout_abstime); + int err = 0; + // pthread_cond_timedwait() or pthread_cond_wait() will atomically + // unlock the mutex and wait for the condition to be set. When either + // function returns, they will re-lock the mutex. We use an auto lock/unlock + // class (PThreadMutex::Locker) to allow us to return at any point in this + // function and not have to worry about unlocking the mutex. + PTHREAD_MUTEX_LOCKER(locker, m_mutex); + do { + // Check our predicate (event bits) each time through this do loop + if ((mask & m_bits) == 0) { + // All the bits requested have been reset, return zero indicating + // which bits from the mask were still set (none of them) + return 0; + } + if (timeout_abstime) { + // Wait for condition to get broadcast, or for a timeout. If we get + // a timeout we will drop out of the do loop and return false which + // is what we want. + err = ::pthread_cond_timedwait(m_reset_condition.Condition(), + m_mutex.Mutex(), timeout_abstime); + } else { + // Wait for condition to get broadcast. The only error this function + // should return is if + err = ::pthread_cond_wait(m_reset_condition.Condition(), m_mutex.Mutex()); + } + } while (err == 0); + // Return a mask indicating which bits (if any) were still set + return mask & m_bits; } uint32_t -PThreadEvent::WaitForResetAck (const uint32_t mask, const struct timespec *timeout_abstime) const -{ - if (mask & m_reset_ack_mask) - { - // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime); - return WaitForEventsToReset (mask & m_reset_ack_mask, timeout_abstime); - } - return 0; +PThreadEvent::WaitForResetAck(const uint32_t mask, + const struct timespec *timeout_abstime) const { + if (mask & m_reset_ack_mask) { + // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, + // __FUNCTION__, mask, timeout_abstime); + return WaitForEventsToReset(mask & m_reset_ack_mask, timeout_abstime); + } + return 0; } |