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