Implement enum and sequence capture serialization functions
[lttng-ust.git] / liblttng-ust / event-notifier-notification.c
1 /*
2 * event-notifier-notification.c
3 *
4 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define _LGPL_SOURCE
22
23 #include <assert.h>
24 #include <byteswap.h>
25 #include <errno.h>
26 #include <lttng/ust-events.h>
27 #include <usterr-signal-safe.h>
28
29 #include "../libmsgpack/msgpack.h"
30 #include "lttng-bytecode.h"
31 #include "share.h"
32
33 static
34 void capture_enum(struct lttng_msgpack_writer *writer,
35 struct lttng_interpreter_output *output) __attribute__ ((unused));
36 static
37 void capture_enum(struct lttng_msgpack_writer *writer,
38 struct lttng_interpreter_output *output)
39 {
40 lttng_msgpack_begin_map(writer, 2);
41 lttng_msgpack_write_str(writer, "type");
42 lttng_msgpack_write_str(writer, "enum");
43
44 lttng_msgpack_write_str(writer, "value");
45
46 switch (output->type) {
47 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
48 lttng_msgpack_write_signed_integer(writer, output->u.s);
49 break;
50 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
51 lttng_msgpack_write_signed_integer(writer, output->u.u);
52 break;
53 default:
54 abort();
55 }
56
57 lttng_msgpack_end_map(writer);
58 }
59
60 static
61 int64_t capture_sequence_element_signed(uint8_t *ptr,
62 const struct lttng_integer_type *type)
63 {
64 int64_t value;
65 unsigned int size = type->size;
66 bool byte_order_reversed = type->reverse_byte_order;
67
68 switch (size) {
69 case 8:
70 value = *ptr;
71 break;
72 case 16:
73 {
74 int16_t tmp;
75 tmp = *(int16_t *) ptr;
76 if (byte_order_reversed)
77 tmp = bswap_16(tmp);
78
79 value = tmp;
80 break;
81 }
82 case 32:
83 {
84 int32_t tmp;
85 tmp = *(int32_t *) ptr;
86 if (byte_order_reversed)
87 tmp = bswap_32(tmp);
88
89 value = tmp;
90 break;
91 }
92 case 64:
93 {
94 int64_t tmp;
95 tmp = *(int64_t *) ptr;
96 if (byte_order_reversed)
97 tmp = bswap_64(tmp);
98
99 value = tmp;
100 break;
101 }
102 default:
103 abort();
104 }
105
106 return value;
107 }
108
109 static
110 uint64_t capture_sequence_element_unsigned(uint8_t *ptr,
111 const struct lttng_integer_type *type)
112 {
113 uint64_t value;
114 unsigned int size = type->size;
115 bool byte_order_reversed = type->reverse_byte_order;
116
117 switch (size) {
118 case 8:
119 value = *ptr;
120 break;
121 case 16:
122 {
123 uint16_t tmp;
124 tmp = *(uint16_t *) ptr;
125 if (byte_order_reversed)
126 tmp = bswap_16(tmp);
127
128 value = tmp;
129 break;
130 }
131 case 32:
132 {
133 uint32_t tmp;
134 tmp = *(uint32_t *) ptr;
135 if (byte_order_reversed)
136 tmp = bswap_32(tmp);
137
138 value = tmp;
139 break;
140 }
141 case 64:
142 {
143 uint64_t tmp;
144 tmp = *(uint64_t *) ptr;
145 if (byte_order_reversed)
146 tmp = bswap_64(tmp);
147
148 value = tmp;
149 break;
150 }
151 default:
152 abort();
153 }
154
155 return value;
156 }
157
158 static
159 void capture_sequence(struct lttng_msgpack_writer *writer,
160 struct lttng_interpreter_output *output) __attribute__ ((unused));
161 static
162 void capture_sequence(struct lttng_msgpack_writer *writer,
163 struct lttng_interpreter_output *output)
164 {
165 const struct lttng_integer_type *integer_type;
166 const struct lttng_type *nested_type;
167 uint8_t *ptr;
168 bool signedness;
169 int i;
170
171 lttng_msgpack_begin_array(writer, output->u.sequence.nr_elem);
172
173 ptr = (uint8_t *) output->u.sequence.ptr;
174 nested_type = output->u.sequence.nested_type;
175 switch (nested_type->atype) {
176 case atype_integer:
177 integer_type = &nested_type->u.integer;
178 break;
179 case atype_enum:
180 /* Treat enumeration as an integer. */
181 integer_type = &nested_type->u.enum_nestable.container_type->u.integer;
182 break;
183 default:
184 /* Capture of array of non-integer are not supported. */
185 abort();
186 }
187 signedness = integer_type->signedness;
188 for (i = 0; i < output->u.sequence.nr_elem; i++) {
189 if (signedness) {
190 lttng_msgpack_write_signed_integer(writer,
191 capture_sequence_element_signed(ptr, integer_type));
192 } else {
193 lttng_msgpack_write_unsigned_integer(writer,
194 capture_sequence_element_unsigned(ptr, integer_type));
195 }
196
197 /*
198 * We assume that alignment is smaller or equal to the size.
199 * This currently holds true but if it changes in the future,
200 * we will want to change the pointer arithmetics below to
201 * take into account that the next element might be further
202 * away.
203 */
204 assert(integer_type->alignment <= integer_type->size);
205
206 /* Size is in number of bits. */
207 ptr += (integer_type->size / CHAR_BIT) ;
208 }
209
210 lttng_msgpack_end_array(writer);
211 }
212
213 void lttng_event_notifier_notification_send(
214 struct lttng_event_notifier *event_notifier)
215 {
216 /*
217 * We want this write to be atomic AND non-blocking, meaning that we
218 * want to write either everything OR nothing.
219 * According to `pipe(7)`, writes that are smaller that the `PIPE_BUF`
220 * value must be atomic, so we assert that the message we send is less
221 * than PIPE_BUF.
222 */
223 struct lttng_ust_event_notifier_notification notif;
224 ssize_t ret;
225
226 assert(event_notifier);
227 assert(event_notifier->group);
228 assert(sizeof(notif) <= PIPE_BUF);
229
230 notif.token = event_notifier->user_token;
231
232 ret = patient_write(event_notifier->group->notification_fd, &notif,
233 sizeof(notif));
234 if (ret == -1) {
235 if (errno == EAGAIN) {
236 DBG("Cannot send event notifier notification without blocking: %s",
237 strerror(errno));
238 } else {
239 DBG("Error to sending event notifier notification: %s",
240 strerror(errno));
241 abort();
242 }
243 }
244 }
This page took 0.033269 seconds and 4 git commands to generate.