2 * SPDX-License-Identifier: LGPL-2.1-only
4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * LTTng UST application context provider.
12 #include <sys/types.h>
15 #include <ust-context-provider.h>
17 #include "context-internal.h"
18 #include "lttng-tracer-core.h"
20 #include "context-provider-internal.h"
21 #include <ust-helper.h>
23 #define CONTEXT_PROVIDER_HT_BITS 12
24 #define CONTEXT_PROVIDER_HT_SIZE (1U << CONTEXT_PROVIDER_HT_BITS)
25 struct context_provider_ht
{
26 struct cds_hlist_head table
[CONTEXT_PROVIDER_HT_SIZE
];
29 static struct context_provider_ht context_provider_ht
;
31 static struct lttng_ust_context_provider
*
32 lookup_provider_by_name(const char *name
)
34 struct cds_hlist_head
*head
;
35 struct cds_hlist_node
*node
;
36 struct lttng_ust_context_provider
*provider
;
41 /* Lookup using everything before first ':' as key. */
42 end
= strchr(name
, ':');
47 hash
= jhash(name
, len
, 0);
48 head
= &context_provider_ht
.table
[hash
& (CONTEXT_PROVIDER_HT_SIZE
- 1)];
49 cds_hlist_for_each_entry(provider
, node
, head
, node
) {
50 if (!strncmp(provider
->name
, name
, len
))
56 int lttng_ust_context_provider_register(struct lttng_ust_context_provider
*provider
)
58 struct cds_hlist_head
*head
;
59 size_t name_len
= strlen(provider
->name
);
63 lttng_ust_fixup_tls();
65 /* Provider name starts with "$app.". */
66 if (strncmp("$app.", provider
->name
, strlen("$app.")) != 0)
68 /* Provider name cannot contain a colon character. */
69 if (strchr(provider
->name
, ':'))
75 if (lookup_provider_by_name(provider
->name
)) {
79 hash
= jhash(provider
->name
, name_len
, 0);
80 head
= &context_provider_ht
.table
[hash
& (CONTEXT_PROVIDER_HT_SIZE
- 1)];
81 cds_hlist_add_head(&provider
->node
, head
);
83 lttng_ust_context_set_session_provider(provider
->name
,
84 provider
->get_size
, provider
->record
,
87 lttng_ust_context_set_event_notifier_group_provider(provider
->name
,
88 provider
->get_size
, provider
->record
,
95 void lttng_ust_context_provider_unregister(struct lttng_ust_context_provider
*provider
)
97 lttng_ust_fixup_tls();
101 lttng_ust_context_set_session_provider(provider
->name
,
102 lttng_ust_dummy_get_size
, lttng_ust_dummy_record
,
103 lttng_ust_dummy_get_value
);
105 lttng_ust_context_set_event_notifier_group_provider(provider
->name
,
106 lttng_ust_dummy_get_size
, lttng_ust_dummy_record
,
107 lttng_ust_dummy_get_value
);
109 cds_hlist_del(&provider
->node
);
115 * Called with ust mutex held.
116 * Add application context to array of context, even if the application
117 * context is not currently loaded by application. It will then use the
118 * dummy callbacks in that case.
119 * Always performed before tracing is started, since it modifies
120 * metadata describing the context.
122 int lttng_ust_add_app_context_to_ctx_rcu(const char *name
,
123 struct lttng_ust_ctx
**ctx
)
125 struct lttng_ust_context_provider
*provider
;
126 struct lttng_ust_ctx_field
*new_field
= NULL
;
129 if (*ctx
&& lttng_find_context(*ctx
, name
))
131 new_field
= zmalloc(sizeof(struct lttng_ust_ctx_field
));
134 goto error_field_alloc
;
136 new_field
->struct_size
= sizeof(struct lttng_ust_ctx_field
);
137 new_field
->event_field
= zmalloc(sizeof(struct lttng_ust_event_field
));
138 if (!new_field
->event_field
) {
140 goto error_event_field_alloc
;
142 new_field
->event_field
->name
= strdup(name
);
143 if (!new_field
->event_field
->name
) {
145 goto error_field_name_alloc
;
147 new_field
->event_field
->type
= zmalloc(sizeof(struct lttng_ust_type_common
));
148 if (!new_field
->event_field
->type
) {
150 goto error_field_type_alloc
;
152 new_field
->event_field
->type
->type
= lttng_ust_type_dynamic
;
154 * If provider is not found, we add the context anyway, but
155 * it will provide a dummy context.
157 provider
= lookup_provider_by_name(name
);
159 new_field
->get_size
= provider
->get_size
;
160 new_field
->record
= provider
->record
;
161 new_field
->get_value
= provider
->get_value
;
163 new_field
->get_size
= lttng_ust_dummy_get_size
;
164 new_field
->record
= lttng_ust_dummy_record
;
165 new_field
->get_value
= lttng_ust_dummy_get_value
;
168 * For application context, add it by expanding
169 * ctx array. Ownership of new_field is passed to the callee on
172 ret
= lttng_context_add_rcu(ctx
, new_field
);
174 free(new_field
->event_field
->type
);
175 free((char *) new_field
->event_field
->name
);
176 free(new_field
->event_field
);
182 error_field_type_alloc
:
183 free((char *) new_field
->event_field
->name
);
184 error_field_name_alloc
:
185 free(new_field
->event_field
);
186 error_event_field_alloc
: