On Wed, 22 Apr 2009, John Baldwin wrote:

 Adjust the way we number CPUs on x86 so that we attempt to "group" all
 logical CPUs in a package.  We do this by numbering the non-boot CPUs
 by starting with the first CPU whose APIC ID is after the boot CPU and
 wrapping back around to APIC ID 0 if needed rather than always starting
 at APIC ID 0.  While here, adjust the cpu_mp_announce() routine to list
 CPUs based on the mapping established by assign_cpu_ids() rather than
 making assumptions about the algorithm assign_cpu_ids() uses.

Something we'd like to be able to do in the fairly near future is assign work from one thread/core to another thread/core that is cache-wise "close" to the current one. For example, if we take a cacheline miss on an mbuf head and the first line of a packet's data on one CPU, and want to hand it off to another CPU for further processing, trying to send it somewhere where it's already quite close, cache-wise, might well be beneficial. Likewise, sending it to another thread or core that is cache-wise close on the lock protecting the queue used to pass it between CPUs, would also be nice.

Do you have any ideas about ways to usefully represent and manage concepts like "pick a close CPU" or "the set of CPUs that are close"? For example, if I have available a flow identifier, hashing to one of a set of available CPUs is easy, but what would you suggest as an efficient representation to hash from a set of close available CPUs rather than the entire pool?

Robert N M Watson
Computer Laboratory
University of Cambridge



 MFC after:     1 month

Modified:
 head/sys/amd64/amd64/mp_machdep.c
 head/sys/i386/i386/mp_machdep.c

Modified: head/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- head/sys/amd64/amd64/mp_machdep.c   Wed Apr 22 20:58:23 2009        
(r191404)
+++ head/sys/amd64/amd64/mp_machdep.c   Wed Apr 22 21:40:37 2009        
(r191405)
@@ -354,8 +354,6 @@ cpu_mp_start(void)
        } else
                KASSERT(boot_cpu_id == PCPU_GET(apic_id),
                    ("BSP's APIC ID doesn't match boot_cpu_id"));
-       cpu_apic_ids[0] = boot_cpu_id;
-       apic_cpuids[boot_cpu_id] = 0;

        /* Setup the initial logical CPUs info. */
        logical_cpus = logical_cpus_mask = 0;
@@ -418,28 +416,30 @@ cpu_mp_start(void)
void
cpu_mp_announce(void)
{
-       int i, x;
        const char *hyperthread;
+       int i;

-       /* List CPUs */
+       /* List active CPUs first. */
        printf(" cpu0 (BSP): APIC ID: %2d\n", boot_cpu_id);
-       for (i = 1, x = 0; x <= MAX_APIC_ID; x++) {
-               if (!cpu_info[x].cpu_present || cpu_info[x].cpu_bsp)
+       for (i = 1; i < mp_ncpus; i++) {
+               if (cpu_info[cpu_apic_ids[i]].cpu_hyperthread)
+                       hyperthread = "/HT";
+               else
+                       hyperthread = "";
+               printf(" cpu%d (AP%s): APIC ID: %2d\n", i, hyperthread,
+                   cpu_apic_ids[i]);
+       }
+
+       /* List disabled CPUs last. */
+       for (i = 0; i <= MAX_APIC_ID; i++) {
+               if (!cpu_info[i].cpu_present || !cpu_info[i].cpu_disabled)
                        continue;
-               if (cpu_info[x].cpu_hyperthread) {
+               if (cpu_info[i].cpu_hyperthread)
                        hyperthread = "/HT";
-               } else {
+               else
                        hyperthread = "";
-               }
-               if (cpu_info[x].cpu_disabled)
-                       printf("  cpu (AP%s): APIC ID: %2d (disabled)\n",
-                           hyperthread, x);
-               else {
-                       KASSERT(i < mp_ncpus,
-                           ("mp_ncpus and actual cpus are out of whack"));
-                       printf(" cpu%d (AP%s): APIC ID: %2d\n", i++,
-                           hyperthread, x);
-               }
+               printf("  cpu (AP%s): APIC ID: %2d (disabled)\n", hyperthread,
+                   i);
        }
}

@@ -693,11 +693,19 @@ assign_cpu_ids(void)

        /*
         * Assign CPU IDs to local APIC IDs and disable any CPUs
-        * beyond MAXCPU.  CPU 0 has already been assigned to the BSP,
-        * so we only have to assign IDs for APs.
+        * beyond MAXCPU.  CPU 0 is always assigned to the BSP.
+        *
+        * To minimize confusion for userland, we attempt to number
+        * CPUs such that all threads and cores in a package are
+        * grouped together.  For now we assume that the BSP is always
+        * the first thread in a package and just start adding APs
+        * starting with the BSP's APIC ID.
         */
        mp_ncpus = 1;
-       for (i = 0; i <= MAX_APIC_ID; i++) {
+       cpu_apic_ids[0] = boot_cpu_id;
+       apic_cpuids[boot_cpu_id] = 0;
+       for (i = boot_cpu_id + 1; i != boot_cpu_id;
+            i == MAX_APIC_ID ? i = 0 : i++) {
                if (!cpu_info[i].cpu_present || cpu_info[i].cpu_bsp ||
                    cpu_info[i].cpu_disabled)
                        continue;

Modified: head/sys/i386/i386/mp_machdep.c
==============================================================================
--- head/sys/i386/i386/mp_machdep.c     Wed Apr 22 20:58:23 2009        
(r191404)
+++ head/sys/i386/i386/mp_machdep.c     Wed Apr 22 21:40:37 2009        
(r191405)
@@ -398,8 +398,6 @@ cpu_mp_start(void)
        } else
                KASSERT(boot_cpu_id == PCPU_GET(apic_id),
                    ("BSP's APIC ID doesn't match boot_cpu_id"));
-       cpu_apic_ids[0] = boot_cpu_id;
-       apic_cpuids[boot_cpu_id] = 0;

        /* Setup the initial logical CPUs info. */
        logical_cpus = logical_cpus_mask = 0;
@@ -462,28 +460,30 @@ cpu_mp_start(void)
void
cpu_mp_announce(void)
{
-       int i, x;
        const char *hyperthread;
+       int i;

-       /* List CPUs */
+       /* List active CPUs first. */
        printf(" cpu0 (BSP): APIC ID: %2d\n", boot_cpu_id);
-       for (i = 1, x = 0; x <= MAX_APIC_ID; x++) {
-               if (!cpu_info[x].cpu_present || cpu_info[x].cpu_bsp)
+       for (i = 1; i < mp_ncpus; i++) {
+               if (cpu_info[cpu_apic_ids[i]].cpu_hyperthread)
+                       hyperthread = "/HT";
+               else
+                       hyperthread = "";
+               printf(" cpu%d (AP%s): APIC ID: %2d\n", i, hyperthread,
+                   cpu_apic_ids[i]);
+       }
+
+       /* List disabled CPUs last. */
+       for (i = 0; i <= MAX_APIC_ID; i++) {
+               if (!cpu_info[i].cpu_present || !cpu_info[i].cpu_disabled)
                        continue;
-               if (cpu_info[x].cpu_hyperthread) {
+               if (cpu_info[i].cpu_hyperthread)
                        hyperthread = "/HT";
-               } else {
+               else
                        hyperthread = "";
-               }
-               if (cpu_info[x].cpu_disabled)
-                       printf("  cpu (AP%s): APIC ID: %2d (disabled)\n",
-                           hyperthread, x);
-               else {
-                       KASSERT(i < mp_ncpus,
-                           ("mp_ncpus and actual cpus are out of whack"));
-                       printf(" cpu%d (AP%s): APIC ID: %2d\n", i++,
-                           hyperthread, x);
-               }
+               printf("  cpu (AP%s): APIC ID: %2d (disabled)\n", hyperthread,
+                   i);
        }
}

@@ -722,11 +722,19 @@ assign_cpu_ids(void)

        /*
         * Assign CPU IDs to local APIC IDs and disable any CPUs
-        * beyond MAXCPU.  CPU 0 has already been assigned to the BSP,
-        * so we only have to assign IDs for APs.
+        * beyond MAXCPU.  CPU 0 is always assigned to the BSP.
+        *
+        * To minimize confusion for userland, we attempt to number
+        * CPUs such that all threads and cores in a package are
+        * grouped together.  For now we assume that the BSP is always
+        * the first thread in a package and just start adding APs
+        * starting with the BSP's APIC ID.
         */
        mp_ncpus = 1;
-       for (i = 0; i <= MAX_APIC_ID; i++) {
+       cpu_apic_ids[0] = boot_cpu_id;
+       apic_cpuids[boot_cpu_id] = 0;
+       for (i = boot_cpu_id + 1; i != boot_cpu_id;
+            i == MAX_APIC_ID ? i = 0 : i++) {
                if (!cpu_info[i].cpu_present || cpu_info[i].cpu_bsp ||
                    cpu_info[i].cpu_disabled)
                        continue;

_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to