diff options
author | Avik Sil <avik.sil@linaro.org> | 2011-03-31 11:06:38 +0000 |
---|---|---|
committer | Avik Sil <avik.sil@linaro.org> | 2011-03-31 11:06:38 +0000 |
commit | ebb688e3183bd5891312bdb8f4e2f520d70b36b6 (patch) | |
tree | c30d1abefaccc8cd1baa4944aae3348668e13bde /include | |
parent | 8061f3a885ec3538bf405ff3957c205b1ab2aae4 (diff) | |
parent | b2afcd30fff4c24290a63a2497de301864d9726d (diff) |
Merge remote branch 'lttng/2.6.38-lttng-0.247'
Conflicts:
arch/arm/kernel/traps.c
arch/arm/mach-omap2/clock34xx.c
arch/arm/mach-omap2/pm34xx.c
Diffstat (limited to 'include')
43 files changed, 1356 insertions, 10 deletions
diff --git a/include/asm-generic/trace-clock.h b/include/asm-generic/trace-clock.h new file mode 100644 index 00000000000..138ac9b7c54 --- /dev/null +++ b/include/asm-generic/trace-clock.h @@ -0,0 +1,76 @@ +#ifndef _ASM_GENERIC_TRACE_CLOCK_H +#define _ASM_GENERIC_TRACE_CLOCK_H + +/* + * include/asm-generic/trace-clock.h + * + * Copyright (C) 2007 - Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca) + * + * Generic tracing clock for architectures without TSC. + */ + +#include <linux/param.h> /* For HZ */ +#include <asm/atomic.h> + +#define TRACE_CLOCK_SHIFT 13 + +/* + * Number of hardware clock bits. The higher order bits are expected to be 0. + * If the hardware clock source has more than 32 bits, the bits higher than the + * 32nd will be truncated by a cast to a 32 bits unsigned. Range : 1 - 32. + * (too few bits would be unrealistic though, since we depend on the timer to + * detect the overflows). + */ +#define TC_HW_BITS 32 + +/* Expected maximum interrupt latency in ms : 15ms, *2 for security */ +#define TC_EXPECTED_INTERRUPT_LATENCY 30 + +extern atomic_long_t trace_clock_var; + +static inline u32 trace_clock_read32(void) +{ + return (u32)atomic_long_add_return(1, &trace_clock_var); +} + +#ifdef CONFIG_HAVE_TRACE_CLOCK_32_TO_64 +extern u64 trace_clock_read_synthetic_tsc(void); +extern void get_synthetic_tsc(void); +extern void put_synthetic_tsc(void); + +static inline u64 trace_clock_read64(void) +{ + return trace_clock_read_synthetic_tsc(); +} +#else +static inline void get_synthetic_tsc(void) +{ +} + +static inline void put_synthetic_tsc(void) +{ +} + +static inline u64 trace_clock_read64(void) +{ + return atomic_long_add_return(1, &trace_clock_var); +} +#endif + +static inline unsigned int trace_clock_frequency(void) +{ + return HZ << TRACE_CLOCK_SHIFT; +} + +static inline u32 trace_clock_freq_scale(void) +{ + return 1; +} + +extern void get_trace_clock(void); +extern void put_trace_clock(void); + +static inline void set_trace_clock_is_sync(int state) +{ +} +#endif /* _ASM_GENERIC_TRACE_CLOCK_H */ diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index fe77e3395b4..69347177e65 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -167,6 +167,10 @@ CPU_KEEP(exit.data) \ MEM_KEEP(init.data) \ MEM_KEEP(exit.data) \ + . = ALIGN(128); \ + VMLINUX_SYMBOL(__start___markers) = .; \ + *(__markers) \ + VMLINUX_SYMBOL(__stop___markers) = .; \ STRUCT_ALIGN(); \ *(__tracepoints) \ /* implement dynamic printk debug */ \ diff --git a/include/linux/Kbuild b/include/linux/Kbuild index b0ada6f37dd..a63b8001b7e 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -42,6 +42,7 @@ header-y += adfs_fs.h header-y += affs_hardblocks.h header-y += agpgart.h header-y += aio_abi.h +header-y += align.h header-y += apm_bios.h header-y += arcfb.h header-y += atalk.h diff --git a/include/linux/align.h b/include/linux/align.h new file mode 100644 index 00000000000..f34d42e625a --- /dev/null +++ b/include/linux/align.h @@ -0,0 +1,60 @@ +#ifndef _LINUX_ALIGN_H +#define _LINUX_ALIGN_H + +#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) +#define __ALIGN_KERNEL_MASK(x, mask) \ + (((x) + (mask)) & ~(mask)) + +#ifdef __KERNEL__ + +#include <linux/types.h> + +#define ALIGN(x, a) __ALIGN_KERNEL(x, a) +#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK(x, mask) +#define PTR_ALIGN(p, a) ((typeof(p)) ALIGN((unsigned long) (p), a)) +#define ALIGN_FLOOR(x, a) __ALIGN_FLOOR_MASK(x, (typeof(x)) (a) - 1) +#define __ALIGN_FLOOR_MASK(x, mask) ((x) & ~(mask)) +#define PTR_ALIGN_FLOOR(p, a) \ + ((typeof(p)) ALIGN_FLOOR((unsigned long) (p), a)) +#define IS_ALIGNED(x, a) (((x) & ((typeof(x)) (a) - 1)) == 0) + +/* + * Align pointer on natural object alignment. + */ +#define object_align(obj) PTR_ALIGN(obj, __alignof__(*(obj))) +#define object_align_floor(obj) PTR_ALIGN_FLOOR(obj, __alignof__(*(obj))) + +/** + * offset_align - Calculate the offset needed to align an object on its natural + * alignment towards higher addresses. + * @align_drift: object offset from an "alignment"-aligned address. + * @alignment: natural object alignment. Must be non-zero, power of 2. + * + * Returns the offset that must be added to align towards higher + * addresses. + */ +#define offset_align(align_drift, alignment) \ + ({ \ + MAYBE_BUILD_BUG_ON((alignment) == 0 \ + || ((alignment) & ((alignment) - 1))); \ + (((alignment) - (align_drift)) & ((alignment) - 1)); \ + }) + +/** + * offset_align_floor - Calculate the offset needed to align an object + * on its natural alignment towards lower addresses. + * @align_drift: object offset from an "alignment"-aligned address. + * @alignment: natural object alignment. Must be non-zero, power of 2. + * + * Returns the offset that must be substracted to align towards lower addresses. + */ +#define offset_align_floor(align_drift, alignment) \ + ({ \ + MAYBE_BUILD_BUG_ON((alignment) == 0 \ + || ((alignment) & ((alignment) - 1))); \ + (((align_drift) - (alignment)) & ((alignment) - 1); \ + }) + +#endif /* __KERNEL__ */ + +#endif diff --git a/include/linux/idle.h b/include/linux/idle.h new file mode 100644 index 00000000000..75bd2a422c8 --- /dev/null +++ b/include/linux/idle.h @@ -0,0 +1,19 @@ +/* + * include/linux/idle.h - generic idle definition + * + */ +#ifndef _LINUX_IDLE_H_ +#define _LINUX_IDLE_H_ + +#include <linux/notifier.h> + +enum idle_val { + IDLE_START = 1, + IDLE_END = 2, +}; + +int notify_idle(enum idle_val val); +void register_idle_notifier(struct notifier_block *n); +void unregister_idle_notifier(struct notifier_block *n); + +#endif /* _LINUX_IDLE_H_ */ diff --git a/include/linux/immediate.h b/include/linux/immediate.h new file mode 100644 index 00000000000..0d62cab5c2e --- /dev/null +++ b/include/linux/immediate.h @@ -0,0 +1,93 @@ +#ifndef _LINUX_IMMEDIATE_H +#define _LINUX_IMMEDIATE_H + +/* + * Immediate values, can be updated at runtime and save cache lines. + * + * (C) Copyright 2007 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> + * + * Dual BSD/GPL v2 license. + */ + +#ifdef CONFIG_IMMEDIATE + +struct __imv { + unsigned long var; /* Pointer to the identifier variable of the + * immediate value + */ + unsigned long imv; /* + * Pointer to the memory location of the + * immediate value within the instruction. + */ + unsigned char size; /* Type size. */ +} __attribute__ ((packed)); + +#include <asm/immediate.h> + +/** + * imv_set - set immediate variable (with locking) + * @name: immediate value name + * @i: required value + * + * Sets the value of @name, taking the module_mutex if required by + * the architecture. + */ +#define imv_set(name, i) \ + do { \ + name##__imv = (i); \ + core_imv_update(); \ + module_imv_update(); \ + } while (0) + +/* + * Internal update functions. + */ +extern void core_imv_update(void); +extern void imv_update_range(const struct __imv *begin, + const struct __imv *end); + +#else + +/* + * Generic immediate values: a simple, standard, memory load. + */ + +/** + * imv_read - read immediate variable + * @name: immediate value name + * + * Reads the value of @name. + */ +#define imv_read(name) _imv_read(name) + +/** + * imv_set - set immediate variable (with locking) + * @name: immediate value name + * @i: required value + * + * Sets the value of @name, taking the module_mutex if required by + * the architecture. + */ +#define imv_set(name, i) (name##__imv = (i)) + +static inline void core_imv_update(void) { } +static inline void module_imv_update(void) { } + +#endif + +#define DECLARE_IMV(type, name) extern __typeof__(type) name##__imv +#define DEFINE_IMV(type, name) __typeof__(type) name##__imv + +#define EXPORT_IMV_SYMBOL(name) EXPORT_SYMBOL(name##__imv) +#define EXPORT_IMV_SYMBOL_GPL(name) EXPORT_SYMBOL_GPL(name##__imv) + +/** + * _imv_read - Read immediate value with standard memory load. + * @name: immediate value name + * + * Force a data read of the immediate value instead of the immediate value + * based mechanism. Useful for __init and __exit section data read. + */ +#define _imv_read(name) (name##__imv) + +#endif diff --git a/include/linux/irqnr.h b/include/linux/irqnr.h index 3bc4dcab6e8..3f8c992934a 100644 --- a/include/linux/irqnr.h +++ b/include/linux/irqnr.h @@ -24,6 +24,7 @@ #else /* CONFIG_GENERIC_HARDIRQS */ extern int nr_irqs; +struct irq_desc; extern struct irq_desc *irq_to_desc(unsigned int irq); unsigned int irq_get_next_irq(unsigned int offset); diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 2fe6e84894a..eff75504cf1 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -4,8 +4,8 @@ /* * 'kernel.h' contains some often-used function prototypes etc */ -#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) -#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) + +#include <linux/align.h> #ifdef __KERNEL__ @@ -37,11 +37,6 @@ #define STACK_MAGIC 0xdeadbeef -#define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) -#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask)) -#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) -#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) - #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) /* diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index b5021db2185..914f0196130 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -15,6 +15,7 @@ #include <linux/sched.h> #include <linux/mm.h> #include <linux/preempt.h> +#include <linux/marker.h> #include <linux/msi.h> #include <linux/slab.h> #include <linux/rcupdate.h> diff --git a/include/linux/ltt-channels.h b/include/linux/ltt-channels.h new file mode 100644 index 00000000000..d8d368d5440 --- /dev/null +++ b/include/linux/ltt-channels.h @@ -0,0 +1,108 @@ +#ifndef _LTT_CHANNELS_H +#define _LTT_CHANNELS_H + +/* + * Copyright (C) 2008 Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca) + * + * Dynamic tracer channel allocation. + + * Dual LGPL v2.1/GPL v2 license. + */ + +#include <linux/limits.h> +#include <linux/kref.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/ltt-core.h> + +#define EVENTS_PER_CHANNEL 65536 + +/* + * Forward declaration of locking-specific per-cpu buffer structure. + */ +struct ltt_chanbuf; +struct ltt_trace; +struct ltt_serialize_closure; +struct ltt_probe_private_data; + +/* Serialization callback '%k' */ +typedef size_t (*ltt_serialize_cb)(struct ltt_chanbuf *buf, size_t buf_offset, + struct ltt_serialize_closure *closure, + void *serialize_private, + unsigned int stack_pos_ctx, + int *largest_align, + const char *fmt, va_list *args); + +struct ltt_probe_private_data { + struct ltt_trace *trace; /* + * Target trace, for metadata + * or statedump. + */ + ltt_serialize_cb serializer; /* + * Serialization function override. + */ + void *serialize_private; /* + * Private data for serialization + * functions. + */ +}; + +struct ltt_chan_alloc { + unsigned long buf_size; /* Size of the buffer */ + unsigned long sb_size; /* Sub-buffer size */ + unsigned int sb_size_order; /* Order of sub-buffer size */ + unsigned int n_sb_order; /* Number of sub-buffers per buffer */ + int extra_reader_sb:1; /* Bool: has extra reader subbuffer */ + struct ltt_chanbuf *buf; /* Channel per-cpu buffers */ + + struct kref kref; /* Reference count */ + unsigned long n_sb; /* Number of sub-buffers */ + struct dentry *parent; /* Associated parent dentry */ + struct dentry *ascii_dentry; /* Text output dentry */ + struct ltt_trace *trace; /* Associated trace */ + char filename[NAME_MAX]; /* Filename for channel files */ +}; + +struct ltt_chan { + struct ltt_chan_alloc a; /* Parent. First field. */ + int overwrite:1; + int active:1; + unsigned long commit_count_mask; /* + * Commit count mask, removing + * the MSBs corresponding to + * bits used to represent the + * subbuffer index. + */ + unsigned long switch_timer_interval; +}; + +struct ltt_channel_setting { + unsigned int sb_size; + unsigned int n_sb; + struct kref kref; /* Number of references to structure content */ + struct list_head list; + unsigned int index; /* index of channel in trace channel array */ + u16 free_event_id; /* Next event ID to allocate */ + char name[PATH_MAX]; +}; + +int ltt_channels_register(const char *name); +int ltt_channels_unregister(const char *name, int compacting); +int ltt_channels_set_default(const char *name, + unsigned int subbuf_size, + unsigned int subbuf_cnt); +const char *ltt_channels_get_name_from_index(unsigned int index); +int ltt_channels_get_index_from_name(const char *name); +int ltt_channels_trace_ref(void); +struct ltt_chan *ltt_channels_trace_alloc(unsigned int *nr_channels, + int overwrite, int active); +void ltt_channels_trace_free(struct ltt_chan *channels, + unsigned int nr_channels); +void ltt_channels_trace_set_timer(struct ltt_chan *chan, + unsigned long interval); + +int _ltt_channels_get_event_id(const char *channel, const char *name); +int ltt_channels_get_event_id(const char *channel, const char *name); +void _ltt_channels_reset_event_ids(void); + +#endif /* _LTT_CHANNELS_H */ diff --git a/include/linux/ltt-core.h b/include/linux/ltt-core.h new file mode 100644 index 00000000000..d02c1e64544 --- /dev/null +++ b/include/linux/ltt-core.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2005-2010 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) + * + * This contains the core definitions for the Linux Trace Toolkit. + * + * Dual LGPL v2.1/GPL v2 license. + */ + +#ifndef LTT_CORE_H +#define LTT_CORE_H + +/* Keep track of trap nesting inside LTT */ +DECLARE_PER_CPU(unsigned int, ltt_nesting); + +#ifndef MAYBE_BUILD_BUG_ON +#define MAYBE_BUILD_BUG_ON(cond) \ + do { \ + if (__builtin_constant_p(cond)) \ + BUILD_BUG_ON(cond); \ + } while (0) +#endif + +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS + +/* + * Calculate the offset needed to align the type. + * size_of_type must be non-zero. + */ +static inline unsigned int ltt_align(size_t align_drift, size_t size_of_type) +{ + return offset_align(align_drift, min(sizeof(void *), size_of_type)); +} +/* Default arch alignment */ +#define LTT_ALIGN + +static inline int ltt_get_alignment(void) +{ + return sizeof(void *); +} + +extern unsigned int ltt_fmt_largest_align(size_t align_drift, const char *fmt); + +#else + +static inline unsigned int ltt_align(size_t align_drift, + size_t size_of_type) +{ + return 0; +} + +#define LTT_ALIGN __attribute__((packed)) + +static inline int ltt_get_alignment(void) +{ + return 0; +} + +static inline unsigned int ltt_fmt_largest_align(size_t align_drift, + const char *fmt) +{ + return 0; +} + +#endif /* HAVE_EFFICIENT_UNALIGNED_ACCESS */ + +#endif /* LTT_CORE_H */ diff --git a/include/linux/marker.h b/include/linux/marker.h new file mode 100644 index 00000000000..c50c66d09f0 --- /dev/null +++ b/include/linux/marker.h @@ -0,0 +1,273 @@ +#ifndef _LINUX_MARKER_H +#define _LINUX_MARKER_H + +/* + * Code markup for dynamic and static tracing. + * + * See Documentation/marker.txt. + * + * (C) Copyright 2006 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + */ + +#include <stdarg.h> +#include <linux/types.h> +#include <linux/immediate.h> + +struct module; +struct marker; +struct marker_probe_array; + +/** + * marker_probe_func - Type of a marker probe function + * @mdata: marker data + * @probe_private: probe private data + * @call_private: call site private data + * @fmt: format string + * @args: variable argument list pointer. Use a pointer to overcome C's + * inability to pass this around as a pointer in a portable manner in + * the callee otherwise. + * + * Type of marker probe functions. They receive the mdata and need to parse the + * format string to recover the variable argument list. + */ +typedef void marker_probe_func(const struct marker *mdata, + void *probe_private, void *call_private, + const char *fmt, va_list *args); + +struct marker_probe_closure { + marker_probe_func *func; /* Callback */ + void *probe_private; /* Private probe data */ +}; + +struct marker { + const char *channel; /* Name of channel where to send data */ + const char *name; /* Marker name */ + const char *format; /* Marker format string, describing the + * variable argument list. + */ + DEFINE_IMV(char, state);/* Immediate value state. */ + char ptype; /* probe type : 0 : single, 1 : multi */ + /* Probe wrapper */ + u16 channel_id; /* Numeric channel identifier, dynamic */ + u16 event_id; /* Numeric event identifier, dynamic */ + void (*call)(const struct marker *mdata, void *call_private, ...); + struct marker_probe_closure single; + struct marker_probe_array *multi; + const char *tp_name; /* Optional tracepoint name */ + void *tp_cb; /* Optional tracepoint callback */ +} __attribute__((aligned(128))); /* + * Aligned on 128 bytes because it is + * globally visible and gcc happily + * align these on the structure size. + * Keep in sync with vmlinux.lds.h. + */ + +#ifdef CONFIG_MARKERS + +#define _DEFINE_MARKER(channel, name, tp_name_str, tp_cb, format) \ + static const char __mstrtab_##channel##_##name[] \ + __attribute__((section("__markers_strings"))) \ + = #channel "\0" #name "\0" format; \ + static struct marker __mark_##channel##_##name \ + __attribute__((section("__markers"), aligned(128))) = \ + { __mstrtab_##channel##_##name, \ + &__mstrtab_##channel##_##name[sizeof(#channel)], \ + &__mstrtab_##channel##_##name[sizeof(#channel) + \ + sizeof(#name)], \ + 0, 0, 0, 0, marker_probe_cb, \ + { __mark_empty_function, NULL}, \ + NULL, tp_name_str, tp_cb } + +#define DEFINE_MARKER(channel, name, format) \ + _DEFINE_MARKER(channel, name, NULL, NULL, format) + +#define DEFINE_MARKER_TP(channel, name, tp_name, tp_cb, format) \ + _DEFINE_MARKER(channel, name, #tp_name, tp_cb, format) + +/* + * Make sure the alignment of the structure in the __markers section will + * not add unwanted padding between the beginning of the section and the + * structure. Force alignment to the same alignment as the section start. + * + * The "generic" argument controls which marker enabling mechanism must be used. + * If generic is true, a variable read is used. + * If generic is false, immediate values are used. + */ +#define __trace_mark(generic, channel, name, call_private, format, args...) \ + do { \ + DEFINE_MARKER(channel, name, format); \ + __mark_check_format(format, ## args); \ + if (!generic) { \ + if (unlikely(imv_read( \ + __mark_##channel##_##name.state))) \ + (*__mark_##channel##_##name.call) \ + (&__mark_##channel##_##name, \ + call_private, ## args); \ + } else { \ + if (unlikely(_imv_read( \ + __mark_##channel##_##name.state))) \ + (*__mark_##channel##_##name.call) \ + (&__mark_##channel##_##name, \ + call_private, ## args); \ + } \ + } while (0) + +#define __trace_mark_tp(channel, name, call_private, tp_name, tp_cb, \ + format, args...) \ + do { \ + void __check_tp_type(void) \ + { \ + register_trace_##tp_name(tp_cb, NULL); \ + } \ + DEFINE_MARKER_TP(channel, name, tp_name, tp_cb, format);\ + __mark_check_format(format, ## args); \ + (*__mark_##channel##_##name.call)(&__mark_##channel##_##name, \ + call_private, ## args); \ + } while (0) + +extern void marker_update_probe_range(struct marker *begin, + struct marker *end); + +#define GET_MARKER(channel, name) (__mark_##channel##_##name) + +#else /* !CONFIG_MARKERS */ +#define DEFINE_MARKER(channel, name, tp_name, tp_cb, format) +#define __trace_mark(generic, channel, name, call_private, format, args...) \ + __mark_check_format(format, ## args) +#define __trace_mark_tp(channel, name, call_private, tp_name, tp_cb, \ + format, args...) \ + do { \ + void __check_tp_type(void) \ + { \ + register_trace_##tp_name(tp_cb, NULL); \ + } \ + __mark_check_format(format, ## args); \ + } while (0) +static inline void marker_update_probe_range(struct marker *begin, + struct marker *end) +{ } +#define GET_MARKER(channel, name) +#endif /* CONFIG_MARKERS */ + +/** + * trace_mark - Marker using code patching + * @channel: marker channel (where to send the data), not quoted. + * @name: marker name, not quoted. + * @format: format string + * @args...: variable argument list + * + * Places a marker using optimized code patching technique (imv_read()) + * to be enabled when immediate values are present. + */ +#define trace_mark(channel, name, format, args...) \ + __trace_mark(0, channel, name, NULL, format, ## args) + +/** + * _trace_mark - Marker using variable read + * @channel: marker channel (where to send the data), not quoted. + * @name: marker name, not quoted. + * @format: format string + * @args...: variable argument list + * + * Places a marker using a standard memory read (_imv_read()) to be + * enabled. Should be used for markers in code paths where instruction + * modification based enabling is not welcome. (__init and __exit functions, + * lockdep, some traps, printk). + */ +#define _trace_mark(channel, name, format, args...) \ + __trace_mark(1, channel, name, NULL, format, ## args) + +/** + * trace_mark_tp - Marker in a tracepoint callback + * @channel: marker channel (where to send the data), not quoted. + * @name: marker name, not quoted. + * @tp_name: tracepoint name, not quoted. + * @tp_cb: tracepoint callback. Should have an associated global symbol so it + * is not optimized away by the compiler (should not be static). + * @format: format string + * @args...: variable argument list + * + * Places a marker in a tracepoint callback. + */ +#define trace_mark_tp(channel, name, tp_name, tp_cb, format, args...) \ + __trace_mark_tp(channel, name, NULL, tp_name, tp_cb, format, ## args) + +/** + * MARK_NOARGS - Format string for a marker with no argument. + */ +#define MARK_NOARGS " " + +extern void lock_markers(void); +extern void unlock_markers(void); + +extern void markers_compact_event_ids(void); + +/* To be used for string format validity checking with gcc */ +static inline void __printf(1, 2) ___mark_check_format(const char *fmt, ...) +{ +} + +#define __mark_check_format(format, args...) \ + do { \ + if (0) \ + ___mark_check_format(format, ## args); \ + } while (0) + +extern marker_probe_func __mark_empty_function; + +extern void marker_probe_cb(const struct marker *mdata, + void *call_private, ...); + +/* + * Connect a probe to a marker. + * private data pointer must be a valid allocated memory address, or NULL. + */ +extern int marker_probe_register(const char *channel, const char *name, + const char *format, marker_probe_func *probe, void *probe_private); + +/* + * Returns the private data given to marker_probe_register. + */ +extern int marker_probe_unregister(const char *channel, const char *name, + marker_probe_func *probe, void *probe_private); +/* + * Unregister a marker by providing the registered private data. + */ +extern int marker_probe_unregister_private_data(marker_probe_func *probe, + void *probe_private); + +extern void *marker_get_private_data(const char *channel, const char *name, + marker_probe_func *probe, int num); + +const char *marker_get_name_from_id(u16 channel_id, u16 event_id); +const char *marker_get_fmt_from_id(u16 channel_id, u16 event_id); + +/* + * marker_synchronize_unregister must be called between the last marker probe + * unregistration and the first one of + * - the end of module exit function + * - the free of any resource used by the probes + * to ensure the code and data are valid for any possibly running probes. + */ +#define marker_synchronize_unregister() synchronize_sched() + +struct marker_iter { + struct module *module; + struct marker *marker; +}; + +extern void marker_iter_start(struct marker_iter *iter); +extern void marker_iter_next(struct marker_iter *iter); +extern void marker_iter_stop(struct marker_iter *iter); +extern void marker_iter_reset(struct marker_iter *iter); +extern int marker_get_iter_range(struct marker **marker, struct marker *begin, + struct marker *end); +extern int _is_marker_enabled(const char *channel, const char *name); +extern int is_marker_enabled(const char *channel, const char *name); +extern int is_marker_present(const char *channel, const char *name); +extern void marker_update_probes(void); + +#endif diff --git a/include/linux/module.h b/include/linux/module.h index 5de42043dff..7ce98816694 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -15,6 +15,7 @@ #include <linux/stringify.h> #include <linux/kobject.h> #include <linux/moduleparam.h> +#include <linux/marker.h> #include <linux/tracepoint.h> #include <linux/percpu.h> @@ -376,6 +377,10 @@ struct module /* The command line arguments (may be mangled). People like keeping pointers to this stuff */ char *args; +#ifdef CONFIG_MARKERS + struct marker *markers; + unsigned int num_markers; +#endif #ifdef CONFIG_TRACEPOINTS struct tracepoint * const *tracepoints_ptrs; unsigned int num_tracepoints; @@ -574,6 +579,10 @@ int register_module_notifier(struct notifier_block * nb); int unregister_module_notifier(struct notifier_block * nb); extern void print_modules(void); +extern void list_modules(void *call_data); + +extern void module_update_markers(void); +extern int module_get_iter_markers(struct marker_iter *iter); extern void module_update_tracepoints(void); extern int module_get_iter_tracepoints(struct tracepoint_iter *iter); @@ -694,6 +703,14 @@ static inline void print_modules(void) { } +static inline void list_modules(void *call_data) +{ +} + +static inline void module_update_markers(void) +{ +} + static inline void module_update_tracepoints(void) { } @@ -702,6 +719,11 @@ static inline int module_get_iter_tracepoints(struct tracepoint_iter *iter) { return 0; } + +static inline int module_get_iter_markers(struct marker_iter *iter) +{ + return 0; +} #endif /* CONFIG_MODULES */ #ifdef CONFIG_SYSFS diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 71caf7a5e6c..436449c81e2 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -44,6 +44,7 @@ #include <linux/rculist.h> #include <linux/dmaengine.h> #include <linux/workqueue.h> +#include <trace/net.h> #include <linux/ethtool.h> #include <net/net_namespace.h> diff --git a/include/linux/poll.h b/include/linux/poll.h index 1a2ccd6f382..09e1375d768 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -81,6 +81,8 @@ static inline int poll_schedule(struct poll_wqueues *pwq, int state) return poll_schedule_timeout(pwq, state, NULL, 0); } +extern void poll_wait_set_exclusive(poll_table *p); + /* * Scaleable version of the fd_set. */ diff --git a/include/linux/rculist.h b/include/linux/rculist.h index 2dea94fc440..52d6122f174 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -241,6 +241,11 @@ static inline void list_splice_init_rcu(struct list_head *list, #define list_first_entry_rcu(ptr, type, member) \ list_entry_rcu((ptr)->next, type, member) +#define __list_for_each_entry_rcu(pos, head, member) \ + for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry_rcu(pos->member.next, typeof(*pos), member)) + /** * list_for_each_entry_rcu - iterate over rcu list of given type * @pos: the type * to use as a loop cursor. @@ -288,6 +293,23 @@ static inline void list_splice_init_rcu(struct list_head *list, pos = list_entry_rcu(pos->member.next, typeof(*pos), member)) /** + * list_for_each_entry_continue_rcu - continue iteration over typed rcu list + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + * It continues an iteration initiated by list_for_each_entry_rcu(). + */ +#define list_for_each_entry_continue_rcu(pos, head, member) \ + for (pos = list_entry_rcu(pos->member.next, typeof(*pos), member); \ + prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry_rcu(pos->member.next, typeof(*pos), member)) + + +/** * hlist_del_rcu - deletes entry from hash list without re-initialization * @n: the element to delete from the hash list. * diff --git a/include/linux/sched.h b/include/linux/sched.h index 777d8a5ed06..d6cde3a56cc 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2620,6 +2620,9 @@ static inline unsigned long rlimit_max(unsigned int limit) return task_rlimit_max(current, limit); } +extern void clear_kernel_trace_flag_all_tasks(void); +extern void set_kernel_trace_flag_all_tasks(void); + #endif /* __KERNEL__ */ #endif diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h index 03c0232b416..34f8680a7b9 100644 --- a/include/linux/seq_file.h +++ b/include/linux/seq_file.h @@ -153,4 +153,25 @@ extern struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head, extern struct hlist_node *seq_hlist_next_rcu(void *v, struct hlist_head *head, loff_t *ppos); + +/* + * Helpers for iteration over a list sorted by ascending head pointer address. + * To be used in contexts where preemption cannot be disabled to insure to + * continue iteration on a modified list starting at the same location where it + * stopped, or at a following location. It insures that the lost information + * will only be in elements added/removed from the list between iterations. + * void *pos is only used to get the next list element and may not be a valid + * list_head anymore when given to seq_sorted_list_start() or + * seq_sorted_list_start_head(). + */ +extern struct list_head *seq_sorted_list_start(struct list_head *head, + loff_t *ppos); +extern struct list_head *seq_sorted_list_start_head(struct list_head *head, + loff_t *ppos); +/* + * next must be called with an existing p node + */ +extern struct list_head *seq_sorted_list_next(void *p, struct list_head *head, + loff_t *ppos); + #endif diff --git a/include/linux/swap.h b/include/linux/swap.h index 4d559325d91..3d2cd9b993c 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -341,6 +341,7 @@ extern int swap_type_of(dev_t, sector_t, struct block_device **); extern unsigned int count_swap_pages(int, int); extern sector_t map_swap_page(struct page *, struct block_device **); extern sector_t swapdev_block(int, pgoff_t); +extern struct swap_info_struct *get_swap_info_struct(unsigned); extern int reuse_swap_page(struct page *); extern int try_to_free_swap(struct page *); struct backing_dev_info; @@ -384,6 +385,8 @@ static inline void mem_cgroup_uncharge_swap(swp_entry_t ent) } #endif +extern void ltt_dump_swap_files(void *call_data); + #else /* CONFIG_SWAP */ #define nr_swap_pages 0L @@ -508,6 +511,10 @@ mem_cgroup_count_swap_user(swp_entry_t ent, struct page **pagep) } #endif +static inline void ltt_dump_swap_files(void *call_data) +{ +} + #endif /* CONFIG_SWAP */ #endif /* __KERNEL__*/ #endif /* _LINUX_SWAP_H */ diff --git a/include/linux/swapops.h b/include/linux/swapops.h index cd42e30b7c6..436a327d803 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h @@ -76,6 +76,14 @@ static inline pte_t swp_entry_to_pte(swp_entry_t entry) return __swp_entry_to_pte(arch_entry); } +static inline swp_entry_t page_swp_entry(struct page *page) +{ + swp_entry_t entry; + VM_BUG_ON(!PageSwapCache(page)); + entry.val = page_private(page); + return entry; +} + #ifdef CONFIG_MIGRATION static inline swp_entry_t make_migration_entry(struct page *page, int write) { diff --git a/include/linux/time.h b/include/linux/time.h index 1e6d3b59238..8ae676f1e7c 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -292,6 +292,8 @@ struct itimerval { #define CLOCK_MONOTONIC_RAW 4 #define CLOCK_REALTIME_COARSE 5 #define CLOCK_MONOTONIC_COARSE 6 +#define CLOCK_TRACE_FREQ 14 +#define CLOCK_TRACE 15 /* * The IDs of various hardware clocks: diff --git a/include/linux/trace-clock.h b/include/linux/trace-clock.h new file mode 100644 index 00000000000..273991a9638 --- /dev/null +++ b/include/linux/trace-clock.h @@ -0,0 +1,17 @@ +#ifndef _LINUX_TRACE_CLOCK_H +#define _LINUX_TRACE_CLOCK_H + +/* + * Trace clock + * + * Chooses between an architecture specific clock or an atomic logical clock. + * + * Copyright (C) 2007,2008 Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca) + */ + +#ifdef CONFIG_HAVE_TRACE_CLOCK +#include <asm/trace-clock.h> +#else +#include <asm-generic/trace-clock.h> +#endif /* CONFIG_HAVE_TRACE_CLOCK */ +#endif /* _LINUX_TRACE_CLOCK_H */ diff --git a/include/trace/events/timer.h b/include/trace/events/timer.h index 425bcfe56c6..f3b763efe11 100644 --- a/include/trace/events/timer.h +++ b/include/trace/events/timer.h @@ -1,8 +1,8 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM timer -#if !defined(_TRACE_TIMER_H) || defined(TRACE_HEADER_MULTI_READ) -#define _TRACE_TIMER_H +#if !defined(_TRACE_EVENTS_TIMER_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_EVENTS_TIMER_H #include <linux/tracepoint.h> #include <linux/hrtimer.h> @@ -323,7 +323,7 @@ TRACE_EVENT(itimer_expire, (int) __entry->pid, (unsigned long long)__entry->now) ); -#endif /* _TRACE_TIMER_H */ +#endif /* _TRACE_EVENTS_TIMER_H */ /* This part must be outside protection */ #include <trace/define_trace.h> diff --git a/include/trace/fault.h b/include/trace/fault.h new file mode 100644 index 00000000000..3277e303fc4 --- /dev/null +++ b/include/trace/fault.h @@ -0,0 +1,25 @@ +#ifndef _TRACE_FAULT_H +#define _TRACE_FAULT_H + +#include <linux/tracepoint.h> + +DECLARE_TRACE(page_fault_entry, + TP_PROTO(struct pt_regs *regs, int trapnr, + struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long address, int write_access), + TP_ARGS(regs, trapnr, mm, vma, address, write_access)); +DECLARE_TRACE(page_fault_exit, + TP_PROTO(int res), + TP_ARGS(res)); +DECLARE_TRACE(page_fault_nosem_entry, + TP_PROTO(struct pt_regs *regs, int trapnr, unsigned long address), + TP_ARGS(regs, trapnr, address)); +DECLARE_TRACE_NOARGS(page_fault_nosem_exit); +DECLARE_TRACE(page_fault_get_user_entry, + TP_PROTO(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long address, int write_access), + TP_ARGS(mm, vma, address, write_access)); +DECLARE_TRACE(page_fault_get_user_exit, + TP_PROTO(int res), + TP_ARGS(res)); +#endif diff --git a/include/trace/filemap.h b/include/trace/filemap.h new file mode 100644 index 00000000000..14e90ba9a09 --- /dev/null +++ b/include/trace/filemap.h @@ -0,0 +1,19 @@ +#ifndef _TRACE_FILEMAP_H +#define _TRACE_FILEMAP_H + +#include <linux/tracepoint.h> + +DECLARE_TRACE(wait_on_page_start, + TP_PROTO(struct page *page, int bit_nr), + TP_ARGS(page, bit_nr)); +DECLARE_TRACE(wait_on_page_end, + TP_PROTO(struct page *page, int bit_nr), + TP_ARGS(page, bit_nr)); +DECLARE_TRACE(add_to_page_cache, + TP_PROTO(struct address_space *mapping, pgoff_t offset), + TP_ARGS(mapping, offset)); +DECLARE_TRACE(remove_from_page_cache, + TP_PROTO(struct address_space *mapping), + TP_ARGS(mapping)); + +#endif diff --git a/include/trace/fs.h b/include/trace/fs.h new file mode 100644 index 00000000000..efe7e477dc1 --- /dev/null +++ b/include/trace/fs.h @@ -0,0 +1,66 @@ +#ifndef _TRACE_FS_H +#define _TRACE_FS_H + +#include <linux/buffer_head.h> +#include <linux/time.h> +#include <linux/tracepoint.h> + +DECLARE_TRACE(fs_buffer_wait_start, + TP_PROTO(struct buffer_head *bh), + TP_ARGS(bh)); +DECLARE_TRACE(fs_buffer_wait_end, + TP_PROTO(struct buffer_head *bh), + TP_ARGS(bh)); +DECLARE_TRACE(fs_exec, + TP_PROTO(const char *filename), + TP_ARGS(filename)); +DECLARE_TRACE(fs_ioctl, + TP_PROTO(unsigned int fd, unsigned int cmd, unsigned long arg), + TP_ARGS(fd, cmd, arg)); +DECLARE_TRACE(fs_open, + TP_PROTO(int fd, char *filename), + TP_ARGS(fd, filename)); +DECLARE_TRACE(fs_close, + TP_PROTO(unsigned int fd), + TP_ARGS(fd)); +DECLARE_TRACE(fs_lseek, + TP_PROTO(unsigned int fd, long offset, unsigned int origin), + TP_ARGS(fd, offset, origin)); +DECLARE_TRACE(fs_llseek, + TP_PROTO(unsigned int fd, loff_t offset, unsigned int origin), + TP_ARGS(fd, offset, origin)); + +/* + * Probes must be aware that __user * may be modified by concurrent userspace + * or kernel threads. + */ +DECLARE_TRACE(fs_read, + TP_PROTO(unsigned int fd, char __user *buf, size_t count, ssize_t ret), + TP_ARGS(fd, buf, count, ret)); +DECLARE_TRACE(fs_write, + TP_PROTO(unsigned int fd, const char __user *buf, size_t count, + ssize_t ret), + TP_ARGS(fd, buf, count, ret)); +DECLARE_TRACE(fs_pread64, + TP_PROTO(unsigned int fd, char __user *buf, size_t count, loff_t pos, + ssize_t ret), + TP_ARGS(fd, buf, count, pos, ret)); +DECLARE_TRACE(fs_pwrite64, + TP_PROTO(unsigned int fd, const char __user *buf, size_t count, + loff_t pos, ssize_t ret), + TP_ARGS(fd, buf, count, pos, ret)); +DECLARE_TRACE(fs_readv, + TP_PROTO(unsigned long fd, const struct iovec __user *vec, + unsigned long vlen, ssize_t ret), + TP_ARGS(fd, vec, vlen, ret)); +DECLARE_TRACE(fs_writev, + TP_PROTO(unsigned long fd, const struct iovec __user *vec, + unsigned long vlen, ssize_t ret), + TP_ARGS(fd, vec, vlen, ret)); +DECLARE_TRACE(fs_select, + TP_PROTO(int fd, struct timespec *end_time), + TP_ARGS(fd, end_time)); +DECLARE_TRACE(fs_poll, + TP_PROTO(int fd), + TP_ARGS(fd)); +#endif diff --git a/include/trace/hugetlb.h b/include/trace/hugetlb.h new file mode 100644 index 00000000000..c18944e3401 --- /dev/null +++ b/include/trace/hugetlb.h @@ -0,0 +1,28 @@ +#ifndef _TRACE_HUGETLB_H +#define _TRACE_HUGETLB_H + +#include <linux/tracepoint.h> + +DECLARE_TRACE(hugetlb_page_release, + TP_PROTO(struct page *page), + TP_ARGS(page)); +DECLARE_TRACE(hugetlb_page_grab, + TP_PROTO(struct page *page), + TP_ARGS(page)); +DECLARE_TRACE(hugetlb_buddy_pgalloc, + TP_PROTO(struct page *page), + TP_ARGS(page)); +DECLARE_TRACE(hugetlb_page_alloc, + TP_PROTO(struct page *page), + TP_ARGS(page)); +DECLARE_TRACE(hugetlb_page_free, + TP_PROTO(struct page *page), + TP_ARGS(page)); +DECLARE_TRACE(hugetlb_pages_reserve, + TP_PROTO(struct inode *inode, long from, long to, int ret), + TP_ARGS(inode, from, to, ret)); +DECLARE_TRACE(hugetlb_pages_unreserve, + TP_PROTO(struct inode *inode, long offset, long freed), + TP_ARGS(inode, offset, freed)); + +#endif diff --git a/include/trace/ipc.h b/include/trace/ipc.h new file mode 100644 index 00000000000..ea9dac190c3 --- /dev/null +++ b/include/trace/ipc.h @@ -0,0 +1,18 @@ +#ifndef _TRACE_IPC_H +#define _TRACE_IPC_H + +#include <linux/tracepoint.h> + +DECLARE_TRACE(ipc_msg_create, + TP_PROTO(long id, int flags), + TP_ARGS(id, flags)); +DECLARE_TRACE(ipc_sem_create, + TP_PROTO(long id, int flags), + TP_ARGS(id, flags)); +DECLARE_TRACE(ipc_shm_create, + TP_PROTO(long id, int flags), + TP_ARGS(id, flags)); +DECLARE_TRACE(ipc_call, + TP_PROTO(unsigned int call, unsigned int first), + TP_ARGS(call, first)); +#endif diff --git a/include/trace/ipv4.h b/include/trace/ipv4.h new file mode 100644 index 00000000000..388908a788e --- /dev/null +++ b/include/trace/ipv4.h @@ -0,0 +1,14 @@ +#ifndef _TRACE_IPV4_H +#define _TRACE_IPV4_H + +#include <linux/inetdevice.h> +#include <linux/tracepoint.h> + +DECLARE_TRACE(ipv4_addr_add, + TP_PROTO(struct in_ifaddr *ifa), + TP_ARGS(ifa)); +DECLARE_TRACE(ipv4_addr_del, + TP_PROTO(struct in_ifaddr *ifa), + TP_ARGS(ifa)); + +#endif diff --git a/include/trace/ipv6.h b/include/trace/ipv6.h new file mode 100644 index 00000000000..ffb9b113048 --- /dev/null +++ b/include/trace/ipv6.h @@ -0,0 +1,14 @@ +#ifndef _TRACE_IPV6_H +#define _TRACE_IPV6_H + +#include <net/if_inet6.h> +#include <linux/tracepoint.h> + +DECLARE_TRACE(ipv6_addr_add, + TP_PROTO(struct inet6_ifaddr *ifa), + TP_ARGS(ifa)); +DECLARE_TRACE(ipv6_addr_del, + TP_PROTO(struct inet6_ifaddr *ifa), + TP_ARGS(ifa)); + +#endif diff --git a/include/trace/irq.h b/include/trace/irq.h new file mode 100644 index 00000000000..58d50636936 --- /dev/null +++ b/include/trace/irq.h @@ -0,0 +1,31 @@ +#ifndef _LTTNG_TRACE_IRQ_H +#define _LTTNG_TRACE_IRQ_H + +#include <linux/kdebug.h> +#include <linux/interrupt.h> + +/* + * action can be NULL if not available. + */ +DECLARE_TRACE(irq_entry, + TP_PROTO(unsigned int id, struct pt_regs *regs, + struct irqaction *action), + TP_ARGS(id, regs, action)); +DECLARE_TRACE(irq_exit, + TP_PROTO(irqreturn_t retval), + TP_ARGS(retval)); + +DECLARE_TRACE(irq_tasklet_low_entry, + TP_PROTO(struct tasklet_struct *t), + TP_ARGS(t)); +DECLARE_TRACE(irq_tasklet_low_exit, + TP_PROTO(struct tasklet_struct *t), + TP_ARGS(t)); +DECLARE_TRACE(irq_tasklet_high_entry, + TP_PROTO(struct tasklet_struct *t), + TP_ARGS(t)); +DECLARE_TRACE(irq_tasklet_high_exit, + TP_PROTO(struct tasklet_struct *t), + TP_ARGS(t)); + +#endif diff --git a/include/trace/kernel.h b/include/trace/kernel.h new file mode 100644 index 00000000000..ca61c54525b --- /dev/null +++ b/include/trace/kernel.h @@ -0,0 +1,31 @@ +#ifndef _TRACE_KERNEL_H +#define _TRACE_KERNEL_H + +#include <linux/tracepoint.h> +#include <linux/kexec.h> + +struct kimage; + +DECLARE_TRACE(kernel_printk, + TP_PROTO(unsigned long retaddr), + TP_ARGS(retaddr)); +DECLARE_TRACE(kernel_vprintk, + TP_PROTO(unsigned long retaddr, char *buf, int len), + TP_ARGS(retaddr, buf, len)); +DECLARE_TRACE(kernel_module_free, + TP_PROTO(struct module *mod), + TP_ARGS(mod)); +DECLARE_TRACE(kernel_module_load, + TP_PROTO(struct module *mod), + TP_ARGS(mod)); +DECLARE_TRACE(kernel_panic, + TP_PROTO(const char *fmt, va_list args), + TP_ARGS(fmt, args)); +DECLARE_TRACE(kernel_kernel_kexec, + TP_PROTO(struct kimage *image), + TP_ARGS(image)); +DECLARE_TRACE(kernel_crash_kexec, + TP_PROTO(struct kimage *image, struct pt_regs *regs), + TP_ARGS(image, regs)); + +#endif diff --git a/include/trace/lockdep.h b/include/trace/lockdep.h new file mode 100644 index 00000000000..dbd4629d0f8 --- /dev/null +++ b/include/trace/lockdep.h @@ -0,0 +1,37 @@ +#ifndef _LTTNG_TRACE_LOCKDEP_H +#define _LTTNG_TRACE_LOCKDEP_H + +#include <linux/lockdep.h> +#include <linux/tracepoint.h> + +/* + * lockdep tracing must be very careful with respect to reentrancy. + * + * It should not use immediate values for activation because it involves + * traps called when the code patching is done. + */ +DECLARE_TRACE(lockdep_hardirqs_on, + TP_PROTO(unsigned long retaddr), + TP_ARGS(retaddr)); +DECLARE_TRACE(lockdep_hardirqs_off, + TP_PROTO(unsigned long retaddr), + TP_ARGS(retaddr)); +DECLARE_TRACE(lockdep_softirqs_on, + TP_PROTO(unsigned long retaddr), + TP_ARGS(retaddr)); +DECLARE_TRACE(lockdep_softirqs_off, + TP_PROTO(unsigned long retaddr), + TP_ARGS(retaddr)); + +/* FIXME : some duplication with lockdep TRACE EVENTs */ +DECLARE_TRACE(lockdep_lock_acquire, + TP_PROTO(unsigned long retaddr, unsigned int subclass, + struct lockdep_map *lock, int trylock, int read, + int hardirqs_off), + TP_ARGS(retaddr, subclass, lock, trylock, read, hardirqs_off)); +DECLARE_TRACE(lockdep_lock_release, + TP_PROTO(unsigned long retaddr, struct lockdep_map *lock, int nested), + TP_ARGS(retaddr, lock, nested)); + + +#endif /* _LTTNG_TRACE_LOCKDEP_H */ diff --git a/include/trace/net.h b/include/trace/net.h new file mode 100644 index 00000000000..91a0f02d0bc --- /dev/null +++ b/include/trace/net.h @@ -0,0 +1,40 @@ +#ifndef _TRACE_LTTNG_NET_H +#define _TRACE_LTTNG_NET_H + +#include <linux/tracepoint.h> + +struct sk_buff; +DECLARE_TRACE(lttng_net_dev_xmit, + TP_PROTO(struct sk_buff *skb), + TP_ARGS(skb)); +DECLARE_TRACE(lttng_net_dev_receive, + TP_PROTO(struct sk_buff *skb), + TP_ARGS(skb)); +DECLARE_TRACE(net_tcpv4_rcv, + TP_PROTO(struct sk_buff *skb), + TP_ARGS(skb)); +DECLARE_TRACE(net_udpv4_rcv, + TP_PROTO(struct sk_buff *skb), + TP_ARGS(skb)); + +/* + * Note these first 2 traces are actually in __napi_schedule and net_rx_action + * respectively. The former is in __napi_schedule because it uses at-most-once + * logic and placing it in the calling routine (napi_schedule) would produce + * countless trace events that were effectively no-ops. napi_poll is + * implemented in net_rx_action, because thats where we do our polling on + * devices. The last trace point is in napi_complete, right where you would + * think it would be. + */ +struct napi_struct; +DECLARE_TRACE(net_napi_schedule, + TP_PROTO(struct napi_struct *n), + TP_ARGS(n)); +DECLARE_TRACE(net_napi_poll, + TP_PROTO(struct napi_struct *n), + TP_ARGS(n)); +DECLARE_TRACE(net_napi_complete, + TP_PROTO(struct napi_struct *n), + TP_ARGS(n)); + +#endif diff --git a/include/trace/page_alloc.h b/include/trace/page_alloc.h new file mode 100644 index 00000000000..c30a389ea91 --- /dev/null +++ b/include/trace/page_alloc.h @@ -0,0 +1,16 @@ +#ifndef _TRACE_PAGE_ALLOC_H +#define _TRACE_PAGE_ALLOC_H + +#include <linux/tracepoint.h> + +/* + * mm_page_alloc : page can be NULL. + */ +DECLARE_TRACE(page_alloc, + TP_PROTO(struct page *page, unsigned int order), + TP_ARGS(page, order)); +DECLARE_TRACE(page_free, + TP_PROTO(struct page *page, unsigned int order), + TP_ARGS(page, order)); + +#endif diff --git a/include/trace/pm.h b/include/trace/pm.h new file mode 100644 index 00000000000..84078bbe1db --- /dev/null +++ b/include/trace/pm.h @@ -0,0 +1,11 @@ +#ifndef _TRACE_PM_H +#define _TRACE_PM_H + +#include <linux/tracepoint.h> + +DECLARE_TRACE_NOARGS(pm_idle_entry); +DECLARE_TRACE_NOARGS(pm_idle_exit); +DECLARE_TRACE_NOARGS(pm_suspend_entry); +DECLARE_TRACE_NOARGS(pm_suspend_exit); + +#endif diff --git a/include/trace/rcu.h b/include/trace/rcu.h new file mode 100644 index 00000000000..f551c2ca9a0 --- /dev/null +++ b/include/trace/rcu.h @@ -0,0 +1,43 @@ +#ifndef _TRACE_RCU_H +#define _TRACE_RCU_H + +#include <linux/tracepoint.h> +#include <linux/rcupdate.h> + +DECLARE_TRACE(rcu_classic_callback, + TP_PROTO(struct rcu_head *head), + TP_ARGS(head)); + +DECLARE_TRACE(rcu_classic_call_rcu, + TP_PROTO(struct rcu_head *head, unsigned long ip), + TP_ARGS(head, ip)); + +DECLARE_TRACE(rcu_classic_call_rcu_bh, + TP_PROTO(struct rcu_head *head, unsigned long ip), + TP_ARGS(head, ip)); + +DECLARE_TRACE(rcu_preempt_callback, + TP_PROTO(struct rcu_head *head), + TP_ARGS(head)); + +DECLARE_TRACE(rcu_preempt_call_rcu, + TP_PROTO(struct rcu_head *head, unsigned long ip), + TP_ARGS(head, ip)); + +DECLARE_TRACE(rcu_preempt_call_rcu_sched, + TP_PROTO(struct rcu_head *head, unsigned long ip), + TP_ARGS(head, ip)); + +DECLARE_TRACE(rcu_tree_callback, + TP_PROTO(struct rcu_head *head), + TP_ARGS(head)); + +DECLARE_TRACE(rcu_tree_call_rcu, + TP_PROTO(struct rcu_head *head, unsigned long ip), + TP_ARGS(head, ip)); + +DECLARE_TRACE(rcu_tree_call_rcu_bh, + TP_PROTO(struct rcu_head *head, unsigned long ip), + TP_ARGS(head, ip)); + +#endif diff --git a/include/trace/sched.h b/include/trace/sched.h new file mode 100644 index 00000000000..a4b0307c4d6 --- /dev/null +++ b/include/trace/sched.h @@ -0,0 +1,11 @@ +#ifndef _LTTNG_TRACE_SCHED_H +#define _LTTNG_TRACE_SCHED_H + +#include <linux/sched.h> +#include <linux/tracepoint.h> + +DECLARE_TRACE(sched_kthread_create, + TP_PROTO(void *fn, int pid), + TP_ARGS(fn, pid)); + +#endif /* _LTTNG_TRACE_SCHED_H */ diff --git a/include/trace/socket.h b/include/trace/socket.h new file mode 100644 index 00000000000..4e8a324575d --- /dev/null +++ b/include/trace/socket.h @@ -0,0 +1,77 @@ +#ifndef _TRACE_SOCKET_H +#define _TRACE_SOCKET_H + +#include <net/sock.h> +#include <linux/tracepoint.h> + +DECLARE_TRACE(socket_create, + TP_PROTO(int family, int type, int protocol, struct socket *sock, + int ret), + TP_ARGS(family, type, protocol, sock, ret)); + +DECLARE_TRACE(socket_bind, + TP_PROTO(int fd, struct sockaddr __user *umyaddr, int addrlen, int ret), + TP_ARGS(fd, umyaddr, addrlen, ret)); + +DECLARE_TRACE(socket_connect, + TP_PROTO(int fd, struct sockaddr __user *uservaddr, int addrlen, + int ret), + TP_ARGS(fd, uservaddr, addrlen, ret)); + +DECLARE_TRACE(socket_listen, + TP_PROTO(int fd, int backlog, int ret), + TP_ARGS(fd, backlog, ret)); + +DECLARE_TRACE(socket_accept, + TP_PROTO(int fd, struct sockaddr __user *upeer_sockaddr, + int __user *upeer_addrlen, int flags, int ret), + TP_ARGS(fd, upeer_sockaddr, upeer_addrlen, flags, ret)); + +DECLARE_TRACE(socket_getsockname, + TP_PROTO(int fd, struct sockaddr __user *usockaddr, + int __user *usockaddr_len, int ret), + TP_ARGS(fd, usockaddr, usockaddr_len, ret)); + +DECLARE_TRACE(socket_getpeername, + TP_PROTO(int fd, struct sockaddr __user *usockaddr, + int __user *usockaddr_len, int ret), + TP_ARGS(fd, usockaddr, usockaddr_len, ret)); + +DECLARE_TRACE(socket_socketpair, + TP_PROTO(int family, int type, int protocol, int __user *usockvec, + int ret), + TP_ARGS(family, type, protocol, usockvec, ret)); + +DECLARE_TRACE(socket_sendmsg, + TP_PROTO(struct socket *sock, struct msghdr *msg, size_t size, int ret), + TP_ARGS(sock, msg, size, ret)); + +DECLARE_TRACE(socket_recvmsg, + TP_PROTO(struct socket *sock, struct msghdr *msg, size_t size, + int flags, int ret), + TP_ARGS(sock, msg, size, flags, ret)); + +DECLARE_TRACE(socket_setsockopt, + TP_PROTO(int fd, int level, int optname, char __user *optval, + int optlen, int ret), + TP_ARGS(fd, level, optname, optval, optlen, ret)); + +DECLARE_TRACE(socket_getsockopt, + TP_PROTO(int fd, int level, int optname, char __user *optval, + int __user *optlen, int ret), + TP_ARGS(fd, level, optname, optval, optlen, ret)); + +DECLARE_TRACE(socket_shutdown, + TP_PROTO(int fd, int how, int ret), + TP_ARGS(fd, how, ret)); + +/* + * socket_call + * + * We also trace socket_call so we can know which syscall is used by user + * (socket_call or sock_send...) + */ +DECLARE_TRACE(socket_call, + TP_PROTO(int call, unsigned long a0), + TP_ARGS(call, a0)); +#endif diff --git a/include/trace/swap.h b/include/trace/swap.h new file mode 100644 index 00000000000..bd035a7204e --- /dev/null +++ b/include/trace/swap.h @@ -0,0 +1,20 @@ +#ifndef _TRACE_SWAP_H +#define _TRACE_SWAP_H + +#include <linux/swap.h> +#include <linux/tracepoint.h> + +DECLARE_TRACE(swap_in, + TP_PROTO(struct page *page, swp_entry_t entry), + TP_ARGS(page, entry)); +DECLARE_TRACE(swap_out, + TP_PROTO(struct page *page), + TP_ARGS(page)); +DECLARE_TRACE(swap_file_open, + TP_PROTO(struct file *file, char *filename), + TP_ARGS(file, filename)); +DECLARE_TRACE(swap_file_close, + TP_PROTO(struct file *file), + TP_ARGS(file)); + +#endif diff --git a/include/trace/syscall.h b/include/trace/syscall.h index 31966a4fb8c..2f40e5e65a2 100644 --- a/include/trace/syscall.h +++ b/include/trace/syscall.h @@ -6,6 +6,7 @@ #include <linux/ftrace_event.h> #include <asm/ptrace.h> +#include <linux/tracepoint.h> /* @@ -54,4 +55,11 @@ int perf_sysexit_enable(struct ftrace_event_call *call); void perf_sysexit_disable(struct ftrace_event_call *call); #endif +DECLARE_TRACE(syscall_entry, + TP_PROTO(struct pt_regs *regs, long id), + TP_ARGS(regs, id)); +DECLARE_TRACE(syscall_exit, + TP_PROTO(long ret), + TP_ARGS(ret)); + #endif /* _TRACE_SYSCALL_H */ diff --git a/include/trace/timer.h b/include/trace/timer.h new file mode 100644 index 00000000000..9b2a852ca21 --- /dev/null +++ b/include/trace/timer.h @@ -0,0 +1,24 @@ +#ifndef _TRACE_TIMER_H +#define _TRACE_TIMER_H + +#include <linux/tracepoint.h> + +DECLARE_TRACE(timer_itimer_expired, + TP_PROTO(struct signal_struct *sig), + TP_ARGS(sig)); +DECLARE_TRACE(timer_itimer_set, + TP_PROTO(int which, struct itimerval *value), + TP_ARGS(which, value)); +DECLARE_TRACE(timer_set, + TP_PROTO(struct timer_list *timer), + TP_ARGS(timer)); +/* + * xtime_lock is taken when kernel_timer_update_time tracepoint is reached. + */ +DECLARE_TRACE(timer_update_time, + TP_PROTO(struct timespec *_xtime, struct timespec *_wall_to_monotonic), + TP_ARGS(_xtime, _wall_to_monotonic)); +DECLARE_TRACE(timer_timeout, + TP_PROTO(struct task_struct *p), + TP_ARGS(p)); +#endif diff --git a/include/trace/trap.h b/include/trace/trap.h new file mode 100644 index 00000000000..1b70c049960 --- /dev/null +++ b/include/trace/trap.h @@ -0,0 +1,11 @@ +#ifndef _TRACE_TRAP_H +#define _TRACE_TRAP_H + +#include <linux/tracepoint.h> + +DECLARE_TRACE(trap_entry, + TP_PROTO(struct pt_regs *regs, long id), + TP_ARGS(regs, id)); +DECLARE_TRACE_NOARGS(trap_exit); + +#endif |