V10/lsys/os/share.C
/*
** Share scheduler
*/
#include "sys/param.h"
#include "sys/lnode.h"
#include "sys/share.h"
#include "sys/charges.h"
float zerof = 0.0;
float onef = 1.0;
float twof = 2.0;
static void adjgroups();
/*
** Assumes that a group parent has been inserted into list before any group member.
** List is rooted in ``lnodes[0]''.
*/
share()
{
register KL_p lp;
register float maxusage;
register float f;
register float g;
register float h;
register float one = onef;
Users = 1;
Groups = 0;
TotUsage = zerof;
MaxUsage = one;
/*
** Special treatment for root.
*/
lp = &lnodes[0];
f = lp->kl_cost;
lp->kl_cost = 0;
lp->kl.l_charge += f;
lp->kl_temp += f; /* Root's node accumulates all charges here */
lp->kl_usage = one; /* Root is not shared */
if ( Shareflags & NOSHARE )
return;
/*
** Scan up active list and accumulate charges.
*/
for ( lp = lastlnode ; lp->kl_prev != (KL_p)0 ; lp = lp->kl_prev )
{
lp->kl_cost += lp->kl_muse * shconsts.sc_click; /* Charge for memory */
shconsts.sc_clickc += lp->kl_muse; /* Count memory click */
lp->kl_temp += lp->kl_cost;
lp->kl.l_charge += lp->kl_temp;
lp->kl_parent->kl_temp += lp->kl_temp;
}
/*
** Adjust costs for groups that are receiving too small a share.
*/
if ( Shareflags & ADJGROUPS )
adjgroups(lnodes, one, 0);
/*
** Scan down active list and process usage.
*/
maxusage = one;
for ( lp = &lnodes[0] ; (lp = lp->kl_next) != (KL_p)0 ; )
{
if ( lp->kl_ghead != (KL_p)0 )
Groups++;
if ( !(lp->kl.l_flags & NOTSHARED) )
Users++;
/*
** Accumulate usage.
*/
f = lp->kl.l_usage;
f *= DecayUsage;
if ( lp->kl_ghead == (KL_p)0 )
f += lp->kl_temp;
else
f += lp->kl_cost;
lp->kl.l_usage = f;
if ( g = lp->kl_norms )
{
if ( (f /= g) < twof )
f = twof; /* The minimum */
lp->kl_usage = f;
if ( f > maxusage && f < MAXUSAGE )
maxusage = f;
TotUsage += one / f;
}
else
lp->kl_usage = MAXUSAGE;
lp->kl_temp = zerof;
lp->kl_cost = 0;
}
MaxUsage = maxusage; /* Export value */
/*
** Limit kl_usage so that no user has more than MAXUSHARE * <allocated share>.
*/
if ( !(Shareflags & LIMSHARE) || TotUsage == zerof )
return;
g = one / MAXUSHARE;
for ( lp = &lnodes[0] ; (lp = lp->kl_next) != (KL_p)0 ; )
if
(
(h = lp->kl_usage) < maxusage
&&
(f = g / (TotUsage * lp->kl_eshare)) > h
&&
f < maxusage
)
{
TotUsage -= one / h;
f = g / lp->kl_eshare - one;
f /= TotUsage;
lp->kl_usage = f;
TotUsage += one / f;
if ( f > maxusage && f < MAXUSAGE )
maxusage = f;
}
MaxUsage = maxusage; /* Export value */
}
/*
** Increase run rates for groups getting more than their share.
*/
static void
adjgroups(gl, aa, d)
KL_p gl;
float aa;
int d;
{
register KL_p lp;
register float f;
register float totcharges = zerof;
register float a = aa;
for ( lp = gl->kl_ghead ; lp != (KL_p)0 ; lp = lp->kl_gnext )
totcharges += lp->kl_temp;
if ( (totcharges /= gl->kl_eshare * MINGSHARE) == zerof )
totcharges = onef;
for ( lp = gl->kl_ghead ; lp != (KL_p)0 ; lp = lp->kl_gnext )
{
if ( lp->kl_ghead == (KL_p)0 || lp->kl_eshare == zerof )
{
lp->kl_rate *= a;
continue;
}
if ( (f = lp->kl_temp / (lp->kl_eshare * totcharges)) > onef )
f *= a;
else
f = a;
lp->kl_rate *= f;
if ( d < MAXGROUPS )
adjgroups(lp, f, d+1);
}
}
/*
** Decay run rate.
*/
decayrate()
{
register KL_p lp = lnodes;
register float min = onef - NiceRates[NZERO];
register float dr = DecayRate;
do
{
if ( (lp->kl_rate *= dr) < min )
lp->kl_rate = min;
}
while
( (lp = lp->kl_next) != (KL_p)0 );
}