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 59dd0f810Scindi * Common Development and Distribution License (the "License"). 69dd0f810Scindi * 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*24db4641Seschrock * Copyright 2007 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 <sys/fm/protocol.h> 307c478bd9Sstevel@tonic-gate #include <limits.h> 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <fmd_alloc.h> 337c478bd9Sstevel@tonic-gate #include <fmd_subr.h> 347c478bd9Sstevel@tonic-gate #include <fmd_event.h> 357c478bd9Sstevel@tonic-gate #include <fmd_string.h> 36d9638e54Smws #include <fmd_module.h> 377c478bd9Sstevel@tonic-gate #include <fmd_case.h> 387c478bd9Sstevel@tonic-gate #include <fmd_log.h> 397c478bd9Sstevel@tonic-gate #include <fmd_time.h> 40*24db4641Seschrock #include <fmd_topo.h> 417c478bd9Sstevel@tonic-gate #include <fmd_ctl.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #include <fmd.h> 447c478bd9Sstevel@tonic-gate 45d9638e54Smws static void 46d9638e54Smws fmd_event_nvwrap(fmd_event_impl_t *ep) 47d9638e54Smws { 48d9638e54Smws (void) nvlist_remove_all(ep->ev_nvl, FMD_EVN_TTL); 49d9638e54Smws (void) nvlist_remove_all(ep->ev_nvl, FMD_EVN_TOD); 50d9638e54Smws 51d9638e54Smws (void) nvlist_add_uint8(ep->ev_nvl, 52d9638e54Smws FMD_EVN_TTL, ep->ev_ttl); 53d9638e54Smws (void) nvlist_add_uint64_array(ep->ev_nvl, 54d9638e54Smws FMD_EVN_TOD, (uint64_t *)&ep->ev_time, 2); 55d9638e54Smws } 56d9638e54Smws 57d9638e54Smws static void 58d9638e54Smws fmd_event_nvunwrap(fmd_event_impl_t *ep, const fmd_timeval_t *tp) 59d9638e54Smws { 60d9638e54Smws uint64_t *tod; 61d9638e54Smws uint_t n; 62d9638e54Smws 63d9638e54Smws if (nvlist_lookup_uint8(ep->ev_nvl, FMD_EVN_TTL, &ep->ev_ttl) != 0) { 64d9638e54Smws ep->ev_flags |= FMD_EVF_LOCAL; 65d9638e54Smws ep->ev_ttl = (uint8_t)fmd.d_xprt_ttl; 66d9638e54Smws } 67d9638e54Smws 68d9638e54Smws if (tp != NULL) 69d9638e54Smws ep->ev_time = *tp; 70d9638e54Smws else if (nvlist_lookup_uint64_array(ep->ev_nvl, 71d9638e54Smws FMD_EVN_TOD, &tod, &n) == 0 && n >= 2) 72d9638e54Smws ep->ev_time = *(const fmd_timeval_t *)tod; 73d9638e54Smws else 74d9638e54Smws fmd_time_sync(&ep->ev_time, &ep->ev_hrt, 1); 75d9638e54Smws } 76d9638e54Smws 777c478bd9Sstevel@tonic-gate fmd_event_t * 787c478bd9Sstevel@tonic-gate fmd_event_recreate(uint_t type, const fmd_timeval_t *tp, 797c478bd9Sstevel@tonic-gate nvlist_t *nvl, void *data, fmd_log_t *lp, off64_t off, size_t len) 807c478bd9Sstevel@tonic-gate { 817c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = fmd_alloc(sizeof (fmd_event_impl_t), FMD_SLEEP); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate fmd_timeval_t tod; 847c478bd9Sstevel@tonic-gate hrtime_t hr0; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&ep->ev_lock, NULL); 877c478bd9Sstevel@tonic-gate ep->ev_refs = 0; 887c478bd9Sstevel@tonic-gate ASSERT(type < FMD_EVT_NTYPES); 89d9638e54Smws ep->ev_type = (uint8_t)type; 907c478bd9Sstevel@tonic-gate ep->ev_state = FMD_EVS_RECEIVED; 917c478bd9Sstevel@tonic-gate ep->ev_flags = FMD_EVF_REPLAY; 927c478bd9Sstevel@tonic-gate ep->ev_nvl = nvl; 937c478bd9Sstevel@tonic-gate ep->ev_data = data; 947c478bd9Sstevel@tonic-gate ep->ev_log = lp; 957c478bd9Sstevel@tonic-gate ep->ev_off = off; 967c478bd9Sstevel@tonic-gate ep->ev_len = len; 977c478bd9Sstevel@tonic-gate 98d9638e54Smws fmd_event_nvunwrap(ep, tp); 99d9638e54Smws 1007c478bd9Sstevel@tonic-gate /* 1017c478bd9Sstevel@tonic-gate * If we're not restoring from a log, the event is marked volatile. If 1027c478bd9Sstevel@tonic-gate * we are restoring from a log, then hold the log pointer and increment 1037c478bd9Sstevel@tonic-gate * the pending count. If we're using a log but no offset and data len 1047c478bd9Sstevel@tonic-gate * are specified, it's a checkpoint event: don't replay or set pending. 1057c478bd9Sstevel@tonic-gate */ 1067c478bd9Sstevel@tonic-gate if (lp == NULL) 1077c478bd9Sstevel@tonic-gate ep->ev_flags |= FMD_EVF_VOLATILE; 1087c478bd9Sstevel@tonic-gate else if (off != 0 && len != 0) 1097c478bd9Sstevel@tonic-gate fmd_log_hold_pending(lp); 1107c478bd9Sstevel@tonic-gate else { 1117c478bd9Sstevel@tonic-gate ep->ev_flags &= ~FMD_EVF_REPLAY; 1127c478bd9Sstevel@tonic-gate fmd_log_hold(lp); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Sample a (TOD, hrtime) pair from the current system clocks and then 117d9638e54Smws * compute ev_hrt by taking the delta between this TOD and ev_time. 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate fmd_time_sync(&tod, &hr0, 1); 120d9638e54Smws fmd_time_tod2hrt(hr0, &tod, &ep->ev_time, &ep->ev_hrt); 1217c478bd9Sstevel@tonic-gate 122d9638e54Smws fmd_event_nvwrap(ep); 1237c478bd9Sstevel@tonic-gate return ((fmd_event_t *)ep); 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate fmd_event_t * 1277c478bd9Sstevel@tonic-gate fmd_event_create(uint_t type, hrtime_t hrt, nvlist_t *nvl, void *data) 1287c478bd9Sstevel@tonic-gate { 1297c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = fmd_alloc(sizeof (fmd_event_impl_t), FMD_SLEEP); 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate fmd_timeval_t tod; 1327c478bd9Sstevel@tonic-gate hrtime_t hr0; 1337c478bd9Sstevel@tonic-gate const char *p; 1347c478bd9Sstevel@tonic-gate uint64_t ena; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&ep->ev_lock, NULL); 1377c478bd9Sstevel@tonic-gate ep->ev_refs = 0; 1387c478bd9Sstevel@tonic-gate ASSERT(type < FMD_EVT_NTYPES); 139d9638e54Smws ep->ev_type = (uint8_t)type; 1407c478bd9Sstevel@tonic-gate ep->ev_state = FMD_EVS_RECEIVED; 141d9638e54Smws ep->ev_flags = FMD_EVF_VOLATILE | FMD_EVF_REPLAY | FMD_EVF_LOCAL; 142d9638e54Smws ep->ev_ttl = (uint8_t)fmd.d_xprt_ttl; 1437c478bd9Sstevel@tonic-gate ep->ev_nvl = nvl; 1447c478bd9Sstevel@tonic-gate ep->ev_data = data; 1457c478bd9Sstevel@tonic-gate ep->ev_log = NULL; 1467c478bd9Sstevel@tonic-gate ep->ev_off = 0; 1477c478bd9Sstevel@tonic-gate ep->ev_len = 0; 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* 1507c478bd9Sstevel@tonic-gate * Sample TOD and then set ev_time to the earlier TOD corresponding to 1517c478bd9Sstevel@tonic-gate * the input hrtime value. This needs to be improved later: hrestime 1527c478bd9Sstevel@tonic-gate * should be sampled by the transport and passed as an input parameter. 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate fmd_time_sync(&tod, &hr0, 1); 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate if (hrt == FMD_HRT_NOW) 1577c478bd9Sstevel@tonic-gate hrt = hr0; /* use hrtime sampled by fmd_time_sync() */ 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* 1607c478bd9Sstevel@tonic-gate * If this is an FMA protocol event of class "ereport.*" that contains 1617c478bd9Sstevel@tonic-gate * valid ENA, we can compute a more precise bound on the event time. 1627c478bd9Sstevel@tonic-gate */ 1637c478bd9Sstevel@tonic-gate if (type == FMD_EVT_PROTOCOL && (p = strchr(data, '.')) != NULL && 1647c478bd9Sstevel@tonic-gate strncmp(data, FM_EREPORT_CLASS, (size_t)(p - (char *)data)) == 0 && 1657c478bd9Sstevel@tonic-gate nvlist_lookup_uint64(nvl, FM_EREPORT_ENA, &ena) == 0 && 1667c478bd9Sstevel@tonic-gate fmd.d_clockops == &fmd_timeops_native) 1677c478bd9Sstevel@tonic-gate hrt = fmd_time_ena2hrt(hrt, ena); 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate fmd_time_hrt2tod(hr0, &tod, hrt, &ep->ev_time); 1707c478bd9Sstevel@tonic-gate ep->ev_hrt = hrt; 1717c478bd9Sstevel@tonic-gate 172d9638e54Smws fmd_event_nvwrap(ep); 1737c478bd9Sstevel@tonic-gate return ((fmd_event_t *)ep); 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate void 1777c478bd9Sstevel@tonic-gate fmd_event_destroy(fmd_event_t *e) 1787c478bd9Sstevel@tonic-gate { 1797c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ep->ev_lock)); 1827c478bd9Sstevel@tonic-gate ASSERT(ep->ev_refs == 0); 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * If the current state is RECEIVED (i.e. no module has accepted the 1867c478bd9Sstevel@tonic-gate * event) and the event was logged, then change the state to DISCARDED. 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate if (ep->ev_state == FMD_EVS_RECEIVED) 1897c478bd9Sstevel@tonic-gate ep->ev_state = FMD_EVS_DISCARDED; 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * If the current state is DISCARDED, ACCEPTED, or DIAGNOSED and the 1937c478bd9Sstevel@tonic-gate * event has not yet been commited, then attempt to commit it now. 1947c478bd9Sstevel@tonic-gate */ 1957c478bd9Sstevel@tonic-gate if (ep->ev_state != FMD_EVS_RECEIVED && (ep->ev_flags & ( 1967c478bd9Sstevel@tonic-gate FMD_EVF_VOLATILE | FMD_EVF_REPLAY)) == FMD_EVF_REPLAY) 1977c478bd9Sstevel@tonic-gate fmd_log_commit(ep->ev_log, e); 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate if (ep->ev_log != NULL) { 2007c478bd9Sstevel@tonic-gate if (ep->ev_flags & FMD_EVF_REPLAY) 2017c478bd9Sstevel@tonic-gate fmd_log_decommit(ep->ev_log, e); 2027c478bd9Sstevel@tonic-gate fmd_log_rele(ep->ev_log); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* 2067c478bd9Sstevel@tonic-gate * Perform any event type-specific cleanup activities, and then free 2077c478bd9Sstevel@tonic-gate * the name-value pair list and underlying event data structure. 2087c478bd9Sstevel@tonic-gate */ 2097c478bd9Sstevel@tonic-gate switch (ep->ev_type) { 210d9638e54Smws case FMD_EVT_TIMEOUT: 211d9638e54Smws fmd_free(ep->ev_data, sizeof (fmd_modtimer_t)); 212d9638e54Smws break; 2137c478bd9Sstevel@tonic-gate case FMD_EVT_CLOSE: 214d9638e54Smws case FMD_EVT_PUBLISH: 2157c478bd9Sstevel@tonic-gate fmd_case_rele(ep->ev_data); 2167c478bd9Sstevel@tonic-gate break; 2177c478bd9Sstevel@tonic-gate case FMD_EVT_CTL: 2187c478bd9Sstevel@tonic-gate fmd_ctl_fini(ep->ev_data); 2197c478bd9Sstevel@tonic-gate break; 220*24db4641Seschrock case FMD_EVT_TOPO: 221*24db4641Seschrock fmd_topo_rele(ep->ev_data); 222*24db4641Seschrock break; 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if (ep->ev_nvl != NULL) 2267c478bd9Sstevel@tonic-gate nvlist_free(ep->ev_nvl); 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate fmd_free(ep, sizeof (fmd_event_impl_t)); 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate void 2327c478bd9Sstevel@tonic-gate fmd_event_hold(fmd_event_t *e) 2337c478bd9Sstevel@tonic-gate { 2347c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ep->ev_lock); 2377c478bd9Sstevel@tonic-gate ep->ev_refs++; 2387c478bd9Sstevel@tonic-gate ASSERT(ep->ev_refs != 0); 2397c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->ev_lock); 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate if (ep->ev_type == FMD_EVT_CTL) 2427c478bd9Sstevel@tonic-gate fmd_ctl_hold(ep->ev_data); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate void 2467c478bd9Sstevel@tonic-gate fmd_event_rele(fmd_event_t *e) 2477c478bd9Sstevel@tonic-gate { 2487c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate if (ep->ev_type == FMD_EVT_CTL) 2517c478bd9Sstevel@tonic-gate fmd_ctl_rele(ep->ev_data); 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ep->ev_lock); 2547c478bd9Sstevel@tonic-gate ASSERT(ep->ev_refs != 0); 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate if (--ep->ev_refs == 0) 2577c478bd9Sstevel@tonic-gate fmd_event_destroy(e); 2587c478bd9Sstevel@tonic-gate else 2597c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->ev_lock); 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * Transition event from its current state to the specified state. The states 2647c478bd9Sstevel@tonic-gate * for events are defined in fmd_event.h and work according to the diagram: 2657c478bd9Sstevel@tonic-gate * 2667c478bd9Sstevel@tonic-gate * ------------- ------------- State Description 2677c478bd9Sstevel@tonic-gate * ( RECEIVED =1 )-->( ACCEPTED =2 ) ---------- --------------------------- 2687c478bd9Sstevel@tonic-gate * -----+-------\ ------+------ DISCARDED No active references in fmd 2697c478bd9Sstevel@tonic-gate * | \ | RECEIVED Active refs in fmd, no case 2707c478bd9Sstevel@tonic-gate * -----v------- \ ------v------ ACCEPTED Active refs, case assigned 2717c478bd9Sstevel@tonic-gate * ( DISCARDED=0 ) v( DIAGNOSED=3 ) DIAGNOSED Active refs, case solved 2727c478bd9Sstevel@tonic-gate * ------------- ------------- 2737c478bd9Sstevel@tonic-gate * 2747c478bd9Sstevel@tonic-gate * Since events are reference counted on behalf of multiple subscribers, any 2757c478bd9Sstevel@tonic-gate * attempt to transition an event to an "earlier" or "equal" state (as defined 2767c478bd9Sstevel@tonic-gate * by the numeric state values shown in the diagram) is silently ignored. 2777c478bd9Sstevel@tonic-gate * An event begins life in the RECEIVED state, so the RECEIVED -> DISCARDED 2787c478bd9Sstevel@tonic-gate * transition is handled by fmd_event_destroy() when no references remain. 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate void 2817c478bd9Sstevel@tonic-gate fmd_event_transition(fmd_event_t *e, uint_t state) 2827c478bd9Sstevel@tonic-gate { 2837c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ep->ev_lock); 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate TRACE((FMD_DBG_EVT, "event %p transition %u -> %u", 2887c478bd9Sstevel@tonic-gate (void *)ep, ep->ev_state, state)); 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate if (state <= ep->ev_state) { 2917c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->ev_lock); 2927c478bd9Sstevel@tonic-gate return; /* no state change necessary */ 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate if (ep->ev_state < FMD_EVS_RECEIVED || ep->ev_state > FMD_EVS_DIAGNOSED) 2967c478bd9Sstevel@tonic-gate fmd_panic("illegal transition %u -> %u\n", ep->ev_state, state); 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate ep->ev_state = state; 2997c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->ev_lock); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * If the specified event is DISCARDED, ACCEPTED, OR DIAGNOSED and it has been 3047c478bd9Sstevel@tonic-gate * written to a log but is still marked for replay, attempt to commit it to the 3057c478bd9Sstevel@tonic-gate * log so that it will not be replayed. If fmd_log_commit() is successful, it 3067c478bd9Sstevel@tonic-gate * will clear the FMD_EVF_REPLAY flag on the event for us. 3077c478bd9Sstevel@tonic-gate */ 3087c478bd9Sstevel@tonic-gate void 3097c478bd9Sstevel@tonic-gate fmd_event_commit(fmd_event_t *e) 3107c478bd9Sstevel@tonic-gate { 3117c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ep->ev_lock); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate if (ep->ev_state != FMD_EVS_RECEIVED && (ep->ev_flags & ( 3167c478bd9Sstevel@tonic-gate FMD_EVF_VOLATILE | FMD_EVF_REPLAY)) == FMD_EVF_REPLAY) 3177c478bd9Sstevel@tonic-gate fmd_log_commit(ep->ev_log, e); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->ev_lock); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * Compute the delta between events in nanoseconds. To account for very old 3247c478bd9Sstevel@tonic-gate * events which are replayed, we must handle the case where ev_hrt is negative. 3257c478bd9Sstevel@tonic-gate * We convert the hrtime_t's to unsigned 64-bit integers and then handle the 3267c478bd9Sstevel@tonic-gate * case where 'old' is greater than 'new' (i.e. high-res time has wrapped). 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate hrtime_t 3297c478bd9Sstevel@tonic-gate fmd_event_delta(fmd_event_t *e1, fmd_event_t *e2) 3307c478bd9Sstevel@tonic-gate { 3317c478bd9Sstevel@tonic-gate uint64_t old = ((fmd_event_impl_t *)e1)->ev_hrt; 3327c478bd9Sstevel@tonic-gate uint64_t new = ((fmd_event_impl_t *)e2)->ev_hrt; 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate return (new >= old ? new - old : (UINT64_MAX - old) + new + 1); 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate hrtime_t 3387c478bd9Sstevel@tonic-gate fmd_event_hrtime(fmd_event_t *ep) 3397c478bd9Sstevel@tonic-gate { 3407c478bd9Sstevel@tonic-gate return (((fmd_event_impl_t *)ep)->ev_hrt); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate int 344d9638e54Smws fmd_event_match(fmd_event_t *e, uint_t type, const void *data) 3457c478bd9Sstevel@tonic-gate { 3467c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate if (type == FMD_EVT_PROTOCOL) 3497c478bd9Sstevel@tonic-gate return (ep->ev_type == type && fmd_strmatch(ep->ev_data, data)); 3509dd0f810Scindi else if (type == FMD_EVT_TIMEOUT) 3519dd0f810Scindi return ((id_t)data == ((fmd_modtimer_t *)ep->ev_data)->mt_id); 3527c478bd9Sstevel@tonic-gate else 3537c478bd9Sstevel@tonic-gate return (ep->ev_type == type && ep->ev_data == data); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate int 3577c478bd9Sstevel@tonic-gate fmd_event_equal(fmd_event_t *e1, fmd_event_t *e2) 3587c478bd9Sstevel@tonic-gate { 3597c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep1 = (fmd_event_impl_t *)e1; 3607c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep2 = (fmd_event_impl_t *)e2; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate return (ep1->ev_log != NULL && 3637c478bd9Sstevel@tonic-gate ep1->ev_log == ep2->ev_log && ep1->ev_off == ep2->ev_off); 3647c478bd9Sstevel@tonic-gate } 365