From: compudj Date: Fri, 29 Sep 2006 18:55:43 +0000 (+0000) Subject: marker tests X-Git-Tag: v0.12.20~1347 X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=bc82195a5cd369d133037ccc20564d89fff523ed;p=lttv.git marker tests git-svn-id: http://ltt.polymtl.ca/svn@2142 04897980-b3bd-0310-b5e0-8ef037075253 --- diff --git a/tests/kernel/test-mark.c b/tests/kernel/test-mark.c index 223b2490..8f998b9b 100644 --- a/tests/kernel/test-mark.c +++ b/tests/kernel/test-mark.c @@ -26,6 +26,7 @@ static int my_open(struct inode *inode, struct file *file) } MARK(subsys_mark2, "%d %s %s", 2, "blah2", "blahx"); MARK(subsys_mark3, "%d %s %s", x, "blah3", "blah5"); + MARK(subsys_mark3, "%d %s %s", x, "blah3", "blah5"); test(NULL); test(NULL); diff --git a/tests/markers/Makefile b/tests/markers/Makefile new file mode 100644 index 00000000..3fef350c --- /dev/null +++ b/tests/markers/Makefile @@ -0,0 +1,30 @@ +ifneq ($(KERNELRELEASE),) +ifneq ($(CONFIG_LTT),) +endif + obj-m += test-micro-loop-marker.o + obj-m += test-micro-loop-empty.o + obj-m += probe.o + obj-m += probe-vararg.o + obj-m += probe-direct.o + obj-m += probe-string.o + obj-m += test-micro-loop-probe.o + obj-m += test-asm.o +else + KERNELDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) + KERNELRELEASE = $(shell cat $(KERNELDIR)/$(KBUILD_OUTPUT)/include/linux/version.h | sed -n 's/.*UTS_RELEASE.*\"\(.*\)\".*/\1/p') +ifneq ($(INSTALL_MOD_PATH),) + DEPMOD_OPT := -b $(INSTALL_MOD_PATH) +endif + +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules + +modules_install: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install + if [ -f $(KERNELDIR)/$(KBUILD_OUTPUT)/System.map ] ; then /sbin/depmod -ae -F $(KERNELDIR)/$(KBUILD_OUTPUT)/System.map $(DEPMOD_OPT) $(KERNELRELEASE) ; fi + + +clean: + $(MAKE) -C $(KERNELDIR) M=$(PWD) clean +endif diff --git a/tests/markers/Modules.symvers b/tests/markers/Modules.symvers new file mode 100644 index 00000000..e69de29b diff --git a/tests/markers/markers-microbench-0.1.txt b/tests/markers/markers-microbench-0.1.txt new file mode 100644 index 00000000..6c52908e --- /dev/null +++ b/tests/markers/markers-microbench-0.1.txt @@ -0,0 +1,168 @@ + + +* Microbenchmarks + +Use timestamp counter to calculate the time spent, with interrupts disabled. +Machine : Pentium 4 3GHz +Fully preemptible kernel +marker : MARK(subsys_mark1, "%d %p", 1, NULL); +Linux Kernel Markers 0.19 + +* Execute an empty loop +NR_LOOPS : 10000000 +time delta (cycles): 15026497 +cycles per loop : 1.50 +- i386 "optimized" : immediate value, test and predicted branch + (non connected marker) +NR_LOOPS : 10000000 +time delta (cycles): 40031640 +cycles per loop : 4.00 +cycles per loop for marker : 2.50 +- i386 "generic" : load, test and predicted branch + (non connected marker) +NR_LOOPS : 10000000 +time delta (cycles): 26697878 +cycles per loop : 2.67 +cycles per loop for marker : 1.17 + +* Execute a loop of memcpy 4096 bytes +- Without marker +NR_LOOPS : 10000 +time delta (cycles): 12981555 +cycles per loop : 1298.16 +- i386 "optimized" : immediate value, test and predicted branch + (non connected marker) +NR_LOOPS : 10000 +time delta (cycles): 12982290 +cycles per loop : 1298.23 +cycles per loop for marker : 0.074 +- i386 "generic" : load, test and predicted branch + (non connected marker) +NR_LOOPS : 10000 +time delta (cycles): 13002788 +cycles per loop : 1300.28 +cycles per loop for marker : 2.123 + + +The following tests are done with the "optimized" markers only + +Execute a loop with a marker enabled, with an empty probe. +NR_LOOPS : 100000 +time delta (cycles): 5210587 +cycles per loop : 52.11 +cycles per loop for empty probe : 52.11-4.00=48.11 + +Execute a loop with marker enabled, with i386 direct argument passing. +NR_LOOPS : 100000 +time delta (cycles): 5299837 +cycles per loop : 53.00 +cycles per loop to get arguments in probe (from stack) on x86 : 53.00-52.11=0.89 + +Execute a loop with marker enabled, with var args probe. +NR_LOOPS : 100000 +time delta (cycles): 5574300 +cycles per loop : 55.74 +cycles per loop to get expected variable arguments on x86 : 55.74-53.00=2.74 + +Execute a loop with marker enabled, with var args probe, format string +processing. +NR_LOOPS : 100000 +time delta (cycles): 9622117 +cycles per loop : 96.22 +cycles per loop to dynamically parse arguments + with format string : 96.22-55.74=40.48 + + +* Assembly code + + +- Optimized + +static int my_open(struct inode *inode, struct file *file) +{ + 0: 55 push %ebp + 1: 89 e5 mov %esp,%ebp + 3: 83 ec 0c sub $0xc,%esp + MARK(subsys_mark1, "%d %p", 1, NULL); + 6: b0 00 mov $0x0,%al + 8: 84 c0 test %al,%al + a: 75 07 jne 13 + + return -EPERM; +} + c: b8 ff ff ff ff mov $0xffffffff,%eax + 11: c9 leave + 12: c3 ret + 13: b8 01 00 00 00 mov $0x1,%eax + 18: e8 fc ff ff ff call 19 + 1d: c7 44 24 08 00 00 00 movl $0x0,0x8(%esp) + 24: 00 + 25: c7 44 24 04 01 00 00 movl $0x1,0x4(%esp) + 2c: 00 + 2d: c7 04 24 0d 00 00 00 movl $0xd,(%esp) + 34: ff 15 74 10 00 00 call *0x1074 + 3a: b8 01 00 00 00 mov $0x1,%eax + 3f: e8 fc ff ff ff call 40 + 44: eb c6 jmp c + + +- Generic + +static int my_open(struct inode *inode, struct file *file) +{ + 0: 55 push %ebp + 1: 89 e5 mov %esp,%ebp + 3: 83 ec 0c sub $0xc,%esp + MARK(subsys_mark1, "%d %p", 1, NULL); + 6: 0f b6 05 20 10 00 00 movzbl 0x1020,%eax + d: 84 c0 test %al,%al + f: 75 07 jne 18 + + return -EPERM; +} + 11: b8 ff ff ff ff mov $0xffffffff,%eax + 16: c9 leave + 17: c3 ret + 18: b8 01 00 00 00 mov $0x1,%eax + 1d: e8 fc ff ff ff call 1e + 22: c7 44 24 08 00 00 00 movl $0x0,0x8(%esp) + 29: 00 + 2a: c7 44 24 04 01 00 00 movl $0x1,0x4(%esp) + 31: 00 + 32: c7 04 24 0d 00 00 00 movl $0xd,(%esp) + 39: ff 15 74 10 00 00 call *0x1074 + 3f: b8 01 00 00 00 mov $0x1,%eax + 44: e8 fc ff ff ff call 45 + 49: eb c6 jmp 11 + +* Size (x86) + +- Optimized + +Adds 6 bytes in the "likely" path. +Adds 32 bytes in the "unlikely" path. + +- Generic + +Adds 11 bytes in the "likely" path. +Adds 32 bytes in the "unlikely" path. + + + +Conclusion + +In an empty loop, the generic marker is faster than the optimized marker. This +may be due to better performances of the movzbl instruction over the movb on the +Pentium 4 architecture. However, when we execute a loop of 4kB copy, the impact +of the movzbl becomes greater because it uses the memory bandwidth. + +The preemption disabling and call to a probe itself costs 48.11 cycles, almost +as much as dynamically parsing the format string to get the variable arguments +(40.48 cycles). + +There is almost no difference, on x86, between passing the arguments directly on +the stack and using a variable argument list when its layout is known +statically (0.89 cycles vs 2.74 cycles). + + + diff --git a/tests/markers/markers-microbench-0.2.txt b/tests/markers/markers-microbench-0.2.txt new file mode 100644 index 00000000..6237f34f --- /dev/null +++ b/tests/markers/markers-microbench-0.2.txt @@ -0,0 +1,216 @@ + + +* Microbenchmarks + +Use timestamp counter to calculate the time spent, with interrupts disabled. +Machine : Pentium 4 3GHz +Fully preemptible kernel +marker : MARK(subsys_mark1, "%d %p", 1, NULL); +Linux Kernel Markers 0.19 + +* Execute an empty loop +NR_LOOPS : 10000000 +time delta (cycles): 15026497 +cycles per loop : 1.50 +- i386 "optimized" : immediate value, test and predicted branch + (non connected marker) +NR_LOOPS : 10000000 +time delta (cycles): 40031640 +cycles per loop : 4.00 +cycles per loop for marker : 2.50 +- i386 "generic" : load, test and predicted branch + (non connected marker) +NR_LOOPS : 10000000 +time delta (cycles): 26697878 +cycles per loop : 2.67 +cycles per loop for marker : 1.17 + +* Execute a loop of memcpy 4096 bytes +- Without marker +NR_LOOPS : 10000 +time delta (cycles): 12981555 +cycles per loop : 1298.16 +- i386 "optimized" : immediate value, test and predicted branch + (non connected marker) +NR_LOOPS : 10000 +time delta (cycles): 12982290 +cycles per loop : 1298.23 +cycles per loop for marker : 0.074 +- i386 "generic" : load, test and predicted branch + (non connected marker) +NR_LOOPS : 10000 +time delta (cycles): 13002788 +cycles per loop : 1300.28 +cycles per loop for marker : 2.123 + + +The following tests are done with the "optimized" markers only + +Execute a loop with marker enabled, with i386 "fastcall" register argument + setup, probe empty. +NR_LOOPS : 100000 +time delta (cycles): 4407608 +cycles per loop : 44.08 +cycles per loop to setup arguments in registers : 44.08-4.00=40.08 + +Execute a loop with a marker enabled, with an empty probe. Var args argument + setup, probe empty. +NR_LOOPS : 100000 +time delta (cycles): 5210587 +cycles per loop : 52.11 +additional cycles per loop to setup var args : 52.11-44.08=8.03 + +Execute a loop with marker enabled, with i386 "asmlinkage" arguments expected. + Data is copied by the probe. +NR_LOOPS : 100000 +time delta (cycles): 5299837 +cycles per loop : 53.00 +additional cycles per loop to get arguments in probe (from stack) on x86 : + 53.00-52.11=0.89 + +Execute a loop with marker enabled, with var args probe expecting arguments. + Data is copied by the probe. +NR_LOOPS : 100000 +time delta (cycles): 5574300 +cycles per loop : 55.74 +additional cycles per loop to get expected variable arguments on x86 : + 55.74-53.00=2.74 + +Execute a loop with marker enabled, with var args probe, format string + Data is copied by the probe. +processing. +NR_LOOPS : 100000 +time delta (cycles): 9622117 +cycles per loop : 96.22 +additional cycles per loop to dynamically parse arguments with format string : + 96.22-55.74=40.48 + + +* Assembly code + + +- Optimized + +static int my_open(struct inode *inode, struct file *file) +{ + 0: 55 push %ebp + 1: 89 e5 mov %esp,%ebp + 3: 83 ec 0c sub $0xc,%esp + MARK(subsys_mark1, "%d %p", 1, NULL); + 6: b0 00 mov $0x0,%al + 8: 84 c0 test %al,%al + a: 75 07 jne 13 + + return -EPERM; +} + c: b8 ff ff ff ff mov $0xffffffff,%eax + 11: c9 leave + 12: c3 ret + 13: b8 01 00 00 00 mov $0x1,%eax + 18: e8 fc ff ff ff call 19 + 1d: c7 44 24 08 00 00 00 movl $0x0,0x8(%esp) + 24: 00 + 25: c7 44 24 04 01 00 00 movl $0x1,0x4(%esp) + 2c: 00 + 2d: c7 04 24 0d 00 00 00 movl $0xd,(%esp) + 34: ff 15 74 10 00 00 call *0x1074 + 3a: b8 01 00 00 00 mov $0x1,%eax + 3f: e8 fc ff ff ff call 40 + 44: eb c6 jmp c + + +- Generic + +static int my_open(struct inode *inode, struct file *file) +{ + 0: 55 push %ebp + 1: 89 e5 mov %esp,%ebp + 3: 83 ec 0c sub $0xc,%esp + MARK(subsys_mark1, "%d %p", 1, NULL); + 6: 0f b6 05 20 10 00 00 movzbl 0x1020,%eax + d: 84 c0 test %al,%al + f: 75 07 jne 18 + + return -EPERM; +} + 11: b8 ff ff ff ff mov $0xffffffff,%eax + 16: c9 leave + 17: c3 ret + 18: b8 01 00 00 00 mov $0x1,%eax + 1d: e8 fc ff ff ff call 1e + 22: c7 44 24 08 00 00 00 movl $0x0,0x8(%esp) + 29: 00 + 2a: c7 44 24 04 01 00 00 movl $0x1,0x4(%esp) + 31: 00 + 32: c7 04 24 0d 00 00 00 movl $0xd,(%esp) + 39: ff 15 74 10 00 00 call *0x1074 + 3f: b8 01 00 00 00 mov $0x1,%eax + 44: e8 fc ff ff ff call 45 + 49: eb c6 jmp 11 + +* Size (x86) + +- Optimized + +Adds 6 bytes in the "likely" path. +Adds 32 bytes in the "unlikely" path. + +- Generic + +Adds 11 bytes in the "likely" path. +Adds 32 bytes in the "unlikely" path. + + +* Macrobenchmarks + +Compiling a 2.6.17 kernel on a Pentium 4 3GHz, 1GB ram, cold cache. +Running a 2.6.17 vanilla kernel : +real 8m2.443s +user 7m35.124s +sys 0m34.950s + +Running a 2.6.17 kernel with lttng-0.6.0pre11 markers (no probe connected) : +real 8m1.635s +user 7m34.552s +sys 0m36.298s + +Ping flood on loopback interface : +Running a 2.6.17 vanilla kernel : +136596 packets transmitted, 136596 packets received, 0% packet loss +round-trip min/avg/max = 0.0/0.0/0.1 ms + +real 0m10.840s +user 0m0.360s +sys 0m10.485s + +12601 packets transmitted/s + +Running a 2.6.17 kernel with lttng-0.6.0pre11 markers (no probe connected) : +108504 packets transmitted, 108504 packets received, 0% packet loss +round-trip min/avg/max = 0.0/0.0/0.1 ms + +real 0m8.614s +user 0m0.264s +sys 0m8.353s + +12596 packets transmitted/s + + + +Conclusion + +In an empty loop, the generic marker is faster than the optimized marker. This +may be due to better performances of the movzbl instruction over the movb on the +Pentium 4 architecture. However, when we execute a loop of 4kB copy, the impact +of the movzbl becomes greater because it uses the memory bandwidth. + +The preemption disabling and call to a probe itself costs 48.11 cycles, almost +as much as dynamically parsing the format string to get the variable arguments +(40.48 cycles). + +There is almost no difference, on x86, between passing the arguments directly on +the stack and using a variable argument list when its layout is known +statically (0.89 cycles vs 2.74 cycles). + + + diff --git a/tests/markers/probe-direct.c b/tests/markers/probe-direct.c new file mode 100644 index 00000000..2457ee36 --- /dev/null +++ b/tests/markers/probe-direct.c @@ -0,0 +1,49 @@ +/* probe.c + * + * Loads a function at a marker call site. + * + * (C) Copyright 2006 Mathieu Desnoyers + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + */ + +#include +#include +#include +#include + + +int value; +void *ptr; + +/* function to install */ +#define DO_MARK1_FORMAT "%d %p" +asmlinkage void do_mark1(const char *format, int pavalue, void *paptr) +{ + value = pavalue; + ptr = paptr; +} + +int init_module(void) +{ + int result; + result = marker_set_probe("subsys_mark1", DO_MARK1_FORMAT, + (marker_probe_func*)do_mark1); + if(!result) goto end; + + return 0; + +end: + marker_remove_probe((marker_probe_func*)do_mark1); + return -EPERM; +} + +void cleanup_module(void) +{ + marker_remove_probe((marker_probe_func*)do_mark1); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Probe"); diff --git a/tests/markers/probe-string.c b/tests/markers/probe-string.c new file mode 100644 index 00000000..e904607a --- /dev/null +++ b/tests/markers/probe-string.c @@ -0,0 +1,75 @@ +/* probe.c + * + * Loads a function at a marker call site. + * + * (C) Copyright 2006 Mathieu Desnoyers + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + */ + +#include +#include +#include + + +int value; +void *ptr; + +/* function to install */ +void do_mark1(const char *format, ...) +{ + unsigned int i = 0; + va_list ap; + int control = 0; + + va_start(ap, format); + while(1) { + if(control) { + switch(format[i]) { + case '\0' : + return; + case 'd' : + value = va_arg(ap, int); + case 'p' : + ptr = va_arg(ap, void*); + } + control = 0; + } else { + switch(format[i]) { + case '%' : + control = 1; + break; + case '\0' : + return; + default: + control = 0; + } + } + i++; + } + va_end(ap); +} + +int init_module(void) +{ + int result; + result = marker_set_probe("subsys_mark1", NULL, + do_mark1); + if(!result) goto end; + + return 0; + +end: + marker_remove_probe(do_mark1); + return -EPERM; +} + +void cleanup_module(void) +{ + marker_remove_probe(do_mark1); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Probe"); diff --git a/tests/markers/probe-vararg.c b/tests/markers/probe-vararg.c new file mode 100644 index 00000000..1ada1fd8 --- /dev/null +++ b/tests/markers/probe-vararg.c @@ -0,0 +1,53 @@ +/* probe.c + * + * Loads a function at a marker call site. + * + * (C) Copyright 2006 Mathieu Desnoyers + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + */ + +#include +#include +#include + + +int value; +void *ptr; + +/* function to install */ +#define DO_MARK1_FORMAT "%d %p" +void do_mark1(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + value = va_arg(ap, int); + ptr = va_arg(ap, void*); + + va_end(ap); +} + +int init_module(void) +{ + int result; + result = marker_set_probe("subsys_mark1", DO_MARK1_FORMAT, + (marker_probe_func*)do_mark1); + if(!result) goto end; + + return 0; + +end: + marker_remove_probe(do_mark1); + return -EPERM; +} + +void cleanup_module(void) +{ + marker_remove_probe(do_mark1); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Probe"); diff --git a/tests/markers/probe.c b/tests/markers/probe.c new file mode 100644 index 00000000..73063f50 --- /dev/null +++ b/tests/markers/probe.c @@ -0,0 +1,52 @@ +/* probe.c + * + * Loads a function at a marker call site. + * + * (C) Copyright 2006 Mathieu Desnoyers + * + * This file is released under the GPLv2. + * See the file COPYING for more details. + */ + +#include +#include +#include + +/* function to install */ +#define DO_MARK1_FORMAT "%d %p" +void do_mark1(const char *format, ...) +{ +#if 0 + va_list ap; + int value; + + va_start(ap, format); + value = va_arg(ap, int); + printk("value is %d\n", value); + + va_end(ap); +#endif //0 +} + +int init_module(void) +{ + int result; + result = marker_set_probe("subsys_mark1", DO_MARK1_FORMAT, + (marker_probe_func*)do_mark1); + if(!result) goto end; + + return 0; + +end: + marker_remove_probe(do_mark1); + return -EPERM; +} + +void cleanup_module(void) +{ + marker_remove_probe(do_mark1); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Probe"); diff --git a/tests/markers/test-asm.c b/tests/markers/test-asm.c new file mode 100644 index 00000000..a086135f --- /dev/null +++ b/tests/markers/test-asm.c @@ -0,0 +1,52 @@ +/* test-micro-loop-marker.c + * + * Execute a marker in a loop + */ + +#include +#include +#include +#include +#include +#include +#include + +#define NR_LOOPS 10000 + + +#define COPYLEN 4096 +char test[COPYLEN]; +char src[COPYLEN] = "aaaaaaaaaaaa"; + +struct proc_dir_entry *pentry = NULL; + +static int my_open(struct inode *inode, struct file *file) +{ + MARK(subsys_mark1, "%d %p", 1, NULL); + + return -EPERM; +} + + +static struct file_operations my_operations = { + .open = my_open, +}; + +int init_module(void) +{ + pentry = create_proc_entry("testmark", 0444, NULL); + if (pentry) + pentry->proc_fops = &my_operations; + + return 0; +} + +void cleanup_module(void) +{ + remove_proc_entry("testmark", NULL); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Marker Test"); + diff --git a/tests/markers/test-micro-loop-empty.c b/tests/markers/test-micro-loop-empty.c new file mode 100644 index 00000000..ec1b0f96 --- /dev/null +++ b/tests/markers/test-micro-loop-empty.c @@ -0,0 +1,57 @@ +/* test-micro-loop-marker.c + * + * Execute a marker in a loop + */ + +#include +#include +#include +#include +#include +#include + +#define NR_LOOPS 10000000 + +struct proc_dir_entry *pentry = NULL; + +static int my_open(struct inode *inode, struct file *file) +{ + unsigned int i; + unsigned long flags; + cycles_t time1, time2; + + local_irq_save(flags); + time1 = get_cycles(); + for(i=0; iproc_fops = &my_operations; + + return 0; +} + +void cleanup_module(void) +{ + remove_proc_entry("testmark", NULL); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Marker Test"); + diff --git a/tests/markers/test-micro-loop-marker.c b/tests/markers/test-micro-loop-marker.c new file mode 100644 index 00000000..2ae26c61 --- /dev/null +++ b/tests/markers/test-micro-loop-marker.c @@ -0,0 +1,64 @@ +/* test-micro-loop-marker.c + * + * Execute a marker in a loop + */ + +#include +#include +#include +#include +#include +#include +#include + +#define NR_LOOPS 100000 + + +#define COPYLEN 4096 +char test[COPYLEN]; +char src[COPYLEN] = "aaaaaaaaaaaa"; + +struct proc_dir_entry *pentry = NULL; + +static int my_open(struct inode *inode, struct file *file) +{ + unsigned int i; + unsigned long flags; + cycles_t time1, time2; + + local_irq_save(flags); + time1 = get_cycles(); + for(i=0; iproc_fops = &my_operations; + + return 0; +} + +void cleanup_module(void) +{ + remove_proc_entry("testmark", NULL); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Marker Test"); + diff --git a/tests/markers/test-micro-loop-probe.c b/tests/markers/test-micro-loop-probe.c new file mode 100644 index 00000000..73402781 --- /dev/null +++ b/tests/markers/test-micro-loop-probe.c @@ -0,0 +1,57 @@ +/* test-micro-loop-marker.c + * + * Execute a marker in a loop + */ + +#include +#include +#include +#include +#include +#include + +#define NR_LOOPS 100000 + +struct proc_dir_entry *pentry = NULL; + +static int my_open(struct inode *inode, struct file *file) +{ + volatile unsigned int i; + unsigned long flags; + cycles_t time1, time2; + + local_irq_save(flags); + time1 = get_cycles(); + for(i=0; iproc_fops = &my_operations; + + return 0; +} + +void cleanup_module(void) +{ + remove_proc_entry("testmark", NULL); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Mathieu Desnoyers"); +MODULE_DESCRIPTION("Marker Test"); +