From fbdb49ffdcff694972edebb91fd5bac19810a193 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 21 Jul 2008 13:39:26 -0700 Subject: [PATCH] Verify that sleeping is allowed in chain contexts where Broadcom will need to. --- datapath/chain.c | 3 +++ .../compat-2.4/include/linux/kernel.h | 23 +++++++++++++++++++ datapath/linux-2.4/compat-2.4/kernel.c | 19 +++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/datapath/chain.c b/datapath/chain.c index f7ea1dc6..71e00ee6 100644 --- a/datapath/chain.c +++ b/datapath/chain.c @@ -89,6 +89,7 @@ int chain_insert(struct sw_chain *chain, struct sw_flow *flow) { int i; + might_sleep(); for (i = 0; i < chain->n_tables; i++) { struct sw_table *t = chain->tables[i]; if (t->insert(t, flow)) @@ -112,6 +113,7 @@ int chain_delete(struct sw_chain *chain, const struct sw_flow_key *key, int count = 0; int i; + might_sleep(); for (i = 0; i < chain->n_tables; i++) { struct sw_table *t = chain->tables[i]; count += t->delete(t, key, priority, strict); @@ -133,6 +135,7 @@ int chain_timeout(struct sw_chain *chain) int count = 0; int i; + might_sleep(); for (i = 0; i < chain->n_tables; i++) { struct sw_table *t = chain->tables[i]; count += t->timeout(chain->dp, t); diff --git a/datapath/linux-2.4/compat-2.4/include/linux/kernel.h b/datapath/linux-2.4/compat-2.4/include/linux/kernel.h index 329dab53..543ba9b6 100644 --- a/datapath/linux-2.4/compat-2.4/include/linux/kernel.h +++ b/datapath/linux-2.4/compat-2.4/include/linux/kernel.h @@ -2,6 +2,7 @@ #define __LINUX_KERNEL_WRAPPER_H 1 #include_next +#include /** * container_of - cast a member of a structure out to the containing structure @@ -40,4 +41,26 @@ int vprintk(const char *msg, ...) /* Force a compilation error if condition is true */ #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) +/** + * might_sleep - annotation for functions that can sleep + * + * this macro will print a stack trace if it is executed in an atomic + * context (spinlock, irq-handler, ...). + * + * This is a useful debugging help to be able to catch problems early and not + * be bitten later when the calling function happens to sleep when it is not + * supposed to. + */ +#define might_resched() do { } while (0) + +#ifdef CONFIG_DEBUG_SPINLOCK + void __might_sleep(char *file, int line); +# define might_sleep() \ + do { __might_sleep(__FILE__, __LINE__); might_resched(); } while (0) +#else +# define might_sleep() do { might_resched(); } while (0) +#endif + +#define might_sleep_if(cond) do { if (cond) might_sleep(); } while (0) + #endif diff --git a/datapath/linux-2.4/compat-2.4/kernel.c b/datapath/linux-2.4/compat-2.4/kernel.c index a08bb2d8..36d2d8ae 100644 --- a/datapath/linux-2.4/compat-2.4/kernel.c +++ b/datapath/linux-2.4/compat-2.4/kernel.c @@ -2,9 +2,11 @@ * Distributed under the terms of the GNU GPL version 2. */ +#include #include #include #include +#include int vprintk(const char *msg, ...) { @@ -25,3 +27,20 @@ int vprintk(const char *msg, ...) } EXPORT_SYMBOL(vprintk); + +#ifdef CONFIG_DEBUG_SPINLOCK +void __might_sleep(char *file, int line) +{ + static unsigned long prev_jiffy; /* ratelimiting */ + + if ((in_interrupt()) && !oops_in_progress) { + if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy) + return; + prev_jiffy = jiffies; + printk(KERN_ERR "BUG: sleeping function called from invalid" + " context at %s:%d\n", file, line); + dump_stack(); + } +} +EXPORT_SYMBOL(__might_sleep); +#endif -- 2.30.2