Cleanup lwkt threads a bit, change the exit/reap interlock.
authorMatthew Dillon <dillon@dragonflybsd.org>
Fri, 27 Jun 2003 03:30:43 +0000 (03:30 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Fri, 27 Jun 2003 03:30:43 +0000 (03:30 +0000)
19 files changed:
sys/i386/i386/genassym.c
sys/i386/i386/machdep.c
sys/i386/i386/pmap.c
sys/i386/i386/swtch.s
sys/i386/i386/vm_machdep.c
sys/kern/kern_exit.c
sys/kern/kern_kthread.c
sys/kern/lwkt_thread.c
sys/platform/pc32/i386/genassym.c
sys/platform/pc32/i386/machdep.c
sys/platform/pc32/i386/pmap.c
sys/platform/pc32/i386/swtch.s
sys/platform/pc32/i386/vm_machdep.c
sys/platform/vkernel/i386/genassym.c
sys/sys/kthread.h
sys/sys/proc.h
sys/sys/thread.h
sys/vm/pmap.h
sys/vm/vm_glue.c

index f522c2e..63e11f5 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.13 2003/06/27 01:53:24 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/genassym.c,v 1.14 2003/06/27 03:30:37 dillon Exp $
  */
 
 #include "opt_user_ldt.h"
@@ -85,8 +85,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(TD_WCHAN, offsetof(struct thread, td_wchan));
+ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
+ASSYM(TDF_EXITED, TDF_EXITED);
 
 ASSYM(RW_OWNER, offsetof(struct lwkt_rwlock, rw_owner));
 
index c96a536..c1f5833 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.12 2003/06/25 03:55:53 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/machdep.c,v 1.13 2003/06/27 03:30:37 dillon Exp $
  */
 
 #include "apm.h"
@@ -1866,14 +1866,13 @@ init386(first)
         */
        gd = &CPU_prvspace[0].globaldata;
 
-       lwkt_init_thread(&thread0, proc0paddr);
+       lwkt_init_thread(&thread0, proc0paddr, 0);
        gd->gd_curthread = &thread0;
        safepri = thread0.td_cpl = SWI_MASK | HWI_MASK;
        thread0.td_switch = cpu_heavy_switch;   /* YYY eventually LWKT */
        proc0.p_addr = (void *)thread0.td_kstack;
        proc0.p_thread = &thread0;
        thread0.td_proc = &proc0;
-       thread0.td_flags = TDF_RUNNING;
 
        atdevbase = ISA_HOLE_START + KERNBASE;
 
@@ -2088,7 +2087,7 @@ cpu_gdinit(struct globaldata *gd, int cpu)
        if (cpu)
            gd->gd_curthread = &gd->gd_idlethread;
        sp = gd->gd_prvspace->idlestack;
-       lwkt_init_thread(&gd->gd_idlethread, sp);
+       lwkt_init_thread(&gd->gd_idlethread, sp, 0);
        gd->gd_idlethread.td_switch = cpu_lwkt_switch;
        gd->gd_idlethread.td_sp -= sizeof(void *);
        *(void **)gd->gd_idlethread.td_sp = cpu_idle_restore;
index dbb4099..4548c71 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.10 2003/06/22 04:30:39 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/pmap.c,v 1.11 2003/06/27 03:30:37 dillon Exp $
  */
 
 /*
@@ -850,29 +850,6 @@ pmap_init_thread(thread_t td)
        td->td_sp = (char *)td->td_pcb - 16;
 }
 
-/*
- * Dispose of a thread, unlink it from its related proc (if any).  Keep
- * CACHE_NTHREAD threads around for fast-startup.
- */
-void
-pmap_dispose_thread(struct thread *td)
-{
-       /* HIPRI YYY */
-       KASSERT((td->td_flags & (TDF_RUNQ|TDF_RUNNING)) == 0,
-               ("pmap_dispose_thread: still on queue: %08x", td->td_flags));
-       if (mycpu->gd_tdfreecount < CACHE_NTHREADS) {
-               ++mycpu->gd_tdfreecount;
-               TAILQ_INSERT_HEAD(&mycpu->gd_tdfreeq, td, td_threadq);
-       } else {
-               if (td->td_kstack) {
-                       kmem_free(kernel_map,
-                           (vm_offset_t)td->td_kstack, UPAGES * PAGE_SIZE);
-                       td->td_kstack = NULL;
-               }
-               zfree(thread_zone, td);
-       }
-}
-
 /*
  * Create the UPAGES for a new process.
  * This routine directly affects the fork perf for a process.
index f9c7908..09261b0 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.13 2003/06/27 01:53:24 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/swtch.s,v 1.14 2003/06/27 03:30:37 dillon Exp $
  */
 
 #include "npx.h"
@@ -214,17 +214,15 @@ ENTRY(cpu_exit_switch)
        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.
+        * We are now the next thread, set the exited flag and wakeup
+        * any waiters.
         */
-       addl    $TD_RWLOCK,%ecx
-       movl    %eax,RW_OWNER(%ecx)
+       orl     $TDF_EXITED,TD_FLAGS(%ecx)
        pushl   %eax
-       pushl   %ecx
-       call    lwkt_exunlock
+       pushl   %ecx    /* wakeup(oldthread) */
+       call    wakeup
        addl    $4,%esp
-       popl    %eax
+       popl    %eax    /* note: next thread expects curthread in %eax */
 
        /*
         * Restore the next thread's state and resume it.  Note: the
index 845ce55..a2ee279 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.11 2003/06/27 01:53:24 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/vm_machdep.c,v 1.12 2003/06/27 03:30:37 dillon Exp $
  */
 
 #include "npx.h"
@@ -257,19 +257,21 @@ cpu_set_thread_handler(thread_t td, void (*rfunc)(void), void *func, void *arg)
 }
 
 void
-cpu_exit(p)
-       register struct proc *p;
+cpu_proc_exit(void)
 {
+       struct thread *td = curthread;
        struct pcb *pcb;
 
+
 #if NNPX > 0
-       npxexit(p);
+       KKASSERT(td->td_proc);
+       npxexit(td->td_proc);
 #endif /* NNPX */
 
        /*
         * Cleanup the PCB
         */
-       pcb = curthread->td_pcb;
+       pcb = td->td_pcb;
        if (pcb->pcb_ext != 0) {
                /* 
                 * XXX do we need to move the TSS off the allocated pages 
@@ -291,29 +293,41 @@ cpu_exit(p)
         }
        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();
+       cpu_thread_exit();
+}
+
+/*
+ * Terminate the current thread.  The caller must have already acquired
+ * the thread's rwlock and placed it on a reap list or otherwise notified
+ * a reaper of its existance.  We set a special assembly switch function which
+ * releases td_rwlock after it has cleaned up the MMU state and switched
+ * out the stack.
+ *
+ * Must be caller from a critical section and with the thread descheduled.
+ */
+void
+cpu_thread_exit(void)
+{
+       curthread->td_switch = cpu_exit_switch;
        lwkt_switch();
        panic("cpu_exit");
 }
 
+/*
+ * Process Reaper.  Called after the caller has acquired the thread's
+ * rwlock and removed it from the reap list.
+ */
 void
-cpu_wait(p)
-       struct proc *p;
+cpu_proc_wait(struct proc *p)
 {
        struct thread *td;
 
        /* drop per-process resources */
        td = pmap_dispose_proc(p);
        if (td)
-           pmap_dispose_thread(td);
+               lwkt_free_thread(td);
 }
 
 /*
index c8b16d7..825e8fa 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.10 2003/06/25 03:55:57 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_exit.c,v 1.11 2003/06/27 03:30:42 dillon Exp $
  */
 
 #include "opt_compat.h"
@@ -277,12 +277,10 @@ exit1(int rv)
        }
 
        /*
-        * 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.
+        * Once we set SZOMB the process can get reaped.  The wait1 code
+        * will also wait for TDF_EXITED to be set in the thread's flags,
+        * indicating that it has been completely switched out.
         */
-       lwkt_exlock(&curthread->td_rwlock, "exit");
 
        /*
         * Remove proc from allproc queue and pidhash chain.
@@ -375,7 +373,7 @@ exit1(int rv)
         * finish.  cpu_exit will end with a call to cpu_switch(), finishing
         * our execution (pun intended).
         */
-       cpu_exit(p);
+       cpu_proc_exit();
 }
 
 #ifdef COMPAT_43
@@ -439,17 +437,13 @@ 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.
+                        * The process's thread may still be in the middle
+                        * of switching away, we can't rip its stack out from
+                        * under it until TDF_EXITED is set.
                         */
-                       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;
+                       if ((p->p_thread->td_flags & TDF_EXITED) == 0) {
+                               tsleep(p->p_thread, PWAIT, "reap", 0);
+                               goto loop;
                        }
                        KASSERT(p->p_lock == 0, ("p_lock not 0! %p", p));
 
index 18ee90a..e118977 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_kthread.c,v 1.5.2.3 2001/12/25 01:51:14 dillon Exp $
- * $DragonFly: src/sys/kern/kern_kthread.c,v 1.6 2003/06/27 01:53:25 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_kthread.c,v 1.7 2003/06/27 03:30:42 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -59,51 +59,6 @@ kproc_start(udata)
                panic("kproc_start: %s: error %d", kp->arg0, error);
 }
 
-/*
- * Create a kernel process/thread/whatever.  It shares it's address space
- * with proc0 - ie: kernel only.
- */
-int
-kthread_create(void (*func)(void *), void *arg,
-    struct thread **tdp, const char *fmt, ...)
-{
-       struct thread *td;
-       va_list ap;
-
-       td = *tdp = lwkt_alloc_thread();
-       cpu_set_thread_handler(td, kthread_exit, func, arg);
-
-       /*
-        * Set up arg0 for 'ps' etc
-        */
-       va_start(ap, fmt);
-       vsnprintf(td->td_comm, sizeof(td->td_comm), fmt, ap);
-       va_end(ap);
-
-       /*
-        * Schedule the thread to run
-        */
-       lwkt_schedule(td);
-       return 0;
-}
-
-/*
- * YYY kthread_exit() should get rid of the kthread.  We have to put it on
- * some sort of wait list and set our switcher to interlock against
- * the reaper.
- */
-void
-kthread_exit(void)
-{
-       thread_t td = curthread;
-
-       printf("kthread %p %s has exited\n", td, td->td_comm); /* YYY */
-       for (;;) {
-               td->td_flags |= TDF_STOPREQ;
-               kproc_suspend_loop();
-       }
-}
-
 /*
  * Advise a kernel process to suspend (or resume) in its main loop.
  * Participation is voluntary.
@@ -112,7 +67,7 @@ int
 suspend_kproc(struct thread *td, int timo)
 {
        if (td->td_proc == NULL) {
-               td->td_flags |= TDF_STOPREQ;    /* request thread exit */
+               td->td_flags |= TDF_STOPREQ;    /* request thread pause */
                wakeup(td);
                while (td->td_flags & TDF_STOPREQ) {
                        int error = tsleep(td, PPAUSE, "suspkp", timo);
index d94bed3..5067c81 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.5 2003/06/27 01:53:25 dillon Exp $
+ * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.6 2003/06/27 03:30:42 dillon Exp $
  */
 
 #include <sys/param.h>
 #include <sys/rtprio.h>
 #include <sys/queue.h>
 #include <sys/thread2.h>
-#include <sys/lock.h>
 #include <sys/sysctl.h>
+#include <sys/kthread.h>
 #include <machine/cpu.h>
+#include <sys/lock.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
@@ -51,6 +52,8 @@
 #include <vm/vm_extern.h>
 #include <vm/vm_zone.h>
 
+#include <machine/stdarg.h>
+
 static int untimely_switch = 0;
 SYSCTL_INT(_debug, OID_AUTO, untimely_switch, CTLFLAG_RW, &untimely_switch, 0, "");
 
@@ -107,24 +110,25 @@ lwkt_init_wait(lwkt_wait_t w)
 thread_t
 lwkt_alloc_thread(void)
 {
-       struct thread *td;
-       void *stack;
+    struct thread *td;
+    void *stack;
 
-       crit_enter();
-       if (mycpu->gd_tdfreecount > 0) {
-               --mycpu->gd_tdfreecount;
-               td = TAILQ_FIRST(&mycpu->gd_tdfreeq);
-               KASSERT(td != NULL, ("unexpected null cache td"));
-               TAILQ_REMOVE(&mycpu->gd_tdfreeq, td, td_threadq);
-               crit_exit();
-               stack = td->td_kstack;
-       } else {
-               crit_exit();
-               td = zalloc(thread_zone);
-               stack = (void *)kmem_alloc(kernel_map, UPAGES * PAGE_SIZE);
-       }
-       lwkt_init_thread(td, stack);
-       return(td);
+    crit_enter();
+    if (mycpu->gd_tdfreecount > 0) {
+       --mycpu->gd_tdfreecount;
+       td = TAILQ_FIRST(&mycpu->gd_tdfreeq);
+       KASSERT(td != NULL && (td->td_flags & TDF_EXITED),
+           ("lwkt_alloc_thread: unexpected NULL or corrupted td"));
+       TAILQ_REMOVE(&mycpu->gd_tdfreeq, td, td_threadq);
+       crit_exit();
+       stack = td->td_kstack;
+    } else {
+       crit_exit();
+       td = zalloc(thread_zone);
+       stack = (void *)kmem_alloc(kernel_map, UPAGES * PAGE_SIZE);
+    }
+    lwkt_init_thread(td, stack, TDF_ALLOCATED_STACK|TDF_ALLOCATED_THREAD);
+    return(td);
 }
 
 /*
@@ -134,14 +138,40 @@ lwkt_alloc_thread(void)
  * NOTE!  called from low level boot code, we cannot do anything fancy!
  */
 void
-lwkt_init_thread(thread_t td, void *stack)
+lwkt_init_thread(thread_t td, void *stack, int flags)
 {
-       bzero(td, sizeof(struct thread));
-       lwkt_rwlock_init(&td->td_rwlock);
-       td->td_kstack = stack;
-       pmap_init_thread(td);
+    bzero(td, sizeof(struct thread));
+    td->td_kstack = stack;
+    td->td_flags |= flags;
+    pmap_init_thread(td);
 }
 
+void
+lwkt_free_thread(struct thread *td)
+{
+    KASSERT(td->td_flags & TDF_EXITED,
+       ("lwkt_free_thread: did not exit! %p", td));
+
+    crit_enter();
+    if (mycpu->gd_tdfreecount < CACHE_NTHREADS &&
+       (td->td_flags & TDF_ALLOCATED_THREAD)
+    ) {
+       ++mycpu->gd_tdfreecount;
+       TAILQ_INSERT_HEAD(&mycpu->gd_tdfreeq, td, td_threadq);
+       crit_exit();
+    } else {
+       crit_exit();
+       if (td->td_kstack && (td->td_flags & TDF_ALLOCATED_STACK)) {
+           kmem_free(kernel_map,
+                   (vm_offset_t)td->td_kstack, UPAGES * PAGE_SIZE);
+           td->td_kstack = NULL;
+       }
+       if (td->td_flags & TDF_ALLOCATED_THREAD)
+           zfree(thread_zone, td);
+    }
+}
+
+
 /*
  * Switch to the next runnable lwkt.  If no LWKTs are runnable then 
  * switch to the idlethread.  Switching must occur within a critical
@@ -169,17 +199,21 @@ lwkt_switch(void)
     thread_t ntd;
 
     crit_enter();
-    if ((ntd = TAILQ_FIRST(&mycpu->gd_tdrunq)) != NULL) {
+    if ((ntd = td->td_preempted) != NULL) {
+       /*
+        * We had preempted another thread on this cpu, resume the preempted
+        * thread.
+        */
+       td->td_preempted = NULL;
+       ntd->td_flags &= ~TDF_PREEMPTED;
+    } else if ((ntd = TAILQ_FIRST(&mycpu->gd_tdrunq)) != NULL) {
        TAILQ_REMOVE(&mycpu->gd_tdrunq, ntd, td_threadq);
        TAILQ_INSERT_TAIL(&mycpu->gd_tdrunq, ntd, td_threadq);
     } else {
        ntd = &mycpu->gd_idlethread;
     }
-    if (td != ntd) {
-       td->td_flags &= ~TDF_RUNNING;
-       ntd->td_flags |= TDF_RUNNING;
+    if (td != ntd)
        td->td_switch(ntd);
-    }
     crit_exit();
 }
 
@@ -257,7 +291,6 @@ lwkt_schedule_self(void)
 
     crit_enter();
     KASSERT(td->td_wait == NULL, ("lwkt_schedule_self(): td_wait not NULL!"));
-    KASSERT(td->td_flags & TDF_RUNNING, ("lwkt_schedule_self(): TDF_RUNNING not set!"));
     _lwkt_enqueue(td);
     crit_exit();
 }
@@ -351,7 +384,6 @@ lwkt_deschedule_self(void)
 
     crit_enter();
     KASSERT(td->td_wait == NULL, ("lwkt_schedule_self(): td_wait not NULL!"));
-    KASSERT(td->td_flags & TDF_RUNNING, ("lwkt_schedule_self(): TDF_RUNNING not set!"));
     _lwkt_dequeue(td);
     crit_exit();
 }
@@ -528,3 +560,97 @@ lwkt_regettoken(lwkt_token_t tok)
     return(0);
 }
 
+/*
+ * Create a kernel process/thread/whatever.  It shares it's address space
+ * with proc0 - ie: kernel only.
+ *
+ * XXX should be renamed to lwkt_create()
+ */
+int
+lwkt_create(void (*func)(void *), void *arg,
+    struct thread **tdp, const char *fmt, ...)
+{
+    struct thread *td;
+    va_list ap;
+
+    td = *tdp = lwkt_alloc_thread();
+    cpu_set_thread_handler(td, kthread_exit, func, arg);
+    td->td_flags |= TDF_VERBOSE;
+
+    /*
+     * Set up arg0 for 'ps' etc
+     */
+    va_start(ap, fmt);
+    vsnprintf(td->td_comm, sizeof(td->td_comm), fmt, ap);
+    va_end(ap);
+
+    /*
+     * Schedule the thread to run
+     */
+    lwkt_schedule(td);
+    return 0;
+}
+
+/*
+ * Destroy an LWKT thread.   Warning!  This function is not called when
+ * a process exits, cpu_proc_exit() directly calls cpu_thread_exit() and
+ * uses a different reaping mechanism.
+ */
+void
+lwkt_exit(void)
+{
+    thread_t td = curthread;
+
+    if (td->td_flags & TDF_VERBOSE)
+       printf("kthread %p %s has exited\n", td, td->td_comm);
+    crit_enter();
+    lwkt_deschedule_self();
+    ++mycpu->gd_tdfreecount;
+    TAILQ_INSERT_TAIL(&mycpu->gd_tdfreeq, td, td_threadq);
+    cpu_thread_exit();
+}
+
+/*
+ * Create a kernel process/thread/whatever.  It shares it's address space
+ * with proc0 - ie: kernel only.
+ *
+ * XXX exact duplicate of lwkt_create().
+ */
+int
+kthread_create(void (*func)(void *), void *arg,
+    struct thread **tdp, const char *fmt, ...)
+{
+    struct thread *td;
+    va_list ap;
+
+    td = *tdp = lwkt_alloc_thread();
+    cpu_set_thread_handler(td, kthread_exit, func, arg);
+    td->td_flags |= TDF_VERBOSE;
+
+    /*
+     * Set up arg0 for 'ps' etc
+     */
+    va_start(ap, fmt);
+    vsnprintf(td->td_comm, sizeof(td->td_comm), fmt, ap);
+    va_end(ap);
+
+    /*
+     * Schedule the thread to run
+     */
+    lwkt_schedule(td);
+    return 0;
+}
+
+/*
+ * Destroy an LWKT thread.   Warning!  This function is not called when
+ * a process exits, cpu_proc_exit() directly calls cpu_thread_exit() and
+ * uses a different reaping mechanism.
+ *
+ * XXX duplicates lwkt_exit()
+ */
+void
+kthread_exit(void)
+{
+    lwkt_exit();
+}
+
index 87ef056..006b6cf 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.13 2003/06/27 01:53:24 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/genassym.c,v 1.14 2003/06/27 03:30:37 dillon Exp $
  */
 
 #include "opt_user_ldt.h"
@@ -85,8 +85,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(TD_WCHAN, offsetof(struct thread, td_wchan));
+ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
+ASSYM(TDF_EXITED, TDF_EXITED);
 
 ASSYM(RW_OWNER, offsetof(struct lwkt_rwlock, rw_owner));
 
index b69c5d6..89b6bcb 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.12 2003/06/25 03:55:53 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.13 2003/06/27 03:30:37 dillon Exp $
  */
 
 #include "apm.h"
@@ -1866,14 +1866,13 @@ init386(first)
         */
        gd = &CPU_prvspace[0].globaldata;
 
-       lwkt_init_thread(&thread0, proc0paddr);
+       lwkt_init_thread(&thread0, proc0paddr, 0);
        gd->gd_curthread = &thread0;
        safepri = thread0.td_cpl = SWI_MASK | HWI_MASK;
        thread0.td_switch = cpu_heavy_switch;   /* YYY eventually LWKT */
        proc0.p_addr = (void *)thread0.td_kstack;
        proc0.p_thread = &thread0;
        thread0.td_proc = &proc0;
-       thread0.td_flags = TDF_RUNNING;
 
        atdevbase = ISA_HOLE_START + KERNBASE;
 
@@ -2088,7 +2087,7 @@ cpu_gdinit(struct globaldata *gd, int cpu)
        if (cpu)
            gd->gd_curthread = &gd->gd_idlethread;
        sp = gd->gd_prvspace->idlestack;
-       lwkt_init_thread(&gd->gd_idlethread, sp);
+       lwkt_init_thread(&gd->gd_idlethread, sp, 0);
        gd->gd_idlethread.td_switch = cpu_lwkt_switch;
        gd->gd_idlethread.td_sp -= sizeof(void *);
        *(void **)gd->gd_idlethread.td_sp = cpu_idle_restore;
index 79f3781..6bdabe6 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.10 2003/06/22 04:30:39 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/pmap.c,v 1.11 2003/06/27 03:30:37 dillon Exp $
  */
 
 /*
@@ -850,29 +850,6 @@ pmap_init_thread(thread_t td)
        td->td_sp = (char *)td->td_pcb - 16;
 }
 
-/*
- * Dispose of a thread, unlink it from its related proc (if any).  Keep
- * CACHE_NTHREAD threads around for fast-startup.
- */
-void
-pmap_dispose_thread(struct thread *td)
-{
-       /* HIPRI YYY */
-       KASSERT((td->td_flags & (TDF_RUNQ|TDF_RUNNING)) == 0,
-               ("pmap_dispose_thread: still on queue: %08x", td->td_flags));
-       if (mycpu->gd_tdfreecount < CACHE_NTHREADS) {
-               ++mycpu->gd_tdfreecount;
-               TAILQ_INSERT_HEAD(&mycpu->gd_tdfreeq, td, td_threadq);
-       } else {
-               if (td->td_kstack) {
-                       kmem_free(kernel_map,
-                           (vm_offset_t)td->td_kstack, UPAGES * PAGE_SIZE);
-                       td->td_kstack = NULL;
-               }
-               zfree(thread_zone, td);
-       }
-}
-
 /*
  * Create the UPAGES for a new process.
  * This routine directly affects the fork perf for a process.
index 65376ef..90e8319 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.13 2003/06/27 01:53:24 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/swtch.s,v 1.14 2003/06/27 03:30:37 dillon Exp $
  */
 
 #include "npx.h"
@@ -214,17 +214,15 @@ ENTRY(cpu_exit_switch)
        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.
+        * We are now the next thread, set the exited flag and wakeup
+        * any waiters.
         */
-       addl    $TD_RWLOCK,%ecx
-       movl    %eax,RW_OWNER(%ecx)
+       orl     $TDF_EXITED,TD_FLAGS(%ecx)
        pushl   %eax
-       pushl   %ecx
-       call    lwkt_exunlock
+       pushl   %ecx    /* wakeup(oldthread) */
+       call    wakeup
        addl    $4,%esp
-       popl    %eax
+       popl    %eax    /* note: next thread expects curthread in %eax */
 
        /*
         * Restore the next thread's state and resume it.  Note: the
index b33d9fc..6855450 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.11 2003/06/27 01:53:24 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/vm_machdep.c,v 1.12 2003/06/27 03:30:37 dillon Exp $
  */
 
 #include "npx.h"
@@ -257,19 +257,21 @@ cpu_set_thread_handler(thread_t td, void (*rfunc)(void), void *func, void *arg)
 }
 
 void
-cpu_exit(p)
-       register struct proc *p;
+cpu_proc_exit(void)
 {
+       struct thread *td = curthread;
        struct pcb *pcb;
 
+
 #if NNPX > 0
-       npxexit(p);
+       KKASSERT(td->td_proc);
+       npxexit(td->td_proc);
 #endif /* NNPX */
 
        /*
         * Cleanup the PCB
         */
-       pcb = curthread->td_pcb;
+       pcb = td->td_pcb;
        if (pcb->pcb_ext != 0) {
                /* 
                 * XXX do we need to move the TSS off the allocated pages 
@@ -291,29 +293,41 @@ cpu_exit(p)
         }
        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();
+       cpu_thread_exit();
+}
+
+/*
+ * Terminate the current thread.  The caller must have already acquired
+ * the thread's rwlock and placed it on a reap list or otherwise notified
+ * a reaper of its existance.  We set a special assembly switch function which
+ * releases td_rwlock after it has cleaned up the MMU state and switched
+ * out the stack.
+ *
+ * Must be caller from a critical section and with the thread descheduled.
+ */
+void
+cpu_thread_exit(void)
+{
+       curthread->td_switch = cpu_exit_switch;
        lwkt_switch();
        panic("cpu_exit");
 }
 
+/*
+ * Process Reaper.  Called after the caller has acquired the thread's
+ * rwlock and removed it from the reap list.
+ */
 void
-cpu_wait(p)
-       struct proc *p;
+cpu_proc_wait(struct proc *p)
 {
        struct thread *td;
 
        /* drop per-process resources */
        td = pmap_dispose_proc(p);
        if (td)
-           pmap_dispose_thread(td);
+               lwkt_free_thread(td);
 }
 
 /*
index 3eb6aab..6a90bea 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.13 2003/06/27 01:53:24 dillon Exp $
+ * $DragonFly: src/sys/platform/vkernel/i386/genassym.c,v 1.14 2003/06/27 03:30:37 dillon Exp $
  */
 
 #include "opt_user_ldt.h"
@@ -85,8 +85,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(TD_WCHAN, offsetof(struct thread, td_wchan));
+ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
+ASSYM(TDF_EXITED, TDF_EXITED);
 
 ASSYM(RW_OWNER, offsetof(struct lwkt_rwlock, rw_owner));
 
index 83cfe69..1d43761 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/sys/kthread.h,v 1.2 2000/01/07 08:36:44 luoqi Exp $
- * $DragonFly: src/sys/sys/kthread.h,v 1.4 2003/06/27 01:53:26 dillon Exp $
+ * $DragonFly: src/sys/sys/kthread.h,v 1.5 2003/06/27 03:30:43 dillon Exp $
  */
 
 #ifndef _SYS_KTHREAD_H_
@@ -45,13 +45,14 @@ struct kproc_desc {
 };
 
 void   kproc_start __P((const void *));
-int     kthread_create __P((void (*)(void *), void *, struct thread **,
-           const char *, ...)) __printflike(4, 5);
-void    kthread_exit __P((void)) __dead2;
 
 int    suspend_kproc __P((struct thread *, int));
 int    resume_kproc __P((struct thread *));
 void   kproc_suspend_loop __P((void));
 void   shutdown_kproc __P((void *, int));
+int    kthread_create __P((void (*)(void *), void *, struct thread **,
+                       const char *, ...));
+void   kthread_exit __P((void)) __dead2;
+
 
 #endif
index 683d1a3..f4eaefc 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.16 2003/06/27 01:53:26 dillon Exp $
+ * $DragonFly: src/sys/sys/proc.h,v 1.17 2003/06/27 03:30:43 dillon Exp $
  */
 
 #ifndef _SYS_PROC_H_
@@ -281,7 +281,6 @@ 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 */
 
 #ifdef _KERNEL
 
@@ -414,7 +413,8 @@ void        cpu_heavy_switch __P((struct thread *));
 void   cpu_lwkt_switch __P((struct thread *));
 void   unsleep __P((struct thread *));
 
-void   cpu_exit __P((struct proc *)) __dead2;
+void   cpu_proc_exit __P((void)) __dead2;
+void   cpu_thread_exit __P((void)) __dead2;
 void   exit1 __P((int)) __dead2;
 void   cpu_fork __P((struct proc *, struct proc *, int));
 void   cpu_set_fork_handler __P((struct proc *, void (*)(void *), void *));
@@ -422,7 +422,8 @@ void        cpu_set_thread_handler(struct thread *td, void (*retfunc)(void), void *func
 int    fork1 __P((struct proc *, int, struct proc **));
 void   start_forked_proc __P((struct proc *, struct proc *));
 int    trace_req __P((struct proc *));
-void   cpu_wait __P((struct proc *));
+void   cpu_proc_wait __P((struct proc *));
+void   cpu_thread_wait __P((struct thread *));
 int    cpu_coredump __P((struct thread *, struct vnode *, struct ucred *));
 void   setsugid __P((void));
 void   faultin __P((struct proc *p));
index 60d5f2f..748b608 100644 (file)
@@ -4,7 +4,7 @@
  *     Implements the architecture independant portion of the LWKT 
  *     subsystem.
  * 
- * $DragonFly: src/sys/sys/thread.h,v 1.10 2003/06/27 01:53:26 dillon Exp $
+ * $DragonFly: src/sys/sys/thread.h,v 1.11 2003/06/27 03:30:43 dillon Exp $
  */
 
 #ifndef _SYS_THREAD_H_
@@ -132,25 +132,26 @@ 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 */
     u_int64_t  td_uticks;      /* Statclock hits in user mode (uS) */
     u_int64_t  td_sticks;      /* Statclock hits in system mode (uS) */
     u_int64_t  td_iticks;      /* Statclock hits processing intr (uS) */
     int                td_locks;       /* lockmgr lock debugging YYY */
     char       td_comm[MAXCOMLEN+1]; /* typ 16+1 bytes */
+    struct thread *td_preempted; /* we preempted this thread */
     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
- * while it is running.  If a thread is preempted it will always be moved
- * back to the RUNQ if it isn't on it.
+ * Thread flags.  Note that TDF_EXITED is set by the appropriate switchout
+ * code when a thread exits, after it has switched to another stack and
+ * cleaned up the MMU state.
  */
-#define TDF_RUNNING            0x0001  /* currently running */
+#define TDF_EXITED             0x0001  /* thread finished exiting */
 #define TDF_RUNQ               0x0002  /* on run queue */
+#define TDF_PREEMPTED          0x0004  /* thread is currently preempted */
+#define TDF_ALLOCATED_THREAD   0x0200  /* zalloc allocated thread */
+#define TDF_ALLOCATED_STACK    0x0400  /* zalloc allocated stack */
+#define TDF_VERBOSE            0x0800  /* verbose on exit */
 #define TDF_DEADLKTREAT                0x1000  /* special lockmgr deadlock treatment */
 #define TDF_STOPREQ            0x2000  /* suspend_kproc */
 #define TDF_WAKEREQ            0x4000  /* resume_kproc */
@@ -190,7 +191,8 @@ struct thread {
 extern struct vm_zone  *thread_zone;
 
 extern struct thread *lwkt_alloc_thread(void);
-extern void lwkt_init_thread(struct thread *td, void *stack);
+extern void lwkt_init_thread(struct thread *td, void *stack, int flags);
+extern void lwkt_free_thread(struct thread *td);
 extern void lwkt_init_wait(struct lwkt_wait *w);
 extern void lwkt_gdinit(struct globaldata *gd);
 extern void lwkt_switch(void);
@@ -213,6 +215,10 @@ 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);
 
+extern int  lwkt_create (void (*func)(void *), void *arg, struct thread **ptd,
+                           const char *ctl, ...);
+extern void lwkt_exit __P((void)) __dead2;
+
 #endif
 
 #endif
index 789ce96..fab9153 100644 (file)
@@ -62,7 +62,7 @@
  * rights to redistribute these changes.
  *
  * $FreeBSD: src/sys/vm/pmap.h,v 1.33.2.4 2002/03/06 22:44:24 silby Exp $
- * $DragonFly: src/sys/vm/pmap.h,v 1.5 2003/06/22 04:30:43 dillon Exp $
+ * $DragonFly: src/sys/vm/pmap.h,v 1.6 2003/06/27 03:30:43 dillon Exp $
  */
 
 /*
@@ -138,7 +138,6 @@ void                 pmap_prefault __P((pmap_t, vm_offset_t, vm_map_entry_t));
 int             pmap_mincore __P((pmap_t pmap, vm_offset_t addr));
 void            pmap_init_proc __P((struct proc *p, struct thread *td));
 void            pmap_init_thread __P((struct thread *td));
-void            pmap_dispose_thread __P((struct thread *td));
 struct thread  *pmap_dispose_proc __P((struct proc *p));
 void            pmap_swapout_proc __P((struct proc *p));
 void            pmap_swapin_proc __P((struct proc *p));
index 1c5b597..9589958 100644 (file)
@@ -60,7 +60,7 @@
  * rights to redistribute these changes.
  *
  * $FreeBSD: src/sys/vm/vm_glue.c,v 1.94.2.4 2003/01/13 22:51:17 dillon Exp $
- * $DragonFly: src/sys/vm/vm_glue.c,v 1.6 2003/06/25 03:56:12 dillon Exp $
+ * $DragonFly: src/sys/vm/vm_glue.c,v 1.7 2003/06/27 03:30:43 dillon Exp $
  */
 
 #include "opt_vm.h"
@@ -283,7 +283,7 @@ vm_fork(p1, p2, flags)
 void
 vm_waitproc(struct proc *p)
 {
-       cpu_wait(p);
+       cpu_proc_wait(p);
        vmspace_exitfree(p);    /* and clean-out the vmspace */
 }