2 * This file contains several functions and variables used for system
5 * Statistical Profiling:
6 * The interrupt handler for profiling clock.
9 * The table used for profiling data and a function to get its size.
11 * The function used by kernelspace processes to register the locations
12 * of their control struct and profiling table.
15 * 14 Aug, 2006 Created, (Rogier Meurs)
18 #include <minix/config.h>
20 #include "kernel/kernel.h"
22 #include <minix/profile.h>
23 #include <minix/portio.h>
30 char sprof_sample_buffer
[SAMPLE_BUFFER_SIZE
];
32 /* Function prototype for the profiling clock handler. */
33 static int profile_clock_handler(irq_hook_t
*hook
);
35 /* A hook for the profiling clock interrupt handler. */
36 static irq_hook_t profile_clock_hook
;
38 /*===========================================================================*
39 * init_profile_clock *
40 *===========================================================================*/
41 void init_profile_clock(u32_t freq
)
45 if((irq
= arch_init_profile_clock(freq
)) >= 0) {
46 /* Register interrupt handler for statistical system profiling. */
47 profile_clock_hook
.proc_nr_e
= CLOCK
;
48 put_irq_handler(&profile_clock_hook
, irq
, profile_clock_handler
);
49 enable_irq(&profile_clock_hook
);
53 /*===========================================================================*
54 * profile_clock_stop *
55 *===========================================================================*/
56 void stop_profile_clock()
58 arch_stop_profile_clock();
60 /* Unregister interrupt handler. */
61 disable_irq(&profile_clock_hook
);
62 rm_irq_handler(&profile_clock_hook
);
65 static void sprof_save_sample(struct proc
* p
, void * pc
)
67 struct sprof_sample
*s
;
69 s
= (struct sprof_sample
*) (sprof_sample_buffer
+ sprof_info
.mem_used
);
71 s
->proc
= p
->p_endpoint
;
74 sprof_info
.mem_used
+= sizeof(struct sprof_sample
);
77 static void sprof_save_proc(struct proc
* p
)
79 struct sprof_proc
* s
;
81 s
= (struct sprof_proc
*) (sprof_sample_buffer
+ sprof_info
.mem_used
);
83 s
->proc
= p
->p_endpoint
;
84 strcpy(s
->name
, p
->p_name
);
86 sprof_info
.mem_used
+= sizeof(struct sprof_proc
);
89 static void profile_sample(struct proc
* p
, void * pc
)
91 /* This executes on every tick of the CMOS timer. */
93 /* Are we profiling, and profiling memory not full? */
94 if (!sprofiling
|| sprof_info
.mem_used
== -1)
97 /* Check if enough memory available before writing sample. */
98 if (sprof_info
.mem_used
+ sizeof(sprof_info
) +
99 2*sizeof(struct sprof_sample
) +
100 2*sizeof(struct sprof_sample
) > sprof_mem_size
) {
101 sprof_info
.mem_used
= -1;
105 /* Runnable system process? */
106 if (p
->p_endpoint
== IDLE
)
107 sprof_info
.idle_samples
++;
108 else if (p
->p_endpoint
== KERNEL
||
109 (priv(p
)->s_flags
& SYS_PROC
&& proc_is_runnable(p
))) {
111 if (!(p
->p_misc_flags
& MF_SPROF_SEEN
)) {
112 p
->p_misc_flags
|= MF_SPROF_SEEN
;
116 sprof_save_sample(p
, pc
);
117 sprof_info
.system_samples
++;
120 sprof_info
.user_samples
++;
123 sprof_info
.total_samples
++;
126 /*===========================================================================*
127 * profile_clock_handler *
128 *===========================================================================*/
129 static int profile_clock_handler(irq_hook_t
*hook
)
132 p
= get_cpulocal_var(proc_ptr
);
134 profile_sample(p
, (void *) p
->p_reg
.pc
);
136 /* Acknowledge interrupt if necessary. */
137 arch_ack_profile_clock();
139 return(1); /* reenable interrupts */
142 void nmi_sprofile_handler(struct nmi_frame
* frame
)
144 struct proc
* p
= get_cpulocal_var(proc_ptr
);
146 * test if the kernel was interrupted. If so, save first a sample fo
147 * kernel and than for the current process, otherwise save just the
150 if (nmi_in_kernel(frame
)) {
154 * if we sample kernel, check if IDLE is scheduled. If so,
155 * account for idle time rather than taking kernel sample
157 if (p
->p_endpoint
== IDLE
) {
158 sprof_info
.idle_samples
++;
159 sprof_info
.total_samples
++;
163 kern
= proc_addr(KERNEL
);
165 profile_sample(kern
, (void *) frame
->pc
);
168 profile_sample(p
, (void *) frame
->pc
);
171 #endif /* SPROFILE */
175 * The following variables and functions are used by the procentry/
176 * procentry syslib functions when linked with kernelspace processes.
177 * For userspace processes, the same variables and function are defined
178 * elsewhere. This enables different functionality and variable sizes,
179 * which is needed is a few cases.
182 /* A small table is declared for the kernelspace processes. */
183 struct cprof_tbl_s cprof_tbl
[CPROF_TABLE_SIZE_KERNEL
];
185 /* Function that returns table size. */
186 int profile_get_tbl_size(void)
188 return CPROF_TABLE_SIZE_KERNEL
;
191 /* Function that returns on which execution of procentry to announce. */
192 int profile_get_announce(void)
194 return CPROF_ACCOUNCE_KERNEL
;
198 * The kernel "announces" its control struct and table locations
199 * to itself through this function.
201 void profile_register(ctl_ptr
, tbl_ptr
)
209 if(cprof_procs_no
>= NR_SYS_PROCS
)
212 /* Store process name, control struct, table locations. */
213 rp
= proc_addr(SYSTEM
);
215 cprof_proc_info
[cprof_procs_no
].endpt
= rp
->p_endpoint
;
216 cprof_proc_info
[cprof_procs_no
].name
= rp
->p_name
;
217 cprof_proc_info
[cprof_procs_no
].ctl_v
= (vir_bytes
) ctl_ptr
;
218 cprof_proc_info
[cprof_procs_no
].buf_v
= (vir_bytes
) tbl_ptr
;