2 * event-notifier-notification.c
4 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; only
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <lttng/ust-events.h>
26 #include <lttng/ust-endian.h>
27 #include <usterr-signal-safe.h>
29 #include "../libmsgpack/msgpack.h"
30 #include "lttng-bytecode.h"
34 * We want this write to be atomic AND non-blocking, meaning that we
35 * want to write either everything OR nothing.
36 * According to `pipe(7)`, writes that are less than `PIPE_BUF` bytes must be
37 * atomic, so we bound the capture buffer size to the `PIPE_BUF` minus the size
38 * of the notification struct we are sending alongside the capture buffer.
40 #define CAPTURE_BUFFER_SIZE \
41 (PIPE_BUF - sizeof(struct lttng_ust_event_notifier_notification) - 1)
43 struct lttng_event_notifier_notification
{
45 uint64_t event_notifier_token
;
46 uint8_t capture_buf
[CAPTURE_BUFFER_SIZE
];
47 struct lttng_msgpack_writer writer
;
52 void capture_enum(struct lttng_msgpack_writer
*writer
,
53 struct lttng_interpreter_output
*output
)
55 lttng_msgpack_begin_map(writer
, 2);
56 lttng_msgpack_write_str(writer
, "type");
57 lttng_msgpack_write_str(writer
, "enum");
59 lttng_msgpack_write_str(writer
, "value");
61 switch (output
->type
) {
62 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM
:
63 lttng_msgpack_write_signed_integer(writer
, output
->u
.s
);
65 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM
:
66 lttng_msgpack_write_signed_integer(writer
, output
->u
.u
);
72 lttng_msgpack_end_map(writer
);
76 int64_t capture_sequence_element_signed(uint8_t *ptr
,
77 const struct lttng_integer_type
*type
)
80 unsigned int size
= type
->size
;
81 bool byte_order_reversed
= type
->reverse_byte_order
;
90 tmp
= *(int16_t *) ptr
;
91 if (byte_order_reversed
)
100 tmp
= *(int32_t *) ptr
;
101 if (byte_order_reversed
)
110 tmp
= *(int64_t *) ptr
;
111 if (byte_order_reversed
)
125 uint64_t capture_sequence_element_unsigned(uint8_t *ptr
,
126 const struct lttng_integer_type
*type
)
129 unsigned int size
= type
->size
;
130 bool byte_order_reversed
= type
->reverse_byte_order
;
139 tmp
= *(uint16_t *) ptr
;
140 if (byte_order_reversed
)
149 tmp
= *(uint32_t *) ptr
;
150 if (byte_order_reversed
)
159 tmp
= *(uint64_t *) ptr
;
160 if (byte_order_reversed
)
174 void capture_sequence(struct lttng_msgpack_writer
*writer
,
175 struct lttng_interpreter_output
*output
)
177 const struct lttng_integer_type
*integer_type
;
178 const struct lttng_type
*nested_type
;
183 lttng_msgpack_begin_array(writer
, output
->u
.sequence
.nr_elem
);
185 ptr
= (uint8_t *) output
->u
.sequence
.ptr
;
186 nested_type
= output
->u
.sequence
.nested_type
;
187 switch (nested_type
->atype
) {
189 integer_type
= &nested_type
->u
.integer
;
192 /* Treat enumeration as an integer. */
193 integer_type
= &nested_type
->u
.enum_nestable
.container_type
->u
.integer
;
196 /* Capture of array of non-integer are not supported. */
199 signedness
= integer_type
->signedness
;
200 for (i
= 0; i
< output
->u
.sequence
.nr_elem
; i
++) {
202 lttng_msgpack_write_signed_integer(writer
,
203 capture_sequence_element_signed(ptr
, integer_type
));
205 lttng_msgpack_write_unsigned_integer(writer
,
206 capture_sequence_element_unsigned(ptr
, integer_type
));
210 * We assume that alignment is smaller or equal to the size.
211 * This currently holds true but if it changes in the future,
212 * we will want to change the pointer arithmetics below to
213 * take into account that the next element might be further
216 assert(integer_type
->alignment
<= integer_type
->size
);
218 /* Size is in number of bits. */
219 ptr
+= (integer_type
->size
/ CHAR_BIT
) ;
222 lttng_msgpack_end_array(writer
);
226 void notification_init(struct lttng_event_notifier_notification
*notif
,
227 struct lttng_event_notifier
*event_notifier
)
229 struct lttng_msgpack_writer
*writer
= ¬if
->writer
;
231 notif
->event_notifier_token
= event_notifier
->user_token
;
232 notif
->notification_fd
= event_notifier
->group
->notification_fd
;
233 notif
->has_captures
= false;
235 if (event_notifier
->num_captures
> 0) {
236 lttng_msgpack_writer_init(writer
, notif
->capture_buf
,
237 CAPTURE_BUFFER_SIZE
);
239 lttng_msgpack_begin_array(writer
, event_notifier
->num_captures
);
240 notif
->has_captures
= true;
245 void notification_append_capture(
246 struct lttng_event_notifier_notification
*notif
,
247 struct lttng_interpreter_output
*output
)
249 struct lttng_msgpack_writer
*writer
= ¬if
->writer
;
251 switch (output
->type
) {
252 case LTTNG_INTERPRETER_TYPE_S64
:
253 lttng_msgpack_write_signed_integer(writer
, output
->u
.s
);
255 case LTTNG_INTERPRETER_TYPE_U64
:
256 lttng_msgpack_write_unsigned_integer(writer
, output
->u
.u
);
258 case LTTNG_INTERPRETER_TYPE_DOUBLE
:
259 lttng_msgpack_write_double(writer
, output
->u
.d
);
261 case LTTNG_INTERPRETER_TYPE_STRING
:
262 lttng_msgpack_write_str(writer
, output
->u
.str
.str
);
264 case LTTNG_INTERPRETER_TYPE_SEQUENCE
:
265 capture_sequence(writer
, output
);
267 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM
:
268 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM
:
269 capture_enum(writer
, output
);
277 void notification_append_empty_capture(
278 struct lttng_event_notifier_notification
*notif
)
280 lttng_msgpack_write_nil(¬if
->writer
);
283 static void record_error(struct lttng_event_notifier
*event_notifier
)
285 struct lttng_event_notifier_group
*event_notifier_group
=
286 event_notifier
->group
;
287 struct lttng_counter
*error_counter
;
288 size_t dimension_index
[1];
291 error_counter
= CMM_LOAD_SHARED(event_notifier_group
->error_counter
);
293 * load-acquire paired with store-release orders creation of the
294 * error counter and setting error_counter_len before the
295 * error_counter is used.
296 * Currently a full memory barrier is used, which could be
297 * turned into acquire-release barriers.
300 /* This group may not have an error counter attached to it. */
304 dimension_index
[0] = event_notifier
->error_counter_index
;
305 ret
= event_notifier_group
->error_counter
->ops
->counter_add(
306 error_counter
->counter
, dimension_index
, 1);
312 void notification_send(struct lttng_event_notifier_notification
*notif
,
313 struct lttng_event_notifier
*event_notifier
)
318 struct lttng_ust_event_notifier_notification ust_notif
= {0};
323 ust_notif
.token
= event_notifier
->user_token
;
326 * Prepare sending the notification from multiple buffers using an
327 * array of `struct iovec`. The first buffer of the vector is
328 * notification structure itself and is always present.
330 iov
[0].iov_base
= &ust_notif
;
331 iov
[0].iov_len
= sizeof(ust_notif
);
333 if (notif
->has_captures
) {
335 * If captures were requested, the second buffer of the array
336 * is the capture buffer.
338 assert(notif
->writer
.buffer
);
339 content_len
= notif
->writer
.write_pos
- notif
->writer
.buffer
;
341 assert(content_len
> 0 && content_len
<= CAPTURE_BUFFER_SIZE
);
343 iov
[1].iov_base
= notif
->capture_buf
;
344 iov
[1].iov_len
= content_len
;
352 * Update the capture buffer size so that receiver of the buffer will
353 * know how much to expect.
355 ust_notif
.capture_buf_size
= content_len
;
357 /* Send all the buffers. */
358 ret
= patient_writev(notif
->notification_fd
, iov
, iovec_count
);
360 if (errno
== EAGAIN
) {
361 record_error(event_notifier
);
362 DBG("Cannot send event_notifier notification without blocking: %s",
365 DBG("Error to sending event notifier notification: %s",
372 void lttng_event_notifier_notification_send(
373 struct lttng_event_notifier
*event_notifier
,
374 const char *stack_data
)
377 * This function is called from the probe, we must do dynamic
378 * allocation in this context.
380 struct lttng_event_notifier_notification notif
= {0};
382 notification_init(¬if
, event_notifier
);
384 if (caa_unlikely(!cds_list_empty(&event_notifier
->capture_bytecode_runtime_head
))) {
385 struct lttng_bytecode_runtime
*capture_bc_runtime
;
388 * Iterate over all the capture bytecodes. If the interpreter
389 * functions returns successfully, append the value of the
390 * `output` parameter to the capture buffer. If the interpreter
391 * fails, append an empty capture to the buffer.
393 cds_list_for_each_entry(capture_bc_runtime
,
394 &event_notifier
->capture_bytecode_runtime_head
, node
) {
395 struct lttng_interpreter_output output
;
397 if (capture_bc_runtime
->interpreter_funcs
.capture(capture_bc_runtime
,
398 stack_data
, &output
) & LTTNG_INTERPRETER_RECORD_FLAG
)
399 notification_append_capture(¬if
, &output
);
401 notification_append_empty_capture(¬if
);
406 * Send the notification (including the capture buffer) to the
409 notification_send(¬if
, event_notifier
);