<a>int atomic_notifier_chain_register(struct atomic_notifier_head *nh, struct notifier_block *n)</a>
<a>{</a>
<a>unsigned long flags;</a>
<a>int ret;</a>
<a>spin_lock_irqsave(&nh->lock, flags);</a>
<a>ret = notifier_chain_register(&nh->head, n);</a>
<a>spin_unlock_irqrestore(&nh->lock, flags);</a>
<a>return ret;</a>
<a>}</a>
<a>static int notifier_chain_register(struct notifier_block **nl, struct notifier_block *n)</a>
<a>while ((*nl) != NULL) {</a>
<a>if (n->priority > (*nl)->priority)</a>
<a>break;</a>
<a>nl = &((*nl)->next);</a>
<a>n->next = *nl;</a>
<a>rcu_assign_pointer(*nl, n);</a>
<a>return 0;</a>
<a>int __kprobes __atomic_notifier_call_chain(struct atomic_notifier_head *nh, unsigned long val, void *v, int nr_to_call, int *nr_calls)</a>
<a>rcu_read_lock();</a>
<a>ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);</a>
<a>rcu_read_unlock();</a>
<a>static int __kprobes notifier_call_chain(struct notifier_block **nl, unsigned long val, void *v, int nr_to_call, int *nr_calls)</a>
<a>int ret = NOTIFY_DONE;</a>
<a>struct notifier_block *nb, *next_nb;</a>
<a>nb = rcu_dereference(*nl);</a>
<a>while (nb && nr_to_call) {</a>
<a>next_nb = rcu_dereference(nb->next);</a>
<a>if (nr_calls)</a>
<a>(*nr_calls)++;</a>
<a>if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)</a>
<a>nb = next_nb;</a>
<a>nr_to_call--;</a>
本文轉自 dog250 51CTO部落格,原文連結:http://blog.51cto.com/dog250/1273649