X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Fwaiter.cpp;h=c0ea3392fceea52f1438b6e839c1742e7348503b;hb=00c2aa6f664e9ec249fd297fb01309477917d029;hp=3ddb68feb7c76dd91f09bec9d7664c02224627a2;hpb=c9e313bc594f40a86eed237dce222c0fc99c957f;p=lttng-tools.git diff --git a/src/common/waiter.cpp b/src/common/waiter.cpp index 3ddb68feb..c0ea3392f 100644 --- a/src/common/waiter.cpp +++ b/src/common/waiter.cpp @@ -6,11 +6,12 @@ * */ -#include "waiter.hpp" -#include -#include #include "error.hpp" +#include "waiter.hpp" + #include +#include +#include /* * Number of busy-loop attempts before waiting on futex. @@ -19,11 +20,11 @@ enum waiter_state { /* WAITER_WAITING is compared directly (futex compares it). */ - WAITER_WAITING = 0, + WAITER_WAITING = 0, /* non-zero are used as masks. */ - WAITER_WOKEN_UP = (1 << 0), - WAITER_RUNNING = (1 << 1), - WAITER_TEARDOWN = (1 << 2), + WAITER_WOKEN_UP = (1 << 0), + WAITER_RUNNING = (1 << 1), + WAITER_TEARDOWN = (1 << 2), }; void lttng_waiter_init(struct lttng_waiter *waiter) @@ -49,15 +50,26 @@ void lttng_waiter_wait(struct lttng_waiter *waiter) } caa_cpu_relax(); } - while (futex_noasync(&waiter->state, FUTEX_WAIT, WAITER_WAITING, - NULL, NULL, 0)) { + while (uatomic_read(&waiter->state) == WAITER_WAITING) { + if (!futex_noasync( + &waiter->state, FUTEX_WAIT, WAITER_WAITING, nullptr, nullptr, 0)) { + /* + * Prior queued wakeups queued by unrelated code + * using the same address can cause futex wait to + * return 0 even through the futex value is still + * WAITER_WAITING (spurious wakeups). Check + * the value again in user-space to validate + * whether it really differs from WAITER_WAITING. + */ + continue; + } switch (errno) { - case EWOULDBLOCK: + case EAGAIN: /* Value already changed. */ goto skip_futex_wait; case EINTR: /* Retry if interrupted by signal. */ - break; /* Get out of switch. */ + break; /* Get out of switch. Check again. */ default: /* Unexpected error. */ PERROR("futex_noasync"); @@ -80,7 +92,7 @@ skip_futex_wait: caa_cpu_relax(); } while (!(uatomic_read(&waiter->state) & WAITER_TEARDOWN)) { - poll(NULL, 0, 10); + poll(nullptr, 0, 10); } LTTNG_ASSERT(uatomic_read(&waiter->state) & WAITER_TEARDOWN); DBG("End of waiter wait period"); @@ -97,8 +109,7 @@ void lttng_waiter_wake_up(struct lttng_waiter *waiter) LTTNG_ASSERT(uatomic_read(&waiter->state) == WAITER_WAITING); uatomic_set(&waiter->state, WAITER_WOKEN_UP); if (!(uatomic_read(&waiter->state) & WAITER_RUNNING)) { - if (futex_noasync(&waiter->state, FUTEX_WAKE, 1, - NULL, NULL, 0) < 0) { + if (futex_noasync(&waiter->state, FUTEX_WAKE, 1, nullptr, nullptr, 0) < 0) { PERROR("futex_noasync"); abort(); }