]> Zhao Yanbai Git Server - minix.git/commitdiff
load average measurement implementation, accessable through
authorBen Gras <ben@minix3.org>
Mon, 14 Nov 2005 15:50:46 +0000 (15:50 +0000)
committerBen Gras <ben@minix3.org>
Mon, 14 Nov 2005 15:50:46 +0000 (15:50 +0000)
getloadavg() system call in the library.

kernel/clock.c
kernel/glo.h
kernel/main.c
kernel/proc.c
kernel/start.c
kernel/system/do_getinfo.c
servers/pm/misc.c

index 1dafb33b2d2b4a76231fc52085cb1442e5c3f18c..d8dfb0d2cb0ced089ecbb45bacc969df1e4067d1 100755 (executable)
@@ -38,6 +38,7 @@
 FORWARD _PROTOTYPE( void init_clock, (void) );
 FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) );
 FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) );
+FORWARD _PROTOTYPE( void load_update, (void));
 
 /* Clock parameters. */
 #define COUNTER_FREQ (2*TIMER_FREQ) /* counter frequency using square wave */
@@ -205,6 +206,9 @@ irq_hook_t *hook;
       bill_ptr->p_ticks_left -= ticks;
   }
 
+  /* 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. 
    */ 
@@ -272,3 +276,30 @@ PUBLIC unsigned long read_clock()
   
   return count;
 }
+
+/*===========================================================================*
+ *                             load_update                                  * 
+ *===========================================================================*/
+PRIVATE void load_update(void)
+{
+       u16_t slot;
+
+       /* Load average data is stored as a list of numbers in a circular
+        * buffer. Each slot accumulates _LOAD_UNIT_SECS of samples of
+        * the number of runnable processes. Computations can then
+        * be made of the load average over variable periods, in the
+        * user library (see getloadavg(3)).
+        */
+       slot = (realtime / HZ / _LOAD_UNIT_SECS) % _LOAD_HISTORY;
+       if(slot != kloadinfo.proc_last_slot) {
+               kloadinfo.proc_load_history[slot] = 0;
+               kloadinfo.proc_last_slot = slot;
+       }
+
+       /* Cumulation. */
+       kloadinfo.proc_load_history[slot] += kloadinfo.procs_enqueued;
+
+       /* Up-to-dateness. */
+       kloadinfo.last_clock = realtime;
+}
+
index e37b7a4d4eea6782fa2601a3c3f0721a018e5f8e..ada3607ed9f74c0eb5de1d75cb60debdefda7c16 100755 (executable)
@@ -24,6 +24,7 @@ EXTERN struct kinfo kinfo;            /* kernel information for users */
 EXTERN struct machine machine;         /* machine information for users */
 EXTERN struct kmessages kmess;         /* diagnostic messages in kernel */
 EXTERN struct randomness krandom;      /* gather kernel random information */
+EXTERN struct loadinfo kloadinfo;      /* status of load average */
 
 /* Process scheduling information and the kernel reentry count. */
 EXTERN struct proc *prev_ptr;  /* previously running process */
index 74c33b2ca683f51f2fdf1da04fd56a6dfa326ebf..8295a78593e4a94d47b322495a04d9ad75c2a3f1 100755 (executable)
@@ -142,6 +142,9 @@ PUBLIC void main()
        alloc_segments(rp);
   }
 
+  /* Special compensation for IDLE - don't let it count in the load average. */
+  kloadinfo.procs_enqueued--;
+
 #if ENABLE_BOOTDEV 
   /* Expect an image of the boot device to be loaded into memory as well. 
    * The boot device is the last module that is loaded into memory, and, 
index 125c3436300b3192dd1ff8cb5867328f0d00c23d..f4d7eafaf2cbb126efe882b8bd23de3af54608a5 100755 (executable)
@@ -500,6 +500,8 @@ register struct proc *rp;   /* this process is now runnable */
   /* Now select the next process to run. */
   pick_proc();                 
 
+  kloadinfo.procs_enqueued++;
+
 #if DEBUG_SCHED_CHECK
   rp->p_ready = 1;
   check_runqueues("enqueue");
@@ -548,10 +550,14 @@ register struct proc *rp; /* this process is no longer runnable */
       }
       prev_xp = *xpp;                          /* save previous in chain */
   }
+
+  kloadinfo.procs_enqueued--;
   
 #if DEBUG_SCHED_CHECK
   rp->p_ready = 0;
   check_runqueues("dequeue");
+  if(kloadinfo.procs_enqueued < 0)
+       kprintf("%d processes enqueued\n", kloadinfo.procs_enqueued);
 #endif
 }
 
index dd860f705dfafb1b681915b12943e7bbd8b623d5..f137f4c6e80bda5c565ce781c273a277f3df49e7 100755 (executable)
@@ -29,6 +29,7 @@ U16_t parmoff, parmsize;      /* boot parameters offset and length */
   char params[128*sizeof(char *)];             /* boot monitor parameters */
   register char *value;                                /* value in key=value pair */
   extern int etext, end;
+  int h;
 
   /* Decide if mode is protected; 386 or higher implies protected mode.
    * This must be done first, because it is needed for, e.g., seg2phys().
@@ -64,6 +65,12 @@ U16_t parmoff, parmsize;     /* boot parameters offset and length */
   kinfo.kmem_base = vir2phys(0);
   kinfo.kmem_size = (phys_bytes) &end; 
 
+  /* Load average data initialization. */
+  kloadinfo.procs_enqueued = 0;
+  kloadinfo.proc_last_slot = 0;
+  for(h = 0; h < _LOAD_HISTORY; h++)
+       kloadinfo.proc_load_history[h] = 0;
+
   /* Processor?  86, 186, 286, 386, ... 
    * Decide if mode is protected for older machines. 
    */
index f6bed77a36d2fda5fcae0cc1cdcef1c5dffce95d..33b7bb7a3a2f6e902904963c3da6cd5c2baaee63 100644 (file)
@@ -42,6 +42,11 @@ register message *m_ptr;     /* pointer to request message */
         src_phys = vir2phys(&kinfo);
         break;
     }
+    case GET_LOADINFO: {
+        length = sizeof(struct loadinfo);
+        src_phys = vir2phys(&kloadinfo);
+        break;
+    }
     case GET_IMAGE: {
         length = sizeof(struct boot_image) * NR_BOOT_PROCS;
         src_phys = vir2phys(image);
index aadd84b6abff5ae4d0e5772ca5652b76315eca0c..a9fbbe78ab2d64722f6609df40afc565e97809a0 100644 (file)
@@ -59,6 +59,7 @@ PUBLIC int do_getsysinfo()
   struct mproc *proc_addr;
   vir_bytes src_addr, dst_addr;
   struct kinfo kinfo;
+  struct loadinfo loadinfo;
   size_t len;
   static struct pm_mem_info pmi;
   int s, r;
@@ -87,6 +88,11 @@ PUBLIC int do_getsysinfo()
        src_addr = (vir_bytes) &pmi;
        len = sizeof(pmi);
        break;
+  case SI_LOADINFO:                    /* loadinfo is obtained via PM */
+        sys_getloadinfo(&loadinfo);
+        src_addr = (vir_bytes) &loadinfo;
+        len = sizeof(struct loadinfo);
+        break;
   default:
        return(EINVAL);
   }