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
parent
8f7b50c514
commit
52159d98be
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue