Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys - Another tweak for SMT: if a new LWP is starting life, ...



details:   https://anonhg.NetBSD.org/src/rev/a237655460f0
branches:  trunk
changeset: 968184:a237655460f0
user:      ad <ad%NetBSD.org@localhost>
date:      Sun Jan 05 20:26:56 2020 +0000

description:
- Another tweak for SMT: if a new LWP is starting life, try to make it run
  on a different CPU in the same CPU core as the parent, because both parent
  and child share lots of state.  (I want to come back later and do
  something different for _lwp_create() and maybe execve().)

- Remove the runqueue evcnts, which are racy and impose a penalty for very
  little payoff.

- Break out of the loop in sched_takecpu() as soon as we have a CPU that can
  run the LWP.  There's no need to look at all CPUs.

- SPCF_IDLE in sched_enqueue() so we know the CPU is not idle sooner.

diffstat:

 sys/kern/kern_runq.c |  71 ++++++++++++++++++++++++---------------------------
 sys/sys/sched.h      |   7 +----
 2 files changed, 35 insertions(+), 43 deletions(-)

diffs (178 lines):

diff -r f0b37e156711 -r a237655460f0 sys/kern/kern_runq.c
--- a/sys/kern/kern_runq.c      Sun Jan 05 20:17:43 2020 +0000
+++ b/sys/kern/kern_runq.c      Sun Jan 05 20:26:56 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_runq.c,v 1.54 2020/01/04 22:46:01 ad Exp $        */
+/*     $NetBSD: kern_runq.c,v 1.55 2020/01/05 20:26:56 ad Exp $        */
 
 /*-
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -56,7 +56,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_runq.c,v 1.54 2020/01/04 22:46:01 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_runq.c,v 1.55 2020/01/05 20:26:56 ad Exp $");
 
 #include "opt_dtrace.h"
 
@@ -178,15 +178,6 @@
        spc->spc_mutex = mutex_obj_alloc(MUTEX_DEFAULT, IPL_SCHED);
        for (i = 0; i < PRI_COUNT; i++)
                TAILQ_INIT(&spc->spc_queue[i]);
-
-       evcnt_attach_dynamic(&spc->spc_ev_pull, EVCNT_TYPE_MISC, NULL,
-          cpu_name(ci), "runqueue pull");
-       evcnt_attach_dynamic(&spc->spc_ev_push, EVCNT_TYPE_MISC, NULL,
-          cpu_name(ci), "runqueue push");
-       evcnt_attach_dynamic(&spc->spc_ev_stay, EVCNT_TYPE_MISC, NULL,
-          cpu_name(ci), "runqueue stay");
-       evcnt_attach_dynamic(&spc->spc_ev_localize, EVCNT_TYPE_MISC, NULL,
-          cpu_name(ci), "runqueue localize");
 }
 
 /*
@@ -235,6 +226,7 @@
        } else {
                TAILQ_INSERT_TAIL(q_head, l, l_runq);
        }
+       spc->spc_flags &= ~SPCF_IDLE;
        spc->spc_count++;
        if ((l->l_pflag & LP_BOUND) == 0)
                spc->spc_mcount++;
@@ -474,15 +466,33 @@
        spc = &ci->ci_schedstate;
        eprio = lwp_eprio(l);
 
+       /*
+        * For new LWPs (LSIDL), l_cpu was inherited from the parent when
+        * the LWP was created (and is probably still curcpu at this point).
+        * The child will initially be in close communication with the
+        * parent and share VM context and cache state.  Look for an idle
+        * SMT sibling to run it, and failing that run on the same CPU as
+        * the parent.
+        */
+       if (l->l_stat == LSIDL) {
+               tci = ci->ci_sibling[CPUREL_CORE];
+               while (tci != ci) {
+                       ici_spc = &tci->ci_schedstate;
+                       if (l->l_psid == ici_spc->spc_psid &&
+                           (ici_spc->spc_flags & SPCF_IDLE) != 0) {
+                               return tci;
+                       }
+                       tci = tci->ci_sibling[CPUREL_CORE];
+               }
+               if (spc->spc_psid == l->l_psid) {
+                       return ci;
+               }
+       }
+
        /* If SMT primary is idle, send it back there. */
        tci = ci->ci_smt_primary;
        if ((tci->ci_schedstate.spc_flags & SPCF_IDLE) != 0 &&
            sched_migratable(l, tci)) {
-               if (tci != ci) {
-                       spc->spc_ev_push.ev_count++;
-               } else {
-                       spc->spc_ev_stay.ev_count++;
-               }
                return tci;
        }
 
@@ -490,23 +500,11 @@
        if (__predict_true(spc->spc_psid == l->l_psid)) {
                /* If CPU of this thread is idling - run there */
                if (spc->spc_count == 0) {
-                       spc->spc_ev_stay.ev_count++;
                        return ci;
                }
-               /*
-                * New LWPs must start on the same CPU as the parent (l_cpu
-                * was inherited when the LWP was created).  Doing otherwise
-                * is bad for performance and repeatability, and agitates
-                * buggy programs.  Also, we want the child to have a good
-                * chance of reusing the VM context from the parent.
-                */
-               if (l->l_stat == LSIDL) {
-                       spc->spc_ev_stay.ev_count++;
-                       return ci;
-               }                
+
                /* Stay if thread is cache-hot */
                if (lwp_cache_hot(l) && eprio >= spc->spc_curpriority) {
-                       spc->spc_ev_stay.ev_count++;
                        return ci;
                }
        }
@@ -515,8 +513,6 @@
        ci = curcpu();
        spc = &ci->ci_schedstate;
        if (eprio > spc->spc_curpriority && sched_migratable(l, ci)) {
-               /* XXXAD foreign CPU not locked */
-               spc->spc_ev_localize.ev_count++;
                return ci;
        }
 
@@ -543,7 +539,7 @@
 
                if (pri == lpri) {
                        /* Pick the least busy CPU. */
-                       if (spc->spc_count < ici_spc->spc_count)
+                       if (spc->spc_count <= ici_spc->spc_count)
                                continue;
 
                        /* Prefer SMT primaries over secondaries. */
@@ -555,11 +551,13 @@
                lpri = pri;
                tci = ci;
                spc = ici_spc;
+
+               /* If this CPU is idle and an SMT primary, we're done. */
+               if ((spc->spc_flags & (SPCF_IDLE | SPCF_SMTPRIMARY)) ==
+                   (SPCF_IDLE | SPCF_SMTPRIMARY)) {
+                       break;
+               }
        } while (ci = next, ci != pivot);
-
-       /* XXXAD remote CPU, unlocked */
-       tci->ci_schedstate.spc_ev_push.ev_count++;
-
        return tci;
 }
 
@@ -626,7 +624,6 @@
                                SPINLOCK_BACKOFF(count);
                }
                l->l_cpu = curci;
-               spc->spc_ev_pull.ev_count++;
                lwp_unlock_to(l, curspc->spc_mutex);
                sched_enqueue(l);
                return l;
diff -r f0b37e156711 -r a237655460f0 sys/sys/sched.h
--- a/sys/sys/sched.h   Sun Jan 05 20:17:43 2020 +0000
+++ b/sys/sys/sched.h   Sun Jan 05 20:26:56 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sched.h,v 1.82 2019/12/21 11:54:04 ad Exp $    */
+/*     $NetBSD: sched.h,v 1.83 2020/01/05 20:26:56 ad Exp $    */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2002, 2007, 2008, 2019
@@ -144,7 +144,6 @@
 
 #include <sys/mutex.h>
 #include <sys/time.h>
-#include <sys/evcnt.h>
 
 /*
  * Per-CPU scheduler state.  Field markings and the corresponding locks: 
@@ -174,10 +173,6 @@
        u_int           spc_mcount;     /* m: count of migratable threads */
        uint32_t        spc_bitmap[8];  /* m: bitmap of active queues */
        TAILQ_HEAD(,lwp) *spc_queue;    /* m: queue for each priority */
-       struct evcnt    spc_ev_pull;    /* m: event counters */
-       struct evcnt    spc_ev_push;
-       struct evcnt    spc_ev_stay;
-       struct evcnt    spc_ev_localize;
 };
 
 /* spc_flags */



Home | Main Index | Thread Index | Old Index