Rename struct lttng_event to struct lttng_ust_event_recorder
[lttng-ust.git] / liblttng-ust / lttng-context-provider.c
... / ...
CommitLineData
1/*
2 * SPDX-License-Identifier: LGPL-2.1-only
3 *
4 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * LTTng UST application context provider.
7 */
8
9#define _LGPL_SOURCE
10#include <stddef.h>
11#include <stdint.h>
12#include <sys/types.h>
13#include <unistd.h>
14
15#include <ust-context-provider.h>
16
17#include "context-internal.h"
18#include "lttng-tracer-core.h"
19#include "jhash.h"
20#include "context-provider-internal.h"
21#include <ust-helper.h>
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
63 lttng_ust_fixup_tls();
64
65 /* Provider name starts with "$app.". */
66 if (strncmp("$app.", provider->name, strlen("$app.")) != 0)
67 return -EINVAL;
68 /* Provider name cannot contain a colon character. */
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);
82
83 lttng_ust_context_set_session_provider(provider->name,
84 provider->get_size, provider->record,
85 provider->get_value);
86
87 lttng_ust_context_set_event_notifier_group_provider(provider->name,
88 provider->get_size, provider->record,
89 provider->get_value);
90end:
91 ust_unlock();
92 return ret;
93}
94
95void lttng_ust_context_provider_unregister(struct lttng_ust_context_provider *provider)
96{
97 lttng_ust_fixup_tls();
98
99 if (ust_lock())
100 goto end;
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);
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
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,
123 struct lttng_ctx **ctx)
124{
125 struct lttng_ust_context_provider *provider;
126 struct lttng_ctx_field new_field;
127 int ret;
128
129 if (*ctx && lttng_find_context(*ctx, name))
130 return -EEXIST;
131 /*
132 * For application context, add it by expanding
133 * ctx array.
134 */
135 memset(&new_field, 0, sizeof(new_field));
136 new_field.field_name = strdup(name);
137 if (!new_field.field_name)
138 return -ENOMEM;
139 new_field.event_field.name = new_field.field_name;
140 new_field.event_field.type.atype = atype_dynamic;
141 /*
142 * If provider is not found, we add the context anyway, but
143 * it will provide a dummy context.
144 */
145 provider = lookup_provider_by_name(name);
146 if (provider) {
147 new_field.get_size = provider->get_size;
148 new_field.record = provider->record;
149 new_field.get_value = provider->get_value;
150 } else {
151 new_field.get_size = lttng_ust_dummy_get_size;
152 new_field.record = lttng_ust_dummy_record;
153 new_field.get_value = lttng_ust_dummy_get_value;
154 }
155 ret = lttng_context_add_rcu(ctx, &new_field);
156 if (ret) {
157 free(new_field.field_name);
158 return ret;
159 }
160 return 0;
161}
This page took 0.022255 seconds and 4 git commands to generate.