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 blocking_notifier_chain_cond_register(
 154                struct blocking_notifier_head *nh,
 155                struct notifier_block *nb);
 156
 157extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
 158                struct notifier_block *nb);
 159extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
 160                struct notifier_block *nb);
 161extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
 162                struct notifier_block *nb);
 163extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
 164                struct notifier_block *nb);
 165
 166extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
 167                unsigned long val, void *v);
 168extern int __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
 169        unsigned long val, void *v, int nr_to_call, int *nr_calls);
 170extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
 171                unsigned long val, void *v);
 172extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
 173        unsigned long val, void *v, int nr_to_call, int *nr_calls);
 174extern int raw_notifier_call_chain(struct raw_notifier_head *nh,
 175                unsigned long val, void *v);
 176extern int __raw_notifier_call_chain(struct raw_notifier_head *nh,
 177        unsigned long val, void *v, int nr_to_call, int *nr_calls);
 178extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
 179                unsigned long val, void *v);
 180extern int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
 181        unsigned long val, void *v, int nr_to_call, int *nr_calls);
 182
 183#define NOTIFY_DONE             0x0000          /* Don't care */
 184#define NOTIFY_OK               0x0001          /* Suits me */
 185#define NOTIFY_STOP_MASK        0x8000          /* Don't call further */
 186#define NOTIFY_BAD              (NOTIFY_STOP_MASK|0x0002)
 187                                                /* Bad/Veto action */
 188/*
 189 * Clean way to return from the notifier and stop further calls.
 190 */
 191#define NOTIFY_STOP             (NOTIFY_OK|NOTIFY_STOP_MASK)
 192
 193/* Encapsulate (negative) errno value (in particular, NOTIFY_BAD <=> EPERM). */
 194static inline int notifier_from_errno(int err)
 195{
 196        if (err)
 197                return NOTIFY_STOP_MASK | (NOTIFY_OK - err);
 198
 199        return NOTIFY_OK;
 200}
 201
 202/* Restore (negative) errno value from notify return value. */
 203static inline int notifier_to_errno(int ret)
 204{
 205        ret &= ~NOTIFY_STOP_MASK;
 206        return ret > NOTIFY_OK ? NOTIFY_OK - ret : 0;
 207}
 208
 209/*
 210 *      Declared notifiers so far. I can imagine quite a few more chains
 211 *      over time (eg laptop power reset chains, reboot chain (to clean 
 212 *      device units up), device [un]mount chain, module load/unload chain,
 213 *      low memory chain, screenblank chain (for plug in modular screenblankers) 
 214 *      VC switch chains (for loadable kernel svgalib VC switch helpers) etc...
 215 */
 216 
 217/* CPU notfiers are defined in include/linux/cpu.h. */
 218
 219/* netdevice notifiers are defined in include/linux/netdevice.h */
 220
 221/* reboot notifiers are defined in include/linux/reboot.h. */
 222
 223/* Hibernation and suspend events are defined in include/linux/suspend.h. */
 224
 225/* Virtual Terminal events are defined in include/linux/vt.h. */
 226
 227#define NETLINK_URELEASE        0x0001  /* Unicast netlink socket released */
 228
 229/* Console keyboard events.
 230 * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
 231 * KBD_KEYSYM. */
 232#define KBD_KEYCODE             0x0001 /* Keyboard keycode, called before any other */
 233#define KBD_UNBOUND_KEYCODE     0x0002 /* Keyboard keycode which is not bound to any other */
 234#define KBD_UNICODE             0x0003 /* Keyboard unicode */
 235#define KBD_KEYSYM              0x0004 /* Keyboard keysym */
 236#define KBD_POST_KEYSYM         0x0005 /* Called after keyboard keysym interpretation */
 237
 238extern struct blocking_notifier_head reboot_notifier_list;
 239
 240#endif /* __KERNEL__ */
 241#endif /* _LINUX_NOTIFIER_H */
 242