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