Re: [PATCH] Kprobes: Add kprobes smoke tests that run on boot

From: Jim Keniston
Date: Wed Jan 09 2008 - 15:29:36 EST


On Wed, 2008-01-09 at 00:28 +0100, Andi Kleen wrote:
> > I have no problem with that, but if we want to make it buildable as a
> > module, the call to get_kprobe() needs to be replaced with some other
> > gcc-inline-defeating mechanism, or we need to export get_probe(). I
>
> It's still unclear where noinline does not work (do you have details on that?
> It sounds a little dubious) ...

Here's a simplified version of a module we've used to gauge kprobes
performance. On my system (i386, 2.6.23-rc8 at the moment, gcc version
4.1.2), the module calls the (empty) probed function (probeme) niter
times, but reports zero probe hits -- indicating probeme was inlined
even though it was declared noinline.

If I change probeme to a varargs function, per your suggestion -- see
diffs below -- the proper number of probe hits are reported.
----- noinline.c -----
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/jiffies.h>
#include <linux/kprobes.h>

/*
* Sample usage: insmod noinline.ko niter=5000000
* printk should report 5000000 calls.
*/

static int niter = 0;
module_param(niter, int, 0);
MODULE_PARM_DESC(niter, "iterations");

static int ncalls = 0;

static int counter_hdlr(struct kprobe *p, struct pt_regs *regs)
{
ncalls++;
return 0;
}

// #define noinline __attribute__((noinline))
noinline static void probeme(void)
{
}

struct kprobe kp = {
.addr = (kprobe_opcode_t*) probeme,
.pre_handler = counter_hdlr
};

static int __init noinline_init(void)
{
int ret;
int i;
u64 start, stop;

ret = register_kprobe(&kp);
if (ret != 0) {
printk(KERN_ERR "register_kprobe returns %d\n", ret);
return ret;
}

start = get_jiffies_64();
for (i = 1; i <= niter; i++)
probeme();
stop = get_jiffies_64();
printk(KERN_INFO "noinline test: %d iterations in %lld jiffies\n",
niter, stop-start);
printk(KERN_INFO "Counted %d calls\n", ncalls);
return 0;
}

static void __exit noinline_exit(void)
{
unregister_kprobe(&kp);
printk(KERN_INFO "noinline test: exiting...\n");
}

module_init(noinline_init);
module_exit(noinline_exit);
MODULE_LICENSE("GPL");
----- Change probeme to a varargs function -----
--- noinline.c 2008-01-09 11:26:09.000000000 -0800
+++ noinline2.c 2008-01-09 11:59:54.000000000 -0800
@@ -22,8 +22,13 @@
}

// #define noinline __attribute__((noinline))
-noinline static void probeme(void)
+noinline static void probeme(int nargs, ...)
{
+ va_list args;
+ va_start(args, nargs);
+ while (nargs-- > 0)
+ printk(KERN_INFO "%p\n", va_arg(args, char*));
+ va_end(args);
}

struct kprobe kp = {
@@ -45,9 +50,9 @@

start = get_jiffies_64();
for (i = 1; i <= niter; i++)
- probeme();
+ probeme(0);
stop = get_jiffies_64();
- printk(KERN_INFO "noinline test: %d iterations in %lld jiffies\n",
+ printk(KERN_INFO "noinline2 test: %d iterations in %lld jiffies\n",
niter, stop-start);
printk(KERN_INFO "Counted %d calls\n", ncalls);
return 0;
@@ -56,7 +61,7 @@
static void __exit noinline_exit(void)
{
unregister_kprobe(&kp);
- printk(KERN_INFO "noinline test: exiting...\n");
+ printk(KERN_INFO "noinline2 test: exiting...\n");
}

module_init(noinline_init);

...
> -Andi

Thanks for the suggestions.
Jim

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/