kernel/SRCU: provide a static initializer
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Fri, 25 May 2018 10:19:57 +0000 (12:19 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 30 May 2018 08:11:34 +0000 (10:11 +0200)
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>
Tested-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
include/linux/notifier.h
include/linux/srcutiny.h
include/linux/srcutree.h

index 6d73111..f35c7bf 100644 (file)
@@ -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(struct srcu_notifier_head *nh);
                .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(struct srcu_notifier_head *nh);
        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, /* not static */)
+
+#define SRCU_NOTIFIER_HEAD_STATIC(name)                                \
+       _SRCU_NOTIFIER_HEAD(name, static)
+
 #ifdef __KERNEL__
 
 extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
index 261471f..f41d2fb 100644 (file)
@@ -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 *wp);
  * 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);
 
index 4eda108..745d4ca 100644 (file)
@@ -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)