Skip to content

Commit c21d8a2

Browse files
JDevlieghereIanWood1
authored andcommitted
[debugserver] Migrate PThreadEvent away from PThreadMutex (NFC) (llvm#137554)
The debugserver code predates modern C++, but with C++11 and later there's no need to have something like PThreadMutex. This migrates PThreadEvent away from PThreadMutex in preparation for removing it.
1 parent 6ef1cbd commit c21d8a2

File tree

2 files changed

+40
-47
lines changed

2 files changed

+40
-47
lines changed

lldb/tools/debugserver/source/PThreadEvent.cpp

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
#include <cerrno>
1616

1717
PThreadEvent::PThreadEvent(uint32_t bits, uint32_t validBits)
18-
: m_mutex(), m_set_condition(), m_reset_condition(), m_bits(bits),
19-
m_validBits(validBits), m_reset_ack_mask(0) {
18+
: m_mutex(), m_set_condition(), m_bits(bits), m_validBits(validBits),
19+
m_reset_ack_mask(0) {
2020
// DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, 0x%8.8x)",
2121
// this, __FUNCTION__, bits, validBits);
2222
}
@@ -27,7 +27,7 @@ PThreadEvent::~PThreadEvent() {
2727

2828
uint32_t PThreadEvent::NewEventBit() {
2929
// DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION);
30-
PTHREAD_MUTEX_LOCKER(locker, m_mutex);
30+
std::lock_guard<std::mutex> guard(m_mutex);
3131
uint32_t mask = 1;
3232
while (mask & m_validBits)
3333
mask <<= 1;
@@ -39,15 +39,15 @@ void PThreadEvent::FreeEventBits(const uint32_t mask) {
3939
// DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this,
4040
// __FUNCTION__, mask);
4141
if (mask) {
42-
PTHREAD_MUTEX_LOCKER(locker, m_mutex);
42+
std::lock_guard<std::mutex> guard(m_mutex);
4343
m_bits &= ~mask;
4444
m_validBits &= ~mask;
4545
}
4646
}
4747

4848
uint32_t PThreadEvent::GetEventBits() const {
4949
// DNBLogThreadedIf(LOG_EVENTS, "%p %s", this, LLVM_PRETTY_FUNCTION);
50-
PTHREAD_MUTEX_LOCKER(locker, m_mutex);
50+
std::lock_guard<std::mutex> guard(m_mutex);
5151
uint32_t bits = m_bits;
5252
return bits;
5353
}
@@ -56,7 +56,7 @@ uint32_t PThreadEvent::GetEventBits() const {
5656
void PThreadEvent::ReplaceEventBits(const uint32_t bits) {
5757
// DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this,
5858
// __FUNCTION__, bits);
59-
PTHREAD_MUTEX_LOCKER(locker, m_mutex);
59+
std::lock_guard<std::mutex> guard(m_mutex);
6060
// Make sure we have some bits and that they aren't already set...
6161
if (m_bits != bits) {
6262
// Figure out which bits are changing
@@ -65,7 +65,7 @@ void PThreadEvent::ReplaceEventBits(const uint32_t bits) {
6565
m_bits = bits;
6666
// If any new bits are set, then broadcast
6767
if (changed_bits & m_bits)
68-
m_set_condition.Broadcast();
68+
m_set_condition.notify_all();
6969
}
7070
}
7171

@@ -77,14 +77,14 @@ void PThreadEvent::SetEvents(const uint32_t mask) {
7777
// __FUNCTION__, mask);
7878
// Make sure we have some bits to set
7979
if (mask) {
80-
PTHREAD_MUTEX_LOCKER(locker, m_mutex);
80+
std::lock_guard<std::mutex> guard(m_mutex);
8181
// Save the old event bit state so we can tell if things change
8282
uint32_t old = m_bits;
8383
// Set the all event bits that are set in 'mask'
8484
m_bits |= mask;
8585
// Broadcast only if any extra bits got set.
8686
if (old != m_bits)
87-
m_set_condition.Broadcast();
87+
m_set_condition.notify_all();
8888
}
8989
}
9090

@@ -93,18 +93,27 @@ void PThreadEvent::ResetEvents(const uint32_t mask) {
9393
// DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x)", this,
9494
// __FUNCTION__, mask);
9595
if (mask) {
96-
PTHREAD_MUTEX_LOCKER(locker, m_mutex);
97-
98-
// Save the old event bit state so we can tell if things change
99-
uint32_t old = m_bits;
96+
std::lock_guard<std::mutex> guard(m_mutex);
10097
// Clear the all event bits that are set in 'mask'
10198
m_bits &= ~mask;
102-
// Broadcast only if any extra bits got reset.
103-
if (old != m_bits)
104-
m_reset_condition.Broadcast();
10599
}
106100
}
107101

102+
static std::chrono::nanoseconds ToDuration(timespec ts) {
103+
auto duration =
104+
std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec};
105+
return std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
106+
}
107+
108+
static std::chrono::time_point<std::chrono::system_clock,
109+
std::chrono::nanoseconds>
110+
ToTimePoint(timespec ts) {
111+
return std::chrono::time_point<std::chrono::system_clock,
112+
std::chrono::nanoseconds>{
113+
std::chrono::duration_cast<std::chrono::system_clock::duration>(
114+
ToDuration(ts))};
115+
}
116+
108117
// Wait until 'timeout_abstime' for any events that are set in
109118
// 'mask'. If 'timeout_abstime' is NULL, then wait forever.
110119
uint32_t
@@ -113,30 +122,17 @@ PThreadEvent::WaitForEventsImpl(const uint32_t mask,
113122
std::function<bool()> predicate) const {
114123
// DNBLogThreadedIf(LOG_EVENTS, "%p PThreadEvent::%s (0x%8.8x, %p)", this,
115124
// __FUNCTION__, mask, timeout_abstime);
116-
117-
int err = 0;
118-
119-
// pthread_cond_timedwait() or pthread_cond_wait() will atomically
120-
// unlock the mutex and wait for the condition to be set. When either
121-
// function returns, they will re-lock the mutex. We use an auto lock/unlock
122-
// class (PThreadMutex::Locker) to allow us to return at any point in this
123-
// function and not have to worry about unlocking the mutex.
124-
PTHREAD_MUTEX_LOCKER(locker, m_mutex);
125-
126-
// Check the predicate and the error code. The functions below do not return
127-
// EINTR so that's not something we need to handle.
128-
while (!predicate() && err == 0) {
129-
if (timeout_abstime) {
130-
// Wait for condition to get broadcast, or for a timeout. If we get
131-
// a timeout we will drop out of the loop on the next iteration and we
132-
// will recompute the mask in case of a race between the condition and the
133-
// timeout.
134-
err = ::pthread_cond_timedwait(m_set_condition.Condition(),
135-
m_mutex.Mutex(), timeout_abstime);
136-
} else {
137-
// Wait for condition to get broadcast.
138-
err = ::pthread_cond_wait(m_set_condition.Condition(), m_mutex.Mutex());
139-
}
125+
std::unique_lock<std::mutex> lock(m_mutex);
126+
127+
if (timeout_abstime) {
128+
// Wait for condition to get broadcast, or for a timeout. If we get
129+
// a timeout we will drop out of the loop on the next iteration and we
130+
// will recompute the mask in case of a race between the condition and the
131+
// timeout.
132+
m_set_condition.wait_until(lock, ToTimePoint(*timeout_abstime), predicate);
133+
} else {
134+
// Wait for condition to get broadcast.
135+
m_set_condition.wait(lock, predicate);
140136
}
141137

142138
// Either the predicate passed, we hit the specified timeout (ETIMEDOUT) or we

lldb/tools/debugserver/source/PThreadEvent.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212

1313
#ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_PTHREADEVENT_H
1414
#define LLDB_TOOLS_DEBUGSERVER_SOURCE_PTHREADEVENT_H
15-
#include "PThreadCondition.h"
16-
#include "PThreadMutex.h"
15+
1716
#include <cstdint>
1817
#include <ctime>
1918
#include <functional>
19+
#include <mutex>
2020

2121
class PThreadEvent {
2222
public:
@@ -45,11 +45,8 @@ class PThreadEvent {
4545
const struct timespec *timeout_abstime = NULL) const;
4646

4747
protected:
48-
// pthread condition and mutex variable to control access and allow
49-
// blocking between the main thread and the spotlight index thread.
50-
mutable PThreadMutex m_mutex;
51-
mutable PThreadCondition m_set_condition;
52-
mutable PThreadCondition m_reset_condition;
48+
mutable std::mutex m_mutex;
49+
mutable std::condition_variable m_set_condition;
5350
uint32_t m_bits;
5451
uint32_t m_validBits;
5552
uint32_t m_reset_ack_mask;

0 commit comments

Comments
 (0)