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 * Subscription event access interfaces.
2811102SGavin.Maltby@Sun.COM */
2911102SGavin.Maltby@Sun.COM
3011102SGavin.Maltby@Sun.COM #include <sys/types.h>
3111102SGavin.Maltby@Sun.COM #include <pthread.h>
3211102SGavin.Maltby@Sun.COM #include <umem.h>
3311102SGavin.Maltby@Sun.COM #include <fm/libfmevent.h>
3411102SGavin.Maltby@Sun.COM
3511102SGavin.Maltby@Sun.COM #include "fmev_impl.h"
3611102SGavin.Maltby@Sun.COM
3711102SGavin.Maltby@Sun.COM static pthread_key_t fmev_tsdkey = PTHREAD_ONCE_KEY_NP;
3811102SGavin.Maltby@Sun.COM static int key_inited;
3911102SGavin.Maltby@Sun.COM
4011102SGavin.Maltby@Sun.COM /*
4111102SGavin.Maltby@Sun.COM * Thread and handle specific data.
4211102SGavin.Maltby@Sun.COM */
4311102SGavin.Maltby@Sun.COM struct fmev_tsd {
4411102SGavin.Maltby@Sun.COM fmev_err_t ts_lasterr;
4511102SGavin.Maltby@Sun.COM };
4611102SGavin.Maltby@Sun.COM
4711102SGavin.Maltby@Sun.COM static void
fmev_tsd_destructor(void * data)4811102SGavin.Maltby@Sun.COM fmev_tsd_destructor(void *data)
4911102SGavin.Maltby@Sun.COM {
5011102SGavin.Maltby@Sun.COM umem_free(data, sizeof (struct fmev_tsd));
5111102SGavin.Maltby@Sun.COM }
5211102SGavin.Maltby@Sun.COM
5311102SGavin.Maltby@Sun.COM /*
5411102SGavin.Maltby@Sun.COM * Called only from fmev_shdl_init. Check we are opening a valid version
5511102SGavin.Maltby@Sun.COM * of the ABI.
5611102SGavin.Maltby@Sun.COM */
5711102SGavin.Maltby@Sun.COM int
fmev_api_init(struct fmev_hdl_cmn * hc)5811102SGavin.Maltby@Sun.COM fmev_api_init(struct fmev_hdl_cmn *hc)
5911102SGavin.Maltby@Sun.COM {
60*12967Sgavin.maltby@oracle.com uint32_t v = hc->hc_api_vers;
61*12967Sgavin.maltby@oracle.com int rc;
62*12967Sgavin.maltby@oracle.com
63*12967Sgavin.maltby@oracle.com if (!fmev_api_enter((struct fmev_hdl_cmn *)fmev_api_init, 0))
6411102SGavin.Maltby@Sun.COM return (0);
65*12967Sgavin.maltby@oracle.com
66*12967Sgavin.maltby@oracle.com switch (v) {
67*12967Sgavin.maltby@oracle.com case LIBFMEVENT_VERSION_1:
68*12967Sgavin.maltby@oracle.com case LIBFMEVENT_VERSION_2:
69*12967Sgavin.maltby@oracle.com rc = 1;
70*12967Sgavin.maltby@oracle.com break;
71*12967Sgavin.maltby@oracle.com
72*12967Sgavin.maltby@oracle.com default:
7311102SGavin.Maltby@Sun.COM if (key_inited)
7411102SGavin.Maltby@Sun.COM (void) fmev_seterr(FMEVERR_VERSION_MISMATCH);
75*12967Sgavin.maltby@oracle.com rc = 0;
76*12967Sgavin.maltby@oracle.com break;
7711102SGavin.Maltby@Sun.COM }
7811102SGavin.Maltby@Sun.COM
79*12967Sgavin.maltby@oracle.com return (rc);
8011102SGavin.Maltby@Sun.COM }
8111102SGavin.Maltby@Sun.COM
8211102SGavin.Maltby@Sun.COM /*
8311102SGavin.Maltby@Sun.COM * On entry to other libfmevent API members we call fmev_api_enter.
8411102SGavin.Maltby@Sun.COM * Some thread-specific data is used to keep a per-thread error value.
8511102SGavin.Maltby@Sun.COM * The version opened must be no greater than the latest version but can
8611102SGavin.Maltby@Sun.COM * be older. The ver_intro is the api version at which the interface
8711102SGavin.Maltby@Sun.COM * was added - the caller must have opened at least this version.
8811102SGavin.Maltby@Sun.COM */
8911102SGavin.Maltby@Sun.COM int
fmev_api_enter(struct fmev_hdl_cmn * hc,uint32_t ver_intro)9011102SGavin.Maltby@Sun.COM fmev_api_enter(struct fmev_hdl_cmn *hc, uint32_t ver_intro)
9111102SGavin.Maltby@Sun.COM {
92*12967Sgavin.maltby@oracle.com uint32_t v;
9311102SGavin.Maltby@Sun.COM struct fmev_tsd *tsd;
9411102SGavin.Maltby@Sun.COM
9511102SGavin.Maltby@Sun.COM /* Initialize key on first visit */
9611102SGavin.Maltby@Sun.COM if (!key_inited) {
9711102SGavin.Maltby@Sun.COM (void) pthread_key_create_once_np(&fmev_tsdkey,
9811102SGavin.Maltby@Sun.COM fmev_tsd_destructor);
9911102SGavin.Maltby@Sun.COM key_inited = 1;
10011102SGavin.Maltby@Sun.COM }
10111102SGavin.Maltby@Sun.COM
10211102SGavin.Maltby@Sun.COM /*
10311102SGavin.Maltby@Sun.COM * Allocate TSD for error value for this thread. It is only
10411102SGavin.Maltby@Sun.COM * freed if/when the thread exits.
10511102SGavin.Maltby@Sun.COM */
10611102SGavin.Maltby@Sun.COM if ((tsd = pthread_getspecific(fmev_tsdkey)) == NULL) {
10711102SGavin.Maltby@Sun.COM if ((tsd = umem_alloc(sizeof (*tsd), UMEM_DEFAULT)) == NULL ||
10811102SGavin.Maltby@Sun.COM pthread_setspecific(fmev_tsdkey, (const void *)tsd) != 0) {
10911102SGavin.Maltby@Sun.COM if (tsd)
11011102SGavin.Maltby@Sun.COM umem_free(tsd, sizeof (*tsd));
11111102SGavin.Maltby@Sun.COM return (0); /* no error set, but what can we do */
11211102SGavin.Maltby@Sun.COM }
11311102SGavin.Maltby@Sun.COM }
11411102SGavin.Maltby@Sun.COM
11511102SGavin.Maltby@Sun.COM tsd->ts_lasterr = 0;
11611102SGavin.Maltby@Sun.COM
117*12967Sgavin.maltby@oracle.com if (hc == (struct fmev_hdl_cmn *)fmev_api_init)
118*12967Sgavin.maltby@oracle.com return (1); /* special case from fmev_api_init only */
119*12967Sgavin.maltby@oracle.com
120*12967Sgavin.maltby@oracle.com if (hc == NULL || hc->hc_magic != _FMEV_SHMAGIC) {
121*12967Sgavin.maltby@oracle.com tsd->ts_lasterr = FMEVERR_API;
122*12967Sgavin.maltby@oracle.com return (0);
12311102SGavin.Maltby@Sun.COM }
12411102SGavin.Maltby@Sun.COM
125*12967Sgavin.maltby@oracle.com v = hc->hc_api_vers; /* API version opened */
126*12967Sgavin.maltby@oracle.com
12711102SGavin.Maltby@Sun.COM /* Enforce version adherence. */
128*12967Sgavin.maltby@oracle.com if (ver_intro > v || v > LIBFMEVENT_VERSION_LATEST ||
12911102SGavin.Maltby@Sun.COM ver_intro > LIBFMEVENT_VERSION_LATEST) {
13011102SGavin.Maltby@Sun.COM tsd->ts_lasterr = FMEVERR_VERSION_MISMATCH;
13111102SGavin.Maltby@Sun.COM return (0);
13211102SGavin.Maltby@Sun.COM }
13311102SGavin.Maltby@Sun.COM
13411102SGavin.Maltby@Sun.COM return (1);
13511102SGavin.Maltby@Sun.COM }
13611102SGavin.Maltby@Sun.COM
13711102SGavin.Maltby@Sun.COM /*
13811102SGavin.Maltby@Sun.COM * Called on any fmev_shdl_fini. Free the TSD for this thread. If this
13911102SGavin.Maltby@Sun.COM * thread makes other API calls for other open handles, or opens a new
14011102SGavin.Maltby@Sun.COM * handle, then TSD will be allocated again in fmev_api_enter.
14111102SGavin.Maltby@Sun.COM */
14211102SGavin.Maltby@Sun.COM void
fmev_api_freetsd(void)14311102SGavin.Maltby@Sun.COM fmev_api_freetsd(void)
14411102SGavin.Maltby@Sun.COM {
14511102SGavin.Maltby@Sun.COM struct fmev_tsd *tsd;
14611102SGavin.Maltby@Sun.COM
14711102SGavin.Maltby@Sun.COM if ((tsd = pthread_getspecific(fmev_tsdkey)) != NULL) {
14811102SGavin.Maltby@Sun.COM (void) pthread_setspecific(fmev_tsdkey, NULL);
14911102SGavin.Maltby@Sun.COM fmev_tsd_destructor((void *)tsd);
15011102SGavin.Maltby@Sun.COM }
15111102SGavin.Maltby@Sun.COM }
15211102SGavin.Maltby@Sun.COM
15311102SGavin.Maltby@Sun.COM /*
15411102SGavin.Maltby@Sun.COM * To return an error condition an API member first sets the error type
15511102SGavin.Maltby@Sun.COM * with a call to fmev_seterr and then returns NULL or whatever it wants.
15611102SGavin.Maltby@Sun.COM * The caller can then retrieve the per-thread error type using fmev_errno
15711102SGavin.Maltby@Sun.COM * or format it with fmev_strerr.
15811102SGavin.Maltby@Sun.COM */
15911102SGavin.Maltby@Sun.COM fmev_err_t
fmev_seterr(fmev_err_t error)16011102SGavin.Maltby@Sun.COM fmev_seterr(fmev_err_t error)
16111102SGavin.Maltby@Sun.COM {
16211102SGavin.Maltby@Sun.COM struct fmev_tsd *tsd;
16311102SGavin.Maltby@Sun.COM
16411102SGavin.Maltby@Sun.COM ASSERT(key_inited);
16511102SGavin.Maltby@Sun.COM
16611102SGavin.Maltby@Sun.COM if ((tsd = pthread_getspecific(fmev_tsdkey)) != NULL)
16711102SGavin.Maltby@Sun.COM tsd->ts_lasterr = error;
16811102SGavin.Maltby@Sun.COM
16911102SGavin.Maltby@Sun.COM return (error);
17011102SGavin.Maltby@Sun.COM }
17111102SGavin.Maltby@Sun.COM
17211102SGavin.Maltby@Sun.COM /*
17311102SGavin.Maltby@Sun.COM * fmev_errno is a macro defined in terms of the following function. It
17411102SGavin.Maltby@Sun.COM * can be used to dereference the last error value on the current thread;
17511102SGavin.Maltby@Sun.COM * it must not be used to assign to fmev_errno.
17611102SGavin.Maltby@Sun.COM */
17711102SGavin.Maltby@Sun.COM
17811102SGavin.Maltby@Sun.COM const fmev_err_t apierr = FMEVERR_API;
17911102SGavin.Maltby@Sun.COM const fmev_err_t unknownerr = FMEVERR_UNKNOWN;
18011102SGavin.Maltby@Sun.COM
18111102SGavin.Maltby@Sun.COM const fmev_err_t *
__fmev_errno(void)18211102SGavin.Maltby@Sun.COM __fmev_errno(void)
18311102SGavin.Maltby@Sun.COM {
18411102SGavin.Maltby@Sun.COM struct fmev_tsd *tsd;
18511102SGavin.Maltby@Sun.COM
18611102SGavin.Maltby@Sun.COM if (!key_inited)
18711102SGavin.Maltby@Sun.COM return (&apierr);
18811102SGavin.Maltby@Sun.COM
18911102SGavin.Maltby@Sun.COM if ((tsd = pthread_getspecific(fmev_tsdkey)) == NULL)
19011102SGavin.Maltby@Sun.COM return (&unknownerr);
19111102SGavin.Maltby@Sun.COM
19211102SGavin.Maltby@Sun.COM return ((const fmev_err_t *)&tsd->ts_lasterr);
19311102SGavin.Maltby@Sun.COM }
194*12967Sgavin.maltby@oracle.com
195*12967Sgavin.maltby@oracle.com void *
dflt_alloc(size_t sz)196*12967Sgavin.maltby@oracle.com dflt_alloc(size_t sz)
197*12967Sgavin.maltby@oracle.com {
198*12967Sgavin.maltby@oracle.com return (umem_alloc(sz, UMEM_DEFAULT));
199*12967Sgavin.maltby@oracle.com }
200*12967Sgavin.maltby@oracle.com
201*12967Sgavin.maltby@oracle.com void *
dflt_zalloc(size_t sz)202*12967Sgavin.maltby@oracle.com dflt_zalloc(size_t sz)
203*12967Sgavin.maltby@oracle.com {
204*12967Sgavin.maltby@oracle.com return (umem_zalloc(sz, UMEM_DEFAULT));
205*12967Sgavin.maltby@oracle.com }
206*12967Sgavin.maltby@oracle.com
207*12967Sgavin.maltby@oracle.com void
dflt_free(void * buf,size_t sz)208*12967Sgavin.maltby@oracle.com dflt_free(void *buf, size_t sz)
209*12967Sgavin.maltby@oracle.com {
210*12967Sgavin.maltby@oracle.com umem_free(buf, sz);
211*12967Sgavin.maltby@oracle.com }
212