1 //===-- PThreadEvent.cpp ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Created by Greg Clayton on 6/16/07.
12 //===----------------------------------------------------------------------===//
14 #include "PThreadEvent.h"
18 PThreadEvent::PThreadEvent(uint32_t bits, uint32_t validBits) :
23 m_validBits(validBits),
26 // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, 0x%8.8x)", this, __FUNCTION__, bits, validBits);
29 PThreadEvent::~PThreadEvent()
31 // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, __PRETTY_FUNCTION__);
36 PThreadEvent::NewEventBit()
38 // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, __PRETTY_FUNCTION__);
39 PTHREAD_MUTEX_LOCKER (locker, m_mutex);
41 while (mask & m_validBits)
48 PThreadEvent::FreeEventBits(const uint32_t mask)
50 // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask);
53 PTHREAD_MUTEX_LOCKER (locker, m_mutex);
61 PThreadEvent::GetEventBits() const
63 // DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, __PRETTY_FUNCTION__);
64 PTHREAD_MUTEX_LOCKER (locker, m_mutex);
65 uint32_t bits = m_bits;
69 // Replace the event bits with a new bitmask value
71 PThreadEvent::ReplaceEventBits(const uint32_t bits)
73 // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, bits);
74 PTHREAD_MUTEX_LOCKER (locker, m_mutex);
75 // Make sure we have some bits and that they aren't already set...
78 // Figure out which bits are changing
79 uint32_t changed_bits = m_bits ^ bits;
80 // Set the new bit values
82 // If any new bits are set, then broadcast
83 if (changed_bits & m_bits)
84 m_set_condition.Broadcast();
88 // Set one or more event bits and broadcast if any new event bits get set
89 // that weren't already set.
92 PThreadEvent::SetEvents(const uint32_t mask)
94 // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask);
95 // Make sure we have some bits to set
98 PTHREAD_MUTEX_LOCKER (locker, m_mutex);
99 // Save the old event bit state so we can tell if things change
100 uint32_t old = m_bits;
101 // Set the all event bits that are set in 'mask'
103 // Broadcast only if any extra bits got set.
105 m_set_condition.Broadcast();
109 // Reset one or more event bits
111 PThreadEvent::ResetEvents(const uint32_t mask)
113 // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this, __FUNCTION__, mask);
116 PTHREAD_MUTEX_LOCKER (locker, m_mutex);
118 // Save the old event bit state so we can tell if things change
119 uint32_t old = m_bits;
120 // Clear the all event bits that are set in 'mask'
122 // Broadcast only if any extra bits got reset.
124 m_reset_condition.Broadcast();
128 //----------------------------------------------------------------------
129 // Wait until 'timeout_abstime' for any events that are set in
130 // 'mask'. If 'timeout_abstime' is NULL, then wait forever.
131 //----------------------------------------------------------------------
133 PThreadEvent::WaitForSetEvents(const uint32_t mask, const struct timespec *timeout_abstime) const
135 // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime);
137 // pthread_cond_timedwait() or pthread_cond_wait() will atomically
138 // unlock the mutex and wait for the condition to be set. When either
139 // function returns, they will re-lock the mutex. We use an auto lock/unlock
140 // class (PThreadMutex::Locker) to allow us to return at any point in this
141 // function and not have to worry about unlocking the mutex.
142 PTHREAD_MUTEX_LOCKER (locker, m_mutex);
145 // Check our predicate (event bits) in case any are already set
148 uint32_t bits_set = mask & m_bits;
149 // Our PThreadMutex::Locker will automatically unlock our mutex
154 // Wait for condition to get broadcast, or for a timeout. If we get
155 // a timeout we will drop out of the do loop and return false which
157 err = ::pthread_cond_timedwait (m_set_condition.Condition(), m_mutex.Mutex(), timeout_abstime);
158 // Retest our predicate in case of a race condition right at the end
160 if (err == ETIMEDOUT)
162 uint32_t bits_set = mask & m_bits;
168 // Wait for condition to get broadcast. The only error this function
169 // should return is if
170 err = ::pthread_cond_wait (m_set_condition.Condition(), m_mutex.Mutex());
176 //----------------------------------------------------------------------
177 // Wait until 'timeout_abstime' for any events in 'mask' to reset.
178 // If 'timeout_abstime' is NULL, then wait forever.
179 //----------------------------------------------------------------------
181 PThreadEvent::WaitForEventsToReset(const uint32_t mask, const struct timespec *timeout_abstime) const
183 // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime);
185 // pthread_cond_timedwait() or pthread_cond_wait() will atomically
186 // unlock the mutex and wait for the condition to be set. When either
187 // function returns, they will re-lock the mutex. We use an auto lock/unlock
188 // class (PThreadMutex::Locker) to allow us to return at any point in this
189 // function and not have to worry about unlocking the mutex.
190 PTHREAD_MUTEX_LOCKER (locker, m_mutex);
193 // Check our predicate (event bits) each time through this do loop
194 if ((mask & m_bits) == 0)
196 // All the bits requested have been reset, return zero indicating
197 // which bits from the mask were still set (none of them)
202 // Wait for condition to get broadcast, or for a timeout. If we get
203 // a timeout we will drop out of the do loop and return false which
205 err = ::pthread_cond_timedwait (m_reset_condition.Condition(), m_mutex.Mutex(), timeout_abstime);
209 // Wait for condition to get broadcast. The only error this function
210 // should return is if
211 err = ::pthread_cond_wait (m_reset_condition.Condition(), m_mutex.Mutex());
214 // Return a mask indicating which bits (if any) were still set
215 return mask & m_bits;
219 PThreadEvent::WaitForResetAck (const uint32_t mask, const struct timespec *timeout_abstime) const
221 if (mask & m_reset_ack_mask)
223 // DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this, __FUNCTION__, mask, timeout_abstime);
224 return WaitForEventsToReset (mask & m_reset_ack_mask, timeout_abstime);