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 <lttng/ust-context-provider.h>
17 #include "lttng-tracer-core.h"
19 #include "context-provider-internal.h"
22 #define CONTEXT_PROVIDER_HT_BITS 12
23 #define CONTEXT_PROVIDER_HT_SIZE (1U << CONTEXT_PROVIDER_HT_BITS)
24 struct context_provider_ht
{
25 struct cds_hlist_head table
[CONTEXT_PROVIDER_HT_SIZE
];
28 static struct context_provider_ht context_provider_ht
;
30 static struct lttng_ust_context_provider
*
31 lookup_provider_by_name(const char *name
)
33 struct cds_hlist_head
*head
;
34 struct cds_hlist_node
*node
;
35 struct lttng_ust_context_provider
*provider
;
40 /* Lookup using everything before first ':' as key. */
41 end
= strchr(name
, ':');
46 hash
= jhash(name
, len
, 0);
47 head
= &context_provider_ht
.table
[hash
& (CONTEXT_PROVIDER_HT_SIZE
- 1)];
48 cds_hlist_for_each_entry(provider
, node
, head
, node
) {
49 if (!strncmp(provider
->name
, name
, len
))
55 int lttng_ust_context_provider_register(struct lttng_ust_context_provider
*provider
)
57 struct cds_hlist_head
*head
;
58 size_t name_len
= strlen(provider
->name
);
62 lttng_ust_fixup_tls();
64 /* Provider name starts with "$app.". */
65 if (strncmp("$app.", provider
->name
, strlen("$app.")) != 0)
67 /* Provider name cannot contain a colon character. */
68 if (strchr(provider
->name
, ':'))
74 if (lookup_provider_by_name(provider
->name
)) {
78 hash
= jhash(provider
->name
, name_len
, 0);
79 head
= &context_provider_ht
.table
[hash
& (CONTEXT_PROVIDER_HT_SIZE
- 1)];
80 cds_hlist_add_head(&provider
->node
, head
);
82 lttng_ust_context_set_session_provider(provider
->name
,
83 provider
->get_size
, provider
->record
,
86 lttng_ust_context_set_event_notifier_group_provider(provider
->name
,
87 provider
->get_size
, provider
->record
,
94 void lttng_ust_context_provider_unregister(struct lttng_ust_context_provider
*provider
)
96 lttng_ust_fixup_tls();
100 lttng_ust_context_set_session_provider(provider
->name
,
101 lttng_ust_dummy_get_size
, lttng_ust_dummy_record
,
102 lttng_ust_dummy_get_value
);
104 lttng_ust_context_set_event_notifier_group_provider(provider
->name
,
105 lttng_ust_dummy_get_size
, lttng_ust_dummy_record
,
106 lttng_ust_dummy_get_value
);
108 cds_hlist_del(&provider
->node
);
114 * Called with ust mutex held.
115 * Add application context to array of context, even if the application
116 * context is not currently loaded by application. It will then use the
117 * dummy callbacks in that case.
118 * Always performed before tracing is started, since it modifies
119 * metadata describing the context.
121 int lttng_ust_add_app_context_to_ctx_rcu(const char *name
,
122 struct lttng_ctx
**ctx
)
124 struct lttng_ust_context_provider
*provider
;
125 struct lttng_ctx_field new_field
;
128 if (*ctx
&& lttng_find_context(*ctx
, name
))
131 * For application context, add it by expanding
134 memset(&new_field
, 0, sizeof(new_field
));
135 new_field
.field_name
= strdup(name
);
136 if (!new_field
.field_name
)
138 new_field
.event_field
.name
= new_field
.field_name
;
139 new_field
.event_field
.type
.atype
= atype_dynamic
;
141 * If provider is not found, we add the context anyway, but
142 * it will provide a dummy context.
144 provider
= lookup_provider_by_name(name
);
146 new_field
.get_size
= provider
->get_size
;
147 new_field
.record
= provider
->record
;
148 new_field
.get_value
= provider
->get_value
;
150 new_field
.get_size
= lttng_ust_dummy_get_size
;
151 new_field
.record
= lttng_ust_dummy_record
;
152 new_field
.get_value
= lttng_ust_dummy_get_value
;
154 ret
= lttng_context_add_rcu(ctx
, &new_field
);
156 free(new_field
.field_name
);