MP Implmentation 2A/4: Post commit cleanup, fix missing token releases that
authorMatthew Dillon <dillon@dragonflybsd.org>
Tue, 8 Jul 2003 09:57:14 +0000 (09:57 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Tue, 8 Jul 2003 09:57:14 +0000 (09:57 +0000)
were messing up td_pri's critical count, and add smart LWKT rescheduling
when a higher priority thread is scheduled (and could not preempt).  This
fixes the priority problems.

sys/i386/i386/machdep.c
sys/kern/lwkt_thread.c
sys/platform/pc32/i386/machdep.c
sys/sys/thread2.h
sys/vfs/gnu/ext2fs/ext2_vfsops.c
sys/vfs/hpfs/hpfs_hash.c
sys/vfs/ufs/ffs_vfsops.c
sys/vfs/ufs/ufs_ihash.c

index 47b4560..ff5eee1 100644 (file)
@@ -36,7 +36,7 @@
  *
  *     from: @(#)machdep.c     7.4 (Berkeley) 6/3/91
  * $FreeBSD: src/sys/i386/i386/machdep.c,v 1.385.2.30 2003/05/31 08:48:05 alc Exp $
- * $DragonFly: src/sys/i386/i386/Attic/machdep.c,v 1.23 2003/07/08 06:27:26 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/machdep.c,v 1.24 2003/07/08 09:57:11 dillon Exp $
  */
 
 #include "apm.h"
@@ -959,6 +959,7 @@ void
 cpu_idle(void)
 {
        crit_exit();
+       KKASSERT(curthread->td_pri < TDPRI_CRIT);
        for (;;) {
                lwkt_switch();
                __asm __volatile("cli");
index 02d43bc..b8692fa 100644 (file)
@@ -28,7 +28,7 @@
  *     to use a critical section to avoid problems.  Foreign thread 
  *     scheduling is queued via (async) IPIs.
  *
- * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.16 2003/07/08 06:27:27 dillon Exp $
+ * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.17 2003/07/08 09:57:13 dillon Exp $
  */
 
 #include <sys/param.h>
 #include <vm/vm_zone.h>
 
 #include <machine/stdarg.h>
+#include <machine/ipl.h>
 #ifdef SMP
 #include <machine/smp.h>
 #endif
 
 static int untimely_switch = 0;
 SYSCTL_INT(_lwkt, OID_AUTO, untimely_switch, CTLFLAG_RW, &untimely_switch, 0, "");
+#ifdef INVARIANTS
+static int token_debug = 0;
+SYSCTL_INT(_lwkt, OID_AUTO, token_debug, CTLFLAG_RW, &token_debug, 0, "");
+#endif
 static quad_t switch_count = 0;
 SYSCTL_QUAD(_lwkt, OID_AUTO, switch_count, CTLFLAG_RW, &switch_count, 0, "");
 static quad_t preempt_hit = 0;
@@ -113,6 +118,13 @@ _lwkt_enqueue(thread_t td)
     }
 }
 
+static __inline
+int
+_lwkt_wantresched(thread_t ntd, thread_t cur)
+{
+    return((ntd->td_pri & TDPRI_MASK) > (cur->td_pri & TDPRI_MASK));
+}
+
 /*
  * LWKTs operate on a per-cpu basis
  *
@@ -281,9 +293,6 @@ lwkt_free_thread(thread_t td)
  * the target thread (not the current thread).
  */
 
-int swtarg[32][2];
-int swtarg2;
-
 void
 lwkt_switch(void)
 {
@@ -407,13 +416,6 @@ again:
        ASSERT_MP_LOCK_HELD();
     }
 #endif
-
-       if (mycpu->gd_cpuid == 1) {
-       bcopy(swtarg[0], swtarg[1], sizeof(int)*31*2);
-       swtarg[0][0] = (int)ntd->td_sp;
-       swtarg[0][1] = *(int *)ntd->td_sp;
-       }
-       KKASSERT(td->td_cpu == ntd->td_cpu);
     if (td != ntd) {
        td->td_switch(ntd);
     }
@@ -458,21 +460,27 @@ lwkt_preempt(thread_t ntd, int critpri)
     thread_t td = curthread;
 #ifdef SMP
     int mpheld;
+    int savecnt;
 #endif
-int savecnt;
 
     /*
      * The caller has put us in a critical section.  We can only preempt
      * if the caller of the caller was not in a critical section (basically
-     * a local interrupt). 
+     * a local interrupt), as determined by the 'critpri' parameter.   If
+     * we are unable to preempt 
      *
      * YYY The target thread must be in a critical section (else it must
      * inherit our critical section?  I dunno yet).
      */
     KASSERT(ntd->td_pri >= TDPRI_CRIT, ("BADCRIT0 %d", ntd->td_pri));
 
+    if (!_lwkt_wantresched(ntd, td)) {
+       ++preempt_miss;
+       return;
+    }
     if ((td->td_pri & ~TDPRI_MASK) > critpri) {
        ++preempt_miss;
+       need_resched();
        return;
     }
 #ifdef SMP
@@ -483,14 +491,12 @@ int savecnt;
 #endif
     if (td == ntd || ((td->td_flags | ntd->td_flags) & TDF_PREEMPT_LOCK)) {
        ++preempt_weird;
+       need_resched();
        return;
     }
     if (ntd->td_preempted) {
        ++preempt_hit;
-       return;
-    }
-    if ((ntd->td_pri & TDPRI_MASK) <= (td->td_pri & TDPRI_MASK)) {
-       ++preempt_miss;
+       need_resched();
        return;
     }
 #ifdef SMP
@@ -502,6 +508,7 @@ int savecnt;
     if (mpheld == 0 && ntd->td_mpcount && !cpu_try_mplock()) {
        ntd->td_mpcount -= td->td_mpcount;
        ++preempt_miss;
+       need_resched();
        return;
     }
 #endif
@@ -653,8 +660,11 @@ lwkt_schedule(thread_t td)
                td->td_wait = NULL;
                if (td->td_cpu == mycpu->gd_cpuid) {
                    _lwkt_enqueue(td);
-                   if (td->td_preemptable)
+                   if (td->td_preemptable) {
                        td->td_preemptable(td, TDPRI_CRIT*2); /* YYY +token */
+                   } else if (_lwkt_wantresched(td, curthread)) {
+                       need_resched();
+                   }
                } else {
                    lwkt_send_ipiq(td->td_cpu, (ipifunc_t)lwkt_schedule, td);
                }
@@ -671,8 +681,11 @@ lwkt_schedule(thread_t td)
             */
            if (td->td_cpu == mycpu->gd_cpuid) {
                _lwkt_enqueue(td);
-               if (td->td_preemptable)
+               if (td->td_preemptable) {
                    td->td_preemptable(td, TDPRI_CRIT);
+               } else if (_lwkt_wantresched(td, curthread)) {
+                   need_resched();
+               }
            } else {
                lwkt_send_ipiq(td->td_cpu, (ipifunc_t)lwkt_schedule, td);
            }
@@ -733,6 +746,7 @@ void
 lwkt_setpri(thread_t td, int pri)
 {
     KKASSERT(pri >= 0);
+    KKASSERT(td->td_cpu == mycpu->gd_cpuid);
     crit_enter();
     if (td->td_flags & TDF_RUNQ) {
        _lwkt_dequeue(td);
@@ -859,6 +873,9 @@ lwkt_signal(lwkt_wait_t w)
  * requesting cpu, unless it has already changed hands.  Since only the
  * current cpu can give away a token it owns we do not need a memory barrier.
  */
+
+#ifdef SMP
+
 static
 void
 lwkt_gettoken_remote(void *arg)
@@ -869,6 +886,8 @@ lwkt_gettoken_remote(void *arg)
     }
 }
 
+#endif
+
 int
 lwkt_gettoken(lwkt_token_t tok)
 {
@@ -878,12 +897,21 @@ lwkt_gettoken(lwkt_token_t tok)
      * block.  The request will be forwarded as necessary playing catchup
      * to the token.
      */
-    struct lwkt_gettoken_req req;
-    int seq;
 
     crit_enter();
+#ifdef INVARIANTS
+    if (token_debug) {
+       printf("gettoken %p %d/%d\n", ((int **)&tok)[-1], (curthread->td_proc?curthread->td_proc->p_pid:-1), curthread->td_pri);
+       if (curthread->td_pri > 2000) {
+           curthread->td_pri = 1000;
+           panic("too HIGH!");
+       }
+    }
+#endif
 #ifdef SMP
     while (tok->t_cpu != mycpu->gd_cpuid) {
+       struct lwkt_gettoken_req req;
+       int seq;
        int dcpu;
 
        req.cpu = mycpu->gd_cpuid;
@@ -966,14 +994,14 @@ lwkt_gentoken(lwkt_token_t tok, int *gen)
 int
 lwkt_regettoken(lwkt_token_t tok)
 {
-    struct lwkt_gettoken_req req;
-    int seq;
-
     /* assert we are in a critical section */
     if (tok->t_cpu != mycpu->gd_cpuid) {
 #ifdef SMP
        while (tok->t_cpu != mycpu->gd_cpuid) {
+           struct lwkt_gettoken_req req;
+           int seq;
            int dcpu;
+
            req.cpu = mycpu->gd_cpuid;
            req.tok = tok;
            dcpu = (volatile int)tok->t_cpu;
index 9894f72..616cc89 100644 (file)
@@ -36,7 +36,7 @@
  *
  *     from: @(#)machdep.c     7.4 (Berkeley) 6/3/91
  * $FreeBSD: src/sys/i386/i386/machdep.c,v 1.385.2.30 2003/05/31 08:48:05 alc Exp $
- * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.23 2003/07/08 06:27:26 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.24 2003/07/08 09:57:11 dillon Exp $
  */
 
 #include "apm.h"
@@ -959,6 +959,7 @@ void
 cpu_idle(void)
 {
        crit_exit();
+       KKASSERT(curthread->td_pri < TDPRI_CRIT);
        for (;;) {
                lwkt_switch();
                __asm __volatile("cli");
index 70ca3e7..dc36ef8 100644 (file)
@@ -8,7 +8,7 @@
  *     on a different cpu will not be immediately scheduled by a yield() on
  *     this cpu.
  *
- * $DragonFly: src/sys/sys/thread2.h,v 1.6 2003/07/08 06:27:28 dillon Exp $
+ * $DragonFly: src/sys/sys/thread2.h,v 1.7 2003/07/08 09:57:13 dillon Exp $
  */
 
 #ifndef _SYS_THREAD2_H_
@@ -24,6 +24,7 @@
  *
  * Synchronous switching and blocking is allowed while in a critical section.
  */
+
 static __inline void
 crit_enter(void)
 {
index 54ba478..0a64d79 100644 (file)
@@ -38,7 +38,7 @@
  *
  *     @(#)ffs_vfsops.c        8.8 (Berkeley) 4/18/94
  *     $FreeBSD: src/sys/gnu/ext2fs/ext2_vfsops.c,v 1.63.2.7 2002/07/01 00:18:51 iedowse Exp $
- *     $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v 1.4 2003/07/06 21:23:48 dillon Exp $
+ *     $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_vfsops.c,v 1.5 2003/07/08 09:57:10 dillon Exp $
  */
 
 #include "opt_quota.h"
@@ -597,6 +597,7 @@ loop:
                    (int)fs->s_blocksize, NOCRED, &bp);
                if (error) {
                        vput(vp);
+                       lwkt_reltoken(&mntvnode_token);
                        return (error);
                }
                ext2_ei2di((struct ext2_inode *) ((char *)bp->b_data + 
index e7fa3f4..78e86db 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
  * $FreeBSD: src/sys/fs/hpfs/hpfs_hash.c,v 1.1 1999/12/09 19:09:58 semenu Exp $
- * $DragonFly: src/sys/vfs/hpfs/hpfs_hash.c,v 1.3 2003/07/06 21:23:47 dillon Exp $
+ * $DragonFly: src/sys/vfs/hpfs/hpfs_hash.c,v 1.4 2003/07/08 09:57:07 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -135,6 +135,7 @@ loop:
                                gen = lwkt_regettoken(&hpfs_hphash_token);
                                goto loop;
                        }
+                       lwkt_reltoken(&hpfs_hphash_token);
                        return (vp);
                }
        }
index bd7d0d6..30675df 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)ffs_vfsops.c        8.31 (Berkeley) 5/20/95
  * $FreeBSD: src/sys/ufs/ffs/ffs_vfsops.c,v 1.117.2.10 2002/06/23 22:34:52 iedowse Exp $
- * $DragonFly: src/sys/vfs/ufs/ffs_vfsops.c,v 1.6 2003/07/06 21:23:55 dillon Exp $
+ * $DragonFly: src/sys/vfs/ufs/ffs_vfsops.c,v 1.7 2003/07/08 09:57:14 dillon Exp $
  */
 
 #include "opt_quota.h"
@@ -560,6 +560,7 @@ loop:
                    (int)fs->fs_bsize, &bp);
                if (error) {
                        vput(vp);
+                       lwkt_reltoken(&mntvnode_token);
                        return (error);
                }
                ip->i_din = *((struct dinode *)bp->b_data +
index 91b269c..34ecd5a 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)ufs_ihash.c 8.7 (Berkeley) 5/17/95
  * $FreeBSD: src/sys/ufs/ufs/ufs_ihash.c,v 1.20 1999/08/28 00:52:29 peter Exp $
- * $DragonFly: src/sys/vfs/ufs/ufs_ihash.c,v 1.4 2003/07/06 21:23:55 dillon Exp $
+ * $DragonFly: src/sys/vfs/ufs/ufs_ihash.c,v 1.5 2003/07/08 09:57:14 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -115,6 +115,7 @@ loop:
                                lwkt_gentoken(&ufs_ihash_token, &gen);
                                goto loop;
                        }
+                       lwkt_reltoken(&ufs_ihash_token);
                        return (vp);
                }
        }