1*0f4c859eSApple OSS Distributions /*
2*0f4c859eSApple OSS Distributions * Copyright (c) 2016-2019 Apple Inc. All rights reserved.
3*0f4c859eSApple OSS Distributions *
4*0f4c859eSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*0f4c859eSApple OSS Distributions *
6*0f4c859eSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*0f4c859eSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*0f4c859eSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*0f4c859eSApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*0f4c859eSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*0f4c859eSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*0f4c859eSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*0f4c859eSApple OSS Distributions * terms of an Apple operating system software license agreement.
14*0f4c859eSApple OSS Distributions *
15*0f4c859eSApple OSS Distributions * Please obtain a copy of the License at
16*0f4c859eSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*0f4c859eSApple OSS Distributions *
18*0f4c859eSApple OSS Distributions * The Original Code and all software distributed under the License are
19*0f4c859eSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*0f4c859eSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*0f4c859eSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*0f4c859eSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*0f4c859eSApple OSS Distributions * Please see the License for the specific language governing rights and
24*0f4c859eSApple OSS Distributions * limitations under the License.
25*0f4c859eSApple OSS Distributions *
26*0f4c859eSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*0f4c859eSApple OSS Distributions */
28*0f4c859eSApple OSS Distributions /*-
29*0f4c859eSApple OSS Distributions * Copyright (c) 1999 Michael Smith <[email protected]>
30*0f4c859eSApple OSS Distributions * All rights reserved.
31*0f4c859eSApple OSS Distributions *
32*0f4c859eSApple OSS Distributions * Redistribution and use in source and binary forms, with or without
33*0f4c859eSApple OSS Distributions * modification, are permitted provided that the following conditions
34*0f4c859eSApple OSS Distributions * are met:
35*0f4c859eSApple OSS Distributions * 1. Redistributions of source code must retain the above copyright
36*0f4c859eSApple OSS Distributions * notice, this list of conditions and the following disclaimer.
37*0f4c859eSApple OSS Distributions * 2. Redistributions in binary form must reproduce the above copyright
38*0f4c859eSApple OSS Distributions * notice, this list of conditions and the following disclaimer in the
39*0f4c859eSApple OSS Distributions * documentation and/or other materials provided with the distribution.
40*0f4c859eSApple OSS Distributions *
41*0f4c859eSApple OSS Distributions * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
42*0f4c859eSApple OSS Distributions * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43*0f4c859eSApple OSS Distributions * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44*0f4c859eSApple OSS Distributions * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45*0f4c859eSApple OSS Distributions * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46*0f4c859eSApple OSS Distributions * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47*0f4c859eSApple OSS Distributions * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48*0f4c859eSApple OSS Distributions * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49*0f4c859eSApple OSS Distributions * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50*0f4c859eSApple OSS Distributions * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51*0f4c859eSApple OSS Distributions * SUCH DAMAGE.
52*0f4c859eSApple OSS Distributions */
53*0f4c859eSApple OSS Distributions
54*0f4c859eSApple OSS Distributions #include <sys/cdefs.h>
55*0f4c859eSApple OSS Distributions #include <sys/param.h>
56*0f4c859eSApple OSS Distributions #include <sys/kernel.h>
57*0f4c859eSApple OSS Distributions #include <kern/queue.h>
58*0f4c859eSApple OSS Distributions #include <kern/locks.h>
59*0f4c859eSApple OSS Distributions #include <sys/malloc.h>
60*0f4c859eSApple OSS Distributions #include <sys/proc.h>
61*0f4c859eSApple OSS Distributions #include <sys/systm.h>
62*0f4c859eSApple OSS Distributions #include <sys/eventhandler.h>
63*0f4c859eSApple OSS Distributions #include <sys/sysctl.h>
64*0f4c859eSApple OSS Distributions #include <sys/mcache.h> /* for VERIFY() */
65*0f4c859eSApple OSS Distributions
66*0f4c859eSApple OSS Distributions int evh_debug = 0;
67*0f4c859eSApple OSS Distributions
68*0f4c859eSApple OSS Distributions SYSCTL_NODE(_kern, OID_AUTO, eventhandler, CTLFLAG_RW | CTLFLAG_LOCKED,
69*0f4c859eSApple OSS Distributions 0, "Eventhandler");
70*0f4c859eSApple OSS Distributions SYSCTL_INT(_kern_eventhandler, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_LOCKED,
71*0f4c859eSApple OSS Distributions &evh_debug, 0, "Eventhandler debug mode");
72*0f4c859eSApple OSS Distributions
73*0f4c859eSApple OSS Distributions struct eventhandler_entry_arg eventhandler_entry_dummy_arg = { .ee_fm_uuid = { 0 }, .ee_fr_uuid = { 0 } };
74*0f4c859eSApple OSS Distributions
75*0f4c859eSApple OSS Distributions /* List of 'slow' lists */
76*0f4c859eSApple OSS Distributions static struct eventhandler_lists_ctxt evthdlr_lists_ctxt_glb;
77*0f4c859eSApple OSS Distributions static LCK_GRP_DECLARE(eventhandler_mutex_grp, "eventhandler");
78*0f4c859eSApple OSS Distributions
79*0f4c859eSApple OSS Distributions LCK_GRP_DECLARE(el_lock_grp, "eventhandler list");
80*0f4c859eSApple OSS Distributions LCK_ATTR_DECLARE(el_lock_attr, 0, 0);
81*0f4c859eSApple OSS Distributions
82*0f4c859eSApple OSS Distributions struct eventhandler_entry_generic {
83*0f4c859eSApple OSS Distributions struct eventhandler_entry ee;
84*0f4c859eSApple OSS Distributions void *func;
85*0f4c859eSApple OSS Distributions };
86*0f4c859eSApple OSS Distributions
87*0f4c859eSApple OSS Distributions static struct eventhandler_list *_eventhandler_find_list(
88*0f4c859eSApple OSS Distributions struct eventhandler_lists_ctxt *evthdlr_lists_ctxt, const char *name);
89*0f4c859eSApple OSS Distributions
90*0f4c859eSApple OSS Distributions void
eventhandler_lists_ctxt_init(struct eventhandler_lists_ctxt * evthdlr_lists_ctxt)91*0f4c859eSApple OSS Distributions eventhandler_lists_ctxt_init(struct eventhandler_lists_ctxt *evthdlr_lists_ctxt)
92*0f4c859eSApple OSS Distributions {
93*0f4c859eSApple OSS Distributions VERIFY(evthdlr_lists_ctxt != NULL);
94*0f4c859eSApple OSS Distributions
95*0f4c859eSApple OSS Distributions TAILQ_INIT(&evthdlr_lists_ctxt->eventhandler_lists);
96*0f4c859eSApple OSS Distributions evthdlr_lists_ctxt->eventhandler_lists_initted = 1;
97*0f4c859eSApple OSS Distributions lck_mtx_init(&evthdlr_lists_ctxt->eventhandler_mutex,
98*0f4c859eSApple OSS Distributions &eventhandler_mutex_grp, LCK_ATTR_NULL);
99*0f4c859eSApple OSS Distributions }
100*0f4c859eSApple OSS Distributions
101*0f4c859eSApple OSS Distributions /*
102*0f4c859eSApple OSS Distributions * Initialize the eventhandler list.
103*0f4c859eSApple OSS Distributions */
104*0f4c859eSApple OSS Distributions void
eventhandler_init(void)105*0f4c859eSApple OSS Distributions eventhandler_init(void)
106*0f4c859eSApple OSS Distributions {
107*0f4c859eSApple OSS Distributions eventhandler_lists_ctxt_init(&evthdlr_lists_ctxt_glb);
108*0f4c859eSApple OSS Distributions }
109*0f4c859eSApple OSS Distributions
110*0f4c859eSApple OSS Distributions /*
111*0f4c859eSApple OSS Distributions * Insertion is O(n) due to the priority scan, but optimises to O(1)
112*0f4c859eSApple OSS Distributions * if all priorities are identical.
113*0f4c859eSApple OSS Distributions */
114*0f4c859eSApple OSS Distributions static eventhandler_tag
eventhandler_register_internal(struct eventhandler_lists_ctxt * evthdlr_lists_ctxt,struct eventhandler_list * list,const char * name,eventhandler_tag epn)115*0f4c859eSApple OSS Distributions eventhandler_register_internal(
116*0f4c859eSApple OSS Distributions struct eventhandler_lists_ctxt *evthdlr_lists_ctxt,
117*0f4c859eSApple OSS Distributions struct eventhandler_list *list,
118*0f4c859eSApple OSS Distributions const char *name, eventhandler_tag epn)
119*0f4c859eSApple OSS Distributions {
120*0f4c859eSApple OSS Distributions struct eventhandler_list *new_list;
121*0f4c859eSApple OSS Distributions struct eventhandler_entry *ep;
122*0f4c859eSApple OSS Distributions
123*0f4c859eSApple OSS Distributions VERIFY(strlen(name) <= (sizeof(new_list->el_name) - 1));
124*0f4c859eSApple OSS Distributions
125*0f4c859eSApple OSS Distributions if (evthdlr_lists_ctxt == NULL) {
126*0f4c859eSApple OSS Distributions evthdlr_lists_ctxt = &evthdlr_lists_ctxt_glb;
127*0f4c859eSApple OSS Distributions }
128*0f4c859eSApple OSS Distributions
129*0f4c859eSApple OSS Distributions VERIFY(evthdlr_lists_ctxt->eventhandler_lists_initted); /* eventhandler registered too early */
130*0f4c859eSApple OSS Distributions VERIFY(epn != NULL); /* cannot register NULL event */
131*0f4c859eSApple OSS Distributions
132*0f4c859eSApple OSS Distributions /* lock the eventhandler lists */
133*0f4c859eSApple OSS Distributions lck_mtx_lock_spin(&evthdlr_lists_ctxt->eventhandler_mutex);
134*0f4c859eSApple OSS Distributions
135*0f4c859eSApple OSS Distributions /* Do we need to find/create the (slow) list? */
136*0f4c859eSApple OSS Distributions if (list == NULL) {
137*0f4c859eSApple OSS Distributions /* look for a matching, existing list */
138*0f4c859eSApple OSS Distributions list = _eventhandler_find_list(evthdlr_lists_ctxt, name);
139*0f4c859eSApple OSS Distributions
140*0f4c859eSApple OSS Distributions /* Do we need to create the list? */
141*0f4c859eSApple OSS Distributions if (list == NULL) {
142*0f4c859eSApple OSS Distributions lck_mtx_convert_spin(&evthdlr_lists_ctxt->eventhandler_mutex);
143*0f4c859eSApple OSS Distributions new_list = kalloc_type(struct eventhandler_list, Z_WAITOK_ZERO);
144*0f4c859eSApple OSS Distributions evhlog((LOG_DEBUG, "%s: creating list \"%s\"", __func__, name));
145*0f4c859eSApple OSS Distributions list = new_list;
146*0f4c859eSApple OSS Distributions list->el_flags = 0;
147*0f4c859eSApple OSS Distributions list->el_runcount = 0;
148*0f4c859eSApple OSS Distributions bzero(&list->el_lock, sizeof(list->el_lock));
149*0f4c859eSApple OSS Distributions (void) snprintf(list->el_name, sizeof(list->el_name), "%s", name);
150*0f4c859eSApple OSS Distributions TAILQ_INSERT_HEAD(&evthdlr_lists_ctxt->eventhandler_lists, list, el_link);
151*0f4c859eSApple OSS Distributions }
152*0f4c859eSApple OSS Distributions }
153*0f4c859eSApple OSS Distributions if (!(list->el_flags & EHL_INITTED)) {
154*0f4c859eSApple OSS Distributions TAILQ_INIT(&list->el_entries);
155*0f4c859eSApple OSS Distributions EHL_LOCK_INIT(list);
156*0f4c859eSApple OSS Distributions list->el_flags |= EHL_INITTED;
157*0f4c859eSApple OSS Distributions }
158*0f4c859eSApple OSS Distributions lck_mtx_unlock(&evthdlr_lists_ctxt->eventhandler_mutex);
159*0f4c859eSApple OSS Distributions
160*0f4c859eSApple OSS Distributions KASSERT(epn->ee_priority != EHE_DEAD_PRIORITY,
161*0f4c859eSApple OSS Distributions ("%s: handler for %s registered with dead priority", __func__, name));
162*0f4c859eSApple OSS Distributions
163*0f4c859eSApple OSS Distributions /* sort it into the list */
164*0f4c859eSApple OSS Distributions evhlog((LOG_DEBUG, "%s: adding item %p (function %p to \"%s\"", __func__, (void *)VM_KERNEL_ADDRPERM(epn),
165*0f4c859eSApple OSS Distributions (void *)VM_KERNEL_UNSLIDE(((struct eventhandler_entry_generic *)epn)->func), name));
166*0f4c859eSApple OSS Distributions EHL_LOCK(list);
167*0f4c859eSApple OSS Distributions TAILQ_FOREACH(ep, &list->el_entries, ee_link) {
168*0f4c859eSApple OSS Distributions if (ep->ee_priority != EHE_DEAD_PRIORITY &&
169*0f4c859eSApple OSS Distributions epn->ee_priority < ep->ee_priority) {
170*0f4c859eSApple OSS Distributions TAILQ_INSERT_BEFORE(ep, epn, ee_link);
171*0f4c859eSApple OSS Distributions break;
172*0f4c859eSApple OSS Distributions }
173*0f4c859eSApple OSS Distributions }
174*0f4c859eSApple OSS Distributions if (ep == NULL) {
175*0f4c859eSApple OSS Distributions TAILQ_INSERT_TAIL(&list->el_entries, epn, ee_link);
176*0f4c859eSApple OSS Distributions }
177*0f4c859eSApple OSS Distributions EHL_UNLOCK(list);
178*0f4c859eSApple OSS Distributions return epn;
179*0f4c859eSApple OSS Distributions }
180*0f4c859eSApple OSS Distributions
181*0f4c859eSApple OSS Distributions eventhandler_tag
eventhandler_register(struct eventhandler_lists_ctxt * evthdlr_lists_ctxt,struct eventhandler_list * list,const char * name,void * func,struct eventhandler_entry_arg arg,int priority)182*0f4c859eSApple OSS Distributions eventhandler_register(struct eventhandler_lists_ctxt *evthdlr_lists_ctxt,
183*0f4c859eSApple OSS Distributions struct eventhandler_list *list, const char *name,
184*0f4c859eSApple OSS Distributions void *func, struct eventhandler_entry_arg arg, int priority)
185*0f4c859eSApple OSS Distributions {
186*0f4c859eSApple OSS Distributions struct eventhandler_entry_generic *eg;
187*0f4c859eSApple OSS Distributions
188*0f4c859eSApple OSS Distributions /* allocate an entry for this handler, populate it */
189*0f4c859eSApple OSS Distributions eg = kalloc_type(struct eventhandler_entry_generic, Z_WAITOK_ZERO);
190*0f4c859eSApple OSS Distributions eg->func = func;
191*0f4c859eSApple OSS Distributions eg->ee.ee_arg = arg;
192*0f4c859eSApple OSS Distributions eg->ee.ee_priority = priority;
193*0f4c859eSApple OSS Distributions
194*0f4c859eSApple OSS Distributions return eventhandler_register_internal(evthdlr_lists_ctxt, list, name, &eg->ee);
195*0f4c859eSApple OSS Distributions }
196*0f4c859eSApple OSS Distributions
197*0f4c859eSApple OSS Distributions void
eventhandler_deregister(struct eventhandler_list * list,eventhandler_tag tag)198*0f4c859eSApple OSS Distributions eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag)
199*0f4c859eSApple OSS Distributions {
200*0f4c859eSApple OSS Distributions struct eventhandler_entry *ep = tag;
201*0f4c859eSApple OSS Distributions
202*0f4c859eSApple OSS Distributions EHL_LOCK_ASSERT(list, LCK_MTX_ASSERT_OWNED);
203*0f4c859eSApple OSS Distributions if (ep != NULL) {
204*0f4c859eSApple OSS Distributions /* remove just this entry */
205*0f4c859eSApple OSS Distributions if (list->el_runcount == 0) {
206*0f4c859eSApple OSS Distributions evhlog((LOG_DEBUG, "%s: removing item %p from \"%s\"", __func__, (void *)VM_KERNEL_ADDRPERM(ep),
207*0f4c859eSApple OSS Distributions list->el_name));
208*0f4c859eSApple OSS Distributions /*
209*0f4c859eSApple OSS Distributions * We may have purged the list because of certain events.
210*0f4c859eSApple OSS Distributions * Make sure that is not the case when a specific entry
211*0f4c859eSApple OSS Distributions * is being removed.
212*0f4c859eSApple OSS Distributions */
213*0f4c859eSApple OSS Distributions if (!TAILQ_EMPTY(&list->el_entries)) {
214*0f4c859eSApple OSS Distributions TAILQ_REMOVE(&list->el_entries, ep, ee_link);
215*0f4c859eSApple OSS Distributions }
216*0f4c859eSApple OSS Distributions EHL_LOCK_CONVERT(list);
217*0f4c859eSApple OSS Distributions kfree_type(struct eventhandler_entry, ep);
218*0f4c859eSApple OSS Distributions } else {
219*0f4c859eSApple OSS Distributions evhlog((LOG_DEBUG, "%s: marking item %p from \"%s\" as dead", __func__,
220*0f4c859eSApple OSS Distributions (void *)VM_KERNEL_ADDRPERM(ep), list->el_name));
221*0f4c859eSApple OSS Distributions ep->ee_priority = EHE_DEAD_PRIORITY;
222*0f4c859eSApple OSS Distributions }
223*0f4c859eSApple OSS Distributions } else {
224*0f4c859eSApple OSS Distributions /* remove entire list */
225*0f4c859eSApple OSS Distributions if (list->el_runcount == 0) {
226*0f4c859eSApple OSS Distributions evhlog((LOG_DEBUG, "%s: removing all items from \"%s\"", __func__,
227*0f4c859eSApple OSS Distributions list->el_name));
228*0f4c859eSApple OSS Distributions EHL_LOCK_CONVERT(list);
229*0f4c859eSApple OSS Distributions while (!TAILQ_EMPTY(&list->el_entries)) {
230*0f4c859eSApple OSS Distributions ep = TAILQ_FIRST(&list->el_entries);
231*0f4c859eSApple OSS Distributions TAILQ_REMOVE(&list->el_entries, ep, ee_link);
232*0f4c859eSApple OSS Distributions kfree_type(struct eventhandler_entry, ep);
233*0f4c859eSApple OSS Distributions }
234*0f4c859eSApple OSS Distributions } else {
235*0f4c859eSApple OSS Distributions evhlog((LOG_DEBUG, "%s: marking all items from \"%s\" as dead",
236*0f4c859eSApple OSS Distributions __func__, list->el_name));
237*0f4c859eSApple OSS Distributions TAILQ_FOREACH(ep, &list->el_entries, ee_link)
238*0f4c859eSApple OSS Distributions ep->ee_priority = EHE_DEAD_PRIORITY;
239*0f4c859eSApple OSS Distributions }
240*0f4c859eSApple OSS Distributions }
241*0f4c859eSApple OSS Distributions while (list->el_runcount > 0) {
242*0f4c859eSApple OSS Distributions msleep((caddr_t)list, &list->el_lock, PSPIN, "evhrm", 0);
243*0f4c859eSApple OSS Distributions }
244*0f4c859eSApple OSS Distributions EHL_UNLOCK(list);
245*0f4c859eSApple OSS Distributions }
246*0f4c859eSApple OSS Distributions
247*0f4c859eSApple OSS Distributions /*
248*0f4c859eSApple OSS Distributions * Internal version for use when eventhandler list is already locked.
249*0f4c859eSApple OSS Distributions */
250*0f4c859eSApple OSS Distributions static struct eventhandler_list *
_eventhandler_find_list(struct eventhandler_lists_ctxt * evthdlr_lists_ctxt,const char * name)251*0f4c859eSApple OSS Distributions _eventhandler_find_list(struct eventhandler_lists_ctxt *evthdlr_lists_ctxt,
252*0f4c859eSApple OSS Distributions const char *name)
253*0f4c859eSApple OSS Distributions {
254*0f4c859eSApple OSS Distributions struct eventhandler_list *list;
255*0f4c859eSApple OSS Distributions
256*0f4c859eSApple OSS Distributions VERIFY(evthdlr_lists_ctxt != NULL);
257*0f4c859eSApple OSS Distributions
258*0f4c859eSApple OSS Distributions LCK_MTX_ASSERT(&evthdlr_lists_ctxt->eventhandler_mutex, LCK_MTX_ASSERT_OWNED);
259*0f4c859eSApple OSS Distributions TAILQ_FOREACH(list, &evthdlr_lists_ctxt->eventhandler_lists, el_link) {
260*0f4c859eSApple OSS Distributions if (!strcmp(name, list->el_name)) {
261*0f4c859eSApple OSS Distributions break;
262*0f4c859eSApple OSS Distributions }
263*0f4c859eSApple OSS Distributions }
264*0f4c859eSApple OSS Distributions return list;
265*0f4c859eSApple OSS Distributions }
266*0f4c859eSApple OSS Distributions
267*0f4c859eSApple OSS Distributions /*
268*0f4c859eSApple OSS Distributions * Lookup a "slow" list by name. Returns with the list locked.
269*0f4c859eSApple OSS Distributions */
270*0f4c859eSApple OSS Distributions struct eventhandler_list *
eventhandler_find_list(struct eventhandler_lists_ctxt * evthdlr_lists_ctxt,const char * name)271*0f4c859eSApple OSS Distributions eventhandler_find_list(struct eventhandler_lists_ctxt *evthdlr_lists_ctxt,
272*0f4c859eSApple OSS Distributions const char *name)
273*0f4c859eSApple OSS Distributions {
274*0f4c859eSApple OSS Distributions struct eventhandler_list *list;
275*0f4c859eSApple OSS Distributions
276*0f4c859eSApple OSS Distributions if (evthdlr_lists_ctxt == NULL) {
277*0f4c859eSApple OSS Distributions evthdlr_lists_ctxt = &evthdlr_lists_ctxt_glb;
278*0f4c859eSApple OSS Distributions }
279*0f4c859eSApple OSS Distributions
280*0f4c859eSApple OSS Distributions if (!evthdlr_lists_ctxt->eventhandler_lists_initted) {
281*0f4c859eSApple OSS Distributions return NULL;
282*0f4c859eSApple OSS Distributions }
283*0f4c859eSApple OSS Distributions
284*0f4c859eSApple OSS Distributions /* scan looking for the requested list */
285*0f4c859eSApple OSS Distributions lck_mtx_lock_spin(&evthdlr_lists_ctxt->eventhandler_mutex);
286*0f4c859eSApple OSS Distributions list = _eventhandler_find_list(evthdlr_lists_ctxt, name);
287*0f4c859eSApple OSS Distributions if (list != NULL) {
288*0f4c859eSApple OSS Distributions lck_mtx_convert_spin(&evthdlr_lists_ctxt->eventhandler_mutex);
289*0f4c859eSApple OSS Distributions EHL_LOCK_SPIN(list);
290*0f4c859eSApple OSS Distributions }
291*0f4c859eSApple OSS Distributions lck_mtx_unlock(&evthdlr_lists_ctxt->eventhandler_mutex);
292*0f4c859eSApple OSS Distributions
293*0f4c859eSApple OSS Distributions return list;
294*0f4c859eSApple OSS Distributions }
295*0f4c859eSApple OSS Distributions
296*0f4c859eSApple OSS Distributions /*
297*0f4c859eSApple OSS Distributions * Prune "dead" entries from an eventhandler list.
298*0f4c859eSApple OSS Distributions */
299*0f4c859eSApple OSS Distributions void
eventhandler_prune_list(struct eventhandler_list * list)300*0f4c859eSApple OSS Distributions eventhandler_prune_list(struct eventhandler_list *list)
301*0f4c859eSApple OSS Distributions {
302*0f4c859eSApple OSS Distributions struct eventhandler_entry *ep, *en;
303*0f4c859eSApple OSS Distributions int pruned = 0;
304*0f4c859eSApple OSS Distributions
305*0f4c859eSApple OSS Distributions evhlog((LOG_DEBUG, "%s: pruning list \"%s\"", __func__, list->el_name));
306*0f4c859eSApple OSS Distributions EHL_LOCK_ASSERT(list, LCK_MTX_ASSERT_OWNED);
307*0f4c859eSApple OSS Distributions TAILQ_FOREACH_SAFE(ep, &list->el_entries, ee_link, en) {
308*0f4c859eSApple OSS Distributions if (ep->ee_priority == EHE_DEAD_PRIORITY) {
309*0f4c859eSApple OSS Distributions TAILQ_REMOVE(&list->el_entries, ep, ee_link);
310*0f4c859eSApple OSS Distributions kfree_type(struct eventhandler_entry, ep);
311*0f4c859eSApple OSS Distributions pruned++;
312*0f4c859eSApple OSS Distributions }
313*0f4c859eSApple OSS Distributions }
314*0f4c859eSApple OSS Distributions if (pruned > 0) {
315*0f4c859eSApple OSS Distributions wakeup(list);
316*0f4c859eSApple OSS Distributions }
317*0f4c859eSApple OSS Distributions }
318*0f4c859eSApple OSS Distributions
319*0f4c859eSApple OSS Distributions /*
320*0f4c859eSApple OSS Distributions * This should be called when last reference to an object
321*0f4c859eSApple OSS Distributions * is being released.
322*0f4c859eSApple OSS Distributions * The individual event type lists must be purged when the object
323*0f4c859eSApple OSS Distributions * becomes defunct.
324*0f4c859eSApple OSS Distributions */
325*0f4c859eSApple OSS Distributions void
eventhandler_lists_ctxt_destroy(struct eventhandler_lists_ctxt * evthdlr_lists_ctxt)326*0f4c859eSApple OSS Distributions eventhandler_lists_ctxt_destroy(struct eventhandler_lists_ctxt *evthdlr_lists_ctxt)
327*0f4c859eSApple OSS Distributions {
328*0f4c859eSApple OSS Distributions struct eventhandler_list *list = NULL;
329*0f4c859eSApple OSS Distributions struct eventhandler_list *list_next = NULL;
330*0f4c859eSApple OSS Distributions
331*0f4c859eSApple OSS Distributions lck_mtx_lock(&evthdlr_lists_ctxt->eventhandler_mutex);
332*0f4c859eSApple OSS Distributions TAILQ_FOREACH_SAFE(list, &evthdlr_lists_ctxt->eventhandler_lists,
333*0f4c859eSApple OSS Distributions el_link, list_next) {
334*0f4c859eSApple OSS Distributions VERIFY(TAILQ_EMPTY(&list->el_entries));
335*0f4c859eSApple OSS Distributions EHL_LOCK_DESTROY(list);
336*0f4c859eSApple OSS Distributions kfree_type(struct eventhandler_list, list);
337*0f4c859eSApple OSS Distributions }
338*0f4c859eSApple OSS Distributions lck_mtx_unlock(&evthdlr_lists_ctxt->eventhandler_mutex);
339*0f4c859eSApple OSS Distributions lck_mtx_destroy(&evthdlr_lists_ctxt->eventhandler_mutex,
340*0f4c859eSApple OSS Distributions &eventhandler_mutex_grp);
341*0f4c859eSApple OSS Distributions return;
342*0f4c859eSApple OSS Distributions }
343