noinst_LTLIBRARIES = \
libcounter.la \
- libcompat.la \
libmsgpack.la \
libringbuffer.la \
libsnprintf.la \
libcounter_la_CFLAGS = -DUST_COMPONENT="libcounter" $(AM_CFLAGS)
-# compat
-libcompat_la_SOURCES = \
- compat/futex.c \
- compat/futex.h
-
# msgpack
libmsgpack_la_SOURCES = \
msgpack/msgpack.c \
patient.c
libcommon_la_LIBADD = \
- libcompat.la \
libmsgpack.la \
libsnprintf.la
+++ /dev/null
-/*
- * SPDX-License-Identifier: LGPL-2.1-or-later
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * Userspace RCU library - sys_futex compatibility code
- */
-
-#include <stdio.h>
-#include <pthread.h>
-#include <signal.h>
-#include <assert.h>
-#include <errno.h>
-#include <poll.h>
-#include <stdint.h>
-
-#include <urcu/arch.h>
-#include <urcu/system.h>
-
-#include "common/compat/futex.h"
-
-/*
- * Using attribute "weak" for __lttng_ust_compat_futex_lock and
- * __lttng_ust_compat_futex_cond. Those are globally visible by the entire
- * program, even though many shared objects may have their own version.
- * The first version that gets loaded will be used by the entire program
- * (executable and all shared objects).
- */
-
-__attribute__((weak))
-pthread_mutex_t __lttng_ust_compat_futex_lock = PTHREAD_MUTEX_INITIALIZER;
-__attribute__((weak))
-pthread_cond_t __lttng_ust_compat_futex_cond = PTHREAD_COND_INITIALIZER;
-
-/*
- * _NOT SIGNAL-SAFE_. pthread_cond is not signal-safe anyway. Though.
- * For now, timeout, uaddr2 and val3 are unused.
- * Waiter will relinquish the CPU until woken up.
- */
-
-int lttng_ust_compat_futex_noasync(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
-{
- int ret = 0, lockret;
-
- /*
- * Check if NULL. Don't let users expect that they are taken into
- * account.
- */
- assert(!timeout);
- assert(!uaddr2);
- assert(!val3);
-
- /*
- * memory barriers to serialize with the previous uaddr modification.
- */
- cmm_smp_mb();
-
- lockret = pthread_mutex_lock(&__lttng_ust_compat_futex_lock);
- if (lockret) {
- errno = lockret;
- ret = -1;
- goto end;
- }
- switch (op) {
- case FUTEX_WAIT:
- /*
- * Wait until *uaddr is changed to something else than "val".
- * Comparing *uaddr content against val figures out which
- * thread has been awakened.
- */
- while (CMM_LOAD_SHARED(*uaddr) == val)
- pthread_cond_wait(&__lttng_ust_compat_futex_cond,
- &__lttng_ust_compat_futex_lock);
- break;
- case FUTEX_WAKE:
- /*
- * Each wake is sending a broadcast, thus attempting wakeup of
- * all awaiting threads, independently of their respective
- * uaddr.
- */
- pthread_cond_broadcast(&__lttng_ust_compat_futex_cond);
- break;
- default:
- errno = EINVAL;
- ret = -1;
- }
- lockret = pthread_mutex_unlock(&__lttng_ust_compat_futex_lock);
- if (lockret) {
- errno = lockret;
- ret = -1;
- }
-end:
- return ret;
-}
-
-/*
- * _ASYNC SIGNAL-SAFE_.
- * For now, timeout, uaddr2 and val3 are unused.
- * Waiter will busy-loop trying to read the condition.
- * It is OK to use compat_futex_async() on a futex address on which
- * futex() WAKE operations are also performed.
- */
-
-int lttng_ust_compat_futex_async(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
-{
- int ret = 0;
-
- /*
- * Check if NULL. Don't let users expect that they are taken into
- * account.
- */
- assert(!timeout);
- assert(!uaddr2);
- assert(!val3);
-
- /*
- * Ensure previous memory operations on uaddr have completed.
- */
- cmm_smp_mb();
-
- switch (op) {
- case FUTEX_WAIT:
- while (CMM_LOAD_SHARED(*uaddr) == val) {
- if (poll(NULL, 0, 10) < 0) {
- ret = -1;
- /* Keep poll errno. Caller handles EINTR. */
- goto end;
- }
- }
- break;
- case FUTEX_WAKE:
- break;
- default:
- errno = EINVAL;
- ret = -1;
- }
-end:
- return ret;
-}
+++ /dev/null
-/*
- * SPDX-License-Identifier: LGPL-2.1-or-later
- *
- * Copyright 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * Userspace RCU - sys_futex/compat_futex header.
- */
-
-#ifndef _UST_COMMON_COMPAT_FUTEX_H
-#define _UST_COMMON_COMPAT_FUTEX_H
-
-#include <errno.h>
-#include <stdint.h>
-#include <time.h>
-#include <sys/syscall.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define FUTEX_WAIT 0
-#define FUTEX_WAKE 1
-
-/*
- * sys_futex compatibility header.
- * Use *only* *either of* futex_noasync OR futex_async on a given address.
- *
- * futex_noasync cannot be executed in signal handlers, but ensures that
- * it will be put in a wait queue even in compatibility mode.
- *
- * futex_async is signal-handler safe for the wakeup. It uses polling
- * on the wait-side in compatibility mode.
- *
- * BEWARE: sys_futex() FUTEX_WAIT may return early if interrupted
- * (returns EINTR).
- */
-
-extern int lttng_ust_compat_futex_noasync(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
- __attribute__((visibility("hidden")));
-
-extern int lttng_ust_compat_futex_async(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
- __attribute__((visibility("hidden")));
-
-#if (defined(__linux__) && defined(__NR_futex))
-
-#include <unistd.h>
-#include <errno.h>
-#include <urcu/compiler.h>
-#include <urcu/arch.h>
-
-static inline int lttng_ust_futex(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
-{
- return syscall(__NR_futex, uaddr, op, val, timeout,
- uaddr2, val3);
-}
-
-static inline int lttng_ust_futex_noasync(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
-{
- int ret;
-
- ret = lttng_ust_futex(uaddr, op, val, timeout, uaddr2, val3);
- if (caa_unlikely(ret < 0 && errno == ENOSYS)) {
- /*
- * The fallback on ENOSYS is the async-safe version of
- * the compat futex implementation, because the
- * async-safe compat implementation allows being used
- * concurrently with calls to futex(). Indeed, sys_futex
- * FUTEX_WAIT, on some architectures (mips and parisc),
- * within a given process, spuriously return ENOSYS due
- * to signal restart bugs on some kernel versions.
- */
- return lttng_ust_compat_futex_async(uaddr, op, val, timeout,
- uaddr2, val3);
- }
- return ret;
-
-}
-
-static inline int lttng_ust_futex_async(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
-{
- int ret;
-
- ret = lttng_ust_futex(uaddr, op, val, timeout, uaddr2, val3);
- if (caa_unlikely(ret < 0 && errno == ENOSYS)) {
- return lttng_ust_compat_futex_async(uaddr, op, val, timeout,
- uaddr2, val3);
- }
- return ret;
-}
-
-#elif defined(__FreeBSD__)
-
-#include <sys/types.h>
-#include <sys/umtx.h>
-
-static inline int lttng_ust_futex_async(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout,
- int32_t *uaddr2 __attribute__((unused)),
- int32_t val3 __attribute__((unused)))
-{
- int umtx_op;
- void *umtx_uaddr = NULL, *umtx_uaddr2 = NULL;
- struct _umtx_time umtx_timeout = {
- ._flags = UMTX_ABSTIME,
- ._clockid = CLOCK_MONOTONIC,
- };
-
- switch (op) {
- case FUTEX_WAIT:
- /* On FreeBSD, a "u_int" is a 32-bit integer. */
- umtx_op = UMTX_OP_WAIT_UINT;
- if (timeout != NULL) {
- umtx_timeout._timeout = *timeout;
- umtx_uaddr = (void *) sizeof(umtx_timeout);
- umtx_uaddr2 = (void *) &umtx_timeout;
- }
- break;
- case FUTEX_WAKE:
- umtx_op = UMTX_OP_WAKE;
- break;
- default:
- errno = EINVAL;
- return -1;
- }
-
- return _umtx_op(uaddr, umtx_op, (uint32_t) val, umtx_uaddr,
- umtx_uaddr2);
-}
-
-static inline int lttng_ust_futex_noasync(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
-{
- return lttng_ust_futex_async(uaddr, op, val, timeout, uaddr2, val3);
-}
-
-#elif defined(__CYGWIN__)
-
-/*
- * The futex_noasync compat code uses a weak symbol to share state across
- * different shared object which is not possible on Windows with the
- * Portable Executable format. Use the async compat code for both cases.
- */
-static inline int lttng_ust_futex_noasync(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
-{
- return lttng_ust_compat_futex_async(uaddr, op, val, timeout, uaddr2, val3);
-}
-
-static inline int lttng_ust_futex_async(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
-{
- return lttng_ust_compat_futex_async(uaddr, op, val, timeout, uaddr2, val3);
-}
-
-#else
-
-static inline int lttng_ust_futex_noasync(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
-{
- return lttng_ust_compat_futex_noasync(uaddr, op, val, timeout, uaddr2, val3);
-}
-
-static inline int lttng_ust_futex_async(int32_t *uaddr, int op, int32_t val,
- const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
-{
- return lttng_ust_compat_futex_async(uaddr, op, val, timeout, uaddr2, val3);
-}
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _UST_COMMON_COMPAT_FUTEX_H */
lttng-ust-statedump.c \
lttng-ust-statedump.h \
lttng-ust-statedump-provider.h \
+ futex.c \
+ futex.h \
ust_lib.c \
ust_lib.h \
context-internal.h \
--- /dev/null
+/*
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Userspace RCU library - sys_futex compatibility code
+ */
+
+#include <stdio.h>
+#include <pthread.h>
+#include <signal.h>
+#include <assert.h>
+#include <errno.h>
+#include <poll.h>
+#include <stdint.h>
+
+#include <urcu/arch.h>
+#include <urcu/system.h>
+
+#include "lib/lttng-ust/futex.h"
+
+/*
+ * This compat header originated in userspace RCU where it's used across
+ * multiple shared objects hence the need to have the mutexes as public weak
+ * symbols, in our case here, it's only used internally by liblttng-ust so we
+ * can hide them. If we end up using this compat header in another library in
+ * this project we will have to use the same scheme, but in the meantime, don't
+ * expose those symbols in the ABI.
+ */
+
+/*
+ * This comment will apply if we start using this compat header in multiple
+ * libraires.
+ *
+ * Using attribute "weak" for __lttng_ust_compat_futex_lock and
+ * __lttng_ust_compat_futex_cond. Those are globally visible by the entire
+ * program, even though many shared objects may have their own version.
+ * The first version that gets loaded will be used by the entire program
+ * (executable and all shared objects).
+ */
+
+static pthread_mutex_t __lttng_ust_compat_futex_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t __lttng_ust_compat_futex_cond = PTHREAD_COND_INITIALIZER;
+
+/*
+ * _NOT SIGNAL-SAFE_. pthread_cond is not signal-safe anyway. Though.
+ * For now, timeout, uaddr2 and val3 are unused.
+ * Waiter will relinquish the CPU until woken up.
+ */
+
+int lttng_ust_compat_futex_noasync(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+{
+ int ret = 0, lockret;
+
+ /*
+ * Check if NULL. Don't let users expect that they are taken into
+ * account.
+ */
+ assert(!timeout);
+ assert(!uaddr2);
+ assert(!val3);
+
+ /*
+ * memory barriers to serialize with the previous uaddr modification.
+ */
+ cmm_smp_mb();
+
+ lockret = pthread_mutex_lock(&__lttng_ust_compat_futex_lock);
+ if (lockret) {
+ errno = lockret;
+ ret = -1;
+ goto end;
+ }
+ switch (op) {
+ case FUTEX_WAIT:
+ /*
+ * Wait until *uaddr is changed to something else than "val".
+ * Comparing *uaddr content against val figures out which
+ * thread has been awakened.
+ */
+ while (CMM_LOAD_SHARED(*uaddr) == val)
+ pthread_cond_wait(&__lttng_ust_compat_futex_cond,
+ &__lttng_ust_compat_futex_lock);
+ break;
+ case FUTEX_WAKE:
+ /*
+ * Each wake is sending a broadcast, thus attempting wakeup of
+ * all awaiting threads, independently of their respective
+ * uaddr.
+ */
+ pthread_cond_broadcast(&__lttng_ust_compat_futex_cond);
+ break;
+ default:
+ errno = EINVAL;
+ ret = -1;
+ }
+ lockret = pthread_mutex_unlock(&__lttng_ust_compat_futex_lock);
+ if (lockret) {
+ errno = lockret;
+ ret = -1;
+ }
+end:
+ return ret;
+}
+
+/*
+ * _ASYNC SIGNAL-SAFE_.
+ * For now, timeout, uaddr2 and val3 are unused.
+ * Waiter will busy-loop trying to read the condition.
+ * It is OK to use compat_futex_async() on a futex address on which
+ * futex() WAKE operations are also performed.
+ */
+
+int lttng_ust_compat_futex_async(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+{
+ int ret = 0;
+
+ /*
+ * Check if NULL. Don't let users expect that they are taken into
+ * account.
+ */
+ assert(!timeout);
+ assert(!uaddr2);
+ assert(!val3);
+
+ /*
+ * Ensure previous memory operations on uaddr have completed.
+ */
+ cmm_smp_mb();
+
+ switch (op) {
+ case FUTEX_WAIT:
+ while (CMM_LOAD_SHARED(*uaddr) == val) {
+ if (poll(NULL, 0, 10) < 0) {
+ ret = -1;
+ /* Keep poll errno. Caller handles EINTR. */
+ goto end;
+ }
+ }
+ break;
+ case FUTEX_WAKE:
+ break;
+ default:
+ errno = EINVAL;
+ ret = -1;
+ }
+end:
+ return ret;
+}
--- /dev/null
+/*
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * Copyright 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * Userspace RCU - sys_futex/compat_futex header.
+ */
+
+#ifndef _UST_COMMON_COMPAT_FUTEX_H
+#define _UST_COMMON_COMPAT_FUTEX_H
+
+#include <errno.h>
+#include <stdint.h>
+#include <time.h>
+#include <sys/syscall.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+
+/*
+ * sys_futex compatibility header.
+ * Use *only* *either of* futex_noasync OR futex_async on a given address.
+ *
+ * futex_noasync cannot be executed in signal handlers, but ensures that
+ * it will be put in a wait queue even in compatibility mode.
+ *
+ * futex_async is signal-handler safe for the wakeup. It uses polling
+ * on the wait-side in compatibility mode.
+ *
+ * BEWARE: sys_futex() FUTEX_WAIT may return early if interrupted
+ * (returns EINTR).
+ */
+
+int lttng_ust_compat_futex_noasync(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+ __attribute__((visibility("hidden")));
+
+int lttng_ust_compat_futex_async(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+ __attribute__((visibility("hidden")));
+
+#if (defined(__linux__) && defined(__NR_futex))
+
+#include <unistd.h>
+#include <errno.h>
+#include <urcu/compiler.h>
+#include <urcu/arch.h>
+
+static inline int lttng_ust_futex(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+{
+ return syscall(__NR_futex, uaddr, op, val, timeout,
+ uaddr2, val3);
+}
+
+static inline int lttng_ust_futex_noasync(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+{
+ int ret;
+
+ ret = lttng_ust_futex(uaddr, op, val, timeout, uaddr2, val3);
+ if (caa_unlikely(ret < 0 && errno == ENOSYS)) {
+ /*
+ * The fallback on ENOSYS is the async-safe version of
+ * the compat futex implementation, because the
+ * async-safe compat implementation allows being used
+ * concurrently with calls to futex(). Indeed, sys_futex
+ * FUTEX_WAIT, on some architectures (mips and parisc),
+ * within a given process, spuriously return ENOSYS due
+ * to signal restart bugs on some kernel versions.
+ */
+ return lttng_ust_compat_futex_async(uaddr, op, val, timeout,
+ uaddr2, val3);
+ }
+ return ret;
+
+}
+
+static inline int lttng_ust_futex_async(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+{
+ int ret;
+
+ ret = lttng_ust_futex(uaddr, op, val, timeout, uaddr2, val3);
+ if (caa_unlikely(ret < 0 && errno == ENOSYS)) {
+ return lttng_ust_compat_futex_async(uaddr, op, val, timeout,
+ uaddr2, val3);
+ }
+ return ret;
+}
+
+#elif defined(__FreeBSD__)
+
+#include <sys/types.h>
+#include <sys/umtx.h>
+
+static inline int lttng_ust_futex_async(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout,
+ int32_t *uaddr2 __attribute__((unused)),
+ int32_t val3 __attribute__((unused)))
+{
+ int umtx_op;
+ void *umtx_uaddr = NULL, *umtx_uaddr2 = NULL;
+ struct _umtx_time umtx_timeout = {
+ ._flags = UMTX_ABSTIME,
+ ._clockid = CLOCK_MONOTONIC,
+ };
+
+ switch (op) {
+ case FUTEX_WAIT:
+ /* On FreeBSD, a "u_int" is a 32-bit integer. */
+ umtx_op = UMTX_OP_WAIT_UINT;
+ if (timeout != NULL) {
+ umtx_timeout._timeout = *timeout;
+ umtx_uaddr = (void *) sizeof(umtx_timeout);
+ umtx_uaddr2 = (void *) &umtx_timeout;
+ }
+ break;
+ case FUTEX_WAKE:
+ umtx_op = UMTX_OP_WAKE;
+ break;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ return _umtx_op(uaddr, umtx_op, (uint32_t) val, umtx_uaddr,
+ umtx_uaddr2);
+}
+
+static inline int lttng_ust_futex_noasync(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+{
+ return lttng_ust_futex_async(uaddr, op, val, timeout, uaddr2, val3);
+}
+
+#elif defined(__CYGWIN__)
+
+/*
+ * The futex_noasync compat code uses a weak symbol to share state across
+ * different shared object which is not possible on Windows with the
+ * Portable Executable format. Use the async compat code for both cases.
+ */
+static inline int lttng_ust_futex_noasync(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+{
+ return lttng_ust_compat_futex_async(uaddr, op, val, timeout, uaddr2, val3);
+}
+
+static inline int lttng_ust_futex_async(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+{
+ return lttng_ust_compat_futex_async(uaddr, op, val, timeout, uaddr2, val3);
+}
+
+#else
+
+static inline int lttng_ust_futex_noasync(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+{
+ return lttng_ust_compat_futex_noasync(uaddr, op, val, timeout, uaddr2, val3);
+}
+
+static inline int lttng_ust_futex_async(int32_t *uaddr, int op, int32_t val,
+ const struct timespec *timeout, int32_t *uaddr2, int32_t val3)
+{
+ return lttng_ust_compat_futex_async(uaddr, op, val, timeout, uaddr2, val3);
+}
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _UST_COMMON_COMPAT_FUTEX_H */
#include <lttng/ust-tracer.h>
#include <lttng/ust-common.h>
#include <urcu/tls-compat.h>
-#include "common/compat/futex.h"
+#include "lib/lttng-ust/futex.h"
#include "common/ustcomm.h"
#include "common/ust-fd.h"
#include "common/logging.h"