1 /******************************************************************************
2 * common/notifier.c
3 *
4 * Routines to manage notifier chains for passing status changes to any
5 * interested routines.
6 *
7 * Original code from Linux kernel 2.6.27 (Alan Cox <Alan.Cox@linux.org>)
8 */
9
10 #include <xen/init.h>
11 #include <xen/notifier.h>
12
13 /**
14 * notifier_chain_register - Add notifier to a raw notifier chain
15 * @nh: Pointer to head of the raw notifier chain
16 * @n: New entry in notifier chain
17 *
18 * Adds a notifier to a raw notifier chain.
19 * All locking must be provided by the caller.
20 */
notifier_chain_register(struct notifier_head * nh,struct notifier_block * n)21 void __init notifier_chain_register(
22 struct notifier_head *nh, struct notifier_block *n)
23 {
24 struct list_head *chain = &nh->head.chain;
25 struct notifier_block *nb;
26
27 while ( chain->next != &nh->head.chain )
28 {
29 nb = list_entry(chain->next, struct notifier_block, chain);
30 if ( n->priority > nb->priority )
31 break;
32 chain = chain->next;
33 }
34
35 list_add(&n->chain, chain);
36 }
37
38 /**
39 * notifier_chain_unregister - Remove notifier from a raw notifier chain
40 * @nh: Pointer to head of the raw notifier chain
41 * @n: Entry to remove from notifier chain
42 *
43 * Removes a notifier from a raw notifier chain.
44 * All locking must be provided by the caller.
45 */
notifier_chain_unregister(struct notifier_head * nh,struct notifier_block * n)46 void __init notifier_chain_unregister(
47 struct notifier_head *nh, struct notifier_block *n)
48 {
49 list_del(&n->chain);
50 }
51
52 /**
53 * notifier_call_chain - Informs the registered notifiers about an event.
54 * @nh: Pointer to head of the raw notifier chain
55 * @val: Value passed unmodified to notifier function
56 * @v: Pointer passed unmodified to notifier function
57 * @pcursor: If non-NULL, position in chain to start from. Also updated on
58 * return to indicate how far notifications got before stopping.
59 *
60 * Calls each function in a notifier chain in turn. The functions run in an
61 * undefined context. All locking must be provided by the caller.
62 *
63 * If the return value of the notifier can be and'ed with %NOTIFY_STOP_MASK
64 * then notifier_call_chain() will return immediately, with teh return value of
65 * the notifier function which halted execution. Otherwise the return value is
66 * the return value of the last notifier function called.
67 */
notifier_call_chain(struct notifier_head * nh,unsigned long val,void * v,struct notifier_block ** pcursor)68 int notifier_call_chain(
69 struct notifier_head *nh, unsigned long val, void *v,
70 struct notifier_block **pcursor)
71 {
72 int ret = NOTIFY_DONE;
73 struct list_head *cursor;
74 struct notifier_block *nb;
75 bool_t reverse = !!(val & NOTIFY_REVERSE);
76
77 cursor = &(pcursor && *pcursor ? *pcursor : &nh->head)->chain;
78
79 do {
80 cursor = reverse ? cursor->prev : cursor->next;
81 nb = list_entry(cursor, struct notifier_block, chain);
82 if ( cursor == &nh->head.chain )
83 break;
84 ret = nb->notifier_call(nb, val, v);
85 } while ( !(ret & NOTIFY_STOP_MASK) );
86
87 if ( pcursor )
88 *pcursor = nb;
89
90 return ret;
91 }
92