]>
Commit | Line | Data |
---|---|---|
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> | |
35 | #include <libkern/libkern.h> | |
36 | ||
37 | #include <kperf/context.h> | |
38 | #include <kperf/action.h> | |
39 | #include <kperf/timetrigger.h> | |
40 | #include <kperf/pet.h> | |
41 | #include <kperf/filter.h> | |
42 | #include <kperf/kperfbsd.h> | |
43 | #include <kperf/kperf.h> | |
44 | ||
45 | #define REQ_SAMPLING (1) | |
46 | #define REQ_ACTION_COUNT (2) | |
47 | #define REQ_ACTION_SAMPLERS (3) | |
48 | #define REQ_TIMER_COUNT (4) | |
49 | #define REQ_TIMER_PERIOD (5) | |
50 | #define REQ_TIMER_PET (6) | |
51 | ||
52 | ||
53 | static int | |
54 | sysctl_timer_period( __unused struct sysctl_oid *oidp, struct sysctl_req *req ) | |
55 | { | |
56 | int error = 0; | |
57 | uint64_t inputs[2], retval; | |
58 | unsigned timer, set = 0; | |
59 | ||
60 | /* get 2x 64-bit words */ | |
61 | error = SYSCTL_IN( req, inputs, 2*sizeof(inputs[0]) ); | |
62 | if(error) | |
63 | { | |
64 | printf( "error in\n" ); | |
65 | return (error); | |
66 | } | |
67 | ||
68 | /* setup inputs */ | |
69 | timer = (unsigned) inputs[0]; | |
70 | if( inputs[1] != ~0ULL ) | |
71 | set = 1; | |
72 | ||
73 | printf( "%s timer: %u, inp[0] %llu\n", set ? "set" : "get", | |
74 | timer, inputs[0] ); | |
75 | ||
76 | if( set ) | |
77 | { | |
78 | printf( "timer set period\n" ); | |
79 | error = kperf_timer_set_period( timer, inputs[1] ); | |
80 | if( error ) | |
81 | return error; | |
82 | } | |
83 | ||
84 | error = kperf_timer_get_period(timer, &retval); | |
85 | if(error) | |
86 | { | |
87 | printf( "error get period\n" ); | |
88 | return (error); | |
89 | } | |
90 | ||
91 | inputs[1] = retval; | |
92 | ||
93 | if( error == 0 ) | |
94 | { | |
95 | error = SYSCTL_OUT( req, inputs, 2*sizeof(inputs[0]) ); | |
96 | if( error ) | |
97 | printf( "error out\n" ); | |
98 | } | |
99 | ||
100 | return error; | |
101 | } | |
102 | ||
103 | static int | |
104 | sysctl_action_samplers( __unused struct sysctl_oid *oidp, | |
105 | struct sysctl_req *req ) | |
106 | { | |
107 | int error = 0; | |
108 | uint64_t inputs[3]; | |
109 | uint32_t retval; | |
110 | unsigned actionid, set = 0; | |
111 | ||
112 | /* get 3x 64-bit words */ | |
113 | error = SYSCTL_IN( req, inputs, 3*sizeof(inputs[0]) ); | |
114 | if(error) | |
115 | { | |
116 | printf( "error in\n" ); | |
117 | return (error); | |
118 | } | |
119 | ||
120 | /* setup inputs */ | |
121 | set = (unsigned) inputs[0]; | |
122 | actionid = (unsigned) inputs[1]; | |
123 | ||
124 | if( set ) | |
125 | { | |
126 | error = kperf_action_set_samplers( actionid, inputs[2] ); | |
127 | if( error ) | |
128 | return error; | |
129 | } | |
130 | ||
131 | printf("set %d actionid %u samplers val %u\n", | |
132 | set, actionid, (unsigned) inputs[2] ); | |
133 | ||
134 | error = kperf_action_get_samplers(actionid, &retval); | |
135 | if(error) | |
136 | { | |
137 | printf( "error get samplers\n" ); | |
138 | return (error); | |
139 | } | |
140 | ||
141 | inputs[2] = retval; | |
142 | ||
143 | if( error == 0 ) | |
144 | { | |
145 | error = SYSCTL_OUT( req, inputs, 3*sizeof(inputs[0]) ); | |
146 | if( error ) | |
147 | printf( "error out\n" ); | |
148 | } | |
149 | ||
150 | return error; | |
151 | } | |
152 | ||
153 | static int | |
154 | sysctl_sampling( struct sysctl_oid *oidp, struct sysctl_req *req ) | |
155 | { | |
156 | int error = 0; | |
157 | uint32_t value = 0; | |
158 | ||
159 | /* get the old value and process it */ | |
160 | value = kperf_sampling_status(); | |
161 | ||
162 | /* copy out the old value, get the new value */ | |
163 | error = sysctl_handle_int(oidp, &value, 0, req); | |
164 | if (error || !req->newptr) | |
165 | return (error); | |
166 | ||
167 | printf( "setting sampling to %d\n", value ); | |
168 | ||
169 | /* if that worked, and we're writing... */ | |
170 | if( value ) | |
171 | error = kperf_sampling_enable(); | |
172 | else | |
173 | error = kperf_sampling_disable(); | |
174 | ||
175 | return error; | |
176 | } | |
177 | ||
178 | static int | |
179 | sysctl_action_count( struct sysctl_oid *oidp, struct sysctl_req *req ) | |
180 | { | |
181 | int error = 0; | |
182 | uint32_t value = 0; | |
183 | ||
184 | /* get the old value and process it */ | |
185 | value = kperf_action_get_count(); | |
186 | ||
187 | /* copy out the old value, get the new value */ | |
188 | error = sysctl_handle_int(oidp, &value, 0, req); | |
189 | if (error || !req->newptr) | |
190 | return (error); | |
191 | ||
192 | printf( "setting action count to %d\n", value ); | |
193 | ||
194 | /* if that worked, and we're writing... */ | |
195 | return kperf_action_set_count(value); | |
196 | } | |
197 | ||
198 | static int | |
199 | sysctl_timer_count( struct sysctl_oid *oidp, struct sysctl_req *req ) | |
200 | { | |
201 | int error = 0; | |
202 | uint32_t value = 0; | |
203 | ||
204 | /* get the old value and process it */ | |
205 | value = kperf_timer_get_count(); | |
206 | ||
207 | /* copy out the old value, get the new value */ | |
208 | error = sysctl_handle_int(oidp, &value, 0, req); | |
209 | if (error || !req->newptr) | |
210 | return (error); | |
211 | ||
212 | printf( "setting timer count to %d\n", value ); | |
213 | ||
214 | /* if that worked, and we're writing... */ | |
215 | return kperf_timer_set_count(value); | |
216 | } | |
217 | ||
218 | static int | |
219 | sysctl_timer_pet( struct sysctl_oid *oidp, struct sysctl_req *req ) | |
220 | { | |
221 | int error = 0; | |
222 | uint32_t value = 0; | |
223 | ||
224 | /* get the old value and process it */ | |
225 | value = kperf_timer_get_petid(); | |
226 | ||
227 | /* copy out the old value, get the new value */ | |
228 | error = sysctl_handle_int(oidp, &value, 0, req); | |
229 | if (error || !req->newptr) | |
230 | return (error); | |
231 | ||
232 | printf( "setting timer petid to %d\n", value ); | |
233 | ||
234 | /* if that worked, and we're writing... */ | |
235 | return kperf_timer_set_petid(value); | |
236 | } | |
237 | ||
238 | /* | |
239 | * #define SYSCTL_HANDLER_ARGS (struct sysctl_oid *oidp, \ | |
240 | * void *arg1, int arg2, \ | |
241 | * struct sysctl_req *req ) | |
242 | */ | |
243 | static int | |
244 | kperf_sysctl SYSCTL_HANDLER_ARGS | |
245 | { | |
246 | // __unused struct sysctl_oid *unused_oidp = oidp; | |
247 | (void)arg2; | |
248 | ||
249 | /* which request */ | |
250 | switch( (uintptr_t) arg1 ) | |
251 | { | |
252 | case REQ_ACTION_COUNT: | |
253 | return sysctl_action_count( oidp, req ); | |
254 | case REQ_ACTION_SAMPLERS: | |
255 | return sysctl_action_samplers( oidp, req ); | |
256 | case REQ_TIMER_COUNT: | |
257 | return sysctl_timer_count( oidp, req ); | |
258 | case REQ_TIMER_PERIOD: | |
259 | return sysctl_timer_period( oidp, req ); | |
260 | case REQ_TIMER_PET: | |
261 | return sysctl_timer_pet( oidp, req ); | |
262 | case REQ_SAMPLING: | |
263 | return sysctl_sampling( oidp, req ); | |
264 | ||
265 | #if 0 | |
266 | case REQ_TIMER: | |
267 | return sysctl_timer_period( req ); | |
268 | case REQ_PET: | |
269 | return sysctl_pet_period( req ); | |
270 | #endif | |
271 | default: | |
272 | return ENOENT; | |
273 | } | |
274 | } | |
275 | ||
276 | /* root kperf node */ | |
277 | SYSCTL_NODE(, OID_AUTO, kperf, CTLFLAG_RW|CTLFLAG_LOCKED, 0, | |
278 | "kperf"); | |
279 | ||
280 | /* action sub-section */ | |
281 | SYSCTL_NODE(_kperf, OID_AUTO, action, CTLFLAG_RW|CTLFLAG_LOCKED, 0, | |
282 | "action"); | |
283 | ||
284 | SYSCTL_PROC(_kperf_action, OID_AUTO, count, | |
285 | CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, | |
286 | (void*)REQ_ACTION_COUNT, | |
287 | sizeof(int), kperf_sysctl, "I", "Number of actions"); | |
288 | ||
289 | SYSCTL_PROC(_kperf_action, OID_AUTO, samplers, | |
290 | CTLFLAG_RW|CTLFLAG_ANYBODY, | |
291 | (void*)REQ_ACTION_SAMPLERS, | |
292 | 3*sizeof(uint64_t), kperf_sysctl, "UQ", | |
293 | "What to sample what a trigger fires an action"); | |
294 | ||
295 | /* timer sub-section */ | |
296 | SYSCTL_NODE(_kperf, OID_AUTO, timer, CTLFLAG_RW|CTLFLAG_LOCKED, 0, | |
297 | "timer"); | |
298 | ||
299 | SYSCTL_PROC(_kperf_timer, OID_AUTO, count, | |
300 | CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, | |
301 | (void*)REQ_TIMER_COUNT, | |
302 | sizeof(int), kperf_sysctl, "I", "Number of time triggers"); | |
303 | ||
304 | SYSCTL_PROC(_kperf_timer, OID_AUTO, period, | |
305 | CTLFLAG_RW|CTLFLAG_ANYBODY, | |
306 | (void*)REQ_TIMER_PERIOD, | |
307 | 2*sizeof(uint64_t), kperf_sysctl, "UQ", "Timer number and period"); | |
308 | ||
309 | SYSCTL_PROC(_kperf_timer, OID_AUTO, pet_timer, | |
310 | CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, | |
311 | (void*)REQ_TIMER_PET, | |
312 | sizeof(int), kperf_sysctl, "I", "Which timer ID does PET"); | |
313 | ||
314 | /* misc */ | |
315 | SYSCTL_PROC(_kperf, OID_AUTO, sampling, | |
316 | CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY, | |
317 | (void*)REQ_SAMPLING, | |
318 | sizeof(int), kperf_sysctl, "I", "Sampling running"); | |
319 | ||
320 | int legacy_mode = 1; | |
321 | SYSCTL_INT(_kperf, OID_AUTO, legacy_mode, CTLFLAG_RW, &legacy_mode, 0, "legacy_mode"); | |
322 | ||
323 | #if 0 | |
324 | SYSCTL_PROC(_kperf, OID_AUTO, timer_period, | |
325 | CTLFLAG_RW, (void*)REQ_TIMER, | |
326 | sizeof(uint64_t), kperf_sysctl, "QU", "nanoseconds"); | |
327 | ||
328 | SYSCTL_PROC(_kperf, OID_AUTO, pet_period, | |
329 | CTLFLAG_RW, (void*)REQ_PET, | |
330 | sizeof(uint64_t), kperf_sysctl, "QU", "nanoseconds"); | |
331 | ||
332 | /* FIXME: do real stuff */ | |
333 | SYSCTL_INT(_kperf, OID_AUTO, filter_pid0, | |
334 | CTLFLAG_RW, &pid_list[0], 0, ""); | |
335 | SYSCTL_INT(_kperf, OID_AUTO, filter_pid1, | |
336 | CTLFLAG_RW, &pid_list[1], 0, ""); | |
337 | SYSCTL_INT(_kperf, OID_AUTO, filter_pid2, | |
338 | CTLFLAG_RW, &pid_list[2], 0, ""); | |
339 | SYSCTL_INT(_kperf, OID_AUTO, filter_pid3, | |
340 | CTLFLAG_RW, &pid_list[3], 0, ""); | |
341 | ||
342 | #endif |