make minix lwip make explicit use of 'int'
[minix3.git] / kernel / profile.c
blob46b0f56b755d22768e5c2693c97374cf02112b8f
1 /*
2 * This file contains several functions and variables used for system
3 * profiling.
5 * Statistical Profiling:
6 * The interrupt handler for profiling clock.
8 * Call Profiling:
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.
14 * Changes:
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>
25 #if SPROFILE
27 #include <string.h>
28 #include "watchdog.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)
43 int irq;
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;
72 s->pc = pc;
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)
95 return;
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;
102 return;
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;
113 sprof_save_proc(p);
116 sprof_save_sample(p, pc);
117 sprof_info.system_samples++;
118 } else {
119 /* User process. */
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)
131 struct proc * p;
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
148 * process
150 if (nmi_in_kernel(frame)) {
151 struct proc *kern;
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++;
160 return;
163 kern = proc_addr(KERNEL);
165 profile_sample(kern, (void *) frame->pc);
167 else
168 profile_sample(p, (void *) frame->pc);
171 #endif /* SPROFILE */
173 #if CPROFILE
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)
202 void *ctl_ptr;
203 void *tbl_ptr;
205 int proc_nr;
206 vir_bytes vir_dst;
207 struct proc *rp;
209 if(cprof_procs_no >= NR_SYS_PROCS)
210 return;
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;
220 cprof_procs_no++;
223 #endif