Index: sys/amd64/amd64/identcpu.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/amd64/identcpu.c,v retrieving revision 1.157 diff -u -p -r1.157 identcpu.c --- sys/amd64/amd64/identcpu.c 2 Feb 2008 23:17:27 -0000 1.157 +++ sys/amd64/amd64/identcpu.c 2 Mar 2008 02:58:05 -0000 @@ -97,6 +97,10 @@ static struct { { "Sledgehammer", CPUCLASS_K8 }, /* CPU_SLEDGEHAMMER */ }; +int cpu_cores; +int cpu_logical; + + extern int pq_l2size; extern int pq_l2nways; @@ -360,11 +364,13 @@ printcpuinfo(void) if ((regs[0] & 0x1f) != 0) cmp = ((regs[0] >> 26) & 0x3f) + 1; } + cpu_cores = cmp; + cpu_logical = htt / cmp; if (cmp > 1) printf("\n Cores per package: %d", cmp); if ((htt / cmp) > 1) printf("\n Logical CPUs per core: %d", - htt / cmp); + cpu_logical); } } /* Avoid ugly blank lines: only print newline when we have to. */ Index: sys/amd64/amd64/mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/amd64/amd64/mp_machdep.c,v retrieving revision 1.287 diff -u -p -r1.287 mp_machdep.c --- sys/amd64/amd64/mp_machdep.c 2 Aug 2007 21:17:58 -0000 1.287 +++ sys/amd64/amd64/mp_machdep.c 2 Mar 2008 02:58:05 -0000 @@ -83,12 +83,6 @@ extern int nkpt; extern struct pcpu __pcpu[]; -/* - * CPU topology map datastructures for HTT. - */ -static struct cpu_group mp_groups[MAXCPU]; -static struct cpu_top mp_top; - /* AP uses this during bootstrap. Do not staticize. */ char *bootSTK; static int bootAP; @@ -182,40 +176,38 @@ mem_range_AP_init(void) mem_range_softc.mr_op->initAP(&mem_range_softc); } -void -mp_topology(void) +struct cpu_group * +cpu_topo(void) { - struct cpu_group *group; - int apic_id; - int groups; - int cpu; - - /* Build the smp_topology map. */ - /* Nothing to do if there is no HTT support. */ - if (hyperthreading_cpus <= 1) - return; - group = &mp_groups[0]; - groups = 1; - for (cpu = 0, apic_id = 0; apic_id <= MAX_APIC_ID; apic_id++) { - if (!cpu_info[apic_id].cpu_present) - continue; - /* - * If the current group has members and we're not a logical - * cpu, create a new group. - */ - if (group->cg_count != 0 && - (apic_id % hyperthreading_cpus) == 0) { - group++; - groups++; - } - group->cg_count++; - group->cg_mask |= 1 << cpu; - cpu++; + if (cpu_cores == 0) + cpu_cores = 1; + if (cpu_logical == 0) + cpu_logical = 1; + if (mp_ncpus % (cpu_cores * cpu_logical) != 0) { + printf("WARNING: Non-uniform processors.\n"); + printf("WARNING: Using suboptimal topology.\n"); + return (smp_topo_none()); } - - mp_top.ct_count = groups; - mp_top.ct_group = mp_groups; - smp_topology = &mp_top; + /* + * No multi-core or hyper-threaded. + */ + if (cpu_logical * cpu_cores == 1) + return (smp_topo_none()); + /* + * Only HTT no multi-core. + */ + if (cpu_logical > 1 && cpu_cores == 1) + return (smp_topo_1level(CG_SHARE_L1, cpu_logical, CG_FLAG_HTT)); + /* + * Only multi-core no HTT. + */ + if (cpu_cores > 1 && cpu_logical == 1) + return (smp_topo_1level(CG_SHARE_NONE, cpu_cores, 0)); + /* + * Both HTT and multi-core. + */ + return (smp_topo_2level(CG_SHARE_NONE, cpu_cores, + CG_SHARE_L1, cpu_logical, CG_FLAG_HTT)); } /* @@ -409,9 +401,6 @@ cpu_mp_start(void) } set_interrupt_apic_ids(); - - /* Last, setup the cpu topology now that we have probed CPUs */ - mp_topology(); } Index: sys/amd64/include/smp.h =================================================================== RCS file: /home/ncvs/src/sys/amd64/include/smp.h,v retrieving revision 1.91 diff -u -p -r1.91 smp.h --- sys/amd64/include/smp.h 20 Sep 2007 20:38:43 -0000 1.91 +++ sys/amd64/include/smp.h 2 Mar 2008 02:58:05 -0000 @@ -36,6 +36,10 @@ extern int boot_cpu_id; extern struct pcb stoppcbs[]; extern int cpu_apic_ids[]; +/* global data in identcpu.c */ +extern int cpu_cores; +extern int cpu_logical; + /* IPI handlers */ inthand_t IDTVEC(invltlb), /* TLB shootdowns - global */ @@ -57,7 +61,6 @@ void ipi_self(u_int ipi); void ipi_bitmap_handler(struct trapframe frame); u_int mp_bootaddress(u_int); int mp_grab_cpu_hlt(void); -void mp_topology(void); void smp_cache_flush(void); void smp_invlpg(vm_offset_t addr); void smp_masked_invlpg(u_int mask, vm_offset_t addr); Index: sys/conf/files =================================================================== RCS file: /home/ncvs/src/sys/conf/files,v retrieving revision 1.1269 diff -u -p -r1.1269 files --- sys/conf/files 20 Feb 2008 07:50:13 -0000 1.1269 +++ sys/conf/files 2 Mar 2008 02:58:06 -0000 @@ -1426,6 +1426,7 @@ kern/kern_clock.c standard kern/kern_condvar.c standard kern/kern_conf.c standard kern/kern_cpu.c standard +kern/kern_cpuset.c standard kern/kern_context.c standard kern/kern_descrip.c standard kern/kern_environment.c standard Index: sys/i386/i386/identcpu.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/identcpu.c,v retrieving revision 1.180 diff -u -p -r1.180 identcpu.c --- sys/i386/i386/identcpu.c 29 May 2007 19:39:18 -0000 1.180 +++ sys/i386/i386/identcpu.c 2 Mar 2008 02:58:09 -0000 @@ -141,6 +141,9 @@ static struct { { "Pentium 4", CPUCLASS_686 }, /* CPU_P4 */ }; +int cpu_cores; +int cpu_logical; + #if defined(I586_CPU) && !defined(NO_F00F_HACK) int has_f00f_bug = 0; /* Initialized so that it can be patched. */ #endif @@ -874,11 +877,13 @@ via_common: if ((regs[0] & 0x1f) != 0) cmp = ((regs[0] >> 26) & 0x3f) + 1; } + cpu_cores = cmp; + cpu_logical = htt / cmp; if (cmp > 1) printf("\n Cores per package: %d", cmp); if ((htt / cmp) > 1) printf("\n Logical CPUs per core: %d", - htt / cmp); + cpu_logical); } } else if (strcmp(cpu_vendor, "CyrixInstead") == 0) { printf(" DIR=0x%04x", cyrix_did); Index: sys/i386/i386/mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/i386/i386/mp_machdep.c,v retrieving revision 1.282 diff -u -p -r1.282 mp_machdep.c --- sys/i386/i386/mp_machdep.c 13 Nov 2007 23:00:24 -0000 1.282 +++ sys/i386/i386/mp_machdep.c 2 Mar 2008 02:58:09 -0000 @@ -135,12 +135,6 @@ extern int nkpt; extern struct pcpu __pcpu[]; -/* - * CPU topology map datastructures for HTT. - */ -static struct cpu_group mp_groups[MAXCPU]; -static struct cpu_top mp_top; - /* AP uses this during bootstrap. Do not staticize. */ char *bootSTK; static int bootAP; @@ -238,40 +232,38 @@ mem_range_AP_init(void) mem_range_softc.mr_op->initAP(&mem_range_softc); } -void -mp_topology(void) +struct cpu_group * +cpu_topo(void) { - struct cpu_group *group; - int apic_id; - int groups; - int cpu; - - /* Build the smp_topology map. */ - /* Nothing to do if there is no HTT support. */ - if (hyperthreading_cpus <= 1) - return; - group = &mp_groups[0]; - groups = 1; - for (cpu = 0, apic_id = 0; apic_id <= MAX_APIC_ID; apic_id++) { - if (!cpu_info[apic_id].cpu_present) - continue; - /* - * If the current group has members and we're not a logical - * cpu, create a new group. - */ - if (group->cg_count != 0 && - (apic_id % hyperthreading_cpus) == 0) { - group++; - groups++; - } - group->cg_count++; - group->cg_mask |= 1 << cpu; - cpu++; + if (cpu_cores == 0) + cpu_cores = 1; + if (cpu_logical == 0) + cpu_logical = 1; + if (mp_ncpus % (cpu_cores * cpu_logical) != 0) { + printf("WARNING: Non-uniform processors.\n"); + printf("WARNING: Using suboptimal topology.\n"); + return (smp_topo_none()); } - - mp_top.ct_count = groups; - mp_top.ct_group = mp_groups; - smp_topology = &mp_top; + /* + * No multi-core or hyper-threaded. + */ + if (cpu_logical * cpu_cores == 1) + return (smp_topo_none()); + /* + * Only HTT no multi-core. + */ + if (cpu_logical > 1 && cpu_cores == 1) + return (smp_topo_1level(CG_SHARE_L1, cpu_logical, CG_FLAG_HTT)); + /* + * Only multi-core no HTT. + */ + if (cpu_cores > 1 && cpu_logical == 1) + return (smp_topo_1level(CG_SHARE_NONE, cpu_cores, 0)); + /* + * Both HTT and multi-core. + */ + return (smp_topo_2level(CG_SHARE_NONE, cpu_cores, + CG_SHARE_L1, cpu_logical, CG_FLAG_HTT)); } @@ -459,9 +451,6 @@ cpu_mp_start(void) } set_interrupt_apic_ids(); - - /* Last, setup the cpu topology now that we have probed CPUs */ - mp_topology(); } Index: sys/i386/include/smp.h =================================================================== RCS file: /home/ncvs/src/sys/i386/include/smp.h,v retrieving revision 1.90 diff -u -p -r1.90 smp.h --- sys/i386/include/smp.h 20 Sep 2007 20:38:43 -0000 1.90 +++ sys/i386/include/smp.h 2 Mar 2008 02:58:10 -0000 @@ -45,6 +45,10 @@ extern u_long *ipi_rendezvous_counts[MAX extern u_long *ipi_lazypmap_counts[MAXCPU]; #endif +/* global data in identcpu.c */ +extern int cpu_cores; +extern int cpu_logical; + /* IPI handlers */ inthand_t IDTVEC(invltlb), /* TLB shootdowns - global */ @@ -67,7 +71,6 @@ void ipi_self(u_int ipi); void ipi_bitmap_handler(struct trapframe frame); u_int mp_bootaddress(u_int); int mp_grab_cpu_hlt(void); -void mp_topology(void); void smp_cache_flush(void); void smp_invlpg(vm_offset_t addr); void smp_masked_invlpg(u_int mask, vm_offset_t addr); Index: sys/ia64/ia64/mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/ia64/ia64/mp_machdep.c,v retrieving revision 1.67 diff -u -p -r1.67 mp_machdep.c --- sys/ia64/ia64/mp_machdep.c 6 Aug 2007 05:15:57 -0000 1.67 +++ sys/ia64/ia64/mp_machdep.c 2 Mar 2008 02:58:10 -0000 @@ -84,6 +84,13 @@ volatile int ap_spin; static void cpu_mp_unleash(void *); +struct cpu_group * +cpu_topo(void) +{ + + return smp_topo_none(); +} + void ia64_ap_startup(void) { Index: sys/kern/init_main.c =================================================================== RCS file: /home/ncvs/src/sys/kern/init_main.c,v retrieving revision 1.290 diff -u -p -r1.290 init_main.c --- sys/kern/init_main.c 10 Jan 2008 22:11:20 -0000 1.290 +++ sys/kern/init_main.c 2 Mar 2008 02:58:10 -0000 @@ -73,6 +73,7 @@ __FBSDID("$FreeBSD: src/sys/kern/init_ma #include #include #include +#include #include @@ -430,6 +431,7 @@ proc0_init(void *dummy __unused) td->td_base_pri = PUSER; td->td_oncpu = 0; td->td_flags = TDF_INMEM|TDP_KTHREAD; + td->td_cpuset = cpuset_thread0(); p->p_peers = 0; p->p_leader = p; Index: sys/kern/kern_thread.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_thread.c,v retrieving revision 1.265 diff -u -p -r1.265 kern_thread.c --- sys/kern/kern_thread.c 22 Dec 2007 04:56:48 -0000 1.265 +++ sys/kern/kern_thread.c 2 Mar 2008 02:58:10 -0000 @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_th #include #include #include +#include #include @@ -342,7 +343,8 @@ thread_alloc(void) void thread_free(struct thread *td) { - + cpuset_rel(td->td_cpuset); + td->td_cpuset = NULL; cpu_thread_free(td); if (td->td_altkstack != 0) vm_thread_dispose_altkstack(td); @@ -527,6 +529,8 @@ thread_wait(struct proc *p) /* Wait for any remaining threads to exit cpu_throw(). */ while (p->p_exitthreads) sched_relinquish(curthread); + cpuset_rel(td->td_cpuset); + td->td_cpuset = NULL; cpu_thread_clean(td); crfree(td->td_ucred); thread_reap(); /* check for zombie threads etc. */ Index: sys/kern/subr_smp.c =================================================================== RCS file: /home/ncvs/src/sys/kern/subr_smp.c,v retrieving revision 1.203 diff -u -p -r1.203 subr_smp.c --- sys/kern/subr_smp.c 2 Jan 2008 17:09:15 -0000 1.203 +++ sys/kern/subr_smp.c 2 Mar 2008 02:58:10 -0000 @@ -68,7 +68,6 @@ int mp_ncpus; /* export this for libkvm consumers. */ int mp_maxcpus = MAXCPU; -struct cpu_top *smp_topology; volatile int smp_started; u_int mp_maxid; @@ -90,6 +89,11 @@ int smp_cpus = 1; /* how many cpu's runn SYSCTL_INT(_kern_smp, OID_AUTO, cpus, CTLFLAG_RD, &smp_cpus, 0, "Number of CPUs online"); +int smp_topology = 0; /* Which topology we're using. */ +SYSCTL_INT(_kern_smp, OID_AUTO, topology, CTLFLAG_RD, &smp_topology, 0, + "Topology override setting; 0 is default provided by hardware."); +TUNABLE_INT("kern.smp.topology", &smp_topology); + #ifdef SMP /* Enable forwarding of a signal to a process running on a different CPU */ static int forward_signal_enabled = 1; @@ -385,22 +389,177 @@ smp_rendezvous(void (* setup_func)(void /* release lock */ mtx_unlock_spin(&smp_ipi_mtx); } -#else /* !SMP */ -/* - * Provide dummy SMP support for UP kernels. Modules that need to use SMP - * APIs will still work using this dummy support. - */ -static void -mp_setvariables_for_up(void *dummy) +static struct cpu_group group[MAXCPU]; + +struct cpu_group * +smp_topo(void) { - mp_ncpus = 1; - mp_maxid = PCPU_GET(cpuid); - all_cpus = PCPU_GET(cpumask); - KASSERT(PCPU_GET(cpuid) == 0, ("UP must have a CPU ID of zero")); + struct cpu_group *top; + + /* + * Check for a fake topology request for debugging purposes. + */ + switch (smp_topology) { + case 1: + /* Dual core with no sharing. */ + top = smp_topo_1level(CG_SHARE_NONE, 2, 0); + break; + case 3: + /* Dual core with shared L2. */ + top = smp_topo_1level(CG_SHARE_L2, 2, 0); + break; + case 4: + /* quad core, shared l3 among each package, private l2. */ + top = smp_topo_1level(CG_SHARE_L3, 4, 0); + break; + case 5: + /* quad core, 2 dualcore parts on each package share l2. */ + top = smp_topo_2level(CG_SHARE_NONE, 2, CG_SHARE_L2, 2, 0); + break; + case 6: + /* Single-core 2xHTT */ + top = smp_topo_1level(CG_SHARE_L1, 2, CG_FLAG_HTT); + break; + case 7: + /* quad core with a shared l3, 8 threads sharing L2. */ + top = smp_topo_2level(CG_SHARE_L3, 4, CG_SHARE_L2, 8, + CG_FLAG_THREAD); + break; + default: + /* Default, ask the system what it wants. */ + top = cpu_topo(); + break; + } + /* + * Verify the returned topology. + */ + if (top->cg_count != mp_ncpus) + panic("Built bad topology at %p. CPU count %d != %d", + top, top->cg_count, mp_ncpus); + if (top->cg_mask != all_cpus) + panic("Built bad topology at %p. CPU mask 0x%X != 0x%X", + top, top->cg_mask, all_cpus); + return (top); +} + +struct cpu_group * +smp_topo_none(void) +{ + struct cpu_group *top; + + top = &group[0]; + top->cg_parent = NULL; + top->cg_child = NULL; + top->cg_mask = (1 << mp_ncpus) - 1; + top->cg_count = mp_ncpus; + top->cg_children = 0; + top->cg_level = CG_SHARE_NONE; + top->cg_flags = 0; + + return (top); +} + +static int +smp_topo_addleaf(struct cpu_group *parent, struct cpu_group *child, int share, + int count, int flags, int start) +{ + cpumask_t mask; + int i; + + for (mask = 0, i = 0; i < count; i++, start++) + mask |= (1 << start); + child->cg_parent = parent; + child->cg_child = NULL; + child->cg_children = 0; + child->cg_level = share; + child->cg_count = count; + child->cg_flags = flags; + child->cg_mask = mask; + parent->cg_children++; + for (; parent != NULL; parent = parent->cg_parent) { + if ((parent->cg_mask & child->cg_mask) != 0) + panic("Duplicate children in %p. mask 0x%X child 0x%X", + parent, parent->cg_mask, child->cg_mask); + parent->cg_mask |= child->cg_mask; + parent->cg_count += child->cg_count; + } + + return (start); } -SYSINIT(cpu_mp_setvariables, SI_SUB_TUNABLES, SI_ORDER_FIRST, - mp_setvariables_for_up, NULL) + +struct cpu_group * +smp_topo_1level(int share, int count, int flags) +{ + struct cpu_group *child; + struct cpu_group *top; + int packages; + int cpu; + int i; + + cpu = 0; + top = &group[0]; + packages = mp_ncpus / count; + top->cg_child = child = &group[1]; + top->cg_level = CG_SHARE_NONE; + for (i = 0; i < packages; i++, child++) + cpu = smp_topo_addleaf(top, child, share, count, flags, cpu); + return (top); +} + +struct cpu_group * +smp_topo_2level(int l2share, int l2count, int l1share, int l1count, + int l1flags) +{ + struct cpu_group *top; + struct cpu_group *l1g; + struct cpu_group *l2g; + int cpu; + int i; + int j; + + cpu = 0; + top = &group[0]; + l2g = &group[1]; + top->cg_child = l2g; + top->cg_level = CG_SHARE_NONE; + top->cg_children = mp_ncpus / (l2count * l1count); + l1g = l2g + top->cg_children; + for (i = 0; i < top->cg_children; i++, l2g++) { + l2g->cg_parent = top; + l2g->cg_child = l1g; + l2g->cg_level = l2share; + for (j = 0; j < l2count; j++, l1g++) + cpu = smp_topo_addleaf(l2g, l1g, l1share, l1count, + l1flags, cpu); + } + return (top); +} + + +struct cpu_group * +smp_topo_find(struct cpu_group *top, int cpu) +{ + struct cpu_group *cg; + cpumask_t mask; + int children; + int i; + + mask = (1 << cpu); + cg = top; + for (;;) { + if ((cg->cg_mask & mask) == 0) + return (NULL); + if (cg->cg_children == 0) + return (cg); + children = cg->cg_children; + for (i = 0, cg = cg->cg_child; i < children; cg++, i++) + if ((cg->cg_mask & mask) != 0) + break; + } + return (NULL); +} +#else /* !SMP */ void smp_rendezvous(void (*setup_func)(void *), @@ -416,4 +575,19 @@ smp_rendezvous(void (*setup_func)(void * if (teardown_func != NULL) teardown_func(arg); } + +/* + * Provide dummy SMP support for UP kernels. Modules that need to use SMP + * APIs will still work using this dummy support. + */ +static void +mp_setvariables_for_up(void *dummy) +{ + mp_ncpus = 1; + mp_maxid = PCPU_GET(cpuid); + all_cpus = PCPU_GET(cpumask); + KASSERT(PCPU_GET(cpuid) == 0, ("UP must have a CPU ID of zero")); +} +SYSINIT(cpu_mp_setvariables, SI_SUB_TUNABLES, SI_ORDER_FIRST, + mp_setvariables_for_up, NULL) #endif /* SMP */ Index: sys/kern/syscalls.master =================================================================== RCS file: /home/ncvs/src/sys/kern/syscalls.master,v retrieving revision 1.237 diff -u -p -r1.237 syscalls.master --- sys/kern/syscalls.master 12 Feb 2008 20:09:04 -0000 1.237 +++ sys/kern/syscalls.master 2 Mar 2008 02:58:10 -0000 @@ -850,5 +850,18 @@ 482 AUE_SHMOPEN STD { int shm_open(const char *path, int flags, \ mode_t mode); } 483 AUE_SHMUNLINK STD { int shm_unlink(const char *path); } +484 AUE_NULL STD { int cpuset(cpusetid_t *setid); } +485 AUE_NULL STD { int cpuset_setid(cpuwhich_t which, id_t id, \ + cpusetid_t setid); } +486 AUE_NULL STD { int cpuset_getid(cpulevel_t level, \ + cpuwhich_t which, id_t id, \ + cpusetid_t *setid); } +487 AUE_NULL STD { int cpuset_getaffinity(cpulevel_t level, \ + cpuwhich_t which, id_t id, int cpusetsize, \ + long *mask); } +488 AUE_NULL STD { int cpuset_setaffinity(cpulevel_t level, \ + cpuwhich_t which, id_t id, int cpusetsize, \ + long *mask); } + ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master Index: sys/powerpc/powerpc/mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/powerpc/powerpc/mp_machdep.c,v retrieving revision 1.13 diff -u -p -r1.13 mp_machdep.c --- sys/powerpc/powerpc/mp_machdep.c 16 May 2006 14:32:17 -0000 1.13 +++ sys/powerpc/powerpc/mp_machdep.c 2 Mar 2008 02:58:16 -0000 @@ -45,6 +45,13 @@ int boot_cpu_id; +struct cpu_group * +cpu_topo(void) +{ + + return smp_topo_none(); +} + void cpu_mp_setmaxid(void) { Index: sys/sparc64/sparc64/mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/sparc64/sparc64/mp_machdep.c,v retrieving revision 1.36 diff -u -p -r1.36 mp_machdep.c --- sys/sparc64/sparc64/mp_machdep.c 16 Jun 2007 23:26:00 -0000 1.36 +++ sys/sparc64/sparc64/mp_machdep.c 2 Mar 2008 02:58:16 -0000 @@ -189,6 +189,13 @@ cpu_mp_probe(void) return (mp_maxid > 0); } +struct cpu_group * +cpu_topo(void) +{ + + return smp_topo_none(); +} + static void sun4u_startcpu(phandle_t cpu, void *func, u_long arg) { Index: sys/sun4v/sun4v/mp_machdep.c =================================================================== RCS file: /home/ncvs/src/sys/sun4v/sun4v/mp_machdep.c,v retrieving revision 1.8 diff -u -p -r1.8 mp_machdep.c --- sys/sun4v/sun4v/mp_machdep.c 6 Jul 2007 00:41:53 -0000 1.8 +++ sys/sun4v/sun4v/mp_machdep.c 2 Mar 2008 02:58:16 -0000 @@ -241,6 +241,13 @@ cpu_mp_probe(void) return (mp_maxid > 0); } +struct cpu_group * +cpu_topo(void) +{ + + return smp_topo_none(); +} + static int start_ap_bycpuid(int cpuid, void *func, u_long arg) { Index: sys/sys/_types.h =================================================================== RCS file: /home/ncvs/src/sys/sys/_types.h,v retrieving revision 1.23 diff -u -p -r1.23 _types.h --- sys/sys/_types.h 1 Mar 2006 06:29:34 -0000 1.23 +++ sys/sys/_types.h 2 Mar 2008 02:58:16 -0000 @@ -61,6 +61,9 @@ typedef struct __timer *__timer_t; /* ti typedef struct __mq *__mqd_t; /* mq_open()... */ typedef __uint32_t __uid_t; typedef unsigned int __useconds_t; /* microseconds (unsigned) */ +typedef int __cpuwhich_t; /* which parameter for cpuset. */ +typedef int __cpulevel_t; /* level parameter for cpuset. */ +typedef int __cpusetid_t; /* cpuset identifier. */ /* * Unusual type definitions. Index: sys/sys/proc.h =================================================================== RCS file: /home/ncvs/src/sys/sys/proc.h,v retrieving revision 1.503 diff -u -p -r1.503 proc.h --- sys/sys/proc.h 7 Feb 2008 06:55:38 -0000 1.503 +++ sys/sys/proc.h 2 Mar 2008 02:58:16 -0000 @@ -163,6 +163,7 @@ struct thread; struct trapframe; struct turnstile; struct mqueue_notifier; +struct cpuset; /* * Here we define the two structures used for process information. @@ -208,7 +209,7 @@ struct thread { /* The two queues below should someday be merged. */ TAILQ_ENTRY(thread) td_slpq; /* (t) Sleep queue. */ TAILQ_ENTRY(thread) td_lockq; /* (t) Lock queue. */ - + struct cpuset *td_cpuset; /* (t) CPU affinity mask. */ struct seltd *td_sel; /* Select queue/channel. */ struct sleepqueue *td_sleepqueue; /* (k) Associated sleep queue. */ struct turnstile *td_turnstile; /* (k) Associated turnstile. */ Index: sys/sys/sched.h =================================================================== RCS file: /home/ncvs/src/sys/sys/sched.h,v retrieving revision 1.33 diff -u -p -r1.33 sched.h --- sys/sys/sched.h 12 Jun 2007 19:49:39 -0000 1.33 +++ sys/sys/sched.h 2 Mar 2008 02:58:16 -0000 @@ -32,7 +32,7 @@ */ /*- - * Copyright (c) 2002, Jeffrey Roberson + * Copyright (c) 2002-2008, Jeffrey Roberson * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -129,6 +129,7 @@ static __inline void sched_pin(void); void sched_unbind(struct thread *td); static __inline void sched_unpin(void); int sched_is_bound(struct thread *td); +void sched_affinity(struct thread *td); /* * These procedures tell the process data structure allocation code how @@ -175,6 +176,7 @@ extern long switch_needresched; void schedinit(void); void sched_newproc(struct proc *p, struct thread *td); void sched_newthread(struct thread *td); + #endif /* _KERNEL */ /* POSIX 1003.1b Process Scheduling */ Index: sys/sys/smp.h =================================================================== RCS file: /home/ncvs/src/sys/sys/smp.h,v retrieving revision 1.86 diff -u -p -r1.86 smp.h --- sys/sys/smp.h 8 Nov 2007 14:47:55 -0000 1.86 +++ sys/sys/smp.h 2 Mar 2008 02:58:16 -0000 @@ -32,18 +32,40 @@ */ struct cpu_group { - cpumask_t cg_mask; /* Mask of cpus in this group. */ - int cg_count; /* Count of cpus in this group. */ - int cg_children; /* Number of children groups. */ - struct cpu_group *cg_child; /* Optional child group. */ + struct cpu_group *cg_parent; /* Our parent group. */ + struct cpu_group *cg_child; /* Optional children groups. */ + cpumask_t cg_mask; /* Mask of cpus in this group. */ + int8_t cg_count; /* Count of cpus in this group. */ + int8_t cg_children; /* Number of children groups. */ + int8_t cg_level; /* Shared cache level. */ + int8_t cg_flags; /* Traversal modifiers. */ }; -struct cpu_top { - int ct_count; /* Count of groups. */ - struct cpu_group *ct_group; /* Array of pointers to cpu groups. */ -}; +/* + * Defines common resources for CPUs in the group. The highest level + * resource should be used when multiple are shared. + */ +#define CG_SHARE_NONE 0 +#define CG_SHARE_L1 1 +#define CG_SHARE_L2 2 +#define CG_SHARE_L3 3 + +/* + * Behavior modifiers for load balancing and affinity. + */ +#define CG_FLAG_HTT 0x01 /* Schedule the alternate core last. */ +#define CG_FLAG_THREAD 0x02 /* New age htt, less crippled. */ + +/* + * Convenience routines for building topologies. + */ +struct cpu_group *smp_topo(void); +struct cpu_group *smp_topo_none(void); +struct cpu_group *smp_topo_1level(int l1share, int l1count, int l1flags); +struct cpu_group *smp_topo_2level(int l2share, int l2count, int l1share, + int l1count, int l1flags); +struct cpu_group *smp_topo_find(struct cpu_group *top, int cpu); -extern struct cpu_top *smp_topology; extern void (*cpustop_restartfunc)(void); extern int smp_active; extern int smp_cpus; @@ -90,6 +112,7 @@ extern cpumask_t all_cpus; */ struct thread; +struct cpu_group *cpu_topo(void); void cpu_mp_announce(void); int cpu_mp_probe(void); void cpu_mp_setmaxid(void); Index: sys/sys/types.h =================================================================== RCS file: /home/ncvs/src/sys/sys/types.h,v retrieving revision 1.97 diff -u -p -r1.97 types.h --- sys/sys/types.h 28 Nov 2007 21:54:46 -0000 1.97 +++ sys/sys/types.h 2 Mar 2008 02:58:16 -0000 @@ -124,6 +124,10 @@ typedef __blksize_t blksize_t; #define _BLKSIZE_T_DECLARED #endif +typedef __cpuwhich_t cpuwhich_t; +typedef __cpulevel_t cpulevel_t; +typedef __cpusetid_t cpusetid_t; + #ifndef _BLKCNT_T_DECLARED typedef __blkcnt_t blkcnt_t; #define _BLKCNT_T_DECLARED Index: usr.bin/Makefile =================================================================== RCS file: /home/ncvs/src/usr.bin/Makefile,v retrieving revision 1.306 diff -u -p -r1.306 Makefile --- usr.bin/Makefile 20 Dec 2007 16:40:25 -0000 1.306 +++ usr.bin/Makefile 2 Mar 2008 02:58:20 -0000 @@ -42,6 +42,7 @@ SUBDIR= alias \ comm \ compile_et \ compress \ + cpuset \ csplit \ ${_csup} \ ctags \ Index: usr.bin/cpuset/Makefile =================================================================== RCS file: usr.bin/cpuset/Makefile diff -N usr.bin/cpuset/Makefile --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ usr.bin/cpuset/Makefile 2 Mar 2008 02:58:20 -0000 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +PROG= cpuset +NO_MAN= true +WARNS?= 1 + +.include