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;
25     struct notifier_block *nb;
26 
27     while ( chain->next != &nh->head )
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 = NULL;
75     bool_t reverse = !!(val & NOTIFY_REVERSE);
76 
77     cursor = pcursor && *pcursor ? &(*pcursor)->chain : &nh->head;
78 
79     do {
80         cursor = reverse ? cursor->prev : cursor->next;
81         if ( cursor == &nh->head )
82             break;
83         nb = list_entry(cursor, struct notifier_block, chain);
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