xref: /titanic_52/usr/src/lib/libcpc/common/obsoleted.c (revision 1a6fa3a5205c95d7c4ea1caa5f0f9b408e0a2c1b)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*1a6fa3a5Srab  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <sys/stat.h>
317c478bd9Sstevel@tonic-gate #include <sys/syscall.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <stdio.h>
347c478bd9Sstevel@tonic-gate #include <unistd.h>
357c478bd9Sstevel@tonic-gate #include <errno.h>
367c478bd9Sstevel@tonic-gate #include <string.h>
377c478bd9Sstevel@tonic-gate #include <strings.h>
387c478bd9Sstevel@tonic-gate #include <stdarg.h>
397c478bd9Sstevel@tonic-gate #include <signal.h>
407c478bd9Sstevel@tonic-gate #include <libintl.h>
417c478bd9Sstevel@tonic-gate #include <dirent.h>
427c478bd9Sstevel@tonic-gate #include <sys/cpc_impl.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #include "libcpc.h"
457c478bd9Sstevel@tonic-gate #include "libcpc_impl.h"
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate /*
487c478bd9Sstevel@tonic-gate  * CPC library handle for use by CPCv1 implementation.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate cpc_t *__cpc = NULL;
517c478bd9Sstevel@tonic-gate mutex_t __cpc_lock;		/* protects __cpc handle */
527c478bd9Sstevel@tonic-gate int __cpc_v1_cpuver;		/* CPU version in use by CPCv1 client */
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #ifdef __sparc
557c478bd9Sstevel@tonic-gate uint64_t __cpc_v1_pcr;		/* last bound %pcr value */
567c478bd9Sstevel@tonic-gate #else
577c478bd9Sstevel@tonic-gate uint32_t __cpc_v1_pes[2];	/* last bound %pes values */
587c478bd9Sstevel@tonic-gate #endif /* __sparc */
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate int
617c478bd9Sstevel@tonic-gate __cpc_init(void)
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate 	const char *fn = "__cpc_init";
647c478bd9Sstevel@tonic-gate 	extern cpc_t *__cpc;	/* CPC handle for obsolete clients to share */
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&__cpc_lock);
677c478bd9Sstevel@tonic-gate 	if (__cpc == NULL && (__cpc = cpc_open(CPC_VER_CURRENT)) == NULL) {
687c478bd9Sstevel@tonic-gate 		__cpc_error(fn, dgettext(TEXT_DOMAIN,
697c478bd9Sstevel@tonic-gate 		    "Couldn't open CPC library handle\n"));
707c478bd9Sstevel@tonic-gate 		(void) mutex_unlock(&__cpc_lock);
717c478bd9Sstevel@tonic-gate 		return (-1);
727c478bd9Sstevel@tonic-gate 	}
737c478bd9Sstevel@tonic-gate 	(void) mutex_unlock(&__cpc_lock);
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	return (0);
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate int
797c478bd9Sstevel@tonic-gate cpc_bind_event(cpc_event_t *this, int flags)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate 	cpc_set_t		*set;
827c478bd9Sstevel@tonic-gate 	cpc_request_t		*rp;
837c478bd9Sstevel@tonic-gate 	int			ret;
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	if (this == NULL) {
867c478bd9Sstevel@tonic-gate 		(void) cpc_rele();
877c478bd9Sstevel@tonic-gate 		return (0);
887c478bd9Sstevel@tonic-gate 	}
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	if (__cpc_init() != 0) {
917c478bd9Sstevel@tonic-gate 		errno = ENXIO;
927c478bd9Sstevel@tonic-gate 		return (-1);
937c478bd9Sstevel@tonic-gate 	}
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	/*
967c478bd9Sstevel@tonic-gate 	 * The cpuver and control fields of the cpc_event_t must be saved off
977c478bd9Sstevel@tonic-gate 	 * for later. The user may call cpc_take_sample(), expecting these to
987c478bd9Sstevel@tonic-gate 	 * be copied into a different cpc_event_t struct by the kernel. We have
997c478bd9Sstevel@tonic-gate 	 * to fake that behavior for CPCv1 clients.
1007c478bd9Sstevel@tonic-gate 	 */
1017c478bd9Sstevel@tonic-gate 	__cpc_v1_cpuver = this->ce_cpuver;
1027c478bd9Sstevel@tonic-gate #ifdef __sparc
1037c478bd9Sstevel@tonic-gate 	__cpc_v1_pcr = this->ce_pcr;
1047c478bd9Sstevel@tonic-gate #else
1057c478bd9Sstevel@tonic-gate 	__cpc_v1_pes[0] = this->ce_pes[0];
1067c478bd9Sstevel@tonic-gate 	__cpc_v1_pes[1] = this->ce_pes[1];
1077c478bd9Sstevel@tonic-gate #endif /* __sparc */
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	if ((set = __cpc_eventtoset(__cpc, this, flags)) == NULL) {
1107c478bd9Sstevel@tonic-gate 		errno = EINVAL;
1117c478bd9Sstevel@tonic-gate 		return (-1);
1127c478bd9Sstevel@tonic-gate 	}
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	/*
1157c478bd9Sstevel@tonic-gate 	 * Convert flags to CPC2.
1167c478bd9Sstevel@tonic-gate 	 */
1177c478bd9Sstevel@tonic-gate 	if (flags & CPC_BIND_EMT_OVF) {
1187c478bd9Sstevel@tonic-gate 		for (rp = set->cs_request; rp != NULL; rp = rp->cr_next)
1197c478bd9Sstevel@tonic-gate 			rp->cr_flags |= CPC_OVF_NOTIFY_EMT;
1207c478bd9Sstevel@tonic-gate 		flags &= ~CPC_BIND_EMT_OVF;
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	ret = cpc_bind_curlwp(__cpc, set, flags);
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	(void) cpc_set_destroy(__cpc, set);
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	return (ret);
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate int
1317c478bd9Sstevel@tonic-gate cpc_take_sample(cpc_event_t *this)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate 	this->ce_cpuver = __cpc_v1_cpuver;
1347c478bd9Sstevel@tonic-gate #ifdef __sparc
1357c478bd9Sstevel@tonic-gate 	this->ce_pcr = __cpc_v1_pcr;
1367c478bd9Sstevel@tonic-gate #else
1377c478bd9Sstevel@tonic-gate 	this->ce_pes[0] = __cpc_v1_pes[0];
1387c478bd9Sstevel@tonic-gate 	this->ce_pes[1] = __cpc_v1_pes[1];
1397c478bd9Sstevel@tonic-gate #endif /* __sparc */
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	return (syscall(SYS_cpc, CPC_SAMPLE, -1, this->ce_pic, &this->ce_hrt,
1427c478bd9Sstevel@tonic-gate 	    &CPC_TICKREG(this), 0));
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate int
1467c478bd9Sstevel@tonic-gate cpc_count_usr_events(int enable)
1477c478bd9Sstevel@tonic-gate {
148*1a6fa3a5Srab 	return (syscall(SYS_cpc, CPC_USR_EVENTS, -1, enable, 0));
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate int
1527c478bd9Sstevel@tonic-gate cpc_count_sys_events(int enable)
1537c478bd9Sstevel@tonic-gate {
154*1a6fa3a5Srab 	return (syscall(SYS_cpc, CPC_SYS_EVENTS, -1, enable, 0));
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate int
1587c478bd9Sstevel@tonic-gate cpc_rele(void)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 	return (syscall(SYS_cpc, CPC_RELE, -1, NULL, 0));
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate  * See if the system call is working and installed.
1657c478bd9Sstevel@tonic-gate  *
1667c478bd9Sstevel@tonic-gate  * We invoke the system call with nonsense arguments - if it's
1677c478bd9Sstevel@tonic-gate  * there and working correctly, it will return EINVAL.
1687c478bd9Sstevel@tonic-gate  *
1697c478bd9Sstevel@tonic-gate  * (This avoids the user getting a SIGSYS core dump when they attempt
1707c478bd9Sstevel@tonic-gate  * to bind on older hardware)
1717c478bd9Sstevel@tonic-gate  */
1727c478bd9Sstevel@tonic-gate int
1737c478bd9Sstevel@tonic-gate cpc_access(void)
1747c478bd9Sstevel@tonic-gate {
1757c478bd9Sstevel@tonic-gate 	void (*handler)(int);
1767c478bd9Sstevel@tonic-gate 	int error = 0;
1777c478bd9Sstevel@tonic-gate 	const char fn[] = "access";
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	handler = signal(SIGSYS, SIG_IGN);
1807c478bd9Sstevel@tonic-gate 	if (syscall(SYS_cpc, -1, -1, NULL, 0) == -1 &&
1817c478bd9Sstevel@tonic-gate 	    errno != EINVAL)
1827c478bd9Sstevel@tonic-gate 		error = errno;
1837c478bd9Sstevel@tonic-gate 	(void) signal(SIGSYS, handler);
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	switch (error) {
1867c478bd9Sstevel@tonic-gate 	case EAGAIN:
1877c478bd9Sstevel@tonic-gate 		__cpc_error(fn, dgettext(TEXT_DOMAIN, "Another process may be "
1887c478bd9Sstevel@tonic-gate 		    "sampling system-wide CPU statistics\n"));
1897c478bd9Sstevel@tonic-gate 		break;
1907c478bd9Sstevel@tonic-gate 	case ENOSYS:
1917c478bd9Sstevel@tonic-gate 		__cpc_error(fn,
1927c478bd9Sstevel@tonic-gate 		    dgettext(TEXT_DOMAIN, "CPU performance counters "
1937c478bd9Sstevel@tonic-gate 		    "are inaccessible on this machine\n"));
1947c478bd9Sstevel@tonic-gate 		break;
1957c478bd9Sstevel@tonic-gate 	default:
1967c478bd9Sstevel@tonic-gate 		__cpc_error(fn, "%s\n", strerror(errno));
1977c478bd9Sstevel@tonic-gate 		break;
1987c478bd9Sstevel@tonic-gate 	case 0:
1997c478bd9Sstevel@tonic-gate 		return (0);
2007c478bd9Sstevel@tonic-gate 	}
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	errno = error;
2037c478bd9Sstevel@tonic-gate 	return (-1);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate /*
2077c478bd9Sstevel@tonic-gate  * To look at the system-wide counters, we have to open the
2087c478bd9Sstevel@tonic-gate  * 'shared' device.  Once that device is open, no further contexts
2097c478bd9Sstevel@tonic-gate  * can be installed (though one open is needed per CPU)
2107c478bd9Sstevel@tonic-gate  */
2117c478bd9Sstevel@tonic-gate int
2127c478bd9Sstevel@tonic-gate cpc_shared_open(void)
2137c478bd9Sstevel@tonic-gate {
2147c478bd9Sstevel@tonic-gate 	const char driver[] = CPUDRV_SHARED;
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	return (open(driver, O_RDWR));
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate void
2207c478bd9Sstevel@tonic-gate cpc_shared_close(int fd)
2217c478bd9Sstevel@tonic-gate {
2227c478bd9Sstevel@tonic-gate 	(void) cpc_shared_rele(fd);
2237c478bd9Sstevel@tonic-gate 	(void) close(fd);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate int
2277c478bd9Sstevel@tonic-gate cpc_shared_bind_event(int fd, cpc_event_t *this, int flags)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate 	extern cpc_t		*__cpc;
2307c478bd9Sstevel@tonic-gate 	cpc_set_t		*set;
2317c478bd9Sstevel@tonic-gate 	int			ret;
2327c478bd9Sstevel@tonic-gate 	char			*packed_set;
2337c478bd9Sstevel@tonic-gate 	size_t			packsize;
2347c478bd9Sstevel@tonic-gate 	int			subcode;
2357c478bd9Sstevel@tonic-gate 	__cpc_args_t		cpc_args;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	if (this == NULL) {
2387c478bd9Sstevel@tonic-gate 		(void) cpc_shared_rele(fd);
2397c478bd9Sstevel@tonic-gate 		return (0);
2407c478bd9Sstevel@tonic-gate 	} else if (flags != 0) {
2417c478bd9Sstevel@tonic-gate 		errno = EINVAL;
2427c478bd9Sstevel@tonic-gate 		return (-1);
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	if (__cpc_init() != 0) {
2467c478bd9Sstevel@tonic-gate 		errno = ENXIO;
2477c478bd9Sstevel@tonic-gate 		return (-1);
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate 	if ((set = __cpc_eventtoset(__cpc, this, flags)) == NULL) {
2517c478bd9Sstevel@tonic-gate 		errno = EINVAL;
2527c478bd9Sstevel@tonic-gate 		return (-1);
2537c478bd9Sstevel@tonic-gate 	}
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	__cpc_v1_cpuver = this->ce_cpuver;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	if ((packed_set = __cpc_pack_set(set, flags, &packsize)) == NULL) {
2587c478bd9Sstevel@tonic-gate 		errno = ENOMEM;
2597c478bd9Sstevel@tonic-gate 		return (-1);
2607c478bd9Sstevel@tonic-gate 	}
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	cpc_args.udata1 = packed_set;
2637c478bd9Sstevel@tonic-gate 	cpc_args.udata2 = (void *)packsize;
2647c478bd9Sstevel@tonic-gate 	cpc_args.udata3 = (void *)&subcode;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	ret = ioctl(fd, CPCIO_BIND, &cpc_args);
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	free(packed_set);
2697c478bd9Sstevel@tonic-gate 	(void) cpc_set_destroy(__cpc, set);
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate 	return (ret);
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate int
2757c478bd9Sstevel@tonic-gate cpc_shared_take_sample(int fd, cpc_event_t *this)
2767c478bd9Sstevel@tonic-gate {
2777c478bd9Sstevel@tonic-gate 	__cpc_args_t args;
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	args.udata1 = this->ce_pic;
2807c478bd9Sstevel@tonic-gate 	args.udata2 = &this->ce_hrt;
2817c478bd9Sstevel@tonic-gate 	args.udata3 = &CPC_TICKREG(this);
2827c478bd9Sstevel@tonic-gate 
2837c478bd9Sstevel@tonic-gate 	this->ce_cpuver = __cpc_v1_cpuver;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	return (ioctl(fd, CPCIO_SAMPLE, &args));
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate int
2897c478bd9Sstevel@tonic-gate cpc_shared_rele(int fd)
2907c478bd9Sstevel@tonic-gate {
2917c478bd9Sstevel@tonic-gate 	return (ioctl(fd, CPCIO_RELE, 0));
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate int
2957c478bd9Sstevel@tonic-gate cpc_pctx_bind_event(pctx_t *pctx, id_t lwpid, cpc_event_t *event, int flags)
2967c478bd9Sstevel@tonic-gate {
2977c478bd9Sstevel@tonic-gate 	cpc_set_t		*set;
2987c478bd9Sstevel@tonic-gate 	int			ret;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	if (event == NULL)
3017c478bd9Sstevel@tonic-gate 		return (cpc_pctx_rele(pctx, lwpid));
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	if (__cpc_init() != 0) {
3047c478bd9Sstevel@tonic-gate 		errno = ENXIO;
3057c478bd9Sstevel@tonic-gate 		return (-1);
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	else if (flags != 0) {
3097c478bd9Sstevel@tonic-gate 		errno = EINVAL;
3107c478bd9Sstevel@tonic-gate 		return (-1);
3117c478bd9Sstevel@tonic-gate 	}
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 	if ((set = __cpc_eventtoset(__cpc, event, flags)) == NULL) {
3147c478bd9Sstevel@tonic-gate 		errno = EINVAL;
3157c478bd9Sstevel@tonic-gate 		return (-1);
3167c478bd9Sstevel@tonic-gate 	}
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	/*
3197c478bd9Sstevel@tonic-gate 	 * The cpuver and control fields of the cpc_event_t must be saved off
3207c478bd9Sstevel@tonic-gate 	 * for later. The user may call cpc_take_sample(), expecting these to
3217c478bd9Sstevel@tonic-gate 	 * be copied into a different cpc_event_t struct by the kernel. We have
3227c478bd9Sstevel@tonic-gate 	 * to fake that behavior for CPCv1 clients.
3237c478bd9Sstevel@tonic-gate 	 */
3247c478bd9Sstevel@tonic-gate 	__cpc_v1_cpuver = event->ce_cpuver;
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	ret = cpc_bind_pctx(__cpc, pctx, lwpid, set, 0);
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	(void) cpc_set_destroy(__cpc, set);
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	return (ret);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate int
3347c478bd9Sstevel@tonic-gate cpc_pctx_take_sample(pctx_t *pctx, id_t lwpid, cpc_event_t *event)
3357c478bd9Sstevel@tonic-gate {
3367c478bd9Sstevel@tonic-gate 	event->ce_cpuver = __cpc_v1_cpuver;
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	return (__pctx_cpc(pctx, __cpc, CPC_SAMPLE, lwpid, event->ce_pic,
3397c478bd9Sstevel@tonic-gate 	    &event->ce_hrt, &CPC_TICKREG(event), CPC1_BUFSIZE));
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate /*
3437c478bd9Sstevel@tonic-gate  * Given a process context and an lwpid, mark the CPU performance
3447c478bd9Sstevel@tonic-gate  * counter context as invalid.
3457c478bd9Sstevel@tonic-gate  */
3467c478bd9Sstevel@tonic-gate int
3477c478bd9Sstevel@tonic-gate cpc_pctx_invalidate(pctx_t *pctx, id_t lwpid)
3487c478bd9Sstevel@tonic-gate {
3497c478bd9Sstevel@tonic-gate 	return (__pctx_cpc(pctx, __cpc, CPC_INVALIDATE, lwpid, 0, 0, 0, 0));
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate /*
3537c478bd9Sstevel@tonic-gate  * Given a process context and an lwpid, remove all our
3547c478bd9Sstevel@tonic-gate  * hardware context from it.
3557c478bd9Sstevel@tonic-gate  */
3567c478bd9Sstevel@tonic-gate int
3577c478bd9Sstevel@tonic-gate cpc_pctx_rele(pctx_t *pctx, id_t lwpid)
3587c478bd9Sstevel@tonic-gate {
3597c478bd9Sstevel@tonic-gate 	return (__pctx_cpc(pctx, __cpc, CPC_RELE, lwpid, 0, 0, 0, 0));
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate static cpc_errfn_t *__cpc_uerrfn;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/
3657c478bd9Sstevel@tonic-gate void
3667c478bd9Sstevel@tonic-gate __cpc_error(const char *fn, const char *fmt, ...)
3677c478bd9Sstevel@tonic-gate {
3687c478bd9Sstevel@tonic-gate 	va_list ap;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
3717c478bd9Sstevel@tonic-gate 	if (__cpc_uerrfn)
3727c478bd9Sstevel@tonic-gate 		__cpc_uerrfn(fn, fmt, ap);
3737c478bd9Sstevel@tonic-gate 	else {
3747c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "libcpc: %s: ", fn);
3757c478bd9Sstevel@tonic-gate 		(void) vfprintf(stderr, fmt, ap);
3767c478bd9Sstevel@tonic-gate 	}
3777c478bd9Sstevel@tonic-gate 	va_end(ap);
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate void
3817c478bd9Sstevel@tonic-gate cpc_seterrfn(cpc_errfn_t *errfn)
3827c478bd9Sstevel@tonic-gate {
3837c478bd9Sstevel@tonic-gate 	__cpc_uerrfn = errfn;
3847c478bd9Sstevel@tonic-gate }
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate /*
3877c478bd9Sstevel@tonic-gate  * cpc_version() is only for CPC1 clients.
3887c478bd9Sstevel@tonic-gate  */
3897c478bd9Sstevel@tonic-gate uint_t __cpc_workver = CPC_VER_1;
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate uint_t
3927c478bd9Sstevel@tonic-gate cpc_version(uint_t ver)
3937c478bd9Sstevel@tonic-gate {
3947c478bd9Sstevel@tonic-gate 	__cpc_workver = CPC_VER_1;
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	switch (ver) {
3977c478bd9Sstevel@tonic-gate 	case CPC_VER_NONE:
3987c478bd9Sstevel@tonic-gate 	case CPC_VER_CURRENT:
3997c478bd9Sstevel@tonic-gate 		return (CPC_VER_CURRENT);
4007c478bd9Sstevel@tonic-gate 	case CPC_VER_1:
4017c478bd9Sstevel@tonic-gate 		/*
4027c478bd9Sstevel@tonic-gate 		 * As long as the client is using cpc_version() at all, it is
4037c478bd9Sstevel@tonic-gate 		 * a CPCv1 client.  We still allow CPCv1 clients to compile on
4047c478bd9Sstevel@tonic-gate 		 * CPCv2 systems.
4057c478bd9Sstevel@tonic-gate 		 */
4067c478bd9Sstevel@tonic-gate 		return (CPC_VER_1);
4077c478bd9Sstevel@tonic-gate 	}
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	return (CPC_VER_NONE);
4107c478bd9Sstevel@tonic-gate }
411