49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby/*
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * CDDL HEADER START
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby *
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * The contents of this file are subject to the terms of the
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Common Development and Distribution License (the "License").
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * You may not use this file except in compliance with the License.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby *
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * or http://www.opensolaris.org/os/licensing.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * See the License for the specific language governing permissions
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * and limitations under the License.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby *
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * When distributing Covered Code, include this CDDL HEADER in each
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * If applicable, add the following below this CDDL HEADER, with the
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * fields enclosed by brackets "[]" replaced with your own identifying
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * information: Portions Copyright [yyyy] [name of copyright owner]
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby *
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * CDDL HEADER END
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby/*
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby/*
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * FMA event subscription interfaces - subscribe to FMA protocol
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * from outside the fault manager.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <sys/types.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <atomic.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <libsysevent.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <libuutil.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <pthread.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <stdarg.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <stdlib.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <string.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <strings.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <unistd.h>
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby#include <fm/libtopo.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include <fm/libfmevent.h>
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#include "fmev_impl.h"
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbystatic topo_hdl_t *g_topohdl;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbytypedef struct {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby struct fmev_hdl_cmn sh_cmn;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby evchan_t *sh_binding;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uu_avl_pool_t *sh_pool;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uu_avl_t *sh_avl;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uint32_t sh_subcnt;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uint32_t sh_flags;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sysevent_subattr_t *sh_attr;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby pthread_mutex_t sh_lock;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby pthread_mutex_t sh_srlz_lock;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby} fmev_shdl_impl_t;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#define HDL2IHDL(hdl) ((fmev_shdl_impl_t *)(hdl))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#define IHDL2HDL(ihdl) ((fmev_shdl_t)(ihdl))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#define _FMEV_SHMAGIC 0x5368446c /* ShDl */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#define FMEV_SHDL_VALID(ihdl) ((ihdl)->sh_cmn.hc_magic == _FMEV_SHMAGIC)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#define SHDL_FL_SERIALIZE 0x1
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby#define FMEV_API_ENTER(hdl, v) \
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby fmev_api_enter(&HDL2IHDL(hdl)->sh_cmn, LIBFMEVENT_VERSION_##v)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby/*
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * For each subscription on a handle we add a node to an avl tree
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * to track subscriptions.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby#define FMEV_SID_SZ (16 + 1) /* Matches MAX_SUBID_LEN */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbystruct fmev_subinfo {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uu_avl_node_t si_node;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *si_ihdl;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby char si_pat[FMEV_MAX_CLASS];
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby char si_sid[FMEV_SID_SZ];
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_cbfunc_t *si_cb;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby void *si_cbarg;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby};
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbystruct fmev_hdl_cmn *
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdl_cmn(fmev_shdl_t hdl)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (&HDL2IHDL(hdl)->sh_cmn);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbystatic int
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyshdlctl_start(fmev_shdl_impl_t *ihdl)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_lock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (ihdl->sh_subcnt == 0) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (1); /* lock still held */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby } else {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (0);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbystatic void
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyshdlctl_end(fmev_shdl_impl_t *ihdl)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_err_t
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdlctl_serialize(fmev_shdl_t hdl)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_errno);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (!shdlctl_start(ihdl))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_BUSY));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (!(ihdl->sh_flags & SHDL_FL_SERIALIZE)) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_init(&ihdl->sh_srlz_lock, NULL);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl->sh_flags |= SHDL_FL_SERIALIZE;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby shdlctl_end(ihdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEV_SUCCESS));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_err_t
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdlctl_thrattr(fmev_shdl_t hdl, pthread_attr_t *attr)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_errno);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (!shdlctl_start(ihdl))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_BUSY));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sysevent_subattr_thrattr(ihdl->sh_attr, attr);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby shdlctl_end(ihdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEV_SUCCESS));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_err_t
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdlctl_sigmask(fmev_shdl_t hdl, sigset_t *set)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_errno);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (!shdlctl_start(ihdl))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_BUSY));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sysevent_subattr_sigmask(ihdl->sh_attr, set);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby shdlctl_end(ihdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEV_SUCCESS));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_err_t
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdlctl_thrsetup(fmev_shdl_t hdl, door_xcreate_thrsetup_func_t *func,
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby void *cookie)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_errno);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (!shdlctl_start(ihdl))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_BUSY));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sysevent_subattr_thrsetup(ihdl->sh_attr, func, cookie);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby shdlctl_end(ihdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEV_SUCCESS));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_err_t
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdlctl_thrcreate(fmev_shdl_t hdl, door_xcreate_server_func_t *func,
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby void *cookie)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_errno);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (!shdlctl_start(ihdl))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_BUSY));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sysevent_subattr_thrcreate(ihdl->sh_attr, func, cookie);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby shdlctl_end(ihdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEV_SUCCESS));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby/*
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Our door service function. We return 0 regardless so that the kernel
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * does not keep either retrying (EAGAIN) or bleat to cmn_err.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyuint64_t fmev_proxy_cb_inval;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyuint64_t fmev_proxy_cb_enomem;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyint
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_proxy_cb(sysevent_t *sep, void *arg)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby struct fmev_subinfo *sip = arg;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = sip->si_ihdl;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby nvlist_t *nvl;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby char *class;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_t ev;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (sip == NULL || sip->si_cb == NULL) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_proxy_cb_inval++;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (0);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((ev = fmev_sysev2fmev(IHDL2HDL(ihdl), sep, &class, &nvl)) == NULL) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_proxy_cb_enomem++;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (0);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (ihdl->sh_flags & SHDL_FL_SERIALIZE)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_lock(&ihdl->sh_srlz_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sip->si_cb(ev, class, nvl, sip->si_cbarg);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (ihdl->sh_flags & SHDL_FL_SERIALIZE)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_srlz_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_rele(ev); /* release hold obtained in fmev_sysev2fmev */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (0);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbystatic volatile uint32_t fmev_subid;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_err_t
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdl_subscribe(fmev_shdl_t hdl, const char *pat, fmev_cbfunc_t func,
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby void *funcarg)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby struct fmev_subinfo *sip;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uu_avl_index_t idx;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uint64_t nsid;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby int serr;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_errno);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (pat == NULL || func == NULL)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_API));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby /*
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Empty class patterns are illegal, as is the sysevent magic for
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * all classes. Also validate class length.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (*pat == '\0' || strncmp(pat, EC_ALL, sizeof (EC_ALL)) == 0 ||
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby strncmp(pat, EC_SUB_ALL, sizeof (EC_SUB_ALL)) == 0 ||
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby strnlen(pat, FMEV_MAX_CLASS) == FMEV_MAX_CLASS)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_BADCLASS));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((sip = fmev_shdl_zalloc(hdl, sizeof (*sip))) == NULL)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_ALLOC));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) strncpy(sip->si_pat, pat, sizeof (sip->si_pat));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uu_avl_node_init(sip, &sip->si_node, ihdl->sh_pool);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_lock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (uu_avl_find(ihdl->sh_avl, sip, NULL, &idx) != NULL) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_free(hdl, sip, sizeof (*sip));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_DUPLICATE));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby /*
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Generate a subscriber id for GPEC that is unique to this
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * subscription. There is no provision for persistent
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * subscribers. The subscriber id must be unique within
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * this zone.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby nsid = (uint64_t)getpid() << 32 | atomic_inc_32_nv(&fmev_subid);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) snprintf(sip->si_sid, sizeof (sip->si_sid), "%llx", nsid);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sip->si_ihdl = ihdl;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sip->si_cb = func;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sip->si_cbarg = funcarg;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((serr = sysevent_evc_xsubscribe(ihdl->sh_binding, sip->si_sid,
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sip->si_pat, fmev_proxy_cb, sip, 0, ihdl->sh_attr)) != 0) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_err_t err;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_free(hdl, sip, sizeof (*sip));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby switch (serr) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby case ENOMEM:
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby err = FMEVERR_MAX_SUBSCRIBERS;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby break;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby default:
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby err = FMEVERR_INTERNAL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby break;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(err));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uu_avl_insert(ihdl->sh_avl, sip, idx);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl->sh_subcnt++;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEV_SUCCESS));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbystatic int
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_subinfo_fini(fmev_shdl_impl_t *ihdl, struct fmev_subinfo *sip,
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby boolean_t doavl)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby int err;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ASSERT(sip->si_ihdl == ihdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby err = sysevent_evc_unsubscribe(ihdl->sh_binding, sip->si_sid);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (err == 0) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (doavl) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uu_avl_remove(ihdl->sh_avl, sip);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uu_avl_node_fini(sip, &sip->si_node, ihdl->sh_pool);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_free(IHDL2HDL(ihdl), sip, sizeof (*sip));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl->sh_subcnt--;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (err);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_err_t
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdl_unsubscribe(fmev_shdl_t hdl, const char *pat)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_err_t rv = FMEVERR_NOMATCH;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby struct fmev_subinfo *sip;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby struct fmev_subinfo si;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby int err;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_errno);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (pat == NULL)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_API));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (*pat == '\0' || strncmp(pat, EVCH_ALLSUB, sizeof (EC_ALL)) == 0 ||
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby strnlen(pat, FMEV_MAX_CLASS) == FMEV_MAX_CLASS)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_BADCLASS));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) strncpy(si.si_pat, pat, sizeof (si.si_pat));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_lock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((sip = uu_avl_find(ihdl->sh_avl, &si, NULL, NULL)) != NULL) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((err = fmev_subinfo_fini(ihdl, sip, B_TRUE)) == 0) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby rv = FMEV_SUCCESS;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby } else {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby /*
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Return an API error if the unsubscribe was
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * attempted from within a door callback invocation;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * other errors should not happen.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby rv = (err == EDEADLK) ? FMEVERR_API : FMEVERR_INTERNAL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(rv));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyvoid *
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdl_alloc(fmev_shdl_t hdl, size_t sz)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (NULL);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (ihdl->sh_cmn.hc_alloc(sz));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyvoid *
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdl_zalloc(fmev_shdl_t hdl, size_t sz)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (NULL);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (ihdl->sh_cmn.hc_zalloc(sz));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyvoid
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdl_free(fmev_shdl_t hdl, void *buf, size_t sz)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl->sh_cmn.hc_free(buf, sz);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbychar *
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbyfmev_shdl_strdup(fmev_shdl_t hdl, char *src)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby size_t srclen;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char *dst;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 2))
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby srclen = strlen(src);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if ((dst = ihdl->sh_cmn.hc_alloc(srclen + 1)) == NULL) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) fmev_seterr(FMEVERR_ALLOC);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) strncpy(dst, src, srclen);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby dst[srclen] = '\0';
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (dst);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbyvoid
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbyfmev_shdl_strfree(fmev_shdl_t hdl, char *buf)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) FMEV_API_ENTER(hdl, 2);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby ihdl->sh_cmn.hc_free(buf, strlen(buf) + 1);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyint
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdl_valid(fmev_shdl_t hdl)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (FMEV_SHDL_VALID(HDL2IHDL(hdl)));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby/*ARGSUSED*/
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbystatic int
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_keycmp(const void *l, const void *r, void *arg)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby struct fmev_subinfo *left = (struct fmev_subinfo *)l;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby struct fmev_subinfo *right = (struct fmev_subinfo *)r;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (strncmp(left->si_pat, right->si_pat, FMEV_MAX_CLASS));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdl_t
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdl_init(uint32_t caller_version, void *(*hdlalloc)(size_t),
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby void *(*hdlzalloc)(size_t), void (*hdlfree)(void *, size_t))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby struct fmev_hdl_cmn hc;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby const char *chan_name;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby int err;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby hc.hc_magic = _FMEV_SHMAGIC;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby hc.hc_api_vers = caller_version;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby hc.hc_alloc = hdlalloc ? hdlalloc : dflt_alloc;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby hc.hc_zalloc = hdlzalloc ? hdlzalloc : dflt_zalloc;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby hc.hc_free = hdlfree ? hdlfree : dflt_free;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (!fmev_api_init(&hc))
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (NULL); /* error type set */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (!((hdlalloc == NULL && hdlzalloc == NULL && hdlfree == NULL) ||
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (hdlalloc != NULL && hdlzalloc != NULL && hdlfree != NULL))) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) fmev_seterr(FMEVERR_API);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (NULL);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (hdlzalloc == NULL)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl = dflt_zalloc(sizeof (*ihdl));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby else
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl = hdlzalloc(sizeof (*ihdl));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (ihdl == NULL) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) fmev_seterr(FMEVERR_ALLOC);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (NULL);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl->sh_cmn = hc;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((ihdl->sh_attr = sysevent_subattr_alloc()) == NULL) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby err = FMEVERR_ALLOC;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby goto error;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_init(&ihdl->sh_lock, NULL);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby /*
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * For simulation purposes we allow an environment variable
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * to provide a different channel name.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((chan_name = getenv("FMD_SNOOP_CHANNEL")) == NULL)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby chan_name = FMD_SNOOP_CHANNEL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby /*
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Try to bind to the event channel. If it's not already present,
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * attempt to create the channel so that we can startup before
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * the event producer (who will also apply choices such as
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * channel depth when they bind to the channel).
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (sysevent_evc_bind(chan_name, &ihdl->sh_binding,
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby EVCH_CREAT | EVCH_HOLD_PEND_INDEF) != 0) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby switch (errno) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby case EINVAL:
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby default:
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby err = FMEVERR_INTERNAL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby break;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby case ENOMEM:
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby err = FMEVERR_ALLOC;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby break;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby case EPERM:
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby err = FMEVERR_NOPRIV;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby break;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby goto error;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((ihdl->sh_pool = uu_avl_pool_create("subinfo_pool",
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sizeof (struct fmev_subinfo),
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby offsetof(struct fmev_subinfo, si_node), fmev_keycmp,
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby UU_AVL_POOL_DEBUG)) == NULL) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby err = FMEVERR_INTERNAL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby goto error;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((ihdl->sh_avl = uu_avl_create(ihdl->sh_pool, NULL,
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby UU_DEFAULT)) == NULL) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby err = FMEVERR_INTERNAL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby goto error;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (IHDL2HDL(ihdl));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyerror:
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) fmev_shdl_fini(IHDL2HDL(ihdl));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) fmev_seterr(err);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (NULL);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbyfmev_err_t
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbyfmev_shdl_getauthority(fmev_shdl_t hdl, nvlist_t **nvlp)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_t *propnvl;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby fmev_err_t rc;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 2))
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (fmev_errno);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) pthread_mutex_lock(&ihdl->sh_lock);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (sysevent_evc_getpropnvl(ihdl->sh_binding, &propnvl) != 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *nvlp = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (fmev_seterr(FMEVERR_UNKNOWN));
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (propnvl == NULL) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby rc = FMEVERR_BUSY; /* Other end has not bound */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby } else {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_t *auth;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (nvlist_lookup_nvlist(propnvl, "fmdauth", &auth) == 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby rc = (nvlist_dup(auth, nvlp, 0) == 0) ? FMEV_SUCCESS :
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby FMEVERR_ALLOC;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby } else {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby rc = FMEVERR_INTERNAL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby nvlist_free(propnvl);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (rc != FMEV_SUCCESS) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby *nvlp = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) fmev_seterr(rc);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (rc);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbychar *
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltbyfmev_shdl_nvl2str(fmev_shdl_t hdl, nvlist_t *nvl)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby{
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby char *fmri, *fmricp;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby fmev_err_t err;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby int topoerr;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 2))
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (g_topohdl == NULL) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) pthread_mutex_lock(&ihdl->sh_lock);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (g_topohdl == NULL)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby g_topohdl = topo_open(TOPO_VERSION, NULL, &topoerr);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (g_topohdl == NULL) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) fmev_seterr(FMEVERR_INTERNAL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (topo_fmri_nvl2str(g_topohdl, nvl, &fmri, &topoerr) == 0) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby fmricp = fmev_shdl_strdup(hdl, fmri);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_hdl_strfree(g_topohdl, fmri);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (fmricp); /* fmev_errno set if strdup failed */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby switch (topoerr) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby case ETOPO_FMRI_NOMEM:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err = FMEVERR_ALLOC;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby break;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby case ETOPO_FMRI_MALFORM:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby case ETOPO_METHOD_NOTSUP:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby case ETOPO_METHOD_INVAL:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby default:
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby err = FMEVERR_INVALIDARG;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby break;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby (void) fmev_seterr(err);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (NULL);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby}
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_err_t
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_shdl_fini(fmev_shdl_t hdl)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby{
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_impl_t *ihdl = HDL2IHDL(hdl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!FMEV_API_ENTER(hdl, 1))
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (fmev_errno);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_lock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby /*
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Verify that we are not in callback context - return an API
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * error if we are.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (sysevent_evc_unsubscribe(ihdl->sh_binding, "invalidsid") ==
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby EDEADLK) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEVERR_API));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (ihdl->sh_avl) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby void *cookie = NULL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby struct fmev_subinfo *sip;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby while ((sip = uu_avl_teardown(ihdl->sh_avl, &cookie)) != NULL)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) fmev_subinfo_fini(ihdl, sip, B_FALSE);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uu_avl_destroy(ihdl->sh_avl);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl->sh_avl = NULL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ASSERT(ihdl->sh_subcnt == 0);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (ihdl->sh_binding) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) sysevent_evc_unbind(ihdl->sh_binding);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl->sh_binding = NULL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (ihdl->sh_pool) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby uu_avl_pool_destroy(ihdl->sh_pool);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl->sh_pool = NULL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if (ihdl->sh_attr) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby sysevent_subattr_free(ihdl->sh_attr);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl->sh_attr = NULL;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby }
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby ihdl->sh_cmn.hc_magic = 0;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (g_topohdl) {
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby topo_close(g_topohdl);
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby g_topohdl = NULL;
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby }
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_unlock(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_mutex_destroy(&ihdl->sh_lock);
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_shdl_free(hdl, hdl, sizeof (*ihdl));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby fmev_api_freetsd();
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (fmev_seterr(FMEV_SUCCESS));
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby}