load average measurement implementation, accessable through
getloadavg() system call in the library.
This commit is contained in:
parent
aabef59faa
commit
87f2236ad2
7 changed files with 59 additions and 0 deletions
|
@ -38,6 +38,7 @@
|
||||||
FORWARD _PROTOTYPE( void init_clock, (void) );
|
FORWARD _PROTOTYPE( void init_clock, (void) );
|
||||||
FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) );
|
FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) );
|
||||||
FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) );
|
FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) );
|
||||||
|
FORWARD _PROTOTYPE( void load_update, (void));
|
||||||
|
|
||||||
/* Clock parameters. */
|
/* Clock parameters. */
|
||||||
#define COUNTER_FREQ (2*TIMER_FREQ) /* counter frequency using square wave */
|
#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;
|
bill_ptr->p_ticks_left -= ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update load average. */
|
||||||
|
load_update();
|
||||||
|
|
||||||
/* Check if do_clocktick() must be called. Done for alarms and scheduling.
|
/* Check if do_clocktick() must be called. Done for alarms and scheduling.
|
||||||
* Some processes, such as the kernel tasks, cannot be preempted.
|
* Some processes, such as the kernel tasks, cannot be preempted.
|
||||||
*/
|
*/
|
||||||
|
@ -272,3 +276,30 @@ PUBLIC unsigned long read_clock()
|
||||||
|
|
||||||
return count;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ EXTERN struct kinfo kinfo; /* kernel information for users */
|
||||||
EXTERN struct machine machine; /* machine information for users */
|
EXTERN struct machine machine; /* machine information for users */
|
||||||
EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
|
EXTERN struct kmessages kmess; /* diagnostic messages in kernel */
|
||||||
EXTERN struct randomness krandom; /* gather kernel random information */
|
EXTERN struct randomness krandom; /* gather kernel random information */
|
||||||
|
EXTERN struct loadinfo kloadinfo; /* status of load average */
|
||||||
|
|
||||||
/* Process scheduling information and the kernel reentry count. */
|
/* Process scheduling information and the kernel reentry count. */
|
||||||
EXTERN struct proc *prev_ptr; /* previously running process */
|
EXTERN struct proc *prev_ptr; /* previously running process */
|
||||||
|
|
|
@ -142,6 +142,9 @@ PUBLIC void main()
|
||||||
alloc_segments(rp);
|
alloc_segments(rp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Special compensation for IDLE - don't let it count in the load average. */
|
||||||
|
kloadinfo.procs_enqueued--;
|
||||||
|
|
||||||
#if ENABLE_BOOTDEV
|
#if ENABLE_BOOTDEV
|
||||||
/* Expect an image of the boot device to be loaded into memory as well.
|
/* 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,
|
* The boot device is the last module that is loaded into memory, and,
|
||||||
|
|
|
@ -500,6 +500,8 @@ register struct proc *rp; /* this process is now runnable */
|
||||||
/* Now select the next process to run. */
|
/* Now select the next process to run. */
|
||||||
pick_proc();
|
pick_proc();
|
||||||
|
|
||||||
|
kloadinfo.procs_enqueued++;
|
||||||
|
|
||||||
#if DEBUG_SCHED_CHECK
|
#if DEBUG_SCHED_CHECK
|
||||||
rp->p_ready = 1;
|
rp->p_ready = 1;
|
||||||
check_runqueues("enqueue");
|
check_runqueues("enqueue");
|
||||||
|
@ -548,10 +550,14 @@ register struct proc *rp; /* this process is no longer runnable */
|
||||||
}
|
}
|
||||||
prev_xp = *xpp; /* save previous in chain */
|
prev_xp = *xpp; /* save previous in chain */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kloadinfo.procs_enqueued--;
|
||||||
|
|
||||||
#if DEBUG_SCHED_CHECK
|
#if DEBUG_SCHED_CHECK
|
||||||
rp->p_ready = 0;
|
rp->p_ready = 0;
|
||||||
check_runqueues("dequeue");
|
check_runqueues("dequeue");
|
||||||
|
if(kloadinfo.procs_enqueued < 0)
|
||||||
|
kprintf("%d processes enqueued\n", kloadinfo.procs_enqueued);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ U16_t parmoff, parmsize; /* boot parameters offset and length */
|
||||||
char params[128*sizeof(char *)]; /* boot monitor parameters */
|
char params[128*sizeof(char *)]; /* boot monitor parameters */
|
||||||
register char *value; /* value in key=value pair */
|
register char *value; /* value in key=value pair */
|
||||||
extern int etext, end;
|
extern int etext, end;
|
||||||
|
int h;
|
||||||
|
|
||||||
/* Decide if mode is protected; 386 or higher implies protected mode.
|
/* Decide if mode is protected; 386 or higher implies protected mode.
|
||||||
* This must be done first, because it is needed for, e.g., seg2phys().
|
* 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_base = vir2phys(0);
|
||||||
kinfo.kmem_size = (phys_bytes) &end;
|
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, ...
|
/* Processor? 86, 186, 286, 386, ...
|
||||||
* Decide if mode is protected for older machines.
|
* Decide if mode is protected for older machines.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -42,6 +42,11 @@ register message *m_ptr; /* pointer to request message */
|
||||||
src_phys = vir2phys(&kinfo);
|
src_phys = vir2phys(&kinfo);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case GET_LOADINFO: {
|
||||||
|
length = sizeof(struct loadinfo);
|
||||||
|
src_phys = vir2phys(&kloadinfo);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case GET_IMAGE: {
|
case GET_IMAGE: {
|
||||||
length = sizeof(struct boot_image) * NR_BOOT_PROCS;
|
length = sizeof(struct boot_image) * NR_BOOT_PROCS;
|
||||||
src_phys = vir2phys(image);
|
src_phys = vir2phys(image);
|
||||||
|
|
|
@ -59,6 +59,7 @@ PUBLIC int do_getsysinfo()
|
||||||
struct mproc *proc_addr;
|
struct mproc *proc_addr;
|
||||||
vir_bytes src_addr, dst_addr;
|
vir_bytes src_addr, dst_addr;
|
||||||
struct kinfo kinfo;
|
struct kinfo kinfo;
|
||||||
|
struct loadinfo loadinfo;
|
||||||
size_t len;
|
size_t len;
|
||||||
static struct pm_mem_info pmi;
|
static struct pm_mem_info pmi;
|
||||||
int s, r;
|
int s, r;
|
||||||
|
@ -87,6 +88,11 @@ PUBLIC int do_getsysinfo()
|
||||||
src_addr = (vir_bytes) &pmi;
|
src_addr = (vir_bytes) &pmi;
|
||||||
len = sizeof(pmi);
|
len = sizeof(pmi);
|
||||||
break;
|
break;
|
||||||
|
case SI_LOADINFO: /* loadinfo is obtained via PM */
|
||||||
|
sys_getloadinfo(&loadinfo);
|
||||||
|
src_addr = (vir_bytes) &loadinfo;
|
||||||
|
len = sizeof(struct loadinfo);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return(EINVAL);
|
return(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue