]> git.saurik.com Git - apple/xnu.git/blob - osfmk/profiling/profile-kgmon.c
xnu-4903.270.47.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 /*
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 } else {
118 if (PROFILE_VARS(0)->debug) {
119 printf("_profile_kgmon: copy %5ld bytes, to 0x%lx\n",
120 (long)count,
121 (long)indx);
122 }
123 }
124
125 return count;
126 }
127
128 /*
129 * Decode the record number into the component pieces.
130 */
131
132 DECODE_KGMON(indx, kgmon, cpu);
133
134 if (PROFILE_VARS(0)->debug) {
135 printf("_profile_kgmon: start: kgmon control = %2d, cpu = %d, count = %ld\n",
136 kgmon, cpu, (long)count);
137 }
138
139 /* Validate the CPU number */
140 if (cpu < 0 || cpu >= max_cpus) {
141 if (PROFILE_VARS(0)->debug) {
142 printf("KGMON, bad cpu %d\n", cpu);
143 }
144
145 return -1;
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 } else {
240 switch (kgmon) {
241 default:
242 if (PROFILE_VARS(0)->debug) {
243 printf("Unknown KGMON write command\n");
244 }
245
246 error = -1;
247 break;
248
249 case KGMON_SET_PROFILE_ON: /* turn on profiling */
250 if (cpu != 0) {
251 if (PROFILE_VARS(0)->debug) {
252 printf("KGMON_SET_PROFILE_ON, cpu = %d\n", cpu);
253 }
254
255 error = -1;
256 break;
257 }
258
259 if (!PROFILE_VARS(0)->active) {
260 for (i = 0; i < max_cpus; i++) {
261 PROFILE_VARS(i)->active = 1;
262 }
263
264 if (control_func) {
265 (*control_func)(kgmon);
266 }
267
268 _profile_md_start();
269 }
270
271 count = 0;
272 break;
273
274 case KGMON_SET_PROFILE_OFF: /* turn off profiling */
275 if (cpu != 0) {
276 if (PROFILE_VARS(0)->debug) {
277 printf("KGMON_SET_PROFILE_OFF, cpu = %d\n", cpu);
278 }
279
280 error = -1;
281 break;
282 }
283
284 if (PROFILE_VARS(0)->active) {
285 for (i = 0; i < max_cpus; i++) {
286 PROFILE_VARS(i)->active = 0;
287 }
288
289 _profile_md_stop();
290
291 if (control_func) {
292 (*control_func)(kgmon);
293 }
294 }
295
296 count = 0;
297 break;
298
299 case KGMON_SET_PROFILE_RESET: /* reset profiling */
300 if (cpu != 0) {
301 if (PROFILE_VARS(0)->debug) {
302 printf("KGMON_SET_PROFILE_RESET, cpu = %d\n", cpu);
303 }
304
305 error = -1;
306 break;
307 }
308
309 for (i = 0; i < max_cpus; i++) {
310 _profile_reset(PROFILE_VARS(i));
311 }
312
313 if (control_func) {
314 (*control_func)(kgmon);
315 }
316
317 count = 0;
318 break;
319
320 case KGMON_SET_DEBUG_ON: /* turn on profiling */
321 if (cpu != 0) {
322 if (PROFILE_VARS(0)->debug) {
323 printf("KGMON_SET_DEBUG_ON, cpu = %d\n", cpu);
324 }
325
326 error = -1;
327 break;
328 }
329
330 if (!PROFILE_VARS(0)->debug) {
331 for (i = 0; i < max_cpus; i++) {
332 PROFILE_VARS(i)->debug = 1;
333 }
334
335 if (control_func) {
336 (*control_func)(kgmon);
337 }
338 }
339
340 count = 0;
341 break;
342
343 case KGMON_SET_DEBUG_OFF: /* turn off profiling */
344 if (cpu != 0) {
345 if (PROFILE_VARS(0)->debug) {
346 printf("KGMON_SET_DEBUG_OFF, cpu = %d\n", cpu);
347 }
348
349 error = -1;
350 break;
351 }
352
353 if (PROFILE_VARS(0)->debug) {
354 for (i = 0; i < max_cpus; i++) {
355 PROFILE_VARS(i)->debug = 0;
356 }
357
358 if (control_func) {
359 (*control_func)(kgmon);
360 }
361 }
362
363 count = 0;
364 break;
365 }
366 }
367 }
368
369 if (error) {
370 if (PROFILE_VARS(0)->debug) {
371 printf("_profile_kgmon: done: kgmon control = %2d, cpu = %d, error = %d\n",
372 kgmon, cpu, error);
373 }
374
375 return -1;
376 }
377
378 if (PROFILE_VARS(0)->debug) {
379 printf("_profile_kgmon: done: kgmon control = %2d, cpu = %d, count = %ld\n",
380 kgmon, cpu, (long)count);
381 }
382
383 return count;
384 }