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