xref: /titanic_50/usr/src/lib/libcpc/common/obsoleted.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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