Refactoring: context structures
[lttng-ust.git] / liblttng-ust / lttng-context.c
CommitLineData
8020ceb5 1/*
c0c0989a 2 * SPDX-License-Identifier: LGPL-2.1-only
8020ceb5 3 *
e92f3e28
MD
4 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
c0c0989a 6 * LTTng UST trace/channel/event context management.
8020ceb5
MD
7 */
8
3fbec7dc 9#define _LGPL_SOURCE
4318ae1b
MD
10#include <lttng/ust-events.h>
11#include <lttng/ust-tracer.h>
ae4b659d 12#include <ust-context-provider.h>
10544ee8 13#include <lttng/urcu/pointer.h>
b653ddc1 14#include <lttng/urcu/urcu-ust.h>
a0a3bef9 15#include <usterr-signal-safe.h>
864a1eda 16#include <ust-helper.h>
b4051ad8 17#include <stddef.h>
8d8a24c8 18#include <string.h>
8173ec7c 19#include <assert.h>
10544ee8 20#include "tracepoint-internal.h"
8173ec7c 21
51f804ec
FD
22#include "context-internal.h"
23
77aa5901
MD
24/*
25 * The filter implementation requires that two consecutive "get" for the
26 * same context performed by the same thread return the same result.
27 */
28
daacdbfc 29int lttng_find_context(struct lttng_ust_ctx *ctx, const char *name)
8173ec7c
MD
30{
31 unsigned int i;
53569322 32 const char *subname;
8173ec7c 33
53569322
MD
34 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
35 subname = name + strlen("$ctx.");
36 } else {
37 subname = name;
38 }
8173ec7c
MD
39 for (i = 0; i < ctx->nr_fields; i++) {
40 /* Skip allocated (but non-initialized) contexts */
daacdbfc 41 if (!ctx->fields[i]->event_field->name)
8173ec7c 42 continue;
daacdbfc 43 if (!strcmp(ctx->fields[i]->event_field->name, subname))
8173ec7c
MD
44 return 1;
45 }
46 return 0;
47}
8020ceb5 48
daacdbfc 49int lttng_get_context_index(struct lttng_ust_ctx *ctx, const char *name)
77aa5901
MD
50{
51 unsigned int i;
53569322 52 const char *subname;
77aa5901
MD
53
54 if (!ctx)
55 return -1;
53569322
MD
56 if (strncmp(name, "$ctx.", strlen("$ctx.")) == 0) {
57 subname = name + strlen("$ctx.");
58 } else {
59 subname = name;
60 }
77aa5901
MD
61 for (i = 0; i < ctx->nr_fields; i++) {
62 /* Skip allocated (but non-initialized) contexts */
daacdbfc 63 if (!ctx->fields[i]->event_field->name)
77aa5901 64 continue;
daacdbfc 65 if (!strcmp(ctx->fields[i]->event_field->name, subname))
77aa5901
MD
66 return i;
67 }
68 return -1;
69}
70
daacdbfc 71static int lttng_find_context_provider(struct lttng_ust_ctx *ctx, const char *name)
53569322
MD
72{
73 unsigned int i;
74
75 for (i = 0; i < ctx->nr_fields; i++) {
76 /* Skip allocated (but non-initialized) contexts */
daacdbfc 77 if (!ctx->fields[i]->event_field->name)
53569322 78 continue;
daacdbfc 79 if (!strncmp(ctx->fields[i]->event_field->name, name,
53569322
MD
80 strlen(name)))
81 return 1;
82 }
83 return 0;
84}
85
a0a748b8
MD
86/*
87 * Note: as we append context information, the pointer location may change.
daacdbfc 88 * lttng_add_context leaves the new last context initialized to NULL.
a0a748b8 89 */
daacdbfc
MD
90static
91int lttng_add_context(struct lttng_ust_ctx **ctx_p)
8020ceb5 92{
daacdbfc 93 struct lttng_ust_ctx *ctx;
8020ceb5
MD
94
95 if (!*ctx_p) {
daacdbfc 96 *ctx_p = zmalloc(sizeof(struct lttng_ust_ctx));
8020ceb5 97 if (!*ctx_p)
daacdbfc
MD
98 return -ENOMEM;
99 (*ctx_p)->struct_size = sizeof(struct lttng_ust_ctx);
b2cc986a 100 (*ctx_p)->largest_align = 1;
8020ceb5
MD
101 }
102 ctx = *ctx_p;
103 if (ctx->nr_fields + 1 > ctx->allocated_fields) {
daacdbfc 104 struct lttng_ust_ctx_field **new_fields;
8020ceb5
MD
105
106 ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields);
daacdbfc 107 new_fields = zmalloc(ctx->allocated_fields * sizeof(*new_fields));
8020ceb5 108 if (!new_fields)
daacdbfc
MD
109 return -ENOMEM;
110 /* Copy pointers */
8020ceb5
MD
111 if (ctx->fields)
112 memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields);
8d8a24c8 113 free(ctx->fields);
8020ceb5
MD
114 ctx->fields = new_fields;
115 }
8020ceb5 116 ctx->nr_fields++;
daacdbfc
MD
117 return 0;
118}
119
120struct lttng_ust_ctx_field *lttng_append_context(struct lttng_ust_ctx **ctx_p)
121{
122 struct lttng_ust_ctx_field *field;
123 int ret;
124
125 field = zmalloc(sizeof(struct lttng_ust_ctx_field));
126 if (!field)
127 goto error_alloc_field;
128 field->struct_size = sizeof(struct lttng_ust_ctx_field);
129 field->event_field = zmalloc(sizeof(struct lttng_ust_event_field));
130 if (!field->event_field)
131 goto error_alloc_event_field;
132 field->event_field->struct_size = sizeof(struct lttng_ust_event_field);
133
134 ret = lttng_add_context(ctx_p);
135 if (ret)
136 goto error_add_context;
137 (*ctx_p)->fields[(*ctx_p)->nr_fields - 1] = field;
8020ceb5 138 return field;
daacdbfc
MD
139
140error_add_context:
141 free(field->event_field);
142error_alloc_event_field:
143 free(field);
144error_alloc_field:
145 return NULL;
8020ceb5 146}
8020ceb5 147
daacdbfc
MD
148/*
149 * Takes ownership of @f on success.
150 */
151int lttng_context_add_rcu(struct lttng_ust_ctx **ctx_p,
152 struct lttng_ust_ctx_field *f)
53569322 153{
daacdbfc
MD
154 struct lttng_ust_ctx *old_ctx = *ctx_p, *new_ctx = NULL;
155 struct lttng_ust_ctx_field **new_fields = NULL;
156 int ret;
53569322
MD
157
158 if (old_ctx) {
daacdbfc 159 new_ctx = zmalloc(sizeof(struct lttng_ust_ctx));
53569322
MD
160 if (!new_ctx)
161 return -ENOMEM;
daacdbfc 162 new_ctx->struct_size = sizeof(struct lttng_ust_ctx);
53569322 163 *new_ctx = *old_ctx;
daacdbfc 164 new_fields = zmalloc(new_ctx->allocated_fields * sizeof(*new_fields));
53569322
MD
165 if (!new_fields) {
166 free(new_ctx);
167 return -ENOMEM;
168 }
daacdbfc 169 /* Copy pointers */
53569322
MD
170 memcpy(new_fields, old_ctx->fields,
171 sizeof(*old_ctx->fields) * old_ctx->nr_fields);
172 new_ctx->fields = new_fields;
173 }
daacdbfc
MD
174 ret = lttng_add_context(&new_ctx);
175 if (ret) {
53569322
MD
176 free(new_fields);
177 free(new_ctx);
daacdbfc 178 return ret;
53569322 179 }
daacdbfc
MD
180 /* Taking ownership of f. */
181 (*ctx_p)->fields[(*ctx_p)->nr_fields - 1] = f;
53569322 182 lttng_context_update(new_ctx);
10544ee8 183 lttng_ust_rcu_assign_pointer(*ctx_p, new_ctx);
b653ddc1 184 lttng_ust_urcu_synchronize_rcu();
53569322
MD
185 if (old_ctx) {
186 free(old_ctx->fields);
187 free(old_ctx);
188 }
189 return 0;
190}
191
b2cc986a
MD
192/*
193 * lttng_context_update() should be called at least once between context
194 * modification and trace start.
195 */
daacdbfc 196void lttng_context_update(struct lttng_ust_ctx *ctx)
b2cc986a
MD
197{
198 int i;
199 size_t largest_align = 8; /* in bits */
200
201 for (i = 0; i < ctx->nr_fields; i++) {
202 struct lttng_type *type;
203 size_t field_align = 8;
204
daacdbfc 205 type = &ctx->fields[i]->event_field->type;
b2cc986a
MD
206 switch (type->atype) {
207 case atype_integer:
218deb69 208 field_align = type->u.integer.alignment;
b2cc986a 209 break;
218deb69
MD
210 case atype_array_nestable:
211 {
212 const struct lttng_type *nested_type;
213
214 nested_type = type->u.array_nestable.elem_type;
215 switch (nested_type->atype) {
216 case atype_integer:
217 field_align = nested_type->u.integer.alignment;
218 break;
219 case atype_string:
220 break;
221
218deb69 222 case atype_array_nestable:
218deb69
MD
223 case atype_sequence_nestable:
224 default:
225 WARN_ON_ONCE(1);
226 break;
227 }
228 field_align = max_t(size_t, field_align,
229 type->u.array_nestable.alignment);
230 break;
231 }
218deb69
MD
232 case atype_sequence_nestable:
233 {
234 const struct lttng_type *nested_type;
235
236 nested_type = type->u.sequence_nestable.elem_type;
237 switch (nested_type->atype) {
238 case atype_integer:
239 field_align = nested_type->u.integer.alignment;
240 break;
241
242 case atype_string:
243 break;
244
218deb69 245 case atype_array_nestable:
218deb69 246 case atype_sequence_nestable:
b2cc986a
MD
247 default:
248 WARN_ON_ONCE(1);
249 break;
250 }
218deb69
MD
251 field_align = max_t(size_t, field_align,
252 type->u.sequence_nestable.alignment);
b2cc986a
MD
253 break;
254 }
255 case atype_string:
256 break;
53569322
MD
257 case atype_dynamic:
258 break;
218deb69 259 case atype_enum_nestable:
b2cc986a
MD
260 default:
261 WARN_ON_ONCE(1);
262 break;
263 }
264 largest_align = max_t(size_t, largest_align, field_align);
265 }
266 ctx->largest_align = largest_align >> 3; /* bits to bytes */
267}
268
b13d13b1
MD
269/*
270 * Remove last context field.
271 */
daacdbfc
MD
272void lttng_remove_context_field(struct lttng_ust_ctx **ctx_p,
273 struct lttng_ust_ctx_field *field)
8020ceb5 274{
daacdbfc 275 struct lttng_ust_ctx *ctx;
8020ceb5
MD
276
277 ctx = *ctx_p;
278 ctx->nr_fields--;
daacdbfc 279 assert(ctx->fields[ctx->nr_fields] == field);
53569322 280 assert(field->field_name == NULL);
daacdbfc 281 ctx->fields[ctx->nr_fields] = NULL;
8020ceb5 282}
8020ceb5 283
daacdbfc 284void lttng_destroy_context(struct lttng_ust_ctx *ctx)
8020ceb5
MD
285{
286 int i;
287
288 if (!ctx)
289 return;
290 for (i = 0; i < ctx->nr_fields; i++) {
daacdbfc
MD
291 if (ctx->fields[i]->destroy)
292 ctx->fields[i]->destroy(ctx->fields[i]);
293 free(ctx->fields[i]->field_name);
294 free(ctx->fields[i]->event_field);
295 free(ctx->fields[i]);
8020ceb5 296 }
8d8a24c8
MD
297 free(ctx->fields);
298 free(ctx);
8020ceb5 299}
a0a3bef9 300
53569322
MD
301/*
302 * Can be safely performed concurrently with tracing using the struct
303 * lttng_ctx. Using RCU update. Needs to match RCU read-side handling of
304 * contexts.
305 *
306 * This does not allow adding, removing, or changing typing of the
307 * contexts, since this needs to stay invariant for metadata. However,
308 * it allows updating the handlers associated with all contexts matching
309 * a provider (by name) while tracing is using it, in a way that ensures
310 * a single RCU read-side critical section see either all old, or all
311 * new handlers.
312 */
daacdbfc 313int lttng_ust_context_set_provider_rcu(struct lttng_ust_ctx **_ctx,
53569322 314 const char *name,
daacdbfc
MD
315 size_t (*get_size)(struct lttng_ust_ctx_field *field, size_t offset),
316 void (*record)(struct lttng_ust_ctx_field *field,
53569322
MD
317 struct lttng_ust_lib_ring_buffer_ctx *ctx,
318 struct lttng_channel *chan),
daacdbfc
MD
319 void (*get_value)(struct lttng_ust_ctx_field *field,
320 struct lttng_ust_ctx_value *value))
53569322
MD
321{
322 int i, ret;
daacdbfc
MD
323 struct lttng_ust_ctx *ctx = *_ctx, *new_ctx;
324 struct lttng_ust_ctx_field **new_fields;
53569322
MD
325
326 if (!ctx || !lttng_find_context_provider(ctx, name))
327 return 0;
328 /*
329 * We have at least one instance of context for the provider.
330 */
331 new_ctx = zmalloc(sizeof(*new_ctx));
332 if (!new_ctx)
333 return -ENOMEM;
daacdbfc 334 new_ctx->struct_size = sizeof(*new_ctx);
53569322
MD
335 *new_ctx = *ctx;
336 new_fields = zmalloc(sizeof(*new_fields) * ctx->allocated_fields);
337 if (!new_fields) {
338 ret = -ENOMEM;
339 goto field_error;
340 }
daacdbfc 341 /* Copy pointers */
53569322
MD
342 memcpy(new_fields, ctx->fields,
343 sizeof(*new_fields) * ctx->allocated_fields);
344 for (i = 0; i < ctx->nr_fields; i++) {
daacdbfc 345 if (strncmp(new_fields[i]->event_field->name,
53569322
MD
346 name, strlen(name)) != 0)
347 continue;
daacdbfc
MD
348 new_fields[i]->get_size = get_size;
349 new_fields[i]->record = record;
350 new_fields[i]->get_value = get_value;
53569322
MD
351 }
352 new_ctx->fields = new_fields;
10544ee8 353 lttng_ust_rcu_assign_pointer(*_ctx, new_ctx);
b653ddc1 354 lttng_ust_urcu_synchronize_rcu();
53569322
MD
355 free(ctx->fields);
356 free(ctx);
357 return 0;
358
359field_error:
360 free(new_ctx);
361 return ret;
362}
363
daacdbfc 364int lttng_context_init_all(struct lttng_ust_ctx **ctx)
a0a3bef9
MD
365{
366 int ret;
367
53569322 368 ret = lttng_add_pthread_id_to_ctx(ctx);
a0a3bef9
MD
369 if (ret) {
370 WARN("Cannot add context lttng_add_pthread_id_to_ctx");
53569322 371 goto error;
a0a3bef9 372 }
53569322 373 ret = lttng_add_vtid_to_ctx(ctx);
a0a3bef9
MD
374 if (ret) {
375 WARN("Cannot add context lttng_add_vtid_to_ctx");
53569322 376 goto error;
a0a3bef9 377 }
53569322 378 ret = lttng_add_vpid_to_ctx(ctx);
a0a3bef9
MD
379 if (ret) {
380 WARN("Cannot add context lttng_add_vpid_to_ctx");
53569322 381 goto error;
a0a3bef9 382 }
53569322 383 ret = lttng_add_procname_to_ctx(ctx);
a0a3bef9
MD
384 if (ret) {
385 WARN("Cannot add context lttng_add_procname_to_ctx");
53569322 386 goto error;
a0a3bef9 387 }
53569322 388 ret = lttng_add_cpu_id_to_ctx(ctx);
c7ea8487
MD
389 if (ret) {
390 WARN("Cannot add context lttng_add_cpu_id_to_ctx");
53569322 391 goto error;
c7ea8487 392 }
735bef47
MJ
393 ret = lttng_add_cgroup_ns_to_ctx(ctx);
394 if (ret) {
395 WARN("Cannot add context lttng_add_cgroup_ns_to_ctx");
396 goto error;
397 }
398 ret = lttng_add_ipc_ns_to_ctx(ctx);
399 if (ret) {
400 WARN("Cannot add context lttng_add_ipc_ns_to_ctx");
401 goto error;
402 }
403 ret = lttng_add_mnt_ns_to_ctx(ctx);
404 if (ret) {
405 WARN("Cannot add context lttng_add_mnt_ns_to_ctx");
406 goto error;
407 }
408 ret = lttng_add_net_ns_to_ctx(ctx);
409 if (ret) {
410 WARN("Cannot add context lttng_add_net_ns_to_ctx");
411 goto error;
412 }
413 ret = lttng_add_pid_ns_to_ctx(ctx);
414 if (ret) {
415 WARN("Cannot add context lttng_add_pid_ns_to_ctx");
416 goto error;
417 }
cefef7a7
MJ
418 ret = lttng_add_time_ns_to_ctx(ctx);
419 if (ret) {
420 WARN("Cannot add context lttng_add_time_ns_to_ctx");
421 goto error;
422 }
735bef47
MJ
423 ret = lttng_add_user_ns_to_ctx(ctx);
424 if (ret) {
425 WARN("Cannot add context lttng_add_user_ns_to_ctx");
426 goto error;
427 }
428 ret = lttng_add_uts_ns_to_ctx(ctx);
429 if (ret) {
430 WARN("Cannot add context lttng_add_uts_ns_to_ctx");
431 goto error;
432 }
fca2f191
MJ
433 ret = lttng_add_vuid_to_ctx(ctx);
434 if (ret) {
435 WARN("Cannot add context lttng_add_vuid_to_ctx");
436 goto error;
437 }
438 ret = lttng_add_veuid_to_ctx(ctx);
439 if (ret) {
440 WARN("Cannot add context lttng_add_veuid_to_ctx");
441 goto error;
442 }
443 ret = lttng_add_vsuid_to_ctx(ctx);
444 if (ret) {
445 WARN("Cannot add context lttng_add_vsuid_to_ctx");
446 goto error;
447 }
448 ret = lttng_add_vgid_to_ctx(ctx);
449 if (ret) {
450 WARN("Cannot add context lttng_add_vgid_to_ctx");
451 goto error;
452 }
453 ret = lttng_add_vegid_to_ctx(ctx);
454 if (ret) {
455 WARN("Cannot add context lttng_add_vegid_to_ctx");
456 goto error;
457 }
458 ret = lttng_add_vsgid_to_ctx(ctx);
459 if (ret) {
460 WARN("Cannot add context lttng_add_vsgid_to_ctx");
461 goto error;
462 }
53569322
MD
463 lttng_context_update(*ctx);
464 return 0;
a0a3bef9 465
53569322
MD
466error:
467 lttng_destroy_context(*ctx);
468 return ret;
a0a3bef9 469}
This page took 0.055089 seconds and 4 git commands to generate.