2 * Copyright (C) 2010 Nils Carlson
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation;
7 * version 2.1 of the License.
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.
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
22 #include <ust/tracepoint.h>
23 #include <ust/tracepoint-internal.h>
25 #include <ust/kcompat/kcompat.h>
28 #include "usterr_signal_safe.h"
30 /* libraries that contain trace_events (struct trace_event_lib) */
31 static CDS_LIST_HEAD(libs
);
33 * Nested mutex is not required here, but provide the same guaranteed
34 * for start/stop iteration vs nested ops as markers and tracepoints.
36 static __thread
int nested_mutex
;
37 static DEFINE_MUTEX(trace_events_mutex
);
40 int trace_event_get_iter_range(struct trace_event
* const **trace_event
,
41 struct trace_event
* const *begin
,
42 struct trace_event
* const *end
);
45 void lock_trace_events(void)
47 if (!(nested_mutex
++))
48 pthread_mutex_lock(&trace_events_mutex
);
52 void unlock_trace_events(void)
54 if (!(--nested_mutex
))
55 pthread_mutex_unlock(&trace_events_mutex
);
59 int lib_get_iter_trace_events(struct trace_event_iter
*iter
)
61 struct trace_event_lib
*iter_lib
;
64 cds_list_for_each_entry(iter_lib
, &libs
, list
) {
65 if (iter_lib
< iter
->lib
)
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
);
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
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.
88 * Called with trace event mutex held.
91 int trace_event_get_iter_range(struct trace_event
* const **trace_event
,
92 struct trace_event
* const *begin
,
93 struct trace_event
* const *end
)
95 if (!*trace_event
&& begin
!= end
)
97 while (*trace_event
>= begin
&& *trace_event
< end
) {
99 (*trace_event
)++; /* skip dummy */
106 static void trace_event_get_iter(struct trace_event_iter
*iter
)
110 found
= lib_get_iter_trace_events(iter
);
113 trace_event_iter_reset(iter
);
116 void trace_event_iter_start(struct trace_event_iter
*iter
)
119 trace_event_get_iter(iter
);
123 * Called with trace event mutex held.
125 void trace_event_iter_next(struct trace_event_iter
*iter
)
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.
133 trace_event_get_iter(iter
);
136 void trace_event_iter_stop(struct trace_event_iter
*iter
)
138 unlock_trace_events();
141 void trace_event_iter_reset(struct trace_event_iter
*iter
)
144 iter
->trace_event
= NULL
;
147 int trace_event_register_lib(struct trace_event
* const *trace_events_start
,
148 int trace_events_count
)
150 struct trace_event_lib
*pl
, *iter
;
152 pl
= (struct trace_event_lib
*) malloc(sizeof(struct trace_event_lib
));
154 pl
->trace_events_start
= trace_events_start
;
155 pl
->trace_events_count
= trace_events_count
;
159 * We sort the libs by struct lib pointer address.
161 cds_list_for_each_entry_reverse(iter
, &libs
, list
) {
162 BUG_ON(iter
== pl
); /* Should never be in the list twice */
164 /* We belong to the location right after iter. */
165 cds_list_add(&pl
->list
, &iter
->list
);
169 /* We should be added at the head of the list */
170 cds_list_add(&pl
->list
, &libs
);
172 unlock_trace_events();
174 /* trace_events_count - 1: skip dummy */
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
);
180 int trace_event_unregister_lib(struct trace_event
* const *trace_events_start
)
182 struct trace_event_lib
*lib
;
184 unlock_trace_events();
185 cds_list_for_each_entry(lib
, &libs
, list
) {
186 if(lib
->trace_events_start
== trace_events_start
) {
187 struct trace_event_lib
*lib2free
= lib
;
188 cds_list_del(&lib
->list
);
193 unlock_trace_events();
This page took 0.033161 seconds and 4 git commands to generate.