8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cpc / common / caps.c
blob5ed12182d378aae63ededf92289dbf90e2ad3712
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #define __EXTENSIONS__ /* header bug! strtok_r is overly hidden */
27 #include <string.h>
28 #include <strings.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <libintl.h>
34 #include <libcpc.h>
36 #include "cpucmds.h"
38 struct args {
39 FILE *fp;
40 int colnum;
41 int margin;
44 struct evlist {
45 char *list;
46 int size;
49 #define MAX_RHS_COLUMN 76
50 #define EVENT_MARGIN 17
51 #define ATTR_MARGIN 20
53 /*ARGSUSED*/
54 static void
55 list_cap(void *arg, uint_t regno, const char *name)
57 struct args *args = arg;
58 int i;
60 if ((args->colnum + strlen(name) + 1) > MAX_RHS_COLUMN) {
61 (void) fprintf(args->fp, "\n");
62 for (i = 0; i < args->margin; i++)
63 (void) fprintf(args->fp, " ");
64 args->colnum = args->margin;
66 args->colnum += fprintf(args->fp, "%s ", name);
69 static void
70 list_attr(void *arg, const char *name)
73 * The following attributes are used by the commands but should not be
74 * reported to the user, since they may not be specified directly.
76 if (strncmp(name, "picnum", 7) == 0 ||
77 strncmp(name, "count_sibling_usr", 18) == 0 ||
78 strncmp(name, "count_sibling_sys", 18) == 0)
79 return;
81 list_cap(arg, 0, name);
84 static void *
85 emalloc(size_t size)
87 void *ptr;
89 if ((ptr = malloc(size)) == NULL) {
90 (void) fprintf(stderr, gettext("no memory available\n"));
91 exit(1);
94 return (ptr);
98 * Used by allpics_equal().
100 /*ARGSUSED*/
101 static void
102 cap_walker(void *arg, uint_t regno, const char *name)
104 struct evlist *list = arg;
106 list->size += strlen(name);
107 if ((list->list = realloc(list->list, list->size + 1)) == NULL) {
108 (void) fprintf(stderr, gettext("no memory available\n"));
109 exit(1);
112 (void) strcat(list->list, name);
116 * Returns 1 if all counters on this chip can count all possible events.
118 static int
119 allpics_equal(cpc_t *cpc)
121 int npics = cpc_npic(cpc);
122 int i;
123 struct evlist **lists;
124 int ret = 1;
126 lists = emalloc(npics * sizeof (struct evlist *));
128 for (i = 0; i < npics; i++) {
129 lists[i] = emalloc(sizeof (struct evlist));
130 lists[i]->size = 0;
131 lists[i]->list = emalloc(1);
132 lists[i]->list[0] = '\0';
133 cpc_walk_events_pic(cpc, i, lists[i], cap_walker);
136 for (i = 1; i < npics; i++)
137 if (lists[i]->size != lists[0]->size ||
138 strncmp(lists[i]->list, lists[0]->list,
139 lists[0]->size) != 0) {
140 ret = 0;
141 break;
144 for (i = 0; i < npics; i++) {
145 free(lists[i]->list);
146 free(lists[i]);
148 free(lists);
150 return (ret);
154 capabilities(cpc_t *cpc, FILE *fp)
156 struct args _args, *args = &_args;
157 char *text, *tok, *cp;
158 const char *ccp;
159 int npic = cpc_npic(cpc);
160 int i, pics_equal = allpics_equal(cpc);
162 args->fp = fp;
164 if ((ccp = cpc_cciname(cpc)) == NULL)
165 ccp = "No information available";
166 (void) fprintf(args->fp, "\t%s: %s\n\n",
167 gettext("CPU performance counter interface"), ccp);
169 (void) fprintf(args->fp, gettext("\tevent specification syntax:\n"));
171 (void) fprintf(args->fp, "\t[picn=]<eventn>[,attr[n][=<val>]]"
172 "[,[picn=]<eventn>[,attr[n][=<val>]],...]\n");
174 (void) fprintf(args->fp, gettext("\n\tGeneric Events:\n"));
176 if (pics_equal) {
177 args->margin = args->colnum = EVENT_MARGIN;
178 (void) fprintf(args->fp, "\n\tevent[0-%d]: ", npic - 1);
179 cpc_walk_generic_events_pic(cpc, 0, args, list_cap);
180 (void) fprintf(args->fp, "\n");
181 } else {
182 args->margin = EVENT_MARGIN;
183 for (i = 0; i < npic; i++) {
184 (void) fprintf(args->fp, "\n\tevent%d: ", i);
185 if (i < 10) (void) fprintf(args->fp, " ");
186 args->colnum = EVENT_MARGIN;
187 cpc_walk_generic_events_pic(cpc, i, args, list_cap);
188 (void) fprintf(args->fp, "\n");
192 (void) fprintf(args->fp, gettext("\n\tSee generic_events(3CPC) for"
193 " descriptions of these events\n\n"));
195 (void) fprintf(args->fp, gettext("\tPlatform Specific Events:\n"));
197 if (pics_equal) {
198 args->margin = args->colnum = EVENT_MARGIN;
199 (void) fprintf(args->fp, "\n\tevent[0-%d]: ", npic - 1);
200 cpc_walk_events_pic(cpc, 0, args, list_cap);
201 (void) fprintf(args->fp, "\n");
202 } else {
203 args->margin = EVENT_MARGIN;
204 for (i = 0; i < npic; i++) {
205 (void) fprintf(args->fp, "\n\tevent%d: ", i);
206 if (i < 10) (void) fprintf(args->fp, " ");
207 args->colnum = EVENT_MARGIN;
208 cpc_walk_events_pic(cpc, i, args, list_cap);
209 (void) fprintf(args->fp, "\n");
213 (void) fprintf(args->fp, "\n\tattributes: ");
214 args->colnum = args->margin = ATTR_MARGIN;
215 cpc_walk_attrs(cpc, args, list_attr);
217 * In addition to the attributes published by the kernel, we allow the
218 * user to specify two additional tokens on all platforms. List them
219 * here.
221 list_cap(args, 0, "nouser");
222 list_cap(args, 0, "sys");
223 (void) fprintf(args->fp, "\n\n\t");
224 args->colnum = 8;
226 if ((ccp = cpc_cpuref(cpc)) == NULL)
227 ccp = "No information available";
228 if ((text = strdup(ccp)) == NULL) {
229 (void) fprintf(stderr, gettext("no memory available.\n"));
230 exit(1);
232 for (cp = strtok_r(text, " ", &tok);
233 cp != NULL; cp = strtok_r(NULL, " ", &tok)) {
234 if ((args->colnum + strlen(cp) + 1) > MAX_RHS_COLUMN) {
235 (void) fprintf(args->fp, "\n\t");
236 args->colnum = 8;
238 args->colnum += fprintf(args->fp, "%s ", cp);
240 (void) fprintf(args->fp, "\n");
241 free(text);
243 return (0);
247 * Returns 1 on SMT processors which do not have full CPC hardware for each
248 * logical processor.
251 smt_limited_cpc_hw(cpc_t *cpc)
253 if (strcmp(cpc_cciname(cpc), "Pentium 4 with HyperThreading") == 0)
254 return (1);
255 return (0);