2 * This file contains several functions and variables used for statistical
3 * system profiling, in particular the interrupt handler for profiling clock.
6 * 14 Aug, 2006 Created, (Rogier Meurs)
9 #include "kernel/kernel.h"
16 char sprof_sample_buffer
[SAMPLE_BUFFER_SIZE
];
18 /* Function prototype for the profiling clock handler. */
19 static int profile_clock_handler(irq_hook_t
*hook
);
21 /* A hook for the profiling clock interrupt handler. */
22 static irq_hook_t profile_clock_hook
;
24 /*===========================================================================*
25 * init_profile_clock *
26 *===========================================================================*/
27 void init_profile_clock(u32_t freq
)
31 if((irq
= arch_init_profile_clock(freq
)) >= 0) {
32 /* Register interrupt handler for statistical system profiling. */
33 profile_clock_hook
.proc_nr_e
= CLOCK
;
34 put_irq_handler(&profile_clock_hook
, irq
, profile_clock_handler
);
35 enable_irq(&profile_clock_hook
);
39 /*===========================================================================*
40 * profile_clock_stop *
41 *===========================================================================*/
42 void stop_profile_clock(void)
44 arch_stop_profile_clock();
46 /* Unregister interrupt handler. */
47 disable_irq(&profile_clock_hook
);
48 rm_irq_handler(&profile_clock_hook
);
51 static void sprof_save_sample(struct proc
* p
, void * pc
)
53 struct sprof_sample
*s
;
55 s
= (struct sprof_sample
*) (sprof_sample_buffer
+ sprof_info
.mem_used
);
57 s
->proc
= p
->p_endpoint
;
60 sprof_info
.mem_used
+= sizeof(struct sprof_sample
);
63 static void sprof_save_proc(struct proc
* p
)
65 struct sprof_proc
* s
;
67 s
= (struct sprof_proc
*) (sprof_sample_buffer
+ sprof_info
.mem_used
);
69 s
->proc
= p
->p_endpoint
;
70 strcpy(s
->name
, p
->p_name
);
72 sprof_info
.mem_used
+= sizeof(struct sprof_proc
);
75 static void profile_sample(struct proc
* p
, void * pc
)
77 /* This executes on every tick of the CMOS timer. */
79 /* Are we profiling, and profiling memory not full? */
80 if (!sprofiling
|| sprof_info
.mem_used
== -1)
83 /* Check if enough memory available before writing sample. */
84 if (sprof_info
.mem_used
+ sizeof(sprof_info
) +
85 2*sizeof(struct sprof_sample
) +
86 2*sizeof(struct sprof_sample
) > sprof_mem_size
) {
87 sprof_info
.mem_used
= -1;
91 /* Runnable system process? */
92 if (p
->p_endpoint
== IDLE
)
93 sprof_info
.idle_samples
++;
94 else if (p
->p_endpoint
== KERNEL
||
95 (priv(p
)->s_flags
& SYS_PROC
&& proc_is_runnable(p
))) {
97 if (!(p
->p_misc_flags
& MF_SPROF_SEEN
)) {
98 p
->p_misc_flags
|= MF_SPROF_SEEN
;
102 sprof_save_sample(p
, pc
);
103 sprof_info
.system_samples
++;
106 sprof_info
.user_samples
++;
109 sprof_info
.total_samples
++;
112 /*===========================================================================*
113 * profile_clock_handler *
114 *===========================================================================*/
115 static int profile_clock_handler(irq_hook_t
*hook
)
118 p
= get_cpulocal_var(proc_ptr
);
120 profile_sample(p
, (void *) p
->p_reg
.pc
);
122 /* Acknowledge interrupt if necessary. */
123 arch_ack_profile_clock();
125 return(1); /* reenable interrupts */
128 void nmi_sprofile_handler(struct nmi_frame
* frame
)
130 struct proc
* p
= get_cpulocal_var(proc_ptr
);
132 * test if the kernel was interrupted. If so, save first a sample fo
133 * kernel and than for the current process, otherwise save just the
136 if (nmi_in_kernel(frame
)) {
140 * if we sample kernel, check if IDLE is scheduled. If so,
141 * account for idle time rather than taking kernel sample
143 if (p
->p_endpoint
== IDLE
) {
144 sprof_info
.idle_samples
++;
145 sprof_info
.total_samples
++;
149 kern
= proc_addr(KERNEL
);
151 profile_sample(kern
, (void *) frame
->pc
);
154 profile_sample(p
, (void *) frame
->pc
);
157 #endif /* SPROFILE */