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
59struct profile_vars;
60struct profile_stats;
61struct profile_md;
62struct profile_dci;
63struct profile_profil;
64struct callback;
65struct gprof_arc;
66struct prof_ext;
67
68/*
69 * Profiling type
70 */
71
72typedef 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
82typedef 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
91typedef 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
144typedef 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)				\
167do {									\
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
191struct 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
204struct 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
218struct 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
233struct 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
247struct 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
319extern 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
333extern int _profile_printf(const char *, ...) __attribute__((format(printf,1,2)));
334#endif
335
336extern void *_profile_alloc_pages (size_t);
337extern void _profile_free_pages (void *, size_t);
338extern void _profile_error(struct profile_vars *);
339
340/*
341 * Functions provided by the machine dependent files.
342 */
343
344extern void _profile_md_init(struct profile_vars *, profile_type_t, profile_alloc_mem_t);
345extern int _profile_md_start(void);
346extern int _profile_md_stop(void);
347extern void *_profile_alloc(struct profile_vars *, size_t, acontext_type_t);
348extern size_t _gprof_write(struct profile_vars *, struct callback *);
349extern size_t _prof_write(struct profile_vars *, struct callback *);
350extern void _profile_update_stats(struct profile_vars *);
351extern void _profile_reset(struct profile_vars *);
352
353#if !defined(_KERNEL) && !defined(MACH_KERNEL)
354extern void _profile_print_stats(FILE *, const struct profile_stats *, const struct profile_profil *);
355extern void _profile_merge_stats(struct profile_stats *, const struct profile_stats *);
356#else
357
358/*
359 * Functions defined in profile-kgmon.c
360 */
361
362extern long _profile_kgmon(int,
363			   size_t,
364			   long,
365			   int,
366			   void **,
367			   void (*)(kgmon_control_t));
368#ifdef _KERNEL
369extern void kgmon_server_control(kgmon_control_t);
370
371#endif /* _KERNEL */
372#endif /* _KERNEL or MACH_KERNEL */
373
374#endif /* _PROFILE_INTERNAL_H */
375