Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111659327
D27252.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D27252.diff
View Options
Index: sys/kern/subr_eventhandler.c
===================================================================
--- sys/kern/subr_eventhandler.c
+++ sys/kern/subr_eventhandler.c
@@ -37,6 +37,7 @@
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/systm.h>
+#include <sys/rmlock.h>
#include <sys/eventhandler.h>
static MALLOC_DEFINE(M_EVENTHANDLER, "eventhandler", "Event handler records");
@@ -317,3 +318,226 @@
return (list);
}
+
+/*
+ * Static event handler points.
+ */
+static void
+static_eventhandler_validate(struct static_eventhandler *seh)
+{
+ int i;
+
+ for (i = 0; i < seh->count; i++) {
+ if (seh->cb[i] != NULL) {
+ switch (seh->prio[i]) {
+ case STATIC_EVENTHANDLER_PRIO_FIRST:
+ case STATIC_EVENTHANDLER_PRIO_ANY:
+ case STATIC_EVENTHANDLER_PRIO_LAST:
+ break;
+ default:
+ case STATIC_EVENTHANDLER_PRIO_INVALID:
+ panic("seh %p bad priority %d at %d\n", seh, seh->prio[i], i);
+ break;
+ }
+ }
+ }
+
+ for (i = 1; i < seh->count; i++) {
+ if (seh->prio[i] < seh->prio[i - 1]) {
+ panic("seh %p unsorted priorities (%d < %d) at %d\n", seh,
+ seh->prio[i], seh->prio[i - 1], i);
+ }
+ }
+
+ for (i = seh->count; i < seh->size; i++) {
+ if (seh->cb[i] != NULL) {
+ panic("seh %p callback %p found past the end\n", seh,
+ seh->cb[i]);
+ }
+ if (seh->prio[i] != STATIC_EVENTHANDLER_PRIO_INVALID) {
+ panic("seh %p prio %d found past the end\n", seh,
+ seh->prio[i]);
+ }
+ }
+}
+
+static void
+static_eventhandler_assert_prio(struct static_eventhandler *seh,
+ enum static_eventhandler_prio prio)
+{
+
+ switch (prio) {
+ case STATIC_EVENTHANDLER_PRIO_FIRST:
+ case STATIC_EVENTHANDLER_PRIO_ANY:
+ case STATIC_EVENTHANDLER_PRIO_LAST:
+ break;
+ default:
+ case STATIC_EVENTHANDLER_PRIO_INVALID:
+ panic("invalid priority %d passed", prio);
+ break;
+ }
+}
+
+void
+static_eventhandler_init(struct static_eventhandler *seh)
+{
+
+ rms_init(&seh->lock, seh->ident);
+}
+
+void
+static_eventhandler_register(struct static_eventhandler *seh, void *pcb,
+ enum static_eventhandler_prio prio)
+{
+ static_eventhandler_cb **newcb, **tofree_cb, *cb;
+ size_t newsize;
+ enum static_eventhandler_prio *newprio, *tofree_prio;
+ int i;
+
+ static_eventhandler_assert_prio(seh, prio);
+
+ cb = (void *)pcb;
+ tofree_cb = NULL;
+ tofree_prio = NULL;
+ rms_wlock(&seh->lock);
+ MPASS(seh->count <= seh->size);
+ if (seh->cb == NULL) {
+ seh->size = 8;
+ seh->cb = malloc(sizeof(seh->cb[0]) * seh->size, M_EVENTHANDLER,
+ M_WAITOK | M_ZERO);
+ seh->prio = malloc(sizeof(seh->prio[0]) * seh->size, M_EVENTHANDLER,
+ M_WAITOK | M_ZERO);
+ } else if (seh->count == seh->size) {
+ newsize = seh->size * 2;
+ newcb = malloc(sizeof(seh->cb[0]) * newsize,
+ M_EVENTHANDLER, M_WAITOK | M_ZERO);
+ newprio = malloc(sizeof(seh->prio[0]) * newsize,
+ M_EVENTHANDLER, M_WAITOK | M_ZERO);
+ memcpy(newcb, seh->cb, sizeof(seh->cb[0]) * seh->size);
+ memcpy(newprio, seh->prio, sizeof(seh->prio[0]) * seh->size);
+
+ tofree_cb = seh->cb;
+ tofree_prio = seh->prio;
+ seh->cb = newcb;
+ seh->prio = newprio;
+ seh->size = newsize;
+ }
+
+ static_eventhandler_validate(seh);
+
+ for (i = 0; i < seh->size; i++) {
+ if (seh->cb[i] == cb)
+ panic("callback %p already registered", cb);
+ }
+
+ switch (prio) {
+ case STATIC_EVENTHANDLER_PRIO_INVALID:
+ /* appease clang */
+ panic("should not be here");
+ break;
+ case STATIC_EVENTHANDLER_PRIO_FIRST:
+ memmove(&seh->cb[1], seh->cb,
+ sizeof(seh->cb[0]) * seh->count);
+ memmove(&seh->prio[1], seh->prio,
+ sizeof(seh->prio[0]) * seh->count);
+ seh->cb[0] = cb;
+ seh->prio[0] = prio;
+ seh->count++;
+ break;
+ case STATIC_EVENTHANDLER_PRIO_ANY:
+ for (i = 0; i < seh->count; i++) {
+ if (seh->prio[i] != STATIC_EVENTHANDLER_PRIO_FIRST)
+ break;
+ }
+ if (i == seh->count) {
+ /*
+ * Insert at the end.
+ */
+ seh->cb[seh->count] = cb;
+ seh->prio[seh->count] = prio;
+ seh->count++;
+ } else {
+ /*
+ * Move all entries to handle STATIC_EVENTHANDLER_PRIO_LAST.
+ */
+ memmove(&seh->cb[i + 1], seh->cb,
+ sizeof(seh->cb[0]) * (seh->count - i));
+ memmove(&seh->prio[i + 1], seh->prio,
+ sizeof(seh->prio[0]) * (seh->count - i));
+ seh->cb[i] = cb;
+ seh->prio[i] = prio;
+ seh->count++;
+ }
+ break;
+ case STATIC_EVENTHANDLER_PRIO_LAST:
+ seh->cb[seh->count] = cb;
+ seh->prio[seh->count] = prio;
+ seh->count++;
+ break;
+ }
+ rms_wunlock(&seh->lock);
+ free(tofree_cb, M_EVENTHANDLER);
+ free(tofree_prio, M_EVENTHANDLER);
+}
+
+void
+static_eventhandler_deregister(struct static_eventhandler *seh, void *pcb)
+{
+ static_eventhandler_cb *cb;
+ int i;
+
+ cb = pcb;
+ rms_wlock(&seh->lock);
+ MPASS(seh->count <= seh->size);
+ static_eventhandler_validate(seh);
+
+ for (i = 0; i < seh->count; i++) {
+ if (seh->cb[i] == cb)
+ break;
+ }
+
+ if (i == seh->count)
+ panic("callback %p not found", cb);
+
+ switch (seh->prio[i]) {
+ case STATIC_EVENTHANDLER_PRIO_INVALID:
+ /* appease clang */
+ panic("should not be here");
+ break;
+ case STATIC_EVENTHANDLER_PRIO_FIRST:
+ memmove(seh->cb, &seh->cb[1],
+ sizeof(seh->cb[0]) * (seh->count - 1));
+ memmove(seh->prio, &seh->prio[1],
+ sizeof(seh->prio[0]) * (seh->count - 1));
+ break;
+ case STATIC_EVENTHANDLER_PRIO_ANY:
+ memmove(&seh->cb[i], &seh->cb[i + 1],
+ sizeof(seh->cb[0]) * (seh->count - i));
+ memmove(&seh->prio[i], &seh->cb[i + 1],
+ sizeof(seh->cb[0]) * (seh->count - i));
+ break;
+ case STATIC_EVENTHANDLER_PRIO_LAST:
+ seh->cb[i] = seh->cb[seh->count - 1];
+ seh->prio[i] = seh->prio[seh->count - 1];
+ break;
+ }
+ seh->cb[seh->count] = NULL;
+ seh->prio[seh->count] = STATIC_EVENTHANDLER_PRIO_INVALID;
+ seh->count--;
+ rms_wunlock(&seh->lock);
+}
+
+void
+static_eventhandler_invoke(struct static_eventhandler *seh, void *arg)
+{
+ int i;
+
+ if (seh->count == 0)
+ return;
+
+ rms_rlock(&seh->lock);
+ for (i = 0; i < seh->count; i++) {
+ (seh->cb[i])(arg);
+ }
+ rms_runlock(&seh->lock);
+}
Index: sys/sys/_eventhandler.h
===================================================================
--- sys/sys/_eventhandler.h
+++ sys/sys/_eventhandler.h
@@ -69,4 +69,52 @@
}; \
struct __hack
+/*
+ * Headers to accomodate _rmlock.h
+ */
+#include <sys/param.h>
+#include <sys/_cpuset.h>
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
+#include <sys/_sx.h>
+#include <sys/_rmlock.h>
+
+typedef void static_eventhandler_cb(void *);
+
+enum static_eventhandler_prio {
+ STATIC_EVENTHANDLER_PRIO_INVALID,
+ STATIC_EVENTHANDLER_PRIO_FIRST,
+ STATIC_EVENTHANDLER_PRIO_ANY,
+ STATIC_EVENTHANDLER_PRIO_LAST
+};
+
+struct static_eventhandler {
+ const char *ident;
+ enum static_eventhandler_prio *prio;
+ struct rmslock lock;
+ u_int count;
+ u_int size;
+ static_eventhandler_cb **cb;
+};
+
+#define STATIC_EVENTHANDLER_DECLARE(name) \
+extern struct static_eventhandler static_eventhandler_ ## name
+
+#define STATIC_EVENTHANDLER_REGISTER(name, func, prio) \
+ static_eventhandler_register(&static_eventhandler_ ## name, func, \
+ STATIC_EVENTHANDLER_PRIO_ ## prio)
+
+#define STATIC_EVENTHANDLER_DEREGISTER(name, func) \
+ static_eventhandler_deregister(&static_eventhandler_ ## name, func)
+
+#define STATIC_EVENTHANDLER_INVOKE(name, arg) \
+ static_eventhandler_invoke(&static_eventhandler_ ## name, arg)
+
+#define STATIC_EVENTHANDLER_DEFINE(name) \
+struct static_eventhandler static_eventhandler_ ## name = { \
+ .ident = __STRING(name), \
+}; \
+SYSINIT(_seh_init_ ## name, SI_SUB_EVENTHANDLER, SI_ORDER_ANY, \
+ static_eventhandler_init, &static_eventhandler_ ## name);
+
#endif
Index: sys/sys/eventhandler.h
===================================================================
--- sys/sys/eventhandler.h
+++ sys/sys/eventhandler.h
@@ -317,4 +317,13 @@
typedef void (*rt_addrmsg_fn)(void *, struct ifaddr *, int);
EVENTHANDLER_DECLARE(rt_addrmsg, rt_addrmsg_fn);
+/*
+ * Static eventhandler support.
+ */
+void static_eventhandler_init(struct static_eventhandler *seh);
+void static_eventhandler_register(struct static_eventhandler *seh, void *func,
+ enum static_eventhandler_prio prio);
+void static_eventhandler_deregister(struct static_eventhandler *seh, void *func);
+void static_eventhandler_invoke(struct static_eventhandler *seh, void *arg);
+
#endif /* _SYS_EVENTHANDLER_H_ */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Mar 7, 3:45 PM (17 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17034517
Default Alt Text
D27252.diff (8 KB)
Attached To
Mode
D27252: rms-protected event handlers
Attached
Detach File
Event Timeline
Log In to Comment