X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Fwaiter.c;h=aca88eb4db75ade4fa28b971d4616be68bd92742;hp=c5a2829408215784952d047e272c12682e291c23;hb=HEAD;hpb=287a512f2b868c16132b894a8143a5faf0379ca8 diff --git a/src/common/waiter.c b/src/common/waiter.c deleted file mode 100644 index c5a282940..000000000 --- a/src/common/waiter.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2012 - Mathieu Desnoyers - * 2017 - Jérémie Galarneau - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License, version 2.1 only, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * This code is originally adapted from userspace-rcu's urcu-wait.h - */ - -#include "waiter.h" -#include -#include -#include -#include "error.h" -#include - -/* - * Number of busy-loop attempts before waiting on futex. - */ -#define WAIT_ATTEMPTS 1000 - -enum waiter_state { - /* WAITER_WAITING is compared directly (futex compares it). */ - WAITER_WAITING = 0, - /* non-zero are used as masks. */ - WAITER_WOKEN_UP = (1 << 0), - WAITER_RUNNING = (1 << 1), - WAITER_TEARDOWN = (1 << 2), -}; - -LTTNG_HIDDEN -void lttng_waiter_init(struct lttng_waiter *waiter) -{ - cds_wfs_node_init(&waiter->wait_queue_node); - uatomic_set(&waiter->state, WAITER_WAITING); - cmm_smp_mb(); -} - -/* - * User must init "waiter" before passing its memory to waker thread. - */ -LTTNG_HIDDEN -void lttng_waiter_wait(struct lttng_waiter *waiter) -{ - unsigned int i; - - DBG("Beginning of waiter wait period"); - /* Load and test condition before read state */ - cmm_smp_rmb(); - for (i = 0; i < WAIT_ATTEMPTS; i++) { - if (uatomic_read(&waiter->state) != WAITER_WAITING) { - goto skip_futex_wait; - } - caa_cpu_relax(); - } - while (futex_noasync(&waiter->state, FUTEX_WAIT, WAITER_WAITING, - NULL, NULL, 0)) { - switch (errno) { - case EWOULDBLOCK: - /* Value already changed. */ - goto skip_futex_wait; - case EINTR: - /* Retry if interrupted by signal. */ - break; /* Get out of switch. */ - default: - /* Unexpected error. */ - PERROR("futex_noasync"); - abort(); - } - } -skip_futex_wait: - - /* Tell waker thread than we are running. */ - uatomic_or(&waiter->state, WAITER_RUNNING); - - /* - * Wait until waker thread lets us know it's ok to tear down - * memory allocated for struct lttng_waiter. - */ - for (i = 0; i < WAIT_ATTEMPTS; i++) { - if (uatomic_read(&waiter->state) & WAITER_TEARDOWN) { - break; - } - caa_cpu_relax(); - } - while (!(uatomic_read(&waiter->state) & WAITER_TEARDOWN)) { - poll(NULL, 0, 10); - } - assert(uatomic_read(&waiter->state) & WAITER_TEARDOWN); - DBG("End of waiter wait period"); -} - -/* - * Note: lttng_waiter_wake needs waiter to stay allocated throughout its - * execution. In this scheme, the waiter owns the node memory, and we only allow - * it to free this memory when it sees the WAITER_TEARDOWN flag. - */ -LTTNG_HIDDEN -void lttng_waiter_wake_up(struct lttng_waiter *waiter) -{ - cmm_smp_mb(); - 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) { - PERROR("futex_noasync"); - abort(); - } - } - /* Allow teardown of struct urcu_wait memory. */ - uatomic_or(&waiter->state, WAITER_TEARDOWN); -}