Refactoring: add back constness of public API structures
[lttng-ust.git] / liblttng-ust / lttng-context-provider.c
CommitLineData
53569322 1/*
c0c0989a 2 * SPDX-License-Identifier: LGPL-2.1-only
53569322
MD
3 *
4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
c0c0989a 6 * LTTng UST application context provider.
53569322
MD
7 */
8
3fbec7dc 9#define _LGPL_SOURCE
b4051ad8 10#include <stddef.h>
fb31eb73 11#include <stdint.h>
53569322
MD
12#include <sys/types.h>
13#include <unistd.h>
fb31eb73 14
ae4b659d 15#include <ust-context-provider.h>
d8d2416d 16
fc80554e 17#include "context-internal.h"
53569322
MD
18#include "lttng-tracer-core.h"
19#include "jhash.h"
d8d2416d 20#include "context-provider-internal.h"
864a1eda 21#include <ust-helper.h>
53569322 22
4e48b5d2
MD
23struct lttng_ust_registered_context_provider {
24 const struct lttng_ust_context_provider *provider;
25
26 struct cds_hlist_node node;
27};
28
53569322
MD
29#define CONTEXT_PROVIDER_HT_BITS 12
30#define CONTEXT_PROVIDER_HT_SIZE (1U << CONTEXT_PROVIDER_HT_BITS)
31struct context_provider_ht {
32 struct cds_hlist_head table[CONTEXT_PROVIDER_HT_SIZE];
33};
34
35static struct context_provider_ht context_provider_ht;
36
4e48b5d2 37static const struct lttng_ust_context_provider *
53569322
MD
38 lookup_provider_by_name(const char *name)
39{
40 struct cds_hlist_head *head;
41 struct cds_hlist_node *node;
4e48b5d2 42 struct lttng_ust_registered_context_provider *reg_provider;
53569322
MD
43 uint32_t hash;
44 const char *end;
45 size_t len;
46
47 /* Lookup using everything before first ':' as key. */
48 end = strchr(name, ':');
49 if (end)
50 len = end - name;
51 else
52 len = strlen(name);
53 hash = jhash(name, len, 0);
54 head = &context_provider_ht.table[hash & (CONTEXT_PROVIDER_HT_SIZE - 1)];
4e48b5d2
MD
55 cds_hlist_for_each_entry(reg_provider, node, head, node) {
56 if (!strncmp(reg_provider->provider->name, name, len))
57 return reg_provider->provider;
53569322
MD
58 }
59 return NULL;
60}
61
4e48b5d2 62struct lttng_ust_registered_context_provider *lttng_ust_context_provider_register(struct lttng_ust_context_provider *provider)
53569322 63{
4e48b5d2 64 struct lttng_ust_registered_context_provider *reg_provider = NULL;
53569322
MD
65 struct cds_hlist_head *head;
66 size_t name_len = strlen(provider->name);
67 uint32_t hash;
53569322 68
c362addf
MD
69 lttng_ust_fixup_tls();
70
53569322 71 /* Provider name starts with "$app.". */
fe94775b 72 if (strncmp("$app.", provider->name, strlen("$app.")) != 0)
4e48b5d2 73 return NULL;
8b05d0d4 74 /* Provider name cannot contain a colon character. */
53569322 75 if (strchr(provider->name, ':'))
4e48b5d2
MD
76 return NULL;
77 if (ust_lock())
53569322 78 goto end;
4e48b5d2 79 if (lookup_provider_by_name(provider->name))
53569322 80 goto end;
4e48b5d2
MD
81 reg_provider = zmalloc(sizeof(struct lttng_ust_registered_context_provider));
82 if (!reg_provider)
83 goto end;
84 reg_provider->provider = provider;
53569322
MD
85 hash = jhash(provider->name, name_len, 0);
86 head = &context_provider_ht.table[hash & (CONTEXT_PROVIDER_HT_SIZE - 1)];
4e48b5d2 87 cds_hlist_add_head(&reg_provider->node, head);
d8d2416d 88
53569322
MD
89 lttng_ust_context_set_session_provider(provider->name,
90 provider->get_size, provider->record,
4e48b5d2 91 provider->get_value, provider->priv);
d8d2416d
FD
92
93 lttng_ust_context_set_event_notifier_group_provider(provider->name,
94 provider->get_size, provider->record,
4e48b5d2 95 provider->get_value, provider->priv);
53569322
MD
96end:
97 ust_unlock();
4e48b5d2 98 return reg_provider;
53569322
MD
99}
100
4e48b5d2 101void lttng_ust_context_provider_unregister(struct lttng_ust_registered_context_provider *reg_provider)
53569322 102{
c362addf
MD
103 lttng_ust_fixup_tls();
104
53569322
MD
105 if (ust_lock())
106 goto end;
4e48b5d2 107 lttng_ust_context_set_session_provider(reg_provider->provider->name,
ce7352a2 108 lttng_ust_dummy_get_size, lttng_ust_dummy_record,
4e48b5d2 109 lttng_ust_dummy_get_value, NULL);
d8d2416d 110
4e48b5d2 111 lttng_ust_context_set_event_notifier_group_provider(reg_provider->provider->name,
d8d2416d 112 lttng_ust_dummy_get_size, lttng_ust_dummy_record,
4e48b5d2 113 lttng_ust_dummy_get_value, NULL);
d8d2416d 114
4e48b5d2 115 cds_hlist_del(&reg_provider->node);
53569322
MD
116end:
117 ust_unlock();
4e48b5d2 118 free(reg_provider);
53569322
MD
119}
120
121/*
122 * Called with ust mutex held.
123 * Add application context to array of context, even if the application
124 * context is not currently loaded by application. It will then use the
125 * dummy callbacks in that case.
126 * Always performed before tracing is started, since it modifies
127 * metadata describing the context.
128 */
129int lttng_ust_add_app_context_to_ctx_rcu(const char *name,
daacdbfc 130 struct lttng_ust_ctx **ctx)
53569322 131{
4e48b5d2 132 const struct lttng_ust_context_provider *provider;
daacdbfc 133 struct lttng_ust_ctx_field *new_field = NULL;
4e48b5d2
MD
134 struct lttng_ust_event_field *event_field = NULL;
135 struct lttng_ust_type_common *type = NULL;
53569322
MD
136 int ret;
137
138 if (*ctx && lttng_find_context(*ctx, name))
139 return -EEXIST;
daacdbfc
MD
140 new_field = zmalloc(sizeof(struct lttng_ust_ctx_field));
141 if (!new_field) {
142 ret = -ENOMEM;
143 goto error_field_alloc;
144 }
4e48b5d2
MD
145 event_field = zmalloc(sizeof(struct lttng_ust_event_field));
146 if (!event_field) {
daacdbfc
MD
147 ret = -ENOMEM;
148 goto error_event_field_alloc;
149 }
4e48b5d2
MD
150 event_field->name = strdup(name);
151 if (!event_field->name) {
daacdbfc
MD
152 ret = -ENOMEM;
153 goto error_field_name_alloc;
154 }
4e48b5d2
MD
155 type = zmalloc(sizeof(struct lttng_ust_type_common));
156 if (!type) {
a084756d
MD
157 ret = -ENOMEM;
158 goto error_field_type_alloc;
159 }
4e48b5d2
MD
160 type->type = lttng_ust_type_dynamic;
161 event_field->type = type;
162 new_field->event_field = event_field;
53569322
MD
163 /*
164 * If provider is not found, we add the context anyway, but
165 * it will provide a dummy context.
166 */
167 provider = lookup_provider_by_name(name);
168 if (provider) {
daacdbfc
MD
169 new_field->get_size = provider->get_size;
170 new_field->record = provider->record;
171 new_field->get_value = provider->get_value;
53569322 172 } else {
daacdbfc
MD
173 new_field->get_size = lttng_ust_dummy_get_size;
174 new_field->record = lttng_ust_dummy_record;
175 new_field->get_value = lttng_ust_dummy_get_value;
53569322 176 }
daacdbfc
MD
177 /*
178 * For application context, add it by expanding
179 * ctx array. Ownership of new_field is passed to the callee on
180 * success.
181 */
4e48b5d2 182 ret = lttng_ust_context_append_rcu(ctx, new_field);
53569322 183 if (ret) {
4e48b5d2 184 free(type);
a084756d 185 free((char *) new_field->event_field->name);
4e48b5d2 186 free(event_field);
daacdbfc 187 free(new_field);
53569322
MD
188 return ret;
189 }
190 return 0;
daacdbfc 191
a084756d
MD
192error_field_type_alloc:
193 free((char *) new_field->event_field->name);
daacdbfc 194error_field_name_alloc:
4e48b5d2 195 free(event_field);
daacdbfc
MD
196error_event_field_alloc:
197 free(new_field);
198error_field_alloc:
199 return ret;
53569322 200}
This page took 0.040411 seconds and 4 git commands to generate.