]> git.saurik.com Git - apple/xnu.git/blob - osfmk/profiling/profile-kgmon.c
xnu-792.6.56.tar.gz
[apple/xnu.git] / osfmk / profiling / profile-kgmon.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 * @OSF_COPYRIGHT@
25 */
26 /*
27 * HISTORY
28 *
29 * Revision 1.1.1.1 1998/09/22 21:05:49 wsanchez
30 * Import of Mac OS X kernel (~semeria)
31 *
32 * Revision 1.1.1.1 1998/03/07 02:26:08 wsanchez
33 * Import of OSF Mach kernel (~mburg)
34 *
35 * Revision 1.1.5.1 1995/01/06 19:54:04 devrcs
36 * mk6 CR668 - 1.3b26 merge
37 * new file for mk6
38 * [1994/10/12 22:25:34 dwm]
39 *
40 * Revision 1.1.2.1 1994/04/08 17:52:05 meissner
41 * Add callback function to _profile_kgmon.
42 * [1994/02/16 22:38:31 meissner]
43 *
44 * _profile_kgmon now returns pointer to area, doesn't do move itself.
45 * [1994/02/11 16:52:17 meissner]
46 *
47 * Move all printfs into if (pv->debug) { ... } blocks.
48 * Add debug printfs protected by if (pv->debug) for all error conditions.
49 * Add code to reset profiling information.
50 * Add code to get/set debug flag.
51 * Expand copyright.
52 * [1994/02/07 12:41:14 meissner]
53 *
54 * Add support to copy arbitrary regions.
55 * Delete several of the KGMON_GET commands, now that arb. regions are supported.
56 * Explicitly call _profile_update_stats before dumping vars or stats.
57 * [1994/02/03 00:59:05 meissner]
58 *
59 * Combine _profile_{vars,stats,md}; Allow more than one _profile_vars.
60 * [1994/02/01 12:04:09 meissner]
61 *
62 * CR 10198 - Initial version.
63 * [1994/01/28 23:33:37 meissner]
64 *
65 * $EndLog$
66 */
67
68 #include <profiling/profile-internal.h>
69
70 #ifdef MACH_KERNEL
71 #include <profiling/machine/profile-md.h>
72 #endif
73
74 #ifndef PROFILE_VARS
75 #define PROFILE_VARS(cpu) (&_profile_vars)
76 #endif
77
78 extern int printf(const char *, ...);
79
80 \f
81 /*
82 * Kgmon interface. This returns the count of bytes moved if everything was ok,
83 * or -1 if there were errors.
84 */
85
86 long
87 _profile_kgmon(int write,
88 size_t count,
89 long indx,
90 int max_cpus,
91 void **p_ptr,
92 void (*control_func)(kgmon_control_t))
93 {
94 kgmon_control_t kgmon;
95 int cpu;
96 int error = 0;
97 int i;
98 struct profile_vars *pv;
99 static struct callback dummy_callback;
100
101 *p_ptr = (void *)0;
102
103 /*
104 * If the number passed is not within bounds, just copy the data directly.
105 */
106
107 if (!LEGAL_KGMON(indx)) {
108 *p_ptr = (void *)indx;
109 if (!write) {
110 if (PROFILE_VARS(0)->debug) {
111 printf("_profile_kgmon: copy %5ld bytes, from 0x%lx\n",
112 (long)count,
113 (long)indx);
114 }
115
116 } else {
117 if (PROFILE_VARS(0)->debug) {
118 printf("_profile_kgmon: copy %5ld bytes, to 0x%lx\n",
119 (long)count,
120 (long)indx);
121 }
122 }
123
124 return count;
125 }
126
127 /*
128 * Decode the record number into the component pieces.
129 */
130
131 DECODE_KGMON(indx, kgmon, cpu);
132
133 if (PROFILE_VARS(0)->debug) {
134 printf("_profile_kgmon: start: kgmon control = %2d, cpu = %d, count = %ld\n",
135 kgmon, cpu, (long)count);
136 }
137
138 /* Validate the CPU number */
139 if (cpu < 0 || cpu >= max_cpus) {
140 if (PROFILE_VARS(0)->debug) {
141 printf("KGMON, bad cpu %d\n", cpu);
142 }
143
144 return -1;
145
146 } else {
147 pv = PROFILE_VARS(cpu);
148
149 if (!write) {
150 switch (kgmon) {
151 default:
152 if (PROFILE_VARS(0)->debug) {
153 printf("Unknown KGMON read command\n");
154 }
155
156 error = -1;
157 break;
158
159 case KGMON_GET_STATUS: /* return whether or not profiling is active */
160 if (cpu != 0) {
161 if (PROFILE_VARS(0)->debug) {
162 printf("KGMON_GET_STATUS: cpu = %d\n", cpu);
163 }
164
165 error = -1;
166 break;
167 }
168
169 if (count != sizeof(pv->active)) {
170 if (PROFILE_VARS(0)->debug) {
171 printf("KGMON_GET_STATUS: count = %ld, should be %ld\n",
172 (long)count,
173 (long)sizeof(pv->active));
174 }
175
176 error = -1;
177 break;
178 }
179
180 *p_ptr = (void *)&pv->active;
181 break;
182
183 case KGMON_GET_DEBUG: /* return whether or not debugging is active */
184 if (cpu != 0) {
185 if (PROFILE_VARS(0)->debug) {
186 printf("KGMON_GET_DEBUG: cpu = %d\n", cpu);
187 }
188
189 error = -1;
190 break;
191 }
192
193 if (count != sizeof(pv->debug)) {
194 if (PROFILE_VARS(0)->debug) {
195 printf("KGMON_GET_DEBUG: count = %ld, should be %ld\n",
196 (long)count,
197 (long)sizeof(pv->active));
198 }
199
200 error = -1;
201 break;
202 }
203
204 *p_ptr = (void *)&pv->debug;
205 break;
206
207 case KGMON_GET_PROFILE_VARS: /* return the _profile_vars structure */
208 if (count != sizeof(struct profile_vars)) {
209 if (PROFILE_VARS(0)->debug) {
210 printf("KGMON_GET_PROFILE_VARS: count = %ld, should be %ld\n",
211 (long)count,
212 (long)sizeof(struct profile_vars));
213 }
214
215 error = -1;
216 break;
217 }
218
219 _profile_update_stats(pv);
220 *p_ptr = (void *)pv;
221 break;
222
223 case KGMON_GET_PROFILE_STATS: /* return the _profile_stats structure */
224 if (count != sizeof(struct profile_stats)) {
225 if (PROFILE_VARS(0)->debug) {
226 printf("KGMON_GET_PROFILE_STATS: count = %ld, should be = %ld\n",
227 (long)count,
228 (long)sizeof(struct profile_stats));
229 }
230
231 error = -1;
232 break;
233 }
234
235 _profile_update_stats(pv);
236 *p_ptr = (void *)&pv->stats;
237 break;
238 }
239
240 } else {
241 switch (kgmon) {
242 default:
243 if (PROFILE_VARS(0)->debug) {
244 printf("Unknown KGMON write command\n");
245 }
246
247 error = -1;
248 break;
249
250 case KGMON_SET_PROFILE_ON: /* turn on profiling */
251 if (cpu != 0) {
252 if (PROFILE_VARS(0)->debug) {
253 printf("KGMON_SET_PROFILE_ON, cpu = %d\n", cpu);
254 }
255
256 error = -1;
257 break;
258 }
259
260 if (!PROFILE_VARS(0)->active) {
261 for (i = 0; i < max_cpus; i++) {
262 PROFILE_VARS(i)->active = 1;
263 }
264
265 if (control_func) {
266 (*control_func)(kgmon);
267 }
268
269 _profile_md_start();
270 }
271
272 count = 0;
273 break;
274
275 case KGMON_SET_PROFILE_OFF: /* turn off profiling */
276 if (cpu != 0) {
277 if (PROFILE_VARS(0)->debug) {
278 printf("KGMON_SET_PROFILE_OFF, cpu = %d\n", cpu);
279 }
280
281 error = -1;
282 break;
283 }
284
285 if (PROFILE_VARS(0)->active) {
286 for (i = 0; i < max_cpus; i++) {
287 PROFILE_VARS(i)->active = 0;
288 }
289
290 _profile_md_stop();
291
292 if (control_func) {
293 (*control_func)(kgmon);
294 }
295 }
296
297 count = 0;
298 break;
299
300 case KGMON_SET_PROFILE_RESET: /* reset profiling */
301 if (cpu != 0) {
302 if (PROFILE_VARS(0)->debug) {
303 printf("KGMON_SET_PROFILE_RESET, cpu = %d\n", cpu);
304 }
305
306 error = -1;
307 break;
308 }
309
310 for (i = 0; i < max_cpus; i++) {
311 _profile_reset(PROFILE_VARS(i));
312 }
313
314 if (control_func) {
315 (*control_func)(kgmon);
316 }
317
318 count = 0;
319 break;
320
321 case KGMON_SET_DEBUG_ON: /* turn on profiling */
322 if (cpu != 0) {
323 if (PROFILE_VARS(0)->debug) {
324 printf("KGMON_SET_DEBUG_ON, cpu = %d\n", cpu);
325 }
326
327 error = -1;
328 break;
329 }
330
331 if (!PROFILE_VARS(0)->debug) {
332 for (i = 0; i < max_cpus; i++) {
333 PROFILE_VARS(i)->debug = 1;
334 }
335
336 if (control_func) {
337 (*control_func)(kgmon);
338 }
339 }
340
341 count = 0;
342 break;
343
344 case KGMON_SET_DEBUG_OFF: /* turn off profiling */
345 if (cpu != 0) {
346 if (PROFILE_VARS(0)->debug) {
347 printf("KGMON_SET_DEBUG_OFF, cpu = %d\n", cpu);
348 }
349
350 error = -1;
351 break;
352 }
353
354 if (PROFILE_VARS(0)->debug) {
355 for (i = 0; i < max_cpus; i++) {
356 PROFILE_VARS(i)->debug = 0;
357 }
358
359 if (control_func) {
360 (*control_func)(kgmon);
361 }
362 }
363
364 count = 0;
365 break;
366 }
367 }
368 }
369
370 if (error) {
371 if (PROFILE_VARS(0)->debug) {
372 printf("_profile_kgmon: done: kgmon control = %2d, cpu = %d, error = %d\n",
373 kgmon, cpu, error);
374 }
375
376 return -1;
377 }
378
379 if (PROFILE_VARS(0)->debug) {
380 printf("_profile_kgmon: done: kgmon control = %2d, cpu = %d, count = %ld\n",
381 kgmon, cpu, (long)count);
382 }
383
384 return count;
385 }