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 | * Define the internal interfaces between the profiling support that is |
33 | * common between the kernel, mach servers, and user space library. |
34 | */ |
35 | |
36 | #ifndef _PROFILE_INTERNAL_H |
37 | #define _PROFILE_INTERNAL_H |
38 | |
39 | /* |
40 | * Allow us not to require stdio.h in kernel/server space, but |
41 | * use it in user space. |
42 | */ |
43 | |
44 | #if !defined(MACH_KERNEL) && !defined(_KERNEL) |
45 | #include <stdio.h> |
46 | #endif |
47 | |
48 | /* |
49 | * Scaling factor for the profil system call. |
50 | */ |
51 | |
52 | #define SCALE_1_TO_1 0x10000L |
53 | |
54 | |
55 | /* |
56 | * Forward reference to structures used. |
57 | */ |
58 | |
59 | struct profile_vars; |
60 | struct profile_stats; |
61 | struct profile_md; |
62 | struct profile_dci; |
63 | struct profile_profil; |
64 | struct callback; |
65 | struct gprof_arc; |
66 | struct prof_ext; |
67 | |
68 | /* |
69 | * Profiling type |
70 | */ |
71 | |
72 | typedef enum profile_type { |
73 | PROFILE_NONE, |
74 | PROFILE_GPROF, |
75 | PROFILE_PROF |
76 | } profile_type_t; |
77 | |
78 | /* |
79 | * Whether to allocate memory in _profile_md_init. |
80 | */ |
81 | |
82 | typedef enum profile_alloc_mem { |
83 | PROFILE_ALLOC_MEM_NO, |
84 | PROFILE_ALLOC_MEM_YES |
85 | } profile_alloc_mem_t; |
86 | |
87 | /* |
88 | * Allocation context block types. |
89 | */ |
90 | |
91 | typedef enum acontext_type { |
92 | ACONTEXT_PROF, /* 0: prof records */ |
93 | ACONTEXT_GPROF, /* 1: gprof arcs */ |
94 | ACONTEXT_GFUNC, /* 2: gprof function headers */ |
95 | ACONTEXT_MISC, /* 3: misc. allocations */ |
96 | ACONTEXT_PROFIL, /* 4: profil based allocations */ |
97 | ACONTEXT_DCI, /* 5: dci based allocations */ |
98 | ACONTEXT_BASIC_BLOCK, /* 6: basic block allocations */ |
99 | ACONTEXT_CALLBACK, /* 7: callback structures */ |
100 | ACONTEXT_MAX = 32 /* # allocation contexts */ |
101 | } acontext_type_t; |
102 | |
103 | #define ACONTEXT_FIRST ACONTEXT_PROF |
104 | |
105 | #define ACONTEXT_NAMES { \ |
106 | "prof", \ |
107 | "gprof", \ |
108 | "gfunc", \ |
109 | "misc", \ |
110 | "profil", \ |
111 | "dci", \ |
112 | "bb", \ |
113 | "callback", \ |
114 | "#8", \ |
115 | "#9", \ |
116 | "#10", \ |
117 | "#11", \ |
118 | "#12", \ |
119 | "#13", \ |
120 | "#14", \ |
121 | "#15", \ |
122 | "#16", \ |
123 | "#17", \ |
124 | "#18", \ |
125 | "#19", \ |
126 | "#20", \ |
127 | "#21", \ |
128 | "#22", \ |
129 | "#23", \ |
130 | "#24", \ |
131 | "#25", \ |
132 | "#26", \ |
133 | "#27", \ |
134 | "#28", \ |
135 | "#29", \ |
136 | "#30", \ |
137 | "#31", \ |
138 | } |
139 | |
140 | /* |
141 | * Kgmon control codes |
142 | */ |
143 | |
144 | typedef enum kgmon_control { |
145 | KGMON_UNUSED, /* insure no 0 is ever used */ |
146 | KGMON_GET_STATUS, /* return whether or not profiling is active */ |
147 | KGMON_GET_PROFILE_VARS, /* return the _profile_vars structure */ |
148 | KGMON_GET_PROFILE_STATS, /* return the _profile_stats structure */ |
149 | KGMON_GET_DEBUG, /* return whether or not debugging is on */ |
150 | |
151 | KGMON_SET_PROFILE_ON = 50, /* turn on profiling */ |
152 | KGMON_SET_PROFILE_OFF, /* turn off profiling */ |
153 | KGMON_SET_PROFILE_RESET, /* reset profiling tables */ |
154 | KGMON_SET_DEBUG_ON, /* turn on debugging */ |
155 | KGMON_SET_DEBUG_OFF /* turn off debugging */ |
156 | } kgmon_control_t; |
157 | |
158 | #define KGMON_GET_MIN KGMON_GET_STATUS |
159 | #define KGMON_GET_MAX KGMON_GET_DEBUG |
160 | #define KGMON_SET_MIN KGMON_SET_PROFILE_ON |
161 | #define KGMON_SET_MAX KGMON_SET_DEBUG_OFF |
162 | |
163 | #define ENCODE_KGMON(num, control, cpu_thread) \ |
164 | ((num) = ((cpu_thread) << 8) | (control)) |
165 | |
166 | #define DECODE_KGMON(num, control, cpu_thread) \ |
167 | do { \ |
168 | control = (num) & 0xff; \ |
169 | cpu_thread = (num) >> 8; \ |
170 | } while (0) |
171 | |
172 | #define LEGAL_KGMON(num) (((unsigned long)(num)) <= 0xffff) |
173 | |
174 | /* |
175 | * Pull in all of the machine dependent types now after defining the enums. |
176 | */ |
177 | |
178 | #include <profiling/machine/profile-md.h> |
179 | |
180 | /* |
181 | * general rounding functions. |
182 | */ |
183 | |
184 | #define ROUNDDOWN(x,y) (((x)/(y))*(y)) |
185 | #define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) |
186 | |
187 | /* |
188 | * Linked list of pages allocated for a particular allocation context block. |
189 | */ |
190 | |
191 | struct page_list { |
192 | void *first; /* pointer to first byte available */ |
193 | void *ptr; /* pointer to next available byte */ |
194 | struct page_list *next; /* next page allocated */ |
195 | size_t bytes_free; /* # bytes available */ |
196 | size_t bytes_allocated; /* # bytes allocates so far */ |
197 | size_t num_allocations; /* # of allocations */ |
198 | }; |
199 | |
200 | /* |
201 | * Allocation context block. |
202 | */ |
203 | |
204 | struct alloc_context { |
205 | struct alloc_context *next; /* next allocation context block */ |
206 | struct page_list *plist; /* head of page list */ |
207 | prof_lock_t lock; /* lock field available to asm */ |
208 | }; |
209 | |
210 | |
211 | /* |
212 | * Callback structure that records information for one record in the |
213 | * profiling output. |
214 | */ |
215 | |
216 | #define STR_MAX 32 |
217 | |
218 | struct callback { |
219 | void *sec_ptr; /* callback user data */ |
220 | /* callback function */ |
221 | size_t (*callback)(struct profile_vars *, struct callback *); |
222 | long sec_val1; /* section specific value */ |
223 | long sec_val2; /* section specific value */ |
224 | size_t sec_recsize; /* record size */ |
225 | size_t sec_length; /* total length */ |
226 | char sec_name[STR_MAX]; /* section name */ |
227 | }; |
228 | |
229 | /* |
230 | * Basic profil information (except for the profil buffer). |
231 | */ |
232 | |
233 | struct profile_profil { |
234 | prof_uptrint_t lowpc; /* lowest address */ |
235 | prof_uptrint_t highpc; /* highest address */ |
236 | size_t text_len; /* highpc-lowpc */ |
237 | size_t profil_len; /* length of the profil buffer */ |
238 | size_t counter_size; /* size of indivual counters (HISTCOUNTER) */ |
239 | unsigned long scale; /* scaling factor (65536 / scale) */ |
240 | unsigned long profil_unused[8]; /* currently unused */ |
241 | }; |
242 | |
243 | /* |
244 | * Profiling internal variables. This structure is intended to be machine independent. |
245 | */ |
246 | |
247 | struct profile_vars { |
248 | int major_version; /* major version number */ |
249 | int minor_version; /* minor version number */ |
250 | size_t vars_size; /* size of profile_vars structure */ |
251 | size_t plist_size; /* size of page_list structure */ |
252 | size_t acontext_size; /* size of allocation context struct */ |
253 | size_t callback_size; /* size of callback structure */ |
254 | profile_type_t type; /* profile type */ |
255 | const char *error_msg; /* error message for perror */ |
256 | const char *filename; /* filename to write to */ |
257 | char *str_ptr; /* string table */ |
258 | |
259 | #if !defined(MACH_KERNEL) && !defined(_KERNEL) |
260 | FILE *stream; /* stdio stream to write to */ |
261 | FILE *diag_stream; /* stdio stream to write diagnostics to */ |
262 | /* function to write out some bytes */ |
263 | size_t (*fwrite_func)(const void *, size_t, size_t, FILE *); |
264 | #else |
265 | void *stream; /* pointer passed to fwrite_func */ |
266 | void *diag_stream; /* stdio stream to write diagnostics to */ |
267 | /* function to write out some bytes */ |
268 | size_t (*fwrite_func)(const void *, size_t, size_t, void *); |
269 | #endif |
270 | |
271 | size_t page_size; /* machine pagesize */ |
272 | size_t str_bytes; /* # bytes in string table */ |
273 | size_t str_total; /* # bytes allocated total for string table */ |
274 | long clock_ticks; /* # clock ticks per second */ |
275 | |
276 | /* profil related variables */ |
277 | struct profile_profil profil_info; /* profil information */ |
278 | HISTCOUNTER *profil_buf; /* profil buffer */ |
279 | |
280 | /* Profiling output selection */ |
281 | void (*output_init)(struct profile_vars *); /* output init function */ |
282 | void (*output)(struct profile_vars *); /* output function */ |
283 | void *output_ptr; /* output specific info */ |
284 | |
285 | /* allocation contexts */ |
286 | struct alloc_context *acontext[(int)ACONTEXT_MAX]; |
287 | |
288 | void (*bogus_func)(void); /* Function to use if address out of bounds */ |
289 | prof_uptrint_t vars_unused[63]; /* future growth */ |
290 | |
291 | /* Various flags */ |
292 | prof_flag_t init; /* != 0 if initialized */ |
293 | prof_flag_t active; /* != 0 if profiling is active */ |
294 | prof_flag_t do_profile; /* != 0 if profiling is being done */ |
295 | prof_flag_t use_dci; /* != 0 if using DCI */ |
296 | |
297 | prof_flag_t use_profil; /* != 0 if using profil */ |
298 | prof_flag_t recursive_alloc; /* != 0 if alloc taking place */ |
299 | prof_flag_t output_uarea; /* != 0 if output the uarea */ |
300 | prof_flag_t output_stats; /* != 0 if output the stats */ |
301 | |
302 | prof_flag_t output_clock; /* != 0 if output the clock ticks */ |
303 | prof_flag_t multiple_sections; /* != 0 if output allows multiple sections */ |
304 | prof_flag_t have_bb; /* != 0 if we have basic block data */ |
305 | prof_flag_t init_format; /* != 0 if output format has been chosen */ |
306 | |
307 | prof_flag_t debug; /* != 0 if debugging */ |
308 | prof_flag_t check_funcs; /* != 0 if check gprof arcs for being in range */ |
309 | prof_flag_t flag_unused[62]; /* space for more flags */ |
310 | |
311 | struct profile_stats stats; /* profiling statistics */ |
312 | struct profile_md md; /* machine dependent info */ |
313 | }; |
314 | |
315 | /* |
316 | * Profiling static data. |
317 | */ |
318 | |
319 | extern struct profile_vars _profile_vars; |
320 | |
321 | /* |
322 | * Functions called by the machine dependent routines, and provided by |
323 | * specific routines to the kernel, server, and user space library. |
324 | */ |
325 | |
326 | #if (__GNUC__ < 2) || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || defined(lint) |
327 | #define __attribute__(arg) |
328 | #endif |
329 | |
330 | #if defined(_KERNEL) || defined(MACH_KERNEL) |
331 | #define _profile_printf printf |
332 | #else |
333 | extern int _profile_printf(const char *, ...) __attribute__((format(printf,1,2))); |
334 | #endif |
335 | |
336 | extern void *_profile_alloc_pages (size_t); |
337 | extern void _profile_free_pages (void *, size_t); |
338 | extern void _profile_error(struct profile_vars *); |
339 | |
340 | /* |
341 | * Functions provided by the machine dependent files. |
342 | */ |
343 | |
344 | extern void _profile_md_init(struct profile_vars *, profile_type_t, profile_alloc_mem_t); |
345 | extern int _profile_md_start(void); |
346 | extern int _profile_md_stop(void); |
347 | extern void *_profile_alloc(struct profile_vars *, size_t, acontext_type_t); |
348 | extern size_t _gprof_write(struct profile_vars *, struct callback *); |
349 | extern size_t _prof_write(struct profile_vars *, struct callback *); |
350 | extern void _profile_update_stats(struct profile_vars *); |
351 | extern void _profile_reset(struct profile_vars *); |
352 | |
353 | #if !defined(_KERNEL) && !defined(MACH_KERNEL) |
354 | extern void _profile_print_stats(FILE *, const struct profile_stats *, const struct profile_profil *); |
355 | extern void _profile_merge_stats(struct profile_stats *, const struct profile_stats *); |
356 | #else |
357 | |
358 | /* |
359 | * Functions defined in profile-kgmon.c |
360 | */ |
361 | |
362 | extern long _profile_kgmon(int, |
363 | size_t, |
364 | long, |
365 | int, |
366 | void **, |
367 | void (*)(kgmon_control_t)); |
368 | #ifdef _KERNEL |
369 | extern void kgmon_server_control(kgmon_control_t); |
370 | |
371 | #endif /* _KERNEL */ |
372 | #endif /* _KERNEL or MACH_KERNEL */ |
373 | |
374 | #endif /* _PROFILE_INTERNAL_H */ |
375 | |