]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kperf/kperfbsd.c
xnu-2782.40.9.tar.gz
[apple/xnu.git] / osfmk / kperf / kperfbsd.c
CommitLineData
316670eb
A
1/*
2 * Copyright (c) 2011 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/* sysctl interface for paramters from user-land */
30
31#include <sys/param.h>
32#include <sys/mman.h>
33#include <sys/stat.h>
34#include <sys/sysctl.h>
39236c6e 35#include <sys/kauth.h>
316670eb 36#include <libkern/libkern.h>
39236c6e
A
37#include <kern/debug.h>
38#include <pexpert/pexpert.h>
316670eb
A
39
40#include <kperf/context.h>
41#include <kperf/action.h>
42#include <kperf/timetrigger.h>
43#include <kperf/pet.h>
316670eb
A
44#include <kperf/kperfbsd.h>
45#include <kperf/kperf.h>
46
39236c6e
A
47
48/* a pid which is allowed to control kperf without requiring root access */
49static pid_t blessed_pid = -1;
50static boolean_t blessed_preempt = FALSE;
51
52/* IDs for dispatch from SYSCTL macros */
316670eb
A
53#define REQ_SAMPLING (1)
54#define REQ_ACTION_COUNT (2)
55#define REQ_ACTION_SAMPLERS (3)
56#define REQ_TIMER_COUNT (4)
57#define REQ_TIMER_PERIOD (5)
58#define REQ_TIMER_PET (6)
39236c6e
A
59#define REQ_TIMER_ACTION (7)
60#define REQ_BLESS (8)
61#define REQ_ACTION_USERDATA (9)
62#define REQ_ACTION_FILTER_BY_TASK (10)
63#define REQ_ACTION_FILTER_BY_PID (11)
64#define REQ_KDBG_CALLSTACKS (12)
65#define REQ_PET_IDLE_RATE (13)
66#define REQ_BLESS_PREEMPT (14)
67
68/* simple state variables */
69int kperf_debug_level = 0;
70
71static lck_grp_attr_t *kperf_cfg_lckgrp_attr = NULL;
72static lck_grp_t *kperf_cfg_lckgrp = NULL;
73static lck_mtx_t kperf_cfg_lock;
74static boolean_t kperf_cfg_initted = FALSE;
75
fe8ab488
A
76void kdbg_swap_global_state_pid(pid_t old_pid, pid_t new_pid); /* bsd/kern/kdebug.c */
77
39236c6e
A
78/***************************
79 *
80 * lock init
81 *
82 ***************************/
83
84void
85kperf_bootstrap(void)
86{
87 kperf_cfg_lckgrp_attr = lck_grp_attr_alloc_init();
88 kperf_cfg_lckgrp = lck_grp_alloc_init("kperf cfg",
89 kperf_cfg_lckgrp_attr);
90 lck_mtx_init(&kperf_cfg_lock, kperf_cfg_lckgrp, LCK_ATTR_NULL);
91
92 kperf_cfg_initted = TRUE;
93}
316670eb 94
39236c6e
A
95/***************************
96 *
97 * sysctl handlers
98 *
99 ***************************/
316670eb
A
100
101static int
102sysctl_timer_period( __unused struct sysctl_oid *oidp, struct sysctl_req *req )
103{
104 int error = 0;
105 uint64_t inputs[2], retval;
106 unsigned timer, set = 0;
107
108 /* get 2x 64-bit words */
109 error = SYSCTL_IN( req, inputs, 2*sizeof(inputs[0]) );
110 if(error)
316670eb 111 return (error);
316670eb
A
112
113 /* setup inputs */
114 timer = (unsigned) inputs[0];
115 if( inputs[1] != ~0ULL )
116 set = 1;
117
316670eb
A
118 if( set )
119 {
316670eb
A
120 error = kperf_timer_set_period( timer, inputs[1] );
121 if( error )
122 return error;
123 }
124
125 error = kperf_timer_get_period(timer, &retval);
126 if(error)
316670eb 127 return (error);
316670eb
A
128
129 inputs[1] = retval;
130
131 if( error == 0 )
316670eb 132 error = SYSCTL_OUT( req, inputs, 2*sizeof(inputs[0]) );
39236c6e
A
133
134 return error;
135}
136
137static int
138sysctl_timer_action( __unused struct sysctl_oid *oidp, struct sysctl_req *req )
139{
140 int error = 0;
141 uint64_t inputs[2];
142 uint32_t retval;
143 unsigned timer, set = 0;
144
145 /* get 2x 64-bit words */
146 error = SYSCTL_IN( req, inputs, 2*sizeof(inputs[0]) );
147 if(error)
148 return (error);
149
150 /* setup inputs */
151 timer = (unsigned) inputs[0];
152 if( inputs[1] != ~0ULL )
153 set = 1;
154
155 if( set )
156 {
157 error = kperf_timer_set_action( timer, inputs[1] );
316670eb 158 if( error )
39236c6e 159 return error;
316670eb
A
160 }
161
39236c6e
A
162 error = kperf_timer_get_action(timer, &retval);
163 if(error)
164 return (error);
165
166 inputs[1] = retval;
167
168 if( error == 0 )
169 error = SYSCTL_OUT( req, inputs, 2*sizeof(inputs[0]) );
170
316670eb
A
171 return error;
172}
173
174static int
175sysctl_action_samplers( __unused struct sysctl_oid *oidp,
176 struct sysctl_req *req )
177{
178 int error = 0;
179 uint64_t inputs[3];
180 uint32_t retval;
181 unsigned actionid, set = 0;
182
183 /* get 3x 64-bit words */
184 error = SYSCTL_IN( req, inputs, 3*sizeof(inputs[0]) );
185 if(error)
316670eb 186 return (error);
316670eb
A
187
188 /* setup inputs */
189 set = (unsigned) inputs[0];
190 actionid = (unsigned) inputs[1];
191
192 if( set )
193 {
194 error = kperf_action_set_samplers( actionid, inputs[2] );
195 if( error )
196 return error;
197 }
198
316670eb
A
199 error = kperf_action_get_samplers(actionid, &retval);
200 if(error)
316670eb 201 return (error);
316670eb
A
202
203 inputs[2] = retval;
204
205 if( error == 0 )
39236c6e
A
206 error = SYSCTL_OUT( req, inputs, 3*sizeof(inputs[0]) );
207
208 return error;
209}
210
211static int
212sysctl_action_userdata( __unused struct sysctl_oid *oidp,
213 struct sysctl_req *req )
214{
215 int error = 0;
216 uint64_t inputs[3];
217 uint32_t retval;
218 unsigned actionid, set = 0;
219
220 /* get 3x 64-bit words */
221 error = SYSCTL_IN( req, inputs, 3*sizeof(inputs[0]) );
222 if(error)
223 return (error);
224
225 /* setup inputs */
226 set = (unsigned) inputs[0];
227 actionid = (unsigned) inputs[1];
228
229 if( set )
316670eb 230 {
39236c6e
A
231 error = kperf_action_set_userdata( actionid, inputs[2] );
232 if( error )
233 return error;
234 }
235
236 error = kperf_action_get_userdata(actionid, &retval);
237 if(error)
238 return (error);
239
240 inputs[2] = retval;
241
242 if( error == 0 )
316670eb 243 error = SYSCTL_OUT( req, inputs, 3*sizeof(inputs[0]) );
39236c6e
A
244
245 return error;
246}
247
248static int
249sysctl_action_filter( __unused struct sysctl_oid *oidp,
250 struct sysctl_req *req, int is_task_t )
251{
252 int error = 0;
253 uint64_t inputs[3];
254 int retval;
255 unsigned actionid, set = 0;
256 mach_port_name_t portname;
257 int pid;
258
259 /* get 3x 64-bit words */
260 error = SYSCTL_IN( req, inputs, 3*sizeof(inputs[0]) );
261 if(error)
262 return (error);
263
264 /* setup inputs */
265 set = (unsigned) inputs[0];
266 actionid = (unsigned) inputs[1];
267
268 if( set )
269 {
270 if( is_task_t )
271 {
272 portname = (mach_port_name_t) inputs[2];
273 pid = kperf_port_to_pid(portname);
274 }
275 else
276 pid = (int) inputs[2];
277
278 error = kperf_action_set_filter( actionid, pid );
316670eb 279 if( error )
39236c6e 280 return error;
316670eb
A
281 }
282
39236c6e
A
283 error = kperf_action_get_filter(actionid, &retval);
284 if(error)
285 return (error);
286
287 inputs[2] = retval;
288
289 if( error == 0 )
290 error = SYSCTL_OUT( req, inputs, 3*sizeof(inputs[0]) );
291
316670eb
A
292 return error;
293}
294
295static int
296sysctl_sampling( struct sysctl_oid *oidp, struct sysctl_req *req )
297{
298 int error = 0;
299 uint32_t value = 0;
300
301 /* get the old value and process it */
302 value = kperf_sampling_status();
303
304 /* copy out the old value, get the new value */
305 error = sysctl_handle_int(oidp, &value, 0, req);
306 if (error || !req->newptr)
307 return (error);
308
316670eb
A
309 /* if that worked, and we're writing... */
310 if( value )
311 error = kperf_sampling_enable();
312 else
313 error = kperf_sampling_disable();
314
315 return error;
316}
317
318static int
319sysctl_action_count( struct sysctl_oid *oidp, struct sysctl_req *req )
320{
321 int error = 0;
322 uint32_t value = 0;
323
324 /* get the old value and process it */
325 value = kperf_action_get_count();
326
327 /* copy out the old value, get the new value */
328 error = sysctl_handle_int(oidp, &value, 0, req);
329 if (error || !req->newptr)
330 return (error);
331
316670eb
A
332 /* if that worked, and we're writing... */
333 return kperf_action_set_count(value);
334}
335
336static int
337sysctl_timer_count( struct sysctl_oid *oidp, struct sysctl_req *req )
338{
339 int error = 0;
340 uint32_t value = 0;
341
342 /* get the old value and process it */
343 value = kperf_timer_get_count();
344
345 /* copy out the old value, get the new value */
346 error = sysctl_handle_int(oidp, &value, 0, req);
347 if (error || !req->newptr)
348 return (error);
349
316670eb
A
350 /* if that worked, and we're writing... */
351 return kperf_timer_set_count(value);
352}
353
354static int
355sysctl_timer_pet( struct sysctl_oid *oidp, struct sysctl_req *req )
356{
357 int error = 0;
358 uint32_t value = 0;
359
360 /* get the old value and process it */
361 value = kperf_timer_get_petid();
362
363 /* copy out the old value, get the new value */
364 error = sysctl_handle_int(oidp, &value, 0, req);
365 if (error || !req->newptr)
366 return (error);
367
316670eb
A
368 /* if that worked, and we're writing... */
369 return kperf_timer_set_petid(value);
370}
371
39236c6e
A
372static int
373sysctl_bless( struct sysctl_oid *oidp, struct sysctl_req *req )
374{
375 int error = 0;
376 int value = 0;
377
378 /* get the old value and process it */
379 value = blessed_pid;
380
381 /* copy out the old value, get the new value */
382 error = sysctl_handle_int(oidp, &value, 0, req);
383 if (error || !req->newptr)
384 return (error);
385
386 /* if that worked, and we're writing... */
387 error = kperf_bless_pid(value);
388
389 return error;
390}
391
392static int
393sysctl_bless_preempt( struct sysctl_oid *oidp, struct sysctl_req *req )
394{
395 int error = 0;
396 int value = 0;
397
398 /* get the old value and process it */
399 value = blessed_preempt;
400
401 /* copy out the old value, get the new value */
402 error = sysctl_handle_int(oidp, &value, 0, req);
403 if (error || !req->newptr)
404 return (error);
405
406 /* if that worked, and we're writing... */
407 blessed_preempt = value ? TRUE : FALSE;
408
409 return 0;
410}
411
412
413static int
414sysctl_kdbg_callstacks( struct sysctl_oid *oidp, struct sysctl_req *req )
415{
416 int error = 0;
417 int value = 0;
418
419 /* get the old value and process it */
420 value = kperf_kdbg_get_stacks();
421
422 /* copy out the old value, get the new value */
423 error = sysctl_handle_int(oidp, &value, 0, req);
424 if (error || !req->newptr)
425 return (error);
426
427 /* if that worked, and we're writing... */
428 error = kperf_kdbg_set_stacks(value);
429
430 return error;
431}
432
433static int
434sysctl_pet_idle_rate( struct sysctl_oid *oidp, struct sysctl_req *req )
435{
436 int error = 0;
437 int value = 0;
438
439 /* get the old value and process it */
440 value = kperf_get_pet_idle_rate();
441
442 /* copy out the old value, get the new value */
443 error = sysctl_handle_int(oidp, &value, 0, req);
444 if (error || !req->newptr)
445 return (error);
446
447 /* if that worked, and we're writing... */
448 kperf_set_pet_idle_rate(value);
449
450 return error;
451}
452
316670eb
A
453/*
454 * #define SYSCTL_HANDLER_ARGS (struct sysctl_oid *oidp, \
455 * void *arg1, int arg2, \
456 * struct sysctl_req *req )
457 */
458static int
459kperf_sysctl SYSCTL_HANDLER_ARGS
460{
39236c6e
A
461 int ret;
462
316670eb
A
463 // __unused struct sysctl_oid *unused_oidp = oidp;
464 (void)arg2;
39236c6e
A
465
466 if ( !kperf_cfg_initted )
467 panic("kperf_bootstrap not called");
468
469 ret = kperf_access_check();
470 if (ret) {
471 return ret;
472 }
473
474 lck_mtx_lock(&kperf_cfg_lock);
475
316670eb
A
476 /* which request */
477 switch( (uintptr_t) arg1 )
478 {
479 case REQ_ACTION_COUNT:
39236c6e
A
480 ret = sysctl_action_count( oidp, req );
481 break;
316670eb 482 case REQ_ACTION_SAMPLERS:
39236c6e
A
483 ret = sysctl_action_samplers( oidp, req );
484 break;
485 case REQ_ACTION_USERDATA:
486 ret = sysctl_action_userdata( oidp, req );
487 break;
316670eb 488 case REQ_TIMER_COUNT:
39236c6e
A
489 ret = sysctl_timer_count( oidp, req );
490 break;
316670eb 491 case REQ_TIMER_PERIOD:
39236c6e
A
492 ret = sysctl_timer_period( oidp, req );
493 break;
316670eb 494 case REQ_TIMER_PET:
39236c6e
A
495 ret = sysctl_timer_pet( oidp, req );
496 break;
497 case REQ_TIMER_ACTION:
498 ret = sysctl_timer_action( oidp, req );
499 break;
316670eb 500 case REQ_SAMPLING:
39236c6e
A
501 ret = sysctl_sampling( oidp, req );
502 break;
503 case REQ_KDBG_CALLSTACKS:
504 ret = sysctl_kdbg_callstacks( oidp, req );
505 break;
506 case REQ_ACTION_FILTER_BY_TASK:
507 ret = sysctl_action_filter( oidp, req, 1 );
508 break;
509 case REQ_ACTION_FILTER_BY_PID:
510 ret = sysctl_action_filter( oidp, req, 0 );
511 break;
512 case REQ_PET_IDLE_RATE:
513 ret = sysctl_pet_idle_rate( oidp, req );
514 break;
515 case REQ_BLESS_PREEMPT:
516 ret = sysctl_bless_preempt( oidp, req );
517 break;
316670eb 518 default:
39236c6e
A
519 ret = ENOENT;
520 break;
521 }
522
523 lck_mtx_unlock(&kperf_cfg_lock);
524
525 return ret;
526}
527
528static int
529kperf_sysctl_bless_handler SYSCTL_HANDLER_ARGS
530{
531 int ret;
532 // __unused struct sysctl_oid *unused_oidp = oidp;
533 (void)arg2;
534
535 if ( !kperf_cfg_initted )
536 panic("kperf_bootstrap not called");
537
538 lck_mtx_lock(&kperf_cfg_lock);
539
540 /* which request */
541 if ( (uintptr_t) arg1 == REQ_BLESS )
542 ret = sysctl_bless( oidp, req );
543 else
544 ret = ENOENT;
545
546 lck_mtx_unlock(&kperf_cfg_lock);
547
548 return ret;
549}
550
551
552/***************************
553 *
554 * Access control
555 *
556 ***************************/
557
558/* Validate whether the current process has priviledges to access
559 * kperf (and by extension, trace). Returns 0 if access is granted.
560 */
561int
562kperf_access_check(void)
563{
564 proc_t p = current_proc();
565 proc_t blessed_p;
566 int ret = 0;
567 boolean_t pid_gone = FALSE;
568
569 /* check if the pid that held the lock is gone */
570 blessed_p = proc_find(blessed_pid);
571
572 if ( blessed_p != NULL )
573 proc_rele(blessed_p);
574 else
575 pid_gone = TRUE;
576
577 if ( blessed_pid == -1 || pid_gone ) {
578 /* check for root */
579 ret = suser(kauth_cred_get(), &p->p_acflag);
580 if( !ret )
581 return ret;
582 }
583
584 /* check against blessed pid */
585 if( p->p_pid != blessed_pid )
586 return EACCES;
587
588 /* access granted. */
589 return 0;
590}
591
592/* specify a pid as being able to access kperf/trace, depiste not
593 * being root
594 */
595int
596kperf_bless_pid(pid_t newpid)
597{
598 proc_t p = NULL;
599 pid_t current_pid;
600
601 p = current_proc();
602 current_pid = p->p_pid;
603
604 /* are we allowed to preempt? */
605 if ( (newpid != -1) && (blessed_pid != -1) &&
606 (blessed_pid != current_pid) && !blessed_preempt ) {
607 /* check if the pid that held the lock is gone */
608 p = proc_find(blessed_pid);
609
610 if ( p != NULL ) {
611 proc_rele(p);
612 return EACCES;
613 }
614 }
615
616 /* validate new pid */
617 if ( newpid != -1 ) {
618 p = proc_find(newpid);
619
620 if ( p == NULL )
621 return EINVAL;
622
623 proc_rele(p);
316670eb 624 }
39236c6e 625
fe8ab488
A
626 /* take trace facility as well */
627 kdbg_swap_global_state_pid(blessed_pid, newpid);
628
39236c6e
A
629 blessed_pid = newpid;
630 blessed_preempt = FALSE;
631
632 return 0;
316670eb
A
633}
634
39236c6e
A
635/***************************
636 *
637 * sysctl hooks
638 *
639 ***************************/
640
316670eb
A
641/* root kperf node */
642SYSCTL_NODE(, OID_AUTO, kperf, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
643 "kperf");
644
645/* action sub-section */
646SYSCTL_NODE(_kperf, OID_AUTO, action, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
647 "action");
648
649SYSCTL_PROC(_kperf_action, OID_AUTO, count,
650 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
651 (void*)REQ_ACTION_COUNT,
652 sizeof(int), kperf_sysctl, "I", "Number of actions");
653
654SYSCTL_PROC(_kperf_action, OID_AUTO, samplers,
655 CTLFLAG_RW|CTLFLAG_ANYBODY,
656 (void*)REQ_ACTION_SAMPLERS,
657 3*sizeof(uint64_t), kperf_sysctl, "UQ",
658 "What to sample what a trigger fires an action");
659
39236c6e
A
660SYSCTL_PROC(_kperf_action, OID_AUTO, userdata,
661 CTLFLAG_RW|CTLFLAG_ANYBODY,
662 (void*)REQ_ACTION_USERDATA,
663 3*sizeof(uint64_t), kperf_sysctl, "UQ",
664 "User data to attribute to action");
665
666SYSCTL_PROC(_kperf_action, OID_AUTO, filter_by_task,
667 CTLFLAG_RW|CTLFLAG_ANYBODY,
668 (void*)REQ_ACTION_FILTER_BY_TASK,
669 3*sizeof(uint64_t), kperf_sysctl, "UQ",
670 "Apply a task filter to the action");
671
672SYSCTL_PROC(_kperf_action, OID_AUTO, filter_by_pid,
673 CTLFLAG_RW|CTLFLAG_ANYBODY,
674 (void*)REQ_ACTION_FILTER_BY_PID,
675 3*sizeof(uint64_t), kperf_sysctl, "UQ",
676 "Apply a pid filter to the action");
677
316670eb
A
678/* timer sub-section */
679SYSCTL_NODE(_kperf, OID_AUTO, timer, CTLFLAG_RW|CTLFLAG_LOCKED, 0,
680 "timer");
681
682SYSCTL_PROC(_kperf_timer, OID_AUTO, count,
683 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
684 (void*)REQ_TIMER_COUNT,
685 sizeof(int), kperf_sysctl, "I", "Number of time triggers");
686
687SYSCTL_PROC(_kperf_timer, OID_AUTO, period,
688 CTLFLAG_RW|CTLFLAG_ANYBODY,
689 (void*)REQ_TIMER_PERIOD,
690 2*sizeof(uint64_t), kperf_sysctl, "UQ", "Timer number and period");
691
39236c6e
A
692SYSCTL_PROC(_kperf_timer, OID_AUTO, action,
693 CTLFLAG_RW|CTLFLAG_ANYBODY,
694 (void*)REQ_TIMER_ACTION,
695 2*sizeof(uint64_t), kperf_sysctl, "UQ", "Timer number and actionid");
696
316670eb
A
697SYSCTL_PROC(_kperf_timer, OID_AUTO, pet_timer,
698 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
699 (void*)REQ_TIMER_PET,
700 sizeof(int), kperf_sysctl, "I", "Which timer ID does PET");
701
702/* misc */
703SYSCTL_PROC(_kperf, OID_AUTO, sampling,
704 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
705 (void*)REQ_SAMPLING,
706 sizeof(int), kperf_sysctl, "I", "Sampling running");
707
39236c6e
A
708SYSCTL_PROC(_kperf, OID_AUTO, blessed_pid,
709 CTLTYPE_INT|CTLFLAG_RW, /* must be root */
710 (void*)REQ_BLESS,
711 sizeof(int), kperf_sysctl_bless_handler, "I", "Blessed pid");
712
713SYSCTL_PROC(_kperf, OID_AUTO, blessed_preempt,
714 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
715 (void*)REQ_BLESS_PREEMPT,
716 sizeof(int), kperf_sysctl, "I", "Blessed preemption");
717
718
719SYSCTL_PROC(_kperf, OID_AUTO, kdbg_callstacks,
720 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
721 (void*)REQ_KDBG_CALLSTACKS,
722 sizeof(int), kperf_sysctl, "I", "Generate kdbg callstacks");
723
724SYSCTL_INT(_kperf, OID_AUTO, kdbg_cswitch,
725 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
726 &kperf_cswitch_hook, 0, "Generate context switch info");
727
728SYSCTL_PROC(_kperf, OID_AUTO, pet_idle_rate,
729 CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY,
730 (void*)REQ_PET_IDLE_RATE,
731 sizeof(int), kperf_sysctl, "I", "Rate at which unscheduled threads are forced to be sampled in PET mode");
732
733/* debug */
734SYSCTL_INT(_kperf, OID_AUTO, debug_level, CTLFLAG_RW,
735 &kperf_debug_level, 0, "debug level");
736