111102SGavin.Maltby@Sun.COM /*
211102SGavin.Maltby@Sun.COM * CDDL HEADER START
311102SGavin.Maltby@Sun.COM *
411102SGavin.Maltby@Sun.COM * The contents of this file are subject to the terms of the
511102SGavin.Maltby@Sun.COM * Common Development and Distribution License (the "License").
611102SGavin.Maltby@Sun.COM * You may not use this file except in compliance with the License.
711102SGavin.Maltby@Sun.COM *
811102SGavin.Maltby@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911102SGavin.Maltby@Sun.COM * or http://www.opensolaris.org/os/licensing.
1011102SGavin.Maltby@Sun.COM * See the License for the specific language governing permissions
1111102SGavin.Maltby@Sun.COM * and limitations under the License.
1211102SGavin.Maltby@Sun.COM *
1311102SGavin.Maltby@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1411102SGavin.Maltby@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511102SGavin.Maltby@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1611102SGavin.Maltby@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1711102SGavin.Maltby@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1811102SGavin.Maltby@Sun.COM *
1911102SGavin.Maltby@Sun.COM * CDDL HEADER END
2011102SGavin.Maltby@Sun.COM */
2111102SGavin.Maltby@Sun.COM
2211102SGavin.Maltby@Sun.COM /*
23*12967Sgavin.maltby@oracle.com * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2411102SGavin.Maltby@Sun.COM */
2511102SGavin.Maltby@Sun.COM
2611102SGavin.Maltby@Sun.COM /*
2711102SGavin.Maltby@Sun.COM * FMA event subscription interfaces - subscribe to FMA protocol
2811102SGavin.Maltby@Sun.COM * from outside the fault manager.
2911102SGavin.Maltby@Sun.COM */
3011102SGavin.Maltby@Sun.COM
3111102SGavin.Maltby@Sun.COM #include <sys/types.h>
3211102SGavin.Maltby@Sun.COM #include <atomic.h>
3311102SGavin.Maltby@Sun.COM #include <libsysevent.h>
3411102SGavin.Maltby@Sun.COM #include <libuutil.h>
3511102SGavin.Maltby@Sun.COM #include <pthread.h>
3611102SGavin.Maltby@Sun.COM #include <stdarg.h>
3711102SGavin.Maltby@Sun.COM #include <stdlib.h>
3811102SGavin.Maltby@Sun.COM #include <string.h>
3911102SGavin.Maltby@Sun.COM #include <strings.h>
4011102SGavin.Maltby@Sun.COM #include <unistd.h>
41*12967Sgavin.maltby@oracle.com #include <fm/libtopo.h>
4211102SGavin.Maltby@Sun.COM
4311102SGavin.Maltby@Sun.COM #include <fm/libfmevent.h>
4411102SGavin.Maltby@Sun.COM
4511102SGavin.Maltby@Sun.COM #include "fmev_impl.h"
46*12967Sgavin.maltby@oracle.com
47*12967Sgavin.maltby@oracle.com static topo_hdl_t *g_topohdl;
4811102SGavin.Maltby@Sun.COM
4911102SGavin.Maltby@Sun.COM typedef struct {
5011102SGavin.Maltby@Sun.COM struct fmev_hdl_cmn sh_cmn;
5111102SGavin.Maltby@Sun.COM evchan_t *sh_binding;
5211102SGavin.Maltby@Sun.COM uu_avl_pool_t *sh_pool;
5311102SGavin.Maltby@Sun.COM uu_avl_t *sh_avl;
5411102SGavin.Maltby@Sun.COM uint32_t sh_subcnt;
5511102SGavin.Maltby@Sun.COM uint32_t sh_flags;
5611102SGavin.Maltby@Sun.COM sysevent_subattr_t *sh_attr;
5711102SGavin.Maltby@Sun.COM pthread_mutex_t sh_lock;
5811102SGavin.Maltby@Sun.COM pthread_mutex_t sh_srlz_lock;
5911102SGavin.Maltby@Sun.COM } fmev_shdl_impl_t;
6011102SGavin.Maltby@Sun.COM
6111102SGavin.Maltby@Sun.COM #define HDL2IHDL(hdl) ((fmev_shdl_impl_t *)(hdl))
6211102SGavin.Maltby@Sun.COM #define IHDL2HDL(ihdl) ((fmev_shdl_t)(ihdl))
6311102SGavin.Maltby@Sun.COM
6411102SGavin.Maltby@Sun.COM #define _FMEV_SHMAGIC 0x5368446c /* ShDl */
6511102SGavin.Maltby@Sun.COM #define FMEV_SHDL_VALID(ihdl) ((ihdl)->sh_cmn.hc_magic == _FMEV_SHMAGIC)
6611102SGavin.Maltby@Sun.COM
6711102SGavin.Maltby@Sun.COM #define SHDL_FL_SERIALIZE 0x1
6811102SGavin.Maltby@Sun.COM
69*12967Sgavin.maltby@oracle.com #define FMEV_API_ENTER(hdl, v) \
70*12967Sgavin.maltby@oracle.com fmev_api_enter(&HDL2IHDL(hdl)->sh_cmn, LIBFMEVENT_VERSION_##v)
7111102SGavin.Maltby@Sun.COM
7211102SGavin.Maltby@Sun.COM /*
7311102SGavin.Maltby@Sun.COM * For each subscription on a handle we add a node to an avl tree
7411102SGavin.Maltby@Sun.COM * to track subscriptions.
7511102SGavin.Maltby@Sun.COM */
7611102SGavin.Maltby@Sun.COM
7711102SGavin.Maltby@Sun.COM #define FMEV_SID_SZ (16 + 1) /* Matches MAX_SUBID_LEN */
7811102SGavin.Maltby@Sun.COM
7911102SGavin.Maltby@Sun.COM struct fmev_subinfo {
8011102SGavin.Maltby@Sun.COM uu_avl_node_t si_node;
8111102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *si_ihdl;
8211102SGavin.Maltby@Sun.COM char si_pat[FMEV_MAX_CLASS];
8311102SGavin.Maltby@Sun.COM char si_sid[FMEV_SID_SZ];
8411102SGavin.Maltby@Sun.COM fmev_cbfunc_t *si_cb;
8511102SGavin.Maltby@Sun.COM void *si_cbarg;
8611102SGavin.Maltby@Sun.COM };
8711102SGavin.Maltby@Sun.COM
8811102SGavin.Maltby@Sun.COM struct fmev_hdl_cmn *
fmev_shdl_cmn(fmev_shdl_t hdl)8911102SGavin.Maltby@Sun.COM fmev_shdl_cmn(fmev_shdl_t hdl)
9011102SGavin.Maltby@Sun.COM {
9111102SGavin.Maltby@Sun.COM return (&HDL2IHDL(hdl)->sh_cmn);
9211102SGavin.Maltby@Sun.COM }
9311102SGavin.Maltby@Sun.COM
9411102SGavin.Maltby@Sun.COM static int
shdlctl_start(fmev_shdl_impl_t * ihdl)9511102SGavin.Maltby@Sun.COM shdlctl_start(fmev_shdl_impl_t *ihdl)
9611102SGavin.Maltby@Sun.COM {
9711102SGavin.Maltby@Sun.COM (void) pthread_mutex_lock(&ihdl->sh_lock);
9811102SGavin.Maltby@Sun.COM
9911102SGavin.Maltby@Sun.COM if (ihdl->sh_subcnt == 0) {
10011102SGavin.Maltby@Sun.COM return (1); /* lock still held */
10111102SGavin.Maltby@Sun.COM } else {
10211102SGavin.Maltby@Sun.COM (void) pthread_mutex_unlock(&ihdl->sh_lock);
10311102SGavin.Maltby@Sun.COM return (0);
10411102SGavin.Maltby@Sun.COM }
10511102SGavin.Maltby@Sun.COM }
10611102SGavin.Maltby@Sun.COM
10711102SGavin.Maltby@Sun.COM static void
shdlctl_end(fmev_shdl_impl_t * ihdl)10811102SGavin.Maltby@Sun.COM shdlctl_end(fmev_shdl_impl_t *ihdl)
10911102SGavin.Maltby@Sun.COM {
11011102SGavin.Maltby@Sun.COM (void) pthread_mutex_unlock(&ihdl->sh_lock);
11111102SGavin.Maltby@Sun.COM }
11211102SGavin.Maltby@Sun.COM
11311102SGavin.Maltby@Sun.COM fmev_err_t
fmev_shdlctl_serialize(fmev_shdl_t hdl)11411102SGavin.Maltby@Sun.COM fmev_shdlctl_serialize(fmev_shdl_t hdl)
11511102SGavin.Maltby@Sun.COM {
11611102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
11711102SGavin.Maltby@Sun.COM
118*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
11911102SGavin.Maltby@Sun.COM return (fmev_errno);
12011102SGavin.Maltby@Sun.COM
12111102SGavin.Maltby@Sun.COM if (!shdlctl_start(ihdl))
12211102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_BUSY));
12311102SGavin.Maltby@Sun.COM
12411102SGavin.Maltby@Sun.COM if (!(ihdl->sh_flags & SHDL_FL_SERIALIZE)) {
12511102SGavin.Maltby@Sun.COM (void) pthread_mutex_init(&ihdl->sh_srlz_lock, NULL);
12611102SGavin.Maltby@Sun.COM ihdl->sh_flags |= SHDL_FL_SERIALIZE;
12711102SGavin.Maltby@Sun.COM }
12811102SGavin.Maltby@Sun.COM
12911102SGavin.Maltby@Sun.COM shdlctl_end(ihdl);
13011102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEV_SUCCESS));
13111102SGavin.Maltby@Sun.COM }
13211102SGavin.Maltby@Sun.COM
13311102SGavin.Maltby@Sun.COM fmev_err_t
fmev_shdlctl_thrattr(fmev_shdl_t hdl,pthread_attr_t * attr)13411102SGavin.Maltby@Sun.COM fmev_shdlctl_thrattr(fmev_shdl_t hdl, pthread_attr_t *attr)
13511102SGavin.Maltby@Sun.COM {
13611102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
13711102SGavin.Maltby@Sun.COM
138*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
13911102SGavin.Maltby@Sun.COM return (fmev_errno);
14011102SGavin.Maltby@Sun.COM
14111102SGavin.Maltby@Sun.COM if (!shdlctl_start(ihdl))
14211102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_BUSY));
14311102SGavin.Maltby@Sun.COM
14411102SGavin.Maltby@Sun.COM sysevent_subattr_thrattr(ihdl->sh_attr, attr);
14511102SGavin.Maltby@Sun.COM
14611102SGavin.Maltby@Sun.COM shdlctl_end(ihdl);
14711102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEV_SUCCESS));
14811102SGavin.Maltby@Sun.COM }
14911102SGavin.Maltby@Sun.COM
15011102SGavin.Maltby@Sun.COM fmev_err_t
fmev_shdlctl_sigmask(fmev_shdl_t hdl,sigset_t * set)15111102SGavin.Maltby@Sun.COM fmev_shdlctl_sigmask(fmev_shdl_t hdl, sigset_t *set)
15211102SGavin.Maltby@Sun.COM {
15311102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
15411102SGavin.Maltby@Sun.COM
155*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
15611102SGavin.Maltby@Sun.COM return (fmev_errno);
15711102SGavin.Maltby@Sun.COM
15811102SGavin.Maltby@Sun.COM if (!shdlctl_start(ihdl))
15911102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_BUSY));
16011102SGavin.Maltby@Sun.COM
16111102SGavin.Maltby@Sun.COM sysevent_subattr_sigmask(ihdl->sh_attr, set);
16211102SGavin.Maltby@Sun.COM
16311102SGavin.Maltby@Sun.COM shdlctl_end(ihdl);
16411102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEV_SUCCESS));
16511102SGavin.Maltby@Sun.COM }
16611102SGavin.Maltby@Sun.COM
16711102SGavin.Maltby@Sun.COM fmev_err_t
fmev_shdlctl_thrsetup(fmev_shdl_t hdl,door_xcreate_thrsetup_func_t * func,void * cookie)16811102SGavin.Maltby@Sun.COM fmev_shdlctl_thrsetup(fmev_shdl_t hdl, door_xcreate_thrsetup_func_t *func,
16911102SGavin.Maltby@Sun.COM void *cookie)
17011102SGavin.Maltby@Sun.COM {
17111102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
17211102SGavin.Maltby@Sun.COM
173*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
17411102SGavin.Maltby@Sun.COM return (fmev_errno);
17511102SGavin.Maltby@Sun.COM
17611102SGavin.Maltby@Sun.COM if (!shdlctl_start(ihdl))
17711102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_BUSY));
17811102SGavin.Maltby@Sun.COM
17911102SGavin.Maltby@Sun.COM sysevent_subattr_thrsetup(ihdl->sh_attr, func, cookie);
18011102SGavin.Maltby@Sun.COM
18111102SGavin.Maltby@Sun.COM shdlctl_end(ihdl);
18211102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEV_SUCCESS));
18311102SGavin.Maltby@Sun.COM }
18411102SGavin.Maltby@Sun.COM
18511102SGavin.Maltby@Sun.COM fmev_err_t
fmev_shdlctl_thrcreate(fmev_shdl_t hdl,door_xcreate_server_func_t * func,void * cookie)18611102SGavin.Maltby@Sun.COM fmev_shdlctl_thrcreate(fmev_shdl_t hdl, door_xcreate_server_func_t *func,
18711102SGavin.Maltby@Sun.COM void *cookie)
18811102SGavin.Maltby@Sun.COM {
18911102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
19011102SGavin.Maltby@Sun.COM
191*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
19211102SGavin.Maltby@Sun.COM return (fmev_errno);
19311102SGavin.Maltby@Sun.COM
19411102SGavin.Maltby@Sun.COM if (!shdlctl_start(ihdl))
19511102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_BUSY));
19611102SGavin.Maltby@Sun.COM
19711102SGavin.Maltby@Sun.COM sysevent_subattr_thrcreate(ihdl->sh_attr, func, cookie);
19811102SGavin.Maltby@Sun.COM
19911102SGavin.Maltby@Sun.COM shdlctl_end(ihdl);
20011102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEV_SUCCESS));
20111102SGavin.Maltby@Sun.COM }
20211102SGavin.Maltby@Sun.COM
20311102SGavin.Maltby@Sun.COM /*
20411102SGavin.Maltby@Sun.COM * Our door service function. We return 0 regardless so that the kernel
20511102SGavin.Maltby@Sun.COM * does not keep either retrying (EAGAIN) or bleat to cmn_err.
20611102SGavin.Maltby@Sun.COM */
20711102SGavin.Maltby@Sun.COM
20811102SGavin.Maltby@Sun.COM uint64_t fmev_proxy_cb_inval;
20911102SGavin.Maltby@Sun.COM uint64_t fmev_proxy_cb_enomem;
21011102SGavin.Maltby@Sun.COM
21111102SGavin.Maltby@Sun.COM int
fmev_proxy_cb(sysevent_t * sep,void * arg)21211102SGavin.Maltby@Sun.COM fmev_proxy_cb(sysevent_t *sep, void *arg)
21311102SGavin.Maltby@Sun.COM {
21411102SGavin.Maltby@Sun.COM struct fmev_subinfo *sip = arg;
21511102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = sip->si_ihdl;
21611102SGavin.Maltby@Sun.COM nvlist_t *nvl;
21711102SGavin.Maltby@Sun.COM char *class;
21811102SGavin.Maltby@Sun.COM fmev_t ev;
21911102SGavin.Maltby@Sun.COM
22011102SGavin.Maltby@Sun.COM if (sip == NULL || sip->si_cb == NULL) {
22111102SGavin.Maltby@Sun.COM fmev_proxy_cb_inval++;
22211102SGavin.Maltby@Sun.COM return (0);
22311102SGavin.Maltby@Sun.COM }
22411102SGavin.Maltby@Sun.COM
22511102SGavin.Maltby@Sun.COM if ((ev = fmev_sysev2fmev(IHDL2HDL(ihdl), sep, &class, &nvl)) == NULL) {
22611102SGavin.Maltby@Sun.COM fmev_proxy_cb_enomem++;
22711102SGavin.Maltby@Sun.COM return (0);
22811102SGavin.Maltby@Sun.COM }
22911102SGavin.Maltby@Sun.COM
23011102SGavin.Maltby@Sun.COM if (ihdl->sh_flags & SHDL_FL_SERIALIZE)
23111102SGavin.Maltby@Sun.COM (void) pthread_mutex_lock(&ihdl->sh_srlz_lock);
23211102SGavin.Maltby@Sun.COM
23311102SGavin.Maltby@Sun.COM sip->si_cb(ev, class, nvl, sip->si_cbarg);
23411102SGavin.Maltby@Sun.COM
23511102SGavin.Maltby@Sun.COM if (ihdl->sh_flags & SHDL_FL_SERIALIZE)
23611102SGavin.Maltby@Sun.COM (void) pthread_mutex_unlock(&ihdl->sh_srlz_lock);
23711102SGavin.Maltby@Sun.COM
23811102SGavin.Maltby@Sun.COM fmev_rele(ev); /* release hold obtained in fmev_sysev2fmev */
23911102SGavin.Maltby@Sun.COM
24011102SGavin.Maltby@Sun.COM return (0);
24111102SGavin.Maltby@Sun.COM }
24211102SGavin.Maltby@Sun.COM
24311102SGavin.Maltby@Sun.COM static volatile uint32_t fmev_subid;
24411102SGavin.Maltby@Sun.COM
24511102SGavin.Maltby@Sun.COM fmev_err_t
fmev_shdl_subscribe(fmev_shdl_t hdl,const char * pat,fmev_cbfunc_t func,void * funcarg)24611102SGavin.Maltby@Sun.COM fmev_shdl_subscribe(fmev_shdl_t hdl, const char *pat, fmev_cbfunc_t func,
24711102SGavin.Maltby@Sun.COM void *funcarg)
24811102SGavin.Maltby@Sun.COM {
24911102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
25011102SGavin.Maltby@Sun.COM struct fmev_subinfo *sip;
25111102SGavin.Maltby@Sun.COM uu_avl_index_t idx;
25211102SGavin.Maltby@Sun.COM uint64_t nsid;
25311102SGavin.Maltby@Sun.COM int serr;
25411102SGavin.Maltby@Sun.COM
255*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
25611102SGavin.Maltby@Sun.COM return (fmev_errno);
25711102SGavin.Maltby@Sun.COM
25811102SGavin.Maltby@Sun.COM if (pat == NULL || func == NULL)
25911102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_API));
26011102SGavin.Maltby@Sun.COM
26111102SGavin.Maltby@Sun.COM /*
26211102SGavin.Maltby@Sun.COM * Empty class patterns are illegal, as is the sysevent magic for
26311102SGavin.Maltby@Sun.COM * all classes. Also validate class length.
26411102SGavin.Maltby@Sun.COM */
26511102SGavin.Maltby@Sun.COM if (*pat == '\0' || strncmp(pat, EC_ALL, sizeof (EC_ALL)) == 0 ||
26611102SGavin.Maltby@Sun.COM strncmp(pat, EC_SUB_ALL, sizeof (EC_SUB_ALL)) == 0 ||
26711102SGavin.Maltby@Sun.COM strnlen(pat, FMEV_MAX_CLASS) == FMEV_MAX_CLASS)
26811102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_BADCLASS));
26911102SGavin.Maltby@Sun.COM
27011102SGavin.Maltby@Sun.COM if ((sip = fmev_shdl_zalloc(hdl, sizeof (*sip))) == NULL)
27111102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_ALLOC));
27211102SGavin.Maltby@Sun.COM
27311102SGavin.Maltby@Sun.COM (void) strncpy(sip->si_pat, pat, sizeof (sip->si_pat));
27411102SGavin.Maltby@Sun.COM
27511102SGavin.Maltby@Sun.COM uu_avl_node_init(sip, &sip->si_node, ihdl->sh_pool);
27611102SGavin.Maltby@Sun.COM
27711102SGavin.Maltby@Sun.COM (void) pthread_mutex_lock(&ihdl->sh_lock);
27811102SGavin.Maltby@Sun.COM
27911102SGavin.Maltby@Sun.COM if (uu_avl_find(ihdl->sh_avl, sip, NULL, &idx) != NULL) {
28011102SGavin.Maltby@Sun.COM (void) pthread_mutex_unlock(&ihdl->sh_lock);
28111102SGavin.Maltby@Sun.COM fmev_shdl_free(hdl, sip, sizeof (*sip));
28211102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_DUPLICATE));
28311102SGavin.Maltby@Sun.COM }
28411102SGavin.Maltby@Sun.COM
28511102SGavin.Maltby@Sun.COM /*
28611102SGavin.Maltby@Sun.COM * Generate a subscriber id for GPEC that is unique to this
28711102SGavin.Maltby@Sun.COM * subscription. There is no provision for persistent
28811102SGavin.Maltby@Sun.COM * subscribers. The subscriber id must be unique within
28911102SGavin.Maltby@Sun.COM * this zone.
29011102SGavin.Maltby@Sun.COM */
29111102SGavin.Maltby@Sun.COM nsid = (uint64_t)getpid() << 32 | atomic_inc_32_nv(&fmev_subid);
29211102SGavin.Maltby@Sun.COM (void) snprintf(sip->si_sid, sizeof (sip->si_sid), "%llx", nsid);
29311102SGavin.Maltby@Sun.COM
29411102SGavin.Maltby@Sun.COM sip->si_ihdl = ihdl;
29511102SGavin.Maltby@Sun.COM sip->si_cb = func;
29611102SGavin.Maltby@Sun.COM sip->si_cbarg = funcarg;
29711102SGavin.Maltby@Sun.COM
29811102SGavin.Maltby@Sun.COM if ((serr = sysevent_evc_xsubscribe(ihdl->sh_binding, sip->si_sid,
29911102SGavin.Maltby@Sun.COM sip->si_pat, fmev_proxy_cb, sip, 0, ihdl->sh_attr)) != 0) {
30011102SGavin.Maltby@Sun.COM fmev_err_t err;
30111102SGavin.Maltby@Sun.COM
30211102SGavin.Maltby@Sun.COM (void) pthread_mutex_unlock(&ihdl->sh_lock);
30311102SGavin.Maltby@Sun.COM fmev_shdl_free(hdl, sip, sizeof (*sip));
30411102SGavin.Maltby@Sun.COM
30511102SGavin.Maltby@Sun.COM switch (serr) {
30611102SGavin.Maltby@Sun.COM case ENOMEM:
30711102SGavin.Maltby@Sun.COM err = FMEVERR_MAX_SUBSCRIBERS;
30811102SGavin.Maltby@Sun.COM break;
30911102SGavin.Maltby@Sun.COM
31011102SGavin.Maltby@Sun.COM default:
31111102SGavin.Maltby@Sun.COM err = FMEVERR_INTERNAL;
31211102SGavin.Maltby@Sun.COM break;
31311102SGavin.Maltby@Sun.COM }
31411102SGavin.Maltby@Sun.COM
31511102SGavin.Maltby@Sun.COM return (fmev_seterr(err));
31611102SGavin.Maltby@Sun.COM }
31711102SGavin.Maltby@Sun.COM
31811102SGavin.Maltby@Sun.COM uu_avl_insert(ihdl->sh_avl, sip, idx);
31911102SGavin.Maltby@Sun.COM ihdl->sh_subcnt++;
32011102SGavin.Maltby@Sun.COM
32111102SGavin.Maltby@Sun.COM (void) pthread_mutex_unlock(&ihdl->sh_lock);
32211102SGavin.Maltby@Sun.COM
32311102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEV_SUCCESS));
32411102SGavin.Maltby@Sun.COM }
32511102SGavin.Maltby@Sun.COM
32611102SGavin.Maltby@Sun.COM static int
fmev_subinfo_fini(fmev_shdl_impl_t * ihdl,struct fmev_subinfo * sip,boolean_t doavl)32711102SGavin.Maltby@Sun.COM fmev_subinfo_fini(fmev_shdl_impl_t *ihdl, struct fmev_subinfo *sip,
32811102SGavin.Maltby@Sun.COM boolean_t doavl)
32911102SGavin.Maltby@Sun.COM {
33011102SGavin.Maltby@Sun.COM int err;
33111102SGavin.Maltby@Sun.COM
33211102SGavin.Maltby@Sun.COM ASSERT(sip->si_ihdl == ihdl);
33311102SGavin.Maltby@Sun.COM
33411102SGavin.Maltby@Sun.COM err = sysevent_evc_unsubscribe(ihdl->sh_binding, sip->si_sid);
33511102SGavin.Maltby@Sun.COM
33611102SGavin.Maltby@Sun.COM if (err == 0) {
33711102SGavin.Maltby@Sun.COM if (doavl) {
33811102SGavin.Maltby@Sun.COM uu_avl_remove(ihdl->sh_avl, sip);
33911102SGavin.Maltby@Sun.COM uu_avl_node_fini(sip, &sip->si_node, ihdl->sh_pool);
34011102SGavin.Maltby@Sun.COM }
34111102SGavin.Maltby@Sun.COM fmev_shdl_free(IHDL2HDL(ihdl), sip, sizeof (*sip));
34211102SGavin.Maltby@Sun.COM ihdl->sh_subcnt--;
34311102SGavin.Maltby@Sun.COM }
34411102SGavin.Maltby@Sun.COM
34511102SGavin.Maltby@Sun.COM return (err);
34611102SGavin.Maltby@Sun.COM }
34711102SGavin.Maltby@Sun.COM
34811102SGavin.Maltby@Sun.COM fmev_err_t
fmev_shdl_unsubscribe(fmev_shdl_t hdl,const char * pat)34911102SGavin.Maltby@Sun.COM fmev_shdl_unsubscribe(fmev_shdl_t hdl, const char *pat)
35011102SGavin.Maltby@Sun.COM {
35111102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
35211102SGavin.Maltby@Sun.COM fmev_err_t rv = FMEVERR_NOMATCH;
35311102SGavin.Maltby@Sun.COM struct fmev_subinfo *sip;
35411102SGavin.Maltby@Sun.COM struct fmev_subinfo si;
35511102SGavin.Maltby@Sun.COM int err;
35611102SGavin.Maltby@Sun.COM
357*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
35811102SGavin.Maltby@Sun.COM return (fmev_errno);
35911102SGavin.Maltby@Sun.COM
36011102SGavin.Maltby@Sun.COM if (pat == NULL)
36111102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_API));
36211102SGavin.Maltby@Sun.COM
36311102SGavin.Maltby@Sun.COM if (*pat == '\0' || strncmp(pat, EVCH_ALLSUB, sizeof (EC_ALL)) == 0 ||
36411102SGavin.Maltby@Sun.COM strnlen(pat, FMEV_MAX_CLASS) == FMEV_MAX_CLASS)
36511102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_BADCLASS));
36611102SGavin.Maltby@Sun.COM
36711102SGavin.Maltby@Sun.COM (void) strncpy(si.si_pat, pat, sizeof (si.si_pat));
36811102SGavin.Maltby@Sun.COM
36911102SGavin.Maltby@Sun.COM (void) pthread_mutex_lock(&ihdl->sh_lock);
37011102SGavin.Maltby@Sun.COM
37111102SGavin.Maltby@Sun.COM if ((sip = uu_avl_find(ihdl->sh_avl, &si, NULL, NULL)) != NULL) {
37211102SGavin.Maltby@Sun.COM if ((err = fmev_subinfo_fini(ihdl, sip, B_TRUE)) == 0) {
37311102SGavin.Maltby@Sun.COM rv = FMEV_SUCCESS;
37411102SGavin.Maltby@Sun.COM } else {
37511102SGavin.Maltby@Sun.COM /*
37611102SGavin.Maltby@Sun.COM * Return an API error if the unsubscribe was
37711102SGavin.Maltby@Sun.COM * attempted from within a door callback invocation;
37811102SGavin.Maltby@Sun.COM * other errors should not happen.
37911102SGavin.Maltby@Sun.COM */
38011102SGavin.Maltby@Sun.COM rv = (err == EDEADLK) ? FMEVERR_API : FMEVERR_INTERNAL;
38111102SGavin.Maltby@Sun.COM }
38211102SGavin.Maltby@Sun.COM }
38311102SGavin.Maltby@Sun.COM
38411102SGavin.Maltby@Sun.COM (void) pthread_mutex_unlock(&ihdl->sh_lock);
38511102SGavin.Maltby@Sun.COM
38611102SGavin.Maltby@Sun.COM return (fmev_seterr(rv));
38711102SGavin.Maltby@Sun.COM }
38811102SGavin.Maltby@Sun.COM
38911102SGavin.Maltby@Sun.COM void *
fmev_shdl_alloc(fmev_shdl_t hdl,size_t sz)39011102SGavin.Maltby@Sun.COM fmev_shdl_alloc(fmev_shdl_t hdl, size_t sz)
39111102SGavin.Maltby@Sun.COM {
39211102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
39311102SGavin.Maltby@Sun.COM
394*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
395*12967Sgavin.maltby@oracle.com return (NULL);
39611102SGavin.Maltby@Sun.COM
39711102SGavin.Maltby@Sun.COM return (ihdl->sh_cmn.hc_alloc(sz));
39811102SGavin.Maltby@Sun.COM }
39911102SGavin.Maltby@Sun.COM
40011102SGavin.Maltby@Sun.COM void *
fmev_shdl_zalloc(fmev_shdl_t hdl,size_t sz)40111102SGavin.Maltby@Sun.COM fmev_shdl_zalloc(fmev_shdl_t hdl, size_t sz)
40211102SGavin.Maltby@Sun.COM {
40311102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
40411102SGavin.Maltby@Sun.COM
405*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
406*12967Sgavin.maltby@oracle.com return (NULL);
40711102SGavin.Maltby@Sun.COM
40811102SGavin.Maltby@Sun.COM return (ihdl->sh_cmn.hc_zalloc(sz));
40911102SGavin.Maltby@Sun.COM }
41011102SGavin.Maltby@Sun.COM
41111102SGavin.Maltby@Sun.COM void
fmev_shdl_free(fmev_shdl_t hdl,void * buf,size_t sz)41211102SGavin.Maltby@Sun.COM fmev_shdl_free(fmev_shdl_t hdl, void *buf, size_t sz)
41311102SGavin.Maltby@Sun.COM {
41411102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
41511102SGavin.Maltby@Sun.COM
416*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
417*12967Sgavin.maltby@oracle.com return;
41811102SGavin.Maltby@Sun.COM
41911102SGavin.Maltby@Sun.COM ihdl->sh_cmn.hc_free(buf, sz);
42011102SGavin.Maltby@Sun.COM }
42111102SGavin.Maltby@Sun.COM
422*12967Sgavin.maltby@oracle.com char *
fmev_shdl_strdup(fmev_shdl_t hdl,char * src)423*12967Sgavin.maltby@oracle.com fmev_shdl_strdup(fmev_shdl_t hdl, char *src)
424*12967Sgavin.maltby@oracle.com {
425*12967Sgavin.maltby@oracle.com fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
426*12967Sgavin.maltby@oracle.com size_t srclen;
427*12967Sgavin.maltby@oracle.com char *dst;
428*12967Sgavin.maltby@oracle.com
429*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 2))
430*12967Sgavin.maltby@oracle.com return (NULL);
431*12967Sgavin.maltby@oracle.com
432*12967Sgavin.maltby@oracle.com srclen = strlen(src);
433*12967Sgavin.maltby@oracle.com
434*12967Sgavin.maltby@oracle.com if ((dst = ihdl->sh_cmn.hc_alloc(srclen + 1)) == NULL) {
435*12967Sgavin.maltby@oracle.com (void) fmev_seterr(FMEVERR_ALLOC);
436*12967Sgavin.maltby@oracle.com return (NULL);
437*12967Sgavin.maltby@oracle.com }
438*12967Sgavin.maltby@oracle.com
439*12967Sgavin.maltby@oracle.com (void) strncpy(dst, src, srclen);
440*12967Sgavin.maltby@oracle.com dst[srclen] = '\0';
441*12967Sgavin.maltby@oracle.com return (dst);
442*12967Sgavin.maltby@oracle.com }
443*12967Sgavin.maltby@oracle.com
444*12967Sgavin.maltby@oracle.com void
fmev_shdl_strfree(fmev_shdl_t hdl,char * buf)445*12967Sgavin.maltby@oracle.com fmev_shdl_strfree(fmev_shdl_t hdl, char *buf)
446*12967Sgavin.maltby@oracle.com {
447*12967Sgavin.maltby@oracle.com fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
448*12967Sgavin.maltby@oracle.com
449*12967Sgavin.maltby@oracle.com (void) FMEV_API_ENTER(hdl, 2);
450*12967Sgavin.maltby@oracle.com
451*12967Sgavin.maltby@oracle.com ihdl->sh_cmn.hc_free(buf, strlen(buf) + 1);
452*12967Sgavin.maltby@oracle.com }
453*12967Sgavin.maltby@oracle.com
45411102SGavin.Maltby@Sun.COM int
fmev_shdl_valid(fmev_shdl_t hdl)45511102SGavin.Maltby@Sun.COM fmev_shdl_valid(fmev_shdl_t hdl)
45611102SGavin.Maltby@Sun.COM {
45711102SGavin.Maltby@Sun.COM return (FMEV_SHDL_VALID(HDL2IHDL(hdl)));
45811102SGavin.Maltby@Sun.COM }
45911102SGavin.Maltby@Sun.COM
46011102SGavin.Maltby@Sun.COM /*ARGSUSED*/
46111102SGavin.Maltby@Sun.COM static int
fmev_keycmp(const void * l,const void * r,void * arg)46211102SGavin.Maltby@Sun.COM fmev_keycmp(const void *l, const void *r, void *arg)
46311102SGavin.Maltby@Sun.COM {
46411102SGavin.Maltby@Sun.COM struct fmev_subinfo *left = (struct fmev_subinfo *)l;
46511102SGavin.Maltby@Sun.COM struct fmev_subinfo *right = (struct fmev_subinfo *)r;
46611102SGavin.Maltby@Sun.COM
46711102SGavin.Maltby@Sun.COM return (strncmp(left->si_pat, right->si_pat, FMEV_MAX_CLASS));
46811102SGavin.Maltby@Sun.COM }
46911102SGavin.Maltby@Sun.COM
47011102SGavin.Maltby@Sun.COM fmev_shdl_t
fmev_shdl_init(uint32_t caller_version,void * (* hdlalloc)(size_t),void * (* hdlzalloc)(size_t),void (* hdlfree)(void *,size_t))47111102SGavin.Maltby@Sun.COM fmev_shdl_init(uint32_t caller_version, void *(*hdlalloc)(size_t),
47211102SGavin.Maltby@Sun.COM void *(*hdlzalloc)(size_t), void (*hdlfree)(void *, size_t))
47311102SGavin.Maltby@Sun.COM {
47411102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl;
47511102SGavin.Maltby@Sun.COM struct fmev_hdl_cmn hc;
47611102SGavin.Maltby@Sun.COM const char *chan_name;
47711102SGavin.Maltby@Sun.COM int err;
47811102SGavin.Maltby@Sun.COM
47911102SGavin.Maltby@Sun.COM hc.hc_magic = _FMEV_SHMAGIC;
48011102SGavin.Maltby@Sun.COM hc.hc_api_vers = caller_version;
48111102SGavin.Maltby@Sun.COM hc.hc_alloc = hdlalloc ? hdlalloc : dflt_alloc;
48211102SGavin.Maltby@Sun.COM hc.hc_zalloc = hdlzalloc ? hdlzalloc : dflt_zalloc;
48311102SGavin.Maltby@Sun.COM hc.hc_free = hdlfree ? hdlfree : dflt_free;
48411102SGavin.Maltby@Sun.COM
48511102SGavin.Maltby@Sun.COM if (!fmev_api_init(&hc))
48611102SGavin.Maltby@Sun.COM return (NULL); /* error type set */
48711102SGavin.Maltby@Sun.COM
48811102SGavin.Maltby@Sun.COM if (!((hdlalloc == NULL && hdlzalloc == NULL && hdlfree == NULL) ||
48911102SGavin.Maltby@Sun.COM (hdlalloc != NULL && hdlzalloc != NULL && hdlfree != NULL))) {
49011102SGavin.Maltby@Sun.COM (void) fmev_seterr(FMEVERR_API);
49111102SGavin.Maltby@Sun.COM return (NULL);
49211102SGavin.Maltby@Sun.COM }
49311102SGavin.Maltby@Sun.COM
49411102SGavin.Maltby@Sun.COM if (hdlzalloc == NULL)
49511102SGavin.Maltby@Sun.COM ihdl = dflt_zalloc(sizeof (*ihdl));
49611102SGavin.Maltby@Sun.COM else
49711102SGavin.Maltby@Sun.COM ihdl = hdlzalloc(sizeof (*ihdl));
49811102SGavin.Maltby@Sun.COM
49911102SGavin.Maltby@Sun.COM if (ihdl == NULL) {
50011102SGavin.Maltby@Sun.COM (void) fmev_seterr(FMEVERR_ALLOC);
50111102SGavin.Maltby@Sun.COM return (NULL);
50211102SGavin.Maltby@Sun.COM }
50311102SGavin.Maltby@Sun.COM
50411102SGavin.Maltby@Sun.COM ihdl->sh_cmn = hc;
50511102SGavin.Maltby@Sun.COM
50611102SGavin.Maltby@Sun.COM if ((ihdl->sh_attr = sysevent_subattr_alloc()) == NULL) {
50711102SGavin.Maltby@Sun.COM err = FMEVERR_ALLOC;
50811102SGavin.Maltby@Sun.COM goto error;
50911102SGavin.Maltby@Sun.COM }
51011102SGavin.Maltby@Sun.COM
51111102SGavin.Maltby@Sun.COM (void) pthread_mutex_init(&ihdl->sh_lock, NULL);
51211102SGavin.Maltby@Sun.COM
51311102SGavin.Maltby@Sun.COM /*
51411102SGavin.Maltby@Sun.COM * For simulation purposes we allow an environment variable
51511102SGavin.Maltby@Sun.COM * to provide a different channel name.
51611102SGavin.Maltby@Sun.COM */
51711102SGavin.Maltby@Sun.COM if ((chan_name = getenv("FMD_SNOOP_CHANNEL")) == NULL)
51811102SGavin.Maltby@Sun.COM chan_name = FMD_SNOOP_CHANNEL;
51911102SGavin.Maltby@Sun.COM
52011102SGavin.Maltby@Sun.COM /*
52111102SGavin.Maltby@Sun.COM * Try to bind to the event channel. If it's not already present,
52211102SGavin.Maltby@Sun.COM * attempt to create the channel so that we can startup before
52311102SGavin.Maltby@Sun.COM * the event producer (who will also apply choices such as
52411102SGavin.Maltby@Sun.COM * channel depth when they bind to the channel).
52511102SGavin.Maltby@Sun.COM */
52611102SGavin.Maltby@Sun.COM if (sysevent_evc_bind(chan_name, &ihdl->sh_binding,
52711102SGavin.Maltby@Sun.COM EVCH_CREAT | EVCH_HOLD_PEND_INDEF) != 0) {
52811102SGavin.Maltby@Sun.COM switch (errno) {
52911102SGavin.Maltby@Sun.COM case EINVAL:
53011102SGavin.Maltby@Sun.COM default:
53111102SGavin.Maltby@Sun.COM err = FMEVERR_INTERNAL;
53211102SGavin.Maltby@Sun.COM break;
53311102SGavin.Maltby@Sun.COM case ENOMEM:
53411102SGavin.Maltby@Sun.COM err = FMEVERR_ALLOC;
53511102SGavin.Maltby@Sun.COM break;
53611102SGavin.Maltby@Sun.COM case EPERM:
53711102SGavin.Maltby@Sun.COM err = FMEVERR_NOPRIV;
53811102SGavin.Maltby@Sun.COM break;
53911102SGavin.Maltby@Sun.COM }
54011102SGavin.Maltby@Sun.COM goto error;
54111102SGavin.Maltby@Sun.COM }
54211102SGavin.Maltby@Sun.COM
54311102SGavin.Maltby@Sun.COM if ((ihdl->sh_pool = uu_avl_pool_create("subinfo_pool",
54411102SGavin.Maltby@Sun.COM sizeof (struct fmev_subinfo),
54511102SGavin.Maltby@Sun.COM offsetof(struct fmev_subinfo, si_node), fmev_keycmp,
54611102SGavin.Maltby@Sun.COM UU_AVL_POOL_DEBUG)) == NULL) {
54711102SGavin.Maltby@Sun.COM err = FMEVERR_INTERNAL;
54811102SGavin.Maltby@Sun.COM goto error;
54911102SGavin.Maltby@Sun.COM }
55011102SGavin.Maltby@Sun.COM
55111102SGavin.Maltby@Sun.COM if ((ihdl->sh_avl = uu_avl_create(ihdl->sh_pool, NULL,
55211102SGavin.Maltby@Sun.COM UU_DEFAULT)) == NULL) {
55311102SGavin.Maltby@Sun.COM err = FMEVERR_INTERNAL;
55411102SGavin.Maltby@Sun.COM goto error;
55511102SGavin.Maltby@Sun.COM }
55611102SGavin.Maltby@Sun.COM
55711102SGavin.Maltby@Sun.COM return (IHDL2HDL(ihdl));
55811102SGavin.Maltby@Sun.COM
55911102SGavin.Maltby@Sun.COM error:
56011102SGavin.Maltby@Sun.COM (void) fmev_shdl_fini(IHDL2HDL(ihdl));
56111102SGavin.Maltby@Sun.COM (void) fmev_seterr(err);
56211102SGavin.Maltby@Sun.COM return (NULL);
56311102SGavin.Maltby@Sun.COM }
56411102SGavin.Maltby@Sun.COM
56511102SGavin.Maltby@Sun.COM fmev_err_t
fmev_shdl_getauthority(fmev_shdl_t hdl,nvlist_t ** nvlp)566*12967Sgavin.maltby@oracle.com fmev_shdl_getauthority(fmev_shdl_t hdl, nvlist_t **nvlp)
567*12967Sgavin.maltby@oracle.com {
568*12967Sgavin.maltby@oracle.com fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
569*12967Sgavin.maltby@oracle.com nvlist_t *propnvl;
570*12967Sgavin.maltby@oracle.com fmev_err_t rc;
571*12967Sgavin.maltby@oracle.com
572*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 2))
573*12967Sgavin.maltby@oracle.com return (fmev_errno);
574*12967Sgavin.maltby@oracle.com
575*12967Sgavin.maltby@oracle.com (void) pthread_mutex_lock(&ihdl->sh_lock);
576*12967Sgavin.maltby@oracle.com
577*12967Sgavin.maltby@oracle.com if (sysevent_evc_getpropnvl(ihdl->sh_binding, &propnvl) != 0) {
578*12967Sgavin.maltby@oracle.com *nvlp = NULL;
579*12967Sgavin.maltby@oracle.com (void) pthread_mutex_unlock(&ihdl->sh_lock);
580*12967Sgavin.maltby@oracle.com return (fmev_seterr(FMEVERR_UNKNOWN));
581*12967Sgavin.maltby@oracle.com }
582*12967Sgavin.maltby@oracle.com
583*12967Sgavin.maltby@oracle.com if (propnvl == NULL) {
584*12967Sgavin.maltby@oracle.com rc = FMEVERR_BUSY; /* Other end has not bound */
585*12967Sgavin.maltby@oracle.com } else {
586*12967Sgavin.maltby@oracle.com nvlist_t *auth;
587*12967Sgavin.maltby@oracle.com
588*12967Sgavin.maltby@oracle.com if (nvlist_lookup_nvlist(propnvl, "fmdauth", &auth) == 0) {
589*12967Sgavin.maltby@oracle.com rc = (nvlist_dup(auth, nvlp, 0) == 0) ? FMEV_SUCCESS :
590*12967Sgavin.maltby@oracle.com FMEVERR_ALLOC;
591*12967Sgavin.maltby@oracle.com } else {
592*12967Sgavin.maltby@oracle.com rc = FMEVERR_INTERNAL;
593*12967Sgavin.maltby@oracle.com }
594*12967Sgavin.maltby@oracle.com nvlist_free(propnvl);
595*12967Sgavin.maltby@oracle.com }
596*12967Sgavin.maltby@oracle.com
597*12967Sgavin.maltby@oracle.com (void) pthread_mutex_unlock(&ihdl->sh_lock);
598*12967Sgavin.maltby@oracle.com
599*12967Sgavin.maltby@oracle.com if (rc != FMEV_SUCCESS) {
600*12967Sgavin.maltby@oracle.com *nvlp = NULL;
601*12967Sgavin.maltby@oracle.com (void) fmev_seterr(rc);
602*12967Sgavin.maltby@oracle.com }
603*12967Sgavin.maltby@oracle.com
604*12967Sgavin.maltby@oracle.com return (rc);
605*12967Sgavin.maltby@oracle.com }
606*12967Sgavin.maltby@oracle.com
607*12967Sgavin.maltby@oracle.com char *
fmev_shdl_nvl2str(fmev_shdl_t hdl,nvlist_t * nvl)608*12967Sgavin.maltby@oracle.com fmev_shdl_nvl2str(fmev_shdl_t hdl, nvlist_t *nvl)
609*12967Sgavin.maltby@oracle.com {
610*12967Sgavin.maltby@oracle.com fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
611*12967Sgavin.maltby@oracle.com char *fmri, *fmricp;
612*12967Sgavin.maltby@oracle.com fmev_err_t err;
613*12967Sgavin.maltby@oracle.com int topoerr;
614*12967Sgavin.maltby@oracle.com
615*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 2))
616*12967Sgavin.maltby@oracle.com return (NULL);
617*12967Sgavin.maltby@oracle.com
618*12967Sgavin.maltby@oracle.com if (g_topohdl == NULL) {
619*12967Sgavin.maltby@oracle.com (void) pthread_mutex_lock(&ihdl->sh_lock);
620*12967Sgavin.maltby@oracle.com if (g_topohdl == NULL)
621*12967Sgavin.maltby@oracle.com g_topohdl = topo_open(TOPO_VERSION, NULL, &topoerr);
622*12967Sgavin.maltby@oracle.com (void) pthread_mutex_unlock(&ihdl->sh_lock);
623*12967Sgavin.maltby@oracle.com
624*12967Sgavin.maltby@oracle.com if (g_topohdl == NULL) {
625*12967Sgavin.maltby@oracle.com (void) fmev_seterr(FMEVERR_INTERNAL);
626*12967Sgavin.maltby@oracle.com return (NULL);
627*12967Sgavin.maltby@oracle.com }
628*12967Sgavin.maltby@oracle.com }
629*12967Sgavin.maltby@oracle.com
630*12967Sgavin.maltby@oracle.com if (topo_fmri_nvl2str(g_topohdl, nvl, &fmri, &topoerr) == 0) {
631*12967Sgavin.maltby@oracle.com fmricp = fmev_shdl_strdup(hdl, fmri);
632*12967Sgavin.maltby@oracle.com topo_hdl_strfree(g_topohdl, fmri);
633*12967Sgavin.maltby@oracle.com return (fmricp); /* fmev_errno set if strdup failed */
634*12967Sgavin.maltby@oracle.com }
635*12967Sgavin.maltby@oracle.com
636*12967Sgavin.maltby@oracle.com switch (topoerr) {
637*12967Sgavin.maltby@oracle.com case ETOPO_FMRI_NOMEM:
638*12967Sgavin.maltby@oracle.com err = FMEVERR_ALLOC;
639*12967Sgavin.maltby@oracle.com break;
640*12967Sgavin.maltby@oracle.com
641*12967Sgavin.maltby@oracle.com case ETOPO_FMRI_MALFORM:
642*12967Sgavin.maltby@oracle.com case ETOPO_METHOD_NOTSUP:
643*12967Sgavin.maltby@oracle.com case ETOPO_METHOD_INVAL:
644*12967Sgavin.maltby@oracle.com default:
645*12967Sgavin.maltby@oracle.com err = FMEVERR_INVALIDARG;
646*12967Sgavin.maltby@oracle.com break;
647*12967Sgavin.maltby@oracle.com }
648*12967Sgavin.maltby@oracle.com
649*12967Sgavin.maltby@oracle.com (void) fmev_seterr(err);
650*12967Sgavin.maltby@oracle.com return (NULL);
651*12967Sgavin.maltby@oracle.com }
652*12967Sgavin.maltby@oracle.com
653*12967Sgavin.maltby@oracle.com fmev_err_t
fmev_shdl_fini(fmev_shdl_t hdl)65411102SGavin.Maltby@Sun.COM fmev_shdl_fini(fmev_shdl_t hdl)
65511102SGavin.Maltby@Sun.COM {
65611102SGavin.Maltby@Sun.COM fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
65711102SGavin.Maltby@Sun.COM
658*12967Sgavin.maltby@oracle.com if (!FMEV_API_ENTER(hdl, 1))
659*12967Sgavin.maltby@oracle.com return (fmev_errno);
66011102SGavin.Maltby@Sun.COM
66111102SGavin.Maltby@Sun.COM (void) pthread_mutex_lock(&ihdl->sh_lock);
66211102SGavin.Maltby@Sun.COM
66311102SGavin.Maltby@Sun.COM /*
66411102SGavin.Maltby@Sun.COM * Verify that we are not in callback context - return an API
66511102SGavin.Maltby@Sun.COM * error if we are.
66611102SGavin.Maltby@Sun.COM */
66711102SGavin.Maltby@Sun.COM if (sysevent_evc_unsubscribe(ihdl->sh_binding, "invalidsid") ==
66811102SGavin.Maltby@Sun.COM EDEADLK) {
66911102SGavin.Maltby@Sun.COM (void) pthread_mutex_unlock(&ihdl->sh_lock);
67011102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEVERR_API));
67111102SGavin.Maltby@Sun.COM }
67211102SGavin.Maltby@Sun.COM
67311102SGavin.Maltby@Sun.COM if (ihdl->sh_avl) {
67411102SGavin.Maltby@Sun.COM void *cookie = NULL;
67511102SGavin.Maltby@Sun.COM struct fmev_subinfo *sip;
67611102SGavin.Maltby@Sun.COM
67711102SGavin.Maltby@Sun.COM while ((sip = uu_avl_teardown(ihdl->sh_avl, &cookie)) != NULL)
67811102SGavin.Maltby@Sun.COM (void) fmev_subinfo_fini(ihdl, sip, B_FALSE);
67911102SGavin.Maltby@Sun.COM
68011102SGavin.Maltby@Sun.COM uu_avl_destroy(ihdl->sh_avl);
68111102SGavin.Maltby@Sun.COM ihdl->sh_avl = NULL;
68211102SGavin.Maltby@Sun.COM }
68311102SGavin.Maltby@Sun.COM
68411102SGavin.Maltby@Sun.COM ASSERT(ihdl->sh_subcnt == 0);
68511102SGavin.Maltby@Sun.COM
68611102SGavin.Maltby@Sun.COM if (ihdl->sh_binding) {
68711102SGavin.Maltby@Sun.COM (void) sysevent_evc_unbind(ihdl->sh_binding);
68811102SGavin.Maltby@Sun.COM ihdl->sh_binding = NULL;
68911102SGavin.Maltby@Sun.COM }
69011102SGavin.Maltby@Sun.COM
69111102SGavin.Maltby@Sun.COM if (ihdl->sh_pool) {
69211102SGavin.Maltby@Sun.COM uu_avl_pool_destroy(ihdl->sh_pool);
69311102SGavin.Maltby@Sun.COM ihdl->sh_pool = NULL;
69411102SGavin.Maltby@Sun.COM }
69511102SGavin.Maltby@Sun.COM
69611102SGavin.Maltby@Sun.COM if (ihdl->sh_attr) {
69711102SGavin.Maltby@Sun.COM sysevent_subattr_free(ihdl->sh_attr);
69811102SGavin.Maltby@Sun.COM ihdl->sh_attr = NULL;
69911102SGavin.Maltby@Sun.COM }
70011102SGavin.Maltby@Sun.COM
70111102SGavin.Maltby@Sun.COM ihdl->sh_cmn.hc_magic = 0;
70211102SGavin.Maltby@Sun.COM
703*12967Sgavin.maltby@oracle.com if (g_topohdl) {
704*12967Sgavin.maltby@oracle.com topo_close(g_topohdl);
705*12967Sgavin.maltby@oracle.com g_topohdl = NULL;
706*12967Sgavin.maltby@oracle.com }
707*12967Sgavin.maltby@oracle.com
70811102SGavin.Maltby@Sun.COM (void) pthread_mutex_unlock(&ihdl->sh_lock);
70911102SGavin.Maltby@Sun.COM (void) pthread_mutex_destroy(&ihdl->sh_lock);
71011102SGavin.Maltby@Sun.COM
71111102SGavin.Maltby@Sun.COM fmev_shdl_free(hdl, hdl, sizeof (*ihdl));
71211102SGavin.Maltby@Sun.COM
71311102SGavin.Maltby@Sun.COM fmev_api_freetsd();
71411102SGavin.Maltby@Sun.COM
71511102SGavin.Maltby@Sun.COM return (fmev_seterr(FMEV_SUCCESS));
71611102SGavin.Maltby@Sun.COM }
717