cvs commit: src/sys/kern sched_4bsd.c
John Baldwin
jhb at FreeBSD.org
Mon Jul 28 21:44:36 UTC 2008
On Monday 28 July 2008 04:39:21 pm John Baldwin wrote:
> jhb 2008-07-28 20:39:21 UTC
>
> FreeBSD src repository
>
> Modified files:
> sys/kern sched_4bsd.c
> Log:
> SVN rev 180937 on 2008-07-28 20:39:21Z by jhb
>
> When choosing a CPU for a thread in a cpuset, prefer the last CPU that the
> thread ran on if there are no other CPUs in the set with a shorter per-CPU
> runqueue.
I used the test program below. Prior to this change, the two child processes
bounced between the two CPUs constantly. With this patch on an
otherwise-idle box, they only switched CPUs once after starting. With ULE
they switch CPUs occasionally (once every few seconds) but not nearly as bad
as 4BSD before this patch (multiple switches per second). Granted, this is a
very contrived test. :)
Note that I ran this on a 4-CPU box and used CPUs 2 and 3. You can change
which CPUs are used by changing the 'cpus[]' array. This is also quite x86
specific. :)
#include <sys/param.h>
#include <sys/cpuset.h>
#include <err.h>
#include <stdio.h>
#include <unistd.h>
#include <machine/cpufunc.h>
int apic_ids[2];
int cpus[2] = { 2, 3 };
int
apic_id(void)
{
u_int regs[4];
do_cpuid(1, regs);
return (regs[1] >> 24);
}
void
check_id(pid_t pid, int *id)
{
int new;
new = apic_id();
if (*id == new)
return;
printf("%d: moved from APIC ID %d to APIC ID %d\n", pid, *id, new);
*id = new;
}
void
child(void)
{
int last_id;
pid_t pid;
int i;
pid = getpid();
last_id = apic_id();
printf("%d: starting on APIC ID %d\n", pid, last_id);
for (;;) {
for (i = 0; i < 10000000; i++)
check_id(pid, &last_id);
usleep(5);
check_id(pid, &last_id);
}
}
int
main(int ac, char **av)
{
cpuset_t set;
int i;
for (i = 0; i < 2; i++) {
CPU_ZERO(&set);
CPU_SET(cpus[i], &set);
if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
sizeof(set), &set))
err(1, "cpuset_affinity(%d)", cpus[i]);
apic_ids[i] = apic_id();
printf("CPU%d has APIC ID %d\n", cpus[i], apic_ids[i]);
}
CPU_ZERO(&set);
for (i = 0; i < 2; i++)
CPU_SET(cpus[i], &set);
if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
sizeof(set), &set))
err(1, "cpuset_affinity");
for (i = 0; i < 2; i++) {
switch (fork()) {
case -1:
err(1, "fork");
case 0:
break;
default:
child();
}
}
for (i = 0; i < 2; i++)
wait(NULL);
return (0);
}
--
John Baldwin
More information about the cvs-src
mailing list