Source-Changes-HG archive

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

[src/trunk]: src/sys Reimplement VP donation such that multiple unblocked upc...



details:   https://anonhg.NetBSD.org/src/rev/3199ea0446ed
branches:  trunk
changeset: 554894:3199ea0446ed
user:      cl <cl%NetBSD.org@localhost>
date:      Mon Nov 03 22:34:51 2003 +0000

description:
Reimplement VP donation such that multiple unblocked upcalls can be
combined.  Also prepare for adding VP repossession later.

- kern_sa.c: sa_yield/sa_switch: detect if there are pending unblocked
  upcalls.
- kern_sa.c: sa_unblock_userret/sa_setwoken: queue LWPs about to invoke
  an unblocked upcall on the sa_wokenq.  put queued LWPs in a state where
  they can be put in the cache.  notify LWP on the VP about pending
  upcalls.
- kern_sa.c: sa_upcall_userret: check sa_wokenq for pending upcalls,
  generate unblocked upcalls with multiple event sas
- kern_sa.c: sa_vp_repossess/sa_vp_donate: g/c, restore original
  sa_vp_repossess

diffstat:

 sys/kern/kern_exit.c |   10 +-
 sys/kern/kern_sa.c   |  513 ++++++++++++++++++++++++++++----------------------
 sys/kern/kern_sig.c  |    9 +-
 sys/sys/lwp.h        |    3 +-
 sys/sys/savar.h      |    7 +-
 5 files changed, 297 insertions(+), 245 deletions(-)

diffs (truncated from 815 to 300 lines):

diff -r e2b593b4e81e -r 3199ea0446ed sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c      Mon Nov 03 22:17:42 2003 +0000
+++ b/sys/kern/kern_exit.c      Mon Nov 03 22:34:51 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_exit.c,v 1.124 2003/09/16 13:46:24 cl Exp $       */
+/*     $NetBSD: kern_exit.c,v 1.125 2003/11/03 22:34:51 cl Exp $       */
 
 /*-
  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.124 2003/09/16 13:46:24 cl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.125 2003/11/03 22:34:51 cl Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_perfctrs.h"
@@ -491,14 +491,8 @@
         * them) and then wait for everyone else to finish.  
         */
        LIST_FOREACH(l2, &p->p_lwps, l_sibling) {
-#if 0
                l2->l_flag &= ~(L_DETACHED|L_SA);
-#endif 
-               l2->l_flag &= ~(L_DETACHED);
        
-               if(l2->l_flag & L_SA_WANTS_VP)
-                       wakeup(l2);
-
                if (l2->l_wchan == &l2->l_upcallstack)
                        wakeup(&l2->l_upcallstack);
 
diff -r e2b593b4e81e -r 3199ea0446ed sys/kern/kern_sa.c
--- a/sys/kern/kern_sa.c        Mon Nov 03 22:17:42 2003 +0000
+++ b/sys/kern/kern_sa.c        Mon Nov 03 22:34:51 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_sa.c,v 1.38 2003/11/02 17:04:05 jdolecek Exp $    */
+/*     $NetBSD: kern_sa.c,v 1.39 2003/11/03 22:34:51 cl Exp $  */
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.38 2003/11/02 17:04:05 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.39 2003/11/03 22:34:51 cl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -53,7 +53,7 @@
 
 #include <uvm/uvm_extern.h>
 
-static void sa_vp_donate(struct lwp *);
+static void sa_setwoken(struct lwp *);
 static int sa_newcachelwp(struct lwp *);
 static struct lwp *sa_vp_repossess(struct lwp *l);
 
@@ -150,8 +150,7 @@
                simple_lock_init(&sa->sa_lock);
                sa->sa_flag = SCARG(uap, flags) & SA_FLAG_ALL;
                sa->sa_vp = NULL;
-               sa->sa_old_lwp = NULL;
-               sa->sa_vp_wait_count = 0;
+               sa->sa_wokenq_head = NULL;
                sa->sa_concurrency = 1;
                sa->sa_stacks = malloc(sizeof(stack_t) * SA_NUMSTACKS,
                    M_SA, M_WAITOK);
@@ -215,7 +214,7 @@
                }
        }
 
-       if ((sa->sa_nstacks == 0) && (sa->sa_vp_wait_count != 0))
+       if ((sa->sa_nstacks == 0) && (sa->sa_wokenq_head != NULL))
                l->l_flag |= L_SA_UPCALL; 
 
        /*
@@ -334,64 +333,47 @@
 void
 sa_yield(struct lwp *l)
 {
-#if 0
-       struct lwp *l2;
-#endif
        struct proc *p = l->l_proc;
 #ifdef DEBUG
        struct sadata *sa = p->p_sa;
 #endif
        int ret, s;
-       
+
+#if defined(MULTIPROCESSOR)
+       KDASSERT(l->l_flag & L_BIGLOCK);
+#endif
        /*
         * If we're the last running LWP, stick around to recieve
         * signals.
         */
-#if 0
-       if (p->p_nrlwps == 1) {
-#endif
-               DPRINTFN(1,("sa_yield(%d.%d) going dormant\n",
-                   p->p_pid, l->l_lid));
-               /*
-                * A signal will probably wake us up. Worst case, the upcall
-                * happens and just causes the process to yield again.
-                */     
-               SCHED_ASSERT_UNLOCKED();
-
-               sa_vp_donate(l);
-
-               SCHED_ASSERT_UNLOCKED();
-
-               s = splsched(); /* Protect from timer expirations */
+       KDASSERT((l->l_flag & L_SA_YIELD) == 0);
+       DPRINTFN(1,("sa_yield(%d.%d) going dormant\n",
+                    p->p_pid, l->l_lid));
+       /*
+        * A signal will probably wake us up. Worst case, the upcall
+        * happens and just causes the process to yield again.
+        */     
+       s = splsched(); /* Protect from timer expirations */
+       KDASSERT(sa->sa_vp == l);
+       /*
+        * If we were told to make an upcall or exit before
+        * the splsched(), make sure we process it instead of
+        * going to sleep. It might make more sense for this to
+        * be handled inside of tsleep....
+        */
+       ret = 0;        
+       while (ret == 0 && p->p_userret == NULL &&
+           (l->l_flag & L_SA_UPCALL) == 0) {
+               l->l_flag |= L_SA_YIELD;
+               ret = tsleep((caddr_t) l, PUSER | PCATCH, "sawait", 0);
+               l->l_flag &= ~L_SA_YIELD;
+               if (p->p_flag & P_WEXIT)
+                       lwp_exit(l);
                KDASSERT(sa->sa_vp == l);
-               /*
-                * If we were told to make an upcall or exit before
-                * the splsched(), make sure we process it instead of
-                * going to sleep. It might make more sense for this to
-                * be handled inside of tsleep....
-                */
-               ret = 0;        
-
-               while  ((ret == 0) && (p->p_userret == NULL)) {
-                       l->l_flag |= L_SA_YIELD;
-                       ret = tsleep((caddr_t) l, PUSER | PCATCH, "sawait", 0);
-                       l->l_flag &= ~L_SA_YIELD;
-                       if (p->p_flag & P_WEXIT)
-                               lwp_exit(l);
-                       KDASSERT(sa->sa_vp == l);
-
-                       splx(s);
-                       sa_vp_donate(l);
-                       KDASSERT(sa->sa_vp == l);
-                       s = splsched(); /* Protect from timer expirations */
-               }
-               l->l_flag |= L_SA_UPCALL; 
-               splx(s);
-               DPRINTFN(1,("sa_yield(%d.%d) returned\n",
-                   p->p_pid, l->l_lid));
-#if 0
        }
-#endif
+       splx(s);
+       DPRINTFN(1,("sa_yield(%d.%d) returned\n",
+                    p->p_pid, l->l_lid));
 }
 
 
@@ -726,8 +708,10 @@
                /*
                 * Case 0: we're blocking in sa_yield
                 */
-               l->l_flag |= L_SA_IDLE;
-               mi_switch(l, NULL);
+               if (sa->sa_wokenq_head == NULL) {
+                       l->l_flag |= L_SA_IDLE;
+                       mi_switch(l, NULL);
+               }
                return;
        } else if (sa->sa_vp == l) {
                /*
@@ -849,62 +833,26 @@
                                l2 = NULL;
                }
        } else {
-#if 0
-               /*
-                * Case 3: The VP is empty. As in case 2, we were
-                * woken up and called tsleep again, but additionally,
-                * the running LWP called sa_yield() between our wakeup() and
-                * when we got to run again (in fact, it probably was
-                * responsible for switching to us, via sa_woken).
-                * The right thing is to pull a LWP off the cache and have
-                * it jump straight back into sa_yield.
-                */
-               l2 = sa_getcachelwp(p);
-               if (l2 == NULL) {
-#ifdef DIAGNOSTIC
-                       printf("sa_switch(%d.%d): no cached LWP for reidling.\n",
-                           p->p_pid, l->l_lid);
-#endif
-                       mi_switch(l, NULL);
-                       return;
-               }
-#else
-               mi_switch(l, NULL);
-               return;
-#endif
-               
+               /* NOTREACHED */
+               panic("sa_vp empty");
+
        sa_upcall_failed:
-#if 0
                cpu_setfunc(l2, sa_yieldcall, l2);
 
                l2->l_priority = l2->l_usrpri;
                setrunnable(l2);
                PRELE(l2); /* Remove the artificial hold-count */
-#else
-               /* sa_putcachelwp does not block because we have a hold count on l2 */
-               sa_putcachelwp(p, l2); /* PHOLD from sa_getcachelwp */
-
-               mi_switch(l, NULL);
-               return;
-#endif
        }
 
        DPRINTFN(4,("sa_switch(%d.%d) switching to LWP %d.\n",
            p->p_pid, l->l_lid, l2 ? l2->l_lid : 0));
        mi_switch(l, l2);
 
-       DPRINTFN(4,("sa_switch(%d.%d flag %x) returned.\n", p->p_pid, l->l_lid, l->l_flag));
+       DPRINTFN(4,("sa_switch(%d.%d flag %x) returned.\n",
+           p->p_pid, l->l_lid, l->l_flag));
        KDASSERT(l->l_wchan == 0);
 
        SCHED_ASSERT_UNLOCKED();
-
-       /*
-        * The process is trying to exit. In this case, the last thing
-        * we want to do is put something back on the cache list.
-        * It's also not useful to make the upcall at all, so just punt.
-        */
-       if (p->p_flag & P_WEXIT)
-               return;
 }
 
 void
@@ -933,7 +881,6 @@
        upcallret(l);
 }
 
-#if 0
 void
 sa_yieldcall(void *arg)
 {
@@ -958,7 +905,6 @@
        sa_yield(l);
        upcallret(l);
 }
-#endif
 
 static int
 sa_newcachelwp(struct lwp *l)
@@ -1094,6 +1040,10 @@
 
        if (l->l_flag & L_SA_BLOCKING) {
                /* Invoke an "unblocked" upcall */
+
+               sa_setwoken(l);
+               /* maybe NOTREACHED */
+
                DPRINTFN(8,("sa_unblock_userret(%d.%d) unblocking\n",
                    p->p_pid, l->l_lid));
 
@@ -1112,7 +1062,7 @@
                        sadata_upcall_free(sau);
                        lwp_exit(l);
                }
-       
+
                KDASSERT(sa->sa_nstacks > 0);
                st = sa->sa_stacks[--sa->sa_nstacks];
                DPRINTFN(9,("sa_unblock_userret(%d.%d) nstacks--   = %2d\n",
@@ -1151,15 +1101,18 @@
 void
 sa_upcall_userret(struct lwp *l)
 {
+       struct lwp *l2, *eventq;
        struct proc *p;
        struct sadata *sa;
        struct sa_t **sapp, *sap;
        struct sadata_upcall *sau;



Home | Main Index | Thread Index | Old Index