| From: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| Date: Tue, 19 Mar 2013 14:44:30 +0100 |
| Subject: kernel/SRCU: provide a static initializer |
| |
| There are macros for static initializer for the three out of four |
| possible notifier types, that are: |
| ATOMIC_NOTIFIER_HEAD() |
| BLOCKING_NOTIFIER_HEAD() |
| RAW_NOTIFIER_HEAD() |
| |
| This patch provides a static initilizer for the forth type to make it |
| complete. |
| |
| Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
| --- |
| include/linux/notifier.h | 42 +++++++++++++++++++++++++++++++++--------- |
| include/linux/srcutiny.h | 6 +++--- |
| include/linux/srcutree.h | 6 +++--- |
| 3 files changed, 39 insertions(+), 15 deletions(-) |
| |
| --- a/include/linux/notifier.h |
| +++ b/include/linux/notifier.h |
| @@ -7,7 +7,7 @@ |
| * |
| * Alan Cox <Alan.Cox@linux.org> |
| */ |
| - |
| + |
| #ifndef _LINUX_NOTIFIER_H |
| #define _LINUX_NOTIFIER_H |
| #include <linux/errno.h> |
| @@ -43,9 +43,7 @@ |
| * in srcu_notifier_call_chain(): no cache bounces and no memory barriers. |
| * As compensation, srcu_notifier_chain_unregister() is rather expensive. |
| * SRCU notifier chains should be used when the chain will be called very |
| - * often but notifier_blocks will seldom be removed. Also, SRCU notifier |
| - * chains are slightly more difficult to use because they require special |
| - * runtime initialization. |
| + * often but notifier_blocks will seldom be removed. |
| */ |
| |
| struct notifier_block; |
| @@ -91,7 +89,7 @@ struct srcu_notifier_head { |
| (name)->head = NULL; \ |
| } while (0) |
| |
| -/* srcu_notifier_heads must be initialized and cleaned up dynamically */ |
| +/* srcu_notifier_heads must be cleaned up dynamically */ |
| extern void srcu_init_notifier_head(struct srcu_notifier_head *nh); |
| #define srcu_cleanup_notifier_head(name) \ |
| cleanup_srcu_struct(&(name)->srcu); |
| @@ -104,7 +102,13 @@ extern void srcu_init_notifier_head(stru |
| .head = NULL } |
| #define RAW_NOTIFIER_INIT(name) { \ |
| .head = NULL } |
| -/* srcu_notifier_heads cannot be initialized statically */ |
| + |
| +#define SRCU_NOTIFIER_INIT(name, pcpu) \ |
| + { \ |
| + .mutex = __MUTEX_INITIALIZER(name.mutex), \ |
| + .head = NULL, \ |
| + .srcu = __SRCU_STRUCT_INIT(name.srcu, pcpu), \ |
| + } |
| |
| #define ATOMIC_NOTIFIER_HEAD(name) \ |
| struct atomic_notifier_head name = \ |
| @@ -116,6 +120,26 @@ extern void srcu_init_notifier_head(stru |
| struct raw_notifier_head name = \ |
| RAW_NOTIFIER_INIT(name) |
| |
| +#ifdef CONFIG_TREE_SRCU |
| +#define _SRCU_NOTIFIER_HEAD(name, mod) \ |
| + static DEFINE_PER_CPU(struct srcu_data, \ |
| + name##_head_srcu_data); \ |
| + mod struct srcu_notifier_head name = \ |
| + SRCU_NOTIFIER_INIT(name, name##_head_srcu_data) |
| + |
| +#else |
| +#define _SRCU_NOTIFIER_HEAD(name, mod) \ |
| + mod struct srcu_notifier_head name = \ |
| + SRCU_NOTIFIER_INIT(name, name) |
| + |
| +#endif |
| + |
| +#define SRCU_NOTIFIER_HEAD(name) \ |
| + _SRCU_NOTIFIER_HEAD(name, ) |
| + |
| +#define SRCU_NOTIFIER_HEAD_STATIC(name) \ |
| + _SRCU_NOTIFIER_HEAD(name, static) |
| + |
| #ifdef __KERNEL__ |
| |
| extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh, |
| @@ -185,12 +209,12 @@ static inline int notifier_to_errno(int |
| |
| /* |
| * Declared notifiers so far. I can imagine quite a few more chains |
| - * over time (eg laptop power reset chains, reboot chain (to clean |
| + * over time (eg laptop power reset chains, reboot chain (to clean |
| * device units up), device [un]mount chain, module load/unload chain, |
| - * low memory chain, screenblank chain (for plug in modular screenblankers) |
| + * low memory chain, screenblank chain (for plug in modular screenblankers) |
| * VC switch chains (for loadable kernel svgalib VC switch helpers) etc... |
| */ |
| - |
| + |
| /* CPU notfiers are defined in include/linux/cpu.h. */ |
| |
| /* netdevice notifiers are defined in include/linux/netdevice.h */ |
| --- a/include/linux/srcutiny.h |
| +++ b/include/linux/srcutiny.h |
| @@ -43,7 +43,7 @@ struct srcu_struct { |
| |
| void srcu_drive_gp(struct work_struct *wp); |
| |
| -#define __SRCU_STRUCT_INIT(name) \ |
| +#define __SRCU_STRUCT_INIT(name, __ignored) \ |
| { \ |
| .srcu_wq = __SWAIT_QUEUE_HEAD_INITIALIZER(name.srcu_wq), \ |
| .srcu_cb_tail = &name.srcu_cb_head, \ |
| @@ -56,9 +56,9 @@ void srcu_drive_gp(struct work_struct *w |
| * Tree SRCU, which needs some per-CPU data. |
| */ |
| #define DEFINE_SRCU(name) \ |
| - struct srcu_struct name = __SRCU_STRUCT_INIT(name) |
| + struct srcu_struct name = __SRCU_STRUCT_INIT(name, name) |
| #define DEFINE_STATIC_SRCU(name) \ |
| - static struct srcu_struct name = __SRCU_STRUCT_INIT(name) |
| + static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name) |
| |
| void synchronize_srcu(struct srcu_struct *sp); |
| |
| --- a/include/linux/srcutree.h |
| +++ b/include/linux/srcutree.h |
| @@ -104,9 +104,9 @@ struct srcu_struct { |
| #define SRCU_STATE_SCAN1 1 |
| #define SRCU_STATE_SCAN2 2 |
| |
| -#define __SRCU_STRUCT_INIT(name) \ |
| +#define __SRCU_STRUCT_INIT(name, pcpu_name) \ |
| { \ |
| - .sda = &name##_srcu_data, \ |
| + .sda = &pcpu_name, \ |
| .lock = __SPIN_LOCK_UNLOCKED(name.lock), \ |
| .srcu_gp_seq_needed = 0 - 1, \ |
| __SRCU_DEP_MAP_INIT(name) \ |
| @@ -133,7 +133,7 @@ struct srcu_struct { |
| */ |
| #define __DEFINE_SRCU(name, is_static) \ |
| static DEFINE_PER_CPU(struct srcu_data, name##_srcu_data);\ |
| - is_static struct srcu_struct name = __SRCU_STRUCT_INIT(name) |
| + is_static struct srcu_struct name = __SRCU_STRUCT_INIT(name, name##_srcu_data) |
| #define DEFINE_SRCU(name) __DEFINE_SRCU(name, /* not static */) |
| #define DEFINE_STATIC_SRCU(name) __DEFINE_SRCU(name, static) |
| |