]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kperf/kperf.c
xnu-2050.48.11.tar.gz
[apple/xnu.git] / osfmk / kperf / kperf.c
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 #include <mach/mach_types.h>
29 #include <kern/thread.h>
30 #include <kern/machine.h>
31 #include <kern/kalloc.h>
32 #include <sys/errno.h>
33
34 #include <kperf/filter.h>
35 #include <kperf/sample.h>
36 #include <kperf/kperfbsd.h>
37 #include <kperf/pet.h>
38 #include <kperf/action.h>
39 #include <kperf/kperf.h>
40 #include <kperf/timetrigger.h>
41
42 /** misc functions **/
43 #include <chud/chud_xnu.h> /* XXX: should bust this out */
44
45 static struct kperf_sample *intr_samplev = NULL;
46 static unsigned intr_samplec = 0;
47 static unsigned sampling_status = KPERF_SAMPLING_OFF;
48 static unsigned kperf_initted = 0;
49
50
51 extern void (*chudxnu_thread_ast_handler)(thread_t);
52
53 struct kperf_sample*
54 kperf_intr_sample_buffer(void)
55 {
56 unsigned ncpu = chudxnu_cpu_number();
57
58 // XXX: assert?
59 if( ncpu >= intr_samplec )
60 return NULL;
61
62 return &intr_samplev[ncpu];
63 }
64
65 /* setup interrupt sample buffers */
66 int
67 kperf_init(void)
68 {
69 unsigned ncpus = 0;
70
71 if( kperf_initted )
72 return 0;
73
74 /* get number of cpus */
75 ncpus = machine_info.logical_cpu_max;
76
77 /* make the CPU array
78 * FIXME: cache alignment
79 */
80 intr_samplev = kalloc( ncpus * sizeof(*intr_samplev));
81
82 if( intr_samplev == NULL )
83 return ENOMEM;
84
85 /* clear it */
86 bzero( intr_samplev, ncpus * sizeof(*intr_samplev) );
87
88 chudxnu_thread_ast_handler = kperf_thread_ast_handler;
89
90 /* we're done */
91 intr_samplec = ncpus;
92 kperf_initted = 1;
93
94 return 0;
95 }
96
97
98 /** kext start/stop functions **/
99 kern_return_t kperf_start (kmod_info_t * ki, void * d);
100
101 kern_return_t
102 kperf_start (kmod_info_t * ki, void * d)
103 {
104 (void) ki;
105 (void) d;
106
107 /* say hello */
108 printf( "aprof: kext starting\n" );
109
110 /* register modules */
111 // kperf_action_init();
112 kperf_filter_init();
113 kperf_pet_init();
114
115 /* register the sysctls */
116 //kperf_register_profiling();
117
118 return KERN_SUCCESS;
119 }
120
121
122 /* random misc-ish functions */
123 uint32_t
124 kperf_get_thread_bits( thread_t thread )
125 {
126 return thread->t_chud;
127 }
128
129 void
130 kperf_set_thread_bits( thread_t thread, uint32_t bits )
131 {
132 thread->t_chud = bits;
133 }
134
135 /* mark an AST to fire on a thread */
136 void
137 kperf_set_thread_ast( thread_t thread )
138 {
139 /* FIXME: only call this on current thread from an interrupt
140 * handler for now...
141 */
142 if( thread != current_thread() )
143 panic( "unsafe AST set" );
144
145 act_set_kperf(thread);
146 }
147
148 unsigned
149 kperf_sampling_status(void)
150 {
151 return sampling_status;
152 }
153
154 int
155 kperf_sampling_enable(void)
156 {
157 /* already running! */
158 if( sampling_status == KPERF_SAMPLING_ON )
159 return 0;
160
161 if ( sampling_status != KPERF_SAMPLING_OFF )
162 panic( "kperf: sampling wasn't off" );
163
164 /* make sure interrupt tables and actions are initted */
165 if( !kperf_initted
166 || (kperf_action_get_count() == 0) )
167 return ECANCELED;
168
169 /* mark as running */
170 sampling_status = KPERF_SAMPLING_ON;
171
172 /* tell timers to enable */
173 kperf_timer_go();
174
175 return 0;
176 }
177
178 int
179 kperf_sampling_disable(void)
180 {
181 if( sampling_status != KPERF_SAMPLING_ON )
182 return 0;
183
184 /* mark a shutting down */
185 sampling_status = KPERF_SAMPLING_SHUTDOWN;
186
187 /* tell timers to disable */
188 kperf_timer_stop();
189
190 /* mark as off */
191 sampling_status = KPERF_SAMPLING_OFF;
192
193 return 0;
194 }