kernel: hack processor affinity to allow load sharing

On a multiprocessor, the scheduler can run into
a very unfair distribution of processes to cpus
when there are more long-running processes than cpus.

Say we have a 4 cpu machine and we run 4 long-running
proesses, each cpu will pick up a single process
and each process will get 100% of its fair share.

Everything is good so far.

If we start more long-running processes, all these
processes are going to be picked up by the cpu core
that runs most sporanic / bursty work loads as it
is calling sched() more often.

This results in all the extra long-running prcoesses
to cluster around the same core resulting in very
unfair sharing of load.

The problem is that once a process runs on a cpu,
it stays on that cpu as processor affinity
is never reset.

Process migration only happens when a cpu cannot
find any process to run, given the affinity
constrains, but this can never happen when
the system is under full load and each cpu
always has a low-priority long running
process to run.

How do we fix this?

The idea of this hack is to reset processor
affinity in ready() when its priority changes or,
when it appears to be a long-running process.

That way, we give every cpu a chance to pick
it up and share the load.

This is not a ideal solution of course. Long term,
we should probably have separate runqueues per cpu
and do the balancing explicitely.
This commit is contained in:
cinap_lenrek 2024-07-21 13:44:18 +00:00
parent 11cd33bcec
commit 3598b7cf36

View file

@ -406,6 +406,19 @@ queueproc(Schedq *rq, Proc *p)
return -1;
}
p->state = Ready;
/*
* When the priority is very low (process is using
* more than its fair share) or when it has changed,
* reset processor affinity.
*
* Long running processes would otherwise be stuck
* on the same cpu preventing sharing the load.
* When the priority changes, we want to give
* every cpu a chance to pick up the load.
*/
if(pri < 3 || pri != p->priority)
p->mp = nil;
p->priority = pri;
if(pri == PriEdf){