#define _UST_TRACEPOINT_H
/*
- * Copyright (C) 2008 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
+ * Copyright (C) 2008-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
* Copyright (C) 2009 Pierre-Marc Fournier
* Copyright (C) 2009 Steven Rostedt <rostedt@goodmis.org>
*
*/
#include <urcu-bp.h>
-#include <ust/core.h>
#include <urcu/list.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct tracepoint_probe {
void *func;
void *data;
*/
#define tracepoint(name, args...) __trace_##name(args)
-/*
- * Library should be made known to libust by declaring TRACEPOINT_LIB in
- * the source file. (Usually at the end of the file, in the outermost
- * scope).
- */
-#define TRACEPOINT_LIB \
- extern struct tracepoint * const __start___tracepoints_ptrs[] __attribute__((weak, visibility("hidden"))); \
- extern struct tracepoint * const __stop___tracepoints_ptrs[] __attribute__((weak, visibility("hidden"))); \
- static struct tracepoint * __tracepoint_ptr_dummy \
- __attribute__((used, section("__tracepoints_ptrs"))); \
- static void __attribute__((constructor)) __tracepoints__init(void) \
- { \
- tracepoint_register_lib(__start___tracepoints_ptrs, \
- __stop___tracepoints_ptrs - \
- __start___tracepoints_ptrs); \
- } \
- \
- static void __attribute__((destructor)) __tracepoints__destroy(void) \
- { \
- tracepoint_unregister_lib(__start___tracepoints_ptrs); \
- }
-
/*
* it_func[0] is never NULL because there is at least one element in the array
* when the array itself is non NULL.
do { \
__tp_it_func = __tp_it_probe_ptr->func; \
__tp_cb_data = __tp_it_probe_ptr->data; \
- ((void(*)(proto))__tp_it_func)(args); \
+ URCU_FORCE_CAST(void(*)(proto), __tp_it_func)(args); \
} while ((++__tp_it_probe_ptr)->func); \
} \
rcu_read_unlock(); \
#define __CHECK_TRACE(name, proto, args) \
do { \
- if (unlikely(__tracepoint_##name.state)) \
+ if (caa_unlikely(__tracepoint_##name.state)) \
__DO_TRACE(&__tracepoint_##name, \
TP_PROTO(proto), TP_ARGS(args)); \
} while (0)
{ \
return __tracepoint_probe_register(#name, (void *)probe,\
data); \
- \
} \
static inline int \
__unregister_trace_##name(void (*probe)(data_proto), void *data)\
extern
int __tracepoint_probe_unregister(const char *name, void *probe, void *data);
-struct tracepoint_lib {
- struct tracepoint * const *tracepoints_start;
- int tracepoints_count;
- struct cds_list_head list;
-};
-
extern
int tracepoint_register_lib(struct tracepoint * const *tracepoints_start,
int tracepoints_count);
extern
int tracepoint_unregister_lib(struct tracepoint * const *tracepoints_start);
+/*
+ * These weak symbols, the constructor, and destructor take care of
+ * registering only _one_ instance of the tracepoints per shared-ojbect
+ * (or for the whole main program).
+ */
+extern struct tracepoint * const __start___tracepoints_ptrs[]
+ __attribute__((weak, visibility("hidden")));
+extern struct tracepoint * const __stop___tracepoints_ptrs[]
+ __attribute__((weak, visibility("hidden")));
+int __tracepoint_registered
+ __attribute__((weak, visibility("hidden")));
+
+static void __attribute__((constructor)) __tracepoints__init(void)
+{
+ if (__tracepoint_registered++)
+ return;
+ tracepoint_register_lib(__start___tracepoints_ptrs,
+ __stop___tracepoints_ptrs -
+ __start___tracepoints_ptrs);
+}
+
+static void __attribute__((destructor)) __tracepoints__destroy(void)
+{
+ if (--__tracepoint_registered)
+ return;
+ tracepoint_unregister_lib(__start___tracepoints_ptrs);
+}
#ifndef TRACEPOINT_EVENT
/*
- * For use with the TRACEPOINT_EVENT macro:
+ * Usage of the TRACEPOINT_EVENT macro:
+ *
+ * In short, an example:
+ *
+ * TRACEPOINT_EVENT(< [com_company_]project_[component_]event >,
+ * TP_PROTO(int arg0, void *arg1, char *string, size_t strlen,
+ * long *arg4, size_t arg4_len),
+ * TP_ARGS(arg0, arg1, string, strlen, arg4, arg4_len),
+ * TP_FIELDS(
+ *
+ * * Integer, printed in base 10 *
+ * ctf_integer(int, field_a, arg0)
+ *
+ * * Integer, printed with 0x base 16 *
+ * ctf_integer_hex(unsigned long, field_d, arg1)
+ *
+ * * Array Sequence, printed as UTF8-encoded array of bytes *
+ * ctf_array_text(char, field_b, string, FIXED_LEN)
+ * ctf_sequence_text(char, field_c, string, size_t, strlen)
+ *
+ * * String, printed as UTF8-encoded string *
+ * ctf_string(field_e, string)
+ *
+ * * Array sequence of signed integer values *
+ * ctf_array(long, field_f, arg4, FIXED_LEN4)
+ * ctf_sequence(long, field_g, arg4, size_t, arg4_len)
+ * )
+ * )
+ *
+ * In more detail:
+ *
+ * We define a tracepoint, its arguments, and its 'fast binary record'
+ * layout.
+ *
+ * Firstly, name your tracepoint via TRACEPOINT_EVENT(name,
+ *
+ * The name should be a proper C99 identifier.
+ * The "name" MUST follow these rules to ensure no namespace clash
+ * occurs:
+ *
+ * For projects (applications and libraries) for which an entity
+ * specific to the project controls the source code and thus its
+ * tracepoints (typically with a scope larger than a single company):
+ *
+ * either:
+ * project_component_event
+ * or:
+ * project_event
*
- * We define a tracepoint, its arguments, its printf format
- * and its 'fast binary record' layout.
+ * Where "project" is the name of the project,
+ * "component" is the name of the project component (which may
+ * include several levels of sub-components, e.g.
+ * ...component_subcomponent_...) where the tracepoint is located
+ * (optional),
+ * "event" is the name of the tracepoint event.
*
- * Firstly, name your tracepoint via TRACEPOINT_EVENT(name : the
- * 'subsystem_event' notation is fine.
+ * For projects issued from a single company wishing to advertise that
+ * the company controls the source code and thus the tracepoints, the
+ * "com_" prefix should be used:
*
- * Think about this whole construct as the
- * 'trace_sched_switch() function' from now on.
+ * either:
+ * com_company_project_component_event
+ * or:
+ * com_company_project_event
*
+ * Where "company" is the name of the company,
+ * "project" is the name of the project,
+ * "component" is the name of the project component (which may
+ * include several levels of sub-components, e.g.
+ * ...component_subcomponent_...) where the tracepoint is located
+ * (optional),
+ * "event" is the name of the tracepoint event.
*
- * TRACEPOINT_EVENT(sched_switch,
+ *
+ * As an example, let's consider a user-space application "someproject"
+ * that would have an internal thread scheduler:
+ *
+ * TRACEPOINT_EVENT(someproject_sched_switch,
*
* *
* * A function has a regular function arguments
* * be saved into the ring buffer. These are the fields
* * that will be exposed to readers.
* *
- * * tp_field(pid_t, prev_pid, prev->pid) is equivalent
+ * * ctf_integer(pid_t, prev_pid, prev->pid) is equivalent
* * to a standard declaraton:
* *
* * pid_t prev_pid;
* *
* * prev_pid = prev->pid;
* *
- * * tp_array(char, prev_comm, TASK_COMM_LEN, prev->comm) is
+ * * ctf_array(char, prev_comm, prev->comm, TASK_COMM_LEN) is
* * equivalent to:
* *
* * char prev_comm[TASK_COMM_LEN];
* *
*
* TP_FIELDS(
- * tp_array(char, prev_comm, TASK_COMM_LEN, prev->comm)
- * tp_field(pid_t, prev_pid, prev->pid)
- * tp_field(int, prev_prio, prev->prio)
- * tp_array(char, next_comm, TASK_COMM_LEN, next->comm)
- * tp_field(pid_t, next_pid, next->pid)
- * tp_field(int, next_prio, next->prio)
+ * ctf_array(char, prev_comm, prev->comm, TASK_COMM_LEN)
+ * ctf_integer(pid_t, prev_pid, prev->pid)
+ * ctf_integer(int, prev_prio, prev->prio)
+ * ctf_array(char, next_comm, next->comm, TASK_COMM_LEN)
+ * ctf_integer(pid_t, next_pid, next->pid)
+ * ctf_integer(int, next_prio, next->prio)
* )
- * );
+ * )
+ *
+ * Do _NOT_ add comma (,) nor semicolon (;) after the TRACEPOINT_EVENT
+ * declaration.
+ *
+ * The TRACEPOINT_SYSTEM must be defined when declaring a
+ * TRACEPOINT_EVENT. See ust/tracepoint-event.h for information about
+ * usage of other macros controlling TRACEPOINT_EVENT.
*/
#define TRACEPOINT_EVENT(name, proto, args, fields) \
#define TRACEPOINT_EVENT_INSTANCE_NOARGS(template, name) \
_DECLARE_TRACEPOINT_NOARGS(name)
+#endif /* #ifndef TRACEPOINT_EVENT */
+#ifndef TRACEPOINT_LOGLEVEL
-#define TRACEPOINT_EVENT_LIB \
- extern struct trace_event * const __start___trace_events_ptrs[] \
- __attribute__((weak, visibility("hidden"))); \
- extern struct trace_event * const __stop___trace_events_ptrs[] \
- __attribute__((weak, visibility("hidden"))); \
- static struct trace_event * __event_ptrs_dummy \
- __attribute__((used, section("__trace_events_ptrs"))); \
- static void __attribute__((constructor)) \
- __trace_events__init(void) \
- { \
- trace_event_register_lib(__start___trace_events_ptrs, \
- __stop___trace_events_ptrs - \
- __start___trace_events_ptrs); \
- } \
- \
- static void __attribute__((destructor)) \
- __trace_event__destroy(void) \
- { \
- trace_event_unregister_lib(__start___trace_events_ptrs);\
- }
-
-struct trace_event {
- const char *name;
-};
+/*
+ * Tracepoint Loglevel Declaration Facility
+ *
+ * This is a place-holder the tracepoint loglevel declaration,
+ * overridden by the tracer implementation.
+ *
+ * Typical use of these loglevels:
+ *
+ * 1) Declare the mapping between loglevel names and an integer values
+ * within TRACEPOINT_LOGLEVEL_ENUM, using TP_LOGLEVEL for each tuple.
+ * Do _NOT_ add comma (,) nor semicolon (;) between the
+ * TRACEPOINT_LOGLEVEL_ENUM entries. Do _NOT_ add comma (,) nor
+ * semicolon (;) after the TRACEPOINT_LOGLEVEL_ENUM declaration. The
+ * name should be a proper C99 identifier.
+ *
+ * TRACEPOINT_LOGLEVEL_ENUM(
+ * TP_LOGLEVEL( < loglevel_name >, < value > )
+ * TP_LOGLEVEL( < loglevel_name >, < value > )
+ * ...
+ * )
+ *
+ * e.g.:
+ *
+ * TRACEPOINT_LOGLEVEL_ENUM(
+ * TP_LOGLEVEL(LOG_EMERG, 0)
+ * TP_LOGLEVEL(LOG_ALERT, 1)
+ * TP_LOGLEVEL(LOG_CRIT, 2)
+ * TP_LOGLEVEL(LOG_ERR, 3)
+ * TP_LOGLEVEL(LOG_WARNING, 4)
+ * TP_LOGLEVEL(LOG_NOTICE, 5)
+ * TP_LOGLEVEL(LOG_INFO, 6)
+ * TP_LOGLEVEL(LOG_DEBUG, 7)
+ * )
+ *
+ * 2) Then, declare tracepoint loglevels for tracepoints. A
+ * TRACEPOINT_EVENT should be declared prior to the the
+ * TRACEPOINT_LOGLEVEL for a given tracepoint name. The first field
+ * is the name of the tracepoint, the second field is the loglevel
+ * name.
+ *
+ * TRACEPOINT_LOGLEVEL(< [com_company_]project_[component_]event >,
+ * < loglevel_name >)
+ *
+ * The TRACEPOINT_SYSTEM must be defined when declaring a
+ * TRACEPOINT_LOGLEVEL_ENUM and TRACEPOINT_LOGLEVEL. The tracepoint
+ * loglevel enumeration apply to the entire TRACEPOINT_SYSTEM. Only one
+ * tracepoint loglevel enumeration should be declared per tracepoint
+ * system.
+ */
-struct trace_event_lib {
- struct trace_event * const *trace_events_start;
- int trace_events_count;
- struct cds_list_head list;
-};
+#define TRACEPOINT_LOGLEVEL_ENUM()
+#define TRACEPOINT_LOGLEVEL(name, loglevel)
-extern
-int trace_event_register_lib(struct trace_event * const *start_trace_events,
- int trace_event_count);
-extern
-int trace_event_unregister_lib(struct trace_event * const *start_trace_events);
+#endif /* #ifndef TRACEPOINT_LOGLEVEL */
-#endif /* #ifndef TRACEPOINT_EVENT */
+#ifdef __cplusplus
+}
+#endif
#endif /* _UST_TRACEPOINT_H */