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