V9/sys/sys/old/share.c

Compare this file to the similar file:
Show the results in this format:

/*
**	Share scheduler
*/

#include	"../h/param.h"
#include	"../h/lnode.h"
#include	"../h/share.h"
#include	"../h/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	one = onef;
	register float	zero = zerof;

	Users = 0;
	Groups = 1;
	TotUsage = zero;
	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.l_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.l_flags & NOTSHARED )
			Groups++;
		else
			Users++;

		/*
		**	Accumulate usage. (Background users have no shares.)
		*/

		if ( lp->kl_norms )
		{
			lp->kl.l_usage *= DecayUsage;

			if ( lp->kl_ghead == (KL_p)0 )
				f = lp->kl_temp / lp->kl_norms;
			else
			if ( lp->kl.l_flags & GROUPUSAGE )
				f = lp->kl_temp / (lp->kl_eshare * lp->kl_eshare);
			else
				f = (float)lp->kl_cost / lp->kl_norms;

			if ( (f += lp->kl.l_usage) < twof )
				f = twof;	/* The minimum */

			lp->kl.l_usage = f;

			if ( f > maxusage && f < MAXUSAGE )
				maxusage = f;	/* Remember max. for process priority normalisation */

			TotUsage += one / f;
		}
		else
			lp->kl.l_usage = MAXUSAGE;	/* setpri() treats these specially */

		lp->kl_temp = zero;
		lp->kl_cost = 0;
	}

	MaxUsage = maxusage;	/* Export value */

	/*
	**	Limit usage so that no user has more than MAXUSHARE * <allocated share>.
	*/

	if ( !(Shareflags & LIMSHARE) || TotUsage == zero )
		return;

	maxusage = MAXUSAGE / twof;

	g = one / (TotUsage * MAXUSHARE);

	for ( lp = &lnodes[0] ; (lp = lp->kl_next) != (KL_p)0 ; )
		if
		(
			lp->kl.l_usage < maxusage
			&&
			(f = g / (lp->kl.l_usage * lp->kl_eshare)) > one
			&&
			(f *= lp->kl.l_usage) < maxusage
		)
		{
			TotUsage -= one / lp->kl.l_usage;
			lp->kl.l_usage = f;
			TotUsage += one / f;

			g = one / (TotUsage * MAXUSHARE);
		}
}



/*
**	Decrease costs for groups getting less 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 u_long	totshares = 0;
	register float	a = aa;

	for ( lp = gl->kl_ghead ; lp != (KL_p)0 ; lp = lp->kl_gnext )
	{
		totcharges += (lp->kl_temp *= a);
		totshares += lp->kl.l_shares;
	}

	if ( d >= MAXGROUPS || totshares == 0 || totcharges == zerof )
		return;

	totcharges *= MINGSHARE;
	totcharges /= totshares;

	for ( lp = gl->kl_ghead ; lp != (KL_p)0 ; lp = lp->kl_gnext )
	{
		if ( lp->kl_ghead == (KL_p)0 || lp->kl.l_shares == 0 )
			continue;

		lp->kl_cost *= a;	/* Scale cost in case GROUPUSAGE */

		if ( (f = lp->kl_temp / (lp->kl.l_shares * totcharges)) < onef )
			f *= a;
		else
			f = a;

		adjgroups(lp, f, d+1);
	}
}



/*
**	Decay run rate.
*/

void
decayrate()
{
	register KL_p	lp;
	register float	one = onef;

	for ( lp = lnodes ; lp != (KL_p)0 ; lp = lp->kl_next )
		if ( (lp->kl_rate *= DecayRate) < one )
			lp->kl_rate = one;
}