linux/include/linux/notifier.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2/*
   3 *      Routines to manage notifier chains for passing status changes to any
   4 *      interested routines. We need this instead of hard coded call lists so
   5 *      that modules can poke their nose into the innards. The network devices
   6 *      needed them so here they are for the rest of you.
   7 *
   8 *                              Alan Cox <Alan.Cox@linux.org>
   9 */
  10 
  11#ifndef _LINUX_NOTIFIER_H
  12#define _LINUX_NOTIFIER_H
  13#include <linux/errno.h>
  14#include <linux/mutex.h>
  15#include <linux/rwsem.h>
  16#include <linux/srcu.h>
  17
  18/*
  19 * Notifier chains are of four types:
  20 *
  21 *      Atomic notifier chains: Chain callbacks run in interrupt/atomic
  22 *              context. Callouts are not allowed to block.
  23 *      Blocking notifier chains: Chain callbacks run in process context.
  24 *              Callouts are allowed to block.
  25 *      Raw notifier chains: There are no restrictions on callbacks,
  26 *              registration, or unregistration.  All locking and protection
  27 *              must be provided by the caller.
  28 *      SRCU notifier chains: A variant of blocking notifier chains, with
  29 *              the same restrictions.
  30 *
  31 * atomic_notifier_chain_register() may be called from an atomic context,
  32 * but blocking_notifier_chain_register() and srcu_notifier_chain_register()
  33 * must be called from a process context.  Ditto for the corresponding
  34 * _unregister() routines.
  35 *
  36 * atomic_notifier_chain_unregister(), blocking_notifier_chain_unregister(),
  37 * and srcu_notifier_chain_unregister() _must not_ be called from within
  38 * the call chain.
  39 *
  40 * SRCU notifier chains are an alternative form of blocking notifier chains.
  41 * They use SRCU (Sleepable Read-Copy Update) instead of rw-semaphores for
  42 * protection of the chain links.  This means there is _very_ low overhead
  43 * in srcu_notifier_call_chain(): no cache bounces and no memory barriers.
  44 * As compensation, srcu_notifier_chain_unregister() is rather expensive.
  45 * SRCU notifier chains should be used when the chain will be called very
  46 * often but notifier_blocks will seldom be removed.
  47 */
  48
  49struct notifier_block;
  50
  51typedef int (*notifier_fn_t)(struct notifier_block *nb,
  52                        unsigned long action, void *data);
  53
  54struct notifier_block {
  55        notifier_fn_t notifier_call;
  56        struct notifier_block __rcu *next;
  57        int priority;
  58};
  59
  60struct atomic_notifier_head {
  61        spinlock_t lock;
  62        struct notifier_block __rcu *head;
  63};
  64
  65struct blocking_notifier_head {
  66        struct rw_semaphore rwsem;
  67        struct notifier_block __rcu *head;
  68};
  69
  70struct raw_notifier_head {
  71        struct notifier_block __rcu *head;
  72};
  73
  74struct srcu_notifier_head {
  75        struct mutex mutex;
  76        struct srcu_struct srcu;
  77        struct notifier_block __rcu *head;
  78};
  79
  80#define ATOMIC_INIT_NOTIFIER_HEAD(name) do {    \
  81                spin_lock_init(&(name)->lock);  \
  82                (name)->head = NULL;            \
  83        } while (0)
  84#define BLOCKING_INIT_NOTIFIER_HEAD(name) do {  \
  85                init_rwsem(&(name)->rwsem);     \
  86                (name)->head = NULL;            \
  87        } while (0)
  88#define RAW_INIT_NOTIFIER_HEAD(name) do {       \
  89                (name)->head = NULL;            \
  90        } while (0)
  91
  92/* srcu_notifier_heads must be cleaned up dynamically */
  93extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
  94#define srcu_cleanup_notifier_head(name)        \
  95                cleanup_srcu_struct(&(name)->srcu);
  96
  97#define ATOMIC_NOTIFIER_INIT(name) {                            \
  98                .lock = __SPIN_LOCK_UNLOCKED(name.lock),        \
  99                .head = NULL }
 100#define BLOCKING_NOTIFIER_INIT(name) {                          \
 101                .rwsem = __RWSEM_INITIALIZER((name).rwsem),     \
 102                .head = NULL }
 103#define RAW_NOTIFIER_INIT(name) {                               \
 104                .head = NULL }
 105
 106#define SRCU_NOTIFIER_INIT(name, pcpu)                          \
 107        {                                                       \
 108                .mutex = __MUTEX_INITIALIZER(name.mutex),       \
 109                .head = NULL,                                   \
 110                .srcu = __SRCU_STRUCT_INIT(name.srcu, pcpu),    \
 111        }
 112
 113#define ATOMIC_NOTIFIER_HEAD(name)                              \
 114        struct atomic_notifier_head name =                      \
 115                ATOMIC_NOTIFIER_INIT(name)
 116#define BLOCKING_NOTIFIER_HEAD(name)                            \
 117        struct blocking_notifier_head name =                    \
 118                BLOCKING_NOTIFIER_INIT(name)
 119#define RAW_NOTIFIER_HEAD(name)                                 \
 120        struct raw_notifier_head name =                         \
 121                RAW_NOTIFIER_INIT(name)
 122
 123#ifdef CONFIG_TREE_SRCU
 124#define _SRCU_NOTIFIER_HEAD(name, mod)                          \
 125        static DEFINE_PER_CPU(struct srcu_data, name##_head_srcu_data); \
 126        mod struct srcu_notifier_head name =                    \
 127                        SRCU_NOTIFIER_INIT(name, name##_head_srcu_data)
 128
 129#else
 130#define _SRCU_NOTIFIER_HEAD(name, mod)                          \
 131        mod struct srcu_notifier_head name =                    \
 132                        SRCU_NOTIFIER_INIT(name, name)
 133
 134#endif
 135
 136#define SRCU_NOTIFIER_HEAD(name)                                \
 137        _SRCU_NOTIFIER_HEAD(name, /* not static */)
 138
 139#define SRCU_NOTIFIER_HEAD_STATIC(name)                         \
 140        _SRCU_NOTIFIER_HEAD(name, static)
 141
 142#ifdef __KERNEL__
 143
 144extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
 145                struct notifier_block *nb);
 146extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
 147                struct notifier_block *nb);
 148extern int raw_notifier_chain_register(struct raw_notifier_head *nh,
 149                struct notifier_block *nb);
 150extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
 151                struct notifier_block *nb);
 152
 153extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
 154                struct notifier_block *nb);
 155extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
 156                struct notifier_block *nb);
 157extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
 158                struct notifier_block *nb);
 159extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
 160                struct notifier_block *nb);
 161
 162extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
 163                unsigned long val, void *v);
 164extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
 165                unsigned long val, void *v);
 166extern int raw_notifier_call_chain(struct raw_notifier_head *nh,
 167                unsigned long val, void *v);
 168extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
 169                unsigned long val, void *v);
 170
 171extern int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh,
 172                unsigned long val_up, unsigned long val_down, void *v);
 173extern int raw_notifier_call_chain_robust(struct raw_notifier_head *nh,
 174                unsigned long val_up, unsigned long val_down, void *v);
 175
 176#define NOTIFY_DONE             0x0000          /* Don't care */
 177#define NOTIFY_OK               0x0001          /* Suits me */
 178#define NOTIFY_STOP_MASK        0x8000          /* Don't call further */
 179#define NOTIFY_BAD              (NOTIFY_STOP_MASK|0x0002)
 180                                                /* Bad/Veto action */
 181/*
 182 * Clean way to return from the notifier and stop further calls.
 183 */
 184#define NOTIFY_STOP             (NOTIFY_OK|NOTIFY_STOP_MASK)
 185
 186/* Encapsulate (negative) errno value (in particular, NOTIFY_BAD <=> EPERM). */
 187static inline int notifier_from_errno(int err)
 188{
 189        if (err)
 190                return NOTIFY_STOP_MASK | (NOTIFY_OK - err);
 191
 192        return NOTIFY_OK;
 193}
 194
 195/* Restore (negative) errno value from notify return value. */
 196static inline int notifier_to_errno(int ret)
 197{
 198        ret &= ~NOTIFY_STOP_MASK;
 199        return ret > NOTIFY_OK ? NOTIFY_OK - ret : 0;
 200}
 201
 202/*
 203 *      Declared notifiers so far. I can imagine quite a few more chains
 204 *      over time (eg laptop power reset chains, reboot chain (to clean 
 205 *      device units up), device [un]mount chain, module load/unload chain,
 206 *      low memory chain, screenblank chain (for plug in modular screenblankers) 
 207 *      VC switch chains (for loadable kernel svgalib VC switch helpers) etc...
 208 */
 209 
 210/* CPU notfiers are defined in include/linux/cpu.h. */
 211
 212/* netdevice notifiers are defined in include/linux/netdevice.h */
 213
 214/* reboot notifiers are defined in include/linux/reboot.h. */
 215
 216/* Hibernation and suspend events are defined in include/linux/suspend.h. */
 217
 218/* Virtual Terminal events are defined in include/linux/vt.h. */
 219
 220#define NETLINK_URELEASE        0x0001  /* Unicast netlink socket released */
 221
 222/* Console keyboard events.
 223 * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
 224 * KBD_KEYSYM. */
 225#define KBD_KEYCODE             0x0001 /* Keyboard keycode, called before any other */
 226#define KBD_UNBOUND_KEYCODE     0x0002 /* Keyboard keycode which is not bound to any other */
 227#define KBD_UNICODE             0x0003 /* Keyboard unicode */
 228#define KBD_KEYSYM              0x0004 /* Keyboard keysym */
 229#define KBD_POST_KEYSYM         0x0005 /* Called after keyboard keysym interpretation */
 230
 231extern struct blocking_notifier_head reboot_notifier_list;
 232
 233#endif /* __KERNEL__ */
 234#endif /* _LINUX_NOTIFIER_H */
 235