f0e833adeb71ea77e82f5613d42896d62e8dfafb
[lttng-modules.git] / src / lttng-event-notifier-notification.c
1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
2 *
3 * lttng-event-notifier-notification.c
4 *
5 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
6 */
7
8 #include <linux/bug.h>
9
10 #include <lttng/lttng-bytecode.h>
11 #include <lttng/events.h>
12 #include <lttng/msgpack.h>
13 #include <lttng/event-notifier-notification.h>
14
15 static
16 int capture_enum(struct lttng_msgpack_writer *writer,
17 struct lttng_interpreter_output *output) __attribute__ ((unused));
18 static
19 int capture_enum(struct lttng_msgpack_writer *writer,
20 struct lttng_interpreter_output *output)
21 {
22 int ret;
23
24 /*
25 * Enums are captured as a map containing 2 key-value pairs. Such as:
26 * - type: enum
27 * value: 177
28 */
29 ret = lttng_msgpack_begin_map(writer, 2);
30 if (ret) {
31 WARN_ON_ONCE(1);
32 goto end;
33 }
34
35 ret = lttng_msgpack_write_str(writer, "type");
36 if (ret) {
37 WARN_ON_ONCE(1);
38 goto end;
39 }
40
41 ret = lttng_msgpack_write_str(writer, "enum");
42 if (ret) {
43 WARN_ON_ONCE(1);
44 goto end;
45 }
46
47 ret = lttng_msgpack_write_str(writer, "value");
48 if (ret) {
49 WARN_ON_ONCE(1);
50 goto end;
51 }
52
53 switch (output->type) {
54 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
55 ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
56 if (ret) {
57 WARN_ON_ONCE(1);
58 goto end;
59 }
60 break;
61 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
62 ret = lttng_msgpack_write_signed_integer(writer, output->u.u);
63 if (ret) {
64 WARN_ON_ONCE(1);
65 goto end;
66 }
67 break;
68 default:
69 WARN_ON(1);
70 }
71
72 ret = lttng_msgpack_end_map(writer);
73 if (ret)
74 WARN_ON_ONCE(1);
75
76 end:
77 return ret;
78 }
79
80 static
81 int64_t capture_sequence_element_signed(uint8_t *ptr,
82 const struct lttng_integer_type *type)
83 {
84 int64_t value = 0;
85 unsigned int size = type->size;
86 bool byte_order_reversed = type->reverse_byte_order;
87
88 switch (size) {
89 case 8:
90 value = *ptr;
91 break;
92 case 16:
93 {
94 int16_t tmp;
95 tmp = *(int16_t *) ptr;
96 if (byte_order_reversed)
97 __swab16s(&tmp);
98
99 value = tmp;
100 break;
101 }
102 case 32:
103 {
104 int32_t tmp;
105 tmp = *(int32_t *) ptr;
106 if (byte_order_reversed)
107 __swab32s(&tmp);
108
109 value = tmp;
110 break;
111 }
112 case 64:
113 {
114 int64_t tmp;
115 tmp = *(int64_t *) ptr;
116 if (byte_order_reversed)
117 __swab64s(&tmp);
118
119 value = tmp;
120 break;
121 }
122 default:
123 WARN_ON(1);
124 }
125
126 return value;
127 }
128
129 static
130 uint64_t capture_sequence_element_unsigned(uint8_t *ptr,
131 const struct lttng_integer_type *type)
132 {
133 uint64_t value = 0;
134 unsigned int size = type->size;
135 bool byte_order_reversed = type->reverse_byte_order;
136
137 switch (size) {
138 case 8:
139 value = *ptr;
140 break;
141 case 16:
142 {
143 uint16_t tmp;
144 tmp = *(uint16_t *) ptr;
145 if (byte_order_reversed)
146 __swab16s(&tmp);
147
148 value = tmp;
149 break;
150 }
151 case 32:
152 {
153 uint32_t tmp;
154 tmp = *(uint32_t *) ptr;
155 if (byte_order_reversed)
156 __swab32s(&tmp);
157
158 value = tmp;
159 break;
160 }
161 case 64:
162 {
163 uint64_t tmp;
164 tmp = *(uint64_t *) ptr;
165 if (byte_order_reversed)
166 __swab64s(&tmp);
167
168 value = tmp;
169 break;
170 }
171 default:
172 WARN_ON(1);
173 }
174
175 return value;
176 }
177
178 static
179 int capture_sequence(struct lttng_msgpack_writer *writer,
180 struct lttng_interpreter_output *output) __attribute__ ((unused));
181 int capture_sequence(struct lttng_msgpack_writer *writer,
182 struct lttng_interpreter_output *output)
183 {
184 const struct lttng_integer_type *integer_type = NULL;
185 const struct lttng_type *nested_type;
186 uint8_t *ptr;
187 bool signedness;
188 int ret, i;
189
190 ret = lttng_msgpack_begin_array(writer, output->u.sequence.nr_elem);
191 if (ret) {
192 WARN_ON_ONCE(1);
193 goto end;
194 }
195
196 ptr = (uint8_t *) output->u.sequence.ptr;
197 nested_type = output->u.sequence.nested_type;
198 switch (nested_type->atype) {
199 case atype_integer:
200 integer_type = &nested_type->u.integer;
201 break;
202 case atype_enum_nestable:
203 /* Treat enumeration as an integer. */
204 integer_type = &nested_type->u.enum_nestable.container_type->u.integer;
205 break;
206 default:
207 /* Capture of array of non-integer are not supported. */
208 WARN_ON(1);
209 }
210 signedness = integer_type->signedness;
211 for (i = 0; i < output->u.sequence.nr_elem; i++) {
212 if (signedness) {
213 ret = lttng_msgpack_write_signed_integer(writer,
214 capture_sequence_element_signed(ptr, integer_type));
215 if (ret) {
216 WARN_ON_ONCE(1);
217 goto end;
218 }
219 } else {
220 ret = lttng_msgpack_write_unsigned_integer(writer,
221 capture_sequence_element_unsigned(ptr, integer_type));
222 if (ret) {
223 WARN_ON_ONCE(1);
224 goto end;
225 }
226 }
227
228 /*
229 * We assume that alignment is smaller or equal to the size.
230 * This currently holds true but if it changes in the future,
231 * we will want to change the pointer arithmetics below to
232 * take into account that the next element might be further
233 * away.
234 */
235 WARN_ON(integer_type->alignment > integer_type->size);
236
237 /* Size is in number of bits. */
238 ptr += (integer_type->size / CHAR_BIT) ;
239 }
240
241 ret = lttng_msgpack_end_array(writer);
242 if (ret)
243 WARN_ON_ONCE(1);
244 end:
245 return ret;
246 }
247
248 void lttng_event_notifier_notification_send(struct lttng_event_notifier *event_notifier)
249 {
250 struct lttng_event_notifier_group *event_notifier_group = event_notifier->group;
251 struct lib_ring_buffer_ctx ctx;
252 int ret;
253
254 if (unlikely(!READ_ONCE(event_notifier->enabled)))
255 return;
256
257 lib_ring_buffer_ctx_init(&ctx, event_notifier_group->chan, NULL,
258 sizeof(event_notifier->user_token),
259 lttng_alignof(event_notifier->user_token), -1);
260 ret = event_notifier_group->ops->event_reserve(&ctx, 0);
261 if (ret < 0) {
262 //TODO: error handling with counter maps
263 //silently drop for now.
264 WARN_ON_ONCE(1);
265 return;
266 }
267 lib_ring_buffer_align_ctx(&ctx, lttng_alignof(event_notifier->user_token));
268 event_notifier_group->ops->event_write(&ctx, &event_notifier->user_token,
269 sizeof(event_notifier->user_token));
270 event_notifier_group->ops->event_commit(&ctx);
271 irq_work_queue(&event_notifier_group->wakeup_pending);
272 }
This page took 0.035253 seconds and 3 git commands to generate.