On Wed, Dec 11, 2002 at 10:13:33PM +0000, Alan Cox wrote:
> On Wed, 2002-12-11 at 20:27, John Levon wrote:
> > There are notifiers being used that sleep inside the called notifiers.
> >
> > You could easily make a __notifier_call_chain that is lockless and
> > another one that readlocks the notifier_lock ...
>
> The notifier chains assume the users will do the locking needed for
> them. It might be possible to do cool things there with RCU
>
Hmm. If the called notifiers sleep, RCU can't prevent the notifiers
from being unregistered while they are executing. I suppose then that
RCU is not suitable for generic notifiers. It may still be useful
for managing notifiers in very fast paths where acquiring a
read lock may be undesirable (like the oprofile's NMI handler).
Instead of a lockless __notifier_call_chain, I would rather add
a notifier_call_chain_safe() to avoid changing the existing
handlers. Something like the patch below.
The safe version should be used for the trap handlers: we know
that the called notifiers will not sleep and the smp-safeness
makes the handlers simpler.
Thanks,
Vamsi.
--
Vamsi Krishna S.
Linux Technology Center,
IBM Software Lab, Bangalore.
Ph: +91 80 5044959
Internet: vamsi@in.ibm.com
--
diff -urN -X /home/vamsi/.dontdiff 51-pure/include/linux/notifier.h 51-notifier/include/linux/notifier.h
--- 51-pure/include/linux/notifier.h 2002-12-10 08:15:43.000000000 +0530
+++ 51-notifier/include/linux/notifier.h 2002-12-12 11:53:53.000000000 +0530
@@ -24,6 +24,7 @@
extern int notifier_chain_register(struct notifier_block **list, struct notifier_block *n);
extern int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n);
extern int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v);
+extern int notifier_call_chain_safe(struct notifier_block **n, unsigned long val, void *v);
#define NOTIFY_DONE 0x0000 /* Don't care */
#define NOTIFY_OK 0x0001 /* Suits me */
diff -urN -X /home/vamsi/.dontdiff 51-pure/kernel/sys.c 51-notifier/kernel/sys.c
--- 51-pure/kernel/sys.c 2002-12-10 08:15:43.000000000 +0530
+++ 51-notifier/kernel/sys.c 2002-12-12 11:52:45.000000000 +0530
@@ -166,6 +166,29 @@
}
/**
+ * notifier_call_chain_safe - Call functions in a notifier chain
+ * @n: Pointer to root pointer of notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ *
+ * Calls each function in a notifier chain in turn while ensuring
+ * that a notifier cannot be unregistered while it is being
+ * executed. Because a read_lock is taken, the called notifiers
+ * must not sleep.
+ */
+
+int notifier_call_chain_safe(struct notifier_block **n, unsigned long val, void *v)
+{
+ int ret;
+
+ read_lock(¬ifier_lock);
+ ret = notifier_call_chain(n, val, v);
+ read_unlock(¬ifier_lock);
+
+ return ret;
+}
+
+/**
* register_reboot_notifier - Register function to be called at reboot time
* @nb: Info about notifier function to be called
*
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
This archive was generated by hypermail 2b29 : Sun Dec 15 2002 - 22:00:24 EST