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]
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Subscription event access interfaces.
30 #include <sys/types.h>
33 #include <fm/libfmevent.h>
35 #include "fmev_impl.h"
37 static pthread_key_t fmev_tsdkey
= PTHREAD_ONCE_KEY_NP
;
38 static int key_inited
;
41 * Thread and handle specific data.
44 fmev_err_t ts_lasterr
;
48 fmev_tsd_destructor(void *data
)
50 umem_free(data
, sizeof (struct fmev_tsd
));
54 * Called only from fmev_shdl_init. Check we are opening a valid version
58 fmev_api_init(struct fmev_hdl_cmn
*hc
)
60 uint32_t v
= hc
->hc_api_vers
;
63 if (!fmev_api_enter((struct fmev_hdl_cmn
*)fmev_api_init
, 0))
67 case LIBFMEVENT_VERSION_1
:
68 case LIBFMEVENT_VERSION_2
:
74 (void) fmev_seterr(FMEVERR_VERSION_MISMATCH
);
83 * On entry to other libfmevent API members we call fmev_api_enter.
84 * Some thread-specific data is used to keep a per-thread error value.
85 * The version opened must be no greater than the latest version but can
86 * be older. The ver_intro is the api version at which the interface
87 * was added - the caller must have opened at least this version.
90 fmev_api_enter(struct fmev_hdl_cmn
*hc
, uint32_t ver_intro
)
95 /* Initialize key on first visit */
97 (void) pthread_key_create_once_np(&fmev_tsdkey
,
103 * Allocate TSD for error value for this thread. It is only
104 * freed if/when the thread exits.
106 if ((tsd
= pthread_getspecific(fmev_tsdkey
)) == NULL
) {
107 if ((tsd
= umem_alloc(sizeof (*tsd
), UMEM_DEFAULT
)) == NULL
||
108 pthread_setspecific(fmev_tsdkey
, (const void *)tsd
) != 0) {
110 umem_free(tsd
, sizeof (*tsd
));
111 return (0); /* no error set, but what can we do */
117 if (hc
== (struct fmev_hdl_cmn
*)fmev_api_init
)
118 return (1); /* special case from fmev_api_init only */
120 if (hc
== NULL
|| hc
->hc_magic
!= _FMEV_SHMAGIC
) {
121 tsd
->ts_lasterr
= FMEVERR_API
;
125 v
= hc
->hc_api_vers
; /* API version opened */
127 /* Enforce version adherence. */
128 if (ver_intro
> v
|| v
> LIBFMEVENT_VERSION_LATEST
||
129 ver_intro
> LIBFMEVENT_VERSION_LATEST
) {
130 tsd
->ts_lasterr
= FMEVERR_VERSION_MISMATCH
;
138 * Called on any fmev_shdl_fini. Free the TSD for this thread. If this
139 * thread makes other API calls for other open handles, or opens a new
140 * handle, then TSD will be allocated again in fmev_api_enter.
143 fmev_api_freetsd(void)
145 struct fmev_tsd
*tsd
;
147 if ((tsd
= pthread_getspecific(fmev_tsdkey
)) != NULL
) {
148 (void) pthread_setspecific(fmev_tsdkey
, NULL
);
149 fmev_tsd_destructor((void *)tsd
);
154 * To return an error condition an API member first sets the error type
155 * with a call to fmev_seterr and then returns NULL or whatever it wants.
156 * The caller can then retrieve the per-thread error type using fmev_errno
157 * or format it with fmev_strerr.
160 fmev_seterr(fmev_err_t error
)
162 struct fmev_tsd
*tsd
;
166 if ((tsd
= pthread_getspecific(fmev_tsdkey
)) != NULL
)
167 tsd
->ts_lasterr
= error
;
173 * fmev_errno is a macro defined in terms of the following function. It
174 * can be used to dereference the last error value on the current thread;
175 * it must not be used to assign to fmev_errno.
178 const fmev_err_t apierr
= FMEVERR_API
;
179 const fmev_err_t unknownerr
= FMEVERR_UNKNOWN
;
184 struct fmev_tsd
*tsd
;
189 if ((tsd
= pthread_getspecific(fmev_tsdkey
)) == NULL
)
190 return (&unknownerr
);
192 return ((const fmev_err_t
*)&tsd
->ts_lasterr
);
196 dflt_alloc(size_t sz
)
198 return (umem_alloc(sz
, UMEM_DEFAULT
));
202 dflt_zalloc(size_t sz
)
204 return (umem_zalloc(sz
, UMEM_DEFAULT
));
208 dflt_free(void *buf
, size_t sz
)