.globl phys_memset /* write pattern anywhere in memory */
.globl mem_rdw /* copy one word from [segment:offset] */
.globl reset /* reset the system */
-.globl idle_task /* task executed when there is no work */
+.globl halt_cpu/* halts the current cpu when idle */
.globl level0 /* call a function at level 0 */
.globl read_cpu_flags /* read the cpu flags */
.globl read_cr0 /* read cr0 */
/*===========================================================================*/
-/* idle_task */
+/* halt_cpu */
/*===========================================================================*/
-idle_task:
/*
- * This task is called when the system has nothing else to do. The HLT
- * instruction puts the processor in a state where it draws minimum power.
+ * PUBLIC void halt_cpu(void);
+ * reanables interrupts and puts the cpu in the halts state. Once an interrupt
+ * is handled the execution resumes by disabling interrupts and continues
*/
- push $halt
- call level0 /* level0(halt) */
- add $4, %esp
- jmp idle_task
-halt:
+halt_cpu:
sti
hlt
cli
ret
/*===========================================================================*/
-/* read_flags */
+/* read_flags */
/*===========================================================================*/
/*
* PUBLIC unsigned long read_cpu_flags(void);
/* Set ready. The HARDWARE task is never ready. */
if (rp->p_nr == HARDWARE) RTS_SET(rp, RTS_PROC_STOP);
+ /* IDLE task is never put on a run queue as it is never ready to run */
+ if (rp->p_nr == IDLE) RTS_SET(rp, RTS_PROC_STOP);
RTS_UNSET(rp, RTS_SLOT_FREE); /* remove RTS_SLOT_FREE and schedule */
alloc_segments(rp);
}
/* this enqueues the process again */
if (proc_no_quantum(proc_ptr))
RTS_UNSET(proc_ptr, RTS_NO_QUANTUM);
- proc_ptr = pick_proc();
+
+ /*
+ * if we have no process to run, set IDLE as the current process for
+ * time accounting and put the cpu in and idle state. After the next
+ * timer interrupt the execution resumes here and we can pick another
+ * process. If there is still nothing runnable we "schedule" IDLE again
+ */
+ while (!(proc_ptr = pick_proc())) {
+ proc_ptr = proc_addr(IDLE);
+ if (priv(proc_ptr)->s_flags & BILLABLE)
+ bill_ptr = proc_ptr;
+ halt_cpu();
+ }
check_misc_flags:
bill_ptr = rp; /* bill for system time */
return rp;
}
- minix_panic("no runnable processes", NO_NUM);
return NULL;
}
int, phys_bytes, vir_bytes, int));
_PROTOTYPE( int intr_init, (int) );
_PROTOTYPE( int intr_disabled, (void) );
-_PROTOTYPE( void idle_task, (void) );
+_PROTOTYPE( void halt_cpu, (void) );
_PROTOTYPE( void arch_init, (void) );
_PROTOTYPE( void ser_putc, (char) );
_PROTOTYPE( void arch_shutdown, (int) );
PUBLIC char *t_stack[TOT_STACK_SPACE / sizeof(char *)];
/* Define flags for the various process types. */
-#define IDL_F (SYS_PROC | PREEMPTIBLE | BILLABLE) /* idle task */
+#define IDL_F (SYS_PROC | BILLABLE) /* idle task is not preemptible as we
+ * don't want it to interfere with the
+ * timer tick interrupt handler code.
+ * Unlike other processes idle task is
+ * handled in a special way and is
+ * preempted always if timer tick occurs
+ * and there is another runnable process
+ */
#define TSK_F (SYS_PROC) /* kernel tasks */
#define SRV_F (SYS_PROC | PREEMPTIBLE) /* system services */
#define VM_F (SYS_PROC) /* vm */
PUBLIC struct boot_image image[] = {
/* process nr, pc,flags, qs, queue, stack, traps, ipcto, call, name */
-{IDLE, idle_task,IDL_F, 8, IDLE_Q, IDL_S, 0, 0, no_c,"idle" },
+{IDLE, NULL,IDL_F, 0, IDLE_Q, IDL_S, 0, 0, no_c,"idle" },
{CLOCK,clock_task,TSK_F, 8, TASK_Q, TSK_S, TSK_T, 0, no_c,"clock" },
{SYSTEM, sys_task,TSK_F, 8, TASK_Q, TSK_S, TSK_T, 0, no_c,"system"},
{HARDWARE, 0,TSK_F, 8, TASK_Q, HRD_S, 0, 0, no_c,"kernel"},