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