Re: [patch 3/6] Linux Kernel Markers - Documentation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 06 Sep 2007 16:07:36 -0400 Mathieu Desnoyers wrote:

> Here is some documentation explaining what is/how to use the Linux
> Kernel Markers.
> ---
> 
>  Documentation/marker.txt |  257 +++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 257 insertions(+)
> 
> Index: linux-2.6-lttng/Documentation/marker.txt
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ linux-2.6-lttng/Documentation/marker.txt	2007-08-17 11:56:20.000000000 -0400
> @@ -0,0 +1,257 @@
> + 	             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 your code provides a hook to call a function (probe) that

                      ^^^^ I would drop "your".  It quite likely
	could be someone else's code.

> +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 penality (checking a condition for a branch) and space

                          penalty

> +penality (adding a few bytes for the function call at the end of the

   penalty

> +instrumented function and adds a data structure in a separate section). The
> +immediate values are used to minimize the impact on data cache, encoding the
> +condition in the instruction stream. 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>
> +
> +Add, in your code :

   And,

> +
> +trace_mark(subsystem_event, "%d %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.
> +- "%d %s" is the formatted string for the serializer.
> +- 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 and make
> +sure there is no caller left using the probe when it returns. Probe removal is
> +preempt-safe because preemption is disabled around the probe call. 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.
> +
> +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)"
> +
> +
> +* Optimization for a given architecture
> +
> +One can implement optimized markers for a given architecture by replacing
> +asm-$ARCH/marker.h.
> +
> +To force use of a non-optimized version of the markers, _trace_mark() should be
> +used. It takes the same parameters as the normal markers, but it does not use
> +the immediate values based on code patching.
> +
> +
> +* Probe example

I would much prefer that you put marker-related docs into
Documentation/marker[s]/ and then put the Makefile and source files
into Documentation/marker[s]/src/.

This make the source files more visible (findable, grepable) to other
developers & users.  It also makes it feasible to use and test them
on a regular basis so that API changes (=> bugs:) can be easily
found and fixed.

And then you can drop those "CUT" lines.  :)


> +You can build the kernel modules, probe-example.ko and marker-example.ko,
> +using the following Makefile:
> +------------------------------ CUT -------------------------------------
> +obj-m := probe-example.o marker-example.o
> +KDIR := /lib/modules/$(shell uname -r)/build
> +PWD := $(shell pwd)
> +default:
> +	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
> +clean:
> +	rm -f *.mod.c *.ko *.o
> +------------------------------ CUT -------------------------------------
> +/* probe-example.c
> + *
> + * Connects two functions to marker call sites.
> + *
> + * (C) Copyright 2007 Mathieu Desnoyers <[email protected]>
> + *
> + * 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(const struct __mark_marker *mdata,
> +		const char *format, ...)
> +{
> +	va_list ap;
> +	/* Declare args */
> +	unsigned int value;
> +	const char *mystr;
> +
> +	/* Assign args */
> +	va_start(ap, format);
> +	value = va_arg(ap, typeof(value));
> +	mystr = va_arg(ap, typeof(mystr));
> +
> +	/* Call printk */
> +	printk("Value %u, string %s\n", value, mystr);
> +
> +	/* or count, check rights, serialize data in a buffer */
> +
> +	va_end(ap);
> +}
> +
> +atomic_t eventb_count = ATOMIC_INIT(0);
> +
> +void probe_subsystem_eventb(const struct __mark_marker *mdata,
> +	const char *format, ...)
> +{
> +	/* Increment counter */
> +	atomic_inc(&eventb_count);
> +}
> +
> +static struct probe_data probe_array[] =
> +{
> +	{	.name = "subsystem_event",
> +		.format = "%d %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);
> +		result = marker_arm(probe_array[i].name);
> +		if (result)
> +			printk(KERN_INFO "Unable to arm 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);
> +	}
> +	printk("Number of event b : %u\n", atomic_read(&eventb_count));
> +}
> +
> +module_init(probe_init);
> +module_exit(probe_fini);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Mathieu Desnoyers");
> +MODULE_DESCRIPTION("SUBSYSTEM Probe");
> +------------------------------ CUT -------------------------------------
> +/* marker-example.c
> + *
> + * Executes a marker when /proc/marker-example is opened.
> + *
> + * (C) Copyright 2007 Mathieu Desnoyers <[email protected]>
> + *
> + * 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 = NULL;
> +
> +static int my_open(struct inode *inode, struct file *file)
> +{
> +	int i;
> +
> +	trace_mark(subsystem_event, "%d %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 example_init(void)
> +{
> +	printk(KERN_ALERT "example init\n");
> +	pentry_example = create_proc_entry("marker-example", 0444, NULL);
> +	if (pentry_example)
> +		pentry_example->proc_fops = &mark_ops;
> +	else
> +		return -EPERM;
> +	return 0;
> +}
> +
> +static void 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("Linux Trace Toolkit example");
> +------------------------------ CUT -------------------------------------
> +Sequence of operations : (as root)
> +make
> +insmod marker-example.ko (insmod order is not important)
> +insmod probe-example.ko
> +cat /proc/marker-example (returns an expected error)
> +rmmod marker-example probe-example
> +dmesg
> +------------------------------ CUT -------------------------------------

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux