Update version to 0.16
[ust.git] / libust / trace_event.c
CommitLineData
0c0686ee
NC
1/*
2 * Copyright (C) 2010 Nils Carlson
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
f37142a4
MD
6 * License as published by the Free Software Foundation;
7 * version 2.1 of the License.
0c0686ee
NC
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 */
19
b0c4126f 20#define _LGPL_SOURCE
0c0686ee
NC
21#include <errno.h>
22#include <ust/tracepoint.h>
81614639 23#include <ust/tracepoint-internal.h>
0c0686ee
NC
24#include <ust/core.h>
25#include <ust/kcompat/kcompat.h>
0c0686ee
NC
26#include <urcu-bp.h>
27
b0c4126f
MD
28#include "usterr_signal_safe.h"
29
0c0686ee 30/* libraries that contain trace_events (struct trace_event_lib) */
0222e121 31static CDS_LIST_HEAD(libs);
c7292295
MD
32/*
33 * Nested mutex is not required here, but provide the same guaranteed
34 * for start/stop iteration vs nested ops as markers and tracepoints.
35 */
36static __thread int nested_mutex;
0c0686ee
NC
37static DEFINE_MUTEX(trace_events_mutex);
38
c7292295
MD
39static
40int trace_event_get_iter_range(struct trace_event * const **trace_event,
41 struct trace_event * const *begin,
42 struct trace_event * const *end);
43
44static
0c0686ee
NC
45void lock_trace_events(void)
46{
c7292295
MD
47 if (!(nested_mutex++))
48 pthread_mutex_lock(&trace_events_mutex);
0c0686ee
NC
49}
50
c7292295 51static
0c0686ee
NC
52void unlock_trace_events(void)
53{
c7292295
MD
54 if (!(--nested_mutex))
55 pthread_mutex_unlock(&trace_events_mutex);
0c0686ee
NC
56}
57
c7292295 58static
0c0686ee
NC
59int lib_get_iter_trace_events(struct trace_event_iter *iter)
60{
61 struct trace_event_lib *iter_lib;
62 int found = 0;
63
0222e121 64 cds_list_for_each_entry(iter_lib, &libs, list) {
0c0686ee
NC
65 if (iter_lib < iter->lib)
66 continue;
67 else if (iter_lib > iter->lib)
68 iter->trace_event = NULL;
69 found = trace_event_get_iter_range(&iter->trace_event,
70 iter_lib->trace_events_start,
71 iter_lib->trace_events_start + iter_lib->trace_events_count);
72 if (found) {
73 iter->lib = iter_lib;
74 break;
75 }
76 }
77 return found;
78}
79
80/**
81 * trace_event_get_iter_range - Get a next trace_event iterator given a range.
82 * @trace_event: current trace_events (in), next trace_event (out)
83 * @begin: beginning of the range
84 * @end: end of the range
85 *
86 * Returns whether a next trace_event has been found (1) or not (0).
87 * Will return the first trace_event in the range if the input trace_event is NULL.
c7292295 88 * Called with trace event mutex held.
0c0686ee 89 */
c7292295 90static
fc1caebc
MD
91int trace_event_get_iter_range(struct trace_event * const **trace_event,
92 struct trace_event * const *begin,
93 struct trace_event * const *end)
0c0686ee 94{
f08ebbe2 95 if (!*trace_event && begin != end)
0c0686ee 96 *trace_event = begin;
f08ebbe2
MD
97 while (*trace_event >= begin && *trace_event < end) {
98 if (!**trace_event)
99 (*trace_event)++; /* skip dummy */
100 else
101 return 1;
0c0686ee 102 }
0c0686ee
NC
103 return 0;
104}
105
106static void trace_event_get_iter(struct trace_event_iter *iter)
107{
108 int found = 0;
109
110 found = lib_get_iter_trace_events(iter);
e2b46575 111
0c0686ee
NC
112 if (!found)
113 trace_event_iter_reset(iter);
114}
115
116void trace_event_iter_start(struct trace_event_iter *iter)
117{
c7292295 118 lock_trace_events();
0c0686ee
NC
119 trace_event_get_iter(iter);
120}
121
c7292295
MD
122/*
123 * Called with trace event mutex held.
124 */
0c0686ee
NC
125void trace_event_iter_next(struct trace_event_iter *iter)
126{
127 iter->trace_event++;
128 /*
129 * iter->trace_event may be invalid because we blindly incremented it.
130 * Make sure it is valid by marshalling on the trace_events, getting the
131 * trace_events from following modules if necessary.
132 */
133 trace_event_get_iter(iter);
134}
135
c7292295
MD
136void trace_event_iter_stop(struct trace_event_iter *iter)
137{
138 unlock_trace_events();
139}
140
0c0686ee
NC
141void trace_event_iter_reset(struct trace_event_iter *iter)
142{
143 iter->lib = NULL;
144 iter->trace_event = NULL;
145}
146
fc1caebc 147int trace_event_register_lib(struct trace_event * const *trace_events_start,
0c0686ee
NC
148 int trace_events_count)
149{
b467f7a7 150 struct trace_event_lib *pl, *iter;
0c0686ee
NC
151
152 pl = (struct trace_event_lib *) malloc(sizeof(struct trace_event_lib));
153
154 pl->trace_events_start = trace_events_start;
155 pl->trace_events_count = trace_events_count;
156
c7292295 157 lock_trace_events();
b467f7a7
MD
158 /*
159 * We sort the libs by struct lib pointer address.
160 */
161 cds_list_for_each_entry_reverse(iter, &libs, list) {
162 BUG_ON(iter == pl); /* Should never be in the list twice */
163 if (iter < pl) {
164 /* We belong to the location right after iter. */
165 cds_list_add(&pl->list, &iter->list);
166 goto lib_added;
167 }
168 }
169 /* We should be added at the head of the list */
0222e121 170 cds_list_add(&pl->list, &libs);
b467f7a7 171lib_added:
c7292295 172 unlock_trace_events();
0c0686ee 173
f08ebbe2 174 /* trace_events_count - 1: skip dummy */
3b297856 175 DBG("just registered a trace_events section from %p and having %d trace_events (minus dummy trace_event)", trace_events_start, trace_events_count);
0c0686ee
NC
176
177 return 0;
178}
179
fc1caebc 180int trace_event_unregister_lib(struct trace_event * const *trace_events_start)
0c0686ee
NC
181{
182 struct trace_event_lib *lib;
183
c7292295 184 unlock_trace_events();
0222e121 185 cds_list_for_each_entry(lib, &libs, list) {
0c0686ee
NC
186 if(lib->trace_events_start == trace_events_start) {
187 struct trace_event_lib *lib2free = lib;
0222e121 188 cds_list_del(&lib->list);
0c0686ee
NC
189 free(lib2free);
190 break;
191 }
192 }
c7292295 193 unlock_trace_events();
0c0686ee
NC
194
195 return 0;
196}
This page took 0.03637 seconds and 4 git commands to generate.