49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * See the License for the specific language governing permissions
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * and limitations under the License.
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 * CDDL HEADER END
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Subscription event access interfaces.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbystatic pthread_key_t fmev_tsdkey = PTHREAD_ONCE_KEY_NP;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Thread and handle specific data.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Called only from fmev_shdl_init. Check we are opening a valid version
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * of the ABI.
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (!fmev_api_enter((struct fmev_hdl_cmn *)fmev_api_init, 0))
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby switch (v) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * On entry to other libfmevent API members we call fmev_api_enter.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Some thread-specific data is used to keep a per-thread error value.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * The version opened must be no greater than the latest version but can
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * be older. The ver_intro is the api version at which the interface
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * was added - the caller must have opened at least this version.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltbyfmev_api_enter(struct fmev_hdl_cmn *hc, uint32_t ver_intro)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby /* Initialize key on first visit */
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby (void) pthread_key_create_once_np(&fmev_tsdkey,
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Allocate TSD for error value for this thread. It is only
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * freed if/when the thread exits.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((tsd = pthread_getspecific(fmev_tsdkey)) == NULL) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((tsd = umem_alloc(sizeof (*tsd), UMEM_DEFAULT)) == NULL ||
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby pthread_setspecific(fmev_tsdkey, (const void *)tsd) != 0) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby return (0); /* no error set, but what can we do */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (hc == (struct fmev_hdl_cmn *)fmev_api_init)
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby return (1); /* special case from fmev_api_init only */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (hc == NULL || hc->hc_magic != _FMEV_SHMAGIC) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby /* Enforce version adherence. */
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby if (ver_intro > v || v > LIBFMEVENT_VERSION_LATEST ||
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * Called on any fmev_shdl_fini. Free the TSD for this thread. If this
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * thread makes other API calls for other open handles, or opens a new
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * handle, then TSD will be allocated again in fmev_api_enter.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((tsd = pthread_getspecific(fmev_tsdkey)) != NULL) {
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * To return an error condition an API member first sets the error type
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * with a call to fmev_seterr and then returns NULL or whatever it wants.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * The caller can then retrieve the per-thread error type using fmev_errno
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * or format it with fmev_strerr.
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby if ((tsd = pthread_getspecific(fmev_tsdkey)) != NULL)
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * fmev_errno is a macro defined in terms of the following function. It
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * can be used to dereference the last error value on the current thread;
49b225e1cfa7bbf7738d4df0a03f18e3283426ebGavin Maltby * it must not be used to assign to fmev_errno.