2 * SPDX-License-Identifier: LGPL-2.1-only
4 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
11 #include <lttng/ust-endian.h>
12 #include <usterr-signal-safe.h>
14 #include "ust-events-internal.h"
15 #include "../libmsgpack/msgpack.h"
16 #include "lttng-bytecode.h"
17 #include "ust-share.h"
20 * We want this write to be atomic AND non-blocking, meaning that we
21 * want to write either everything OR nothing.
22 * According to `pipe(7)`, writes that are less than `PIPE_BUF` bytes must be
23 * atomic, so we bound the capture buffer size to the `PIPE_BUF` minus the size
24 * of the notification struct we are sending alongside the capture buffer.
26 #define CAPTURE_BUFFER_SIZE \
27 (PIPE_BUF - sizeof(struct lttng_ust_abi_event_notifier_notification) - 1)
29 struct lttng_event_notifier_notification
{
31 uint64_t event_notifier_token
;
32 uint8_t capture_buf
[CAPTURE_BUFFER_SIZE
];
33 struct lttng_msgpack_writer writer
;
38 void capture_enum(struct lttng_msgpack_writer
*writer
,
39 struct lttng_interpreter_output
*output
)
41 lttng_msgpack_begin_map(writer
, 2);
42 lttng_msgpack_write_str(writer
, "type");
43 lttng_msgpack_write_str(writer
, "enum");
45 lttng_msgpack_write_str(writer
, "value");
47 switch (output
->type
) {
48 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM
:
49 lttng_msgpack_write_signed_integer(writer
, output
->u
.s
);
51 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM
:
52 lttng_msgpack_write_signed_integer(writer
, output
->u
.u
);
58 lttng_msgpack_end_map(writer
);
62 int64_t capture_sequence_element_signed(uint8_t *ptr
,
63 struct lttng_ust_type_integer
*integer_type
)
66 unsigned int size
= integer_type
->size
;
67 bool byte_order_reversed
= integer_type
->reverse_byte_order
;
76 tmp
= *(int16_t *) ptr
;
77 if (byte_order_reversed
)
86 tmp
= *(int32_t *) ptr
;
87 if (byte_order_reversed
)
96 tmp
= *(int64_t *) ptr
;
97 if (byte_order_reversed
)
111 uint64_t capture_sequence_element_unsigned(uint8_t *ptr
,
112 struct lttng_ust_type_integer
*integer_type
)
115 unsigned int size
= integer_type
->size
;
116 bool byte_order_reversed
= integer_type
->reverse_byte_order
;
125 tmp
= *(uint16_t *) ptr
;
126 if (byte_order_reversed
)
135 tmp
= *(uint32_t *) ptr
;
136 if (byte_order_reversed
)
145 tmp
= *(uint64_t *) ptr
;
146 if (byte_order_reversed
)
160 void capture_sequence(struct lttng_msgpack_writer
*writer
,
161 struct lttng_interpreter_output
*output
)
163 struct lttng_ust_type_integer
*integer_type
;
164 struct lttng_ust_type_common
*nested_type
;
169 lttng_msgpack_begin_array(writer
, output
->u
.sequence
.nr_elem
);
171 ptr
= (uint8_t *) output
->u
.sequence
.ptr
;
172 nested_type
= output
->u
.sequence
.nested_type
;
173 switch (nested_type
->type
) {
174 case lttng_ust_type_integer
:
175 integer_type
= lttng_ust_get_type_integer(nested_type
);
177 case lttng_ust_type_enum
:
178 /* Treat enumeration as an integer. */
179 integer_type
= lttng_ust_get_type_integer(lttng_ust_get_type_enum(nested_type
)->container_type
);
182 /* Capture of array of non-integer are not supported. */
185 signedness
= integer_type
->signedness
;
186 for (i
= 0; i
< output
->u
.sequence
.nr_elem
; i
++) {
188 lttng_msgpack_write_signed_integer(writer
,
189 capture_sequence_element_signed(ptr
, integer_type
));
191 lttng_msgpack_write_unsigned_integer(writer
,
192 capture_sequence_element_unsigned(ptr
, integer_type
));
196 * We assume that alignment is smaller or equal to the size.
197 * This currently holds true but if it changes in the future,
198 * we will want to change the pointer arithmetics below to
199 * take into account that the next element might be further
202 assert(integer_type
->alignment
<= integer_type
->size
);
204 /* Size is in number of bits. */
205 ptr
+= (integer_type
->size
/ CHAR_BIT
) ;
208 lttng_msgpack_end_array(writer
);
212 void notification_init(struct lttng_event_notifier_notification
*notif
,
213 struct lttng_ust_event_notifier
*event_notifier
)
215 struct lttng_msgpack_writer
*writer
= ¬if
->writer
;
217 notif
->event_notifier_token
= event_notifier
->priv
->parent
.user_token
;
218 notif
->notification_fd
= event_notifier
->priv
->group
->notification_fd
;
219 notif
->has_captures
= false;
221 if (event_notifier
->priv
->num_captures
> 0) {
222 lttng_msgpack_writer_init(writer
, notif
->capture_buf
,
223 CAPTURE_BUFFER_SIZE
);
225 lttng_msgpack_begin_array(writer
, event_notifier
->priv
->num_captures
);
226 notif
->has_captures
= true;
231 void notification_append_capture(
232 struct lttng_event_notifier_notification
*notif
,
233 struct lttng_interpreter_output
*output
)
235 struct lttng_msgpack_writer
*writer
= ¬if
->writer
;
237 switch (output
->type
) {
238 case LTTNG_INTERPRETER_TYPE_S64
:
239 lttng_msgpack_write_signed_integer(writer
, output
->u
.s
);
241 case LTTNG_INTERPRETER_TYPE_U64
:
242 lttng_msgpack_write_unsigned_integer(writer
, output
->u
.u
);
244 case LTTNG_INTERPRETER_TYPE_DOUBLE
:
245 lttng_msgpack_write_double(writer
, output
->u
.d
);
247 case LTTNG_INTERPRETER_TYPE_STRING
:
248 lttng_msgpack_write_str(writer
, output
->u
.str
.str
);
250 case LTTNG_INTERPRETER_TYPE_SEQUENCE
:
251 capture_sequence(writer
, output
);
253 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM
:
254 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM
:
255 capture_enum(writer
, output
);
263 void notification_append_empty_capture(
264 struct lttng_event_notifier_notification
*notif
)
266 lttng_msgpack_write_nil(¬if
->writer
);
269 static void record_error(struct lttng_ust_event_notifier
*event_notifier
)
271 struct lttng_event_notifier_group
*event_notifier_group
=
272 event_notifier
->priv
->group
;
273 struct lttng_counter
*error_counter
;
274 size_t dimension_index
[1];
277 error_counter
= CMM_LOAD_SHARED(event_notifier_group
->error_counter
);
279 * load-acquire paired with store-release orders creation of the
280 * error counter and setting error_counter_len before the
281 * error_counter is used.
282 * Currently a full memory barrier is used, which could be
283 * turned into acquire-release barriers.
286 /* This group may not have an error counter attached to it. */
290 dimension_index
[0] = event_notifier
->priv
->error_counter_index
;
291 ret
= event_notifier_group
->error_counter
->ops
->counter_add(
292 error_counter
->counter
, dimension_index
, 1);
298 void notification_send(struct lttng_event_notifier_notification
*notif
,
299 struct lttng_ust_event_notifier
*event_notifier
)
304 struct lttng_ust_abi_event_notifier_notification ust_notif
= {0};
309 ust_notif
.token
= event_notifier
->priv
->parent
.user_token
;
312 * Prepare sending the notification from multiple buffers using an
313 * array of `struct iovec`. The first buffer of the vector is
314 * notification structure itself and is always present.
316 iov
[0].iov_base
= &ust_notif
;
317 iov
[0].iov_len
= sizeof(ust_notif
);
319 if (notif
->has_captures
) {
321 * If captures were requested, the second buffer of the array
322 * is the capture buffer.
324 assert(notif
->writer
.buffer
);
325 content_len
= notif
->writer
.write_pos
- notif
->writer
.buffer
;
327 assert(content_len
> 0 && content_len
<= CAPTURE_BUFFER_SIZE
);
329 iov
[1].iov_base
= notif
->capture_buf
;
330 iov
[1].iov_len
= content_len
;
338 * Update the capture buffer size so that receiver of the buffer will
339 * know how much to expect.
341 ust_notif
.capture_buf_size
= content_len
;
343 /* Send all the buffers. */
344 ret
= ust_patient_writev(notif
->notification_fd
, iov
, iovec_count
);
346 if (errno
== EAGAIN
) {
347 record_error(event_notifier
);
348 DBG("Cannot send event_notifier notification without blocking: %s",
351 DBG("Error to sending event notifier notification: %s",
358 void lttng_event_notifier_notification_send(
359 struct lttng_ust_event_notifier
*event_notifier
,
360 const char *stack_data
)
363 * This function is called from the probe, we must do dynamic
364 * allocation in this context.
366 struct lttng_event_notifier_notification notif
= {0};
368 notification_init(¬if
, event_notifier
);
370 if (caa_unlikely(!cds_list_empty(&event_notifier
->capture_bytecode_runtime_head
))) {
371 struct lttng_ust_bytecode_runtime
*capture_bc_runtime
;
374 * Iterate over all the capture bytecodes. If the interpreter
375 * functions returns successfully, append the value of the
376 * `output` parameter to the capture buffer. If the interpreter
377 * fails, append an empty capture to the buffer.
379 cds_list_for_each_entry(capture_bc_runtime
,
380 &event_notifier
->capture_bytecode_runtime_head
, node
) {
381 struct lttng_interpreter_output output
;
383 if (capture_bc_runtime
->interpreter_funcs
.capture(capture_bc_runtime
,
384 stack_data
, &output
) & LTTNG_UST_BYTECODE_INTERPRETER_RECORD_FLAG
)
385 notification_append_capture(¬if
, &output
);
387 notification_append_empty_capture(¬if
);
392 * Send the notification (including the capture buffer) to the
395 notification_send(¬if
, event_notifier
);