Clock task split
- preemption handled in the clock timer interrupt handler, not in the clock task - more achitecture independent clock timer handling code - smp ready as each CPU can have its own timer
This commit is contained in:
		
							parent
							
								
									6eebc03f88
								
							
						
					
					
						commit
						f2a1f21a39
					
				| @ -6,6 +6,8 @@ | ||||
| 
 | ||||
| #include "../../kernel.h" | ||||
| 
 | ||||
| #include "../../clock.h" | ||||
| 
 | ||||
| #define CLOCK_ACK_BIT   0x80    /* PS/2 clock interrupt acknowledge bit */ | ||||
| 
 | ||||
| /* Clock parameters. */ | ||||
| @ -14,28 +16,30 @@ | ||||
| #define SQUARE_WAVE     0x36    /* ccaammmb, a = access, m = mode, b = BCD */ | ||||
|                                 /*   11x11, 11 = LSB then MSB, x11 = sq wave */ | ||||
| #define TIMER_FREQ  1193182    /* clock frequency for timer in PC and AT */ | ||||
| #define TIMER_COUNT (TIMER_FREQ/system_hz) /* initial value for counter*/ | ||||
| #define TIMER_COUNT(freq) (TIMER_FREQ/(freq)) /* initial value for counter*/ | ||||
| 
 | ||||
| PRIVATE irq_hook_t pic_timer_hook;		/* interrupt handler hook */ | ||||
| 
 | ||||
| /*===========================================================================*
 | ||||
|  *				arch_init_clock				     * | ||||
|  *				init_8235A_timer			     * | ||||
|  *===========================================================================*/ | ||||
| PUBLIC int arch_init_clock(void) | ||||
| PUBLIC int init_8253A_timer(unsigned freq) | ||||
| { | ||||
| 	/* Initialize channel 0 of the 8253A timer to, e.g., 60 Hz,
 | ||||
| 	 * and register the CLOCK task's interrupt handler to be run | ||||
| 	 * on every clock tick. | ||||
| 	 */ | ||||
| 	outb(TIMER_MODE, SQUARE_WAVE);  /* run continuously */ | ||||
| 	outb(TIMER0, (TIMER_COUNT & 0xff)); /* timer low byte */ | ||||
| 	outb(TIMER0, TIMER_COUNT >> 8); /* timer high byte */  | ||||
| 	outb(TIMER0, (TIMER_COUNT(freq) & 0xff)); /* timer low byte */ | ||||
| 	outb(TIMER0, TIMER_COUNT(freq) >> 8); /* timer high byte */ | ||||
| 
 | ||||
| 	return OK; | ||||
| } | ||||
| 
 | ||||
| /*===========================================================================*
 | ||||
|  *				clock_stop				     * | ||||
|  *				stop_8235A_timer			     * | ||||
|  *===========================================================================*/ | ||||
| PUBLIC void clock_stop(void) | ||||
| PUBLIC void stop_8253A_timer(void) | ||||
| { | ||||
| 	/* Reset the clock to the BIOS rate. (For rebooting.) */ | ||||
| 	outb(TIMER_MODE, 0x36); | ||||
| @ -44,9 +48,9 @@ PUBLIC void clock_stop(void) | ||||
| } | ||||
| 
 | ||||
| /*===========================================================================*
 | ||||
|  *				read_clock				     * | ||||
|  *				read_8235A_timer			     * | ||||
|  *===========================================================================*/ | ||||
| PUBLIC clock_t read_clock(void) | ||||
| PUBLIC clock_t read_8253A_timer(void) | ||||
| { | ||||
| 	/* Read the counter of channel 0 of the 8253A timer.  This counter
 | ||||
| 	 * counts down at a rate of TIMER_FREQ and restarts at | ||||
| @ -63,3 +67,26 @@ PUBLIC clock_t read_clock(void) | ||||
| 	return count; | ||||
| } | ||||
| 
 | ||||
| PUBLIC int arch_init_local_timer(unsigned freq) | ||||
| { | ||||
| 	init_8253A_timer(freq); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| PUBLIC void arch_stop_local_timer(void) | ||||
| { | ||||
| 	stop_8253A_timer(); | ||||
| } | ||||
| 
 | ||||
| PUBLIC int arch_register_local_timer_handler(irq_handler_t handler) | ||||
| { | ||||
| 	/* Using PIC, Initialize the CLOCK's interrupt hook. */ | ||||
| 	pic_timer_hook.proc_nr_e = NONE; | ||||
| 
 | ||||
| 	put_irq_handler(&pic_timer_hook, CLOCK_IRQ, handler); | ||||
| 	put_irq_handler(&pic_timer_hook, CLOCK_IRQ, | ||||
| 			(irq_handler_t)bsp_timer_int_handler); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
							
								
								
									
										8
									
								
								kernel/arch/i386/clock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								kernel/arch/i386/clock.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| #ifndef __CLOCK_X86_H__ | ||||
| #define __CLOCK_X86_H__ | ||||
| 
 | ||||
| _PROTOTYPE(int init_8253A_timer, (unsigned freq)); | ||||
| _PROTOTYPE(void stop_8253A_timer, (void)); | ||||
| _PROTOTYPE(clock_t read_8253A_timer, (void)); | ||||
| 
 | ||||
| #endif /* __CLOCK_X86_H__ */ | ||||
							
								
								
									
										275
									
								
								kernel/clock.c
									
									
									
									
									
								
							
							
						
						
									
										275
									
								
								kernel/clock.c
									
									
									
									
									
								
							| @ -12,8 +12,8 @@ | ||||
|  *   Sep 30, 2004   source code documentation updated  (Jorrit N. Herder) | ||||
|  *   Sep 24, 2004   redesigned alarm timers  (Jorrit N. Herder) | ||||
|  * | ||||
|  * The function do_clocktick() is triggered by the clock's interrupt  | ||||
|  * handler when a watchdog timer has expired or a process must be scheduled.  | ||||
|  * Clock task is notified by the clock's interrupt handler when a timer | ||||
|  * has expired. | ||||
|  * | ||||
|  * In addition to the main clock_task() entry point, which starts the main  | ||||
|  * loop, there are several other minor entry points: | ||||
| @ -24,7 +24,6 @@ | ||||
|  *   read_clock:	read the counter of channel 0 of the 8253A timer | ||||
|  * | ||||
|  * (+) The CLOCK task keeps tracks of watchdog timers for the entire kernel. | ||||
|  * The watchdog functions of expired timers are executed in do_clocktick().  | ||||
|  * It is crucial that watchdog functions not block, or the CLOCK task may | ||||
|  * be blocked. Do not send() a message when the receiver is not expecting it. | ||||
|  * Instead, notify(), which always returns, should be used.  | ||||
| @ -37,11 +36,11 @@ | ||||
| #include <minix/endpoint.h> | ||||
| #include <minix/portio.h> | ||||
| 
 | ||||
| #include "clock.h" | ||||
| 
 | ||||
| /* Function prototype for PRIVATE functions.
 | ||||
|  */  | ||||
| FORWARD _PROTOTYPE( void init_clock, (void) ); | ||||
| FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) ); | ||||
| FORWARD _PROTOTYPE( void do_clocktick, (message *m_ptr) ); | ||||
| FORWARD _PROTOTYPE( void load_update, (void)); | ||||
| 
 | ||||
| /* The CLOCK's timers queue. The functions in <timers.h> operate on this. 
 | ||||
| @ -57,7 +56,6 @@ PRIVATE clock_t next_timeout;	/* realtime that next timer expires */ | ||||
| /* The time is incremented by the interrupt handler on each clock tick.
 | ||||
|  */ | ||||
| PRIVATE clock_t realtime = 0;		      /* real time clock */ | ||||
| PRIVATE irq_hook_t clock_hook;		/* interrupt handler hook */ | ||||
| 
 | ||||
| /*===========================================================================*
 | ||||
|  *				clock_task				     * | ||||
| @ -83,7 +81,9 @@ PUBLIC void clock_task() | ||||
| 	if (is_notify(m.m_type)) { | ||||
| 		switch (_ENDPOINT_P(m.m_source)) { | ||||
| 			case HARDWARE: | ||||
| 				do_clocktick(&m); /* handle clock tick */ | ||||
| 				tmrs_exptimers(&clock_timers, realtime, NULL); | ||||
| 				next_timeout = (clock_timers == NULL) ? | ||||
| 					TMR_NEVER : clock_timers->tmr_exp_time; | ||||
| 				break; | ||||
| 			default:	/* illegal request type */ | ||||
| 				kprintf("CLOCK: illegal notify %d from %d.\n", | ||||
| @ -98,169 +98,45 @@ PUBLIC void clock_task() | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /*===========================================================================*
 | ||||
|  *				do_clocktick				     * | ||||
|  *===========================================================================*/ | ||||
| PRIVATE void do_clocktick(m_ptr) | ||||
| message *m_ptr;				/* pointer to request message */ | ||||
| { | ||||
|   register struct proc *bill_copy = bill_ptr; | ||||
| 
 | ||||
| /* Despite its name, this routine is not called on every clock tick. It
 | ||||
|  * is called on those clock ticks when a lot of work needs to be done. | ||||
|  */ | ||||
|    | ||||
|   /* A process used up a full quantum. The interrupt handler stored this
 | ||||
|    * process in 'prev_ptr'.  First make sure that the process is not on the  | ||||
|    * scheduling queues.  Then announce the process ready again. Since it has  | ||||
|    * no more time left, it gets a new quantum and is inserted at the right  | ||||
|    * place in the queues.  As a side-effect a new process will be scheduled. | ||||
|    */  | ||||
|   if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) { | ||||
|       if(prev_ptr->p_rts_flags == 0) {	/* if it was runnable .. */ | ||||
|       lock; | ||||
|       { | ||||
| 	dequeue(prev_ptr);		/* take it off the queues */ | ||||
|       	enqueue(prev_ptr);		/* and reinsert it again */  | ||||
|       } | ||||
|       unlock; | ||||
|       } else { | ||||
| 	kprintf("CLOCK: %d not runnable; flags: %x\n", | ||||
| 		prev_ptr->p_endpoint, prev_ptr->p_rts_flags); | ||||
|       } | ||||
|   } | ||||
| 
 | ||||
|   /* Check if a process-virtual timer expired. Check prev_ptr, but also
 | ||||
|    * bill_ptr - one process's user time is another's system time, and the | ||||
|    * profile timer decreases for both! Do this before the queue operations | ||||
|    * below, which may alter bill_ptr. Note the use a copy of bill_ptr, because | ||||
|    * bill_ptr may have been changed above, and this code can't be put higher | ||||
|    * up because otherwise cause_sig() may dequeue prev_ptr before we do. | ||||
|    */ | ||||
|   vtimer_check(prev_ptr); | ||||
| 
 | ||||
|   if (prev_ptr != bill_copy) | ||||
| 	vtimer_check(bill_copy); | ||||
| 
 | ||||
|   /* Check if a clock timer expired and run its watchdog function. */ | ||||
|   if (next_timeout <= realtime) { | ||||
|   	tmrs_exptimers(&clock_timers, realtime, NULL);  	 | ||||
| 	next_timeout = (clock_timers == NULL) ? | ||||
| 		 TMR_NEVER : clock_timers->tmr_exp_time;	 | ||||
|   } | ||||
| 
 | ||||
|   return; | ||||
| } | ||||
| 
 | ||||
| /*===========================================================================*
 | ||||
|  *				init_clock				     * | ||||
|  *===========================================================================*/ | ||||
| PRIVATE void init_clock() | ||||
| { | ||||
|   /* First of all init the clock system.
 | ||||
|    * | ||||
|    * Here the (a) clock is set to produce a interrupt at | ||||
|    * every 1/60 second (ea. 60Hz). | ||||
|    * | ||||
|    * Running right away. | ||||
|    */ | ||||
|   arch_init_clock();	/* architecture-dependent initialization. */ | ||||
|     | ||||
|   /* Initialize the CLOCK's interrupt hook. */ | ||||
|   clock_hook.proc_nr_e = CLOCK; | ||||
|   | ||||
|   put_irq_handler(&clock_hook, CLOCK_IRQ, clock_handler); | ||||
|   enable_irq(&clock_hook);		/* ready for clock interrupts */ | ||||
|      | ||||
|   /* Set a watchdog timer to periodically balance the scheduling queues. */ | ||||
|   balance_queues(NULL);			/* side-effect sets new timer */ | ||||
| 	/* Set a watchdog timer to periodically balance the scheduling queues.
 | ||||
| 	   Side-effect sets new timer */ | ||||
| 
 | ||||
| 	balance_queues(NULL); | ||||
| } | ||||
| 
 | ||||
| /*===========================================================================*
 | ||||
|  *				clock_handler				     * | ||||
|  *===========================================================================*/ | ||||
| PRIVATE int clock_handler(hook) | ||||
| irq_hook_t *hook; | ||||
| { | ||||
| /* This executes on each clock tick (i.e., every time the timer chip generates 
 | ||||
|  * an interrupt). It does a little bit of work so the clock task does not have  | ||||
|  * to be called on every tick.  The clock task is called when: | ||||
|  * | ||||
|  *	(1) the scheduling quantum of the running process has expired, or | ||||
|  *	(2) a timer has expired and the watchdog function should be run. | ||||
|  * | ||||
|  * Many global global and static variables are accessed here.  The safety of | ||||
|  * this must be justified. All scheduling and message passing code acquires a  | ||||
|  * lock by temporarily disabling interrupts, so no conflicts with calls from  | ||||
|  * the task level can occur. Furthermore, interrupts are not reentrant, the  | ||||
|  * interrupt handler cannot be bothered by other interrupts. | ||||
|  *  | ||||
|  * Variables that are updated in the clock's interrupt handler: | ||||
|  *	lost_ticks: | ||||
|  *		Clock ticks counted outside the clock task. This for example | ||||
|  *		is used when the boot monitor processes a real mode interrupt. | ||||
|  * 	realtime: | ||||
|  * 		The current uptime is incremented with all outstanding ticks. | ||||
|  *	proc_ptr, bill_ptr: | ||||
|  *		These are used for accounting and virtual timers. It does not | ||||
|  *		matter if proc.c is changing them, provided they are always | ||||
|  * 		valid pointers, since at worst the previous process would be | ||||
|  *		billed. | ||||
| /*
 | ||||
|  * The boot processor timer interrupt handler. In addition to non-boot cpus it | ||||
|  * keeps real time and notifies the clock task if need be | ||||
|  */ | ||||
|   register unsigned ticks; | ||||
|   register int expired; | ||||
| PUBLIC int bsp_timer_int_handler(void) | ||||
| { | ||||
| 	unsigned ticks; | ||||
| 
 | ||||
|   if(minix_panicing) return; | ||||
| 	if(minix_panicing) | ||||
| 		return 0; | ||||
| 
 | ||||
|   /* Get number of ticks and update realtime. */ | ||||
|   ticks = lost_ticks + 1; | ||||
|   lost_ticks = 0; | ||||
|   realtime += ticks; | ||||
| 	/* Get number of ticks and update realtime. */ | ||||
| 	ticks = lost_ticks + 1; | ||||
| 	lost_ticks = 0; | ||||
| 	realtime += ticks; | ||||
| 
 | ||||
|   /* Update user and system accounting times. Charge the current process for
 | ||||
|    * user time. If the current process is not billable, that is, if a non-user | ||||
|    * process is running, charge the billable process for system time as well. | ||||
|    * Thus the unbillable process' user time is the billable user's system time. | ||||
|    */ | ||||
|    | ||||
|   proc_ptr->p_user_time += ticks; | ||||
|   if (priv(proc_ptr)->s_flags & PREEMPTIBLE) { | ||||
|       proc_ptr->p_ticks_left -= ticks; | ||||
|   } | ||||
|   if (! (priv(proc_ptr)->s_flags & BILLABLE)) { | ||||
|       bill_ptr->p_sys_time += ticks; | ||||
|       bill_ptr->p_ticks_left -= ticks; | ||||
|   } | ||||
| 	ap_timer_int_handler(); | ||||
| 
 | ||||
|   /* Decrement virtual timers, if applicable. We decrement both the virtual
 | ||||
|    * and the profile timer of the current process, and if the current process | ||||
|    * is not billable, the timer of the billed process as well. | ||||
|    * If any of the timers expire, do_clocktick() will send out signals. | ||||
|    */ | ||||
|   expired = 0; | ||||
|   if ((proc_ptr->p_misc_flags & MF_VIRT_TIMER) && | ||||
| 	(proc_ptr->p_virt_left -= ticks) <= 0) expired = 1; | ||||
|   if ((proc_ptr->p_misc_flags & MF_PROF_TIMER) && | ||||
| 	(proc_ptr->p_prof_left -= ticks) <= 0) expired = 1; | ||||
|   if (! (priv(proc_ptr)->s_flags & BILLABLE) && | ||||
|   	(bill_ptr->p_misc_flags & MF_PROF_TIMER) && | ||||
|   	(bill_ptr->p_prof_left -= ticks) <= 0) expired = 1; | ||||
| 	/* if a timer expired, notify the clock task */ | ||||
| 	if ((next_timeout <= realtime)) { | ||||
| 		mini_notify(proc_addr(HARDWARE), CLOCK); /* send notification */ | ||||
| 	} | ||||
| 
 | ||||
|   /* Update load average. */ | ||||
|   load_update(); | ||||
|    | ||||
|   /* Check if do_clocktick() must be called. Done for alarms and scheduling.
 | ||||
|    * Some processes, such as the kernel tasks, cannot be preempted.  | ||||
|    */  | ||||
|   if ((next_timeout <= realtime) || (proc_ptr->p_ticks_left <= 0) || expired) { | ||||
|       prev_ptr = proc_ptr;			/* store running process */ | ||||
|       mini_notify(proc_addr(HARDWARE), CLOCK);		/* send notification */ | ||||
|   }  | ||||
| 	if (do_serial_debug) | ||||
| 		do_ser_debug(); | ||||
| 
 | ||||
|   if (do_serial_debug) | ||||
| 	do_ser_debug(); | ||||
| 
 | ||||
|   return(1);					/* reenable interrupts */ | ||||
| 	return(1);					/* reenable interrupts */ | ||||
| } | ||||
| 
 | ||||
| /*===========================================================================*
 | ||||
| @ -334,3 +210,92 @@ PRIVATE void load_update(void) | ||||
| 	kloadinfo.last_clock = realtime; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Timer interupt handler. This is the only think executed on non boot | ||||
|  * processors. It is called by bsp_timer_int_handler() on the boot processor | ||||
|  */ | ||||
| PUBLIC int ap_timer_int_handler(void) | ||||
| { | ||||
| 
 | ||||
| 	/* Update user and system accounting times. Charge the current process
 | ||||
| 	 * for user time. If the current process is not billable, that is, if a | ||||
| 	 * non-user process is running, charge the billable process for system | ||||
| 	 * time as well.  Thus the unbillable process' user time is the billable | ||||
| 	 * user's system time. | ||||
| 	 */ | ||||
| 
 | ||||
| 	unsigned ticks = 1; | ||||
| 	int expired = 0; | ||||
| 	struct proc * p, * billp; | ||||
| 
 | ||||
| 	/* Update user and system accounting times. Charge the current process
 | ||||
| 	 * for user time. If the current process is not billable, that is, if a | ||||
| 	 * non-user process is running, charge the billable process for system | ||||
| 	 * time as well.  Thus the unbillable process' user time is the billable | ||||
| 	 * user's system time. | ||||
| 	 */ | ||||
| 
 | ||||
| 	/* FIXME prepared for get_cpu_local_var() */ | ||||
| 	p = proc_ptr; | ||||
| 	billp = bill_ptr; | ||||
| 
 | ||||
| 	p->p_user_time += ticks; | ||||
| 	if (priv(p)->s_flags & PREEMPTIBLE) { | ||||
| 		p->p_ticks_left -= ticks; | ||||
| 	} | ||||
| 	if (! (priv(p)->s_flags & BILLABLE)) { | ||||
| 		billp->p_sys_time += ticks; | ||||
| 		billp->p_ticks_left -= ticks; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Decrement virtual timers, if applicable. We decrement both the
 | ||||
| 	 * virtual and the profile timer of the current process, and if the | ||||
| 	 * current process is not billable, the timer of the billed process as | ||||
| 	 * well.  If any of the timers expire, do_clocktick() will send out | ||||
| 	 * signals. | ||||
| 	 */ | ||||
| 	if ((p->p_misc_flags & MF_VIRT_TIMER) && | ||||
| 			(p->p_virt_left -= ticks) <= 0) expired = 1; | ||||
| 	if ((p->p_misc_flags & MF_PROF_TIMER) && | ||||
| 			(p->p_prof_left -= ticks) <= 0) expired = 1; | ||||
| 	if (! (priv(p)->s_flags & BILLABLE) && | ||||
| 			(billp->p_misc_flags & MF_PROF_TIMER) && | ||||
| 			(billp->p_prof_left -= ticks) <= 0) expired = 1; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Check if a process-virtual timer expired. Check current process, but | ||||
| 	 * also bill_ptr - one process's user time is another's system time, and | ||||
| 	 * the profile timer decreases for both! | ||||
| 	 */ | ||||
| 	vtimer_check(p); | ||||
| 
 | ||||
| 	if (p != billp) | ||||
| 		vtimer_check(billp); | ||||
| 
 | ||||
| 	/* Update load average. */ | ||||
| 	load_update(); | ||||
| 
 | ||||
| 	/* check if the process is still runnable after checking the vtimer */ | ||||
| 	if (p->p_rts_flags == 0 && p->p_ticks_left <= 0 && | ||||
| 			priv(p)->s_flags & PREEMPTIBLE) { | ||||
| 		proc_ptr = NULL; /* no process is scheduled for dequeue and
 | ||||
| 				    enqueue */ | ||||
| 		dequeue(p);	/* take it off the queues */ | ||||
| 		enqueue(p);	/* and reinsert it again */ | ||||
| 		proc_ptr = p; /* restore some consitent state */ | ||||
| 	} | ||||
| 
 | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| PUBLIC int boot_cpu_init_timer(unsigned freq) | ||||
| { | ||||
| 	if (arch_init_local_timer(freq)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	if (arch_register_local_timer_handler( | ||||
| 				(irq_handler_t) bsp_timer_int_handler)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
							
								
								
									
										16
									
								
								kernel/clock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								kernel/clock.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| #ifndef __CLOCK_H__ | ||||
| #define __CLOCK_H__ | ||||
| 
 | ||||
| #include "kernel.h" | ||||
| #include "arch/i386/clock.h" | ||||
| 
 | ||||
| _PROTOTYPE(int boot_cpu_init_timer, (unsigned freq)); | ||||
| 
 | ||||
| _PROTOTYPE(int bsp_timer_int_handler, (void)); | ||||
| _PROTOTYPE(int ap_timer_int_handler, (void)); | ||||
| 
 | ||||
| _PROTOTYPE(int arch_init_local_timer, (unsigned freq)); | ||||
| _PROTOTYPE(void arch_stop_local_timer, (void)); | ||||
| _PROTOTYPE(int arch_register_local_timer_handler, (irq_handler_t handler)); | ||||
| 
 | ||||
| #endif /* __CLOCK_H__ */ | ||||
| @ -32,7 +32,6 @@ EXTERN struct loadinfo kloadinfo;	/* status of load average */ | ||||
| /* Process scheduling information and the kernel reentry count. */ | ||||
| EXTERN struct proc *proc_ptr;	/* pointer to currently running process */ | ||||
| EXTERN struct proc *next_ptr;	/* next process to run after restart() */ | ||||
| EXTERN struct proc *prev_ptr;	 | ||||
| EXTERN struct proc *bill_ptr;	/* process to bill for clock ticks */ | ||||
| EXTERN struct proc *vmrestart;  /* first process on vmrestart queue */ | ||||
| EXTERN struct proc *vmrequest;  /* first process on vmrequest queue */ | ||||
|  | ||||
| @ -18,6 +18,7 @@ | ||||
| #include <minix/endpoint.h> | ||||
| #include "proc.h" | ||||
| #include "debug.h" | ||||
| #include "clock.h" | ||||
| 
 | ||||
| /* Prototype declarations for PRIVATE functions. */ | ||||
| FORWARD _PROTOTYPE( void announce, (void));	 | ||||
| @ -195,6 +196,16 @@ PUBLIC void main() | ||||
|    */ | ||||
|   bill_ptr = proc_addr(IDLE);	/* it has to point somewhere */ | ||||
|   announce();				/* print MINIX startup banner */ | ||||
| 
 | ||||
|   /*
 | ||||
|    * enable timer interrupts and clock task on the boot CPU | ||||
|    */ | ||||
|   if (boot_cpu_init_timer(system_hz)) { | ||||
| 	  minix_panic("FATAL : failed to initialize timer interrupts, " | ||||
| 			  "cannot continue without any clock source!", | ||||
| 			  NO_NUM); | ||||
|   } | ||||
| 
 | ||||
| /* Warnings for sanity checks that take time. These warnings are printed
 | ||||
|  * so it's a clear warning no full release should be done with them | ||||
|  * enabled. | ||||
| @ -208,6 +219,7 @@ PUBLIC void main() | ||||
| #if DEBUG_PROC_CHECK | ||||
|   FIXME("PROC check enabled"); | ||||
| #endif | ||||
| 
 | ||||
|   restart(); | ||||
| } | ||||
| 
 | ||||
| @ -257,7 +269,7 @@ timer_t *tp; | ||||
|  * monitor), RBT_MONITOR (execute given code), RBT_RESET (hard reset).  | ||||
|  */ | ||||
|   intr_init(INTS_ORIG); | ||||
|   clock_stop(); | ||||
|   arch_stop_local_timer(); | ||||
|   arch_shutdown(tp ? tmr_arg(tp)->ta_int : RBT_PANIC); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1190,9 +1190,8 @@ register struct proc *rp;	/* this process is now runnable */ | ||||
|    * process yet or current process isn't ready any more, or | ||||
|    * it's PREEMPTIBLE. | ||||
|    */ | ||||
| 	vmassert(proc_ptr); | ||||
|   if((proc_ptr->p_priority > rp->p_priority) && | ||||
|    (priv(proc_ptr)->s_flags & PREEMPTIBLE))  | ||||
|   if(!proc_ptr || (proc_ptr->p_priority > rp->p_priority) || | ||||
| 		  (priv(proc_ptr)->s_flags & PREEMPTIBLE)) | ||||
|      pick_proc(); | ||||
| 
 | ||||
| #if DEBUG_SCHED_CHECK | ||||
|  | ||||
| @ -132,9 +132,6 @@ _PROTOTYPE( int vm_phys_memset, (phys_bytes source, u8_t pattern, | ||||
|                 phys_bytes count)                                       ); | ||||
| _PROTOTYPE( vir_bytes alloc_remote_segment, (u32_t *, segframe_t *, | ||||
|         int, phys_bytes, vir_bytes, int)); | ||||
| _PROTOTYPE( int arch_init_clock, (void)					); | ||||
| _PROTOTYPE( clock_t read_clock, (void)					); | ||||
| _PROTOTYPE( void clock_stop, (void)    					); | ||||
| _PROTOTYPE( int intr_init, (int)					); | ||||
| _PROTOTYPE( int intr_disabled, (void)					); | ||||
| _PROTOTYPE( void idle_task, (void)                                     ); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Tomas Hruby
						Tomas Hruby