2 * SPDX-License-Identifier: LGPL-2.1-only
4 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * LTTng UST trace/channel/event context management.
10 #include <lttng/ust-events.h>
11 #include <lttng/ust-tracer.h>
12 #include <ust-context-provider.h>
13 #include <lttng/urcu/pointer.h>
14 #include <lttng/urcu/urcu-ust.h>
15 #include <usterr-signal-safe.h>
16 #include <ust-helper.h>
20 #include "tracepoint-internal.h"
22 #include "context-internal.h"
25 * The filter implementation requires that two consecutive "get" for the
26 * same context performed by the same thread return the same result.
29 int lttng_find_context(struct lttng_ust_ctx
*ctx
, const char *name
)
34 if (strncmp(name
, "$ctx.", strlen("$ctx.")) == 0) {
35 subname
= name
+ strlen("$ctx.");
39 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
40 /* Skip allocated (but non-initialized) contexts */
41 if (!ctx
->fields
[i
]->event_field
->name
)
43 if (!strcmp(ctx
->fields
[i
]->event_field
->name
, subname
))
49 int lttng_get_context_index(struct lttng_ust_ctx
*ctx
, const char *name
)
56 if (strncmp(name
, "$ctx.", strlen("$ctx.")) == 0) {
57 subname
= name
+ strlen("$ctx.");
61 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
62 /* Skip allocated (but non-initialized) contexts */
63 if (!ctx
->fields
[i
]->event_field
->name
)
65 if (!strcmp(ctx
->fields
[i
]->event_field
->name
, subname
))
71 static int lttng_find_context_provider(struct lttng_ust_ctx
*ctx
, const char *name
)
75 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
76 /* Skip allocated (but non-initialized) contexts */
77 if (!ctx
->fields
[i
]->event_field
->name
)
79 if (!strncmp(ctx
->fields
[i
]->event_field
->name
, name
,
87 * Note: as we append context information, the pointer location may change.
88 * lttng_add_context leaves the new last context initialized to NULL.
91 int lttng_add_context(struct lttng_ust_ctx
**ctx_p
)
93 struct lttng_ust_ctx
*ctx
;
96 *ctx_p
= zmalloc(sizeof(struct lttng_ust_ctx
));
99 (*ctx_p
)->struct_size
= sizeof(struct lttng_ust_ctx
);
100 (*ctx_p
)->largest_align
= 1;
103 if (ctx
->nr_fields
+ 1 > ctx
->allocated_fields
) {
104 struct lttng_ust_ctx_field
**new_fields
;
106 ctx
->allocated_fields
= max_t(size_t, 1, 2 * ctx
->allocated_fields
);
107 new_fields
= zmalloc(ctx
->allocated_fields
* sizeof(*new_fields
));
112 memcpy(new_fields
, ctx
->fields
, sizeof(*ctx
->fields
) * ctx
->nr_fields
);
114 ctx
->fields
= new_fields
;
120 struct lttng_ust_ctx_field
*lttng_append_context(struct lttng_ust_ctx
**ctx_p
)
122 struct lttng_ust_ctx_field
*field
;
125 field
= zmalloc(sizeof(struct lttng_ust_ctx_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
);
134 ret
= lttng_add_context(ctx_p
);
136 goto error_add_context
;
137 (*ctx_p
)->fields
[(*ctx_p
)->nr_fields
- 1] = field
;
141 free(field
->event_field
);
142 error_alloc_event_field
:
149 * Takes ownership of @f on success.
151 int lttng_context_add_rcu(struct lttng_ust_ctx
**ctx_p
,
152 struct lttng_ust_ctx_field
*f
)
154 struct lttng_ust_ctx
*old_ctx
= *ctx_p
, *new_ctx
= NULL
;
155 struct lttng_ust_ctx_field
**new_fields
= NULL
;
159 new_ctx
= zmalloc(sizeof(struct lttng_ust_ctx
));
162 new_ctx
->struct_size
= sizeof(struct lttng_ust_ctx
);
164 new_fields
= zmalloc(new_ctx
->allocated_fields
* sizeof(*new_fields
));
170 memcpy(new_fields
, old_ctx
->fields
,
171 sizeof(*old_ctx
->fields
) * old_ctx
->nr_fields
);
172 new_ctx
->fields
= new_fields
;
174 ret
= lttng_add_context(&new_ctx
);
180 /* Taking ownership of f. */
181 (*ctx_p
)->fields
[(*ctx_p
)->nr_fields
- 1] = f
;
182 lttng_context_update(new_ctx
);
183 lttng_ust_rcu_assign_pointer(*ctx_p
, new_ctx
);
184 lttng_ust_urcu_synchronize_rcu();
186 free(old_ctx
->fields
);
193 * lttng_context_update() should be called at least once between context
194 * modification and trace start.
196 void lttng_context_update(struct lttng_ust_ctx
*ctx
)
199 size_t largest_align
= 8; /* in bits */
201 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
202 struct lttng_type
*type
;
203 size_t field_align
= 8;
205 type
= &ctx
->fields
[i
]->event_field
->type
;
206 switch (type
->atype
) {
208 field_align
= type
->u
.integer
.alignment
;
210 case atype_array_nestable
:
212 const struct lttng_type
*nested_type
;
214 nested_type
= type
->u
.array_nestable
.elem_type
;
215 switch (nested_type
->atype
) {
217 field_align
= nested_type
->u
.integer
.alignment
;
222 case atype_array_nestable
:
223 case atype_sequence_nestable
:
228 field_align
= max_t(size_t, field_align
,
229 type
->u
.array_nestable
.alignment
);
232 case atype_sequence_nestable
:
234 const struct lttng_type
*nested_type
;
236 nested_type
= type
->u
.sequence_nestable
.elem_type
;
237 switch (nested_type
->atype
) {
239 field_align
= nested_type
->u
.integer
.alignment
;
245 case atype_array_nestable
:
246 case atype_sequence_nestable
:
251 field_align
= max_t(size_t, field_align
,
252 type
->u
.sequence_nestable
.alignment
);
259 case atype_enum_nestable
:
264 largest_align
= max_t(size_t, largest_align
, field_align
);
266 ctx
->largest_align
= largest_align
>> 3; /* bits to bytes */
270 * Remove last context field.
272 void lttng_remove_context_field(struct lttng_ust_ctx
**ctx_p
,
273 struct lttng_ust_ctx_field
*field
)
275 struct lttng_ust_ctx
*ctx
;
279 assert(ctx
->fields
[ctx
->nr_fields
] == field
);
280 assert(field
->field_name
== NULL
);
281 ctx
->fields
[ctx
->nr_fields
] = NULL
;
284 void lttng_destroy_context(struct lttng_ust_ctx
*ctx
)
290 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
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
]);
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
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
313 int lttng_ust_context_set_provider_rcu(struct lttng_ust_ctx
**_ctx
,
315 size_t (*get_size
)(struct lttng_ust_ctx_field
*field
, size_t offset
),
316 void (*record
)(struct lttng_ust_ctx_field
*field
,
317 struct lttng_ust_lib_ring_buffer_ctx
*ctx
,
318 struct lttng_channel
*chan
),
319 void (*get_value
)(struct lttng_ust_ctx_field
*field
,
320 struct lttng_ust_ctx_value
*value
))
323 struct lttng_ust_ctx
*ctx
= *_ctx
, *new_ctx
;
324 struct lttng_ust_ctx_field
**new_fields
;
326 if (!ctx
|| !lttng_find_context_provider(ctx
, name
))
329 * We have at least one instance of context for the provider.
331 new_ctx
= zmalloc(sizeof(*new_ctx
));
334 new_ctx
->struct_size
= sizeof(*new_ctx
);
336 new_fields
= zmalloc(sizeof(*new_fields
) * ctx
->allocated_fields
);
342 memcpy(new_fields
, ctx
->fields
,
343 sizeof(*new_fields
) * ctx
->allocated_fields
);
344 for (i
= 0; i
< ctx
->nr_fields
; i
++) {
345 if (strncmp(new_fields
[i
]->event_field
->name
,
346 name
, strlen(name
)) != 0)
348 new_fields
[i
]->get_size
= get_size
;
349 new_fields
[i
]->record
= record
;
350 new_fields
[i
]->get_value
= get_value
;
352 new_ctx
->fields
= new_fields
;
353 lttng_ust_rcu_assign_pointer(*_ctx
, new_ctx
);
354 lttng_ust_urcu_synchronize_rcu();
364 int lttng_context_init_all(struct lttng_ust_ctx
**ctx
)
368 ret
= lttng_add_pthread_id_to_ctx(ctx
);
370 WARN("Cannot add context lttng_add_pthread_id_to_ctx");
373 ret
= lttng_add_vtid_to_ctx(ctx
);
375 WARN("Cannot add context lttng_add_vtid_to_ctx");
378 ret
= lttng_add_vpid_to_ctx(ctx
);
380 WARN("Cannot add context lttng_add_vpid_to_ctx");
383 ret
= lttng_add_procname_to_ctx(ctx
);
385 WARN("Cannot add context lttng_add_procname_to_ctx");
388 ret
= lttng_add_cpu_id_to_ctx(ctx
);
390 WARN("Cannot add context lttng_add_cpu_id_to_ctx");
393 ret
= lttng_add_cgroup_ns_to_ctx(ctx
);
395 WARN("Cannot add context lttng_add_cgroup_ns_to_ctx");
398 ret
= lttng_add_ipc_ns_to_ctx(ctx
);
400 WARN("Cannot add context lttng_add_ipc_ns_to_ctx");
403 ret
= lttng_add_mnt_ns_to_ctx(ctx
);
405 WARN("Cannot add context lttng_add_mnt_ns_to_ctx");
408 ret
= lttng_add_net_ns_to_ctx(ctx
);
410 WARN("Cannot add context lttng_add_net_ns_to_ctx");
413 ret
= lttng_add_pid_ns_to_ctx(ctx
);
415 WARN("Cannot add context lttng_add_pid_ns_to_ctx");
418 ret
= lttng_add_time_ns_to_ctx(ctx
);
420 WARN("Cannot add context lttng_add_time_ns_to_ctx");
423 ret
= lttng_add_user_ns_to_ctx(ctx
);
425 WARN("Cannot add context lttng_add_user_ns_to_ctx");
428 ret
= lttng_add_uts_ns_to_ctx(ctx
);
430 WARN("Cannot add context lttng_add_uts_ns_to_ctx");
433 ret
= lttng_add_vuid_to_ctx(ctx
);
435 WARN("Cannot add context lttng_add_vuid_to_ctx");
438 ret
= lttng_add_veuid_to_ctx(ctx
);
440 WARN("Cannot add context lttng_add_veuid_to_ctx");
443 ret
= lttng_add_vsuid_to_ctx(ctx
);
445 WARN("Cannot add context lttng_add_vsuid_to_ctx");
448 ret
= lttng_add_vgid_to_ctx(ctx
);
450 WARN("Cannot add context lttng_add_vgid_to_ctx");
453 ret
= lttng_add_vegid_to_ctx(ctx
);
455 WARN("Cannot add context lttng_add_vegid_to_ctx");
458 ret
= lttng_add_vsgid_to_ctx(ctx
);
460 WARN("Cannot add context lttng_add_vsgid_to_ctx");
463 lttng_context_update(*ctx
);
467 lttng_destroy_context(*ctx
);