diff --git a/kernel/arch/i386/klib386.S b/kernel/arch/i386/klib386.S index 9a0eb5295..944c590a9 100644 --- a/kernel/arch/i386/klib386.S +++ b/kernel/arch/i386/klib386.S @@ -30,7 +30,7 @@ .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 */ @@ -436,18 +436,14 @@ idt_zero: /*===========================================================================*/ -/* 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 @@ -481,7 +477,7 @@ level0: ret /*===========================================================================*/ -/* read_flags */ +/* read_flags */ /*===========================================================================*/ /* * PUBLIC unsigned long read_cpu_flags(void); diff --git a/kernel/main.c b/kernel/main.c index 8bc34d338..5eadff0fe 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -178,6 +178,8 @@ PUBLIC void main() /* 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); } diff --git a/kernel/proc.c b/kernel/proc.c index d24ebcfdd..e7a04f2aa 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -155,7 +155,19 @@ not_runnable_pick_new: /* 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: @@ -1388,7 +1400,6 @@ PRIVATE struct proc * pick_proc(void) bill_ptr = rp; /* bill for system time */ return rp; } - minix_panic("no runnable processes", NO_NUM); return NULL; } diff --git a/kernel/proto.h b/kernel/proto.h index d52d8ca93..e01e4c3df 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -136,7 +136,7 @@ _PROTOTYPE( vir_bytes alloc_remote_segment, (u32_t *, segframe_t *, 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) ); diff --git a/kernel/table.c b/kernel/table.c index 960801981..73c19d6ff 100644 --- a/kernel/table.c +++ b/kernel/table.c @@ -45,7 +45,14 @@ 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 */ @@ -113,7 +120,7 @@ PRIVATE int 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"},