Namespace remaining symbols in lttng/ringbuffer-context.h
[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
MD
22
23#define CONTEXT_PROVIDER_HT_BITS 12
24#define CONTEXT_PROVIDER_HT_SIZE (1U << CONTEXT_PROVIDER_HT_BITS)
25struct context_provider_ht {
26 struct cds_hlist_head table[CONTEXT_PROVIDER_HT_SIZE];
27};
28
29static struct context_provider_ht context_provider_ht;
30
31static struct lttng_ust_context_provider *
32 lookup_provider_by_name(const char *name)
33{
34 struct cds_hlist_head *head;
35 struct cds_hlist_node *node;
36 struct lttng_ust_context_provider *provider;
37 uint32_t hash;
38 const char *end;
39 size_t len;
40
41 /* Lookup using everything before first ':' as key. */
42 end = strchr(name, ':');
43 if (end)
44 len = end - name;
45 else
46 len = strlen(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))
51 return provider;
52 }
53 return NULL;
54}
55
56int lttng_ust_context_provider_register(struct lttng_ust_context_provider *provider)
57{
58 struct cds_hlist_head *head;
59 size_t name_len = strlen(provider->name);
60 uint32_t hash;
61 int ret = 0;
62
c362addf
MD
63 lttng_ust_fixup_tls();
64
53569322 65 /* Provider name starts with "$app.". */
fe94775b 66 if (strncmp("$app.", provider->name, strlen("$app.")) != 0)
53569322 67 return -EINVAL;
8b05d0d4 68 /* Provider name cannot contain a colon character. */
53569322
MD
69 if (strchr(provider->name, ':'))
70 return -EINVAL;
71 if (ust_lock()) {
72 ret = -EBUSY;
73 goto end;
74 }
75 if (lookup_provider_by_name(provider->name)) {
76 ret = -EBUSY;
77 goto end;
78 }
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);
d8d2416d 82
53569322
MD
83 lttng_ust_context_set_session_provider(provider->name,
84 provider->get_size, provider->record,
85 provider->get_value);
d8d2416d
FD
86
87 lttng_ust_context_set_event_notifier_group_provider(provider->name,
88 provider->get_size, provider->record,
89 provider->get_value);
53569322
MD
90end:
91 ust_unlock();
92 return ret;
93}
94
53569322
MD
95void lttng_ust_context_provider_unregister(struct lttng_ust_context_provider *provider)
96{
c362addf
MD
97 lttng_ust_fixup_tls();
98
53569322
MD
99 if (ust_lock())
100 goto end;
101 lttng_ust_context_set_session_provider(provider->name,
ce7352a2
MD
102 lttng_ust_dummy_get_size, lttng_ust_dummy_record,
103 lttng_ust_dummy_get_value);
d8d2416d
FD
104
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);
108
53569322
MD
109 cds_hlist_del(&provider->node);
110end:
111 ust_unlock();
112}
113
114/*
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.
121 */
122int lttng_ust_add_app_context_to_ctx_rcu(const char *name,
daacdbfc 123 struct lttng_ust_ctx **ctx)
53569322
MD
124{
125 struct lttng_ust_context_provider *provider;
daacdbfc 126 struct lttng_ust_ctx_field *new_field = NULL;
53569322
MD
127 int ret;
128
129 if (*ctx && lttng_find_context(*ctx, name))
130 return -EEXIST;
daacdbfc
MD
131 new_field = zmalloc(sizeof(struct lttng_ust_ctx_field));
132 if (!new_field) {
133 ret = -ENOMEM;
134 goto error_field_alloc;
135 }
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) {
139 ret = -ENOMEM;
140 goto error_event_field_alloc;
141 }
a084756d
MD
142 new_field->event_field->name = strdup(name);
143 if (!new_field->event_field->name) {
daacdbfc
MD
144 ret = -ENOMEM;
145 goto error_field_name_alloc;
146 }
a084756d
MD
147 new_field->event_field->type = zmalloc(sizeof(struct lttng_ust_type_common));
148 if (!new_field->event_field->type) {
149 ret = -ENOMEM;
150 goto error_field_type_alloc;
151 }
152 new_field->event_field->type->type = lttng_ust_type_dynamic;
53569322
MD
153 /*
154 * If provider is not found, we add the context anyway, but
155 * it will provide a dummy context.
156 */
157 provider = lookup_provider_by_name(name);
158 if (provider) {
daacdbfc
MD
159 new_field->get_size = provider->get_size;
160 new_field->record = provider->record;
161 new_field->get_value = provider->get_value;
53569322 162 } else {
daacdbfc
MD
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;
53569322 166 }
daacdbfc
MD
167 /*
168 * For application context, add it by expanding
169 * ctx array. Ownership of new_field is passed to the callee on
170 * success.
171 */
172 ret = lttng_context_add_rcu(ctx, new_field);
53569322 173 if (ret) {
a084756d
MD
174 free(new_field->event_field->type);
175 free((char *) new_field->event_field->name);
daacdbfc
MD
176 free(new_field->event_field);
177 free(new_field);
53569322
MD
178 return ret;
179 }
180 return 0;
daacdbfc 181
a084756d
MD
182error_field_type_alloc:
183 free((char *) new_field->event_field->name);
daacdbfc
MD
184error_field_name_alloc:
185 free(new_field->event_field);
186error_event_field_alloc:
187 free(new_field);
188error_field_alloc:
189 return ret;
53569322 190}
This page took 0.034578 seconds and 4 git commands to generate.