xref: /illumos-gate/usr/src/cmd/fm/fmd/common/fmd_eventq.c (revision 8aec91825357bbeaf2ab5d30fc97fe5051a6b8dd)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*8aec9182Sstephh  * Common Development and Distribution License (the "License").
6*8aec9182Sstephh  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21d9638e54Smws 
227c478bd9Sstevel@tonic-gate /*
23*8aec9182Sstephh  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <fmd_alloc.h>
307c478bd9Sstevel@tonic-gate #include <fmd_eventq.h>
317c478bd9Sstevel@tonic-gate #include <fmd_module.h>
32d9638e54Smws #include <fmd_dispq.h>
33d9638e54Smws #include <fmd_subr.h>
34d9638e54Smws 
35d9638e54Smws #include <fmd.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate fmd_eventq_t *
38d9638e54Smws fmd_eventq_create(fmd_module_t *mp, fmd_eventqstat_t *stats,
39d9638e54Smws     pthread_mutex_t *stats_lock, uint_t limit)
407c478bd9Sstevel@tonic-gate {
417c478bd9Sstevel@tonic-gate 	fmd_eventq_t *eq = fmd_zalloc(sizeof (fmd_eventq_t), FMD_SLEEP);
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&eq->eq_lock, NULL);
447c478bd9Sstevel@tonic-gate 	(void) pthread_cond_init(&eq->eq_cv, NULL);
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate 	eq->eq_mod = mp;
47d9638e54Smws 	eq->eq_stats = stats;
48d9638e54Smws 	eq->eq_stats_lock = stats_lock;
497c478bd9Sstevel@tonic-gate 	eq->eq_limit = limit;
50d9638e54Smws 	eq->eq_sgid = fmd_dispq_getgid(fmd.d_disp, eq);
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate 	return (eq);
537c478bd9Sstevel@tonic-gate }
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate void
567c478bd9Sstevel@tonic-gate fmd_eventq_destroy(fmd_eventq_t *eq)
577c478bd9Sstevel@tonic-gate {
587c478bd9Sstevel@tonic-gate 	fmd_eventqelem_t *eqe;
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 	while ((eqe = fmd_list_next(&eq->eq_list)) != NULL) {
617c478bd9Sstevel@tonic-gate 		fmd_list_delete(&eq->eq_list, eqe);
627c478bd9Sstevel@tonic-gate 		fmd_event_rele(eqe->eqe_event);
637c478bd9Sstevel@tonic-gate 		fmd_free(eqe, sizeof (fmd_eventqelem_t));
647c478bd9Sstevel@tonic-gate 	}
657c478bd9Sstevel@tonic-gate 
66d9638e54Smws 	fmd_dispq_delgid(fmd.d_disp, eq->eq_sgid);
677c478bd9Sstevel@tonic-gate 	fmd_free(eq, sizeof (fmd_eventq_t));
687c478bd9Sstevel@tonic-gate }
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate static void
717c478bd9Sstevel@tonic-gate fmd_eventq_drop(fmd_eventq_t *eq, fmd_eventqelem_t *eqe)
727c478bd9Sstevel@tonic-gate {
73d9638e54Smws 	(void) pthread_mutex_lock(eq->eq_stats_lock);
74d9638e54Smws 	eq->eq_stats->eqs_dropped.fmds_value.ui64++;
75d9638e54Smws 	(void) pthread_mutex_unlock(eq->eq_stats_lock);
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	fmd_event_rele(eqe->eqe_event);
787c478bd9Sstevel@tonic-gate 	fmd_free(eqe, sizeof (fmd_eventqelem_t));
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate 
81d9638e54Smws /*
82d9638e54Smws  * Update statistics when an event is dispatched and placed on a module's event
83d9638e54Smws  * queue.  This is essentially the same code as kstat_waitq_enter(9F).
84d9638e54Smws  */
85d9638e54Smws static void
86d9638e54Smws fmd_eventqstat_dispatch(fmd_eventq_t *eq)
87d9638e54Smws {
88d9638e54Smws 	fmd_eventqstat_t *eqs = eq->eq_stats;
89d9638e54Smws 	hrtime_t new, delta;
90d9638e54Smws 	uint32_t wcnt;
91d9638e54Smws 
92d9638e54Smws 	(void) pthread_mutex_lock(eq->eq_stats_lock);
93d9638e54Smws 
94d9638e54Smws 	new = gethrtime();
95d9638e54Smws 	delta = new - eqs->eqs_wlastupdate.fmds_value.ui64;
96d9638e54Smws 	eqs->eqs_wlastupdate.fmds_value.ui64 = new;
97d9638e54Smws 	wcnt = eqs->eqs_wcnt.fmds_value.ui32++;
98d9638e54Smws 
99d9638e54Smws 	if (wcnt != 0) {
100d9638e54Smws 		eqs->eqs_wlentime.fmds_value.ui64 += delta * wcnt;
101d9638e54Smws 		eqs->eqs_wtime.fmds_value.ui64 += delta;
102d9638e54Smws 	}
103d9638e54Smws 
104d9638e54Smws 	eqs->eqs_dispatched.fmds_value.ui64++;
105d9638e54Smws 	(void) pthread_mutex_unlock(eq->eq_stats_lock);
106d9638e54Smws }
107d9638e54Smws 
1087c478bd9Sstevel@tonic-gate void
1097c478bd9Sstevel@tonic-gate fmd_eventq_insert_at_head(fmd_eventq_t *eq, fmd_event_t *ep)
1107c478bd9Sstevel@tonic-gate {
111d9638e54Smws 	uint_t evt = FMD_EVENT_TYPE(ep);
112d9638e54Smws 	fmd_eventqelem_t *eqe;
1137c478bd9Sstevel@tonic-gate 	int ok;
1147c478bd9Sstevel@tonic-gate 
115d9638e54Smws 	/*
116d9638e54Smws 	 * If this event queue is acting as /dev/null, bounce the reference
117d9638e54Smws 	 * count to free an unreferenced event and just return immediately.
118d9638e54Smws 	 */
119d9638e54Smws 	if (eq->eq_limit == 0) {
120d9638e54Smws 		fmd_event_hold(ep);
121d9638e54Smws 		fmd_event_rele(ep);
122d9638e54Smws 		return;
123d9638e54Smws 	}
124d9638e54Smws 
125d9638e54Smws 	eqe = fmd_alloc(sizeof (fmd_eventqelem_t), FMD_SLEEP);
1267c478bd9Sstevel@tonic-gate 	fmd_event_hold(ep);
1277c478bd9Sstevel@tonic-gate 	eqe->eqe_event = ep;
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&eq->eq_lock);
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	if ((ok = eq->eq_size < eq->eq_limit || evt != FMD_EVT_PROTOCOL) != 0) {
1327c478bd9Sstevel@tonic-gate 		if (evt != FMD_EVT_CTL)
133d9638e54Smws 			fmd_eventqstat_dispatch(eq);
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 		fmd_list_prepend(&eq->eq_list, eqe);
1367c478bd9Sstevel@tonic-gate 		eq->eq_size++;
1377c478bd9Sstevel@tonic-gate 	}
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	(void) pthread_cond_broadcast(&eq->eq_cv);
140d9638e54Smws 	(void) pthread_mutex_unlock(&eq->eq_lock);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	if (!ok)
1437c478bd9Sstevel@tonic-gate 		fmd_eventq_drop(eq, eqe);
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate void
1477c478bd9Sstevel@tonic-gate fmd_eventq_insert_at_time(fmd_eventq_t *eq, fmd_event_t *ep)
1487c478bd9Sstevel@tonic-gate {
149d9638e54Smws 	uint_t evt = FMD_EVENT_TYPE(ep);
1507c478bd9Sstevel@tonic-gate 	hrtime_t hrt = fmd_event_hrtime(ep);
151d9638e54Smws 	fmd_eventqelem_t *eqe, *oqe;
1527c478bd9Sstevel@tonic-gate 	int ok;
1537c478bd9Sstevel@tonic-gate 
154d9638e54Smws 	/*
155d9638e54Smws 	 * If this event queue is acting as /dev/null, bounce the reference
156d9638e54Smws 	 * count to free an unreferenced event and just return immediately.
157d9638e54Smws 	 */
158d9638e54Smws 	if (eq->eq_limit == 0) {
159d9638e54Smws 		fmd_event_hold(ep);
160d9638e54Smws 		fmd_event_rele(ep);
161d9638e54Smws 		return;
162d9638e54Smws 	}
163d9638e54Smws 
164d9638e54Smws 	eqe = fmd_alloc(sizeof (fmd_eventqelem_t), FMD_SLEEP);
1657c478bd9Sstevel@tonic-gate 	fmd_event_hold(ep);
1667c478bd9Sstevel@tonic-gate 	eqe->eqe_event = ep;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&eq->eq_lock);
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	/*
1717c478bd9Sstevel@tonic-gate 	 * fmd makes no guarantees that events will be delivered in time order
1727c478bd9Sstevel@tonic-gate 	 * because its transport can make no such guarantees.  Instead we make
1737c478bd9Sstevel@tonic-gate 	 * a looser guarantee that an enqueued event will be dequeued before
1747c478bd9Sstevel@tonic-gate 	 * any newer *pending* events according to event time.  This permits us
1757c478bd9Sstevel@tonic-gate 	 * to state, for example, that a timer expiry event will be delivered
1767c478bd9Sstevel@tonic-gate 	 * prior to any enqueued event whose time is after the timer expired.
1777c478bd9Sstevel@tonic-gate 	 * We use a simple insertion sort for this task, as queue lengths are
1787c478bd9Sstevel@tonic-gate 	 * typically short and events do *tend* to be received chronologically.
1797c478bd9Sstevel@tonic-gate 	 */
1807c478bd9Sstevel@tonic-gate 	for (oqe = fmd_list_prev(&eq->eq_list); oqe; oqe = fmd_list_prev(oqe)) {
1817c478bd9Sstevel@tonic-gate 		if (hrt >= fmd_event_hrtime(oqe->eqe_event))
1827c478bd9Sstevel@tonic-gate 			break; /* 'ep' is newer than the event in 'oqe' */
1837c478bd9Sstevel@tonic-gate 	}
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	if ((ok = eq->eq_size < eq->eq_limit || evt != FMD_EVT_PROTOCOL) != 0) {
1867c478bd9Sstevel@tonic-gate 		if (evt != FMD_EVT_CTL)
187d9638e54Smws 			fmd_eventqstat_dispatch(eq);
1887c478bd9Sstevel@tonic-gate 
189*8aec9182Sstephh 		if (oqe == NULL)
190*8aec9182Sstephh 			fmd_list_prepend(&eq->eq_list, eqe);
191*8aec9182Sstephh 		else
1927c478bd9Sstevel@tonic-gate 			fmd_list_insert_after(&eq->eq_list, oqe, eqe);
1937c478bd9Sstevel@tonic-gate 		eq->eq_size++;
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	(void) pthread_cond_broadcast(&eq->eq_cv);
197d9638e54Smws 	(void) pthread_mutex_unlock(&eq->eq_lock);
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	if (!ok)
2007c478bd9Sstevel@tonic-gate 		fmd_eventq_drop(eq, eqe);
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate fmd_event_t *
2047c478bd9Sstevel@tonic-gate fmd_eventq_delete(fmd_eventq_t *eq)
2057c478bd9Sstevel@tonic-gate {
206d9638e54Smws 	fmd_eventqstat_t *eqs = eq->eq_stats;
207d9638e54Smws 	hrtime_t new, delta;
208d9638e54Smws 	uint32_t wcnt;
209d9638e54Smws 
2107c478bd9Sstevel@tonic-gate 	fmd_eventqelem_t *eqe;
2117c478bd9Sstevel@tonic-gate 	fmd_event_t *ep;
212d9638e54Smws top:
2137c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&eq->eq_lock);
2147c478bd9Sstevel@tonic-gate 
215d9638e54Smws 	while (!(eq->eq_flags & FMD_EVENTQ_ABORT) &&
216d9638e54Smws 	    (eq->eq_size == 0 || (eq->eq_flags & FMD_EVENTQ_SUSPEND)))
2177c478bd9Sstevel@tonic-gate 		(void) pthread_cond_wait(&eq->eq_cv, &eq->eq_lock);
2187c478bd9Sstevel@tonic-gate 
219d9638e54Smws 	if (eq->eq_flags & FMD_EVENTQ_ABORT) {
2207c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&eq->eq_lock);
2217c478bd9Sstevel@tonic-gate 		return (NULL);
2227c478bd9Sstevel@tonic-gate 	}
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	eqe = fmd_list_next(&eq->eq_list);
2257c478bd9Sstevel@tonic-gate 	fmd_list_delete(&eq->eq_list, eqe);
2267c478bd9Sstevel@tonic-gate 	eq->eq_size--;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&eq->eq_lock);
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	ep = eqe->eqe_event;
2317c478bd9Sstevel@tonic-gate 	fmd_free(eqe, sizeof (fmd_eventqelem_t));
2327c478bd9Sstevel@tonic-gate 
233d9638e54Smws 	/*
234d9638e54Smws 	 * If we dequeued a control event, release it and go back to sleep.
235d9638e54Smws 	 * fmd_event_rele() on the event will block as described in fmd_ctl.c.
236d9638e54Smws 	 * This effectively renders control events invisible to our callers
237d9638e54Smws 	 * as well as to statistics and observability tools (e.g. fmstat(1M)).
238d9638e54Smws 	 */
239d9638e54Smws 	if (FMD_EVENT_TYPE(ep) == FMD_EVT_CTL) {
240d9638e54Smws 		fmd_event_rele(ep);
241d9638e54Smws 		goto top;
242d9638e54Smws 	}
243d9638e54Smws 
244d9638e54Smws 	/*
245d9638e54Smws 	 * Before returning, update our statistics.  This code is essentially
246d9638e54Smws 	 * kstat_waitq_to_runq(9F), except simplified because our queues are
247d9638e54Smws 	 * always consumed by a single thread (i.e. runq len == 1).
248d9638e54Smws 	 */
249d9638e54Smws 	(void) pthread_mutex_lock(eq->eq_stats_lock);
250d9638e54Smws 
251d9638e54Smws 	new = gethrtime();
252d9638e54Smws 	delta = new - eqs->eqs_wlastupdate.fmds_value.ui64;
253d9638e54Smws 
254d9638e54Smws 	eqs->eqs_wlastupdate.fmds_value.ui64 = new;
255d9638e54Smws 	eqs->eqs_dlastupdate.fmds_value.ui64 = new;
256d9638e54Smws 
257d9638e54Smws 	ASSERT(eqs->eqs_wcnt.fmds_value.ui32 != 0);
258d9638e54Smws 	wcnt = eqs->eqs_wcnt.fmds_value.ui32--;
259d9638e54Smws 
260d9638e54Smws 	eqs->eqs_wlentime.fmds_value.ui64 += delta * wcnt;
261d9638e54Smws 	eqs->eqs_wtime.fmds_value.ui64 += delta;
262d9638e54Smws 
263d9638e54Smws 	if (FMD_EVENT_TYPE(ep) == FMD_EVT_PROTOCOL)
264d9638e54Smws 		eqs->eqs_prdequeued.fmds_value.ui64++;
265d9638e54Smws 
266d9638e54Smws 	eqs->eqs_dequeued.fmds_value.ui64++;
267d9638e54Smws 	(void) pthread_mutex_unlock(eq->eq_stats_lock);
268d9638e54Smws 
2697c478bd9Sstevel@tonic-gate 	return (ep);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
272d9638e54Smws /*
273d9638e54Smws  * Update statistics when an event is done being processed by the eventq's
274d9638e54Smws  * consumer thread.  This is essentially kstat_runq_exit(9F) simplified for
275d9638e54Smws  * our principle that a single thread consumes the queue (i.e. runq len == 1).
276d9638e54Smws  */
277d9638e54Smws void
278d9638e54Smws fmd_eventq_done(fmd_eventq_t *eq)
279d9638e54Smws {
280d9638e54Smws 	fmd_eventqstat_t *eqs = eq->eq_stats;
281d9638e54Smws 	hrtime_t new, delta;
282d9638e54Smws 
283d9638e54Smws 	(void) pthread_mutex_lock(eq->eq_stats_lock);
284d9638e54Smws 
285d9638e54Smws 	new = gethrtime();
286d9638e54Smws 	delta = new - eqs->eqs_dlastupdate.fmds_value.ui64;
287d9638e54Smws 
288d9638e54Smws 	eqs->eqs_dlastupdate.fmds_value.ui64 = new;
289d9638e54Smws 	eqs->eqs_dtime.fmds_value.ui64 += delta;
290d9638e54Smws 
291d9638e54Smws 	(void) pthread_mutex_unlock(eq->eq_stats_lock);
292d9638e54Smws }
293d9638e54Smws 
2947c478bd9Sstevel@tonic-gate void
2957c478bd9Sstevel@tonic-gate fmd_eventq_cancel(fmd_eventq_t *eq, uint_t type, void *data)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate 	fmd_eventqelem_t *eqe, *nqe;
2987c478bd9Sstevel@tonic-gate 
2997c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&eq->eq_lock);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	for (eqe = fmd_list_next(&eq->eq_list); eqe != NULL; eqe = nqe) {
3027c478bd9Sstevel@tonic-gate 		nqe = fmd_list_next(eqe);
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 		if (fmd_event_match(eqe->eqe_event, type, data)) {
3057c478bd9Sstevel@tonic-gate 			fmd_list_delete(&eq->eq_list, eqe);
3067c478bd9Sstevel@tonic-gate 			eq->eq_size--;
3077c478bd9Sstevel@tonic-gate 			fmd_event_rele(eqe->eqe_event);
3087c478bd9Sstevel@tonic-gate 			fmd_free(eqe, sizeof (fmd_eventqelem_t));
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&eq->eq_lock);
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate void
316d9638e54Smws fmd_eventq_suspend(fmd_eventq_t *eq)
317d9638e54Smws {
318d9638e54Smws 	(void) pthread_mutex_lock(&eq->eq_lock);
319d9638e54Smws 	eq->eq_flags |= FMD_EVENTQ_SUSPEND;
320d9638e54Smws 	(void) pthread_mutex_unlock(&eq->eq_lock);
321d9638e54Smws }
322d9638e54Smws 
323d9638e54Smws void
324d9638e54Smws fmd_eventq_resume(fmd_eventq_t *eq)
325d9638e54Smws {
326d9638e54Smws 	(void) pthread_mutex_lock(&eq->eq_lock);
327d9638e54Smws 	eq->eq_flags &= ~FMD_EVENTQ_SUSPEND;
328d9638e54Smws 	(void) pthread_cond_broadcast(&eq->eq_cv);
329d9638e54Smws 	(void) pthread_mutex_unlock(&eq->eq_lock);
330d9638e54Smws }
331d9638e54Smws 
332d9638e54Smws void
3337c478bd9Sstevel@tonic-gate fmd_eventq_abort(fmd_eventq_t *eq)
3347c478bd9Sstevel@tonic-gate {
3357c478bd9Sstevel@tonic-gate 	fmd_eventqelem_t *eqe;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&eq->eq_lock);
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	while ((eqe = fmd_list_next(&eq->eq_list)) != NULL) {
3407c478bd9Sstevel@tonic-gate 		fmd_list_delete(&eq->eq_list, eqe);
3417c478bd9Sstevel@tonic-gate 		fmd_event_rele(eqe->eqe_event);
3427c478bd9Sstevel@tonic-gate 		fmd_free(eqe, sizeof (fmd_eventqelem_t));
3437c478bd9Sstevel@tonic-gate 	}
3447c478bd9Sstevel@tonic-gate 
345d9638e54Smws 	eq->eq_flags |= FMD_EVENTQ_ABORT;
3467c478bd9Sstevel@tonic-gate 	(void) pthread_cond_broadcast(&eq->eq_cv);
347d9638e54Smws 	(void) pthread_mutex_unlock(&eq->eq_lock);
3487c478bd9Sstevel@tonic-gate }
349