1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h> 32*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <unistd.h> 35*7c478bd9Sstevel@tonic-gate #include <errno.h> 36*7c478bd9Sstevel@tonic-gate #include <string.h> 37*7c478bd9Sstevel@tonic-gate #include <strings.h> 38*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 39*7c478bd9Sstevel@tonic-gate #include <signal.h> 40*7c478bd9Sstevel@tonic-gate #include <libintl.h> 41*7c478bd9Sstevel@tonic-gate #include <dirent.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/cpc_impl.h> 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate #include "libcpc.h" 45*7c478bd9Sstevel@tonic-gate #include "libcpc_impl.h" 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate /* 48*7c478bd9Sstevel@tonic-gate * CPC library handle for use by CPCv1 implementation. 49*7c478bd9Sstevel@tonic-gate */ 50*7c478bd9Sstevel@tonic-gate cpc_t *__cpc = NULL; 51*7c478bd9Sstevel@tonic-gate mutex_t __cpc_lock; /* protects __cpc handle */ 52*7c478bd9Sstevel@tonic-gate int __cpc_v1_cpuver; /* CPU version in use by CPCv1 client */ 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #ifdef __sparc 55*7c478bd9Sstevel@tonic-gate uint64_t __cpc_v1_pcr; /* last bound %pcr value */ 56*7c478bd9Sstevel@tonic-gate #else 57*7c478bd9Sstevel@tonic-gate uint32_t __cpc_v1_pes[2]; /* last bound %pes values */ 58*7c478bd9Sstevel@tonic-gate #endif /* __sparc */ 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate int 61*7c478bd9Sstevel@tonic-gate __cpc_init(void) 62*7c478bd9Sstevel@tonic-gate { 63*7c478bd9Sstevel@tonic-gate const char *fn = "__cpc_init"; 64*7c478bd9Sstevel@tonic-gate extern cpc_t *__cpc; /* CPC handle for obsolete clients to share */ 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&__cpc_lock); 67*7c478bd9Sstevel@tonic-gate if (__cpc == NULL && (__cpc = cpc_open(CPC_VER_CURRENT)) == NULL) { 68*7c478bd9Sstevel@tonic-gate __cpc_error(fn, dgettext(TEXT_DOMAIN, 69*7c478bd9Sstevel@tonic-gate "Couldn't open CPC library handle\n")); 70*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&__cpc_lock); 71*7c478bd9Sstevel@tonic-gate return (-1); 72*7c478bd9Sstevel@tonic-gate } 73*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&__cpc_lock); 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate return (0); 76*7c478bd9Sstevel@tonic-gate } 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate int 79*7c478bd9Sstevel@tonic-gate cpc_bind_event(cpc_event_t *this, int flags) 80*7c478bd9Sstevel@tonic-gate { 81*7c478bd9Sstevel@tonic-gate cpc_set_t *set; 82*7c478bd9Sstevel@tonic-gate cpc_request_t *rp; 83*7c478bd9Sstevel@tonic-gate int ret; 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate if (this == NULL) { 86*7c478bd9Sstevel@tonic-gate (void) cpc_rele(); 87*7c478bd9Sstevel@tonic-gate return (0); 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate if (__cpc_init() != 0) { 91*7c478bd9Sstevel@tonic-gate errno = ENXIO; 92*7c478bd9Sstevel@tonic-gate return (-1); 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate /* 96*7c478bd9Sstevel@tonic-gate * The cpuver and control fields of the cpc_event_t must be saved off 97*7c478bd9Sstevel@tonic-gate * for later. The user may call cpc_take_sample(), expecting these to 98*7c478bd9Sstevel@tonic-gate * be copied into a different cpc_event_t struct by the kernel. We have 99*7c478bd9Sstevel@tonic-gate * to fake that behavior for CPCv1 clients. 100*7c478bd9Sstevel@tonic-gate */ 101*7c478bd9Sstevel@tonic-gate __cpc_v1_cpuver = this->ce_cpuver; 102*7c478bd9Sstevel@tonic-gate #ifdef __sparc 103*7c478bd9Sstevel@tonic-gate __cpc_v1_pcr = this->ce_pcr; 104*7c478bd9Sstevel@tonic-gate #else 105*7c478bd9Sstevel@tonic-gate __cpc_v1_pes[0] = this->ce_pes[0]; 106*7c478bd9Sstevel@tonic-gate __cpc_v1_pes[1] = this->ce_pes[1]; 107*7c478bd9Sstevel@tonic-gate #endif /* __sparc */ 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate if ((set = __cpc_eventtoset(__cpc, this, flags)) == NULL) { 110*7c478bd9Sstevel@tonic-gate errno = EINVAL; 111*7c478bd9Sstevel@tonic-gate return (-1); 112*7c478bd9Sstevel@tonic-gate } 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate /* 115*7c478bd9Sstevel@tonic-gate * Convert flags to CPC2. 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate if (flags & CPC_BIND_EMT_OVF) { 118*7c478bd9Sstevel@tonic-gate for (rp = set->cs_request; rp != NULL; rp = rp->cr_next) 119*7c478bd9Sstevel@tonic-gate rp->cr_flags |= CPC_OVF_NOTIFY_EMT; 120*7c478bd9Sstevel@tonic-gate flags &= ~CPC_BIND_EMT_OVF; 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate ret = cpc_bind_curlwp(__cpc, set, flags); 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate (void) cpc_set_destroy(__cpc, set); 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate return (ret); 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate int 131*7c478bd9Sstevel@tonic-gate cpc_take_sample(cpc_event_t *this) 132*7c478bd9Sstevel@tonic-gate { 133*7c478bd9Sstevel@tonic-gate this->ce_cpuver = __cpc_v1_cpuver; 134*7c478bd9Sstevel@tonic-gate #ifdef __sparc 135*7c478bd9Sstevel@tonic-gate this->ce_pcr = __cpc_v1_pcr; 136*7c478bd9Sstevel@tonic-gate #else 137*7c478bd9Sstevel@tonic-gate this->ce_pes[0] = __cpc_v1_pes[0]; 138*7c478bd9Sstevel@tonic-gate this->ce_pes[1] = __cpc_v1_pes[1]; 139*7c478bd9Sstevel@tonic-gate #endif /* __sparc */ 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate return (syscall(SYS_cpc, CPC_SAMPLE, -1, this->ce_pic, &this->ce_hrt, 142*7c478bd9Sstevel@tonic-gate &CPC_TICKREG(this), 0)); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate int 146*7c478bd9Sstevel@tonic-gate cpc_count_usr_events(int enable) 147*7c478bd9Sstevel@tonic-gate { 148*7c478bd9Sstevel@tonic-gate return (syscall(SYS_cpc, CPC_USR_EVENTS, -1, (void *)enable, 0)); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate int 152*7c478bd9Sstevel@tonic-gate cpc_count_sys_events(int enable) 153*7c478bd9Sstevel@tonic-gate { 154*7c478bd9Sstevel@tonic-gate return (syscall(SYS_cpc, CPC_SYS_EVENTS, -1, (void *)enable, 0)); 155*7c478bd9Sstevel@tonic-gate } 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate int 158*7c478bd9Sstevel@tonic-gate cpc_rele(void) 159*7c478bd9Sstevel@tonic-gate { 160*7c478bd9Sstevel@tonic-gate return (syscall(SYS_cpc, CPC_RELE, -1, NULL, 0)); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* 164*7c478bd9Sstevel@tonic-gate * See if the system call is working and installed. 165*7c478bd9Sstevel@tonic-gate * 166*7c478bd9Sstevel@tonic-gate * We invoke the system call with nonsense arguments - if it's 167*7c478bd9Sstevel@tonic-gate * there and working correctly, it will return EINVAL. 168*7c478bd9Sstevel@tonic-gate * 169*7c478bd9Sstevel@tonic-gate * (This avoids the user getting a SIGSYS core dump when they attempt 170*7c478bd9Sstevel@tonic-gate * to bind on older hardware) 171*7c478bd9Sstevel@tonic-gate */ 172*7c478bd9Sstevel@tonic-gate int 173*7c478bd9Sstevel@tonic-gate cpc_access(void) 174*7c478bd9Sstevel@tonic-gate { 175*7c478bd9Sstevel@tonic-gate void (*handler)(int); 176*7c478bd9Sstevel@tonic-gate int error = 0; 177*7c478bd9Sstevel@tonic-gate const char fn[] = "access"; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate handler = signal(SIGSYS, SIG_IGN); 180*7c478bd9Sstevel@tonic-gate if (syscall(SYS_cpc, -1, -1, NULL, 0) == -1 && 181*7c478bd9Sstevel@tonic-gate errno != EINVAL) 182*7c478bd9Sstevel@tonic-gate error = errno; 183*7c478bd9Sstevel@tonic-gate (void) signal(SIGSYS, handler); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate switch (error) { 186*7c478bd9Sstevel@tonic-gate case EAGAIN: 187*7c478bd9Sstevel@tonic-gate __cpc_error(fn, dgettext(TEXT_DOMAIN, "Another process may be " 188*7c478bd9Sstevel@tonic-gate "sampling system-wide CPU statistics\n")); 189*7c478bd9Sstevel@tonic-gate break; 190*7c478bd9Sstevel@tonic-gate case ENOSYS: 191*7c478bd9Sstevel@tonic-gate __cpc_error(fn, 192*7c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "CPU performance counters " 193*7c478bd9Sstevel@tonic-gate "are inaccessible on this machine\n")); 194*7c478bd9Sstevel@tonic-gate break; 195*7c478bd9Sstevel@tonic-gate default: 196*7c478bd9Sstevel@tonic-gate __cpc_error(fn, "%s\n", strerror(errno)); 197*7c478bd9Sstevel@tonic-gate break; 198*7c478bd9Sstevel@tonic-gate case 0: 199*7c478bd9Sstevel@tonic-gate return (0); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate errno = error; 203*7c478bd9Sstevel@tonic-gate return (-1); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate /* 207*7c478bd9Sstevel@tonic-gate * To look at the system-wide counters, we have to open the 208*7c478bd9Sstevel@tonic-gate * 'shared' device. Once that device is open, no further contexts 209*7c478bd9Sstevel@tonic-gate * can be installed (though one open is needed per CPU) 210*7c478bd9Sstevel@tonic-gate */ 211*7c478bd9Sstevel@tonic-gate int 212*7c478bd9Sstevel@tonic-gate cpc_shared_open(void) 213*7c478bd9Sstevel@tonic-gate { 214*7c478bd9Sstevel@tonic-gate const char driver[] = CPUDRV_SHARED; 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate return (open(driver, O_RDWR)); 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate void 220*7c478bd9Sstevel@tonic-gate cpc_shared_close(int fd) 221*7c478bd9Sstevel@tonic-gate { 222*7c478bd9Sstevel@tonic-gate (void) cpc_shared_rele(fd); 223*7c478bd9Sstevel@tonic-gate (void) close(fd); 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate int 227*7c478bd9Sstevel@tonic-gate cpc_shared_bind_event(int fd, cpc_event_t *this, int flags) 228*7c478bd9Sstevel@tonic-gate { 229*7c478bd9Sstevel@tonic-gate extern cpc_t *__cpc; 230*7c478bd9Sstevel@tonic-gate cpc_set_t *set; 231*7c478bd9Sstevel@tonic-gate int ret; 232*7c478bd9Sstevel@tonic-gate char *packed_set; 233*7c478bd9Sstevel@tonic-gate size_t packsize; 234*7c478bd9Sstevel@tonic-gate int subcode; 235*7c478bd9Sstevel@tonic-gate __cpc_args_t cpc_args; 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate if (this == NULL) { 238*7c478bd9Sstevel@tonic-gate (void) cpc_shared_rele(fd); 239*7c478bd9Sstevel@tonic-gate return (0); 240*7c478bd9Sstevel@tonic-gate } else if (flags != 0) { 241*7c478bd9Sstevel@tonic-gate errno = EINVAL; 242*7c478bd9Sstevel@tonic-gate return (-1); 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate if (__cpc_init() != 0) { 246*7c478bd9Sstevel@tonic-gate errno = ENXIO; 247*7c478bd9Sstevel@tonic-gate return (-1); 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate if ((set = __cpc_eventtoset(__cpc, this, flags)) == NULL) { 251*7c478bd9Sstevel@tonic-gate errno = EINVAL; 252*7c478bd9Sstevel@tonic-gate return (-1); 253*7c478bd9Sstevel@tonic-gate } 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate __cpc_v1_cpuver = this->ce_cpuver; 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate if ((packed_set = __cpc_pack_set(set, flags, &packsize)) == NULL) { 258*7c478bd9Sstevel@tonic-gate errno = ENOMEM; 259*7c478bd9Sstevel@tonic-gate return (-1); 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate cpc_args.udata1 = packed_set; 263*7c478bd9Sstevel@tonic-gate cpc_args.udata2 = (void *)packsize; 264*7c478bd9Sstevel@tonic-gate cpc_args.udata3 = (void *)&subcode; 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate ret = ioctl(fd, CPCIO_BIND, &cpc_args); 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate free(packed_set); 269*7c478bd9Sstevel@tonic-gate (void) cpc_set_destroy(__cpc, set); 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate return (ret); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate int 275*7c478bd9Sstevel@tonic-gate cpc_shared_take_sample(int fd, cpc_event_t *this) 276*7c478bd9Sstevel@tonic-gate { 277*7c478bd9Sstevel@tonic-gate __cpc_args_t args; 278*7c478bd9Sstevel@tonic-gate 279*7c478bd9Sstevel@tonic-gate args.udata1 = this->ce_pic; 280*7c478bd9Sstevel@tonic-gate args.udata2 = &this->ce_hrt; 281*7c478bd9Sstevel@tonic-gate args.udata3 = &CPC_TICKREG(this); 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate this->ce_cpuver = __cpc_v1_cpuver; 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate return (ioctl(fd, CPCIO_SAMPLE, &args)); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate int 289*7c478bd9Sstevel@tonic-gate cpc_shared_rele(int fd) 290*7c478bd9Sstevel@tonic-gate { 291*7c478bd9Sstevel@tonic-gate return (ioctl(fd, CPCIO_RELE, 0)); 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate int 295*7c478bd9Sstevel@tonic-gate cpc_pctx_bind_event(pctx_t *pctx, id_t lwpid, cpc_event_t *event, int flags) 296*7c478bd9Sstevel@tonic-gate { 297*7c478bd9Sstevel@tonic-gate cpc_set_t *set; 298*7c478bd9Sstevel@tonic-gate int ret; 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate if (event == NULL) 301*7c478bd9Sstevel@tonic-gate return (cpc_pctx_rele(pctx, lwpid)); 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate if (__cpc_init() != 0) { 304*7c478bd9Sstevel@tonic-gate errno = ENXIO; 305*7c478bd9Sstevel@tonic-gate return (-1); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate else if (flags != 0) { 309*7c478bd9Sstevel@tonic-gate errno = EINVAL; 310*7c478bd9Sstevel@tonic-gate return (-1); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate if ((set = __cpc_eventtoset(__cpc, event, flags)) == NULL) { 314*7c478bd9Sstevel@tonic-gate errno = EINVAL; 315*7c478bd9Sstevel@tonic-gate return (-1); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* 319*7c478bd9Sstevel@tonic-gate * The cpuver and control fields of the cpc_event_t must be saved off 320*7c478bd9Sstevel@tonic-gate * for later. The user may call cpc_take_sample(), expecting these to 321*7c478bd9Sstevel@tonic-gate * be copied into a different cpc_event_t struct by the kernel. We have 322*7c478bd9Sstevel@tonic-gate * to fake that behavior for CPCv1 clients. 323*7c478bd9Sstevel@tonic-gate */ 324*7c478bd9Sstevel@tonic-gate __cpc_v1_cpuver = event->ce_cpuver; 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate ret = cpc_bind_pctx(__cpc, pctx, lwpid, set, 0); 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate (void) cpc_set_destroy(__cpc, set); 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate return (ret); 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate int 334*7c478bd9Sstevel@tonic-gate cpc_pctx_take_sample(pctx_t *pctx, id_t lwpid, cpc_event_t *event) 335*7c478bd9Sstevel@tonic-gate { 336*7c478bd9Sstevel@tonic-gate event->ce_cpuver = __cpc_v1_cpuver; 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate return (__pctx_cpc(pctx, __cpc, CPC_SAMPLE, lwpid, event->ce_pic, 339*7c478bd9Sstevel@tonic-gate &event->ce_hrt, &CPC_TICKREG(event), CPC1_BUFSIZE)); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate /* 343*7c478bd9Sstevel@tonic-gate * Given a process context and an lwpid, mark the CPU performance 344*7c478bd9Sstevel@tonic-gate * counter context as invalid. 345*7c478bd9Sstevel@tonic-gate */ 346*7c478bd9Sstevel@tonic-gate int 347*7c478bd9Sstevel@tonic-gate cpc_pctx_invalidate(pctx_t *pctx, id_t lwpid) 348*7c478bd9Sstevel@tonic-gate { 349*7c478bd9Sstevel@tonic-gate return (__pctx_cpc(pctx, __cpc, CPC_INVALIDATE, lwpid, 0, 0, 0, 0)); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Given a process context and an lwpid, remove all our 354*7c478bd9Sstevel@tonic-gate * hardware context from it. 355*7c478bd9Sstevel@tonic-gate */ 356*7c478bd9Sstevel@tonic-gate int 357*7c478bd9Sstevel@tonic-gate cpc_pctx_rele(pctx_t *pctx, id_t lwpid) 358*7c478bd9Sstevel@tonic-gate { 359*7c478bd9Sstevel@tonic-gate return (__pctx_cpc(pctx, __cpc, CPC_RELE, lwpid, 0, 0, 0, 0)); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate static cpc_errfn_t *__cpc_uerrfn; 363*7c478bd9Sstevel@tonic-gate 364*7c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 365*7c478bd9Sstevel@tonic-gate void 366*7c478bd9Sstevel@tonic-gate __cpc_error(const char *fn, const char *fmt, ...) 367*7c478bd9Sstevel@tonic-gate { 368*7c478bd9Sstevel@tonic-gate va_list ap; 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 371*7c478bd9Sstevel@tonic-gate if (__cpc_uerrfn) 372*7c478bd9Sstevel@tonic-gate __cpc_uerrfn(fn, fmt, ap); 373*7c478bd9Sstevel@tonic-gate else { 374*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libcpc: %s: ", fn); 375*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap); 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate va_end(ap); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate void 381*7c478bd9Sstevel@tonic-gate cpc_seterrfn(cpc_errfn_t *errfn) 382*7c478bd9Sstevel@tonic-gate { 383*7c478bd9Sstevel@tonic-gate __cpc_uerrfn = errfn; 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate /* 387*7c478bd9Sstevel@tonic-gate * cpc_version() is only for CPC1 clients. 388*7c478bd9Sstevel@tonic-gate */ 389*7c478bd9Sstevel@tonic-gate uint_t __cpc_workver = CPC_VER_1; 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate uint_t 392*7c478bd9Sstevel@tonic-gate cpc_version(uint_t ver) 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate __cpc_workver = CPC_VER_1; 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate switch (ver) { 397*7c478bd9Sstevel@tonic-gate case CPC_VER_NONE: 398*7c478bd9Sstevel@tonic-gate case CPC_VER_CURRENT: 399*7c478bd9Sstevel@tonic-gate return (CPC_VER_CURRENT); 400*7c478bd9Sstevel@tonic-gate case CPC_VER_1: 401*7c478bd9Sstevel@tonic-gate /* 402*7c478bd9Sstevel@tonic-gate * As long as the client is using cpc_version() at all, it is 403*7c478bd9Sstevel@tonic-gate * a CPCv1 client. We still allow CPCv1 clients to compile on 404*7c478bd9Sstevel@tonic-gate * CPCv2 systems. 405*7c478bd9Sstevel@tonic-gate */ 406*7c478bd9Sstevel@tonic-gate return (CPC_VER_1); 407*7c478bd9Sstevel@tonic-gate } 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate return (CPC_VER_NONE); 410*7c478bd9Sstevel@tonic-gate } 411