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