Initial import of lldb
Change-Id: Ib244e837bee349effa12b2ff6ffffbe3d730e929
This commit is contained in:
227
external/bsd/llvm/dist/lldb/tools/debugserver/source/PThreadEvent.cpp
vendored
Normal file
227
external/bsd/llvm/dist/lldb/tools/debugserver/source/PThreadEvent.cpp
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
//===-- PThreadEvent.cpp ----------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Created by Greg Clayton on 6/16/07.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PThreadEvent.h"
|
||||
#include "errno.h"
|
||||
#include "DNBLog.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()
|
||||
{
|
||||
// DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, __PRETTY_FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
PThreadEvent::NewEventBit()
|
||||
{
|
||||
// DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, __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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
PThreadEvent::GetEventBits() const
|
||||
{
|
||||
// DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, __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();
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Wait until 'timeout_abstime' for any events that are set in
|
||||
// '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;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 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::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;
|
||||
}
|
||||
Reference in New Issue
Block a user