Add kern/lwkt_rwlock.c -- reader/writer locks. Clean up the process exit &
authorMatthew Dillon <dillon@dragonflybsd.org>
Sat, 21 Jun 2003 17:31:22 +0000 (17:31 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sat, 21 Jun 2003 17:31:22 +0000 (17:31 +0000)
reaping interlock code to allow context switches to occur.  Clean up and
make operational the lwkt_block/signaling code.

17 files changed:
sys/conf/files
sys/i386/i386/genassym.c
sys/i386/i386/pmap.c
sys/i386/i386/swtch.s
sys/i386/i386/vm_machdep.c
sys/i386/include/md_var.h
sys/kern/kern_exit.c
sys/kern/lwkt_rwlock.c [new file with mode: 0644]
sys/kern/lwkt_thread.c
sys/platform/pc32/i386/genassym.c
sys/platform/pc32/i386/pmap.c
sys/platform/pc32/i386/swtch.s
sys/platform/pc32/i386/vm_machdep.c
sys/platform/pc32/include/md_var.h
sys/platform/vkernel/i386/genassym.c
sys/sys/proc.h
sys/sys/thread.h

index 54b2b43..2aaf2a9 100644 (file)
@@ -1,5 +1,5 @@
 # $FreeBSD: src/sys/conf/files,v 1.340.2.137 2003/06/04 17:10:30 sam Exp $
-# $DragonFly: src/sys/conf/files,v 1.4 2003/06/21 07:54:53 dillon Exp $
+# $DragonFly: src/sys/conf/files,v 1.5 2003/06/21 17:31:05 dillon Exp $
 #
 # The long compile-with and dependency lines are required because of
 # limitations in config: backslash-newline doesn't work in strings, and
@@ -627,6 +627,7 @@ kern/kern_sig.c             standard
 kern/kern_subr.c       standard
 kern/kern_switch.c     standard
 kern/lwkt_thread.c     standard
+kern/lwkt_rwlock.c     standard
 kern/kern_synch.c      standard
 kern/kern_syscalls.c   standard
 kern/kern_sysctl.c     standard
index 4e51d8f..20e3140 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     from: @(#)genassym.c    5.11 (Berkeley) 5/10/91
  * $FreeBSD: src/sys/i386/i386/genassym.c,v 1.86.2.3 2002/03/03 05:42:49 nyan Exp $
- * $DragonFly: src/sys/i386/i386/Attic/genassym.c,v 1.9 2003/06/21 07:54:55 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/genassym.c,v 1.10 2003/06/21 17:31:08 dillon Exp $
  */
 
 #include "opt_user_ldt.h"
@@ -86,6 +86,9 @@ ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
 ASSYM(TD_SP, offsetof(struct thread, td_sp));
 ASSYM(TD_PRI, offsetof(struct thread, td_pri));
 ASSYM(TD_MACH, offsetof(struct thread, td_mach));
+ASSYM(TD_RWLOCK, offsetof(struct thread, td_rwlock));
+
+ASSYM(RW_OWNER, offsetof(struct lwkt_rwlock, rw_owner));
 
 ASSYM(MTD_CPL, offsetof(struct mi_thread, mtd_cpl));
 
index 582f5b9..08b7f01 100644 (file)
@@ -40,7 +40,7 @@
  *
  *     from:   @(#)pmap.c      7.7 (Berkeley)  5/12/91
  * $FreeBSD: src/sys/i386/i386/pmap.c,v 1.250.2.18 2002/03/06 22:48:53 silby Exp $
- * $DragonFly: src/sys/i386/i386/Attic/pmap.c,v 1.8 2003/06/21 07:54:56 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/pmap.c,v 1.9 2003/06/21 17:31:08 dillon Exp $
  */
 
 /*
@@ -858,7 +858,13 @@ pmap_new_thread()
                td = zalloc(thread_zone);
                td->td_kstack = 
                    (void *)kmem_alloc(kernel_map, UPAGES * PAGE_SIZE);
+               lwkt_rwlock_init(&td->td_rwlock);
        }
+
+       /*
+        * Sometimes td_pcb is moved around YYY.  Make sure that it is
+        * properly initialized.
+        */
        td->td_pcb = (struct pcb *)(td->td_kstack + UPAGES * PAGE_SIZE) - 1;
        return(td);
 }
index adf52fb..e9cf0e5 100644 (file)
@@ -35,7 +35,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/swtch.s,v 1.89.2.10 2003/01/23 03:36:24 ps Exp $
- * $DragonFly: src/sys/i386/i386/Attic/swtch.s,v 1.8 2003/06/21 07:54:56 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/swtch.s,v 1.9 2003/06/21 17:31:08 dillon Exp $
  */
 
 #include "npx.h"
@@ -191,18 +191,48 @@ ENTRY(cpu_heavy_switch)
  *     The switch function is changed to this when a thread is going away
  *     for good.  We have to ensure that the MMU state is not cached, and
  *     we don't bother saving the existing thread state before switching.
+ *
+ *     At this point we are in a critical section and this cpu owns the
+ *     thread's token, which serves as an interlock until the switchout is
+ *     complete.
  */
 ENTRY(cpu_exit_switch)
+       /*
+        * Get us out of the vmspace
+        */
        movl    _IdlePTD,%ecx
        movl    %cr3,%eax
        cmpl    %ecx,%eax
        je      1f
        movl    %ecx,%cr3
+       movl    _curthread,%ecx
 1:
+       /*
+        * Switch to the next thread.
+        */
        cli
        movl    4(%esp),%eax
        movl    %eax,_curthread
        movl    TD_SP(%eax),%esp
+
+       /*
+        * We are now effectively the next thread, transfer ownership to
+        * this thread and release the original thread's RW lock, which
+        * will allow it to be reaped.   Messy but rock solid.
+        */
+       addl    $TD_RWLOCK,%ecx
+       movl    %eax,RW_OWNER(%ecx)
+       pushl   %eax
+       pushl   %ecx
+       call    lwkt_exunlock
+       addl    $4,%esp
+       popl    %eax
+
+       /*
+        * Restore the next thread's state and resume it.  Note: the
+        * restore function assumes that the next thread's address is
+        * in %eax.
+        */
        ret
 
 /*
index a7f54d5..8291617 100644 (file)
@@ -39,7 +39,7 @@
  *     from: @(#)vm_machdep.c  7.3 (Berkeley) 5/13/91
  *     Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
  * $FreeBSD: src/sys/i386/i386/vm_machdep.c,v 1.132.2.9 2003/01/25 19:02:23 dillon Exp $
- * $DragonFly: src/sys/i386/i386/Attic/vm_machdep.c,v 1.7 2003/06/20 02:09:50 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/vm_machdep.c,v 1.8 2003/06/21 17:31:08 dillon Exp $
  */
 
 #include "npx.h"
@@ -79,6 +79,7 @@
 #include <vm/vm_extern.h>
 
 #include <sys/user.h>
+#include <sys/thread2.h>
 
 #ifdef PC98
 #include <pc98/pc98/pc98.h>
@@ -248,18 +249,16 @@ void
 cpu_exit(p)
        register struct proc *p;
 {
-       struct pcb *pcb = p->p_thread->td_pcb; 
-
-       /*
-        * This allows us to disassociate curproc from the thread.
-        */
-       if (p->p_thread->td_switch == cpu_heavy_switch)
-           p->p_thread->td_switch = cpu_exit_switch;
-       p->p_thread->td_proc = NULL;
+       struct pcb *pcb;
 
 #if NNPX > 0
        npxexit(p);
 #endif /* NNPX */
+
+       /*
+        * Cleanup the PCB
+        */
+       pcb = curthread->td_pcb;
        if (pcb->pcb_ext != 0) {
                /* 
                 * XXX do we need to move the TSS off the allocated pages 
@@ -280,6 +279,16 @@ cpu_exit(p)
                 pcb->pcb_flags &= ~PCB_DBREGS;
         }
        cnt.v_swtch++;
+
+       /*
+        * Set a special switch function which will release td_rwlock after
+        * the thread has been derferenced.
+        */
+       crit_enter();
+       KASSERT(curthread->td_switch == cpu_heavy_switch,
+           ("cpu_exit: unexpected switchout"));
+       curthread->td_switch = cpu_exit_switch;
+       lwkt_deschedule_self();
        lwkt_switch();
        panic("cpu_exit");
 }
index 92da9b1..57695ba 100644 (file)
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/md_var.h,v 1.35.2.4 2003/01/22 20:14:53 jhb Exp $
- * $DragonFly: src/sys/i386/include/Attic/md_var.h,v 1.4 2003/06/20 02:09:54 dillon Exp $
+ * $DragonFly: src/sys/i386/include/Attic/md_var.h,v 1.5 2003/06/21 17:31:14 dillon Exp $
  */
 
 #ifndef _MACHINE_MD_VAR_H_
@@ -83,6 +83,7 @@ void  cpu_switch_load_gs __P((void)) __asm(__STRING(cpu_switch_load_gs));
 void   cpu_heavy_restore __P((void));  /* cannot be called from C */
 void   cpu_lwkt_restore __P((void));   /* cannot be called from C */
 void   cpu_idle_restore __P((void));   /* cannot be called from C */
+void   cpu_exit_idleptd __P((void));   /* disassociate proc MMU */
 void   cpu_exit_switch __P((struct thread *next));
 void   doreti_iret __P((void)) __asm(__STRING(doreti_iret));
 void   doreti_iret_fault __P((void)) __asm(__STRING(doreti_iret_fault));
index 3526d30..d368a26 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_exit.c 8.7 (Berkeley) 2/12/94
  * $FreeBSD: src/sys/kern/kern_exit.c,v 1.92.2.11 2003/01/13 22:51:16 dillon Exp $
- * $DragonFly: src/sys/kern/kern_exit.c,v 1.6 2003/06/20 02:09:56 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_exit.c,v 1.7 2003/06/21 17:31:19 dillon Exp $
  */
 
 #include "opt_compat.h"
@@ -280,6 +280,14 @@ exit1(p, rv)
                vrele(vtmp);
        }
 
+       /*
+        * Once we set SZOMB the process can get reaped.  To prevent this
+        * from occuring we obtain an exclusive access lock on the underlying
+        * thread which will not be released until the thread has been
+        * completed switched out.
+        */
+       lwkt_exlock(&curthread->td_rwlock, "exit");
+
        /*
         * Remove proc from allproc queue and pidhash chain.
         * Place onto zombproc.  Unlink from parent's child list.
@@ -364,9 +372,6 @@ exit1(p, rv)
         * cpu_exit is responsible for clearing curproc, since
         * it is heavily integrated with the thread/switching sequence.
         *
-        * After this point we cannot block and we cannot become runnable
-        * again.
-        *
         * Other substructures are freed from wait().
         */
        if (--p->p_limit->p_refcnt == 0) {
@@ -451,6 +456,21 @@ loop:
 
                nfound++;
                if (p->p_stat == SZOMB) {
+                       /*
+                        * This is a tad nasty because lwkt_*() functions can
+                        * block, causing our information to become out of
+                        * date.
+                        *
+                        * YYY there may be some inefficiency here.
+                        */
+                       if ((p->p_flag & P_EXITINTERLOCK) == 0) {
+                           lwkt_exlock(&p->p_thread->td_rwlock, "reap");
+                           p->p_flag |= P_EXITINTERLOCK;
+                           lwkt_exunlock(&p->p_thread->td_rwlock);
+                           goto loop;
+                       }
+                       KASSERT(p->p_lock == 0, ("p_lock not 0! %p", p));
+
                        /* charge childs scheduling cpu usage to parent */
                        if (curproc->p_pid != 1) {
                                curproc->p_estcpu =
@@ -533,11 +553,6 @@ loop:
                                p->p_procsig = NULL;
                        }
 
-                       /*
-                        * Give machine-dependent layer a chance
-                        * to free anything that cpu_exit couldn't
-                        * release while still running in process context.
-                        */
                        vm_waitproc(p);
                        zfree(proc_zone, p);
                        nprocs--;
diff --git a/sys/kern/lwkt_rwlock.c b/sys/kern/lwkt_rwlock.c
new file mode 100644 (file)
index 0000000..8476b02
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2003 Matthew Dillon <dillon@backplane.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Implements simple shared/exclusive locks using LWKT. 
+ *
+ * $DragonFly: src/sys/kern/Attic/lwkt_rwlock.c,v 1.1 2003/06/21 17:31:19 dillon Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/rtprio.h>
+#include <sys/queue.h>
+
+void
+lwkt_rwlock_init(lwkt_rwlock_t lock)
+{
+    lwkt_wait_init(&lock->rw_wait);
+}
+
+void
+lwkt_exlock(lwkt_rwlock_t lock, const char *wmesg)
+{
+    int gen;
+
+    lwkt_gettoken(&lock->rw_token);
+    gen = lock->rw_wait.wa_gen;
+    while (lock->rw_owner != curthread) {
+       if (lock->rw_owner == NULL && lock->rw_count == 0) {
+           lock->rw_owner = curthread;
+           break;
+       }
+       lwkt_block(&lock->rw_wait, wmesg, &gen);
+       lwkt_regettoken(&lock->rw_token);
+    }
+    ++lock->rw_count;
+    lwkt_reltoken(&lock->rw_token);
+}
+
+void
+lwkt_shlock(lwkt_rwlock_t lock, const char *wmesg)
+{
+    int gen;
+
+    lwkt_gettoken(&lock->rw_token);
+    gen = lock->rw_wait.wa_gen;
+    while (lock->rw_owner != NULL) {
+       lwkt_block(&lock->rw_wait, wmesg, &gen);
+       lwkt_regettoken(&lock->rw_token);
+    }
+    ++lock->rw_count;
+    lwkt_reltoken(&lock->rw_token);
+}
+
+void
+lwkt_exunlock(lwkt_rwlock_t lock)
+{
+    lwkt_gettoken(&lock->rw_token);
+    KASSERT(lock->rw_owner != NULL, ("lwkt_exunlock: shared lock"));
+    KASSERT(lock->rw_owner == curthread, ("lwkt_exunlock: not owner"));
+    if (--lock->rw_count == 0) {
+       lock->rw_owner = NULL;
+       lwkt_signal(&lock->rw_wait);
+    }
+    lwkt_reltoken(&lock->rw_token);
+}
+
+void
+lwkt_shunlock(lwkt_rwlock_t lock)
+{
+    lwkt_gettoken(&lock->rw_token);
+    KASSERT(lock->rw_owner == NULL, ("lwkt_shunlock: exclusive lock"));
+    if (--lock->rw_count == 0)
+       lwkt_signal(&lock->rw_wait);
+    lwkt_reltoken(&lock->rw_token);
+}
+
index 1c47fb6..e5ef33a 100644 (file)
@@ -27,7 +27,7 @@
  *     thread scheduler, which means that generally speaking we only need
  *     to use a critical section to prevent hicups.
  *
- * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.2 2003/06/21 07:54:57 dillon Exp $
+ * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.3 2003/06/21 17:31:19 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -315,6 +315,15 @@ lwkt_deschedule(thread_t td)
     crit_exit();
 }
 
+/*
+ * Initialize a thread wait queue
+ */
+void
+lwkt_wait_init(lwkt_wait_t w)
+{
+    TAILQ_INIT(&w->wa_waitq);
+}
+
 /*
  * This function deschedules the current thread and blocks on the specified
  * wait queue.  We obtain ownership of the wait queue in order to block
@@ -327,20 +336,21 @@ lwkt_deschedule(thread_t td)
  * Note: wait queue signals normally ping-pong the cpu as an optimization.
  */
 void
-lwkt_block(lwkt_wait_t w)
+lwkt_block(lwkt_wait_t w, const char *wmesg, int *gen)
 {
     thread_t td = curthread;
-    int gen;
 
-    gen = td->td_gen;
     lwkt_gettoken(&w->wa_token);
-    if (w->wa_gen == gen) {
+    if (w->wa_gen == *gen) {
        _lwkt_dequeue(td);
        TAILQ_INSERT_TAIL(&w->wa_waitq, td, td_threadq);
        ++w->wa_count;
        td->td_wait = w;
+       td->td_wmesg = wmesg;
        lwkt_switch();
     }
+    /* token might be lost, doesn't matter for gen update */
+    *gen = w->wa_gen;
     lwkt_reltoken(&w->wa_token);
 }
 
@@ -366,6 +376,7 @@ lwkt_signal(lwkt_wait_t w)
        --w->wa_count;
        TAILQ_REMOVE(&w->wa_waitq, td, td_threadq);
        td->td_wait = NULL;
+       td->td_wmesg = NULL;
        if (td->td_cpu == mycpu->gd_cpu) {
            _lwkt_enqueue(td);
        } else {
index 398765a..6e98700 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     from: @(#)genassym.c    5.11 (Berkeley) 5/10/91
  * $FreeBSD: src/sys/i386/i386/genassym.c,v 1.86.2.3 2002/03/03 05:42:49 nyan Exp $
- * $DragonFly: src/sys/platform/pc32/i386/genassym.c,v 1.9 2003/06/21 07:54:55 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/genassym.c,v 1.10 2003/06/21 17:31:08 dillon Exp $
  */
 
 #include "opt_user_ldt.h"
@@ -86,6 +86,9 @@ ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
 ASSYM(TD_SP, offsetof(struct thread, td_sp));
 ASSYM(TD_PRI, offsetof(struct thread, td_pri));
 ASSYM(TD_MACH, offsetof(struct thread, td_mach));
+ASSYM(TD_RWLOCK, offsetof(struct thread, td_rwlock));
+
+ASSYM(RW_OWNER, offsetof(struct lwkt_rwlock, rw_owner));
 
 ASSYM(MTD_CPL, offsetof(struct mi_thread, mtd_cpl));
 
index 0e85214..e9deafa 100644 (file)
@@ -40,7 +40,7 @@
  *
  *     from:   @(#)pmap.c      7.7 (Berkeley)  5/12/91
  * $FreeBSD: src/sys/i386/i386/pmap.c,v 1.250.2.18 2002/03/06 22:48:53 silby Exp $
- * $DragonFly: src/sys/platform/pc32/i386/pmap.c,v 1.8 2003/06/21 07:54:56 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/pmap.c,v 1.9 2003/06/21 17:31:08 dillon Exp $
  */
 
 /*
@@ -858,7 +858,13 @@ pmap_new_thread()
                td = zalloc(thread_zone);
                td->td_kstack = 
                    (void *)kmem_alloc(kernel_map, UPAGES * PAGE_SIZE);
+               lwkt_rwlock_init(&td->td_rwlock);
        }
+
+       /*
+        * Sometimes td_pcb is moved around YYY.  Make sure that it is
+        * properly initialized.
+        */
        td->td_pcb = (struct pcb *)(td->td_kstack + UPAGES * PAGE_SIZE) - 1;
        return(td);
 }
index 755d02c..ccf1095 100644 (file)
@@ -35,7 +35,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/swtch.s,v 1.89.2.10 2003/01/23 03:36:24 ps Exp $
- * $DragonFly: src/sys/platform/pc32/i386/swtch.s,v 1.8 2003/06/21 07:54:56 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/swtch.s,v 1.9 2003/06/21 17:31:08 dillon Exp $
  */
 
 #include "npx.h"
@@ -191,18 +191,48 @@ ENTRY(cpu_heavy_switch)
  *     The switch function is changed to this when a thread is going away
  *     for good.  We have to ensure that the MMU state is not cached, and
  *     we don't bother saving the existing thread state before switching.
+ *
+ *     At this point we are in a critical section and this cpu owns the
+ *     thread's token, which serves as an interlock until the switchout is
+ *     complete.
  */
 ENTRY(cpu_exit_switch)
+       /*
+        * Get us out of the vmspace
+        */
        movl    _IdlePTD,%ecx
        movl    %cr3,%eax
        cmpl    %ecx,%eax
        je      1f
        movl    %ecx,%cr3
+       movl    _curthread,%ecx
 1:
+       /*
+        * Switch to the next thread.
+        */
        cli
        movl    4(%esp),%eax
        movl    %eax,_curthread
        movl    TD_SP(%eax),%esp
+
+       /*
+        * We are now effectively the next thread, transfer ownership to
+        * this thread and release the original thread's RW lock, which
+        * will allow it to be reaped.   Messy but rock solid.
+        */
+       addl    $TD_RWLOCK,%ecx
+       movl    %eax,RW_OWNER(%ecx)
+       pushl   %eax
+       pushl   %ecx
+       call    lwkt_exunlock
+       addl    $4,%esp
+       popl    %eax
+
+       /*
+        * Restore the next thread's state and resume it.  Note: the
+        * restore function assumes that the next thread's address is
+        * in %eax.
+        */
        ret
 
 /*
index ae6b023..2448fcb 100644 (file)
@@ -39,7 +39,7 @@
  *     from: @(#)vm_machdep.c  7.3 (Berkeley) 5/13/91
  *     Utah $Hdr: vm_machdep.c 1.16.1.1 89/06/23$
  * $FreeBSD: src/sys/i386/i386/vm_machdep.c,v 1.132.2.9 2003/01/25 19:02:23 dillon Exp $
- * $DragonFly: src/sys/platform/pc32/i386/vm_machdep.c,v 1.7 2003/06/20 02:09:50 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/vm_machdep.c,v 1.8 2003/06/21 17:31:08 dillon Exp $
  */
 
 #include "npx.h"
@@ -79,6 +79,7 @@
 #include <vm/vm_extern.h>
 
 #include <sys/user.h>
+#include <sys/thread2.h>
 
 #ifdef PC98
 #include <pc98/pc98/pc98.h>
@@ -248,18 +249,16 @@ void
 cpu_exit(p)
        register struct proc *p;
 {
-       struct pcb *pcb = p->p_thread->td_pcb; 
-
-       /*
-        * This allows us to disassociate curproc from the thread.
-        */
-       if (p->p_thread->td_switch == cpu_heavy_switch)
-           p->p_thread->td_switch = cpu_exit_switch;
-       p->p_thread->td_proc = NULL;
+       struct pcb *pcb;
 
 #if NNPX > 0
        npxexit(p);
 #endif /* NNPX */
+
+       /*
+        * Cleanup the PCB
+        */
+       pcb = curthread->td_pcb;
        if (pcb->pcb_ext != 0) {
                /* 
                 * XXX do we need to move the TSS off the allocated pages 
@@ -280,6 +279,16 @@ cpu_exit(p)
                 pcb->pcb_flags &= ~PCB_DBREGS;
         }
        cnt.v_swtch++;
+
+       /*
+        * Set a special switch function which will release td_rwlock after
+        * the thread has been derferenced.
+        */
+       crit_enter();
+       KASSERT(curthread->td_switch == cpu_heavy_switch,
+           ("cpu_exit: unexpected switchout"));
+       curthread->td_switch = cpu_exit_switch;
+       lwkt_deschedule_self();
        lwkt_switch();
        panic("cpu_exit");
 }
index cd82933..90a7206 100644 (file)
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/md_var.h,v 1.35.2.4 2003/01/22 20:14:53 jhb Exp $
- * $DragonFly: src/sys/platform/pc32/include/md_var.h,v 1.4 2003/06/20 02:09:54 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/include/md_var.h,v 1.5 2003/06/21 17:31:14 dillon Exp $
  */
 
 #ifndef _MACHINE_MD_VAR_H_
@@ -83,6 +83,7 @@ void  cpu_switch_load_gs __P((void)) __asm(__STRING(cpu_switch_load_gs));
 void   cpu_heavy_restore __P((void));  /* cannot be called from C */
 void   cpu_lwkt_restore __P((void));   /* cannot be called from C */
 void   cpu_idle_restore __P((void));   /* cannot be called from C */
+void   cpu_exit_idleptd __P((void));   /* disassociate proc MMU */
 void   cpu_exit_switch __P((struct thread *next));
 void   doreti_iret __P((void)) __asm(__STRING(doreti_iret));
 void   doreti_iret_fault __P((void)) __asm(__STRING(doreti_iret_fault));
index 1ded946..5463f25 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     from: @(#)genassym.c    5.11 (Berkeley) 5/10/91
  * $FreeBSD: src/sys/i386/i386/genassym.c,v 1.86.2.3 2002/03/03 05:42:49 nyan Exp $
- * $DragonFly: src/sys/platform/vkernel/i386/genassym.c,v 1.9 2003/06/21 07:54:55 dillon Exp $
+ * $DragonFly: src/sys/platform/vkernel/i386/genassym.c,v 1.10 2003/06/21 17:31:08 dillon Exp $
  */
 
 #include "opt_user_ldt.h"
@@ -86,6 +86,9 @@ ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
 ASSYM(TD_SP, offsetof(struct thread, td_sp));
 ASSYM(TD_PRI, offsetof(struct thread, td_pri));
 ASSYM(TD_MACH, offsetof(struct thread, td_mach));
+ASSYM(TD_RWLOCK, offsetof(struct thread, td_rwlock));
+
+ASSYM(RW_OWNER, offsetof(struct lwkt_rwlock, rw_owner));
 
 ASSYM(MTD_CPL, offsetof(struct mi_thread, mtd_cpl));
 
index e6c14e9..3cb25ae 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)proc.h      8.15 (Berkeley) 5/19/95
  * $FreeBSD: src/sys/sys/proc.h,v 1.99.2.9 2003/06/06 20:21:32 tegge Exp $
- * $DragonFly: src/sys/sys/proc.h,v 1.9 2003/06/21 07:54:57 dillon Exp $
+ * $DragonFly: src/sys/sys/proc.h,v 1.10 2003/06/21 17:31:22 dillon Exp $
  */
 
 #ifndef _SYS_PROC_H_
@@ -291,6 +291,7 @@ struct      proc {
 #define        P_OLDMASK       0x2000000 /* need to restore mask before pause */
 #define        P_ALTSTACK      0x4000000 /* have alternate signal stack */
 #define        P_INEXEC        0x8000000 /* Process is in execve(). */
+#define P_EXITINTERLOCK        0x10000000 /* Reaping process exit interlock */
 
 /*
  * MOVE TO ucred.h?
index 74c5803..f43096c 100644 (file)
@@ -4,7 +4,7 @@
  *     Implements the architecture independant portion of the LWKT 
  *     subsystem.
  * 
- * $DragonFly: src/sys/sys/thread.h,v 1.4 2003/06/21 07:54:57 dillon Exp $
+ * $DragonFly: src/sys/sys/thread.h,v 1.5 2003/06/21 17:31:22 dillon Exp $
  */
 
 #ifndef _SYS_THREAD_H_
@@ -102,7 +102,7 @@ typedef struct lwkt_cpu_msg {
  * reader/writer lock
  */
 typedef struct lwkt_rwlock {
-    lwkt_token rw_token;
+    lwkt_wait  rw_wait;
     thread_t   rw_owner;
     int                rw_count;
 } lwkt_rwlock;
@@ -121,6 +121,7 @@ struct thread {
     TAILQ_ENTRY(thread) td_threadq;
     struct proc        *td_proc;       /* (optional) associated process */
     struct pcb *td_pcb;        /* points to pcb and top of kstack */
+    const char *td_wmesg;      /* string name for blockage */
     int                td_cpu;         /* cpu owning the thread */
     int                td_pri;         /* 0-31, 0=highest priority */
     int                td_flags;       /* THF flags */
@@ -129,9 +130,12 @@ struct thread {
     char       *td_sp;         /* kernel stack pointer for LWKT restore */
     void       (*td_switch)(struct thread *ntd);
     lwkt_wait_t td_wait;       /* thread sitting on wait structure */
+    lwkt_rwlock        td_rwlock;      /* thread arbitration */
     struct mi_thread td_mach;
 };
 
+#define td_token       td_rwlock.rw_token
+
 /*
  * Thread flags.  Note that the RUNNING state is independant from the
  * RUNQ/WAITQ state.  That is, a thread's queueing state can be manipulated
@@ -158,6 +162,7 @@ struct thread {
 #define TDPRI_KERN_USER                10      /* kernel / block in syscall */
 #define TDPRI_SOFT_NORM                14      /* kernel / normal */
 #define TDPRI_SOFT_TIMER       16      /* kernel / timer */
+#define TDPRI_EXITING          19      /* exiting thread */
 #define TDPRI_INT_SUPPORT      20      /* kernel / high priority support */
 #define TDPRI_INT_LOW          27      /* low priority interrupt */
 #define TDPRI_INT_MED          28      /* medium priority interrupt */
@@ -173,6 +178,7 @@ struct thread {
 
 extern struct vm_zone  *thread_zone;
 
+extern void lwkt_wait_init(struct lwkt_wait *w);
 extern void lwkt_gdinit(struct globaldata *gd);
 extern void lwkt_switch(void);
 extern void lwkt_preempt(void);
@@ -183,11 +189,16 @@ extern void lwkt_deschedule_self(void);
 extern void lwkt_yield(void);
 extern void lwkt_yield_quick(void);
 
-extern void lwkt_block(lwkt_wait_t w);
+extern void lwkt_block(lwkt_wait_t w, const char *wmesg, int *gen);
 extern void lwkt_signal(lwkt_wait_t w);
 extern void lwkt_gettoken(lwkt_token_t tok);
 extern void lwkt_reltoken(lwkt_token_t tok);
 extern int  lwkt_regettoken(lwkt_token_t tok);
+extern void lwkt_rwlock_init(lwkt_rwlock_t lock);
+extern void lwkt_exlock(lwkt_rwlock_t lock, const char *wmesg);
+extern void lwkt_shlock(lwkt_rwlock_t lock, const char *wmesg);
+extern void lwkt_exunlock(lwkt_rwlock_t lock);
+extern void lwkt_shunlock(lwkt_rwlock_t lock);
 
 #endif