Skip to content

Commit

Permalink
src/bthread/butex.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
jenrryyou committed Jan 15, 2023
1 parent b734c4e commit 4d84f91
Showing 1 changed file with 28 additions and 23 deletions.
51 changes: 28 additions & 23 deletions src/bthread/butex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,21 @@ static void wakeup_pthread(ButexPthreadWaiter* pw) {

bool erase_from_butex(ButexWaiter*, bool, WaiterState);

int wait_pthread(ButexPthreadWaiter& pw, timespec* ptimeout) {
int wait_pthread(ButexPthreadWaiter& pw, const timespec* abstime) {
timespec * ptimeout = NULL;
timespec timeout;
int64_t timeout_us;

if (abstime != NULL) {
timeout_us = butil::timespec_to_microseconds(*abstime) - butil::gettimeofday_us();
if (timeout_us < MIN_SLEEP_US) {
errno = ETIMEDOUT;
return -1;
}
timeout = butil::microseconds_to_timespec(timeout_us);
ptimeout = &timeout;
}

while (true) {
const int rc = futex_wait_private(&pw.sig, PTHREAD_NOT_SIGNALLED, ptimeout);
if (PTHREAD_NOT_SIGNALLED != pw.sig.load(butil::memory_order_acquire)) {
Expand All @@ -146,13 +160,19 @@ int wait_pthread(ButexPthreadWaiter& pw, timespec* ptimeout) {
// Acquire fence makes this thread sees changes before wakeup.
return rc;
}
if (rc != 0 && errno == ETIMEDOUT) {
// Note that we don't handle the EINTR from futex_wait here since
// pthreads waiting on a butex should behave similarly as bthreads
// which are not able to be woken-up by signals.
// EINTR on butex is only producible by TaskGroup::interrupt().
if (rc != 0 && ptimeout != NULL) {
// Handle the EINTR from futex_wait
if (errno != ETIMEDOUT)
{
timeout_us = butil::timespec_to_microseconds(*abstime) - butil::gettimeofday_us();
if (timeout_us > MIN_SLEEP_US) {
timeout = butil::microseconds_to_timespec(timeout_us);
continue;
}
errno = ETIMEDOUT;
}

// `pw' is still in the queue, remove it.
// wait futex timeout, `pw' is still in the queue, remove it.
if (!erase_from_butex(&pw, false, WAITER_STATE_TIMEDOUT)) {
// Another thread is erasing `pw' as well, wait for the signal.
// Acquire fence makes this thread sees changes before wakeup.
Expand Down Expand Up @@ -567,21 +587,6 @@ static void wait_for_butex(void* arg) {

static int butex_wait_from_pthread(TaskGroup* g, Butex* b, int expected_value,
const timespec* abstime) {
// sys futex needs relative timeout.
// Compute diff between abstime and now.
timespec* ptimeout = NULL;
timespec timeout;
if (abstime != NULL) {
const int64_t timeout_us = butil::timespec_to_microseconds(*abstime) -
butil::gettimeofday_us();
if (timeout_us < MIN_SLEEP_US) {
errno = ETIMEDOUT;
return -1;
}
timeout = butil::microseconds_to_timespec(timeout_us);
ptimeout = &timeout;
}

TaskMeta* task = NULL;
ButexPthreadWaiter pw;
pw.tid = 0;
Expand Down Expand Up @@ -612,7 +617,7 @@ static int butex_wait_from_pthread(TaskGroup* g, Butex* b, int expected_value,
bvar::Adder<int64_t>& num_waiters = butex_waiter_count();
num_waiters << 1;
#endif
rc = wait_pthread(pw, ptimeout);
rc = wait_pthread(pw, abstime);
#ifdef SHOW_BTHREAD_BUTEX_WAITER_COUNT_IN_VARS
num_waiters << -1;
#endif
Expand Down

0 comments on commit 4d84f91

Please sign in to comment.