Include lttng/tracepoint-types.h from tracepoint.h
[lttng-ust.git] / liblttng-ust / ltt-probes.c
CommitLineData
ce5aef0b
MD
1/*
2 * ltt-probes.c
3 *
4 * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * Holds LTTng probes registry.
7 *
8 * Dual LGPL v2.1/GPL v2 license.
9 */
10
8d8a24c8
MD
11#include <string.h>
12#include <errno.h>
13#include <urcu/list.h>
4318ae1b 14#include <lttng/ust-events.h>
a3bb4b27 15#include <assert.h>
c8fcf224 16#include <helper.h>
ce5aef0b 17
8165c8da
MD
18#include "ltt-tracer-core.h"
19
20/*
17dfb34b 21 * probe list is protected by ust_lock()/ust_unlock().
8165c8da 22 */
8d8a24c8 23static CDS_LIST_HEAD(probe_list);
ce5aef0b 24
df854e41
MD
25static
26const struct lttng_probe_desc *find_provider(const char *provider)
27{
28 struct lttng_probe_desc *iter;
29
30 cds_list_for_each_entry(iter, &probe_list, head) {
31 if (!strcmp(iter->provider, provider))
32 return iter;
33 }
34 return NULL;
35}
36
ce5aef0b
MD
37static
38const struct lttng_event_desc *find_event(const char *name)
39{
40 struct lttng_probe_desc *probe_desc;
41 int i;
42
8d8a24c8 43 cds_list_for_each_entry(probe_desc, &probe_list, head) {
ce5aef0b 44 for (i = 0; i < probe_desc->nr_events; i++) {
df854e41
MD
45 if (!strcmp(probe_desc->event_desc[i]->name, name))
46 return probe_desc->event_desc[i];
ce5aef0b
MD
47 }
48 }
49 return NULL;
50}
51
52int ltt_probe_register(struct lttng_probe_desc *desc)
53{
df854e41 54 struct lttng_probe_desc *iter;
ce5aef0b
MD
55 int ret = 0;
56 int i;
57
17dfb34b 58 ust_lock();
df854e41
MD
59 if (find_provider(desc->provider)) {
60 ret = -EEXIST;
61 goto end;
62 }
ce5aef0b
MD
63 /*
64 * TODO: This is O(N^2). Turn into a hash table when probe registration
65 * overhead becomes an issue.
66 */
67 for (i = 0; i < desc->nr_events; i++) {
df854e41 68 if (find_event(desc->event_desc[i]->name)) {
ce5aef0b
MD
69 ret = -EEXIST;
70 goto end;
71 }
72 }
df854e41
MD
73
74 /*
75 * We sort the providers by struct lttng_probe_desc pointer
76 * address.
77 */
78 cds_list_for_each_entry_reverse(iter, &probe_list, head) {
79 BUG_ON(iter == desc); /* Should never be in the list twice */
80 if (iter < desc) {
81 /* We belong to the location right after iter. */
82 cds_list_add(&desc->head, &iter->head);
83 goto desc_added;
84 }
85 }
86 /* We should be added at the head of the list */
8d8a24c8 87 cds_list_add(&desc->head, &probe_list);
df854e41 88desc_added:
8165c8da
MD
89
90 /*
91 * fix the events awaiting probe load.
92 */
93 for (i = 0; i < desc->nr_events; i++) {
df854e41 94 ret = pending_probe_fix_events(desc->event_desc[i]);
8165c8da
MD
95 assert(!ret);
96 }
ce5aef0b 97end:
17dfb34b 98 ust_unlock();
ce5aef0b
MD
99 return ret;
100}
ce5aef0b
MD
101
102void ltt_probe_unregister(struct lttng_probe_desc *desc)
103{
17dfb34b 104 ust_lock();
8d8a24c8 105 cds_list_del(&desc->head);
17dfb34b 106 ust_unlock();
ce5aef0b 107}
ce5aef0b 108
8165c8da
MD
109/*
110 * called with UST lock held.
111 */
ce5aef0b
MD
112const struct lttng_event_desc *ltt_event_get(const char *name)
113{
114 const struct lttng_event_desc *event;
ce5aef0b 115
ce5aef0b 116 event = find_event(name);
ce5aef0b
MD
117 if (!event)
118 return NULL;
ce5aef0b
MD
119 return event;
120}
ce5aef0b
MD
121
122void ltt_event_put(const struct lttng_event_desc *event)
123{
ce5aef0b 124}
c8fcf224
MD
125
126void ltt_probes_prune_event_list(struct lttng_ust_tracepoint_list *list)
127{
128 struct tp_list_entry *list_entry, *tmp;
129
130 cds_list_for_each_entry_safe(list_entry, tmp, &list->head, head) {
131 cds_list_del(&list_entry->head);
132 free(list_entry);
133 }
134}
135
136/*
137 * called with UST lock held.
138 */
139int ltt_probes_get_event_list(struct lttng_ust_tracepoint_list *list)
140{
141 struct lttng_probe_desc *probe_desc;
142 int i;
143
144 CDS_INIT_LIST_HEAD(&list->head);
145 cds_list_for_each_entry(probe_desc, &probe_list, head) {
146 for (i = 0; i < probe_desc->nr_events; i++) {
147 struct tp_list_entry *list_entry;
148
149 list_entry = zmalloc(sizeof(*list_entry));
150 if (!list_entry)
151 goto err_nomem;
152 cds_list_add(&list_entry->head, &list->head);
153 strncpy(list_entry->tp.name,
154 probe_desc->event_desc[i]->name,
155 LTTNG_UST_SYM_NAME_LEN);
156 list_entry->tp.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
157 if (!probe_desc->event_desc[i]->loglevel) {
158 list_entry->tp.loglevel[0] = '\0';
159 list_entry->tp.loglevel_value = 0;
160 } else {
161 strncpy(list_entry->tp.loglevel,
162 (*probe_desc->event_desc[i]->loglevel)->identifier,
163 LTTNG_UST_SYM_NAME_LEN);
164 list_entry->tp.loglevel[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
165 list_entry->tp.loglevel_value =
166 (*probe_desc->event_desc[i]->loglevel)->value;
167 }
168 }
169 }
170 if (cds_list_empty(&list->head))
171 list->iter = NULL;
172 else
173 list->iter =
174 cds_list_first_entry(&list->head, struct tp_list_entry, head);
175 return 0;
176
177err_nomem:
178 ltt_probes_prune_event_list(list);
179 return -ENOMEM;
180}
181
182/*
183 * Return current iteration position, advance internal iterator to next.
184 * Return NULL if end of list.
185 */
186struct lttng_ust_tracepoint_iter *
187 lttng_ust_tracepoint_list_get_iter_next(struct lttng_ust_tracepoint_list *list)
188{
189 struct tp_list_entry *entry;
190
191 if (!list->iter)
192 return NULL;
193 entry = list->iter;
194 if (entry->head.next == &list->head)
195 list->iter = NULL;
196 else
197 list->iter = cds_list_entry(entry->head.next,
198 struct tp_list_entry, head);
199 return &entry->tp;
200}
This page took 0.032216 seconds and 4 git commands to generate.