From b2c5f61a9cb94a79c35167450666e540b3e0fffe Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 26 May 2017 17:59:54 +0200 Subject: [PATCH] Introduce LTTNG_UST_ALLOW_BLOCKING env. var. Introduce the LTTNG_UST_ALLOW_BLOCKING env. var. to control whether applications are allowed to block when a buffer is full. If set, it allows the tracer to block the application when buffers are full. The blocking is now controlled by a per-channel configuration option in the LTTng control interface for channels with the "--blocking-timeout" parameter, which is specified in usec (or -1 to block forever). This replaces the LTTNG_UST_BLOCKING_RETRY_TIMEOUT env. var., which actually never made it into a stable release (we therefore remove this env. var). Signed-off-by: Mathieu Desnoyers --- configure.ac | 4 +-- doc/man/Makefile.am | 3 +- doc/man/lttng-ust.3.txt | 28 +++++---------- include/lttng/ust-abi.h | 7 +++- include/lttng/ust-ctl.h | 1 + include/lttng/ust-events.h | 3 +- liblttng-ust-ctl/ustctl.c | 3 +- liblttng-ust/getenv.c | 2 +- liblttng-ust/lttng-ring-buffer-client.h | 5 +-- .../lttng-ring-buffer-metadata-client.h | 5 +-- liblttng-ust/lttng-ust-comm.c | 29 +++++---------- libringbuffer/frontend.h | 3 +- libringbuffer/frontend_types.h | 8 ++++- libringbuffer/rb-init.h | 2 +- libringbuffer/ring_buffer_frontend.c | 36 +++++++++++++++---- 15 files changed, 77 insertions(+), 62 deletions(-) diff --git a/configure.ac b/configure.ac index 2440cab6..e2acfa90 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,7 @@ AC_SUBST([LTTNG_UST_LIBRARY_VERSION], [0:0:0]) # This is the library version of liblttng-ust-ctl, used internally by # liblttng-ust, lttng-sessiond, and lttng-consumerd. -AC_SUBST([LTTNG_UST_CTL_LIBRARY_VERSION], [3:0:1]) +AC_SUBST([LTTNG_UST_CTL_LIBRARY_VERSION], [4:0:0]) AC_CONFIG_HEADERS([config.h include/lttng/ust-config.h]) AC_CONFIG_AUX_DIR([config]) @@ -463,8 +463,6 @@ AC_DEFUN([_AC_DEFINE_AND_SUBST], [ ]) _AC_DEFINE_AND_SUBST([LTTNG_UST_DEFAULT_CONSTRUCTOR_TIMEOUT_MS], [3000]) -# By default, do not retry on buffer full condition. -_AC_DEFINE_AND_SUBST([LTTNG_UST_DEFAULT_BLOCKING_RETRY_TIMEOUT_MS], [0]) AM_CFLAGS="-Wall" AC_SUBST(AM_CFLAGS) diff --git a/doc/man/Makefile.am b/doc/man/Makefile.am index 449377ff..3d8ee494 100644 --- a/doc/man/Makefile.am +++ b/doc/man/Makefile.am @@ -56,8 +56,7 @@ if HAVE_ASCIIDOC_XMLTO # Tools to execute: ADOC = $(ASCIIDOC) -f $(ASCIIDOC_CONF) -d manpage \ -a lttng_version="$(PACKAGE_VERSION)" \ - -a lttng_ust_register_timeout="@LTTNG_UST_DEFAULT_CONSTRUCTOR_TIMEOUT_MS@" \ - -a lttng_ust_blocking_retry_timeout="@LTTNG_UST_DEFAULT_BLOCKING_RETRY_TIMEOUT_MS@" + -a lttng_ust_register_timeout="@LTTNG_UST_DEFAULT_CONSTRUCTOR_TIMEOUT_MS@" ADOC_DOCBOOK = $(ADOC) -b docbook XTO = $(XMLTO) -m $(firstword $(XSL_SRC_FILES)) man diff --git a/doc/man/lttng-ust.3.txt b/doc/man/lttng-ust.3.txt index 21f60984..28d66f25 100644 --- a/doc/man/lttng-ust.3.txt +++ b/doc/man/lttng-ust.3.txt @@ -1292,31 +1292,19 @@ LTTng session and consumer daemons (part of the LTTng-tools project) are located in a specific directory under `$LTTNG_HOME` (or `$HOME` if `$LTTNG_HOME` is not set). -`LTTNG_UST_BLOCKING_RETRY_TIMEOUT`:: - Maximum duration (milliseconds) to retry event tracing when - there's no space left for the event record in the sub-buffer. -+ --- -`0`:: - Never block the application. - -Positive value:: - Block the application for the specified number of milliseconds. If - there's no space left after this duration, discard the event - record. - -Negative value:: - Block the application until there's space left for the event record. --- -+ -Default: {lttng_ust_blocking_retry_timeout}. +`LTTNG_UST_ALLOW_BLOCKING`:: + If set, allow application to retry event tracing when there's + no space left for the event record in the sub-buffer, therefore + effectively blocking the application until space is made available + or timeout is reached. This only has effect on channels with + `blocking-timeout` set. + This option can be useful in workloads generating very large trace data throughput, where blocking the application is an acceptable trade-off to prevent discarding event records. + -WARNING: Setting this environment variable to a non-zero value may -significantly affect application timings. +WARNING: Setting this environment variable may significantly +affect application timings. `LTTNG_UST_CLOCK_PLUGIN`:: Path to the shared object which acts as the clock override plugin. diff --git a/include/lttng/ust-abi.h b/include/lttng/ust-abi.h index f76d2a9f..4976b1bf 100644 --- a/include/lttng/ust-abi.h +++ b/include/lttng/ust-abi.h @@ -177,7 +177,12 @@ struct lttng_ust_channel_attr { unsigned int switch_timer_interval; /* usec */ unsigned int read_timer_interval; /* usec */ enum lttng_ust_output output; /* splice, mmap */ - char padding[LTTNG_UST_CHANNEL_ATTR_PADDING]; + union { + struct { + int64_t blocking_timeout; /* Blocking timeout (usec) */ + } s; + char padding[LTTNG_UST_CHANNEL_ATTR_PADDING]; + } u; } LTTNG_PACKED; #define LTTNG_UST_TRACEPOINT_ITER_PADDING 16 diff --git a/include/lttng/ust-ctl.h b/include/lttng/ust-ctl.h index f6c1dc45..f83124d1 100644 --- a/include/lttng/ust-ctl.h +++ b/include/lttng/ust-ctl.h @@ -53,6 +53,7 @@ struct ustctl_consumer_channel_attr { enum lttng_ust_output output; /* splice, mmap */ uint32_t chan_id; /* channel ID */ unsigned char uuid[LTTNG_UST_UUID_LEN]; /* Trace session unique ID */ + int64_t blocking_timeout; /* Blocking timeout (usec) */ } LTTNG_PACKED; /* diff --git a/include/lttng/ust-events.h b/include/lttng/ust-events.h index 6b7bd00e..caf7e63a 100644 --- a/include/lttng/ust-events.h +++ b/include/lttng/ust-events.h @@ -489,7 +489,8 @@ struct lttng_channel_ops { unsigned int read_timer_interval, unsigned char *uuid, uint32_t chan_id, - const int *stream_fds, int nr_stream_fds); + const int *stream_fds, int nr_stream_fds, + int64_t blocking_timeout); void (*channel_destroy)(struct lttng_channel *chan); union { void *_deprecated1; diff --git a/liblttng-ust-ctl/ustctl.c b/liblttng-ust-ctl/ustctl.c index 8e2e8f1b..8c38ffaf 100644 --- a/liblttng-ust-ctl/ustctl.c +++ b/liblttng-ust-ctl/ustctl.c @@ -1057,7 +1057,8 @@ struct ustctl_consumer_channel * attr->switch_timer_interval, attr->read_timer_interval, attr->uuid, attr->chan_id, - stream_fds, nr_stream_fds); + stream_fds, nr_stream_fds, + attr->blocking_timeout); if (!chan->chan) { goto chan_error; } diff --git a/liblttng-ust/getenv.c b/liblttng-ust/getenv.c index b4dc73a0..25740a50 100644 --- a/liblttng-ust/getenv.c +++ b/liblttng-ust/getenv.c @@ -50,7 +50,7 @@ static struct lttng_env lttng_env[] = { /* Env. var. which are not fetched in setuid/setgid executables. */ { "LTTNG_UST_CLOCK_PLUGIN", LTTNG_ENV_SECURE, NULL, }, { "LTTNG_UST_GETCPU_PLUGIN", LTTNG_ENV_SECURE, NULL, }, - { "LTTNG_UST_BLOCKING_RETRY_TIMEOUT", LTTNG_ENV_SECURE, NULL, }, + { "LTTNG_UST_ALLOW_BLOCKING", LTTNG_ENV_SECURE, NULL, }, { "HOME", LTTNG_ENV_SECURE, NULL, }, { "LTTNG_HOME", LTTNG_ENV_SECURE, NULL, }, }; diff --git a/liblttng-ust/lttng-ring-buffer-client.h b/liblttng-ust/lttng-ring-buffer-client.h index 2f67799e..0fae8878 100644 --- a/liblttng-ust/lttng-ring-buffer-client.h +++ b/liblttng-ust/lttng-ring-buffer-client.h @@ -682,7 +682,8 @@ struct lttng_channel *_channel_create(const char *name, unsigned int read_timer_interval, unsigned char *uuid, uint32_t chan_id, - const int *stream_fds, int nr_stream_fds) + const int *stream_fds, int nr_stream_fds, + int64_t blocking_timeout) { struct lttng_channel chan_priv_init; struct lttng_ust_shm_handle *handle; @@ -698,7 +699,7 @@ struct lttng_channel *_channel_create(const char *name, &chan_priv_init, buf_addr, subbuf_size, num_subbuf, switch_timer_interval, read_timer_interval, - stream_fds, nr_stream_fds); + stream_fds, nr_stream_fds, blocking_timeout); if (!handle) return NULL; lttng_chan = priv; diff --git a/liblttng-ust/lttng-ring-buffer-metadata-client.h b/liblttng-ust/lttng-ring-buffer-metadata-client.h index 64940163..45340a7b 100644 --- a/liblttng-ust/lttng-ring-buffer-metadata-client.h +++ b/liblttng-ust/lttng-ring-buffer-metadata-client.h @@ -208,7 +208,8 @@ struct lttng_channel *_channel_create(const char *name, unsigned int read_timer_interval, unsigned char *uuid, uint32_t chan_id, - const int *stream_fds, int nr_stream_fds) + const int *stream_fds, int nr_stream_fds, + int64_t blocking_timeout) { struct lttng_channel chan_priv_init; struct lttng_ust_shm_handle *handle; @@ -224,7 +225,7 @@ struct lttng_channel *_channel_create(const char *name, &chan_priv_init, buf_addr, subbuf_size, num_subbuf, switch_timer_interval, read_timer_interval, - stream_fds, nr_stream_fds); + stream_fds, nr_stream_fds, blocking_timeout); if (!handle) return NULL; lttng_chan = priv; diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c index 43728ff4..511b9cf4 100644 --- a/liblttng-ust/lttng-ust-comm.c +++ b/liblttng-ust/lttng-ust-comm.c @@ -535,26 +535,15 @@ int get_constructor_timeout(struct timespec *constructor_timeout) } static -void get_blocking_retry_timeout(void) +void get_allow_blocking(void) { - const char *str_blocking_retry_timeout = - lttng_getenv("LTTNG_UST_BLOCKING_RETRY_TIMEOUT"); - - if (str_blocking_retry_timeout) { - long timeout = strtol(str_blocking_retry_timeout, NULL, 10); - - if (timeout < 0) - timeout = -1; - if (timeout > INT_MAX) { - WARN("Saturating %s value from %ld to %d\n", - "LTTNG_UST_BLOCKING_RETRY_TIMEOUT", - timeout, INT_MAX); - timeout = INT_MAX; - } - DBG("%s environment variable value is %ld", - "LTTNG_UST_BLOCKING_RETRY_TIMEOUT", - timeout); - lttng_ust_ringbuffer_set_retry_timeout(timeout); + const char *str_allow_blocking = + lttng_getenv("LTTNG_UST_ALLOW_BLOCKING"); + + if (str_allow_blocking) { + DBG("%s environment variable is set", + "LTTNG_UST_ALLOW_BLOCKING"); + lttng_ust_ringbuffer_set_allow_blocking(); } } @@ -1698,7 +1687,7 @@ void __attribute__((constructor)) lttng_ust_init(void) timeout_mode = get_constructor_timeout(&constructor_timeout); - get_blocking_retry_timeout(); + get_allow_blocking(); ret = sem_init(&constructor_wait, 0, 0); if (ret) { diff --git a/libringbuffer/frontend.h b/libringbuffer/frontend.h index a2f74596..2a9fd09a 100644 --- a/libringbuffer/frontend.h +++ b/libringbuffer/frontend.h @@ -65,7 +65,8 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff size_t subbuf_size, size_t num_subbuf, unsigned int switch_timer_interval, unsigned int read_timer_interval, - const int *stream_fds, int nr_stream_fds); + const int *stream_fds, int nr_stream_fds, + int64_t blocking_timeout); /* * channel_destroy finalizes all channel's buffers, waits for readers to diff --git a/libringbuffer/frontend_types.h b/libringbuffer/frontend_types.h index bf4b4185..629abcbd 100644 --- a/libringbuffer/frontend_types.h +++ b/libringbuffer/frontend_types.h @@ -70,7 +70,13 @@ struct channel { size_t priv_data_offset; unsigned int nr_streams; /* Number of streams */ struct lttng_ust_shm_handle *handle; - char padding[RB_CHANNEL_PADDING]; + /* Extended options. */ + union { + struct { + int32_t blocking_timeout_ms; + } s; + char padding[RB_CHANNEL_PADDING]; + } u; /* * Associated backend contains a variable-length array. Needs to * be last member. diff --git a/libringbuffer/rb-init.h b/libringbuffer/rb-init.h index eba087fa..f36d4ecd 100644 --- a/libringbuffer/rb-init.h +++ b/libringbuffer/rb-init.h @@ -22,6 +22,6 @@ */ void lttng_fixup_ringbuffer_tls(void); -void lttng_ust_ringbuffer_set_retry_timeout(int timeout); +void lttng_ust_ringbuffer_set_allow_blocking(void); #endif /* _LTTNG_UST_LIB_RINGBUFFER_RB_INIT_H */ diff --git a/libringbuffer/ring_buffer_frontend.c b/libringbuffer/ring_buffer_frontend.c index 76d6ec74..331639f1 100644 --- a/libringbuffer/ring_buffer_frontend.c +++ b/libringbuffer/ring_buffer_frontend.c @@ -151,12 +151,19 @@ static struct timer_signal_data timer_signal = { .lock = PTHREAD_MUTEX_INITIALIZER, }; -int lttng_ust_blocking_retry_timeout = - CONFIG_LTTNG_UST_DEFAULT_BLOCKING_RETRY_TIMEOUT_MS; +static bool lttng_ust_allow_blocking; -void lttng_ust_ringbuffer_set_retry_timeout(int timeout) +void lttng_ust_ringbuffer_set_allow_blocking(void) { - lttng_ust_blocking_retry_timeout = timeout; + lttng_ust_allow_blocking = true; +} + +/* Get blocking timeout, in ms */ +static int lttng_ust_ringbuffer_get_timeout(struct channel *chan) +{ + if (!lttng_ust_allow_blocking) + return 0; + return chan->u.s.blocking_timeout_ms; } /** @@ -951,7 +958,8 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff void *buf_addr, size_t subbuf_size, size_t num_subbuf, unsigned int switch_timer_interval, unsigned int read_timer_interval, - const int *stream_fds, int nr_stream_fds) + const int *stream_fds, int nr_stream_fds, + int64_t blocking_timeout) { int ret; size_t shmsize, chansize; @@ -959,6 +967,7 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff struct lttng_ust_shm_handle *handle; struct shm_object *shmobj; unsigned int nr_streams; + int64_t blocking_timeout_ms; if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) nr_streams = num_possible_cpus(); @@ -968,6 +977,19 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff if (nr_stream_fds != nr_streams) return NULL; + if (blocking_timeout < -1) { + return NULL; + } + /* usec to msec */ + if (blocking_timeout == -1) { + blocking_timeout_ms = -1; + } else { + blocking_timeout_ms = blocking_timeout / 1000; + if (blocking_timeout_ms != (int32_t) blocking_timeout_ms) { + return NULL; + } + } + if (lib_ring_buffer_check_config(config, switch_timer_interval, read_timer_interval)) return NULL; @@ -1021,6 +1043,8 @@ struct lttng_ust_shm_handle *channel_create(const struct lttng_ust_lib_ring_buff *priv_data = NULL; } + chan->u.s.blocking_timeout_ms = (int32_t) blocking_timeout_ms; + ret = channel_backend_init(&chan->backend, name, config, subbuf_size, num_subbuf, handle, stream_fds); @@ -2066,7 +2090,7 @@ int lib_ring_buffer_try_reserve_slow(struct lttng_ust_lib_ring_buffer *buf, const struct lttng_ust_lib_ring_buffer_config *config = &chan->backend.config; struct lttng_ust_shm_handle *handle = ctx->handle; unsigned long reserve_commit_diff, offset_cmp; - int timeout_left_ms = lttng_ust_blocking_retry_timeout; + int timeout_left_ms = lttng_ust_ringbuffer_get_timeout(chan); retry: offsets->begin = offset_cmp = v_read(config, &buf->offset); -- 2.34.1