# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1273828410 -3600
# Node ID 9ff084bae83a1506f731ff6a926fefcccec5b1b1
# Parent baccadfd9418b8dee931945e5752cb118f5bf3cb
Import raw notifier subsystem from Linux.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/common/Makefile | 1
xen/common/notifier.c | 153 +++++++++++++++++++++++++++++++++++++++++++++
xen/include/xen/notifier.h | 89 ++++++++++++++++++++++++++
3 files changed, 243 insertions(+)
diff -r baccadfd9418 -r 9ff084bae83a xen/common/Makefile
--- a/xen/common/Makefile Fri May 14 08:05:05 2010 +0100
+++ b/xen/common/Makefile Fri May 14 10:13:30 2010 +0100
@@ -11,6 +11,7 @@ obj-y += lib.o
obj-y += lib.o
obj-y += memory.o
obj-y += multicall.o
+obj-y += notifier.o
obj-y += page_alloc.o
obj-y += rangeset.o
obj-y += sched_credit.o
diff -r baccadfd9418 -r 9ff084bae83a xen/common/notifier.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/common/notifier.c Fri May 14 10:13:30 2010 +0100
@@ -0,0 +1,153 @@
+/******************************************************************************
+ * common/notifier.c
+ *
+ * Routines to manage notifier chains for passing status changes to any
+ * interested routines.
+ *
+ * Original code from Linux kernel 2.6.27 (Alan Cox <Alan.Cox@xxxxxxxxx>)
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/notifier.h>
+#include <xen/rcupdate.h>
+
+/*
+ * Notifier chain core routines. The exported routines below
+ * are layered on top of these, with appropriate locking added.
+ */
+
+static int notifier_chain_register(
+ struct notifier_block **nl, struct notifier_block *n)
+{
+ while ( (*nl) != NULL )
+ {
+ if ( n->priority > (*nl)->priority )
+ break;
+ nl = &((*nl)->next);
+ }
+ n->next = *nl;
+ rcu_assign_pointer(*nl, n);
+ return 0;
+}
+
+static int notifier_chain_unregister(
+ struct notifier_block **nl, struct notifier_block *n)
+{
+ while ( (*nl) != NULL )
+ {
+ if ( (*nl) == n )
+ {
+ rcu_assign_pointer(*nl, n->next);
+ return 0;
+ }
+ nl = &((*nl)->next);
+ }
+ return -ENOENT;
+}
+
+/**
+ * notifier_call_chain - Informs the registered notifiers about an event.
+ * @nl: Pointer to head of the blocking notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ * @nr_to_call: Number of notifier functions to be called. Don't care
+ * value of this parameter is -1.
+ * @nr_calls: Records the number of notifications sent. Don't care
+ * value of this field is NULL.
+ * @returns: notifier_call_chain returns the value returned by the
+ * last notifier function called.
+ */
+static int notifier_call_chain(
+ struct notifier_block **nl, unsigned long val, void *v,
+ int nr_to_call, int *nr_calls)
+{
+ int ret = NOTIFY_DONE;
+ struct notifier_block *nb, *next_nb;
+
+ nb = rcu_dereference(*nl);
+
+ while ( nb && nr_to_call )
+ {
+ next_nb = rcu_dereference(nb->next);
+ ret = nb->notifier_call(nb, val, v);
+
+ if ( nr_calls )
+ (*nr_calls)++;
+
+ if ( (ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK )
+ break;
+ nb = next_nb;
+ nr_to_call--;
+ }
+ return ret;
+}
+
+/*
+ * Raw notifier chain routines. There is no protection;
+ * the caller must provide it. Use at your own risk!
+ */
+
+/**
+ * raw_notifier_chain_register - Add notifier to a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @n: New entry in notifier chain
+ *
+ * Adds a notifier to a raw notifier chain.
+ * All locking must be provided by the caller.
+ *
+ * Currently always returns zero.
+ */
+int raw_notifier_chain_register(
+ struct raw_notifier_head *nh, struct notifier_block *n)
+{
+ return notifier_chain_register(&nh->head, n);
+}
+
+/**
+ * raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from a raw notifier chain.
+ * All locking must be provided by the caller.
+ *
+ * Returns zero on success or %-ENOENT on failure.
+ */
+int raw_notifier_chain_unregister(
+ struct raw_notifier_head *nh, struct notifier_block *n)
+{
+ return notifier_chain_unregister(&nh->head, n);
+}
+
+/**
+ * __raw_notifier_call_chain - Call functions in a raw notifier chain
+ * @nh: Pointer to head of the raw notifier chain
+ * @val: Value passed unmodified to notifier function
+ * @v: Pointer passed unmodified to notifier function
+ * @nr_to_call: See comment for notifier_call_chain.
+ * @nr_calls: See comment for notifier_call_chain
+ *
+ * Calls each function in a notifier chain in turn. The functions
+ * run in an undefined context.
+ * All locking must be provided by the caller.
+ *
+ * If the return value of the notifier can be and'ed
+ * with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
+ * will return immediately, with the return value of
+ * the notifier function which halted execution.
+ * Otherwise the return value is the return value
+ * of the last notifier function called.
+ */
+int __raw_notifier_call_chain(
+ struct raw_notifier_head *nh, unsigned long val, void *v,
+ int nr_to_call, int *nr_calls)
+{
+ return notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
+}
+
+int raw_notifier_call_chain(
+ struct raw_notifier_head *nh, unsigned long val, void *v)
+{
+ return __raw_notifier_call_chain(nh, val, v, -1, NULL);
+}
diff -r baccadfd9418 -r 9ff084bae83a xen/include/xen/notifier.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/include/xen/notifier.h Fri May 14 10:13:30 2010 +0100
@@ -0,0 +1,89 @@
+/******************************************************************************
+ * include/xen/notifier.h
+ *
+ * Routines to manage notifier chains for passing status changes to any
+ * interested routines.
+ *
+ * Original code from Linux kernel 2.6.27 (Alan Cox <Alan.Cox@xxxxxxxxx>)
+ */
+
+#ifndef __XEN_NOTIFIER_H__
+#define __XEN_NOTIFIER_H__
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/errno.h>
+
+/*
+ * Xen includes only one type of notifier chains inherited from Linux:
+ * Raw notifier chains: There are no restrictions on callbacks,
+ * registration, or unregistration. All locking and protection
+ * must be provided by the caller.
+ */
+
+struct notifier_block {
+ int (*notifier_call)(struct notifier_block *, unsigned long, void *);
+ struct notifier_block *next;
+ int priority;
+};
+
+struct raw_notifier_head {
+ struct notifier_block *head;
+};
+
+#define RAW_INIT_NOTIFIER_HEAD(name) do { \
+ (name)->head = NULL; \
+} while (0)
+
+#define RAW_NOTIFIER_INIT(name) { .head = NULL }
+
+#define RAW_NOTIFIER_HEAD(name) \
+ struct raw_notifier_head name = RAW_NOTIFIER_INIT(name)
+
+int raw_notifier_chain_register(
+ struct raw_notifier_head *nh, struct notifier_block *nb);
+
+int raw_notifier_chain_unregister(
+ struct raw_notifier_head *nh, struct notifier_block *nb);
+
+int raw_notifier_call_chain(
+ struct raw_notifier_head *nh, unsigned long val, void *v);
+int __raw_notifier_call_chain(
+ struct raw_notifier_head *nh, unsigned long val, void *v,
+ int nr_to_call, int *nr_calls);
+
+#define NOTIFY_DONE 0x0000 /* Don't care */
+#define NOTIFY_OK 0x0001 /* Suits me */
+#define NOTIFY_STOP_MASK 0x8000 /* Don't call further */
+#define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002)
+/* Bad/Veto action */
+/*
+ * Clean way to return from the notifier and stop further calls.
+ */
+#define NOTIFY_STOP (NOTIFY_OK|NOTIFY_STOP_MASK)
+
+/* Encapsulate (negative) errno value (in particular, NOTIFY_BAD <=> EPERM). */
+static inline int notifier_from_errno(int err)
+{
+ return NOTIFY_STOP_MASK | (NOTIFY_OK - err);
+}
+
+/* Restore (negative) errno value from notify return value. */
+static inline int notifier_to_errno(int ret)
+{
+ ret &= ~NOTIFY_STOP_MASK;
+ return ret > NOTIFY_OK ? NOTIFY_OK - ret : 0;
+}
+
+#define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */
+#define CPU_UP_PREPARE 0x0003 /* CPU (unsigned)v coming up */
+#define CPU_UP_CANCELED 0x0004 /* CPU (unsigned)v NOT coming up */
+#define CPU_DOWN_PREPARE 0x0005 /* CPU (unsigned)v going down */
+#define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */
+#define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */
+#define CPU_DYING 0x0008 /* CPU (unsigned)v not running any task,
+ * not handling interrupts, soon dead */
+#define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug
+ * lock is dropped */
+
+#endif /* __XEN_NOTIFIER_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|