mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
tracing: Remove markers
Now that the last users of markers have migrated to the event tracer we can kill off the (now orphan) support code. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20090917173527.GA1699@lst.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
committed by
Ingo Molnar
parent
df58bee21e
commit
fc5377668c
@@ -1,104 +0,0 @@
|
||||
Using the Linux Kernel Markers
|
||||
|
||||
Mathieu Desnoyers
|
||||
|
||||
|
||||
This document introduces Linux Kernel Markers and their use. It provides
|
||||
examples of how to insert markers in the kernel and connect probe functions to
|
||||
them and provides some examples of probe functions.
|
||||
|
||||
|
||||
* Purpose of markers
|
||||
|
||||
A marker placed in code provides a hook to call a function (probe) that you can
|
||||
provide at runtime. A marker can be "on" (a probe is connected to it) or "off"
|
||||
(no probe is attached). When a marker is "off" it has no effect, except for
|
||||
adding a tiny time penalty (checking a condition for a branch) and space
|
||||
penalty (adding a few bytes for the function call at the end of the
|
||||
instrumented function and adds a data structure in a separate section). When a
|
||||
marker is "on", the function you provide is called each time the marker is
|
||||
executed, in the execution context of the caller. When the function provided
|
||||
ends its execution, it returns to the caller (continuing from the marker site).
|
||||
|
||||
You can put markers at important locations in the code. Markers are
|
||||
lightweight hooks that can pass an arbitrary number of parameters,
|
||||
described in a printk-like format string, to the attached probe function.
|
||||
|
||||
They can be used for tracing and performance accounting.
|
||||
|
||||
|
||||
* Usage
|
||||
|
||||
In order to use the macro trace_mark, you should include linux/marker.h.
|
||||
|
||||
#include <linux/marker.h>
|
||||
|
||||
And,
|
||||
|
||||
trace_mark(subsystem_event, "myint %d mystring %s", someint, somestring);
|
||||
Where :
|
||||
- subsystem_event is an identifier unique to your event
|
||||
- subsystem is the name of your subsystem.
|
||||
- event is the name of the event to mark.
|
||||
- "myint %d mystring %s" is the formatted string for the serializer. "myint" and
|
||||
"mystring" are repectively the field names associated with the first and
|
||||
second parameter.
|
||||
- someint is an integer.
|
||||
- somestring is a char pointer.
|
||||
|
||||
Connecting a function (probe) to a marker is done by providing a probe (function
|
||||
to call) for the specific marker through marker_probe_register() and can be
|
||||
activated by calling marker_arm(). Marker deactivation can be done by calling
|
||||
marker_disarm() as many times as marker_arm() has been called. Removing a probe
|
||||
is done through marker_probe_unregister(); it will disarm the probe.
|
||||
|
||||
marker_synchronize_unregister() must be called between probe unregistration and
|
||||
the first occurrence of
|
||||
- the end of module exit function,
|
||||
to make sure there is no caller left using the probe;
|
||||
- the free of any resource used by the probes,
|
||||
to make sure the probes wont be accessing invalid data.
|
||||
This, and the fact that preemption is disabled around the probe call, make sure
|
||||
that probe removal and module unload are safe. See the "Probe example" section
|
||||
below for a sample probe module.
|
||||
|
||||
The marker mechanism supports inserting multiple instances of the same marker.
|
||||
Markers can be put in inline functions, inlined static functions, and
|
||||
unrolled loops as well as regular functions.
|
||||
|
||||
The naming scheme "subsystem_event" is suggested here as a convention intended
|
||||
to limit collisions. Marker names are global to the kernel: they are considered
|
||||
as being the same whether they are in the core kernel image or in modules.
|
||||
Conflicting format strings for markers with the same name will cause the markers
|
||||
to be detected to have a different format string not to be armed and will output
|
||||
a printk warning which identifies the inconsistency:
|
||||
|
||||
"Format mismatch for probe probe_name (format), marker (format)"
|
||||
|
||||
Another way to use markers is to simply define the marker without generating any
|
||||
function call to actually call into the marker. This is useful in combination
|
||||
with tracepoint probes in a scheme like this :
|
||||
|
||||
void probe_tracepoint_name(unsigned int arg1, struct task_struct *tsk);
|
||||
|
||||
DEFINE_MARKER_TP(marker_eventname, tracepoint_name, probe_tracepoint_name,
|
||||
"arg1 %u pid %d");
|
||||
|
||||
notrace void probe_tracepoint_name(unsigned int arg1, struct task_struct *tsk)
|
||||
{
|
||||
struct marker *marker = &GET_MARKER(kernel_irq_entry);
|
||||
/* write data to trace buffers ... */
|
||||
}
|
||||
|
||||
* Probe / marker example
|
||||
|
||||
See the example provided in samples/markers/src
|
||||
|
||||
Compile them with your kernel.
|
||||
|
||||
Run, as root :
|
||||
modprobe marker-example (insmod order is not important)
|
||||
modprobe probe-example
|
||||
cat /proc/marker-example (returns an expected error)
|
||||
rmmod marker-example probe-example
|
||||
dmesg
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <linux/poll.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/marker.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/time.h>
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
#include <linux/pid_namespace.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/marker.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/mmu_context.h>
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/preempt.h>
|
||||
#include <linux/marker.h>
|
||||
#include <linux/msi.h>
|
||||
#include <asm/signal.h>
|
||||
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
#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>
|
||||
|
||||
struct module;
|
||||
struct marker;
|
||||
|
||||
/**
|
||||
* marker_probe_func - Type of a marker probe function
|
||||
* @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(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 *name; /* Marker name */
|
||||
const char *format; /* Marker format string, describing the
|
||||
* variable argument list.
|
||||
*/
|
||||
char state; /* Marker state. */
|
||||
char ptype; /* probe type : 0 : single, 1 : multi */
|
||||
/* Probe wrapper */
|
||||
void (*call)(const struct marker *mdata, void *call_private, ...);
|
||||
struct marker_probe_closure single;
|
||||
struct marker_probe_closure *multi;
|
||||
const char *tp_name; /* Optional tracepoint name */
|
||||
void *tp_cb; /* Optional tracepoint callback */
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
#ifdef CONFIG_MARKERS
|
||||
|
||||
#define _DEFINE_MARKER(name, tp_name_str, tp_cb, format) \
|
||||
static const char __mstrtab_##name[] \
|
||||
__attribute__((section("__markers_strings"))) \
|
||||
= #name "\0" format; \
|
||||
static struct marker __mark_##name \
|
||||
__attribute__((section("__markers"), aligned(8))) = \
|
||||
{ __mstrtab_##name, &__mstrtab_##name[sizeof(#name)], \
|
||||
0, 0, marker_probe_cb, { __mark_empty_function, NULL},\
|
||||
NULL, tp_name_str, tp_cb }
|
||||
|
||||
#define DEFINE_MARKER(name, format) \
|
||||
_DEFINE_MARKER(name, NULL, NULL, format)
|
||||
|
||||
#define DEFINE_MARKER_TP(name, tp_name, tp_cb, format) \
|
||||
_DEFINE_MARKER(name, #tp_name, tp_cb, format)
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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, name, call_private, format, args...) \
|
||||
do { \
|
||||
DEFINE_MARKER(name, format); \
|
||||
__mark_check_format(format, ## args); \
|
||||
if (unlikely(__mark_##name.state)) { \
|
||||
(*__mark_##name.call) \
|
||||
(&__mark_##name, call_private, ## args);\
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \
|
||||
do { \
|
||||
void __check_tp_type(void) \
|
||||
{ \
|
||||
register_trace_##tp_name(tp_cb); \
|
||||
} \
|
||||
DEFINE_MARKER_TP(name, tp_name, tp_cb, format); \
|
||||
__mark_check_format(format, ## args); \
|
||||
(*__mark_##name.call)(&__mark_##name, call_private, \
|
||||
## args); \
|
||||
} while (0)
|
||||
|
||||
extern void marker_update_probe_range(struct marker *begin,
|
||||
struct marker *end);
|
||||
|
||||
#define GET_MARKER(name) (__mark_##name)
|
||||
|
||||
#else /* !CONFIG_MARKERS */
|
||||
#define DEFINE_MARKER(name, tp_name, tp_cb, format)
|
||||
#define __trace_mark(generic, name, call_private, format, args...) \
|
||||
__mark_check_format(format, ## args)
|
||||
#define __trace_mark_tp(name, call_private, tp_name, tp_cb, format, args...) \
|
||||
do { \
|
||||
void __check_tp_type(void) \
|
||||
{ \
|
||||
register_trace_##tp_name(tp_cb); \
|
||||
} \
|
||||
__mark_check_format(format, ## args); \
|
||||
} while (0)
|
||||
static inline void marker_update_probe_range(struct marker *begin,
|
||||
struct marker *end)
|
||||
{ }
|
||||
#define GET_MARKER(name)
|
||||
#endif /* CONFIG_MARKERS */
|
||||
|
||||
/**
|
||||
* trace_mark - Marker using code patching
|
||||
* @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(name, format, args...) \
|
||||
__trace_mark(0, name, NULL, format, ## args)
|
||||
|
||||
/**
|
||||
* _trace_mark - Marker using variable read
|
||||
* @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(name, format, args...) \
|
||||
__trace_mark(1, name, NULL, format, ## args)
|
||||
|
||||
/**
|
||||
* trace_mark_tp - Marker in a tracepoint callback
|
||||
* @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(name, tp_name, tp_cb, format, args...) \
|
||||
__trace_mark_tp(name, NULL, tp_name, tp_cb, format, ## args)
|
||||
|
||||
/**
|
||||
* 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, ...)
|
||||
{
|
||||
}
|
||||
|
||||
#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 *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 *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 *name, marker_probe_func *probe,
|
||||
int num);
|
||||
|
||||
/*
|
||||
* 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()
|
||||
|
||||
#endif
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/marker.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
#include <asm/local.h>
|
||||
@@ -327,10 +326,6 @@ 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 *tracepoints;
|
||||
unsigned int num_tracepoints;
|
||||
@@ -535,8 +530,6 @@ int unregister_module_notifier(struct notifier_block * nb);
|
||||
|
||||
extern void print_modules(void);
|
||||
|
||||
extern void module_update_markers(void);
|
||||
|
||||
extern void module_update_tracepoints(void);
|
||||
extern int module_get_iter_tracepoints(struct tracepoint_iter *iter);
|
||||
|
||||
@@ -651,10 +644,6 @@ static inline void print_modules(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void module_update_markers(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void module_update_tracepoints(void)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1054,13 +1054,6 @@ config PROFILING
|
||||
config TRACEPOINTS
|
||||
bool
|
||||
|
||||
config MARKERS
|
||||
bool "Activate markers"
|
||||
select TRACEPOINTS
|
||||
help
|
||||
Place an empty function call at each marker site. Can be
|
||||
dynamically changed for a probe function.
|
||||
|
||||
source "arch/Kconfig"
|
||||
|
||||
config SLOW_WORK
|
||||
|
||||
@@ -87,7 +87,6 @@ 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
|
||||
obj-$(CONFIG_TRACEPOINTS) += tracepoint.o
|
||||
obj-$(CONFIG_LATENCYTOP) += latencytop.o
|
||||
obj-$(CONFIG_FUNCTION_TRACER) += trace/
|
||||
|
||||
930
kernel/marker.c
930
kernel/marker.c
File diff suppressed because it is too large
Load Diff
@@ -2237,10 +2237,6 @@ static noinline struct module *load_module(void __user *umod,
|
||||
sizeof(*mod->ctors), &mod->num_ctors);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MARKERS
|
||||
mod->markers = section_objs(hdr, sechdrs, secstrings, "__markers",
|
||||
sizeof(*mod->markers), &mod->num_markers);
|
||||
#endif
|
||||
#ifdef CONFIG_TRACEPOINTS
|
||||
mod->tracepoints = section_objs(hdr, sechdrs, secstrings,
|
||||
"__tracepoints",
|
||||
@@ -2958,20 +2954,6 @@ void module_layout(struct module *mod,
|
||||
EXPORT_SYMBOL(module_layout);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_MARKERS
|
||||
void module_update_markers(void)
|
||||
{
|
||||
struct module *mod;
|
||||
|
||||
mutex_lock(&module_mutex);
|
||||
list_for_each_entry(mod, &modules, list)
|
||||
if (!mod->taints)
|
||||
marker_update_probe_range(mod->markers,
|
||||
mod->markers + mod->num_markers);
|
||||
mutex_unlock(&module_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TRACEPOINTS
|
||||
void module_update_tracepoints(void)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/marker.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
@@ -7,12 +7,6 @@ menuconfig SAMPLES
|
||||
|
||||
if SAMPLES
|
||||
|
||||
config SAMPLE_MARKERS
|
||||
tristate "Build markers examples -- loadable modules only"
|
||||
depends on MARKERS && m
|
||||
help
|
||||
This build markers example modules.
|
||||
|
||||
config SAMPLE_TRACEPOINTS
|
||||
tristate "Build tracepoints examples -- loadable modules only"
|
||||
depends on TRACEPOINTS && m
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Makefile for Linux samples code
|
||||
|
||||
obj-$(CONFIG_SAMPLES) += markers/ kobject/ kprobes/ tracepoints/ trace_events/
|
||||
obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ tracepoints/ trace_events/
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
# builds the kprobes example kernel modules;
|
||||
# then to use one (as root): insmod <module_name.ko>
|
||||
|
||||
obj-$(CONFIG_SAMPLE_MARKERS) += probe-example.o marker-example.o
|
||||
@@ -1,53 +0,0 @@
|
||||
/* marker-example.c
|
||||
*
|
||||
* Executes a marker when /proc/marker-example is opened.
|
||||
*
|
||||
* (C) Copyright 2007 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
|
||||
*
|
||||
* This file is released under the GPLv2.
|
||||
* See the file COPYING for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/marker.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/proc_fs.h>
|
||||
|
||||
struct proc_dir_entry *pentry_example;
|
||||
|
||||
static int my_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int i;
|
||||
|
||||
trace_mark(subsystem_event, "integer %d string %s", 123,
|
||||
"example string");
|
||||
for (i = 0; i < 10; i++)
|
||||
trace_mark(subsystem_eventb, MARK_NOARGS);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static struct file_operations mark_ops = {
|
||||
.open = my_open,
|
||||
};
|
||||
|
||||
static int __init example_init(void)
|
||||
{
|
||||
printk(KERN_ALERT "example init\n");
|
||||
pentry_example = proc_create("marker-example", 0444, NULL, &mark_ops);
|
||||
if (!pentry_example)
|
||||
return -EPERM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit example_exit(void)
|
||||
{
|
||||
printk(KERN_ALERT "example exit\n");
|
||||
remove_proc_entry("marker-example", NULL);
|
||||
}
|
||||
|
||||
module_init(example_init)
|
||||
module_exit(example_exit)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mathieu Desnoyers");
|
||||
MODULE_DESCRIPTION("Marker example");
|
||||
@@ -1,92 +0,0 @@
|
||||
/* probe-example.c
|
||||
*
|
||||
* Connects two functions to marker call sites.
|
||||
*
|
||||
* (C) Copyright 2007 Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
|
||||
*
|
||||
* This file is released under the GPLv2.
|
||||
* See the file COPYING for more details.
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/marker.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
struct probe_data {
|
||||
const char *name;
|
||||
const char *format;
|
||||
marker_probe_func *probe_func;
|
||||
};
|
||||
|
||||
void probe_subsystem_event(void *probe_data, void *call_data,
|
||||
const char *format, va_list *args)
|
||||
{
|
||||
/* Declare args */
|
||||
unsigned int value;
|
||||
const char *mystr;
|
||||
|
||||
/* Assign args */
|
||||
value = va_arg(*args, typeof(value));
|
||||
mystr = va_arg(*args, typeof(mystr));
|
||||
|
||||
/* Call printk */
|
||||
printk(KERN_INFO "Value %u, string %s\n", value, mystr);
|
||||
|
||||
/* or count, check rights, serialize data in a buffer */
|
||||
}
|
||||
|
||||
atomic_t eventb_count = ATOMIC_INIT(0);
|
||||
|
||||
void probe_subsystem_eventb(void *probe_data, void *call_data,
|
||||
const char *format, va_list *args)
|
||||
{
|
||||
/* Increment counter */
|
||||
atomic_inc(&eventb_count);
|
||||
}
|
||||
|
||||
static struct probe_data probe_array[] =
|
||||
{
|
||||
{ .name = "subsystem_event",
|
||||
.format = "integer %d string %s",
|
||||
.probe_func = probe_subsystem_event },
|
||||
{ .name = "subsystem_eventb",
|
||||
.format = MARK_NOARGS,
|
||||
.probe_func = probe_subsystem_eventb },
|
||||
};
|
||||
|
||||
static int __init probe_init(void)
|
||||
{
|
||||
int result;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(probe_array); i++) {
|
||||
result = marker_probe_register(probe_array[i].name,
|
||||
probe_array[i].format,
|
||||
probe_array[i].probe_func, &probe_array[i]);
|
||||
if (result)
|
||||
printk(KERN_INFO "Unable to register probe %s\n",
|
||||
probe_array[i].name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit probe_fini(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(probe_array); i++)
|
||||
marker_probe_unregister(probe_array[i].name,
|
||||
probe_array[i].probe_func, &probe_array[i]);
|
||||
printk(KERN_INFO "Number of event b : %u\n",
|
||||
atomic_read(&eventb_count));
|
||||
marker_synchronize_unregister();
|
||||
}
|
||||
|
||||
module_init(probe_init);
|
||||
module_exit(probe_fini);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mathieu Desnoyers");
|
||||
MODULE_DESCRIPTION("SUBSYSTEM Probe");
|
||||
@@ -13,7 +13,6 @@
|
||||
# 2) modpost is then used to
|
||||
# 3) create one <module>.mod.c file pr. module
|
||||
# 4) create one Module.symvers file with CRC for all exported symbols
|
||||
# 4a) [CONFIG_MARKERS] create one Module.markers file listing defined markers
|
||||
# 5) compile all <module>.mod.c files
|
||||
# 6) final link of the module to a <module.ko> file
|
||||
|
||||
@@ -59,10 +58,6 @@ include scripts/Makefile.lib
|
||||
|
||||
kernelsymfile := $(objtree)/Module.symvers
|
||||
modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
|
||||
kernelmarkersfile := $(objtree)/Module.markers
|
||||
modulemarkersfile := $(firstword $(KBUILD_EXTMOD))/Module.markers
|
||||
|
||||
markersfile = $(if $(KBUILD_EXTMOD),$(modulemarkersfile),$(kernelmarkersfile))
|
||||
|
||||
# Step 1), find all modules listed in $(MODVERDIR)/
|
||||
__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
|
||||
@@ -85,8 +80,6 @@ modpost = scripts/mod/modpost \
|
||||
$(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
|
||||
$(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \
|
||||
$(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \
|
||||
$(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \
|
||||
$(if $(CONFIG_MARKERS),-M $(markersfile)) \
|
||||
$(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
|
||||
$(if $(cross_build),-c)
|
||||
|
||||
@@ -101,17 +94,12 @@ quiet_cmd_kernel-mod = MODPOST $@
|
||||
cmd_kernel-mod = $(modpost) $@
|
||||
|
||||
vmlinux.o: FORCE
|
||||
@rm -fr $(kernelmarkersfile)
|
||||
$(call cmd,kernel-mod)
|
||||
|
||||
# Declare generated files as targets for modpost
|
||||
$(symverfile): __modpost ;
|
||||
$(modules:.ko=.mod.c): __modpost ;
|
||||
|
||||
ifdef CONFIG_MARKERS
|
||||
$(markersfile): __modpost ;
|
||||
endif
|
||||
|
||||
|
||||
# Step 5), compile all *.mod.c files
|
||||
|
||||
|
||||
Reference in New Issue
Block a user