]> Zhao Yanbai Git Server - minix.git/commitdiff
Idle task never runs
authorTomas Hruby <tom@minix3.org>
Thu, 12 Nov 2009 08:42:18 +0000 (08:42 +0000)
committerTomas Hruby <tom@minix3.org>
Thu, 12 Nov 2009 08:42:18 +0000 (08:42 +0000)
- idle task becomes a pseudo task which is never scheduled. It is never put on
  any run queue and never enters userspace. An entry for this task still remains
  in the process table for time accounting

- Instead of panicing if there is not process to schedule, pick_proc() returns
  NULL which is a signal to put the cpu in an idle state and set everything in
  such a way that after receiving and interrupt it looks like idle task was
  preempted

- idle task is set non-preemptible to avoid handling in the timer interrupt code
  which make userspace scheduling simpler as idle task does not need to be
  handled as a special case.

kernel/arch/i386/klib386.S
kernel/main.c
kernel/proc.c
kernel/proto.h
kernel/table.c

index 9a0eb52959108be774557e83c19b0679c2d05689..944c590a938a1708cc7ec5b73b73a05634903754 100644 (file)
@@ -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);
index 8bc34d338b750b399793b8de7a1e5d711c4ef2e8..5eadff0fe520a600d17e660d21ca5b34358a5ece 100644 (file)
@@ -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);
   }
index d24ebcfdd7589bad918690fb55164318c5b7f742..e7a04f2aabf88126626e87dd6036c29f7810ddaf 100644 (file)
@@ -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;
 }
 
index d52d8ca93b26022d31ccd2c93ab992ea39781a7e..e01e4c3dfe38c96f1c121fc69dd4435706f43e63 100644 (file)
@@ -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)                                  );
index 96080198151ef951b574363c0039cf76d027a589..73c19d6ff6c9d8ab07d2dace5663898ce8998a22 100644 (file)
 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"},