import less(1)
[unleashed/tickless.git] / usr / src / lib / fm / libfmevent / common / fmev_evaccess.c
blob519f4701d3a6f86ad225b7e74cbe8a6041116bbf
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Subscription event access interfaces.
30 #include <sys/types.h>
31 #include <limits.h>
32 #include <atomic.h>
33 #include <libsysevent.h>
34 #include <umem.h>
35 #include <fm/libfmevent.h>
36 #include <sys/fm/protocol.h>
38 #include "fmev_impl.h"
40 #define FMEV_API_ENTER(iep, v) \
41 fmev_api_enter(fmev_shdl_cmn(((iep)->ei_hdl)), LIBFMEVENT_VERSION_##v)
43 typedef struct {
44 uint32_t ei_magic; /* _FMEVMAGIC */
45 volatile uint32_t ei_refcnt; /* reference count */
46 fmev_shdl_t ei_hdl; /* handle received on */
47 nvlist_t *ei_nvl; /* (duped) sysevent attribute list */
48 uint64_t ei_fmtime[2]; /* embedded protocol event time */
49 } fmev_impl_t;
51 #define FMEV2IMPL(ev) ((fmev_impl_t *)(ev))
52 #define IMPL2FMEV(iep) ((fmev_t)(iep))
54 #define _FMEVMAGIC 0x466d4576 /* "FmEv" */
56 #define EVENT_VALID(iep) ((iep)->ei_magic == _FMEVMAGIC && \
57 (iep)->ei_refcnt > 0 && fmev_shdl_valid((iep)->ei_hdl))
59 #define FM_TIME_SEC 0
60 #define FM_TIME_NSEC 1
63 * Transform a received sysevent_t into an fmev_t.
66 uint64_t fmev_bad_attr, fmev_bad_tod, fmev_bad_class;
68 fmev_t
69 fmev_sysev2fmev(fmev_shdl_t hdl, sysevent_t *sep, char **clsp, nvlist_t **nvlp)
71 fmev_impl_t *iep;
72 uint64_t *tod;
73 uint_t nelem;
75 if ((iep = fmev_shdl_alloc(hdl, sizeof (*iep))) == NULL)
76 return (NULL);
79 * sysevent_get_attr_list duplicates the nvlist - we free it
80 * in fmev_free when the reference count hits zero.
82 if (sysevent_get_attr_list(sep, &iep->ei_nvl) != 0) {
83 fmev_shdl_free(hdl, iep, sizeof (*iep));
84 fmev_bad_attr++;
85 return (NULL);
88 *nvlp = iep->ei_nvl;
90 if (nvlist_lookup_string(iep->ei_nvl, FM_CLASS, clsp) != 0) {
91 nvlist_free(iep->ei_nvl);
92 fmev_shdl_free(hdl, iep, sizeof (*iep));
93 fmev_bad_class++;
94 return (NULL);
97 if (nvlist_lookup_uint64_array(iep->ei_nvl, "__tod", &tod,
98 &nelem) != 0 || nelem != 2) {
99 nvlist_free(iep->ei_nvl);
100 fmev_shdl_free(hdl, iep, sizeof (*iep));
101 fmev_bad_tod++;
102 return (NULL);
105 iep->ei_fmtime[FM_TIME_SEC] = tod[0];
106 iep->ei_fmtime[FM_TIME_NSEC] = tod[1];
109 * Now remove the fmd-private __tod and __ttl members.
111 (void) nvlist_remove_all(iep->ei_nvl, "__tod");
112 (void) nvlist_remove_all(iep->ei_nvl, "__ttl");
114 iep->ei_magic = _FMEVMAGIC;
115 iep->ei_hdl = hdl;
116 iep->ei_refcnt = 1;
117 ASSERT(EVENT_VALID(iep));
119 return (IMPL2FMEV(iep));
122 static void
123 fmev_free(fmev_impl_t *iep)
125 ASSERT(iep->ei_refcnt == 0);
127 nvlist_free(iep->ei_nvl);
128 fmev_shdl_free(iep->ei_hdl, iep, sizeof (*iep));
131 void
132 fmev_hold(fmev_t ev)
134 fmev_impl_t *iep = FMEV2IMPL(ev);
136 ASSERT(EVENT_VALID(iep));
138 (void) FMEV_API_ENTER(iep, 1);
140 atomic_inc_32(&iep->ei_refcnt);
143 void
144 fmev_rele(fmev_t ev)
146 fmev_impl_t *iep = FMEV2IMPL(ev);
148 ASSERT(EVENT_VALID(iep));
150 (void) FMEV_API_ENTER(iep, 1);
152 if (atomic_dec_32_nv(&iep->ei_refcnt) == 0)
153 fmev_free(iep);
156 fmev_t
157 fmev_dup(fmev_t ev)
159 fmev_impl_t *iep = FMEV2IMPL(ev);
160 fmev_impl_t *cp;
162 ASSERT(EVENT_VALID(iep));
164 if (!FMEV_API_ENTER(iep, 1))
165 return (NULL); /* fmev_errno set */
167 if (ev == NULL) {
168 (void) fmev_seterr(FMEVERR_API);
169 return (NULL);
172 if ((cp = fmev_shdl_alloc(iep->ei_hdl, sizeof (*iep))) == NULL) {
173 (void) fmev_seterr(FMEVERR_ALLOC);
174 return (NULL);
177 if (nvlist_dup(iep->ei_nvl, &cp->ei_nvl, 0) != 0) {
178 fmev_shdl_free(iep->ei_hdl, cp, sizeof (*cp));
179 (void) fmev_seterr(FMEVERR_ALLOC);
180 return (NULL);
183 cp->ei_magic = _FMEVMAGIC;
184 cp->ei_hdl = iep->ei_hdl;
185 cp->ei_refcnt = 1;
186 return (IMPL2FMEV(cp));
189 nvlist_t *
190 fmev_attr_list(fmev_t ev)
192 fmev_impl_t *iep = FMEV2IMPL(ev);
194 ASSERT(EVENT_VALID(iep));
196 if (!FMEV_API_ENTER(iep, 1))
197 return (NULL); /* fmev_errno set */
199 if (ev == NULL) {
200 (void) fmev_seterr(FMEVERR_API);
201 return (NULL);
202 } else if (iep->ei_nvl == NULL) {
203 (void) fmev_seterr(FMEVERR_MALFORMED_EVENT);
204 return (NULL);
207 return (iep->ei_nvl);
210 const char *
211 fmev_class(fmev_t ev)
213 fmev_impl_t *iep = FMEV2IMPL(ev);
214 const char *class;
216 ASSERT(EVENT_VALID(iep));
218 if (!FMEV_API_ENTER(iep, 1))
219 return (NULL); /* fmev_errno set */
221 if (ev == NULL) {
222 (void) fmev_seterr(FMEVERR_API);
223 return ("");
226 if (nvlist_lookup_string(iep->ei_nvl, FM_CLASS, (char **)&class) != 0 ||
227 *class == '\0') {
228 (void) fmev_seterr(FMEVERR_MALFORMED_EVENT);
229 return ("");
232 return (class);
235 fmev_err_t
236 fmev_timespec(fmev_t ev, struct timespec *tp)
238 fmev_impl_t *iep = FMEV2IMPL(ev);
239 uint64_t timetlimit;
241 ASSERT(EVENT_VALID(iep));
242 if (!FMEV_API_ENTER(iep, 1))
243 return (fmev_errno);
245 #ifdef _LP64
246 timetlimit = INT64_MAX;
247 #else
248 timetlimit = INT32_MAX;
249 #endif
251 if (iep->ei_fmtime[FM_TIME_SEC] > timetlimit)
252 return (FMEVERR_OVERFLOW);
254 tp->tv_sec = (time_t)iep->ei_fmtime[FM_TIME_SEC];
255 tp->tv_nsec = (long)iep->ei_fmtime[FM_TIME_NSEC];
257 return (FMEV_SUCCESS);
260 uint64_t
261 fmev_time_sec(fmev_t ev)
263 return (FMEV2IMPL(ev)->ei_fmtime[FM_TIME_SEC]);
266 uint64_t
267 fmev_time_nsec(fmev_t ev)
269 return (FMEV2IMPL(ev)->ei_fmtime[FM_TIME_NSEC]);
272 struct tm *
273 fmev_localtime(fmev_t ev, struct tm *tm)
275 time_t seconds;
277 seconds = (time_t)fmev_time_sec(ev);
278 return (localtime_r(&seconds, tm));
281 fmev_shdl_t
282 fmev_ev2shdl(fmev_t ev)
284 fmev_impl_t *iep = FMEV2IMPL(ev);
286 if (!FMEV_API_ENTER(iep, 2))
287 return (NULL);
289 return (iep->ei_hdl);