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