SMP - CPU local idle stub
- each CPU has its own pseudo idle process and its structure - idle cycles accounting is agregated when exporting to userspace
This commit is contained in:
		
							parent
							
								
									fac5fbfdbf
								
							
						
					
					
						commit
						865e21b884
					
				| @ -223,7 +223,6 @@ PRIVATE void ap_finish_booting(void) | |||||||
| 
 | 
 | ||||||
| 	ap_boot_finished(cpu); | 	ap_boot_finished(cpu); | ||||||
| 	spinlock_unlock(&boot_lock); | 	spinlock_unlock(&boot_lock); | ||||||
| 	for(;;); |  | ||||||
| 
 | 
 | ||||||
| 	/* finish processor initialisation. */ | 	/* finish processor initialisation. */ | ||||||
| 	lapic_enable(cpu); | 	lapic_enable(cpu); | ||||||
|  | |||||||
| @ -55,6 +55,7 @@ DECLARE_CPULOCAL_START | |||||||
| /* Process scheduling information and the kernel reentry count. */ | /* Process scheduling information and the kernel reentry count. */ | ||||||
| DECLARE_CPULOCAL(struct proc *,proc_ptr);/* pointer to currently running process */ | DECLARE_CPULOCAL(struct proc *,proc_ptr);/* pointer to currently running process */ | ||||||
| DECLARE_CPULOCAL(struct proc *,bill_ptr);/* process to bill for clock ticks */ | DECLARE_CPULOCAL(struct proc *,bill_ptr);/* process to bill for clock ticks */ | ||||||
|  | DECLARE_CPULOCAL(struct proc ,idle_proc);/* stub for an idle process */ | ||||||
| 
 | 
 | ||||||
| /* 
 | /* 
 | ||||||
|  * signal whether pagefault is already being handled to detect recursive |  * signal whether pagefault is already being handled to detect recursive | ||||||
|  | |||||||
| @ -65,6 +65,42 @@ FORWARD _PROTOTYPE( int try_one, (struct proc *src_ptr, struct proc *dst_ptr, | |||||||
| FORWARD _PROTOTYPE( struct proc * pick_proc, (void)); | FORWARD _PROTOTYPE( struct proc * pick_proc, (void)); | ||||||
| FORWARD _PROTOTYPE( void enqueue_head, (struct proc *rp)); | FORWARD _PROTOTYPE( void enqueue_head, (struct proc *rp)); | ||||||
| 
 | 
 | ||||||
|  | /* all idles share the same idle_priv structure */ | ||||||
|  | PRIVATE struct priv idle_priv; | ||||||
|  | 
 | ||||||
|  | PRIVATE void set_idle_name(char * name, int n) | ||||||
|  | { | ||||||
|  |         int i, c; | ||||||
|  |         int p_z = 0; | ||||||
|  |         /*   
 | ||||||
|  |          * P_NAME_LEN limits us to 3 characters for the idle task numer. 999 | ||||||
|  |          * should be enough though. | ||||||
|  |          */ | ||||||
|  |         if (n > 999)  | ||||||
|  |                 n = 999;  | ||||||
|  | 
 | ||||||
|  |         name[0] = 'i';  | ||||||
|  |         name[1] = 'd';  | ||||||
|  |         name[2] = 'l';  | ||||||
|  |         name[3] = 'e';  | ||||||
|  | 
 | ||||||
|  |         for (i = 4, c = 100; c > 0; c /= 10) { | ||||||
|  |                 int digit; | ||||||
|  | 
 | ||||||
|  |                 digit = n / c;   | ||||||
|  |                 n -= digit * c;   | ||||||
|  | 
 | ||||||
|  |                 if (p_z || digit != 0 || c == 1) { | ||||||
|  |                         p_z = 1; | ||||||
|  |                         name[i++] = '0' + digit; | ||||||
|  |                 }    | ||||||
|  |         }     | ||||||
|  | 
 | ||||||
|  |         name[i] = '\0'; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| #define PICK_ANY	1 | #define PICK_ANY	1 | ||||||
| #define PICK_HIGHERONLY	2 | #define PICK_HIGHERONLY	2 | ||||||
| 
 | 
 | ||||||
| @ -108,6 +144,14 @@ PUBLIC void proc_init(void) | |||||||
| 		sp->s_sig_mgr = NONE;		/* clear signal managers */ | 		sp->s_sig_mgr = NONE;		/* clear signal managers */ | ||||||
| 		sp->s_bak_sig_mgr = NONE; | 		sp->s_bak_sig_mgr = NONE; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	idle_priv.s_flags = IDL_F; | ||||||
|  | 	/* initialize IDLE structures for every CPU */ | ||||||
|  | 	for (i = 0; i < CONFIG_MAX_CPUS; i++) { | ||||||
|  | 		struct proc * ip = get_cpu_var_ptr(i, idle_proc); | ||||||
|  | 		ip->p_priv = &idle_priv; | ||||||
|  | 		set_idle_name(ip->p_name, i); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PRIVATE void switch_address_space_idle(void) | PRIVATE void switch_address_space_idle(void) | ||||||
| @ -127,12 +171,18 @@ PRIVATE void switch_address_space_idle(void) | |||||||
|  *===========================================================================*/ |  *===========================================================================*/ | ||||||
| PRIVATE void idle(void) | PRIVATE void idle(void) | ||||||
| { | { | ||||||
|  | 	struct proc * p; | ||||||
|  | 
 | ||||||
| 	/* This function is called whenever there is no work to do.
 | 	/* This function is called whenever there is no work to do.
 | ||||||
| 	 * Halt the CPU, and measure how many timestamp counter ticks are | 	 * Halt the CPU, and measure how many timestamp counter ticks are | ||||||
| 	 * spent not doing anything. This allows test setups to measure | 	 * spent not doing anything. This allows test setups to measure | ||||||
| 	 * the CPU utiliziation of certain workloads with high precision. | 	 * the CPU utiliziation of certain workloads with high precision. | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	p = get_cpulocal_var(proc_ptr) = get_cpulocal_var_ptr(idle_proc); | ||||||
|  | 	if (priv(p)->s_flags & BILLABLE) | ||||||
|  | 		get_cpulocal_var(bill_ptr) = p; | ||||||
|  | 
 | ||||||
| 	switch_address_space_idle(); | 	switch_address_space_idle(); | ||||||
| 
 | 
 | ||||||
| 	/* start accounting for the idle time */ | 	/* start accounting for the idle time */ | ||||||
| @ -184,9 +234,6 @@ not_runnable_pick_new: | |||||||
| 	 * process. If there is still nothing runnable we "schedule" IDLE again | 	 * process. If there is still nothing runnable we "schedule" IDLE again | ||||||
| 	 */ | 	 */ | ||||||
| 	while (!(p = pick_proc())) { | 	while (!(p = pick_proc())) { | ||||||
| 		p = get_cpulocal_var(proc_ptr) = proc_addr(IDLE); |  | ||||||
| 		if (priv(p)->s_flags & BILLABLE) |  | ||||||
| 			get_cpulocal_var(bill_ptr) = p; |  | ||||||
| 		idle(); | 		idle(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -17,6 +17,19 @@ | |||||||
| 
 | 
 | ||||||
| #if USE_GETINFO | #if USE_GETINFO | ||||||
| 
 | 
 | ||||||
|  | #include <minix/u64.h> | ||||||
|  | 
 | ||||||
|  | PRIVATE void update_idle_time(void) | ||||||
|  | { | ||||||
|  | 	int i; | ||||||
|  | 	struct proc * idl = proc_addr(IDLE); | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < CONFIG_MAX_CPUS ; i++) { | ||||||
|  | 		idl->p_cycles = add64(idl->p_cycles, | ||||||
|  | 				get_cpu_var(i, idle_proc).p_cycles); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /*===========================================================================*
 | /*===========================================================================*
 | ||||||
|  *			        do_getinfo				     * |  *			        do_getinfo				     * | ||||||
|  *===========================================================================*/ |  *===========================================================================*/ | ||||||
| @ -64,6 +77,7 @@ PUBLIC int do_getinfo(struct proc * caller, message * m_ptr) | |||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     case GET_PROCTAB: { |     case GET_PROCTAB: { | ||||||
|  | 	update_idle_time(); | ||||||
|         length = sizeof(struct proc) * (NR_PROCS + NR_TASKS); |         length = sizeof(struct proc) * (NR_PROCS + NR_TASKS); | ||||||
|         src_vir = (vir_bytes) proc; |         src_vir = (vir_bytes) proc; | ||||||
|         break; |         break; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tomas Hruby
						Tomas Hruby