1 /* 2 * This file contains several functions and variables used for statistical 3 * system profiling, in particular the interrupt handler for profiling clock. 4 * 5 * Changes: 6 * 14 Aug, 2006 Created, (Rogier Meurs) 7 */ 8 9 #include "kernel/kernel.h" 10 11 #if SPROFILE 12 13 #include <string.h> 14 #include "watchdog.h" 15 16 char sprof_sample_buffer[SAMPLE_BUFFER_SIZE]; 17 18 /* Function prototype for the profiling clock handler. */ 19 static int profile_clock_handler(irq_hook_t *hook); 20 21 /* A hook for the profiling clock interrupt handler. */ 22 static irq_hook_t profile_clock_hook; 23 24 /*===========================================================================* 25 * init_profile_clock * 26 *===========================================================================*/ 27 void init_profile_clock(u32_t freq) 28 { 29 int irq; 30 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); 36 } 37 } 38 39 /*===========================================================================* 40 * profile_clock_stop * 41 *===========================================================================*/ 42 void stop_profile_clock(void) 43 { 44 arch_stop_profile_clock(); 45 46 /* Unregister interrupt handler. */ 47 disable_irq(&profile_clock_hook); 48 rm_irq_handler(&profile_clock_hook); 49 } 50 51 static void sprof_save_sample(struct proc * p, void * pc) 52 { 53 struct sprof_sample *s; 54 55 s = (struct sprof_sample *) (sprof_sample_buffer + sprof_info.mem_used); 56 57 s->proc = p->p_endpoint; 58 s->pc = pc; 59 60 sprof_info.mem_used += sizeof(struct sprof_sample); 61 } 62 63 static void sprof_save_proc(struct proc * p) 64 { 65 struct sprof_proc * s; 66 67 s = (struct sprof_proc *) (sprof_sample_buffer + sprof_info.mem_used); 68 69 s->proc = p->p_endpoint; 70 strcpy(s->name, p->p_name); 71 72 sprof_info.mem_used += sizeof(struct sprof_proc); 73 } 74 75 static void profile_sample(struct proc * p, void * pc) 76 { 77 /* This executes on every tick of the CMOS timer. */ 78 79 /* Are we profiling, and profiling memory not full? */ 80 if (!sprofiling || sprof_info.mem_used == -1) 81 return; 82 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; 88 return; 89 } 90 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))) { 96 97 if (!(p->p_misc_flags & MF_SPROF_SEEN)) { 98 p->p_misc_flags |= MF_SPROF_SEEN; 99 sprof_save_proc(p); 100 } 101 102 sprof_save_sample(p, pc); 103 sprof_info.system_samples++; 104 } else { 105 /* User process. */ 106 sprof_info.user_samples++; 107 } 108 109 sprof_info.total_samples++; 110 } 111 112 /*===========================================================================* 113 * profile_clock_handler * 114 *===========================================================================*/ 115 static int profile_clock_handler(irq_hook_t *hook) 116 { 117 struct proc * p; 118 p = get_cpulocal_var(proc_ptr); 119 120 profile_sample(p, (void *) p->p_reg.pc); 121 122 /* Acknowledge interrupt if necessary. */ 123 arch_ack_profile_clock(); 124 125 return(1); /* reenable interrupts */ 126 } 127 128 void nmi_sprofile_handler(struct nmi_frame * frame) 129 { 130 struct proc * p = get_cpulocal_var(proc_ptr); 131 /* 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 134 * process 135 */ 136 if (nmi_in_kernel(frame)) { 137 struct proc *kern; 138 139 /* 140 * if we sample kernel, check if IDLE is scheduled. If so, 141 * account for idle time rather than taking kernel sample 142 */ 143 if (p->p_endpoint == IDLE) { 144 sprof_info.idle_samples++; 145 sprof_info.total_samples++; 146 return; 147 } 148 149 kern = proc_addr(KERNEL); 150 151 profile_sample(kern, (void *) frame->pc); 152 } 153 else 154 profile_sample(p, (void *) frame->pc); 155 } 156 157 #endif /* SPROFILE */ 158