8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cpc / common / setgrp.c
blobada70f7e41651a6a86c3b6d719887fa880e86e54
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <libintl.h>
34 #include <sys/types.h>
37 #include <libcpc.h>
38 #include "cpucmds.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.
46 struct __cpc_setgrp {
47 struct setgrp_elem {
48 cpc_set_t *set;
49 uint8_t sysonly; /* All reqs sys-mode only ? */
50 int nreqs;
51 int *picnums; /* picnum used per req */
52 cpc_buf_t *data1;
53 cpc_buf_t *data2;
54 cpc_buf_t *scratch;
55 char *name;
56 char *hdr;
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);
67 cpc_setgrp_t *
68 cpc_setgrp_new(cpc_t *cpc, int smt)
70 cpc_setgrp_t *sgrp;
72 sgrp = emalloc(sizeof (*sgrp));
73 sgrp->current = -1;
74 sgrp->cpc = cpc;
75 sgrp->smt = smt;
76 sgrp->has_sysonly_set = 0;
77 return (sgrp);
81 * Walker to count the number of requests in a set, and check if any requests
82 * count user-mode events.
84 /*ARGSUSED*/
85 static void
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;
91 se->nreqs++;
92 if (flags & CPC_COUNT_USER)
93 se->sysonly = 0;
97 * Walker to discover the picnums used by the requests in a set.
99 /*ARGSUSED*/
100 static void
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)
104 int *picnums = arg;
105 int i;
107 for (i = 0; i < nattrs; i++) {
108 if (strncmp(attrs[i].ca_name, "picnum", 7) == 0)
109 break;
111 if (i == nattrs)
112 picnums[index] = -1;
114 picnums[index] = (int)attrs[i].ca_val;
117 cpc_setgrp_t *
118 cpc_setgrp_newset(cpc_setgrp_t *sgrp, const char *spec, int *errcnt)
120 cpc_set_t *set;
121 struct setgrp_elem *new;
122 char hdr[CHARS_PER_REQ+1];
123 int i;
125 if ((set = cpc_strtoset(sgrp->cpc, spec, sgrp->smt)) == NULL) {
126 *errcnt += 1;
127 return (NULL);
130 if ((new = realloc(sgrp->sets, (1 + sgrp->nelem) * sizeof (*new)))
131 == NULL) {
132 (void) fprintf(stderr,
133 gettext("cpc_setgrp: no re memory available\n"));
134 exit(0);
137 sgrp->sets = new;
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
142 * be cleared.
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]),
147 cpc_setgrp_walker);
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
153 * sizeof (int));
155 sgrp->sets[sgrp->nelem].hdr = emalloc((sgrp->sets[sgrp->nelem].nreqs *
156 CHARS_PER_REQ) + 1);
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
165 * set.
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"));
179 exit(0);
182 if ((sgrp->sets[sgrp->nelem].data1 = cpc_buf_create(sgrp->cpc, set))
183 == NULL ||
184 (sgrp->sets[sgrp->nelem].data2 = cpc_buf_create(sgrp->cpc, set))
185 == NULL ||
186 (sgrp->sets[sgrp->nelem].scratch = cpc_buf_create(sgrp->cpc, set))
187 == NULL) {
188 (void) fprintf(stderr,
189 gettext("cpc_setgrp: no memory available\n"));
190 exit(0);
193 if (sgrp->current < 0)
194 sgrp->current = 0;
195 sgrp->nelem++;
196 return (sgrp);
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)
204 return (-1);
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);
213 cpc_setgrp_t *
214 cpc_setgrp_clone(cpc_setgrp_t *old)
216 int i;
217 cpc_setgrp_t *new;
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;
225 new->cpc = old->cpc;
226 new->sets = newa;
227 new->smt = old->smt;
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"));
234 exit(0);
236 if ((newa[i].name = strdup(old->sets[i].name)) == NULL) {
237 (void) fprintf(stderr,
238 gettext("cpc_setgrp: no memory available\n"));
239 exit(0);
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"));
250 exit(0);
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);
256 return (new);
259 static void
260 cpc_setgrp_delset(cpc_setgrp_t *sgrp)
262 int l;
264 if ((uint_t)sgrp->current >= sgrp->nelem)
265 sgrp->current = sgrp->nelem - 1;
266 if (sgrp->current < 0)
267 return;
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];
276 sgrp->nelem--;
279 void
280 cpc_setgrp_free(cpc_setgrp_t *sgrp)
282 if (sgrp->sets) {
283 while (sgrp->nelem)
284 cpc_setgrp_delset(sgrp);
285 free(sgrp->sets);
287 free(sgrp);
290 cpc_set_t *
291 cpc_setgrp_getset(cpc_setgrp_t *sgrp)
293 if ((uint_t)sgrp->current >= sgrp->nelem)
294 return (NULL);
295 return (sgrp->sets[sgrp->current].set);
298 const char *
299 cpc_setgrp_getname(cpc_setgrp_t *sgrp)
301 if ((uint_t)sgrp->current >= sgrp->nelem)
302 return (NULL);
303 return (sgrp->sets[sgrp->current].name);
306 const char *
307 cpc_setgrp_gethdr(cpc_setgrp_t *sgrp)
309 if ((uint_t)sgrp->current >= sgrp->nelem)
310 return (NULL);
311 return (sgrp->sets[sgrp->current].hdr);
315 cpc_setgrp_numsets(cpc_setgrp_t *sgrp)
317 return (sgrp->nelem);
320 cpc_set_t *
321 cpc_setgrp_nextset(cpc_setgrp_t *sgrp)
323 if (sgrp->current < 0)
324 return (NULL);
326 if (++sgrp->current >= sgrp->nelem)
327 sgrp->current = 0;
329 return (cpc_setgrp_getset(sgrp));
333 * Put the setgrp pointer back to the beginning of the set
335 void
336 cpc_setgrp_reset(cpc_setgrp_t *sgrp)
338 if (sgrp->current > 0)
339 sgrp->current = 0;
343 * Adds the data from the 'data1' buf into the accum setgrp.
345 void
346 cpc_setgrp_accum(cpc_setgrp_t *accum, cpc_setgrp_t *sgrp)
348 int i;
350 cpc_setgrp_reset(accum);
351 cpc_setgrp_reset(sgrp);
352 if (accum->nelem != sgrp->nelem)
353 return;
355 for (i = 0; i < sgrp->nelem; i++) {
356 if (accum->sets[i].nreqs != sgrp->sets[i].nreqs)
357 return;
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.
384 static void *
385 emalloc(size_t n)
388 * Several callers of this routine need zero-filled buffers.
390 void *p = calloc(1, n);
392 if (p == NULL) {
393 (void) fprintf(stderr,
394 gettext("cpc_setgrp: no memory available\n"));
395 exit(0);
398 return (p);