/root/src/xen/xen/common/notifier.c
Line | Count | Source (jump to first uncovered line) |
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 | | */ |
21 | | void __init notifier_chain_register( |
22 | | struct notifier_head *nh, struct notifier_block *n) |
23 | 18 | { |
24 | 18 | struct list_head *chain = &nh->head.chain; |
25 | 18 | struct notifier_block *nb; |
26 | 18 | |
27 | 159 | while ( chain->next != &nh->head.chain ) |
28 | 143 | { |
29 | 143 | nb = list_entry(chain->next, struct notifier_block, chain); |
30 | 143 | if ( n->priority > nb->priority ) |
31 | 2 | break; |
32 | 141 | chain = chain->next; |
33 | 141 | } |
34 | 18 | |
35 | 18 | list_add(&n->chain, chain); |
36 | 18 | } |
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 | | */ |
46 | | void __init notifier_chain_unregister( |
47 | | struct notifier_head *nh, struct notifier_block *n) |
48 | 0 | { |
49 | 0 | list_del(&n->chain); |
50 | 0 | } |
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 | | */ |
68 | | int notifier_call_chain( |
69 | | struct notifier_head *nh, unsigned long val, void *v, |
70 | | struct notifier_block **pcursor) |
71 | 33 | { |
72 | 33 | int ret = NOTIFY_DONE; |
73 | 33 | struct list_head *cursor; |
74 | 33 | struct notifier_block *nb; |
75 | 33 | bool_t reverse = !!(val & NOTIFY_REVERSE); |
76 | 33 | |
77 | 33 | cursor = &(pcursor && *pcursor ? *pcursor : &nh->head)->chain; |
78 | 33 | |
79 | 495 | do { |
80 | 495 | cursor = reverse ? cursor->prev : cursor->next; |
81 | 495 | nb = list_entry(cursor, struct notifier_block, chain); |
82 | 495 | if ( cursor == &nh->head.chain ) |
83 | 33 | break; |
84 | 462 | ret = nb->notifier_call(nb, val, v); |
85 | 462 | } while ( !(ret & NOTIFY_STOP_MASK) ); |
86 | 33 | |
87 | 33 | if ( pcursor ) |
88 | 11 | *pcursor = nb; |
89 | 33 | |
90 | 33 | return ret; |
91 | 33 | } |