4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
34 #include <sys/types.h>
40 #define CHARS_PER_REQ 11 /* space required for printing column headers */
43 * These routines are solely used to manage a list of request sets.
49 uint8_t sysonly
; /* All reqs sys-mode only ? */
51 int *picnums
; /* picnum used per req */
57 } *sets
; /* array of events and names */
58 int nelem
; /* size of array */
59 int current
; /* currently bound event in eventset */
60 int smt
; /* Measures physical events on SMT CPU */
61 int has_sysonly_set
; /* Does this group have a system-only set? */
62 cpc_t
*cpc
; /* library handle */
65 static void *emalloc(size_t n
);
68 cpc_setgrp_new(cpc_t
*cpc
, int smt
)
72 sgrp
= emalloc(sizeof (*sgrp
));
76 sgrp
->has_sysonly_set
= 0;
81 * Walker to count the number of requests in a set, and check if any requests
82 * count user-mode events.
86 cpc_setgrp_walker(void *arg
, int index
, const char *event
, uint64_t preset
,
87 uint_t flags
, int nattrs
, const cpc_attr_t
*attrs
)
89 struct setgrp_elem
*se
= arg
;
92 if (flags
& CPC_COUNT_USER
)
97 * Walker to discover the picnums used by the requests in a set.
101 cpc_setgrp_picwalker(void *arg
, int index
, const char *event
, uint64_t preset
,
102 uint_t flags
, int nattrs
, const cpc_attr_t
*attrs
)
107 for (i
= 0; i
< nattrs
; i
++) {
108 if (strncmp(attrs
[i
].ca_name
, "picnum", 7) == 0)
114 picnums
[index
] = (int)attrs
[i
].ca_val
;
118 cpc_setgrp_newset(cpc_setgrp_t
*sgrp
, const char *spec
, int *errcnt
)
121 struct setgrp_elem
*new;
122 char hdr
[CHARS_PER_REQ
+1];
125 if ((set
= cpc_strtoset(sgrp
->cpc
, spec
, sgrp
->smt
)) == NULL
) {
130 if ((new = realloc(sgrp
->sets
, (1 + sgrp
->nelem
) * sizeof (*new)))
132 (void) fprintf(stderr
,
133 gettext("cpc_setgrp: no re memory available\n"));
138 sgrp
->sets
[sgrp
->nelem
].set
= set
;
140 * Count the number of requests in the set we just made. If any requests
141 * in the set have CPC_COUNT_USER in the flags, the sysonly flag will
144 sgrp
->sets
[sgrp
->nelem
].nreqs
= 0;
145 sgrp
->sets
[sgrp
->nelem
].sysonly
= 1;
146 cpc_walk_requests(sgrp
->cpc
, set
, &(sgrp
->sets
[sgrp
->nelem
]),
149 if (sgrp
->sets
[sgrp
->nelem
].sysonly
== 1)
150 sgrp
->has_sysonly_set
= 1;
152 sgrp
->sets
[sgrp
->nelem
].picnums
= emalloc(sgrp
->sets
[sgrp
->nelem
].nreqs
155 sgrp
->sets
[sgrp
->nelem
].hdr
= emalloc((sgrp
->sets
[sgrp
->nelem
].nreqs
*
159 * Find out which picnums the requests are using.
161 cpc_walk_requests(sgrp
->cpc
, set
, sgrp
->sets
[sgrp
->nelem
].picnums
,
162 cpc_setgrp_picwalker
);
164 * Use the picnums we discovered to build a printable header for this
167 sgrp
->sets
[sgrp
->nelem
].hdr
[0] = '\0';
168 for (i
= 0; i
< sgrp
->sets
[sgrp
->nelem
].nreqs
; i
++) {
169 (void) snprintf(hdr
, CHARS_PER_REQ
, "%8s%-2d ", "pic",
170 sgrp
->sets
[sgrp
->nelem
].picnums
[i
]);
171 (void) strncat(sgrp
->sets
[sgrp
->nelem
].hdr
, hdr
,
172 sgrp
->sets
[sgrp
->nelem
].nreqs
* CHARS_PER_REQ
);
174 sgrp
->sets
[sgrp
->nelem
].hdr
[strlen(sgrp
->sets
[sgrp
->nelem
].hdr
)] = '\0';
176 if ((sgrp
->sets
[sgrp
->nelem
].name
= strdup(spec
)) == NULL
) {
177 (void) fprintf(stderr
,
178 gettext("cpc_setgrp: no memory available\n"));
182 if ((sgrp
->sets
[sgrp
->nelem
].data1
= cpc_buf_create(sgrp
->cpc
, set
))
184 (sgrp
->sets
[sgrp
->nelem
].data2
= cpc_buf_create(sgrp
->cpc
, set
))
186 (sgrp
->sets
[sgrp
->nelem
].scratch
= cpc_buf_create(sgrp
->cpc
, set
))
188 (void) fprintf(stderr
,
189 gettext("cpc_setgrp: no memory available\n"));
193 if (sgrp
->current
< 0)
200 cpc_setgrp_getbufs(cpc_setgrp_t
*sgrp
, cpc_buf_t
***data1
, cpc_buf_t
***data2
,
201 cpc_buf_t
***scratch
)
203 if ((uint_t
)sgrp
->current
>= sgrp
->nelem
)
206 *data1
= &(sgrp
->sets
[sgrp
->current
].data1
);
207 *data2
= &(sgrp
->sets
[sgrp
->current
].data2
);
208 *scratch
= &(sgrp
->sets
[sgrp
->current
].scratch
);
210 return (sgrp
->sets
[sgrp
->current
].nreqs
);
214 cpc_setgrp_clone(cpc_setgrp_t
*old
)
218 struct setgrp_elem
*newa
;
220 new = emalloc(sizeof (*new));
221 newa
= emalloc(old
->nelem
* sizeof (*newa
));
223 new->nelem
= old
->nelem
;
224 new->current
= old
->current
;
228 new->has_sysonly_set
= old
->has_sysonly_set
;
229 for (i
= 0; i
< old
->nelem
; i
++) {
230 if ((newa
[i
].set
= cpc_strtoset(old
->cpc
, old
->sets
[i
].name
,
231 old
->smt
)) == NULL
) {
232 (void) fprintf(stderr
,
233 gettext("cpc_setgrp: cpc_strtoset() failed\n"));
236 if ((newa
[i
].name
= strdup(old
->sets
[i
].name
)) == NULL
) {
237 (void) fprintf(stderr
,
238 gettext("cpc_setgrp: no memory available\n"));
241 newa
[i
].sysonly
= old
->sets
[i
].sysonly
;
242 newa
[i
].nreqs
= old
->sets
[i
].nreqs
;
243 newa
[i
].data1
= cpc_buf_create(old
->cpc
, newa
[i
].set
);
244 newa
[i
].data2
= cpc_buf_create(old
->cpc
, newa
[i
].set
);
245 newa
[i
].scratch
= cpc_buf_create(old
->cpc
, newa
[i
].set
);
246 if (newa
[i
].data1
== NULL
|| newa
[i
].data2
== NULL
||
247 newa
[i
].scratch
== NULL
) {
248 (void) fprintf(stderr
,
249 gettext("cpc_setgrp: no memory available\n"));
252 cpc_buf_copy(old
->cpc
, newa
[i
].data1
, old
->sets
[i
].data1
);
253 cpc_buf_copy(old
->cpc
, newa
[i
].data2
, old
->sets
[i
].data2
);
254 cpc_buf_copy(old
->cpc
, newa
[i
].scratch
, old
->sets
[i
].scratch
);
260 cpc_setgrp_delset(cpc_setgrp_t
*sgrp
)
264 if ((uint_t
)sgrp
->current
>= sgrp
->nelem
)
265 sgrp
->current
= sgrp
->nelem
- 1;
266 if (sgrp
->current
< 0)
268 free(sgrp
->sets
[sgrp
->current
].name
);
269 free(sgrp
->sets
[sgrp
->current
].hdr
);
270 free(sgrp
->sets
[sgrp
->current
].picnums
);
271 (void) cpc_buf_destroy(sgrp
->cpc
, sgrp
->sets
[sgrp
->current
].data1
);
272 (void) cpc_buf_destroy(sgrp
->cpc
, sgrp
->sets
[sgrp
->current
].data2
);
273 (void) cpc_buf_destroy(sgrp
->cpc
, sgrp
->sets
[sgrp
->current
].scratch
);
274 for (l
= sgrp
->current
; l
< sgrp
->nelem
- 1; l
++)
275 sgrp
->sets
[l
] = sgrp
->sets
[l
+ 1];
280 cpc_setgrp_free(cpc_setgrp_t
*sgrp
)
284 cpc_setgrp_delset(sgrp
);
291 cpc_setgrp_getset(cpc_setgrp_t
*sgrp
)
293 if ((uint_t
)sgrp
->current
>= sgrp
->nelem
)
295 return (sgrp
->sets
[sgrp
->current
].set
);
299 cpc_setgrp_getname(cpc_setgrp_t
*sgrp
)
301 if ((uint_t
)sgrp
->current
>= sgrp
->nelem
)
303 return (sgrp
->sets
[sgrp
->current
].name
);
307 cpc_setgrp_gethdr(cpc_setgrp_t
*sgrp
)
309 if ((uint_t
)sgrp
->current
>= sgrp
->nelem
)
311 return (sgrp
->sets
[sgrp
->current
].hdr
);
315 cpc_setgrp_numsets(cpc_setgrp_t
*sgrp
)
317 return (sgrp
->nelem
);
321 cpc_setgrp_nextset(cpc_setgrp_t
*sgrp
)
323 if (sgrp
->current
< 0)
326 if (++sgrp
->current
>= sgrp
->nelem
)
329 return (cpc_setgrp_getset(sgrp
));
333 * Put the setgrp pointer back to the beginning of the set
336 cpc_setgrp_reset(cpc_setgrp_t
*sgrp
)
338 if (sgrp
->current
> 0)
343 * Adds the data from the 'data1' buf into the accum setgrp.
346 cpc_setgrp_accum(cpc_setgrp_t
*accum
, cpc_setgrp_t
*sgrp
)
350 cpc_setgrp_reset(accum
);
351 cpc_setgrp_reset(sgrp
);
352 if (accum
->nelem
!= sgrp
->nelem
)
355 for (i
= 0; i
< sgrp
->nelem
; i
++) {
356 if (accum
->sets
[i
].nreqs
!= sgrp
->sets
[i
].nreqs
)
358 cpc_buf_add(sgrp
->cpc
, accum
->sets
[i
].data1
,
359 accum
->sets
[i
].data1
, sgrp
->sets
[i
].data1
);
364 * Returns 1 if all requests in the current set count only system-mode events.
367 cpc_setgrp_sysonly(cpc_setgrp_t
*sgrp
)
369 return ((int)sgrp
->sets
[sgrp
->current
].sysonly
);
373 * Returns 1 if any set in the group is a system-mode-only set.
376 cpc_setgrp_has_sysonly(cpc_setgrp_t
*sgrp
)
378 return (sgrp
->has_sysonly_set
);
382 * If we ever fail to get memory, we print an error message and exit.
388 * Several callers of this routine need zero-filled buffers.
390 void *p
= calloc(1, n
);
393 (void) fprintf(stderr
,
394 gettext("cpc_setgrp: no memory available\n"));