Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8256e47c authored by Mathieu Desnoyers's avatar Mathieu Desnoyers Committed by Linus Torvalds
Browse files

Linux Kernel Markers



The marker activation functions sits in kernel/marker.c.  A hash table is used
to keep track of the registered probes and armed markers, so the markers
within a newly loaded module that should be active can be activated at module
load time.

marker_query has been removed. marker_get_first, marker_get_next and
marker_release should be used as iterators on the markers.

[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: default avatarMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Acked-by: default avatar"Frank Ch. Eigler" <fche@redhat.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Mike Mason <mmlnx@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 09cadedb
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -12,7 +12,11 @@
/* .data section */
#define DATA_DATA							\
	*(.data)							\
	*(.data.init.refok)
	*(.data.init.refok)						\
	. = ALIGN(8);							\
	VMLINUX_SYMBOL(__start___markers) = .;				\
	*(__markers)							\
	VMLINUX_SYMBOL(__stop___markers) = .;

#define RO_DATA(align)							\
	. = ALIGN((align));						\
@@ -20,6 +24,7 @@
		VMLINUX_SYMBOL(__start_rodata) = .;			\
		*(.rodata) *(.rodata.*)					\
		*(__vermagic)		/* Kernel version magic */	\
		*(__markers_strings)	/* Markers: strings */		\
	}								\
									\
	.rodata1          : AT(ADDR(.rodata1) - LOAD_OFFSET) {		\

include/linux/marker.h

0 → 100644
+130 −0
Original line number Diff line number Diff line
#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 <linux/types.h>

struct module;
struct marker;

/**
 * marker_probe_func - Type of a marker probe function
 * @mdata: pointer of type struct marker
 * @private_data: caller site private data
 * @fmt: format string
 * @...: variable argument list
 *
 * 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 *private_data, const char *fmt, ...);

struct marker {
	const char *name;	/* Marker name */
	const char *format;	/* Marker format string, describing the
				 * variable argument list.
				 */
	char state;		/* Marker state. */
	marker_probe_func *call;/* Probe handler function pointer */
	void *private;		/* Private probe data */
} __attribute__((aligned(8)));

#ifdef CONFIG_MARKERS

/*
 * Note : the empty asm volatile with read constraint is used here instead of a
 * "used" attribute to fix a gcc 4.1.x bug.
 * 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.
 */
#define __trace_mark(name, call_data, format, args...)			\
	do {								\
		static const char __mstrtab_name_##name[]		\
		__attribute__((section("__markers_strings")))		\
		= #name;						\
		static const char __mstrtab_format_##name[]		\
		__attribute__((section("__markers_strings")))		\
		= format;						\
		static struct marker __mark_##name			\
		__attribute__((section("__markers"), aligned(8))) =	\
		{ __mstrtab_name_##name, __mstrtab_format_##name,	\
		0, __mark_empty_function, NULL };			\
		asm volatile("" : : "i" (&__mark_##name));		\
		__mark_check_format(format, ## args);			\
		if (unlikely(__mark_##name.state)) {			\
			preempt_disable();				\
			(*__mark_##name.call)				\
				(&__mark_##name, call_data,		\
				format, ## args);			\
			preempt_enable();				\
		}							\
	} while (0)

extern void marker_update_probe_range(struct marker *begin,
	struct marker *end, struct module *probe_module, int *refcount);
#else /* !CONFIG_MARKERS */
#define __trace_mark(name, call_data, format, args...) \
		__mark_check_format(format, ## args)
static inline void marker_update_probe_range(struct marker *begin,
	struct marker *end, struct module *probe_module, int *refcount)
{ }
#endif /* CONFIG_MARKERS */

/**
 * trace_mark - Marker
 * @name: marker name, not quoted.
 * @format: format string
 * @args...: variable argument list
 *
 * Places a marker.
 */
#define trace_mark(name, format, args...) \
	__trace_mark(name, NULL, format, ## args)

#define MARK_MAX_FORMAT_LEN	1024

/**
 * MARK_NOARGS - Format string for a marker with no argument.
 */
#define MARK_NOARGS " "

/* To be used for string format validity checking with gcc */
static inline void __printf(1, 2) __mark_check_format(const char *fmt, ...)
{
}

extern marker_probe_func __mark_empty_function;

/*
 * 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 *name, const char *format,
				marker_probe_func *probe, void *private);

/*
 * Returns the private data given to marker_probe_register.
 */
extern void *marker_probe_unregister(const char *name);
/*
 * Unregister a marker by providing the registered private data.
 */
extern void *marker_probe_unregister_private_data(void *private);

extern int marker_arm(const char *name);
extern int marker_disarm(const char *name);
extern void *marker_get_private_data(const char *name);

#endif
+12 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/stringify.h>
#include <linux/kobject.h>
#include <linux/moduleparam.h>
#include <linux/marker.h>
#include <asm/local.h>

#include <asm/module.h>
@@ -354,6 +355,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
};
#ifndef MODULE_ARCH_INIT
#define MODULE_ARCH_INIT {}
@@ -457,6 +462,8 @@ int unregister_module_notifier(struct notifier_block * nb);

extern void print_modules(void);

extern void module_update_markers(struct module *probe_module, int *refcount);

#else /* !CONFIG_MODULES... */
#define EXPORT_SYMBOL(sym)
#define EXPORT_SYMBOL_GPL(sym)
@@ -556,6 +563,11 @@ static inline void print_modules(void)
{
}

static inline void module_update_markers(struct module *probe_module,
		int *refcount)
{
}

#endif /* CONFIG_MODULES */

struct device_driver;
+6 −0
Original line number Diff line number Diff line
@@ -40,4 +40,10 @@ config KPROBES
	  for kernel debugging, non-intrusive instrumentation and testing.
	  If in doubt, say "N".

config MARKERS
	bool "Activate markers"
	help
	  Place an empty function call at each marker site. Can be
	  dynamically changed for a probe function.

endif # INSTRUMENTATION
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ obj-$(CONFIG_RELAY) += relay.o
obj-$(CONFIG_SYSCTL) += utsname_sysctl.o
obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
obj-$(CONFIG_MARKERS) += marker.o

ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
Loading