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
clean_seen_flag(void)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 *===========================================================================*/
do_sprofile(struct proc * caller,message * m_ptr)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 m_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