summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/subr_eventhandler.c71
-rw-r--r--sys/net/vnet.c39
-rw-r--r--sys/net/vnet.h30
-rw-r--r--sys/sys/eventhandler.h16
4 files changed, 139 insertions, 17 deletions
diff --git a/sys/kern/subr_eventhandler.c b/sys/kern/subr_eventhandler.c
index 37c482c..5894099 100644
--- a/sys/kern/subr_eventhandler.c
+++ b/sys/kern/subr_eventhandler.c
@@ -68,15 +68,15 @@ SYSINIT(eventhandlers, SI_SUB_EVENTHANDLER, SI_ORDER_FIRST, eventhandler_init,
* Insertion is O(n) due to the priority scan, but optimises to O(1)
* if all priorities are identical.
*/
-eventhandler_tag
-eventhandler_register(struct eventhandler_list *list, const char *name,
- void *func, void *arg, int priority)
+static eventhandler_tag
+eventhandler_register_internal(struct eventhandler_list *list,
+ const char *name, eventhandler_tag epn)
{
struct eventhandler_list *new_list;
- struct eventhandler_entry_generic *eg;
struct eventhandler_entry *ep;
KASSERT(eventhandler_lists_initted, ("eventhandler registered too early"));
+ KASSERT(epn != NULL, ("%s: cannot register NULL event", __func__));
/* lock the eventhandler lists */
mtx_lock(&eventhandler_mutex);
@@ -117,31 +117,68 @@ eventhandler_register(struct eventhandler_list *list, const char *name,
}
mtx_unlock(&eventhandler_mutex);
- /* allocate an entry for this handler, populate it */
- eg = malloc(sizeof(struct eventhandler_entry_generic), M_EVENTHANDLER,
- M_WAITOK | M_ZERO);
- eg->func = func;
- eg->ee.ee_arg = arg;
- eg->ee.ee_priority = priority;
- KASSERT(priority != EHE_DEAD_PRIORITY,
+ KASSERT(epn->ee_priority != EHE_DEAD_PRIORITY,
("%s: handler for %s registered with dead priority", __func__, name));
/* sort it into the list */
- CTR4(KTR_EVH, "%s: adding item %p (function %p) to \"%s\"", __func__, eg,
- func, name);
+ CTR4(KTR_EVH, "%s: adding item %p (function %p) to \"%s\"", __func__, epn,
+ ((struct eventhandler_entry_generic *)epn)->func, name);
EHL_LOCK(list);
TAILQ_FOREACH(ep, &list->el_entries, ee_link) {
if (ep->ee_priority != EHE_DEAD_PRIORITY &&
- eg->ee.ee_priority < ep->ee_priority) {
- TAILQ_INSERT_BEFORE(ep, &eg->ee, ee_link);
+ epn->ee_priority < ep->ee_priority) {
+ TAILQ_INSERT_BEFORE(ep, epn, ee_link);
break;
}
}
if (ep == NULL)
- TAILQ_INSERT_TAIL(&list->el_entries, &eg->ee, ee_link);
+ TAILQ_INSERT_TAIL(&list->el_entries, epn, ee_link);
EHL_UNLOCK(list);
- return(&eg->ee);
+ return(epn);
+}
+
+eventhandler_tag
+eventhandler_register(struct eventhandler_list *list, const char *name,
+ void *func, void *arg, int priority)
+{
+ struct eventhandler_entry_generic *eg;
+
+ /* allocate an entry for this handler, populate it */
+ eg = malloc(sizeof(struct eventhandler_entry_generic), M_EVENTHANDLER,
+ M_WAITOK | M_ZERO);
+ eg->func = func;
+ eg->ee.ee_arg = arg;
+ eg->ee.ee_priority = priority;
+
+ return (eventhandler_register_internal(list, name, &eg->ee));
+}
+
+#ifdef VIMAGE
+struct eventhandler_entry_generic_vimage
+{
+ struct eventhandler_entry ee;
+ vimage_iterator_func_t func; /* Vimage iterator function. */
+ struct eventhandler_entry_vimage v_ee; /* Original func, arg. */
+};
+
+eventhandler_tag
+vimage_eventhandler_register(struct eventhandler_list *list, const char *name,
+ void *func, void *arg, int priority, vimage_iterator_func_t iterfunc)
+{
+ struct eventhandler_entry_generic_vimage *eg;
+
+ /* allocate an entry for this handler, populate it */
+ eg = malloc(sizeof(struct eventhandler_entry_generic_vimage),
+ M_EVENTHANDLER, M_WAITOK | M_ZERO);
+ eg->func = iterfunc;
+ eg->v_ee.func = func;
+ eg->v_ee.ee_arg = arg;
+ eg->ee.ee_arg = &eg->v_ee;
+ eg->ee.ee_priority = priority;
+
+ return (eventhandler_register_internal(list, name, &eg->ee));
}
+#endif
void
eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag)
diff --git a/sys/net/vnet.c b/sys/net/vnet.c
index 323ed08..1dac03a 100644
--- a/sys/net/vnet.c
+++ b/sys/net/vnet.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sdt.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
+#include <sys/eventhandler.h>
#include <sys/linker_set.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -55,6 +56,8 @@ __FBSDID("$FreeBSD$");
#include <sys/sx.h>
#include <sys/sysctl.h>
+#include <machine/stdarg.h>
+
#ifdef DDB
#include <ddb/ddb.h>
#include <ddb/db_sym.h>
@@ -637,6 +640,39 @@ vnet_sysuninit(void)
VNET_SYSINIT_RUNLOCK();
}
+/*
+ * EVENTHANDLER(9) extensions.
+ */
+/*
+ * Invoke the eventhandler function originally registered with the possibly
+ * registered argument for all virtual network stack instances.
+ *
+ * This iterator can only be used for eventhandlers that do not take any
+ * additional arguments, as we do ignore the variadic arguments from the
+ * EVENTHANDLER_INVOKE() call.
+ */
+void
+vnet_global_eventhandler_iterator_func(void *arg, ...)
+{
+ VNET_ITERATOR_DECL(vnet_iter);
+ struct eventhandler_entry_vimage *v_ee;
+
+ /*
+ * There is a bug here in that we should actually cast things to
+ * (struct eventhandler_entry_ ## name *) but that's not easily
+ * possible in here so just re-using the variadic version we
+ * defined for the generic vimage case.
+ */
+ v_ee = arg;
+ VNET_LIST_RLOCK();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+ ((vimage_iterator_func_t)v_ee->func)(v_ee->ee_arg);
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK();
+}
+
#ifdef VNET_DEBUG
struct vnet_recursion {
SLIST_ENTRY(vnet_recursion) vnr_le;
@@ -696,6 +732,9 @@ vnet_log_recursion(struct vnet *old_vnet, const char *old_fn, int line)
}
#endif /* VNET_DEBUG */
+/*
+ * DDB(4).
+ */
#ifdef DDB
DB_SHOW_COMMAND(vnets, db_show_vnets)
{
diff --git a/sys/net/vnet.h b/sys/net/vnet.h
index d9a1ee0..fb2cc39 100644
--- a/sys/net/vnet.h
+++ b/sys/net/vnet.h
@@ -313,6 +313,29 @@ void vnet_register_sysuninit(void *arg);
void vnet_deregister_sysinit(void *arg);
void vnet_deregister_sysuninit(void *arg);
+/*
+ * EVENTHANDLER(9) extensions.
+ */
+#include <sys/eventhandler.h>
+
+void vnet_global_eventhandler_iterator_func(void *, ...);
+#define VNET_GLOBAL_EVENTHANDLER_REGISTER_TAG(tag, name, func, arg, priority) \
+do { \
+ if (IS_DEFAULT_VNET(curvnet)) { \
+ (tag) = vimage_eventhandler_register(NULL, #name, func, \
+ arg, priority, \
+ vnet_global_eventhandler_iterator_func); \
+ } \
+} while(0)
+#define VNET_GLOBAL_EVENTHANDLER_REGISTER(name, func, arg, priority) \
+do { \
+ if (IS_DEFAULT_VNET(curvnet)) { \
+ vimage_eventhandler_register(NULL, #name, func, \
+ arg, priority, \
+ vnet_global_eventhandler_iterator_func); \
+ } \
+} while(0)
+
#else /* !VIMAGE */
/*
@@ -384,6 +407,13 @@ void vnet_deregister_sysuninit(void *arg);
#define VNET_SYSUNINIT(ident, subsystem, order, func, arg) \
SYSUNINIT(ident, subsystem, order, func, arg)
+/*
+ * Without VIMAGE revert to the default implementation.
+ */
+#define VNET_GLOBAL_EVENTHANDLER_REGISTER_TAG(tag, name, func, arg, priority) \
+ (tag) = eventhandler_register(NULL, #name, func, arg, priority)
+#define VNET_GLOBAL_EVENTHANDLER_REGISTER(name, func, arg, priority) \
+ eventhandler_register(NULL, #name, func, arg, priority)
#endif /* VIMAGE */
#endif /* _KERNEL */
diff --git a/sys/sys/eventhandler.h b/sys/sys/eventhandler.h
index 6715efc..47a0efc 100644
--- a/sys/sys/eventhandler.h
+++ b/sys/sys/eventhandler.h
@@ -41,6 +41,14 @@ struct eventhandler_entry {
void *ee_arg;
};
+#ifdef VIMAGE
+struct eventhandler_entry_vimage {
+ void (* func)(void); /* Original function registered. */
+ void *ee_arg; /* Original argument registered. */
+ void *sparep[2];
+};
+#endif
+
struct eventhandler_list {
char *el_name;
int el_flags;
@@ -142,6 +150,14 @@ void eventhandler_deregister(struct eventhandler_list *list,
struct eventhandler_list *eventhandler_find_list(const char *name);
void eventhandler_prune_list(struct eventhandler_list *list);
+#ifdef VIMAGE
+typedef void (*vimage_iterator_func_t)(void *, ...);
+
+eventhandler_tag vimage_eventhandler_register(struct eventhandler_list *list,
+ const char *name, void *func, void *arg, int priority,
+ vimage_iterator_func_t);
+#endif
+
/*
* Standard system event queues.
*/
OpenPOWER on IntegriCloud