/* kern_synch.c 4.20 82/09/06 */
* Force switch among equal priority processes every 100ms.
timeout(roundrobin
, 0, hz
/ 10);
* The digital decay cpu usage priority assignment is scaled to run in
* time as expanded by the 1 minute load average. Each second we
* multiply the the previous cpu usage estimate by
* The following relates the load average to the period over which
* cpu usage is 90% forgotten:
* This is a great improvement on the previous algorithm which
* decayed the priorities by a constant, and decayed away all knowledge
* of previous activity in about 20 seconds. Under heavy load,
* the previous algorithm degenerated to round-robin with poor response
* time when there was a high load average.
#define ave(a,b) ((int)(((int)(a*b))/(b+1)))
* Constant for decay filter for cpu usage field
* in process table (used by ps au).
double ccpu
= 0.95122942450071400909; /* exp(-1/20) */
* Automatic niceness rate & max constants
#define MAXNICE (8 + NZERO) /* maximum auto nice value */
#define NFACT (40 * hz) /* nice++ every 40 secs cpu+sys time */
* Recompute process priorities, once a second
s
= spl6(); time
.tv_sec
+= lbolt
/ hz
; lbolt
%= hz
; splx(s
);
for (p
= proc
; p
< procNPROC
; p
++) if (p
->p_stat
&& p
->p_stat
!=SZOMB
) {
* Charge process for memory in use
shconsts
.sc_click
* p
->p_rssize
;
if (timerisset(&p
->p_seltimer
) &&
--p
->p_seltimer
.tv_sec
<= 0) {
timerclear(&p
->p_seltimer
);
if (timerisset(&p
->p_realtimer
.it_value
) &&
itimerdecr(&p
->p_realtimer
, 1000000) == 0)
if (p
->p_stat
==SSLEEP
|| p
->p_stat
==SSTOP
)
p
->p_pctcpu
= ccpu
* p
->p_pctcpu
+
(1.0 - ccpu
) * (p
->p_cpticks
/(float)hz
);
a
= ave((p
->p_cpu
& 0377), avenrun
[0]*nrscale
) +
p
->p_nice
- NZERO
+ p
->p_quota
->q_nice
;
a
= ave((p
->p_cpu
& 0377), avenrun
[0]*nrscale
) +
s
= spl6(); /* prevent state changes */
if ((p
!= u
.u_procp
|| noproc
) &&
p
->p_pri
!= p
->p_usrpri
) {
wakeup((caddr_t
)&proc
[2]);
timeout(schedcpu
, 0, hz
);
#define SQSIZE 0100 /* Must be power of 2 */
#define HASH(x) (( (int) x >> 5) & (SQSIZE-1))
struct proc
*slpque
[SQSIZE
];
* Give up the processor till a wakeup occurs
* on chan, at which time the process
* enters the scheduling queue at priority pri.
* The most important effect of pri is that when
* pri<=PZERO a signal cannot disturb the sleep;
* if pri>PZERO signals will be processed.
* Callers of this routine must be prepared for
* premature return, and check that the reason for
* sleeping has gone away.
register struct proc
*rp
, **hp
;
if (chan
==0 || rp
->p_stat
!= SRUN
|| rp
->p_rlink
)
hp
= &slpque
[HASH(chan
)];
* If priority was low (>PZERO) and
* there has been a signal, execute non-local goto through
* u.u_qsav, aborting the system call in progress (see trap.c)
* (or finishing a tsleep, see below)
* Sleep on chan at pri for at most a specified amount of time.
* Return (TS_OK,TS_TIME,TS_SIG) on (normal,timeout,signal) condition.
register struct proc
*p
= u
.u_procp
;
if (timercmp(tvp
, &p
->p_realtimer
.it_value
, >)) {
/* alarm will occur first! */
rval
= TS_OK
; /* almost NOTREACHED modulo fuzz */
bcopy((caddr_t
)u
.u_qsav
, (caddr_t
)lqsav
, sizeof (label_t
));
timerclear(&p
->p_seltimer
);
bcopy((caddr_t
)lqsav
, (caddr_t
)u
.u_qsav
, sizeof (label_t
));
* Remove a process from its wait queue
register struct proc
**hp
;
hp
= &slpque
[HASH(p
->p_wchan
)];
* Wake up all processes sleeping on chan.
register struct proc
*p
, **q
, **h
;
if (p
->p_rlink
|| p
->p_stat
!= SSLEEP
&& p
->p_stat
!= SSTOP
)
if (p
->p_stat
== SSLEEP
) {
/* OPTIMIZED INLINE EXPANSION OF setrun(p) */
if ((p
->p_flag
&SLOAD
) == 0) {
wakeup((caddr_t
)&runout
);
/* END INLINE EXPANSION */
* Initialize the (doubly-linked) run queues
for (i
= 0; i
< NQS
; i
++)
qs
[i
].ph_link
= qs
[i
].ph_rlink
= (struct proc
*)&qs
[i
];
* Set the process running;
* arrange for it to be swapped in if necessary.
unsleep(p
); /* e.g. when sending signals */
if ((p
->p_flag
&SLOAD
) == 0) {
wakeup((caddr_t
)&runout
);
* The rescheduling flag (runrun)
* is set if the priority is better
* than the currently running process.
register struct proc
*pp
;
p
= (pp
->p_cpu
& 0377)/4;
p
+= PUSER
+ 2*(pp
->p_nice
- NZERO
);
if (pp
->p_rssize
> pp
->p_maxrss
&& freemem
< desfree
)
p
+= 2*4; /* effectively, nice(4) */