1 /* The kernel call that is implemented in this file: 2 * m_type: SYS_SPROF 3 * 4 * The parameters for this kernel call are: 5 * m_lsys_krn_sys_sprof.action (start/stop profiling) 6 * m_lsys_krn_sys_sprof.mem_size (available memory for data) 7 * m_lsys_krn_sys_sprof.freq (requested sample frequency) 8 * m_lsys_krn_sys_sprof.endpt (endpoint of caller) 9 * m_lsys_krn_sys_sprof.ctl_ptr (location of info struct) 10 * m_lsys_krn_sys_sprof.mem_ptr (location of memory for data) 11 * m_lsys_krn_sys_sprof.intr_type (interrupt source: RTC/NMI) 12 * 13 * Changes: 14 * 14 Aug, 2006 Created (Rogier Meurs) 15 */ 16 17 #include "kernel/system.h" 18 #include "kernel/watchdog.h" 19 20 #if SPROFILE 21 22 /* user address to write info struct */ 23 static vir_bytes sprof_info_addr_vir; 24 25 static void clean_seen_flag(void) 26 { 27 int i; 28 29 for (i = 0; i < NR_TASKS + NR_PROCS; i++) 30 proc[i].p_misc_flags &= ~MF_SPROF_SEEN; 31 } 32 33 /*===========================================================================* 34 * do_sprofile * 35 *===========================================================================*/ 36 int do_sprofile(struct proc * caller, message * m_ptr) 37 { 38 int proc_nr; 39 int err; 40 41 switch(m_ptr->m_lsys_krn_sys_sprof.action) { 42 43 case PROF_START: 44 /* Starting profiling. 45 * 46 * Check if profiling is not already running. Calculate physical 47 * addresses of user pointers. Reset counters. Start CMOS timer. 48 * Turn on profiling. 49 */ 50 if (sprofiling) { 51 printf("SYSTEM: start s-profiling: already started\n"); 52 return EBUSY; 53 } 54 55 /* Test endpoint number. */ 56 if(!isokendpt(m_ptr->m_lsys_krn_sys_sprof.endpt, &proc_nr)) 57 return EINVAL; 58 59 /* Set parameters for statistical profiler. */ 60 sprof_ep = m_ptr->m_lsys_krn_sys_sprof.endpt; 61 sprof_info_addr_vir = m_ptr->m_lsys_krn_sys_sprof.ctl_ptr; 62 sprof_data_addr_vir = m_ptr->m_lsys_krn_sys_sprof.mem_ptr; 63 64 sprof_info.mem_used = 0; 65 sprof_info.total_samples = 0; 66 sprof_info.idle_samples = 0; 67 sprof_info.system_samples = 0; 68 sprof_info.user_samples = 0; 69 70 sprof_mem_size = 71 m_ptr->m_lsys_krn_sys_sprof.mem_size < SAMPLE_BUFFER_SIZE ? 72 m_ptr->m_lsys_krn_sys_sprof.mem_size : SAMPLE_BUFFER_SIZE; 73 74 switch (sprofiling_type = m_ptr->m_lsys_krn_sys_sprof.intr_type) { 75 case PROF_RTC: 76 init_profile_clock(m_ptr->m_lsys_krn_sys_sprof.freq); 77 break; 78 case PROF_NMI: 79 err = nmi_watchdog_start_profiling( 80 _ptr->m_lsys_krn_sys_sprof.freq); 81 if (err) 82 return err; 83 break; 84 default: 85 printf("ERROR : unknown profiling interrupt type\n"); 86 return EINVAL; 87 } 88 89 sprofiling = 1; 90 91 clean_seen_flag(); 92 93 return OK; 94 95 case PROF_STOP: 96 /* Stopping profiling. 97 * 98 * Check if profiling is indeed running. Turn off profiling. 99 * Stop CMOS timer. Copy info struct to user process. 100 */ 101 if (!sprofiling) { 102 printf("SYSTEM: stop s-profiling: not started\n"); 103 return EBUSY; 104 } 105 106 sprofiling = 0; 107 108 switch (sprofiling_type) { 109 case PROF_RTC: 110 stop_profile_clock(); 111 break; 112 case PROF_NMI: 113 nmi_watchdog_stop_profiling(); 114 break; 115 } 116 117 data_copy(KERNEL, (vir_bytes) &sprof_info, 118 sprof_ep, sprof_info_addr_vir, sizeof(sprof_info)); 119 data_copy(KERNEL, (vir_bytes) sprof_sample_buffer, 120 sprof_ep, sprof_data_addr_vir, sprof_info.mem_used); 121 122 clean_seen_flag(); 123 124 return OK; 125 126 default: 127 return EINVAL; 128 } 129 } 130 131 #endif /* SPROFILE */ 132 133