xref: /onnv-gate/usr/src/lib/fm/libfmevent/common/fmev_util.c (revision 12967:ab9ae749152f)
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