Index: sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c +++ sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c @@ -222,7 +222,7 @@ static void fasttrap_proc_release(fasttrap_proc_t *); #ifndef illumos -static void fasttrap_thread_dtor(void *, struct thread *); +static void fasttrap_thread_dtor(struct thread *); #endif #define FASTTRAP_PROVS_INDEX(pid, name) \ @@ -232,7 +232,6 @@ #ifndef illumos struct rmlock fasttrap_tp_lock; -static eventhandler_tag fasttrap_thread_dtor_tag; #endif static unsigned long tpoints_hash_size = FASTTRAP_TPOINTS_DEFAULT_SIZE; @@ -382,7 +381,7 @@ * free list. */ static void -fasttrap_thread_dtor(void *arg __unused, struct thread *td) +fasttrap_thread_dtor(struct thread *td) { fasttrap_bucket_t *bucket; fasttrap_proc_t *fprc; @@ -2499,8 +2498,7 @@ * This event handler must run before kdtrace_thread_dtor() since it * accesses the thread's struct kdtrace_thread. */ - fasttrap_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor, - fasttrap_thread_dtor, NULL, EVENTHANDLER_PRI_FIRST); + STATIC_EVENTHANDLER_REGISTER(thread_dtor, fasttrap_thread_dtor, FIRST); #endif /* @@ -2602,7 +2600,7 @@ #endif #ifndef illumos - EVENTHANDLER_DEREGISTER(thread_dtor, fasttrap_thread_dtor_tag); + STATIC_EVENTHANDLER_DEREGISTER(thread_dtor, fasttrap_thread_dtor); for (i = 0; i < fasttrap_tpoints.fth_nent; i++) mutex_destroy(&fasttrap_tpoints.fth_table[i].ftb_mtx); Index: sys/kern/init_main.c =================================================================== --- sys/kern/init_main.c +++ sys/kern/init_main.c @@ -607,8 +607,10 @@ */ EVENTHANDLER_DIRECT_INVOKE(process_init, p); EVENTHANDLER_DIRECT_INVOKE(thread_init, td); + STATIC_EVENTHANDLER_INVOKE(thread_init, td); EVENTHANDLER_DIRECT_INVOKE(process_ctor, p); EVENTHANDLER_DIRECT_INVOKE(thread_ctor, td); + STATIC_EVENTHANDLER_INVOKE(thread_ctor, td); /* * Charge root for one process. Index: sys/kern/kern_dtrace.c =================================================================== --- sys/kern/kern_dtrace.c +++ sys/kern/kern_dtrace.c @@ -93,14 +93,14 @@ } static void -kdtrace_thread_ctor(void *arg __unused, struct thread *td) +kdtrace_thread_ctor(struct thread *td) { td->td_dtrace = malloc(KDTRACE_THREAD_SIZE, M_KDTRACE, M_WAITOK|M_ZERO); } static void -kdtrace_thread_dtor(void *arg __unused, struct thread *td) +kdtrace_thread_dtor(struct thread *td) { if (td->td_dtrace != NULL) { @@ -120,10 +120,8 @@ EVENTHANDLER_PRI_ANY); EVENTHANDLER_REGISTER(process_dtor, kdtrace_proc_dtor, NULL, EVENTHANDLER_PRI_ANY); - EVENTHANDLER_REGISTER(thread_ctor, kdtrace_thread_ctor, NULL, - EVENTHANDLER_PRI_ANY); - EVENTHANDLER_REGISTER(thread_dtor, kdtrace_thread_dtor, NULL, - EVENTHANDLER_PRI_ANY); + STATIC_EVENTHANDLER_REGISTER(thread_ctor, kdtrace_thread_ctor, ANY); + STATIC_EVENTHANDLER_REGISTER(thread_dtor, kdtrace_thread_dtor, ANY); } SYSINIT(kdtrace, SI_SUB_KDTRACE, SI_ORDER_FIRST, init_dtrace, NULL); Index: sys/kern/kern_proc.c =================================================================== --- sys/kern/kern_proc.c +++ sys/kern/kern_proc.c @@ -212,6 +212,7 @@ if (td != NULL) { /* Make sure all thread constructors are executed */ EVENTHANDLER_DIRECT_INVOKE(thread_ctor, td); + STATIC_EVENTHANDLER_INVOKE(thread_ctor, td); } return (0); } @@ -241,6 +242,7 @@ /* Make sure all thread destructors are executed */ EVENTHANDLER_DIRECT_INVOKE(thread_dtor, td); + STATIC_EVENTHANDLER_INVOKE(thread_dtor, td); } EVENTHANDLER_DIRECT_INVOKE(process_dtor, p); if (p->p_ksi != NULL) Index: sys/kern/kern_thread.c =================================================================== --- sys/kern/kern_thread.c +++ sys/kern/kern_thread.c @@ -169,6 +169,10 @@ EVENTHANDLER_LIST_DEFINE(thread_dtor); EVENTHANDLER_LIST_DEFINE(thread_init); EVENTHANDLER_LIST_DEFINE(thread_fini); +STATIC_EVENTHANDLER_DEFINE(thread_ctor); +STATIC_EVENTHANDLER_DEFINE(thread_dtor); +STATIC_EVENTHANDLER_DEFINE(thread_init); +STATIC_EVENTHANDLER_DEFINE(thread_fini); static bool thread_count_inc_try(void) @@ -414,6 +418,7 @@ td->td_turnstile = turnstile_alloc(); td->td_rlqe = NULL; EVENTHANDLER_DIRECT_INVOKE(thread_init, td); + STATIC_EVENTHANDLER_INVOKE(thread_init, td); umtx_thread_init(td); td->td_kstack = 0; td->td_sel = NULL; @@ -430,6 +435,7 @@ td = (struct thread *)mem; EVENTHANDLER_DIRECT_INVOKE(thread_fini, td); + STATIC_EVENTHANDLER_INVOKE(thread_fini, td); rlqentry_free(td->td_rlqe); turnstile_free(td->td_turnstile); sleepq_free(td->td_sleepqueue); @@ -603,6 +609,7 @@ while (itd != NULL) { ntd = itd->td_zombie; EVENTHANDLER_DIRECT_INVOKE(thread_dtor, itd); + STATIC_EVENTHANDLER_INVOKE(thread_dtor, itd); tidbatch_add(&tidbatch, itd); credbatch_add(&credbatch, itd); MPASS(itd->td_limit != NULL); @@ -721,6 +728,7 @@ td->td_tid = tid; cpu_thread_alloc(td); EVENTHANDLER_DIRECT_INVOKE(thread_ctor, td); + STATIC_EVENTHANDLER_INVOKE(thread_ctor, td); return (td); } @@ -764,6 +772,7 @@ lwpid_t tid; EVENTHANDLER_DIRECT_INVOKE(thread_dtor, td); + STATIC_EVENTHANDLER_INVOKE(thread_dtor, td); tid = td->td_tid; thread_free_batched(td); tid_free(tid); Index: sys/kern/subr_eventhandler.c =================================================================== --- sys/kern/subr_eventhandler.c +++ sys/kern/subr_eventhandler.c @@ -37,6 +37,7 @@ #include #include #include +#include #include static MALLOC_DEFINE(M_EVENTHANDLER, "eventhandler", "Event handler records"); @@ -317,3 +318,228 @@ 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) +{ + + bzero(seh, sizeof(*seh)); + rms_init(&seh->lock, "seh eventhandler"); +} + +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,49 @@ }; \ struct __hack +/* + * Headers to accomodate _rmlock.h + */ +#include +#include +#include +#include +#include +#include + +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 { + 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; \ +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_ */ Index: sys/sys/proc.h =================================================================== --- sys/sys/proc.h +++ sys/sys/proc.h @@ -1235,6 +1235,10 @@ EVENTHANDLER_LIST_DECLARE(thread_dtor); EVENTHANDLER_LIST_DECLARE(thread_init); +STATIC_EVENTHANDLER_DECLARE(thread_ctor); +STATIC_EVENTHANDLER_DECLARE(thread_dtor); +STATIC_EVENTHANDLER_DECLARE(thread_init); + #endif /* _KERNEL */ #endif /* !_SYS_PROC_H_ */