1
0
Fork 0

jump label: Convert dynamic debug to use jump labels

Convert the 'dynamic debug' infrastructure to use jump labels.

Signed-off-by: Jason Baron <jbaron@redhat.com>
LKML-Reference: <b77627358cea3e27d7be4386f45f66219afb8452.1284733808.git.jbaron@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
hifive-unleashed-5.1
Jason Baron 2010-09-17 11:09:17 -04:00 committed by Steven Rostedt
parent 8f7b50c514
commit 52159d98be
5 changed files with 26 additions and 132 deletions

View File

@ -1,6 +1,8 @@
#ifndef _DYNAMIC_DEBUG_H #ifndef _DYNAMIC_DEBUG_H
#define _DYNAMIC_DEBUG_H #define _DYNAMIC_DEBUG_H
#include <linux/jump_label.h>
/* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which /* dynamic_printk_enabled, and dynamic_printk_enabled2 are bitmasks in which
* bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They * bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
* use independent hash functions, to reduce the chance of false positives. * use independent hash functions, to reduce the chance of false positives.
@ -22,8 +24,6 @@ struct _ddebug {
const char *function; const char *function;
const char *filename; const char *filename;
const char *format; const char *format;
char primary_hash;
char secondary_hash;
unsigned int lineno:24; unsigned int lineno:24;
/* /*
* The flags field controls the behaviour at the callsite. * The flags field controls the behaviour at the callsite.
@ -33,6 +33,7 @@ struct _ddebug {
#define _DPRINTK_FLAGS_PRINT (1<<0) /* printk() a message using the format */ #define _DPRINTK_FLAGS_PRINT (1<<0) /* printk() a message using the format */
#define _DPRINTK_FLAGS_DEFAULT 0 #define _DPRINTK_FLAGS_DEFAULT 0
unsigned int flags:8; unsigned int flags:8;
char enabled;
} __attribute__((aligned(8))); } __attribute__((aligned(8)));
@ -42,33 +43,35 @@ int ddebug_add_module(struct _ddebug *tab, unsigned int n,
#if defined(CONFIG_DYNAMIC_DEBUG) #if defined(CONFIG_DYNAMIC_DEBUG)
extern int ddebug_remove_module(const char *mod_name); extern int ddebug_remove_module(const char *mod_name);
#define __dynamic_dbg_enabled(dd) ({ \
int __ret = 0; \
if (unlikely((dynamic_debug_enabled & (1LL << DEBUG_HASH)) && \
(dynamic_debug_enabled2 & (1LL << DEBUG_HASH2)))) \
if (unlikely(dd.flags)) \
__ret = 1; \
__ret; })
#define dynamic_pr_debug(fmt, ...) do { \ #define dynamic_pr_debug(fmt, ...) do { \
__label__ do_printk; \
__label__ out; \
static struct _ddebug descriptor \ static struct _ddebug descriptor \
__used \ __used \
__attribute__((section("__verbose"), aligned(8))) = \ __attribute__((section("__verbose"), aligned(8))) = \
{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \ { KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__, \
DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ _DPRINTK_FLAGS_DEFAULT }; \
if (__dynamic_dbg_enabled(descriptor)) \ JUMP_LABEL(&descriptor.enabled, do_printk); \
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \ goto out; \
do_printk: \
printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); \
out: ; \
} while (0) } while (0)
#define dynamic_dev_dbg(dev, fmt, ...) do { \ #define dynamic_dev_dbg(dev, fmt, ...) do { \
__label__ do_printk; \
__label__ out; \
static struct _ddebug descriptor \ static struct _ddebug descriptor \
__used \ __used \
__attribute__((section("__verbose"), aligned(8))) = \ __attribute__((section("__verbose"), aligned(8))) = \
{ KBUILD_MODNAME, __func__, __FILE__, fmt, DEBUG_HASH, \ { KBUILD_MODNAME, __func__, __FILE__, fmt, __LINE__, \
DEBUG_HASH2, __LINE__, _DPRINTK_FLAGS_DEFAULT }; \ _DPRINTK_FLAGS_DEFAULT }; \
if (__dynamic_dbg_enabled(descriptor)) \ JUMP_LABEL(&descriptor.enabled, do_printk); \
dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \ goto out; \
do_printk: \
dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); \
out: ; \
} while (0) } while (0)
#else #else

View File

@ -26,19 +26,11 @@
#include <linux/dynamic_debug.h> #include <linux/dynamic_debug.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/jump_label.h>
extern struct _ddebug __start___verbose[]; extern struct _ddebug __start___verbose[];
extern struct _ddebug __stop___verbose[]; extern struct _ddebug __stop___verbose[];
/* dynamic_debug_enabled, and dynamic_debug_enabled2 are bitmasks in which
* bit n is set to 1 if any modname hashes into the bucket n, 0 otherwise. They
* use independent hash functions, to reduce the chance of false positives.
*/
long long dynamic_debug_enabled;
EXPORT_SYMBOL_GPL(dynamic_debug_enabled);
long long dynamic_debug_enabled2;
EXPORT_SYMBOL_GPL(dynamic_debug_enabled2);
struct ddebug_table { struct ddebug_table {
struct list_head link; struct list_head link;
char *mod_name; char *mod_name;
@ -87,26 +79,6 @@ static char *ddebug_describe_flags(struct _ddebug *dp, char *buf,
return buf; return buf;
} }
/*
* must be called with ddebug_lock held
*/
static int disabled_hash(char hash, bool first_table)
{
struct ddebug_table *dt;
char table_hash_value;
list_for_each_entry(dt, &ddebug_tables, link) {
if (first_table)
table_hash_value = dt->ddebugs->primary_hash;
else
table_hash_value = dt->ddebugs->secondary_hash;
if (dt->num_enabled && (hash == table_hash_value))
return 0;
}
return 1;
}
/* /*
* Search the tables for _ddebug's which match the given * Search the tables for _ddebug's which match the given
* `query' and apply the `flags' and `mask' to them. Tells * `query' and apply the `flags' and `mask' to them. Tells
@ -170,17 +142,9 @@ static void ddebug_change(const struct ddebug_query *query,
dt->num_enabled++; dt->num_enabled++;
dp->flags = newflags; dp->flags = newflags;
if (newflags) { if (newflags) {
dynamic_debug_enabled |= enable_jump_label(&dp->enabled);
(1LL << dp->primary_hash);
dynamic_debug_enabled2 |=
(1LL << dp->secondary_hash);
} else { } else {
if (disabled_hash(dp->primary_hash, true)) disable_jump_label(&dp->enabled);
dynamic_debug_enabled &=
~(1LL << dp->primary_hash);
if (disabled_hash(dp->secondary_hash, false))
dynamic_debug_enabled2 &=
~(1LL << dp->secondary_hash);
} }
if (verbose) if (verbose)
printk(KERN_INFO printk(KERN_INFO

View File

@ -101,14 +101,6 @@ basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
modname_flags = $(if $(filter 1,$(words $(modname))),\ modname_flags = $(if $(filter 1,$(words $(modname))),\
-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
#hash values
ifdef CONFIG_DYNAMIC_DEBUG
debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
-D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
else
debug_flags =
endif
orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \ orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
$(ccflags-y) $(CFLAGS_$(basetarget).o) $(ccflags-y) $(CFLAGS_$(basetarget).o)
_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags)) _c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
@ -152,8 +144,7 @@ endif
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__c_flags) $(modkern_cflags) \ $(__c_flags) $(modkern_cflags) \
-D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \ -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
$(debug_flags)
a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
$(__a_flags) $(modkern_aflags) $(__a_flags) $(modkern_aflags)

View File

@ -9,7 +9,7 @@
# fixdep: Used to generate dependency information during build process # fixdep: Used to generate dependency information during build process
# docproc: Used in Documentation/DocBook # docproc: Used in Documentation/DocBook
hostprogs-y := fixdep docproc hash hostprogs-y := fixdep docproc
always := $(hostprogs-y) always := $(hostprogs-y)
# fixdep is needed to compile other host programs # fixdep is needed to compile other host programs

View File

@ -1,64 +0,0 @@
/*
* Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DYNAMIC_DEBUG_HASH_BITS 6
static const char *program;
static void usage(void)
{
printf("Usage: %s <djb2|r5> <modname>\n", program);
exit(1);
}
/* djb2 hashing algorithm by Dan Bernstein. From:
* http://www.cse.yorku.ca/~oz/hash.html
*/
static unsigned int djb2_hash(char *str)
{
unsigned long hash = 5381;
int c;
c = *str;
while (c) {
hash = ((hash << 5) + hash) + c;
c = *++str;
}
return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
}
static unsigned int r5_hash(char *str)
{
unsigned long hash = 0;
int c;
c = *str;
while (c) {
hash = (hash + (c << 4) + (c >> 4)) * 11;
c = *++str;
}
return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
}
int main(int argc, char *argv[])
{
program = argv[0];
if (argc != 3)
usage();
if (!strcmp(argv[1], "djb2"))
printf("%d\n", djb2_hash(argv[2]));
else if (!strcmp(argv[1], "r5"))
printf("%d\n", r5_hash(argv[2]));
else
usage();
exit(0);
}