Newtoken commit. Change the token implementation as follows: (1) Obtaining
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 1 Mar 2004 06:33:24 +0000 (06:33 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 1 Mar 2004 06:33:24 +0000 (06:33 +0000)
a token no longer enters a critical section.  (2) tokens can be held through
schedular switches and blocking conditions and are effectively released and
reacquired on resume.  Thus tokens serialize access only while the thread
is actually running.  Serialization is not broken by preemptive interrupts.
That is, interrupt threads which preempt do no release the preempted thread's
tokens.  (3) Unlike spl's, tokens will interlock w/ interrupt threads on
the same or on a different cpu.

The vnode interlock code has been rewritten and the API has changed.  The
mountlist vnode scanning code has been consolidated and all known races have
been fixed.  The vnode interlock is now a pool token.

The code that frees unreferenced vnodes whos last VM page has been freed has
been moved out of the low level vm_page_free() code and moved to the
periodic filesystem sycer code in vfs_msycn().

The SMP startup code and the IPI code has been cleaned up considerably.
Certain early token interactions on AP cpus have been moved to the BSP.

The LWKT rwlock API has been cleaned up and turned on.

Major testing by: David Rhodus

163 files changed:
sys/config/LINT
sys/ddb/db_ps.c
sys/dev/acpica5/Osd/OsdSynch.c
sys/dev/acpica5/acpi_ec.c
sys/dev/agp/agp.c
sys/dev/disk/ccd/ccd.c
sys/dev/disk/vn/vn.c
sys/dev/drm/drm_os_freebsd.h
sys/dev/pccard/pccbb/pccbb.c
sys/dev/raid/aac/aacvar.h
sys/emulation/43bsd/43bsd_file.c
sys/emulation/ibcs2/coff/imgact_coff.c
sys/emulation/ibcs2/i386/ibcs2_misc.c
sys/emulation/linux/i386/linprocfs/linprocfs_subr.c
sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c
sys/emulation/linux/linux_file.c
sys/emulation/linux/linux_getcwd.c
sys/emulation/linux/linux_misc.c
sys/emulation/svr4/svr4_misc.c
sys/i386/apic/mpapic.c
sys/i386/apic/mpapic.h
sys/i386/conf/LINT
sys/i386/i386/machdep.c
sys/i386/i386/mp_machdep.c
sys/i386/i386/mpapic.c
sys/i386/i386/nexus.c
sys/i386/i386/pmap.c
sys/i386/include/mpapic.h
sys/i386/include/smp.h
sys/kern/imgact_elf.c
sys/kern/init_main.c
sys/kern/kern_acct.c
sys/kern/kern_acl.c
sys/kern/kern_descrip.c
sys/kern/kern_exec.c
sys/kern/kern_fp.c
sys/kern/kern_ktrace.c
sys/kern/kern_linker.c
sys/kern/kern_lock.c
sys/kern/kern_sig.c
sys/kern/kern_switch.c
sys/kern/link_aout.c
sys/kern/link_elf.c
sys/kern/lwkt_ipiq.c
sys/kern/lwkt_rwlock.c
sys/kern/lwkt_thread.c
sys/kern/lwkt_token.c
sys/kern/subr_rman.c
sys/kern/tty_tty.c
sys/kern/uipc_syscalls.c
sys/kern/uipc_usrreq.c
sys/kern/vfs_bio.c
sys/kern/vfs_cache.c
sys/kern/vfs_conf.c
sys/kern/vfs_default.c
sys/kern/vfs_lookup.c
sys/kern/vfs_subr.c
sys/kern/vfs_syscalls.c
sys/kern/vfs_vnops.c
sys/kern/vnode_if.src
sys/netproto/ncp/ncp_conn.c
sys/netproto/smb/smb_conn.c
sys/netproto/smb/smb_conn.h
sys/netproto/smb/smb_iod.c
sys/netproto/smb/smb_rq.c
sys/netproto/smb/smb_rq.h
sys/netproto/smb/smb_subr.c
sys/netproto/smb/smb_subr.h
sys/platform/pc32/apic/mpapic.c
sys/platform/pc32/apic/mpapic.h
sys/platform/pc32/i386/machdep.c
sys/platform/pc32/i386/mp_machdep.c
sys/platform/pc32/i386/mpapic.c
sys/platform/pc32/i386/nexus.c
sys/platform/pc32/i386/pmap.c
sys/platform/pc32/include/mpapic.h
sys/platform/pc32/include/smp.h
sys/sys/buf2.h
sys/sys/globaldata.h
sys/sys/kernel.h
sys/sys/lock.h
sys/sys/mount.h
sys/sys/proc.h
sys/sys/rman.h
sys/sys/thread.h
sys/sys/thread2.h
sys/sys/vnode.h
sys/vfs/coda/coda_subr.c
sys/vfs/coda/coda_vfsops.c
sys/vfs/coda/coda_vnops.c
sys/vfs/deadfs/dead_vnops.c
sys/vfs/fdesc/fdesc_vfsops.c
sys/vfs/fdesc/fdesc_vnops.c
sys/vfs/fifofs/fifo_vnops.c
sys/vfs/gnu/ext2fs/ext2_lookup.c
sys/vfs/gnu/ext2fs/ext2_vfsops.c
sys/vfs/gnu/ext2fs/ext2_vnops.c
sys/vfs/gnu/ext2fs/fs.h
sys/vfs/hpfs/hpfs.h
sys/vfs/hpfs/hpfs_hash.c
sys/vfs/hpfs/hpfs_vfsops.c
sys/vfs/isofs/cd9660/cd9660_lookup.c
sys/vfs/isofs/cd9660/cd9660_node.c
sys/vfs/isofs/cd9660/cd9660_vfsops.c
sys/vfs/mfs/mfs_vnops.c
sys/vfs/msdosfs/msdosfs_denode.c
sys/vfs/msdosfs/msdosfs_lookup.c
sys/vfs/msdosfs/msdosfs_vfsops.c
sys/vfs/msdosfs/msdosfs_vnops.c
sys/vfs/nfs/nfs_node.c
sys/vfs/nfs/nfs_nqlease.c
sys/vfs/nfs/nfs_serv.c
sys/vfs/nfs/nfs_subs.c
sys/vfs/nfs/nfs_vfsops.c
sys/vfs/nfs/nfs_vnops.c
sys/vfs/ntfs/ntfs.h
sys/vfs/ntfs/ntfs_ihash.c
sys/vfs/ntfs/ntfs_subr.c
sys/vfs/ntfs/ntfs_vfsops.c
sys/vfs/nullfs/null_subr.c
sys/vfs/nullfs/null_vfsops.c
sys/vfs/nullfs/null_vnops.c
sys/vfs/nwfs/nwfs_node.c
sys/vfs/nwfs/nwfs_vfsops.c
sys/vfs/nwfs/nwfs_vnops.c
sys/vfs/portal/portal_vfsops.c
sys/vfs/portal/portal_vnops.c
sys/vfs/procfs/procfs_subr.c
sys/vfs/procfs/procfs_vnops.c
sys/vfs/smbfs/smbfs_io.c
sys/vfs/smbfs/smbfs_node.c
sys/vfs/smbfs/smbfs_vfsops.c
sys/vfs/smbfs/smbfs_vnops.c
sys/vfs/specfs/spec_vnops.c
sys/vfs/ufs/ffs_rawread.c
sys/vfs/ufs/ffs_softdep.c
sys/vfs/ufs/ffs_vfsops.c
sys/vfs/ufs/ufs_ihash.c
sys/vfs/ufs/ufs_inode.c
sys/vfs/ufs/ufs_lookup.c
sys/vfs/ufs/ufs_quota.c
sys/vfs/ufs/ufs_vfsops.c
sys/vfs/ufs/ufs_vnops.c
sys/vfs/umapfs/umap_subr.c
sys/vfs/umapfs/umap_vfsops.c
sys/vfs/umapfs/umap_vnops.c
sys/vfs/union/union_subr.c
sys/vfs/union/union_vfsops.c
sys/vfs/union/union_vnops.c
sys/vm/vm_contig.c
sys/vm/vm_extern.h
sys/vm/vm_fault.c
sys/vm/vm_glue.c
sys/vm/vm_init.c
sys/vm/vm_kern.c
sys/vm/vm_map.c
sys/vm/vm_map.h
sys/vm/vm_object.c
sys/vm/vm_page.c
sys/vm/vm_pageout.c
sys/vm/vm_swap.c
sys/vm/vm_zone.c
sys/vm/vnode_pager.c

index bcb713a..293ecc6 100644 (file)
@@ -3,7 +3,7 @@
 #      as much of the source tree as it can.
 #
 # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $
-# $DragonFly: src/sys/config/LINT,v 1.23 2004/02/27 11:56:12 joerg Exp $
+# $DragonFly: src/sys/config/LINT,v 1.24 2004/03/01 06:33:16 dillon Exp $
 #
 # NB: You probably don't want to try running a kernel built from this
 # file.  Instead, you should start from GENERIC, and add options from
@@ -2684,8 +2684,6 @@ device            ubsec           # Broadcom 5501, 5601, 58xx
 options                UBSEC_DEBUG     # enable debugging support: hw.ubsec.debug
 options                UBSEC_RNDTEST   # enable rndtest support
 
-device         acpica          # basic ACPI support
-
 # DRM options:
 # mgadrm:    AGP Matrox G200, G400, G450, G550
 # tdfxdrm:   3dfx Voodoo 3/4/5 and Banshee
index 3f5a8c4..4b31e07 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/ddb/db_ps.c,v 1.20 1999/08/28 00:41:09 peter Exp $
- * $DragonFly: src/sys/ddb/db_ps.c,v 1.8 2003/07/12 17:54:30 dillon Exp $
+ * $DragonFly: src/sys/ddb/db_ps.c,v 1.9 2004/03/01 06:32:49 dillon Exp $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -40,7 +40,7 @@
 
 #include <ddb/ddb.h>
 
-static void
+static int
 db_more(int *nl)
 {
        ++*nl;
@@ -62,11 +62,14 @@ db_more(int *nl)
                        break;
                default:                /* exit */
                        db_printf("\n");
-                       return;
+                       return(-1);
                }
        }
+       return(0);
 }
 
+static void db_dump_td_tokens(thread_t td);
+
 void
 db_ps(dummy1, dummy2, dummy3, dummy4)
        db_expr_t       dummy1;
@@ -86,12 +89,15 @@ db_ps(dummy1, dummy2, dummy3, dummy4)
        else
                p = &proc0;
 
+       if (db_more(&nl) < 0)
+           return;
        db_printf("  pid   proc     addr    uid  ppid  pgrp  flag stat wmesg   wchan   cmd\n");
        while (--np >= 0) {
                /*
                 * XXX just take 20 for now...
                 */
-               db_more(&nl);
+               if (db_more(&nl) < 0)
+                       return;
                if (p == NULL) {
                        printf("oops, ran out of processes early!\n");
                        break;
@@ -110,6 +116,7 @@ db_ps(dummy1, dummy2, dummy3, dummy4)
                        db_printf("                 ");
                }
                db_printf(" %s\n", p->p_comm ? p->p_comm : "");
+               db_dump_td_tokens(p->p_thread);
 
                p = p->p_list.le_next;
                if (p == NULL && np > 0)
@@ -120,16 +127,46 @@ db_ps(dummy1, dummy2, dummy3, dummy4)
         * Dump running threads
         */
        for (cpuidx = 0; cpuidx < ncpus; ++cpuidx) {
-           thread_t td;
            struct globaldata *gd = &CPU_prvspace[cpuidx].mdglobaldata.mi;
+           thread_t td;
+           int j;
 
+           if (db_more(&nl) < 0)
+               return;
            db_printf("cpu %d tdrunqmask %08x curthread %p reqflags %04x\n",
                    gd->gd_cpuid, gd->gd_runqmask,
                    gd->gd_curthread, gd->gd_reqflags);
+           if (gd->gd_tokreqbase) {
+               lwkt_tokref_t ref;
+
+               if (db_more(&nl) < 0)
+                   return;
+               db_printf("      tokenrequests:");
+               for (ref = gd->gd_tokreqbase; ref; ref = ref->tr_next) {
+                   db_printf(" [r=%p,t=%p]", ref, ref->tr_tok);
+               }
+               db_printf("\n");
+           }
+           if (db_more(&nl) < 0)
+               return;
+           db_printf("      INCOMMING IPIQS:");
+           for (j = 0; j < ncpus; ++j) {
+               lwkt_ipiq_t ip = globaldata_find(j)->gd_ipiq;
+               if (ip != NULL) {
+                   ip = &ip[cpuidx];
+                   if (ip->ip_windex != ip->ip_rindex)
+                       db_printf(" cpu%d:%d", j, ip->ip_windex - ip->ip_rindex);
+               }
+           }
+           db_printf("\n");
+
+           if (db_more(&nl) < 0)
+               return;
            db_printf("  tdq     thread    pid flags  pri(act)        sp    wmesg comm\n");
            for (np = 0; np < 32; ++np) {
                TAILQ_FOREACH(td, &gd->gd_tdrunq[np], td_threadq) {
-                   db_more(&nl);
+                   if (db_more(&nl) < 0)
+                       return;
                    db_printf("  %3d %p %3d %08x %3d(%3d) %p %8.8s %s\n",
                        np, td, 
                        (td->td_proc ? td->td_proc->p_pid : -1),
@@ -138,12 +175,18 @@ db_ps(dummy1, dummy2, dummy3, dummy4)
                        td->td_sp,
                        td->td_wmesg ? td->td_wmesg : "-",
                        td->td_proc ? td->td_proc->p_comm : td->td_comm);
+                   db_dump_td_tokens(td);
                }
            }
+           if (db_more(&nl) < 0)
+               return;
            db_printf("\n");
+           if (db_more(&nl) < 0)
+               return;
            db_printf("  tdq     thread    pid flags  pri(act)        sp    wmesg comm\n");
            TAILQ_FOREACH(td, &gd->gd_tdallq, td_allq) {
-               db_more(&nl);
+               if (db_more(&nl) < 0)
+                   return;
                db_printf("  %3d %p %3d %08x %3d(%3d) %p %8.8s %s\n",
                    np, td, 
                    (td->td_proc ? td->td_proc->p_pid : -1),
@@ -152,11 +195,42 @@ db_ps(dummy1, dummy2, dummy3, dummy4)
                    td->td_sp,
                    td->td_wmesg ? td->td_wmesg : "-",
                    td->td_proc ? td->td_proc->p_comm : td->td_comm);
+               db_dump_td_tokens(td);
            }
        }
-       printf("CURCPU %d CURTHREAD %p (%d)\n",
+       if (db_more(&nl) < 0)
+           return;
+       db_printf("CURCPU %d CURTHREAD %p (%d)\n",
            mycpu->gd_cpuid,
            curthread,
            (curthread->td_proc ? curthread->td_proc->p_pid : -1)
        );
+       db_dump_td_tokens(curthread);
 }
+
+static void
+db_dump_td_tokens(thread_t td)
+{
+       lwkt_tokref_t ref;
+       lwkt_token_t tok;
+
+       if (td->td_toks == NULL)
+               return;
+       db_printf("    TOKENS:");
+       for (ref = td->td_toks; ref; ref = ref->tr_next) {
+               tok = ref->tr_tok;
+
+               db_printf(" %p[tok=%p", ref, ref->tr_tok);
+               if (td->td_gd == tok->t_cpu)
+                   db_printf(",held");
+               if (ref->tr_magic == LWKT_TOKREF_MAGIC1)
+                   ;
+               else if (ref->tr_magic == LWKT_TOKREF_MAGIC2)
+                   db_printf(",wait");
+               else
+                   db_printf(",badmagic");
+               db_printf("]");
+       }
+       db_printf("\n");
+}
+
index 9682647..b6b830a 100644 (file)
@@ -25,7 +25,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/acpica/Osd/OsdSynch.c,v 1.18 2003/09/26 21:22:10 njl Exp $
- * $DragonFly: src/sys/dev/acpica5/Osd/OsdSynch.c,v 1.1 2004/02/21 06:48:09 dillon Exp $
+ * $DragonFly: src/sys/dev/acpica5/Osd/OsdSynch.c,v 1.2 2004/03/01 06:33:13 dillon Exp $
  */
 
 /*
@@ -349,29 +349,27 @@ AcpiOsSignalSemaphore(ACPI_HANDLE Handle, UINT32 Units)
 ACPI_STATUS
 AcpiOsCreateLock (ACPI_HANDLE *OutHandle)
 {
-    lwkt_token_t tok;
+    lwkt_rwlock_t lock;
 
     if (OutHandle == NULL)
        return (AE_BAD_PARAMETER);
-    MALLOC(tok, lwkt_token_t, sizeof(*tok), M_ACPISEM, M_WAITOK | M_ZERO);
-    if (tok == NULL)
+    MALLOC(lock, lwkt_rwlock_t, sizeof(*lock), M_ACPISEM, M_WAITOK | M_ZERO);
+    if (lock == NULL)
        return (AE_NO_MEMORY);
 
-    lwkt_inittoken(tok);
-    *OutHandle = (ACPI_HANDLE)tok;
+    lwkt_rwlock_init(lock);
+    *OutHandle = (ACPI_HANDLE)lock;
     return (AE_OK);
 }
 
 void
 AcpiOsDeleteLock (ACPI_HANDLE Handle)
 {
-#if 0
-    lwkt_token_t tok = (lwkt_token_t)Handle;
+    lwkt_rwlock_t lock = (lwkt_rwlock_t)Handle;
 
     if (Handle == NULL)
         return;
-    /*mtx_destroy(m);*/
-#endif
+    lwkt_rwlock_uninit(lock);
 }
 
 /*
@@ -382,19 +380,19 @@ AcpiOsDeleteLock (ACPI_HANDLE Handle)
 void
 AcpiOsAcquireLock (ACPI_HANDLE Handle, UINT32 Flags)
 {
-    lwkt_token_t tok = (lwkt_token_t)Handle;
+    lwkt_rwlock_t lock = (lwkt_rwlock_t)Handle;
 
     if (Handle == NULL)
         return;
-    lwkt_gettoken(tok);
+    lwkt_exlock(lock, "acpi1");
 }
 
 void
 AcpiOsReleaseLock (ACPI_HANDLE Handle, UINT32 Flags)
 {
-    lwkt_token_t tok = (lwkt_token_t)Handle;
+    lwkt_rwlock_t lock = (lwkt_rwlock_t)Handle;
 
     if (Handle == NULL)
         return;
-    lwkt_reltoken(tok);
+    lwkt_exunlock(lock);
 }
index f8e5edf..85e1599 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.42 2004/01/03 02:01:39 njl Exp $
- * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.1 2004/02/21 06:48:08 dillon Exp $
+ * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.2 2004/03/01 06:33:13 dillon Exp $
  */
 /******************************************************************************
  *
  *****************************************************************************/
  /*
   * $FreeBSD: src/sys/dev/acpica/acpi_ec.c,v 1.42 2004/01/03 02:01:39 njl Exp $
-  * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.1 2004/02/21 06:48:08 dillon Exp $
+  * $DragonFly: src/sys/dev/acpica5/acpi_ec.c,v 1.2 2004/03/01 06:33:13 dillon Exp $
   *
   */
 
@@ -269,7 +269,7 @@ struct acpi_ec_softc {
 
     int                        ec_glk;
     int                        ec_glkhandle;
-    struct lwkt_token  ec_token;
+    struct lwkt_rwlock ec_rwlock;
     int                        ec_polldelay;
 };
 
@@ -304,13 +304,13 @@ EcLock(struct acpi_ec_softc *sc)
     ACPI_STATUS        status = AE_OK;
 
     /* Always acquire this EC's mutex. */
-    lwkt_gettoken(&sc->ec_token);
+    lwkt_exlock(&sc->ec_rwlock, "acpi2");
 
     /* If _GLK is non-zero, also acquire the global lock. */
     if (sc->ec_glk) {
        status = AcpiAcquireGlobalLock(EC_LOCK_TIMEOUT, &sc->ec_glkhandle);
        if (ACPI_FAILURE(status))
-           lwkt_reltoken(&sc->ec_token);
+           lwkt_exunlock(&sc->ec_rwlock);
     }
 
     return (status);
@@ -321,7 +321,7 @@ EcUnlock(struct acpi_ec_softc *sc)
 {
     if (sc->ec_glk)
        AcpiReleaseGlobalLock(sc->ec_glkhandle);
-    lwkt_reltoken(&sc->ec_token);
+    lwkt_exunlock(&sc->ec_rwlock);
 }
 
 static void            EcGpeHandler(void *Context);
@@ -501,9 +501,9 @@ acpi_ec_probe(device_t dev)
            if (sc->ec_glk != glk) {
                ACPI_VPRINT(peer, acpi_device_get_parent_softc(peer),
                    "Changing GLK from %d to %d\n", sc->ec_glk, glk);
-               lwkt_gettoken(&sc->ec_token);
+               lwkt_exlock(&sc->ec_rwlock, "acpi2");
                sc->ec_glk = glk != 0 ? 1 : 0;
-               lwkt_reltoken(&sc->ec_token);
+               lwkt_exunlock(&sc->ec_rwlock);
            }
        }
     }
@@ -525,7 +525,7 @@ acpi_ec_attach(device_t dev)
     sc->ec_dev = dev;
     sc->ec_handle = acpi_get_handle(dev);
     sc->ec_polldelay = EC_POLL_DELAY;
-    lwkt_inittoken(&sc->ec_token);
+    lwkt_rwlock_init(&sc->ec_rwlock);
 
     /* Retrieve previously probed values via device ivars. */
     magic = acpi_get_magic(dev);
index 4bcfa88..9b72f20 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  *     $FreeBSD: src/sys/pci/agp.c,v 1.3.2.4 2002/08/11 19:58:12 alc Exp $
- *     $DragonFly: src/sys/dev/agp/agp.c,v 1.9 2004/01/20 05:04:03 dillon Exp $
+ *     $DragonFly: src/sys/dev/agp/agp.c,v 1.10 2004/03/01 06:33:13 dillon Exp $
  */
 
 #include "opt_bus.h"
@@ -278,7 +278,7 @@ agp_generic_detach(device_t dev)
 {
        struct agp_softc *sc = device_get_softc(dev);
        bus_release_resource(dev, SYS_RES_MEMORY, AGP_APBASE, sc->as_aperture);
-       lockmgr(&sc->as_lock, LK_DRAIN, 0, curthread); /* XXX */
+       lockmgr(&sc->as_lock, LK_DRAIN, NULL, curthread); /* XXX */
        destroy_dev(sc->as_devnode);
        agp_flush_cache();
        return 0;
@@ -491,7 +491,7 @@ agp_generic_bind_memory(device_t dev, struct agp_memory *mem,
        vm_page_t m;
        int error;
 
-       lockmgr(&sc->as_lock, LK_EXCLUSIVE, 0, curthread); /* XXX */
+       lockmgr(&sc->as_lock, LK_EXCLUSIVE, NULL, curthread); /* XXX */
 
        if (mem->am_is_bound) {
                device_printf(dev, "memory already bound\n");
@@ -554,7 +554,7 @@ agp_generic_bind_memory(device_t dev, struct agp_memory *mem,
                                                           OFF_TO_IDX(k));
                                        vm_page_unwire(m, 0);
                                }
-                               lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
+                               lockmgr(&sc->as_lock, LK_RELEASE, NULL, curthread); /* XXX */
                                return error;
                        }
                }
@@ -575,7 +575,7 @@ agp_generic_bind_memory(device_t dev, struct agp_memory *mem,
        mem->am_offset = offset;
        mem->am_is_bound = 1;
 
-       lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
+       lockmgr(&sc->as_lock, LK_RELEASE, NULL, curthread); /* XXX */
 
        return 0;
 }
@@ -587,7 +587,7 @@ agp_generic_unbind_memory(device_t dev, struct agp_memory *mem)
        vm_page_t m;
        int i;
 
-       lockmgr(&sc->as_lock, LK_EXCLUSIVE, 0, curthread); /* XXX */
+       lockmgr(&sc->as_lock, LK_EXCLUSIVE, NULL, curthread); /* XXX */
 
        if (!mem->am_is_bound) {
                device_printf(dev, "memory is not bound\n");
@@ -612,7 +612,7 @@ agp_generic_unbind_memory(device_t dev, struct agp_memory *mem)
        mem->am_offset = 0;
        mem->am_is_bound = 0;
 
-       lockmgr(&sc->as_lock, LK_RELEASE, 0, curthread); /* XXX */
+       lockmgr(&sc->as_lock, LK_RELEASE, NULL, curthread); /* XXX */
 
        return 0;
 }
index 726fc1e..f6caf64 100644 (file)
@@ -1,5 +1,5 @@
 /* $FreeBSD: src/sys/dev/ccd/ccd.c,v 1.73.2.1 2001/09/11 09:49:52 kris Exp $ */
-/* $DragonFly: src/sys/dev/disk/ccd/ccd.c,v 1.12 2003/09/23 05:03:40 dillon Exp $ */
+/* $DragonFly: src/sys/dev/disk/ccd/ccd.c,v 1.13 2004/03/01 06:33:13 dillon Exp $ */
 
 /*     $NetBSD: ccd.c,v 1.22 1995/12/08 19:13:26 thorpej Exp $ */
 
@@ -1578,12 +1578,12 @@ ccdlookup(char *path, struct thread *td, struct vnode **vpp)
                vprint("ccdlookup: vnode info", vp);
 #endif
 
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        NDFREE(&nd, NDF_ONLY_PNBUF);
        *vpp = vp;
        return (0);
 bad:
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        NDFREE(&nd, NDF_ONLY_PNBUF);
        /* vn_close does vrele() for vp */
        (void)vn_close(vp, FREAD|FWRITE, td);
index 9e4bcf4..9ba4064 100644 (file)
@@ -39,7 +39,7 @@
  *
  *     from: @(#)vn.c  8.6 (Berkeley) 4/1/94
  * $FreeBSD: src/sys/dev/vn/vn.c,v 1.105.2.4 2001/11/18 07:11:00 dillon Exp $
- * $DragonFly: src/sys/dev/disk/vn/vn.c,v 1.7 2003/09/23 05:03:46 dillon Exp $
+ * $DragonFly: src/sys/dev/disk/vn/vn.c,v 1.8 2004/03/01 06:33:14 dillon Exp $
  */
 
 /*
@@ -387,12 +387,12 @@ vnstrategy(struct buf *bp)
                        auio.uio_rw = UIO_WRITE;
                auio.uio_resid = bp->b_bcount;
                auio.uio_td = curthread;
-               vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+               vn_lock(vn->sc_vp, NULL, LK_EXCLUSIVE | LK_RETRY, curthread);
                if (bp->b_flags & B_READ)
                        error = VOP_READ(vn->sc_vp, &auio, IO_DIRECT, vn->sc_cred);
                else
                        error = VOP_WRITE(vn->sc_vp, &auio, IO_NOWDRAIN, vn->sc_cred);
-               VOP_UNLOCK(vn->sc_vp, 0, curthread);
+               VOP_UNLOCK(vn->sc_vp, NULL, 0, curthread);
                bp->b_resid = auio.uio_resid;
 
                if (error) {
@@ -560,11 +560,11 @@ vniocattach_file(vn, vio, dev, flag, td)
        NDFREE(&nd, NDF_ONLY_PNBUF);
        if (nd.ni_vp->v_type != VREG ||
            (error = VOP_GETATTR(nd.ni_vp, &vattr, td))) {
-               VOP_UNLOCK(nd.ni_vp, 0, td);
+               VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
                (void) vn_close(nd.ni_vp, flags, td);
                return (error ? error : EINVAL);
        }
-       VOP_UNLOCK(nd.ni_vp, 0, td);
+       VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
        vn->sc_secsize = DEV_BSIZE;
        vn->sc_vp = nd.ni_vp;
 
@@ -715,9 +715,9 @@ vnsetcred(struct vn_softc *vn, struct ucred *cred)
                auio.uio_rw = UIO_READ;
                auio.uio_segflg = UIO_SYSSPACE;
                auio.uio_resid = aiov.iov_len;
-               vn_lock(vn->sc_vp, LK_EXCLUSIVE | LK_RETRY, curthread);
+               vn_lock(vn->sc_vp, NULL, LK_EXCLUSIVE | LK_RETRY, curthread);
                error = VOP_READ(vn->sc_vp, &auio, 0, vn->sc_cred);
-               VOP_UNLOCK(vn->sc_vp, 0, curthread);
+               VOP_UNLOCK(vn->sc_vp, NULL, 0, curthread);
                free(tmpbuf, M_TEMP);
        }
        return (error);
index 451f6c2..acfb20b 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * $FreeBSD: src/sys/dev/drm/drm_os_freebsd.h,v 1.10.2.1 2003/04/26 07:05:28 anholt Exp $
- * $DragonFly: src/sys/dev/drm/Attic/drm_os_freebsd.h,v 1.8 2004/02/13 01:23:57 joerg Exp $
+ * $DragonFly: src/sys/dev/drm/Attic/drm_os_freebsd.h,v 1.9 2004/03/01 06:33:14 dillon Exp $
  */
 #include <sys/param.h>
 #include <sys/queue.h>
 #else
 #define DRM_CURPROC            curthread
 #define DRM_STRUCTPROC         struct thread
-#define DRM_SPINTYPE           struct lwkt_token
-#define DRM_SPININIT(l,name)   lwkt_inittoken(&l)
+#define DRM_SPINTYPE           struct lwkt_rwlock
+#define DRM_SPININIT(l,name)   lwkt_rwlock_init(&l)
 #define DRM_SPINUNINIT(l)
-#define DRM_SPINLOCK(l)                lwkt_gettoken(l)
-#define DRM_SPINUNLOCK(u)      lwkt_reltoken(u);
+#define DRM_SPINLOCK(l)                lwkt_exlock(l, "drm")
+#define DRM_SPINUNLOCK(u)      lwkt_exunlock(u);
 #define DRM_CURRENTPID         curthread->td_proc->p_pid
 #endif
 
  * code for that is not yet written */
 #define DRMFILE                        void *
 #define DRM_IOCTL_ARGS         dev_t kdev, u_long cmd, caddr_t data, int flags, DRM_STRUCTPROC *p, DRMFILE filp
-#define DRM_LOCK               lockmgr(&dev->dev_lock, LK_EXCLUSIVE, 0, DRM_CURPROC)
-#define DRM_UNLOCK             lockmgr(&dev->dev_lock, LK_RELEASE, 0, DRM_CURPROC)
+#define DRM_LOCK               lockmgr(&dev->dev_lock, LK_EXCLUSIVE, NULL, DRM_CURPROC)
+#define DRM_UNLOCK             lockmgr(&dev->dev_lock, LK_RELEASE, NULL, DRM_CURPROC)
 #define DRM_SUSER(td)          suser(td)
 #define DRM_TASKQUEUE_ARGS     void *arg, int pending
 #define DRM_IRQ_ARGS           void *arg
index dc88a13..3b729ed 100644 (file)
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/pccbb/pccbb.c,v 1.64 2002/11/23 23:09:45 imp Exp $
- * $DragonFly: src/sys/dev/pccard/pccbb/pccbb.c,v 1.1 2004/02/10 07:55:47 joerg Exp $
+ * $DragonFly: src/sys/dev/pccard/pccbb/pccbb.c,v 1.2 2004/03/01 06:33:14 dillon Exp $
  */
 
 /*
@@ -719,14 +719,14 @@ cbb_detach(device_t brdev)
        if (error > 0)
                return (ENXIO);
 
-       lockmgr(&sc->lock, LK_EXCLUSIVE, 0, curthread);
+       lockmgr(&sc->lock, LK_EXCLUSIVE, NULL, curthread);
        bus_teardown_intr(brdev, sc->irq_res, sc->intrhand);
        sc->flags |= CBB_KTHREAD_DONE;
        if (sc->flags & CBB_KTHREAD_RUNNING) {
                wakeup(sc);
                tsleep(sc, 0, "pccbb", 0);
        }
-       lockmgr(&sc->lock, LK_RELEASE, 0, curthread);
+       lockmgr(&sc->lock, LK_RELEASE, NULL, curthread);
 
        bus_release_resource(brdev, SYS_RES_IRQ, 0, sc->irq_res);
        if (sc->flags & CBB_KLUDGE_ALLOC)
@@ -894,7 +894,7 @@ cbb_event_thread(void *arg)
                 * if there's a card already inserted, we do the
                 * right thing.
                 */
-               lockmgr(&sc->lock, LK_EXCLUSIVE, 0, curthread);
+               lockmgr(&sc->lock, LK_EXCLUSIVE, NULL, curthread);
                if (sc->flags & CBB_KTHREAD_DONE)
                        break;
 
@@ -904,7 +904,7 @@ cbb_event_thread(void *arg)
                        cbb_insert(sc);
                else
                        cbb_removal(sc);
-               lockmgr(&sc->lock, LK_RELEASE, 0, curthread);
+               lockmgr(&sc->lock, LK_RELEASE, NULL, curthread);
                /* mtx_unlock(&Giant); */
 
                /*
@@ -917,7 +917,7 @@ cbb_event_thread(void *arg)
                    (sc->flags & CBB_KTHREAD_DONE) == 0)
                        err = tsleep(sc, 0, "pccbb", 1 * hz);
        }
-       lockmgr(&sc->lock, LK_RELEASE, 0, curthread);
+       lockmgr(&sc->lock, LK_RELEASE, NULL, curthread);
        sc->flags &= ~CBB_KTHREAD_RUNNING;
        /* mtx_lock(&Giant); */
        kthread_exit();
@@ -1019,9 +1019,9 @@ cbb_intr(void *arg)
                 * excellent results.
                 */
                if (sockevent & CBB_SOCKET_EVENT_CD) {
-                       lockmgr(&sc->lock, LK_EXCLUSIVE, 0, curthread);
+                       lockmgr(&sc->lock, LK_EXCLUSIVE, NULL, curthread);
                        sc->flags &= ~CBB_CARD_OK;
-                       lockmgr(&sc->lock, LK_RELEASE, 0, curthread);
+                       lockmgr(&sc->lock, LK_RELEASE, NULL, curthread);
                        wakeup(sc);
                }
                if (sockevent & CBB_SOCKET_EVENT_CSTS) {
index e75987b..38ebed3 100644 (file)
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  *     $FreeBSD: src/sys/dev/aac/aacvar.h,v 1.4.2.7 2003/04/08 13:22:08 scottl Exp $
- *     $DragonFly: src/sys/dev/raid/aac/aacvar.h,v 1.5 2004/02/13 01:33:19 joerg Exp $
+ *     $DragonFly: src/sys/dev/raid/aac/aacvar.h,v 1.6 2004/03/01 06:33:14 dillon Exp $
  */
 
 /*
@@ -259,10 +259,10 @@ typedef struct mtx aac_lock_t;
 #define AAC_LOCK_ACQUIRE(l)    mtx_lock(l)
 #define AAC_LOCK_RELEASE(l)    mtx_unlock(l)
 #else
-typedef struct lwkt_token aac_lock_t;
-#define AAC_LOCK_INIT(l, s)    lwkt_inittoken(l)
-#define AAC_LOCK_ACQUIRE(l)    lwkt_gettoken(l)
-#define AAC_LOCK_RELEASE(l)    lwkt_reltoken(l)
+typedef struct lwkt_rwlock aac_lock_t;
+#define AAC_LOCK_INIT(l, s)    lwkt_rwlock_init(l)
+#define AAC_LOCK_ACQUIRE(l)    lwkt_exlock(l, "aac")
+#define AAC_LOCK_RELEASE(l)    lwkt_exunlock(l)
 #endif
 
 #if defined(__FreeBSD__) && __FreeBSD_version >= 500005
index 710d83f..002f3e5 100644 (file)
@@ -37,7 +37,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/emulation/43bsd/43bsd_file.c,v 1.3 2003/11/11 09:28:15 daver Exp $
+ * $DragonFly: src/sys/emulation/43bsd/43bsd_file.c,v 1.4 2004/03/01 06:33:15 dillon Exp $
  *     from: DragonFly kern/vfs_syscalls.c,v 1.20
  *
  * These syscalls used to live in kern/vfs_syscalls.c.  They are modified
@@ -147,7 +147,7 @@ unionread:
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_td = td;
        auio.uio_resid = uap->count;
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        loff = auio.uio_offset = fp->f_offset;
 #      if (BYTE_ORDER != LITTLE_ENDIAN)
                if (vp->v_mount->mnt_maxsymlinklen <= 0) {
@@ -200,7 +200,7 @@ unionread:
                }
                FREE(dirbuf, M_TEMP);
        }
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        if (error)
                return (error);
        if (uap->count == auio.uio_resid) {
index ecd5884..4d824f6 100644 (file)
@@ -27,7 +27,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/ibcs2/imgact_coff.c,v 1.40 1999/12/15 23:01:47 eivind Exp $
- * $DragonFly: src/sys/emulation/ibcs2/coff/Attic/imgact_coff.c,v 1.9 2004/01/20 18:41:49 dillon Exp $
+ * $DragonFly: src/sys/emulation/ibcs2/coff/Attic/imgact_coff.c,v 1.10 2004/03/01 06:33:15 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -211,7 +211,7 @@ coff_load_file(struct thread *td, char *name)
         * Lose the lock on the vnode. It's no longer needed, and must not
         * exist for the pagefault paging to work below.
         */
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
 
        if ((error = vm_mmap(kernel_map,
                            (vm_offset_t *) &ptr,
@@ -284,7 +284,7 @@ coff_load_file(struct thread *td, char *name)
                panic(__FUNCTION__ " vm_map_remove failed");
 
  fail:
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
  unlocked_fail:
        NDFREE(&nd, NDF_ONLY_PNBUF);
        vrele(nd.ni_vp);
index 8b5d0d0..1b9cb59 100644 (file)
@@ -46,7 +46,7 @@
  *     @(#)sun_misc.c  8.1 (Berkeley) 6/18/93
  *
  * $FreeBSD: src/sys/i386/ibcs2/ibcs2_misc.c,v 1.34 1999/09/29 15:12:09 marcel Exp $
- * $DragonFly: src/sys/emulation/ibcs2/i386/Attic/ibcs2_misc.c,v 1.8 2003/08/20 07:13:25 dillon Exp $
+ * $DragonFly: src/sys/emulation/ibcs2/i386/Attic/ibcs2_misc.c,v 1.9 2004/03/01 06:33:15 dillon Exp $
  */
 
 /*
@@ -330,7 +330,7 @@ ibcs2_getdents(struct ibcs2_getdents_args *uap)
        buflen = max(DIRBLKSIZ, SCARG(uap, nbytes));
        buflen = min(buflen, MAXBSIZE);
        buf = malloc(buflen, M_TEMP, M_WAITOK);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 again:
        aiov.iov_base = buf;
        aiov.iov_len = buflen;
@@ -432,7 +432,7 @@ eof:
 out:
        if (cookies)
                free(cookies, M_TEMP);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        free(buf, M_TEMP);
        return (error);
 }
@@ -479,7 +479,7 @@ ibcs2_read(struct ibcs2_read_args *uap)
        buflen = max(DIRBLKSIZ, SCARG(uap, nbytes));
        buflen = min(buflen, MAXBSIZE);
        buf = malloc(buflen, M_TEMP, M_WAITOK);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 again:
        aiov.iov_base = buf;
        aiov.iov_len = buflen;
@@ -585,7 +585,7 @@ eof:
 out:
        if (cookies)
                free(cookies, M_TEMP);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        free(buf, M_TEMP);
        return (error);
 }
index 08bc74d..dcddd95 100644 (file)
@@ -39,7 +39,7 @@
  *     @(#)procfs_subr.c       8.6 (Berkeley) 5/14/95
  *
  * $FreeBSD: src/sys/i386/linux/linprocfs/linprocfs_subr.c,v 1.3.2.4 2001/06/25 19:46:47 pirzyk Exp $
- * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c,v 1.6 2003/08/27 06:30:04 rob Exp $
+ * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_subr.c,v 1.7 2004/03/01 06:33:15 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -99,7 +99,7 @@ loop:
                if (pfs->pfs_pid == pid &&
                    pfs->pfs_type == pfs_type &&
                    vp->v_mount == mp) {
-                       if (vget(vp, 0, td))
+                       if (vget(vp, NULL, 0, td))
                                goto loop;
                        *vpp = vp;
                        return (0);
index 0c3744f..e5947cf 100644 (file)
@@ -39,7 +39,7 @@
  *     @(#)procfs_vnops.c      8.18 (Berkeley) 5/21/95
  *
  * $FreeBSD: src/sys/i386/linux/linprocfs/linprocfs_vnops.c,v 1.3.2.5 2001/08/12 14:29:19 rwatson Exp $
- * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v 1.9 2003/09/23 05:03:51 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v 1.10 2004/03/01 06:33:15 dillon Exp $
  */
 
 /*
@@ -338,7 +338,7 @@ linprocfs_inactive(ap)
 {
        struct vnode *vp = ap->a_vp;
 
-       VOP_UNLOCK(vp, 0, ap->a_td);
+       VOP_UNLOCK(vp, NULL, 0, ap->a_td);
 
        return (0);
 }
@@ -669,7 +669,7 @@ linprocfs_lookup(ap)
        if (cnp->cn_namelen == 1 && *pname == '.') {
                *vpp = dvp;
                VREF(dvp);
-               /* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */
+               /* vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, curp); */
                return (0);
        }
 
index 8bf958f..82551c6 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/compat/linux/linux_file.c,v 1.41.2.6 2003/01/06 09:19:43 fjoe Exp $
- * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.15 2003/11/15 00:40:06 daver Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.16 2004/03/01 06:33:15 dillon Exp $
  */
 
 #include "opt_compat.h"
@@ -290,7 +290,7 @@ getdents_common(struct linux_getdents64_args *args, int is64bit)
        buflen = max(LINUX_DIRBLKSIZ, nbytes);
        buflen = min(buflen, MAXBSIZE);
        buf = malloc(buflen, M_TEMP, M_WAITOK);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 again:
        aiov.iov_base = buf;
@@ -429,7 +429,7 @@ out:
        if (cookies)
                free(cookies, M_TEMP);
 
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        free(buf, M_TEMP);
        return (error);
 }
index 081c379..102ed09 100644 (file)
@@ -1,5 +1,5 @@
 /* $FreeBSD: src/sys/compat/linux/linux_getcwd.c,v 1.2.2.3 2001/11/05 19:08:22 marcel Exp $ */
-/* $DragonFly: src/sys/emulation/linux/linux_getcwd.c,v 1.13 2003/10/09 22:27:08 dillon Exp $ */
+/* $DragonFly: src/sys/emulation/linux/linux_getcwd.c,v 1.14 2004/03/01 06:33:15 dillon Exp $ */
 /* $OpenBSD: linux_getcwd.c,v 1.2 2001/05/16 12:50:21 ho Exp $ */
 /* $NetBSD: vfs_getcwd.c,v 1.3.2.3 1999/07/11 10:24:09 sommerfeld Exp $ */
 
@@ -313,7 +313,7 @@ linux_getcwd_common (lvp, rvp, bpp, bufp, limit, flags, td)
         *      uvp is either NULL, or locked and held.
         */
 
-       error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td);
+       error = vn_lock(lvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        if (error) {
                vrele(lvp);
                lvp = NULL;
@@ -369,7 +369,7 @@ linux_getcwd_common (lvp, rvp, bpp, bufp, limit, flags, td)
                                goto out;
                        }
                        VREF(lvp);
-                       error = vn_lock(lvp, LK_EXCLUSIVE | LK_RETRY, td);
+                       error = vn_lock(lvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
                        if (error != 0) {
                                vrele(lvp);
                                lvp = NULL;
index 4aa7347..0df4d71 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/compat/linux/linux_misc.c,v 1.85.2.9 2002/09/24 08:11:41 mdodd Exp $
- * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.18 2004/01/07 10:54:57 dillon Exp $
+ * $DragonFly: src/sys/emulation/linux/linux_misc.c,v 1.19 2004/03/01 06:33:15 dillon Exp $
  */
 
 #include "opt_compat.h"
@@ -326,7 +326,7 @@ linux_uselib(struct linux_uselib_args *args)
        /*
         * Lock no longer needed
         */
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        locked = 0;
 
        /* Pull in executable header into kernel_map */
@@ -464,7 +464,7 @@ linux_uselib(struct linux_uselib_args *args)
 cleanup:
        /* Unlock vnode if needed */
        if (locked)
-               VOP_UNLOCK(vp, 0, td);
+               VOP_UNLOCK(vp, NULL, 0, td);
 
        /* Release the kernel mapping. */
        if (a_out)
index c9f32a4..04e6fd1 100644 (file)
@@ -26,7 +26,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * 
  * $FreeBSD: src/sys/svr4/svr4_misc.c,v 1.13.2.7 2003/01/14 21:33:58 dillon Exp $
- * $DragonFly: src/sys/emulation/svr4/Attic/svr4_misc.c,v 1.20 2004/02/12 23:33:26 joerg Exp $
+ * $DragonFly: src/sys/emulation/svr4/Attic/svr4_misc.c,v 1.21 2004/03/01 06:33:15 dillon Exp $
  */
 
 /*
@@ -286,7 +286,7 @@ svr4_sys_getdents64(struct svr4_sys_getdents64_args *uap)
        buflen = max(DIRBLKSIZ, nbytes);
        buflen = min(buflen, MAXBSIZE);
        buf = malloc(buflen, M_TEMP, M_WAITOK);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 again:
        aiov.iov_base = buf;
        aiov.iov_len = buflen;
@@ -400,7 +400,7 @@ eof:
 out:
        if (cookies)
                free(cookies, M_TEMP);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        free(buf, M_TEMP);
        return error;
 }
@@ -440,7 +440,7 @@ svr4_sys_getdents(struct svr4_sys_getdents_args *uap)
 
        buflen = min(MAXBSIZE, SCARG(uap, nbytes));
        buf = malloc(buflen, M_TEMP, M_WAITOK);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        off = fp->f_offset;
 again:
        aiov.iov_base = buf;
@@ -514,7 +514,7 @@ again:
 eof:
        *retval = SCARG(uap, nbytes) - resid;
 out:
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        if (cookiebuf)
                free(cookiebuf, M_TEMP);
        free(buf, M_TEMP);
@@ -609,12 +609,12 @@ svr4_sys_fchroot(struct svr4_sys_fchroot_args *uap)
        if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
                return error;
        vp = (struct vnode *) fp->f_data;
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        if (vp->v_type != VDIR)
                error = ENOTDIR;
        else
                error = VOP_ACCESS(vp, VEXEC, cred, td);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        if (error)
                return error;
        VREF(vp);
index 240024b..b7fd1e7 100644 (file)
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/mpapic.c,v 1.37.2.7 2003/01/25 02:31:47 peter Exp $
- * $DragonFly: src/sys/i386/apic/Attic/mpapic.c,v 1.7 2003/08/26 21:42:18 rob Exp $
+ * $DragonFly: src/sys/i386/apic/Attic/mpapic.c,v 1.8 2004/03/01 06:33:16 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -514,12 +514,13 @@ apic_ipi(int dest_type, int vector, int delivery_mode)
        return 0;
 }
 
-static int
-apic_ipi_singledest(int cpu, int vector, int delivery_mode)
+void
+single_apic_ipi(int cpu, int vector, int delivery_mode)
 {
        u_long  icr_lo;
        u_long  icr_hi;
 
+       crit_enter();
        if ((lapic.icr_lo & APIC_DELSTAT_MASK) != 0) {
            unsigned int eflags = read_eflags();
            cpu_enable_intr();
@@ -538,9 +539,44 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode)
 
        /* write APIC ICR */
        lapic.icr_lo = icr_lo;
-       return 0;
+       crit_exit();
 }
 
+#if 0  
+
+/*
+ * Returns 0 if the apic is busy, 1 if we were able to queue the request.
+ *
+ * NOT WORKING YET!  The code as-is may end up not queueing an IPI at all
+ * to the target, and the scheduler does not 'poll' for IPI messages.
+ */
+int
+single_apic_ipi_passive(int cpu, int vector, int delivery_mode)
+{
+       u_long  icr_lo;
+       u_long  icr_hi;
+
+       crit_enter();
+       if ((lapic.icr_lo & APIC_DELSTAT_MASK) != 0) {
+           crit_exit();
+           return(0);
+       }
+       icr_hi = lapic.icr_hi & ~APIC_ID_MASK;
+       icr_hi |= (CPU_TO_ID(cpu) << 24);
+       lapic.icr_hi = icr_hi;
+
+       /* build IRC_LOW */
+       icr_lo = (lapic.icr_lo & APIC_RESV2_MASK)
+           | APIC_DEST_DESTFLD | delivery_mode | vector;
+
+       /* write APIC ICR */
+       lapic.icr_lo = icr_lo;
+       crit_exit();
+       return(1);
+}
+
+#endif
+
 /*
  * Send APIC IPI 'vector' to 'target's via 'delivery_mode'.
  *
@@ -548,20 +584,16 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode)
  * valid system INT vector.  Delivery mode may be either
  * APIC_DELMODE_FIXED or APIC_DELMODE_LOWPRIO.
  */
-int
+void
 selected_apic_ipi(u_int target, int vector, int delivery_mode)
 {
-       int status = 0;
-
        crit_enter();
        while (target) {
                int n = bsfl(target);
                target &= ~(1 << n);
-               if (apic_ipi_singledest(n, vector, delivery_mode) < 0)
-                       status |= 1 << n;
+               single_apic_ipi(n, vector, delivery_mode);
        }
        crit_exit();
-       return(status);
 }
 
 #endif /* APIC_IO */
index 11a09c2..336cf4f 100644 (file)
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/mpapic.h,v 1.14.2.2 2000/09/30 02:49:34 ps Exp $
- * $DragonFly: src/sys/i386/apic/Attic/mpapic.h,v 1.6 2004/02/21 06:37:07 dillon Exp $
+ * $DragonFly: src/sys/i386/apic/Attic/mpapic.h,v 1.7 2004/03/01 06:33:16 dillon Exp $
  */
 
 #ifndef _MACHINE_MPAPIC_H_
@@ -63,18 +63,6 @@ enum busTypes {
 
 #ifdef SMP
 
-/*
- * send an IPI INTerrupt containing 'vector' to CPUs in 'targetMap'
- * 'targetMap' is a bitfiled of length 14,
- *   APIC #0 == bit 0, ..., APIC #14 == bit 14
- *   NOTE: these are LOGICAL APIC IDs
- */
-static __inline int
-selected_procs_ipi(int targetMap, int vector)
-{
-       return selected_apic_ipi(targetMap, vector, APIC_DELMODE_FIXED);
-}
-
 /*
  * send an IPI INTerrupt containing 'vector' to all CPUs EXCEPT myself
  */
index 5a7ea32..67483cb 100644 (file)
@@ -3,7 +3,7 @@
 #      as much of the source tree as it can.
 #
 # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $
-# $DragonFly: src/sys/i386/conf/Attic/LINT,v 1.23 2004/02/27 11:56:12 joerg Exp $
+# $DragonFly: src/sys/i386/conf/Attic/LINT,v 1.24 2004/03/01 06:33:16 dillon Exp $
 #
 # NB: You probably don't want to try running a kernel built from this
 # file.  Instead, you should start from GENERIC, and add options from
@@ -2684,8 +2684,6 @@ device            ubsec           # Broadcom 5501, 5601, 58xx
 options                UBSEC_DEBUG     # enable debugging support: hw.ubsec.debug
 options                UBSEC_RNDTEST   # enable rndtest support
 
-device         acpica          # basic ACPI support
-
 # DRM options:
 # mgadrm:    AGP Matrox G200, G400, G450, G550
 # tdfxdrm:   3dfx Voodoo 3/4/5 and Banshee
index 5e9400c..a188c2d 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.54 2004/02/17 19:38:53 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/machdep.c,v 1.55 2004/03/01 06:33:16 dillon Exp $
  */
 
 #include "use_apm.h"
@@ -2648,6 +2648,7 @@ init_locks(void)
 #ifdef SMP
        cpu_get_initial_mplock();
 #endif
+       /* DEPRECATED */
        spin_lock_init(&mcount_spinlock);
        spin_lock_init(&fast_intr_spinlock);
        spin_lock_init(&intr_spinlock);
@@ -2657,5 +2658,8 @@ init_locks(void)
        spin_lock_init(&com_spinlock);
        spin_lock_init(&clock_spinlock);
        spin_lock_init(&cons_spinlock);
+
+       /* our token pool needs to work early */
+       lwkt_token_pool_init();
 }
 
index 1fd097d..3677e42 100644 (file)
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/mp_machdep.c,v 1.115.2.15 2003/03/14 21:22:35 jhb Exp $
- * $DragonFly: src/sys/i386/i386/Attic/mp_machdep.c,v 1.23 2004/02/21 06:37:07 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/mp_machdep.c,v 1.24 2004/03/01 06:33:16 dillon Exp $
  */
 
 #include "opt_cpu.h"
@@ -280,7 +280,7 @@ struct pcb stoppcbs[MAXCPU];
 static int     mp_capable;
 static u_int   boot_address;
 static u_int   base_memory;
-static cpumask_t smp_startup_mask = 1; /* which cpus have been started */
+static int     mp_finish;
 
 static int     picmode;                /* 0: virtual wire mode, 1: PIC mode */
 static mpfps_t mpfps;
@@ -298,6 +298,7 @@ static void install_ap_tramp(u_int boot_addr);
 static int     start_ap(struct mdglobaldata *gd, u_int boot_addr);
 static int     apic_int_is_bus_type(int intr, int bus_type);
 
+static cpumask_t smp_startup_mask = 1; /* which cpus have been started */
 cpumask_t smp_active_mask = 1; /* which cpus are ready for IPIs etc? */
 SYSCTL_INT(_machdep, OID_AUTO, smp_active, CTLFLAG_RD, &smp_active_mask, 0, "");
 
@@ -2313,7 +2314,6 @@ restart_cpus(u_int map)
  * loop for the idlethread.  Interrupts are disabled on entry and should
  * remain disabled at return.
  */
-
 void
 ap_init(void)
 {
@@ -2332,17 +2332,27 @@ ap_init(void)
        cpu_mb1();
 
        /*
-        * Get the MP lock so we can finish initializing.  Note: we are
-        * in a critical section.  td_mpcount must always be bumped prior
-        * to obtaining the actual lock.
+        * Interlock for finalization.  Wait until mp_finish is non-zero,
+        * then get the MP lock.
+        *
+        * Note: We are in a critical section.
+        *
+        * Note: We have to synchronize td_mpcount to our desired MP state
+        * before calling cpu_try_mplock().
+        *
+        * Note: we are the idle thread, we can only spin.
+        *
+        * Note: cpu_mb1() is memory volatile and prevents mp_finish from
+        *       being cached.
         */
        ++curthread->td_mpcount;
+       while (mp_finish == 0)
+           cpu_mb1();
        while (cpu_try_mplock() == 0)
            ;
 
        /* BSP may have changed PTD while we're waiting for the lock */
        cpu_invltlb();
-       smp_active_mask |= 1 << mycpu->gd_cpuid;
 
 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
        lidt(&r_idt);
@@ -2377,27 +2387,43 @@ ap_init(void)
        /* Set memory range attributes for this CPU to match the BSP */
        mem_range_AP_init();
 
-       /*
-        * AP helper function for kernel memory support.  This will create
-        * a memory reserve for the AP that is necessary to avoid certain
-        * memory deadlock situations, such as when the kernel_map needs
-        * a vm_map_entry and zalloc has no free entries and tries to allocate
-        * a new one from the ... kernel_map :-)
-        */
-       kmem_cpu_init();
-
-       sched_thread_init();    /* startup helper thread(s) one per cpu */
        initclocks_pcpu();      /* clock interrupts (via IPIs) */
 
        /*
         * The idle loop doesn't expect the BGL to be held and while
         * lwkt_switch() normally cleans things up this is a special case
         * because we returning almost directly into the idle loop.
+        *
+        * The idle thread is never placed on the runq, make sure
+        * nothing we've done put it thre.
         */
        KKASSERT(curthread->td_mpcount == 1);
+       smp_active_mask |= 1 << mycpu->gd_cpuid;
        rel_mplock();
+       KKASSERT((curthread->td_flags & TDF_RUNQ) == 0);
 }
 
+/*
+ * Get SMP fully working before we start initializing devices.
+ */
+static
+void
+ap_finish(void)
+{
+       mp_finish = 1;
+       if (bootverbose)
+               printf("Finish MP startup");
+       rel_mplock();
+       while (smp_active_mask != smp_startup_mask)
+               cpu_mb1();
+       while (cpu_try_mplock() == 0)
+               ;
+       if (bootverbose)
+               printf("Active CPU Mask: %08x\n", smp_active_mask);
+}
+
+SYSINIT(finishsmp, SI_SUB_FINISH_SMP, SI_ORDER_FIRST, ap_finish, NULL)
+
 #ifdef APIC_INTR_REORDER
 /*
  *     Maintain mapping from softintr vector to isr bit in local apic.
@@ -2492,6 +2518,23 @@ smp_rendezvous(void (* setup_func)(void *),
 void
 cpu_send_ipiq(int dcpu)
 {
-       if ((1 << dcpu) & smp_active_mask)
-               selected_apic_ipi(1 << dcpu, XIPIQ_OFFSET, APIC_DELMODE_FIXED);
+        if ((1 << dcpu) & smp_active_mask)
+                single_apic_ipi(dcpu, XIPIQ_OFFSET, APIC_DELMODE_FIXED);
 }
+
+#if 0  /* single_apic_ipi_passive() not working yet */
+/*
+ * Returns 0 on failure, 1 on success
+ */
+int
+cpu_send_ipiq_passive(int dcpu)
+{
+        int r = 0;
+        if ((1 << dcpu) & smp_active_mask) {
+                r = single_apic_ipi_passive(dcpu, XIPIQ_OFFSET,
+                                        APIC_DELMODE_FIXED);
+        }
+       return(r);
+}
+#endif
+
index 0a8d9bc..7b5e6c9 100644 (file)
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/mpapic.c,v 1.37.2.7 2003/01/25 02:31:47 peter Exp $
- * $DragonFly: src/sys/i386/i386/Attic/mpapic.c,v 1.7 2003/08/26 21:42:18 rob Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/mpapic.c,v 1.8 2004/03/01 06:33:16 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -514,12 +514,13 @@ apic_ipi(int dest_type, int vector, int delivery_mode)
        return 0;
 }
 
-static int
-apic_ipi_singledest(int cpu, int vector, int delivery_mode)
+void
+single_apic_ipi(int cpu, int vector, int delivery_mode)
 {
        u_long  icr_lo;
        u_long  icr_hi;
 
+       crit_enter();
        if ((lapic.icr_lo & APIC_DELSTAT_MASK) != 0) {
            unsigned int eflags = read_eflags();
            cpu_enable_intr();
@@ -538,9 +539,44 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode)
 
        /* write APIC ICR */
        lapic.icr_lo = icr_lo;
-       return 0;
+       crit_exit();
 }
 
+#if 0  
+
+/*
+ * Returns 0 if the apic is busy, 1 if we were able to queue the request.
+ *
+ * NOT WORKING YET!  The code as-is may end up not queueing an IPI at all
+ * to the target, and the scheduler does not 'poll' for IPI messages.
+ */
+int
+single_apic_ipi_passive(int cpu, int vector, int delivery_mode)
+{
+       u_long  icr_lo;
+       u_long  icr_hi;
+
+       crit_enter();
+       if ((lapic.icr_lo & APIC_DELSTAT_MASK) != 0) {
+           crit_exit();
+           return(0);
+       }
+       icr_hi = lapic.icr_hi & ~APIC_ID_MASK;
+       icr_hi |= (CPU_TO_ID(cpu) << 24);
+       lapic.icr_hi = icr_hi;
+
+       /* build IRC_LOW */
+       icr_lo = (lapic.icr_lo & APIC_RESV2_MASK)
+           | APIC_DEST_DESTFLD | delivery_mode | vector;
+
+       /* write APIC ICR */
+       lapic.icr_lo = icr_lo;
+       crit_exit();
+       return(1);
+}
+
+#endif
+
 /*
  * Send APIC IPI 'vector' to 'target's via 'delivery_mode'.
  *
@@ -548,20 +584,16 @@ apic_ipi_singledest(int cpu, int vector, int delivery_mode)
  * valid system INT vector.  Delivery mode may be either
  * APIC_DELMODE_FIXED or APIC_DELMODE_LOWPRIO.
  */
-int
+void
 selected_apic_ipi(u_int target, int vector, int delivery_mode)
 {
-       int status = 0;
-
        crit_enter();
        while (target) {
                int n = bsfl(target);
                target &= ~(1 << n);
-               if (apic_ipi_singledest(n, vector, delivery_mode) < 0)
-                       status |= 1 << n;
+               single_apic_ipi(n, vector, delivery_mode);
        }
        crit_exit();
-       return(status);
 }
 
 #endif /* APIC_IO */
index 697d9b3..ae1c770 100644 (file)
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/i386/nexus.c,v 1.26.2.10 2003/02/22 13:16:45 imp Exp $
- * $DragonFly: src/sys/i386/i386/Attic/nexus.c,v 1.9 2004/02/23 21:23:42 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/nexus.c,v 1.10 2004/03/01 06:33:16 dillon Exp $
  */
 
 /*
@@ -82,6 +82,7 @@ struct nexus_device {
 
 static struct rman irq_rman, drq_rman, port_rman, mem_rman;
 
+static void nexus_identify(driver_t *, device_t);
 static int nexus_probe(device_t);
 static int nexus_attach(device_t);
 static int nexus_print_all_resources(device_t dev);
@@ -108,6 +109,7 @@ static void nexus_delete_resource(device_t, device_t, int, int);
 
 static device_method_t nexus_methods[] = {
        /* Device interface */
+       DEVMETHOD(device_identify,      nexus_identify),
        DEVMETHOD(device_probe,         nexus_probe),
        DEVMETHOD(device_attach,        nexus_attach),
        DEVMETHOD(device_detach,        bus_generic_detach),
@@ -142,9 +144,32 @@ static devclass_t nexus_devclass;
 
 DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
 
+static void
+nexus_identify(driver_t *driver, device_t parent)
+{
+        /*
+         * Add child device with order of 1 so it gets probed
+         * after ACPI (which is at order 0.
+         */
+        if (BUS_ADD_CHILD(parent, 1, "legacy", 0) == NULL)
+                panic("legacy: could not attach");
+}
+
 static int
 nexus_probe(device_t dev)
 {
+#if 0  /* FUTURE */
+       device_t acpi;
+#endif
+
+#if 0  /* FUTURE */
+       /*
+        * Fail to probe if ACPI is ok.
+        */
+       acpi = devclass_get_device(devclass_find("acpi"), 0);
+       if (acpi != NULL && device_is_alive(acpi))
+               return(ENXIO);
+#endif
 
        device_quiet(dev);      /* suppress attach message for neatness */
 
@@ -229,9 +254,15 @@ nexus_attach(device_t dev)
        device_t        child;
 
        /*
-        * First, deal with the children we know about already
+        * First, let our child driver's identify any child devices that
+        * they can find.  Once that is done attach any devices that we
+        * found.
         */
+#if 0 /* FUTURE */
+       bus_generic_probe(dev);
+#endif
        bus_generic_attach(dev);
+
        /*
         * And if we didn't see EISA or ISA on a pci bridge, create some
         * connection points now so they show up "on motherboard".
index 4341fea..367cb49 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.31 2004/02/21 06:37:07 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/pmap.c,v 1.32 2004/03/01 06:33:16 dillon Exp $
  */
 
 /*
@@ -1535,7 +1535,7 @@ pmap_remove_pte(struct pmap *pmap, unsigned *ptq, vm_offset_t va,
         * the SMP case.
         */
        if (oldpte & PG_G)
-               cpu_invlpg(va);
+               cpu_invlpg((void *)va);
        pmap->pm_stats.resident_count -= 1;
        if (oldpte & PG_MANAGED) {
                m = PHYS_TO_VM_PAGE(oldpte);
index 2745c0c..8ffac14 100644 (file)
@@ -23,7 +23,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/mpapic.h,v 1.14.2.2 2000/09/30 02:49:34 ps Exp $
- * $DragonFly: src/sys/i386/include/Attic/mpapic.h,v 1.6 2004/02/21 06:37:07 dillon Exp $
+ * $DragonFly: src/sys/i386/include/Attic/mpapic.h,v 1.7 2004/03/01 06:33:16 dillon Exp $
  */
 
 #ifndef _MACHINE_MPAPIC_H_
@@ -63,18 +63,6 @@ enum busTypes {
 
 #ifdef SMP
 
-/*
- * send an IPI INTerrupt containing 'vector' to CPUs in 'targetMap'
- * 'targetMap' is a bitfiled of length 14,
- *   APIC #0 == bit 0, ..., APIC #14 == bit 14
- *   NOTE: these are LOGICAL APIC IDs
- */
-static __inline int
-selected_procs_ipi(int targetMap, int vector)
-{
-       return selected_apic_ipi(targetMap, vector, APIC_DELMODE_FIXED);
-}
-
 /*
  * send an IPI INTerrupt containing 'vector' to all CPUs EXCEPT myself
  */
index e473aa0..8f835ad 100644 (file)
@@ -7,7 +7,7 @@
  * ----------------------------------------------------------------------------
  *
  * $FreeBSD: src/sys/i386/include/smp.h,v 1.50.2.5 2001/02/13 22:32:45 tegge Exp $
- * $DragonFly: src/sys/i386/include/Attic/smp.h,v 1.10 2004/02/21 06:37:07 dillon Exp $
+ * $DragonFly: src/sys/i386/include/Attic/smp.h,v 1.11 2004/03/01 06:33:16 dillon Exp $
  *
  */
 
@@ -128,7 +128,9 @@ void        apic_dump               (char*);
 void   apic_initialize         (void);
 void   imen_dump               (void);
 int    apic_ipi                (int, int, int);
-int    selected_apic_ipi       (u_int, int, int);
+void   selected_apic_ipi       (u_int, int, int);
+void   single_apic_ipi(int cpu, int vector, int delivery_mode);
+int    single_apic_ipi_passive(int cpu, int vector, int delivery_mode);
 int    io_apic_setup           (int);
 void   io_apic_setup_intpin    (int, int);
 void   io_apic_set_id          (int, int);
@@ -144,6 +146,7 @@ void        set_apic_timer          (int);
 int    read_apic_timer         (void);
 void   u_sleep                 (int);
 void   cpu_send_ipiq           (int);
+int    cpu_send_ipiq_passive   (int);
 
 /* global data in init_smp.c */
 extern cpumask_t               smp_active_mask;
index 05e6f15..a5352c4 100644 (file)
@@ -27,7 +27,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/imgact_elf.c,v 1.73.2.13 2002/12/28 19:49:41 dillon Exp $
- * $DragonFly: src/sys/kern/imgact_elf.c,v 1.16 2004/01/20 18:41:51 dillon Exp $
+ * $DragonFly: src/sys/kern/imgact_elf.c,v 1.17 2004/03/01 06:33:16 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -387,7 +387,7 @@ elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
         */
        error = exec_check_permissions(imgp);
        if (error) {
-               VOP_UNLOCK(nd->ni_vp, 0, td);
+               VOP_UNLOCK(nd->ni_vp, NULL, 0, td);
                goto fail;
        }
 
@@ -398,7 +398,7 @@ elf_load_file(struct proc *p, const char *file, u_long *addr, u_long *entry)
         */
        if (error == 0)
                nd->ni_vp->v_flag |= VTEXT;
-       VOP_UNLOCK(nd->ni_vp, 0, td);
+       VOP_UNLOCK(nd->ni_vp, NULL, 0, td);
        if (error)
                 goto fail;
 
@@ -492,6 +492,7 @@ exec_elf_imgact(struct image_params *imgp)
        const char *interp = NULL;
        Elf_Brandinfo *brand_info;
        char *path;
+       lwkt_tokref ilock;
 
        error = 0;
 
@@ -525,9 +526,9 @@ exec_elf_imgact(struct image_params *imgp)
         * a context switch.  Better safe than sorry; I really don't want
         * the file to change while it's being loaded.
         */
-       lwkt_gettoken(&imgp->vp->v_interlock);
+       lwkt_gettoken(&ilock, imgp->vp->v_interlock);
        imgp->vp->v_flag |= VTEXT;
-       lwkt_reltoken(&imgp->vp->v_interlock);
+       lwkt_reltoken(&ilock);
 
        vmspace = imgp->proc->p_vmspace;
 
@@ -815,7 +816,7 @@ elf_coredump(struct proc *p, struct vnode *vp, off_t limit)
        fp->f_flag = O_CREAT|O_WRONLY|O_NOFOLLOW;
        fp->f_ops = &vnops;
        fp->f_type = DTYPE_VNODE;
-       VOP_UNLOCK(vp, 0, p->p_thread);
+       VOP_UNLOCK(vp, NULL, 0, p->p_thread);
        
        error = generic_elf_coredump(p, fp, limit);
 
index c1f884c..29f7579 100644 (file)
@@ -40,7 +40,7 @@
  *
  *     @(#)init_main.c 8.9 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/kern/init_main.c,v 1.134.2.8 2003/06/06 20:21:32 tegge Exp $
- * $DragonFly: src/sys/kern/init_main.c,v 1.27 2004/01/30 05:42:17 dillon Exp $
+ * $DragonFly: src/sys/kern/init_main.c,v 1.28 2004/03/01 06:33:16 dillon Exp $
  */
 
 #include "opt_init_path.h"
@@ -465,7 +465,7 @@ start_init(void *dummy)
        p->p_fd->fd_rdir = rootvnode;
        VREF(p->p_fd->fd_rdir);
        vfs_cache_setroot(rootvnode);
-       VOP_UNLOCK(rootvnode, 0, curthread);
+       VOP_UNLOCK(rootvnode, NULL, 0, curthread);
 
        /*
         * Need just enough stack to hold the faked-up "execve()" arguments.
@@ -613,6 +613,7 @@ mi_gdinit(struct globaldata *gd, int cpuid)
        TAILQ_INIT(&gd->gd_systimerq);
        gd->gd_cpuid = cpuid;
        lwkt_gdinit(gd);
+       vm_map_entry_reserve_cpu_init(gd);
 }
 
 
index f0ae149..40453b8 100644 (file)
@@ -38,7 +38,7 @@
  *
  *     @(#)kern_acct.c 8.1 (Berkeley) 6/14/93
  * $FreeBSD: src/sys/kern/kern_acct.c,v 1.23.2.1 2002/07/24 18:33:55 johan Exp $
- * $DragonFly: src/sys/kern/kern_acct.c,v 1.8 2003/09/29 18:52:06 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_acct.c,v 1.9 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -136,7 +136,7 @@ acct(uap)
                if (error)
                        return (error);
                NDFREE(&nd, NDF_ONLY_PNBUF);
-               VOP_UNLOCK(nd.ni_vp, 0, td);
+               VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
                if (nd.ni_vp->v_type != VREG) {
                        vn_close(nd.ni_vp, FWRITE | O_APPEND, td);
                        return (EACCES);
index 3e97090..9a73fd1 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_acl.c,v 1.2.2.1 2000/07/28 18:48:16 rwatson Exp $
- * $DragonFly: src/sys/kern/kern_acl.c,v 1.5 2003/09/23 05:03:51 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_acl.c,v 1.6 2004/03/01 06:33:17 dillon Exp $
  */
 
 /*
@@ -80,9 +80,9 @@ vacl_set_acl(struct vnode *vp, acl_type_t type, struct acl *aclp)
        ucred = td->td_proc->p_ucred;
 
        VOP_LEASE(vp, td, ucred, LEASE_WRITE);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        error = VOP_SETACL(vp, type, &inkernacl, ucred, td);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return(error);
 }
 
@@ -118,9 +118,9 @@ vacl_delete(struct vnode *vp, acl_type_t type)
        KKASSERT(td->td_proc);
        ucred = td->td_proc->p_ucred;
        VOP_LEASE(vp, td, ucred, LEASE_WRITE);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        error = VOP_SETACL(vp, ACL_TYPE_DEFAULT, 0, ucred, td);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return (error);
 }
 
index c672911..4a00423 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_descrip.c      8.6 (Berkeley) 4/19/94
  * $FreeBSD: src/sys/kern/kern_descrip.c,v 1.81.2.17 2003/06/06 20:21:32 tegge Exp $
- * $DragonFly: src/sys/kern/kern_descrip.c,v 1.18 2004/01/17 21:23:38 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_descrip.c,v 1.19 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include "opt_compat.h"
@@ -1353,7 +1353,7 @@ fdcheckstd(struct proc *p)
                        fp->f_flag = flags;
                        fp->f_ops = &vnops;
                        fp->f_type = DTYPE_VNODE;
-                       VOP_UNLOCK(nd.ni_vp, 0, td);
+                       VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
                        devnull = fd;
                } else {
                        error = kern_dup(DUP_FIXED, devnull, i, &retval);
index 3c33c9b..1d44828 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_exec.c,v 1.107.2.15 2002/07/30 15:40:46 nectar Exp $
- * $DragonFly: src/sys/kern/kern_exec.c,v 1.19 2004/01/20 18:41:51 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_exec.c,v 1.20 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -186,12 +186,12 @@ interpret:
         */
        error = exec_check_permissions(imgp);
        if (error) {
-               VOP_UNLOCK(imgp->vp, 0, td);
+               VOP_UNLOCK(imgp->vp, NULL, 0, td);
                goto exec_fail_dealloc;
        }
 
        error = exec_map_first_page(imgp);
-       VOP_UNLOCK(imgp->vp, 0, td);
+       VOP_UNLOCK(imgp->vp, NULL, 0, td);
        if (error)
                goto exec_fail_dealloc;
 
index fa702f3..5161356 100644 (file)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/kern_fp.c,v 1.4 2003/10/19 23:23:26 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_fp.c,v 1.5 2004/03/01 06:33:17 dillon Exp $
  */
 
 /*
@@ -105,7 +105,7 @@ fp_open(const char *path, int flags, int mode, file_t *fpp)
        fp->f_flag = flags;
        fp->f_ops = &vnops;
        fp->f_type = DTYPE_VNODE;
-       VOP_UNLOCK(nd.ni_vp, 0, td);
+       VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
     } else {
        fdrop(fp, td);
        *fpp = NULL;
@@ -191,7 +191,7 @@ fp_vpopen(struct vnode *vp, int flags, file_t *fpp)
     if (flags & FWRITE)
        vp->v_writecount++;
 done:
-    VOP_UNLOCK(vp, 0, td);
+    VOP_UNLOCK(vp, NULL, 0, td);
     return (error);
 }
 
index 39a6d71..f8138b9 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)kern_ktrace.c       8.2 (Berkeley) 9/23/93
  * $FreeBSD: src/sys/kern/kern_ktrace.c,v 1.35.2.6 2002/07/05 22:36:38 darrenr Exp $
- * $DragonFly: src/sys/kern/kern_ktrace.c,v 1.12 2004/02/14 12:14:30 eirikn Exp $
+ * $DragonFly: src/sys/kern/kern_ktrace.c,v 1.13 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include "opt_ktrace.h"
@@ -268,7 +268,7 @@ ktrace(struct ktrace_args *uap)
                }
                NDFREE(&nd, NDF_ONLY_PNBUF);
                vp = nd.ni_vp;
-               VOP_UNLOCK(vp, 0, td);
+               VOP_UNLOCK(vp, NULL, 0, td);
                if (vp->v_type != VREG) {
                        (void) vn_close(vp, FREAD|FWRITE, td);
                        curp->p_traceflag &= ~KTRFAC_ACTIVE;
@@ -487,14 +487,14 @@ ktrwrite(struct vnode *vp, struct ktr_header *kth, struct uio *uio)
                if (uio != NULL)
                        kth->ktr_len += uio->uio_resid;
        }
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        (void)VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
        error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, p->p_ucred);
        if (error == 0 && uio != NULL) {
                (void)VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
                error = VOP_WRITE(vp, uio, IO_UNIT | IO_APPEND, p->p_ucred);
        }
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        if (!error)
                return;
        /*
index a8c5de0..25b2d0b 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_linker.c,v 1.41.2.3 2001/11/21 17:50:35 luigi Exp $
- * $DragonFly: src/sys/kern/kern_linker.c,v 1.17 2004/01/17 03:24:50 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_linker.c,v 1.18 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include "opt_ddb.h"
@@ -326,14 +326,14 @@ linker_find_file_by_name(const char* filename)
        goto out;
     sprintf(koname, "%s.ko", filename);
 
-    lockmgr(&lock, LK_SHARED, 0, curthread);
+    lockmgr(&lock, LK_SHARED, NULL, curthread);
     for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link)) {
        if (!strcmp(lf->filename, koname))
            break;
        if (!strcmp(lf->filename, filename))
            break;
     }
-    lockmgr(&lock, LK_RELEASE, 0, curthread);
+    lockmgr(&lock, LK_RELEASE, NULL, curthread);
 
 out:
     if (koname)
@@ -346,11 +346,11 @@ linker_find_file_by_id(int fileid)
 {
     linker_file_t lf = 0;
 
-    lockmgr(&lock, LK_SHARED, 0, curthread);
+    lockmgr(&lock, LK_SHARED, NULL, curthread);
     for (lf = TAILQ_FIRST(&linker_files); lf; lf = TAILQ_NEXT(lf, link))
        if (lf->id == fileid)
            break;
-    lockmgr(&lock, LK_RELEASE, 0, curthread);
+    lockmgr(&lock, LK_RELEASE, NULL, curthread);
 
     return lf;
 }
@@ -369,7 +369,7 @@ linker_make_file(const char* pathname, void* priv, struct linker_file_ops* ops)
        filename = pathname;
 
     KLD_DPF(FILE, ("linker_make_file: new file, filename=%s\n", filename));
-    lockmgr(&lock, LK_EXCLUSIVE, 0, curthread);
+    lockmgr(&lock, LK_EXCLUSIVE, NULL, curthread);
     namelen = strlen(filename) + 1;
     lf = malloc(sizeof(struct linker_file) + namelen, M_LINKER, M_WAITOK);
     if (!lf)
@@ -392,7 +392,7 @@ linker_make_file(const char* pathname, void* priv, struct linker_file_ops* ops)
     TAILQ_INSERT_TAIL(&linker_files, lf, link);
 
 out:
-    lockmgr(&lock, LK_RELEASE, 0, curthread);
+    lockmgr(&lock, LK_RELEASE, NULL, curthread);
     return lf;
 }
 
@@ -409,7 +409,7 @@ linker_file_unload(linker_file_t file)
        return EPERM; 
 
     KLD_DPF(FILE, ("linker_file_unload: lf->refs=%d\n", file->refs));
-    lockmgr(&lock, LK_EXCLUSIVE, 0, curthread);
+    lockmgr(&lock, LK_EXCLUSIVE, NULL, curthread);
     if (file->refs == 1) {
        KLD_DPF(FILE, ("linker_file_unload: file is unloading, informing modules\n"));
        /*
@@ -430,7 +430,7 @@ linker_file_unload(linker_file_t file)
            if ((error = module_unload(mod)) != 0) {
                KLD_DPF(FILE, ("linker_file_unload: module %x vetoes unload\n",
                               mod));
-               lockmgr(&lock, LK_RELEASE, 0, curthread);
+               lockmgr(&lock, LK_RELEASE, NULL, curthread);
                goto out;
            }
 
@@ -459,7 +459,7 @@ linker_file_unload(linker_file_t file)
 
     file->refs--;
     if (file->refs > 0) {
-       lockmgr(&lock, LK_RELEASE, 0, curthread);
+       lockmgr(&lock, LK_RELEASE, NULL, curthread);
        goto out;
     }
 
@@ -470,7 +470,7 @@ linker_file_unload(linker_file_t file)
     }
 
     TAILQ_REMOVE(&linker_files, file, link);
-    lockmgr(&lock, LK_RELEASE, 0, curthread);
+    lockmgr(&lock, LK_RELEASE, NULL, curthread);
 
     for (i = 0; i < file->ndeps; i++)
        linker_file_unload(file->deps[i]);
@@ -1129,7 +1129,7 @@ linker_search_path(const char *name)
        if (error == 0) {
            NDFREE(&nd, NDF_ONLY_PNBUF);
            type = nd.ni_vp->v_type;
-           VOP_UNLOCK(nd.ni_vp, 0, td);
+           VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
            vn_close(nd.ni_vp, FREAD, td);
            if (type == VREG)
                return(result);
index 02db658..6ff5f13 100644 (file)
@@ -39,7 +39,7 @@
  *
  *     @(#)kern_lock.c 8.18 (Berkeley) 5/21/95
  * $FreeBSD: src/sys/kern/kern_lock.c,v 1.31.2.3 2001/12/25 01:44:44 dillon Exp $
- * $DragonFly: src/sys/kern/kern_lock.c,v 1.9 2003/11/12 22:08:02 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_lock.c,v 1.10 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include "opt_lint.h"
@@ -123,10 +123,9 @@ acquire(struct lock *lkp, int extflags, int wanted)
        while ((lkp->lk_flags & wanted) != 0) {
                lkp->lk_flags |= LK_WAIT_NONZERO;
                lkp->lk_waitcount++;
-               lwkt_reltoken(&lkp->lk_interlock);
+               /* note: serialization lock is held through tsleep */
                error = tsleep(lkp, lkp->lk_prio, lkp->lk_wmesg, 
                            ((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0));
-               lwkt_gettoken(&lkp->lk_interlock);
                if (lkp->lk_waitcount == 1) {
                        lkp->lk_flags &= ~LK_WAIT_NONZERO;
                        lkp->lk_waitcount = 0;
@@ -155,15 +154,16 @@ acquire(struct lock *lkp, int extflags, int wanted)
  */
 int
 #ifndef        DEBUG_LOCKS
-lockmgr(struct lock *lkp, u_int flags, struct lwkt_token *interlkp,
+lockmgr(struct lock *lkp, u_int flags, lwkt_tokref_t interlkp,
        struct thread *td)
 #else
-debuglockmgr(struct lock *lkp, u_int flags, struct lwkt_token *interlkp,
+debuglockmgr(struct lock *lkp, u_int flags, lwkt_tokref_t interlkp,
        struct thread *td, const char *name, const char *file, int line)
 #endif
 {
        int error;
        int extflags;
+       lwkt_tokref ilock;
        static int didpanic;
 
        error = 0;
@@ -198,7 +198,7 @@ debuglockmgr(struct lock *lkp, u_int flags, struct lwkt_token *interlkp,
 #endif
        }
 
-       lwkt_gettoken(&lkp->lk_interlock);
+       lwkt_gettoken(&ilock, &lkp->lk_interlock);
        if (flags & LK_INTERLOCK)
                lwkt_reltoken(interlkp);
 
@@ -427,7 +427,7 @@ debuglockmgr(struct lock *lkp, u_int flags, struct lwkt_token *interlkp,
                break;
 
        default:
-               lwkt_reltoken(&lkp->lk_interlock);
+               lwkt_reltoken(&ilock);
                panic("lockmgr: unknown locktype request %d",
                    flags & LK_TYPE_MASK);
                /* NOTREACHED */
@@ -438,7 +438,7 @@ debuglockmgr(struct lock *lkp, u_int flags, struct lwkt_token *interlkp,
                lkp->lk_flags &= ~LK_WAITDRAIN;
                wakeup((void *)&lkp->lk_flags);
        }
-       lwkt_reltoken(&lkp->lk_interlock);
+       lwkt_reltoken(&ilock);
        return (error);
 }
 
@@ -456,11 +456,10 @@ acquiredrain(struct lock *lkp, int extflags)
 
        while (lkp->lk_flags & LK_ALL) {
                lkp->lk_flags |= LK_WAITDRAIN;
-               lwkt_reltoken(&lkp->lk_interlock);
+               /* interlock serialization held through tsleep */
                error = tsleep(&lkp->lk_flags, lkp->lk_prio,
                        lkp->lk_wmesg, 
                        ((extflags & LK_TIMELOCK) ? lkp->lk_timo : 0));
-               lwkt_gettoken(&lkp->lk_interlock);
                if (error)
                        return error;
                if (extflags & LK_SLEEPFAIL) {
@@ -481,7 +480,7 @@ lockinit(lkp, prio, wmesg, timo, flags)
        int timo;
        int flags;
 {
-       lwkt_inittoken(&lkp->lk_interlock);
+       lwkt_token_init(&lkp->lk_interlock);
        lkp->lk_flags = (flags & LK_EXTFLG_MASK);
        lkp->lk_sharecount = 0;
        lkp->lk_waitcount = 0;
@@ -498,9 +497,10 @@ lockinit(lkp, prio, wmesg, timo, flags)
 int
 lockstatus(struct lock *lkp, struct thread *td)
 {
+       lwkt_tokref ilock;
        int lock_type = 0;
 
-       lwkt_gettoken(&lkp->lk_interlock);
+       lwkt_gettoken(&ilock, &lkp->lk_interlock);
        if (lkp->lk_exclusivecount != 0) {
                if (td == NULL || lkp->lk_lockholder == td)
                        lock_type = LK_EXCLUSIVE;
@@ -509,7 +509,7 @@ lockstatus(struct lock *lkp, struct thread *td)
        } else if (lkp->lk_sharecount != 0) {
                lock_type = LK_SHARED;
        }
-       lwkt_reltoken(&lkp->lk_interlock);
+       lwkt_reltoken(&ilock);
        return (lock_type);
 }
 
@@ -520,11 +520,12 @@ int
 lockcount(lkp)
        struct lock *lkp;
 {
+       lwkt_tokref ilock;
        int count;
 
-       lwkt_gettoken(&lkp->lk_interlock);
+       lwkt_gettoken(&ilock, &lkp->lk_interlock);
        count = lkp->lk_exclusivecount + lkp->lk_sharecount;
-       lwkt_reltoken(&lkp->lk_interlock);
+       lwkt_reltoken(&ilock);
        return (count);
 }
 
index 433f58e..8432a0a 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)kern_sig.c  8.7 (Berkeley) 4/18/94
  * $FreeBSD: src/sys/kern/kern_sig.c,v 1.72.2.17 2003/05/16 16:34:34 obrien Exp $
- * $DragonFly: src/sys/kern/kern_sig.c,v 1.26 2004/02/12 06:57:48 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_sig.c,v 1.27 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include "opt_ktrace.h"
@@ -1467,7 +1467,7 @@ coredump(struct proc *p)
        NDFREE(&nd, NDF_ONLY_PNBUF);
        vp = nd.ni_vp;
 
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        lf.l_whence = SEEK_SET;
        lf.l_start = 0;
        lf.l_len = 0;
@@ -1484,12 +1484,12 @@ coredump(struct proc *p)
        }
 
        VATTR_NULL(&vattr);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        vattr.va_size = 0;
        VOP_LEASE(vp, td, cred, LEASE_WRITE);
        VOP_SETATTR(vp, &vattr, cred, td);
        p->p_acflag |= ACORE;
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
 
        error = p->p_sysent->sv_coredump ?
          p->p_sysent->sv_coredump(p, vp, limit) :
index 0b6ddd8..3ad34cb 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/kern_switch.c,v 1.3.2.1 2000/05/16 06:58:12 dillon Exp $
- * $DragonFly: src/sys/kern/Attic/kern_switch.c,v 1.17 2004/02/12 06:57:48 dillon Exp $
+ * $DragonFly: src/sys/kern/Attic/kern_switch.c,v 1.18 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -39,6 +39,7 @@
 #include <sys/sysctl.h>
 #include <machine/ipl.h>
 #include <machine/cpu.h>
+#include <machine/smp.h>
 
 /*
  * debugging only YYY Remove me!   define to schedule user processes only
@@ -64,8 +65,8 @@ static struct rq idqueues[NQS];
 static u_int32_t queuebits;
 static u_int32_t rtqueuebits;
 static u_int32_t idqueuebits;
-static u_int32_t curprocmask = -1;     /* currently running a user process */
-static u_int32_t rdyprocmask;          /* ready to accept a user process */
+static cpumask_t curprocmask = -1;     /* currently running a user process */
+static cpumask_t rdyprocmask;          /* ready to accept a user process */
 static int      runqcount;
 #ifdef SMP
 static int      scancpu;
@@ -93,6 +94,8 @@ SYSCTL_INT(_debug, OID_AUTO, choose_affinity, CTLFLAG_RD,
         &choose_affinity, 0, "chooseproc() was smart");
 #endif
 
+static void sched_thread_cpu_init(void);
+
 #define USCHED_COUNTER(td)     ((td->td_gd == mycpu) ? ++usched_optimal : ++usched_steal)
 
 /*
@@ -108,11 +111,7 @@ rqinit(void *dummy)
                TAILQ_INIT(&rtqueues[i]);
                TAILQ_INIT(&idqueues[i]);
        }
-#ifdef SMP
-       sched_thread_init();
-#else
        curprocmask &= ~1;
-#endif
 }
 SYSINIT(runqueue, SI_SUB_RUN_QUEUE, SI_ORDER_FIRST, rqinit, NULL)
 
@@ -249,7 +248,7 @@ setrunqueue(struct proc *p)
        int cpuid;
 #ifdef SMP
        int count;
-       u_int32_t mask;
+       cpumask_t mask;
 #endif
 
        crit_enter();
@@ -379,6 +378,11 @@ setrunqueue(struct proc *p)
         * We depress the priority check so multiple cpu bound programs
         * do not bounce between cpus.  Remember that the clock interrupt
         * will also cause all cpus to reschedule.
+        *
+        * We must mask against rdyprocmask or we will race in the boot
+        * code (before all cpus have working scheduler helpers), plus
+        * some cpus might not be operational and/or not configured to
+        * handle user processes.
         */
        if (count && remote_resched && ncpus > 1) {
                cpuid = scancpu;
@@ -388,12 +392,14 @@ setrunqueue(struct proc *p)
                } while (cpuid == mycpu->gd_cpuid);
                scancpu = cpuid;
 
-               gd = globaldata_find(cpuid);
+               if (rdyprocmask & (1 << cpuid)) {
+                       gd = globaldata_find(cpuid);
 
-               if (p->p_priority / PPQ < gd->gd_upri / PPQ - 2) {
-                       gd->gd_upri = p->p_priority;
-                       lwkt_send_ipiq(gd, need_resched_remote, NULL);
-                       ++remote_resched_nonaffinity;
+                       if (p->p_priority / PPQ < gd->gd_upri / PPQ - 2) {
+                               gd->gd_upri = p->p_priority;
+                               lwkt_send_ipiq(gd, need_resched_remote, NULL);
+                               ++remote_resched_nonaffinity;
+                       }
                }
        }
 #else
@@ -625,6 +631,7 @@ uio_yield(void)
        }
 }
 
+#ifdef SMP
 
 /*
  * For SMP systems a user scheduler helper thread is created for each
@@ -634,9 +641,6 @@ uio_yield(void)
  * thread for this because we need to hold the MP lock.  Additionally,
  * doing things this way allows us to HLT idle cpus on MP systems.
  */
-
-#ifdef SMP
-
 static void
 sched_thread(void *dummy)
 {
@@ -667,21 +671,43 @@ sched_thread(void *dummy)
     }
 }
 
-void
-sched_thread_init(void)
+/*
+ * Setup our scheduler helpers.  Note that curprocmask bit 0 has already
+ * been cleared by rqinit() and we should not mess with it further.
+ */
+static void
+sched_thread_cpu_init(void)
 {
-    int cpuid = mycpu->gd_cpuid;
+    int i;
+
+    if (bootverbose)
+       printf("start scheduler helpers on cpus:");
 
-    lwkt_create(sched_thread, NULL, NULL, &mycpu->gd_schedthread, 
-               TDF_STOPREQ, -1,
-               "usched %d", cpuid);
-    curprocmask &= ~(1 << cpuid);      /* schedule user proc on cpu */
+    for (i = 0; i < ncpus; ++i) {
+       globaldata_t dgd = globaldata_find(i);
+       cpumask_t mask = 1 << i;
+
+       if ((mask & smp_active_mask) == 0)
+           continue;
+
+       if (bootverbose)
+           printf(" %d", i);
+
+       lwkt_create(sched_thread, NULL, NULL, &dgd->gd_schedthread, 
+                   TDF_STOPREQ, i, "usched %d", i);
 #ifdef ONLY_ONE_USER_CPU
-    if (cpuid)
-       curprocmask |= 1 << cpuid;      /* DISABLE USER PROCS */
+       if (i)
+           curprocmask |= mask;        /* DISABLE USER PROCS */
+#else
+       if (i)
+           curprocmask &= ~mask;       /* schedule user proc on cpu */
 #endif
-    rdyprocmask |= 1 << cpuid;
+       rdyprocmask |= mask;
+    }
+    if (bootverbose)
+       printf("\n");
 }
+SYSINIT(uschedtd, SI_SUB_FINISH_SMP, SI_ORDER_ANY, sched_thread_cpu_init, NULL)
 
 #endif
 
index 962fc05..d5fccea 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/link_aout.c,v 1.26 1999/12/24 15:33:36 bde Exp $
- * $DragonFly: src/sys/kern/link_aout.c,v 1.9 2003/11/13 22:02:42 dillon Exp $
+ * $DragonFly: src/sys/kern/link_aout.c,v 1.10 2004/03/01 06:33:17 dillon Exp $
  */
 
 #ifndef __alpha__
@@ -285,7 +285,7 @@ link_aout_load_file(const char* filename, linker_file_t* result)
     *result = lf;
 
 out:
-    VOP_UNLOCK(nd.ni_vp, 0, td);
+    VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
     vn_close(nd.ni_vp, FREAD, td);
 
     return error;
index cff2ee7..fe88bcd 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/link_elf.c,v 1.24 1999/12/24 15:33:36 bde Exp $
- * $DragonFly: src/sys/kern/link_elf.c,v 1.11 2004/01/17 03:26:18 dillon Exp $
+ * $DragonFly: src/sys/kern/link_elf.c,v 1.12 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -700,7 +700,7 @@ out:
        free(shdr, M_LINKER);
     if (firstpage)
        free(firstpage, M_LINKER);
-    VOP_UNLOCK(nd.ni_vp, 0, td);
+    VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
     vn_close(nd.ni_vp, FREAD, td);
 
     return error;
index 340bd16..95ff667 100644 (file)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/lwkt_ipiq.c,v 1.3 2004/02/17 19:38:49 dillon Exp $
+ * $DragonFly: src/sys/kern/lwkt_ipiq.c,v 1.4 2004/03/01 06:33:17 dillon Exp $
  */
 
 /*
@@ -147,7 +147,7 @@ lwkt_send_ipiq(globaldata_t target, ipifunc_t func, void *arg)
     windex = ip->ip_windex & MAXCPUFIFO_MASK;
     ip->ip_func[windex] = (ipifunc2_t)func;
     ip->ip_arg[windex] = arg;
-    /* YYY memory barrier */
+    cpu_mb1();
     ++ip->ip_windex;
     if (ip->ip_windex - ip->ip_rindex > MAXCPUFIFO / 2) {
        unsigned int eflags = read_eflags();
@@ -165,6 +165,48 @@ lwkt_send_ipiq(globaldata_t target, ipifunc_t func, void *arg)
     return(ip->ip_windex);
 }
 
+/*
+ * Send an IPI request passively, return 0 on success and ENOENT on failure.
+ * This routine does not recursive through lwkt_process_ipiq() nor does it
+ * block trying to queue the actual IPI.  If we successfully queue the
+ * message but fail to queue the IPI, we still count it as a success.
+ * The occassional small race against a target cpu HLT is recovered at
+ * the next clock interrupt.
+ */
+int
+lwkt_send_ipiq_passive(globaldata_t target, ipifunc_t func, void *arg)
+{
+    lwkt_ipiq_t ip;
+    int windex;
+    struct globaldata *gd = mycpu;
+
+    KKASSERT(curthread->td_pri >= TDPRI_CRIT);
+    if (target == gd) {
+       func(arg);
+       return(0);
+    } 
+    ++ipiq_count;
+    ip = &gd->gd_ipiq[target->gd_cpuid];
+
+    if (ip->ip_windex - ip->ip_rindex >= MAXCPUFIFO - 1) {
+       return(ENOENT);
+    }
+    windex = ip->ip_windex & MAXCPUFIFO_MASK;
+    ip->ip_func[windex] = (ipifunc2_t)func;
+    ip->ip_arg[windex] = arg;
+    cpu_mb1();
+    ++ip->ip_windex;
+    /*
+     * passive mode doesn't work yet :-( 
+     */
+#if 1
+    cpu_send_ipiq(target->gd_cpuid);
+#else
+    cpu_send_ipiq_passive(target->gd_cpuid);
+#endif
+    return(0);
+}
+
 /*
  * deprecated, used only by fast int forwarding.
  */
@@ -217,7 +259,9 @@ lwkt_wait_ipiq(globaldata_t target, int seq)
            unsigned int eflags = read_eflags();
            cpu_enable_intr();
            while ((int)(ip->ip_xindex - seq) < 0) {
+               crit_enter();
                lwkt_process_ipiq();
+               crit_exit();
                if (--maxc == 0)
                        printf("LWKT_WAIT_IPIQ WARNING! %d wait %d (%d)\n", mycpu->gd_cpuid, target->gd_cpuid, ip->ip_xindex - seq);
                if (maxc < -1000000)
@@ -228,6 +272,15 @@ lwkt_wait_ipiq(globaldata_t target, int seq)
     }
 }
 
+int
+lwkt_seq_ipiq(globaldata_t target)
+{
+    lwkt_ipiq_t ip;
+
+    ip = &mycpu->gd_ipiq[target->gd_cpuid];
+    return(ip->ip_windex);
+}
+
 /*
  * Called from IPI interrupt (like a fast interrupt), which has placed
  * us in a critical section.  The MP lock may or may not be held.
@@ -434,7 +487,9 @@ void
 lwkt_cpusync_add(cpumask_t mask, lwkt_cpusync_t poll)
 {
     globaldata_t gd = mycpu;
+#ifdef SMP
     int count;
+#endif
 
     mask &= ~poll->cs_mask;
     poll->cs_mask |= mask;
index 4962e79..008e7f1 100644 (file)
@@ -25,7 +25,7 @@
  *
  * Implements simple shared/exclusive locks using LWKT. 
  *
- * $DragonFly: src/sys/kern/Attic/lwkt_rwlock.c,v 1.4 2003/07/20 01:37:22 dillon Exp $
+ * $DragonFly: src/sys/kern/Attic/lwkt_rwlock.c,v 1.5 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include <sys/param.h>
 void
 lwkt_rwlock_init(lwkt_rwlock_t lock)
 {
-    lwkt_init_wait(&lock->rw_wait);
+    lwkt_wait_init(&lock->rw_wait);
+    lock->rw_owner = NULL;
+    lock->rw_count = 0;
+    lock->rw_requests = 0;
 }
 
-#if 0
+void
+lwkt_rwlock_uninit(lwkt_rwlock_t lock)
+{
+    /* empty */
+}
 
 void
 lwkt_exlock(lwkt_rwlock_t lock, const char *wmesg)
 {
+    lwkt_tokref ilock;
     int gen;
 
-    lwkt_gettoken(&lock->rw_token);
+    lwkt_gettoken(&ilock, &lock->rw_token);
     gen = lock->rw_wait.wa_gen;
     while (lock->rw_owner != curthread) {
        if (lock->rw_owner == NULL && lock->rw_count == 0) {
@@ -60,34 +68,35 @@ lwkt_exlock(lwkt_rwlock_t lock, const char *wmesg)
        }
        ++lock->rw_requests;
        lwkt_block(&lock->rw_wait, wmesg, &gen);
-       lwkt_regettoken(&lock->rw_token);
        --lock->rw_requests;
     }
     ++lock->rw_count;
-    lwkt_reltoken(&lock->rw_token);
+    lwkt_reltoken(&ilock);
 }
 
 void
 lwkt_shlock(lwkt_rwlock_t lock, const char *wmesg)
 {
+    lwkt_tokref ilock;
     int gen;
 
-    lwkt_gettoken(&lock->rw_token);
+    lwkt_gettoken(&ilock, &lock->rw_token);
     gen = lock->rw_wait.wa_gen;
     while (lock->rw_owner != NULL) {
        ++lock->rw_requests;
        lwkt_block(&lock->rw_wait, wmesg, &gen);
-       lwkt_regettoken(&lock->rw_token);
        --lock->rw_requests;
     }
     ++lock->rw_count;
-    lwkt_reltoken(&lock->rw_token);
+    lwkt_reltoken(&ilock);
 }
 
 void
 lwkt_exunlock(lwkt_rwlock_t lock)
 {
-    lwkt_gettoken(&lock->rw_token);
+    lwkt_tokref ilock;
+
+    lwkt_gettoken(&ilock, &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) {
@@ -95,19 +104,20 @@ lwkt_exunlock(lwkt_rwlock_t lock)
        if (lock->rw_requests)
            lwkt_signal(&lock->rw_wait, 1);
     }
-    lwkt_reltoken(&lock->rw_token);
+    lwkt_reltoken(&ilock);
 }
 
 void
 lwkt_shunlock(lwkt_rwlock_t lock)
 {
-    lwkt_gettoken(&lock->rw_token);
+    lwkt_tokref ilock;
+
+    lwkt_gettoken(&ilock, &lock->rw_token);
     KASSERT(lock->rw_owner == NULL, ("lwkt_shunlock: exclusive lock"));
     if (--lock->rw_count == 0) {
        if (lock->rw_requests)
            lwkt_signal(&lock->rw_wait, 1);
     }
-    lwkt_reltoken(&lock->rw_token);
+    lwkt_reltoken(&ilock);
 }
 
-#endif
index f8eb53c..92285b3 100644 (file)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.55 2004/02/17 19:38:49 dillon Exp $
+ * $DragonFly: src/sys/kern/lwkt_thread.c,v 1.56 2004/03/01 06:33:17 dillon Exp $
  */
 
 /*
@@ -174,9 +174,12 @@ lwkt_gdinit(struct globaldata *gd)
  * NOTE!  called from low level boot code, we cannot do anything fancy!
  */
 void
-lwkt_init_wait(lwkt_wait_t w)
+lwkt_wait_init(lwkt_wait_t w)
 {
+    lwkt_token_init(&w->wa_token);
     TAILQ_INIT(&w->wa_waitq);
+    w->wa_gen = 0;
+    w->wa_count = 0;
 }
 
 /*
@@ -246,6 +249,8 @@ lwkt_alloc_thread(struct thread *td, int cpu)
  * NOTE! we have to be careful in regards to creating threads for other cpus
  * if SMP has not yet been activated.
  */
+#ifdef SMP
+
 static void
 lwkt_init_thread_remote(void *arg)
 {
@@ -254,6 +259,8 @@ lwkt_init_thread_remote(void *arg)
     TAILQ_INSERT_TAIL(&td->td_gd->gd_tdallq, td, td_allq);
 }
 
+#endif
+
 void
 lwkt_init_thread(thread_t td, void *stack, int flags, struct globaldata *gd)
 {
@@ -379,7 +386,7 @@ lwkt_free_thread(thread_t td)
 void
 lwkt_switch(void)
 {
-    struct globaldata *gd;
+    globaldata_t gd;
     thread_t td = curthread;
     thread_t ntd;
 #ifdef SMP
@@ -462,9 +469,24 @@ lwkt_switch(void)
         *
         * We have to adjust the MP lock for the target thread.  If we 
         * need the MP lock and cannot obtain it we try to locate a
-        * thread that does not need the MP lock.
+        * thread that does not need the MP lock.  If we cannot, we spin
+        * instead of HLT.
+        *
+        * A similar issue exists for the tokens held by the target thread.
+        * If we cannot obtain ownership of the tokens we cannot immediately
+        * schedule the thread.
+        */
+
+       /*
+        * We are switching threads.  If there are any pending requests for
+        * tokens we can satisfy all of them here.
         */
        gd = mycpu;
+#ifdef SMP
+       if (gd->gd_tokreqbase)
+               lwkt_drain_token_requests();
+#endif
+
 again:
        if (gd->gd_runqmask) {
            int nq = bsrl(gd->gd_runqmask);
@@ -473,17 +495,24 @@ again:
                goto again;
            }
 #ifdef SMP
-           if (ntd->td_mpcount && mpheld == 0 && !cpu_try_mplock()) {
-               /*
-                * Target needs MP lock and we couldn't get it, try
-                * to locate a thread which does not need the MP lock
-                * to run.  If we cannot locate a thread spin in idle.
-                */
+           /*
+            * If the target needs the MP lock and we couldn't get it,
+            * or if the target is holding tokens and we could not 
+            * gain ownership of the tokens, continue looking for a
+            * thread to schedule and spin instead of HLT if we can't.
+            */
+           if ((ntd->td_mpcount && mpheld == 0 && !cpu_try_mplock()) ||
+               (ntd->td_toks && lwkt_chktokens(ntd) == 0)
+           ) {
                u_int32_t rqmask = gd->gd_runqmask;
                while (rqmask) {
                    TAILQ_FOREACH(ntd, &gd->gd_tdrunq[nq], td_threadq) {
-                       if (ntd->td_mpcount == 0)
-                           break;
+                       if (ntd->td_mpcount && !mpheld && !cpu_try_mplock())
+                           continue;
+                       mpheld = MP_LOCK_HELD();
+                       if (ntd->td_toks && !lwkt_chktokens(ntd))
+                           continue;
+                       break;
                    }
                    if (ntd)
                        break;
@@ -603,6 +632,10 @@ lwkt_preempt(thread_t ntd, int critpri)
      *
      * YYY The target thread must be in a critical section (else it must
      * inherit our critical section?  I dunno yet).
+     *
+     * Any tokens held by the target may not be held by thread(s) being
+     * preempted.  We take the easy way out and do not preempt if
+     * the target is holding tokens.
      */
     KASSERT(ntd->td_pri >= TDPRI_CRIT, ("BADCRIT0 %d", ntd->td_pri));
 
@@ -621,6 +654,17 @@ lwkt_preempt(thread_t ntd, int critpri)
        return;
     }
 #endif
+    /*
+     * Take the easy way out and do not preempt if the target is holding
+     * one or more tokens.  We could test whether the thread(s) being
+     * preempted interlock against the target thread's tokens and whether
+     * we can get all the target thread's tokens, but this situation 
+     * should not occur very often so its easier to simply not preempt.
+     */
+    if (ntd->td_toks != NULL) {
+       ++preempt_miss;
+       return;
+    }
     if (td == ntd || ((td->td_flags | ntd->td_flags) & TDF_PREEMPT_LOCK)) {
        ++preempt_weird;
        return;
@@ -754,14 +798,15 @@ lwkt_schedule_self(void)
 {
     thread_t td = curthread;
 
-    crit_enter();
+    crit_enter_quick(td);
     KASSERT(td->td_wait == NULL, ("lwkt_schedule_self(): td_wait not NULL!"));
+    KASSERT(td != &td->td_gd->gd_idlethread, ("lwkt_schedule_self(): scheduling gd_idlethread is illegal!"));
     _lwkt_enqueue(td);
 #ifdef _KERNEL
     if (td->td_proc && td->td_proc->p_stat == SSLEEP)
        panic("SCHED SELF PANIC");
 #endif
-    crit_exit();
+    crit_exit_quick(td);
 }
 
 /*
@@ -776,6 +821,7 @@ void
 lwkt_schedule(thread_t td)
 {
 #ifdef INVARIANTS
+    KASSERT(td != &td->td_gd->gd_idlethread, ("lwkt_schedule(): scheduling gd_idlethread is illegal!"));
     if ((td->td_flags & TDF_PREEMPT_LOCK) == 0 && td->td_proc 
        && td->td_proc->p_stat == SSLEEP
     ) {
@@ -807,7 +853,9 @@ lwkt_schedule(thread_t td)
         * (remember, wait structures use stable storage)
         */
        if ((w = td->td_wait) != NULL) {
-           if (lwkt_trytoken(&w->wa_token)) {
+           lwkt_tokref wref;
+
+           if (lwkt_trytoken(&wref, &w->wa_token)) {
                TAILQ_REMOVE(&w->wa_waitq, td, td_threadq);
                --w->wa_count;
                td->td_wait = NULL;
@@ -828,7 +876,7 @@ lwkt_schedule(thread_t td)
                else if (_lwkt_wantresched(td, curthread))
                    need_resched();
 #endif
-               lwkt_reltoken(&w->wa_token);
+               lwkt_reltoken(&wref);
            } else {
                lwkt_send_ipiq(w->wa_token.t_cpu, (ipifunc_t)lwkt_schedule, td);
            }
@@ -980,43 +1028,36 @@ lwkt_preempted_proc(void)
     return(td->td_proc);
 }
 
-#if 0
-
 /*
- * This function deschedules the current thread and blocks on the specified
- * wait queue.  We obtain ownership of the wait queue in order to block
- * on it.  A generation number is used to interlock the wait queue in case
- * it gets signalled while we are blocked waiting on the token.
- *
- * Note: alternatively we could dequeue our thread and then message the
- * target cpu owning the wait queue.  YYY implement as sysctl.
- *
- * Note: wait queue signals normally ping-pong the cpu as an optimization.
+ * Block on the specified wait queue until signaled.  A generation number
+ * must be supplied to interlock the wait queue.  The function will
+ * return immediately if the generation number does not match the wait
+ * structure's generation number.
  */
-
 void
 lwkt_block(lwkt_wait_t w, const char *wmesg, int *gen)
 {
     thread_t td = curthread;
+    lwkt_tokref ilock;
 
-    lwkt_gettoken(&w->wa_token);
+    lwkt_gettoken(&ilock, &w->wa_token);
+    crit_enter();
     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;
-again:
+    again:
        lwkt_switch();
-       lwkt_regettoken(&w->wa_token);
        if (td->td_wmesg != NULL) {
            _lwkt_dequeue(td);
            goto again;
        }
     }
-    /* token might be lost, doesn't matter for gen update */
+    crit_exit();
     *gen = w->wa_gen;
-    lwkt_reltoken(&w->wa_token);
+    lwkt_reltoken(&ilock);
 }
 
 /*
@@ -1031,10 +1072,11 @@ void
 lwkt_signal(lwkt_wait_t w, int count)
 {
     thread_t td;
-    int count;
+    lwkt_tokref ilock;
 
-    lwkt_gettoken(&w->wa_token);
+    lwkt_gettoken(&ilock, &w->wa_token);
     ++w->wa_gen;
+    crit_enter();
     if (count < 0)
        count = w->wa_count;
     while ((td = TAILQ_FIRST(&w->wa_waitq)) != NULL && count) {
@@ -1048,13 +1090,11 @@ lwkt_signal(lwkt_wait_t w, int count)
        } else {
            lwkt_send_ipiq(td->td_gd, (ipifunc_t)lwkt_schedule, td);
        }
-       lwkt_regettoken(&w->wa_token);
     }
-    lwkt_reltoken(&w->wa_token);
+    crit_exit();
+    lwkt_reltoken(&ilock);
 }
 
-#endif
-
 /*
  * Create a kernel process/thread/whatever.  It shares it's address space
  * with proc0 - ie: kernel only.
index 4e7a5fe..6b83b77 100644 (file)
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/lwkt_token.c,v 1.4 2004/02/18 16:31:37 joerg Exp $
+ * $DragonFly: src/sys/kern/lwkt_token.c,v 1.5 2004/03/01 06:33:17 dillon Exp $
  */
 
 #ifdef _KERNEL
 
 #endif
 
+#define        MAKE_TOKENS_SPIN
+/* #define MAKE_TOKENS_YIELD */
+
+#ifndef LWKT_NUM_POOL_TOKENS
+#define LWKT_NUM_POOL_TOKENS   1024    /* power of 2 */
+#endif
+#define LWKT_MASK_POOL_TOKENS  (LWKT_NUM_POOL_TOKENS - 1)
+
 #ifdef INVARIANTS
 static int token_debug = 0;
 #endif
 
+static lwkt_token      pool_tokens[LWKT_NUM_POOL_TOKENS];
+
 #ifdef _KERNEL
 
 #ifdef INVARIANTS
@@ -87,214 +97,428 @@ SYSCTL_INT(_lwkt, OID_AUTO, token_debug, CTLFLAG_RW, &token_debug, 0, "");
 
 #endif
 
-typedef struct lwkt_gettoken_req {
-    lwkt_token_t tok;
-    globaldata_t cpu;
-} lwkt_gettoken_req;
+#ifdef SMP
 
 /*
- * Acquire ownership of a token
- *
- * Acquire ownership of a token.  The token may have spl and/or critical
- * section side effects, depending on its purpose.  These side effects
- * guarentee that you will maintain ownership of the token as long as you
- * do not block.  If you block you may lose access to the token (but you
- * must still release it even if you lose your access to it).
- *
- * YYY for now we use a critical section to prevent IPIs from taking away
- * a token, but do we really only need to disable IPIs ?
- *
- * YYY certain tokens could be made to act like mutexes when performance
- * would be better (e.g. t_cpu == NULL).  This is not yet implemented.
- *
- * YYY the tokens replace 4.x's simplelocks for the most part, but this
- * means that 4.x does not expect a switch so for now we cannot switch
- * when waiting for an IPI to be returned.  
+ * Determine if we own all the tokens in the token reference list.
+ * Return 1 on success, 0 on failure. 
  *
- * YYY If the token is owned by another cpu we may have to send an IPI to
- * it and then block.   The IPI causes the token to be given away to the
- * 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.
- * This needs serious optimization.
+ * As a side effect, queue requests for tokens we want which are owned
+ * by other cpus.  The magic number is used to communicate when the 
+ * target cpu has processed the request.  Note, however, that the
+ * target cpu may not be able to assign the token to us which is why
+ * the scheduler must spin.
  */
+int
+lwkt_chktokens(thread_t td)
+{
+    globaldata_t gd = td->td_gd;       /* mycpu */
+    lwkt_tokref_t refs;
+    globaldata_t dgd;
+    lwkt_token_t tok;
+    int r = 1;
 
-#ifdef SMP
+    for (refs = td->td_toks; refs; refs = refs->tr_next) {
+       tok = refs->tr_tok;
+       if ((dgd = tok->t_cpu) != gd) {
+           cpu_mb1();
+           r = 0;
 
-static
-void
-lwkt_gettoken_remote(void *arg)
-{
-    lwkt_gettoken_req *req = arg;
-    if (req->tok->t_cpu == mycpu) {
-#ifdef INVARIANTS
-       if (token_debug)
-           printf("GT(%d,%d) ", req->tok->t_cpu->gd_cpuid, req->cpu->gd_cpuid);
-#endif
-       req->tok->t_cpu = req->cpu;
-       req->tok->t_reqcpu = req->cpu;  /* YYY leave owned by target cpu */
-       /* else set reqcpu to point to current cpu for release */
+           /*
+            * Queue a request to the target cpu, exit the loop early if
+            * we are unable to queue the IPI message.  The magic number
+            * flags whether we have a pending ipi request queued or not.
+            */
+           if (refs->tr_magic == LWKT_TOKREF_MAGIC1) {
+               refs->tr_magic = LWKT_TOKREF_MAGIC2;    /* MP synched slowreq*/
+               refs->tr_reqgd = gd;
+               tok->t_reqcpu = gd;     /* MP unsynchronized 'fast' req */
+               if (lwkt_send_ipiq_passive(dgd, lwkt_reqtoken_remote, refs)) {
+                   /* failed */
+                   refs->tr_magic = LWKT_TOKREF_MAGIC1;
+                   break;
+               }
+           }
+       }
     }
+    return(r);
 }
 
 #endif
 
+/*
+ * Check if we already own the token.  Return 1 on success, 0 on failure.
+ */
 int
-lwkt_gettoken(lwkt_token_t tok)
+lwkt_havetoken(lwkt_token_t tok)
 {
-    /*
-     * Prevent preemption so the token can't be taken away from us once
-     * we gain ownership of it.  Use a synchronous request which might
-     * block.  The request will be forwarded as necessary playing catchup
-     * to the token.
-     */
+    globaldata_t gd = mycpu;
+    thread_t td = gd->gd_curthread;
+    lwkt_tokref_t ref;
 
-    crit_enter();
-#ifdef INVARIANTS
-    if (curthread->td_pri > 1800) {
-       printf("lwkt_gettoken: %p called from %p: crit sect nesting warning\n",
-           tok, ((int **)&tok)[-1]);
+    for (ref = td->td_toks; ref; ref = ref->tr_next) {
+        if (ref->tr_tok == tok)
+            return(1);
     }
-    if (curthread->td_pri > 2000) {
-       curthread->td_pri = 1000;
-       panic("too HIGH!");
+    return(0);
+}
+
+int
+lwkt_havetokref(lwkt_tokref_t xref)
+{
+    globaldata_t gd = mycpu;
+    thread_t td = gd->gd_curthread;
+    lwkt_tokref_t ref;
+
+    for (ref = td->td_toks; ref; ref = ref->tr_next) {
+        if (ref == xref)
+            return(1);
     }
-#endif
+    return(0);
+}
+
 #ifdef SMP
-    while (tok->t_cpu != mycpu) {
-       struct lwkt_gettoken_req req;
-       int seq;
-       globaldata_t dcpu;
-
-       req.cpu = mycpu;
-       req.tok = tok;
-       dcpu = tok->t_cpu;
-#ifdef INVARIANTS
-       if (token_debug)
-           printf("REQT%d ", dcpu->gd_cpuid);
-#endif
-       seq = lwkt_send_ipiq(dcpu, lwkt_gettoken_remote, &req);
-       lwkt_wait_ipiq(dcpu, seq);
-#ifdef INVARIANTS
-       if (token_debug)
-           printf("REQR%d ", tok->t_cpu->gd_cpuid);
-#endif
+
+/*
+ * Returns 1 if it is ok to give a token away, 0 if it is not.
+ */
+static int
+lwkt_oktogiveaway_token(lwkt_token_t tok)
+{
+    globaldata_t gd = mycpu;
+    lwkt_tokref_t ref;
+    thread_t td;
+
+    for (td = gd->gd_curthread; td; td = td->td_preempted) {
+       for (ref = td->td_toks; ref; ref = ref->tr_next) {
+           if (ref->tr_tok == tok)
+               return(0);
+       }
     }
+    return(1);
+}
+
 #endif
+
+/*
+ * Acquire a serializing token
+ */
+
+static __inline
+void
+_lwkt_gettokref(lwkt_tokref_t ref)
+{
+    lwkt_token_t tok;
+    globaldata_t gd;
+    thread_t td;
+
+    gd = mycpu;                        /* our cpu */
+    KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC1);
+    td = gd->gd_curthread;     /* our thread */
+
     /*
-     * leave us in a critical section on return.  This will be undone
-     * by lwkt_reltoken().  Bump the generation number.
+     * Link the request into our thread's list.  This interlocks against
+     * remote requests from other cpus and prevents the token from being
+     * given away if our cpu already owns it.  This also allows us to
+     * avoid using a critical section.
      */
-    return(++tok->t_gen);
+    ref->tr_next = td->td_toks;
+    cpu_mb1();         /* order memory / we can be interrupted */
+    td->td_toks = ref;
+
+    /*
+     * If our cpu does not own the token then let the scheduler deal with
+     * it.  We are guarenteed to own the tokens on our thread's token
+     * list when we are switched back in.
+     *
+     * Otherwise make sure the token is not held by a thread we are
+     * preempting.  If it is, let the scheduler deal with it.
+     */
+    tok = ref->tr_tok;
+#ifdef SMP
+    if (tok->t_cpu != gd) {
+       /*
+        * Temporarily operate on tokens synchronously.  We have to fix
+        * a number of interlocks and especially the softupdates code to
+        * be able to properly yield.  ZZZ
+        */
+#if defined(MAKE_TOKENS_SPIN)
+       int x = 40000000;
+       crit_enter();
+       while (lwkt_chktokens(td) == 0) {
+           lwkt_process_ipiq();
+           lwkt_drain_token_requests();
+           if (--x == 0) {
+               x = 40000000;
+               printf("CHKTOKEN loop %d\n", gd->gd_cpuid);
+               Debugger("x");
+           }
+           splz();
+       }
+       crit_exit();
+#elif defined(MAKE_TOKENS_YIELD)
+       lwkt_yield();
+#else
+#error MAKE_TOKENS_XXX ?
+#endif
+       KKASSERT(tok->t_cpu == gd);
+    } else /* NOTE CONDITIONAL */
+#endif
+    if (td->td_preempted) {
+       while ((td = td->td_preempted) != NULL) {
+           lwkt_tokref_t scan;
+           for (scan = td->td_toks; scan; scan = scan->tr_next) {
+               if (scan->tr_tok == tok) {
+                   lwkt_yield();
+                   KKASSERT(tok->t_cpu == gd);
+                   goto breakout;
+               }
+           }
+       }
+breakout:
+    }
+    /* 'td' variable no longer valid due to preempt loop above */
 }
 
+
 /*
- * Attempt to acquire ownership of a token.  Returns 1 on success, 0 on
- * failure.
+ * Attempt to acquire a serializing token
  */
+static __inline
 int
-lwkt_trytoken(lwkt_token_t tok)
+_lwkt_trytokref(lwkt_tokref_t ref)
 {
-    crit_enter();
+    lwkt_token_t tok;
+    globaldata_t gd;
+    thread_t td;
+
+    gd = mycpu;                        /* our cpu */
+    KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC1);
+    td = gd->gd_curthread;     /* our thread */
+
+    /*
+     * Link the request into our thread's list.  This interlocks against
+     * remote requests from other cpus and prevents the token from being
+     * given away if our cpu already owns it.  This also allows us to
+     * avoid using a critical section.
+     */
+    ref->tr_next = td->td_toks;
+    cpu_mb1();         /* order memory / we can be interrupted */
+    td->td_toks = ref;
+
+    /*
+     * If our cpu does not own the token then stop now.
+     *
+     * Otherwise make sure the token is not held by a thread we are
+     * preempting.  If it is, stop.
+     */
+    tok = ref->tr_tok;
 #ifdef SMP
-    if (tok->t_cpu != mycpu) {
-       crit_exit();
+    if (tok->t_cpu != gd) {
+       td->td_toks = ref->tr_next;     /* remove ref */
        return(0);
-    } 
+    } else /* NOTE CONDITIONAL */
 #endif
-    /* leave us in the critical section */
-    ++tok->t_gen;
+    if (td->td_preempted) {
+       while ((td = td->td_preempted) != NULL) {
+           lwkt_tokref_t scan;
+           for (scan = td->td_toks; scan; scan = scan->tr_next) {
+               if (scan->tr_tok == tok) {
+                   td = gd->gd_curthread;      /* our thread */
+                   td->td_toks = ref->tr_next; /* remove ref */
+                   return(0);
+               }
+           }
+       }
+    }
+    /* 'td' variable no longer valid */
     return(1);
 }
 
-/*
- * Release your ownership of a token.  Releases must occur in reverse
- * order to aquisitions, eventually so priorities can be unwound properly
- * like SPLs.  At the moment the actual implemention doesn't care.
- *
- * We can safely hand a token that we own to another cpu without notifying
- * it, but once we do we can't get it back without requesting it (unless
- * the other cpu hands it back to us before we check).
- *
- * We might have lost the token, so check that.
- *
- * Return the token's generation number.  The number is useful to callers
- * who may want to know if the token was stolen during potential blockages.
- */
-int
-lwkt_reltoken(lwkt_token_t tok)
+void
+lwkt_gettoken(lwkt_tokref_t ref, lwkt_token_t tok)
 {
-    int gen;
+    lwkt_tokref_init(ref, tok);
+    _lwkt_gettokref(ref);
+}
 
-    if (tok->t_cpu == mycpu) {
-       tok->t_cpu = tok->t_reqcpu;
-    }
-    gen = tok->t_gen;
-    crit_exit();
-    return(gen);
+void
+lwkt_gettokref(lwkt_tokref_t ref)
+{
+    _lwkt_gettokref(ref);
 }
 
-/*
- * Reacquire a token that might have been lost.  0 is returned if the 
- * generation has not changed (nobody stole the token from us), -1 is 
- * returned otherwise.  The token is reacquired regardless but the
- * generation number is not bumped further if we already own the token.
- *
- * For efficiency we inline the best-case situation for lwkt_regettoken()
- * (i.e .we still own the token).
- */
 int
-lwkt_gentoken(lwkt_token_t tok, int *gen)
+lwkt_trytoken(lwkt_tokref_t ref, lwkt_token_t tok)
 {
-    if (tok->t_cpu == mycpu && tok->t_gen == *gen)
-       return(0);
-    *gen = lwkt_regettoken(tok);
-    return(-1);
+    lwkt_tokref_init(ref, tok);
+    return(_lwkt_trytokref(ref));
+}
+
+int
+lwkt_trytokref(lwkt_tokref_t ref)
+{
+    return(_lwkt_trytokref(ref));
 }
 
 /*
- * Re-acquire a token that might have been lost.   The generation number
- * is bumped and returned regardless of whether the token had been lost
- * or not (because we only have cpu granularity we have to bump the token
- * either way).
+ * Release a serializing token
  */
-int
-lwkt_regettoken(lwkt_token_t tok)
+void
+lwkt_reltoken(lwkt_tokref *_ref)
 {
-    /* assert we are in a critical section */
-    if (tok->t_cpu != mycpu) {
-#ifdef SMP
-       while (tok->t_cpu != mycpu) {
-           struct lwkt_gettoken_req req;
-           int seq;
-           globaldata_t dcpu;
-
-           req.cpu = mycpu;
-           req.tok = tok;
-           dcpu = tok->t_cpu;
+    lwkt_tokref *ref;
+    lwkt_tokref **pref;
+    lwkt_token_t tok;
+    globaldata_t gd;
+    thread_t td;
+
+    /*
+     * Guard check and stack check (if in the same stack page).  We must
+     * also wait for any action pending on remote cpus which we do by
+     * checking the magic number and yielding in a loop.
+     */
+    ref = _ref;
 #ifdef INVARIANTS
-           if (token_debug)
-               printf("REQT%d ", dcpu->gd_cpuid);
+    if ((((intptr_t)ref ^ (intptr_t)&_ref) && ~(intptr_t)PAGE_MASK) == 0)
+       KKASSERT((char *)ref > (char *)&_ref);
+    KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC1 || 
+            ref->tr_magic == LWKT_TOKREF_MAGIC2);
 #endif
-           seq = lwkt_send_ipiq(dcpu, lwkt_gettoken_remote, &req);
-           lwkt_wait_ipiq(dcpu, seq);
-#ifdef INVARIANTS
-           if (token_debug)
-               printf("REQR%d ", tok->t_cpu->gd_cpuid);
+    /*
+     * Locate and unlink the token.  Interlock with the token's cpureq
+     * to give the token away before we release it from our thread list,
+     * which allows us to avoid using a critical section.
+     */
+    gd = mycpu;
+    td = gd->gd_curthread;
+    for (pref = &td->td_toks; (ref = *pref) != _ref; pref = &ref->tr_next) {
+       KKASSERT(ref != NULL);
+    }
+    tok = ref->tr_tok;
+    KKASSERT(tok->t_cpu == gd);
+    tok->t_cpu = tok->t_reqcpu;        /* we do not own 'tok' after this */
+    *pref = ref->tr_next;      /* note: also removes giveaway interlock */
+
+    /*
+     * If we had gotten the token opportunistically and it still happens to
+     * be queued to a target cpu, we have to wait for the target cpu
+     * to finish processing it.  This does not happen very often and does
+     * not need to be optimal.
+     */
+    while (ref->tr_magic == LWKT_TOKREF_MAGIC2) {
+#if defined(MAKE_TOKENS_SPIN)
+       crit_enter();
+#ifdef SMP
+       lwkt_process_ipiq();
 #endif
-       }
+       splz();
+       crit_exit();
+#elif defined(MAKE_TOKENS_YIELD)
+       lwkt_yield();
+#else
+#error MAKE_TOKENS_XXX ?
 #endif
     }
-    ++tok->t_gen;
-    return(tok->t_gen);
 }
 
+/*
+ * Pool tokens are used to provide a type-stable serializing token
+ * pointer that does not race against disappearing data structures.
+ *
+ * This routine is called in early boot just after we setup the BSP's
+ * globaldata structure.
+ */
+void
+lwkt_token_pool_init(void)
+{
+    int i;
+
+    for (i = 0; i < LWKT_NUM_POOL_TOKENS; ++i)
+       lwkt_token_init(&pool_tokens[i]);
+}
+
+lwkt_token_t
+lwkt_token_pool_get(void *ptraddr)
+{
+    int i;
+
+    i = ((int)(intptr_t)ptraddr >> 2) ^ ((int)(intptr_t)ptraddr >> 12);
+    return(&pool_tokens[i & LWKT_MASK_POOL_TOKENS]);
+}
+
+#ifdef SMP
+
+/*
+ * This is the receiving side of a remote IPI requesting a token.  If we
+ * cannot immediately hand the token off to another cpu we queue it.
+ *
+ * NOTE!  we 'own' the ref structure, but we only 'own' the token if
+ * t_cpu == mycpu.
+ */
 void
-lwkt_inittoken(lwkt_token_t tok)
+lwkt_reqtoken_remote(void *data)
 {
+    lwkt_tokref_t ref = data;
+    globaldata_t gd = mycpu;
+    lwkt_token_t tok = ref->tr_tok;
+
     /*
-     * Zero structure and set cpu owner and reqcpu to cpu 0.
+     * We do not have to queue the token if we can give it away
+     * immediately.  Otherwise we queue it to our globaldata structure.
      */
+    KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC2);
+    if (lwkt_oktogiveaway_token(tok)) {
+       if (tok->t_cpu == gd)
+           tok->t_cpu = ref->tr_reqgd;
+       cpu_mb1();
+       ref->tr_magic = LWKT_TOKREF_MAGIC1;
+    } else {
+       ref->tr_gdreqnext = gd->gd_tokreqbase;
+       gd->gd_tokreqbase = ref;
+    }
+}
+
+/*
+ * Must be called from a critical section.  Satisfy all remote token
+ * requests that are pending on our globaldata structure.  The request
+ * does not have to be satisfied with a successful change of ownership
+ * but we do have to acknowledge that we have completed processing the
+ * request by setting the magic number back to MAGIC1.
+ *
+ * NOTE!  we 'own' the ref structure, but we only 'own' the token if
+ * t_cpu == mycpu.
+ */
+void
+lwkt_drain_token_requests(void)
+{
+    globaldata_t gd = mycpu;
+    lwkt_tokref_t ref;
+
+    while ((ref = gd->gd_tokreqbase) != NULL) {
+       gd->gd_tokreqbase = ref->tr_gdreqnext;
+       KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC2);
+       if (ref->tr_tok->t_cpu == gd)
+           ref->tr_tok->t_cpu = ref->tr_reqgd;
+       cpu_mb1();
+       ref->tr_magic = LWKT_TOKREF_MAGIC1;
+    }
+}
+
+#endif
+
+/*
+ * Initialize the owner and release-to cpu to the current cpu
+ * and reset the generation count.
+ */
+void
+lwkt_token_init(lwkt_token_t tok)
+{
     tok->t_cpu = tok->t_reqcpu = mycpu;
-    tok->t_gen = 0;
 }
 
+void
+lwkt_token_uninit(lwkt_token_t tok)
+{
+    /* empty */
+}
index e0a49af..ad1d6b0 100644 (file)
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/kern/subr_rman.c,v 1.10.2.1 2001/06/05 08:06:08 imp Exp $
- * $DragonFly: src/sys/kern/subr_rman.c,v 1.5 2003/11/15 21:05:43 dillon Exp $
+ * $DragonFly: src/sys/kern/subr_rman.c,v 1.6 2004/03/01 06:33:17 dillon Exp $
  */
 
 /*
@@ -82,11 +82,12 @@ int
 rman_init(struct rman *rm)
 {
        static int once;
+       lwkt_tokref ilock;
 
        if (once == 0) {
                once = 1;
                TAILQ_INIT(&rman_head);
-               lwkt_inittoken(&rman_tok);
+               lwkt_token_init(&rman_tok);
        }
 
        if (rm->rm_type == RMAN_UNINIT)
@@ -98,11 +99,11 @@ rman_init(struct rman *rm)
        rm->rm_slock = malloc(sizeof *rm->rm_slock, M_RMAN, M_NOWAIT);
        if (rm->rm_slock == NULL)
                return ENOMEM;
-       lwkt_inittoken(rm->rm_slock);
+       lwkt_token_init(rm->rm_slock);
 
-       lwkt_gettoken(&rman_tok);
+       lwkt_gettoken(&ilock, &rman_tok);
        TAILQ_INSERT_TAIL(&rman_head, rm, rm_link);
-       lwkt_reltoken(&rman_tok);
+       lwkt_reltoken(&ilock);
        return 0;
 }
 
@@ -114,6 +115,7 @@ int
 rman_manage_region(struct rman *rm, u_long start, u_long end)
 {
        struct resource *r, *s;
+       lwkt_tokref ilock;
 
        r = malloc(sizeof *r, M_RMAN, M_NOWAIT);
        if (r == 0)
@@ -126,7 +128,7 @@ rman_manage_region(struct rman *rm, u_long start, u_long end)
        r->r_dev = 0;
        r->r_rm = rm;
 
-       lwkt_gettoken(rm->rm_slock);
+       lwkt_gettoken(&ilock, rm->rm_slock);
        for (s = CIRCLEQ_FIRST(&rm->rm_list);   
             !CIRCLEQ_TERMCOND(s, rm->rm_list) && s->r_end < r->r_start;
             s = CIRCLEQ_NEXT(s, r_link))
@@ -138,7 +140,7 @@ rman_manage_region(struct rman *rm, u_long start, u_long end)
                CIRCLEQ_INSERT_BEFORE(&rm->rm_list, s, r, r_link);
        }
 
-       lwkt_reltoken(rm->rm_slock);
+       lwkt_reltoken(&ilock);
        return 0;
 }
 
@@ -146,11 +148,12 @@ int
 rman_fini(struct rman *rm)
 {
        struct resource *r;
+       lwkt_tokref ilock;
 
-       lwkt_gettoken(rm->rm_slock);
+       lwkt_gettoken(&ilock, rm->rm_slock);
        CIRCLEQ_FOREACH(r, &rm->rm_list, r_link) {
                if (r->r_flags & RF_ALLOCATED) {
-                       lwkt_reltoken(rm->rm_slock);
+                       lwkt_reltoken(&ilock);
                        return EBUSY;
                }
        }
@@ -164,10 +167,11 @@ rman_fini(struct rman *rm)
                CIRCLEQ_REMOVE(&rm->rm_list, r, r_link);
                free(r, M_RMAN);
        }
-       lwkt_reltoken(rm->rm_slock);
-       lwkt_gettoken(&rman_tok);
+       lwkt_reltoken(&ilock);
+       /* XXX what's the point of this if we are going to free the struct? */
+       lwkt_gettoken(&ilock, &rman_tok);
        TAILQ_REMOVE(&rman_head, rm, rm_link);
-       lwkt_reltoken(&rman_tok);
+       lwkt_reltoken(&ilock);
        free(rm->rm_slock, M_RMAN);
 
        return 0;
@@ -180,6 +184,7 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count,
        u_int   want_activate;
        struct  resource *r, *s, *rv;
        u_long  rstart, rend;
+       lwkt_tokref ilock;
 
        rv = 0;
 
@@ -191,7 +196,7 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count,
        want_activate = (flags & RF_ACTIVE);
        flags &= ~RF_ACTIVE;
 
-       lwkt_gettoken(rm->rm_slock);
+       lwkt_gettoken(&ilock, rm->rm_slock);
 
        for (r = CIRCLEQ_FIRST(&rm->rm_list); 
             !CIRCLEQ_TERMCOND(r, rm->rm_list) && r->r_end < start;
@@ -396,8 +401,7 @@ out:
                        rv = 0;
                }
        }
-                       
-       lwkt_reltoken(rm->rm_slock);
+       lwkt_reltoken(&ilock);
        return (rv);
 }
 
@@ -441,17 +445,21 @@ rman_activate_resource(struct resource *r)
 {
        int rv;
        struct resource *whohas;
+       lwkt_tokref ilock;
        struct rman *rm;
 
        rm = r->r_rm;
-       lwkt_gettoken(rm->rm_slock);
+       lwkt_gettoken(&ilock, rm->rm_slock);
        rv = int_rman_activate_resource(rm, r, &whohas);
-       lwkt_reltoken(rm->rm_slock);
+       lwkt_reltoken(&ilock);
        return rv;
 }
 
+#if 0
+
+/* XXX */
 int
-rman_await_resource(struct resource *r, int slpflags, int timo)
+rman_await_resource(struct resource *r, lwkt_tokref_t ilock, int slpflags, int timo)
 {
        int     rv, s;
        struct  resource *whohas;
@@ -459,10 +467,10 @@ rman_await_resource(struct resource *r, int slpflags, int timo)
 
        rm = r->r_rm;
        for (;;) {
-               lwkt_gettoken(rm->rm_slock);
+               lwkt_gettoken(ilock, rm->rm_slock);
                rv = int_rman_activate_resource(rm, r, &whohas);
                if (rv != EBUSY)
-                       return (rv);    /* returns with simple token */
+                       return (rv);    /* returns with ilock held */
 
                if (r->r_sharehead == 0)
                        panic("rman_await_resource");
@@ -474,17 +482,18 @@ rman_await_resource(struct resource *r, int slpflags, int timo)
                 */
                s = splhigh();
                whohas->r_flags |= RF_WANTED;
-               lwkt_reltoken(rm->rm_slock);    /* YYY */
                rv = tsleep(r->r_sharehead, slpflags, "rmwait", timo);
                if (rv) {
+                       lwkt_reltoken(ilock);
                        splx(s);
                        return rv;
                }
-               lwkt_gettoken(rm->rm_slock);
                splx(s);
        }
 }
 
+#endif
+
 static int
 int_rman_deactivate_resource(struct resource *r)
 {
@@ -502,12 +511,13 @@ int_rman_deactivate_resource(struct resource *r)
 int
 rman_deactivate_resource(struct resource *r)
 {
-       struct  rman *rm;
+       lwkt_tokref ilock;
+       struct rman *rm;
 
        rm = r->r_rm;
-       lwkt_gettoken(rm->rm_slock);
+       lwkt_gettoken(&ilock, rm->rm_slock);
        int_rman_deactivate_resource(r);
-       lwkt_reltoken(rm->rm_slock);
+       lwkt_reltoken(&ilock);
        return 0;
 }
 
@@ -602,12 +612,13 @@ out:
 int
 rman_release_resource(struct resource *r)
 {
-       int     rv;
        struct  rman *rm = r->r_rm;
+       lwkt_tokref ilock;
+       int     rv;
 
-       lwkt_gettoken(rm->rm_slock);
+       lwkt_gettoken(&ilock, rm->rm_slock);
        rv = int_rman_release_resource(rm, r);
-       lwkt_reltoken(rm->rm_slock);
+       lwkt_reltoken(&ilock);
        return (rv);
 }
 
index abc1b1d..84af7f7 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     @(#)tty_tty.c   8.2 (Berkeley) 9/23/93
  * $FreeBSD: src/sys/kern/tty_tty.c,v 1.30 1999/09/25 18:24:24 phk Exp $
- * $DragonFly: src/sys/kern/tty_tty.c,v 1.6 2003/08/26 21:09:02 rob Exp $
+ * $DragonFly: src/sys/kern/tty_tty.c,v 1.7 2004/03/01 06:33:17 dillon Exp $
  */
 
 /*
@@ -90,7 +90,7 @@ cttyopen(dev_t dev, int flag, int mode, struct thread *td)
 
        if (ttyvp == NULL)
                return (ENXIO);
-       vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(ttyvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 #ifdef PARANOID
        /*
         * Since group is tty and mode is 620 on most terminal lines
@@ -105,7 +105,7 @@ cttyopen(dev_t dev, int flag, int mode, struct thread *td)
        if (!error)
 #endif /* PARANOID */
                error = VOP_OPEN(ttyvp, flag, NOCRED, td);
-       VOP_UNLOCK(ttyvp, 0, td);
+       VOP_UNLOCK(ttyvp, NULL, 0, td);
        return (error);
 }
 
@@ -125,9 +125,9 @@ cttyread(dev, uio, flag)
        ttyvp = cttyvp(p);
        if (ttyvp == NULL)
                return (EIO);
-       vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(ttyvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        error = VOP_READ(ttyvp, uio, flag, NOCRED);
-       VOP_UNLOCK(ttyvp, 0, td);
+       VOP_UNLOCK(ttyvp, NULL, 0, td);
        return (error);
 }
 
@@ -147,9 +147,9 @@ cttywrite(dev, uio, flag)
        ttyvp = cttyvp(p);
        if (ttyvp == NULL)
                return (EIO);
-       vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(ttyvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        error = VOP_WRITE(ttyvp, uio, flag, NOCRED);
-       VOP_UNLOCK(ttyvp, 0, td);
+       VOP_UNLOCK(ttyvp, NULL, 0, td);
        return (error);
 }
 
index a7408bb..f95d1f8 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)uipc_syscalls.c     8.4 (Berkeley) 2/21/94
  * $FreeBSD: src/sys/kern/uipc_syscalls.c,v 1.65.2.17 2003/04/04 17:11:16 tegge Exp $
- * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.23 2003/12/20 05:53:59 dillon Exp $
+ * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.24 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include "opt_ktrace.h"
@@ -1484,11 +1484,11 @@ retry_lookup:
                        auio.uio_segflg = UIO_NOCOPY;
                        auio.uio_rw = UIO_READ;
                        auio.uio_td = td;
-                       vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, td);
+                       vn_lock(vp, NULL, LK_SHARED | LK_NOPAUSE | LK_RETRY, td);
                        error = VOP_READ(vp, &auio, 
                                    IO_VMIO | ((MAXBSIZE / bsize) << 16),
                                    p->p_ucred);
-                       VOP_UNLOCK(vp, 0, td);
+                       VOP_UNLOCK(vp, NULL, 0, td);
                        vm_page_flag_clear(pg, PG_ZERO);
                        vm_page_io_finish(pg);
                        if (error) {
index 7301b07..7679c41 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94
  * $FreeBSD: src/sys/kern/uipc_usrreq.c,v 1.54.2.10 2003/03/04 17:28:09 nectar Exp $
- * $DragonFly: src/sys/kern/uipc_usrreq.c,v 1.10 2003/10/09 22:27:19 dillon Exp $
+ * $DragonFly: src/sys/kern/uipc_usrreq.c,v 1.11 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -627,7 +627,7 @@ unp_bind(struct unpcb *unp, struct sockaddr *nam, struct thread *td)
        vp->v_socket = unp->unp_socket;
        unp->unp_vnode = vp;
        unp->unp_addr = (struct sockaddr_un *)dup_sockaddr(nam, 1);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return (0);
 }
 
index 118fef8..2d41546 100644 (file)
@@ -12,7 +12,7 @@
  *             John S. Dyson.
  *
  * $FreeBSD: src/sys/kern/vfs_bio.c,v 1.242.2.20 2003/05/28 18:38:10 alc Exp $
- * $DragonFly: src/sys/kern/vfs_bio.c,v 1.18 2004/02/16 19:37:48 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_bio.c,v 1.19 2004/03/01 06:33:17 dillon Exp $
  */
 
 /*
@@ -351,7 +351,7 @@ bufinit(void)
 
        TAILQ_INIT(&bswlist);
        LIST_INIT(&invalhash);
-       lwkt_inittoken(&buftimetoken);
+       lwkt_token_init(&buftimetoken);
 
        for (i = 0; i <= bufhashmask; i++)
                LIST_INIT(&bufhashtbl[i]);
index 5132230..876b66c 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95
  * $FreeBSD: src/sys/kern/vfs_cache.c,v 1.42.2.6 2001/10/05 20:07:03 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_cache.c,v 1.12 2003/10/18 05:53:57 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_cache.c,v 1.13 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -792,17 +792,17 @@ vfs_cache_lookup(struct vop_lookup_args *ap)
                VREF(vp);
                error = 0;
        } else if (flags & CNP_ISDOTDOT) {
-               VOP_UNLOCK(dvp, 0, td);
+               VOP_UNLOCK(dvp, NULL, 0, td);
                cnp->cn_flags |= CNP_PDIRUNLOCK;
-               error = vget(vp, LK_EXCLUSIVE, td);
+               error = vget(vp, NULL, LK_EXCLUSIVE, td);
                if (!error && lockparent && (flags & CNP_ISLASTCN)) {
-                       if ((error = vn_lock(dvp, LK_EXCLUSIVE, td)) == 0)
+                       if ((error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td)) == 0)
                                cnp->cn_flags &= ~CNP_PDIRUNLOCK;
                }
        } else {
-               error = vget(vp, LK_EXCLUSIVE, td);
+               error = vget(vp, NULL, LK_EXCLUSIVE, td);
                if (!lockparent || error || !(flags & CNP_ISLASTCN)) {
-                       VOP_UNLOCK(dvp, 0, td);
+                       VOP_UNLOCK(dvp, NULL, 0, td);
                        cnp->cn_flags |= CNP_PDIRUNLOCK;
                }
        }
@@ -815,12 +815,12 @@ vfs_cache_lookup(struct vop_lookup_args *ap)
                        return (0);
                vput(vp);
                if (lockparent && dvp != vp && (flags & CNP_ISLASTCN)) {
-                       VOP_UNLOCK(dvp, 0, td);
+                       VOP_UNLOCK(dvp, NULL, 0, td);
                        cnp->cn_flags |= CNP_PDIRUNLOCK;
                }
        }
        if (cnp->cn_flags & CNP_PDIRUNLOCK) {
-               error = vn_lock(dvp, LK_EXCLUSIVE, td);
+               error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
                if (error)
                        return (error);
                cnp->cn_flags &= ~CNP_PDIRUNLOCK;
index 03f5cd4..220ed69 100644 (file)
@@ -26,7 +26,7 @@
  * SUCH DAMAGE.
  *
  *     $FreeBSD: src/sys/kern/vfs_conf.c,v 1.49.2.5 2003/01/07 11:56:53 joerg Exp $
- *     $DragonFly: src/sys/kern/vfs_conf.c,v 1.6 2003/08/07 21:17:23 dillon Exp $
+ *     $DragonFly: src/sys/kern/vfs_conf.c,v 1.7 2004/03/01 06:33:17 dillon Exp $
  */
 
 /*
@@ -177,6 +177,7 @@ vfs_mountroot_try(char *mountfrom)
        char            *vfsname, *path;
        int             error;
        char            patt[32];
+       lwkt_tokref     ilock;
        int             s;
 
        vfsname = NULL;
@@ -235,9 +236,9 @@ done:
        } else {
 
                /* register with list of mounted filesystems */
-               lwkt_gettoken(&mountlist_token);
+               lwkt_gettoken(&ilock, &mountlist_token);
                TAILQ_INSERT_HEAD(&mountlist, mp, mnt_list);
-               lwkt_reltoken(&mountlist_token);
+               lwkt_reltoken(&ilock);
 
                /* sanity check system clock against root fs timestamp */
                inittodr(mp->mnt_time);
index bd1ad1e..88b8d22 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $
- * $DragonFly: src/sys/kern/vfs_default.c,v 1.8 2003/08/26 21:09:02 rob Exp $
+ * $DragonFly: src/sys/kern/vfs_default.c,v 1.9 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -241,6 +241,7 @@ int
 vop_stdlock(ap)
        struct vop_lock_args /* {
                struct vnode *a_vp;
+               lwkt_tokref_t a_vlock;
                int a_flags;
                struct proc *a_p;
        } */ *ap;
@@ -249,14 +250,14 @@ vop_stdlock(ap)
 
        if ((l = (struct lock *)ap->a_vp->v_data) == NULL) {
                if (ap->a_flags & LK_INTERLOCK)
-                       lwkt_reltoken(&ap->a_vp->v_interlock);
+                       lwkt_reltoken(ap->a_vlock);
                return 0;
        }
 
 #ifndef        DEBUG_LOCKS
-       return (lockmgr(l, ap->a_flags, &ap->a_vp->v_interlock, ap->a_td));
+       return (lockmgr(l, ap->a_flags, ap->a_vlock, ap->a_td));
 #else
-       return (debuglockmgr(l, ap->a_flags, &ap->a_vp->v_interlock, ap->a_td,
+       return (debuglockmgr(l, ap->a_flags, ap->a_vlock, ap->a_td,
            "vop_stdlock", ap->a_vp->filename, ap->a_vp->line));
 #endif
 }
@@ -265,6 +266,7 @@ int
 vop_stdunlock(ap)
        struct vop_unlock_args /* {
                struct vnode *a_vp;
+               lwkt_tokref_t a_vlock;
                int a_flags;
                struct thread *a_td;
        } */ *ap;
@@ -273,12 +275,11 @@ vop_stdunlock(ap)
 
        if ((l = (struct lock *)ap->a_vp->v_data) == NULL) {
                if (ap->a_flags & LK_INTERLOCK)
-                       lwkt_reltoken(&ap->a_vp->v_interlock);
+                       lwkt_reltoken(ap->a_vlock);
                return 0;
        }
 
-       return (lockmgr(l, ap->a_flags | LK_RELEASE,
-                   &ap->a_vp->v_interlock, ap->a_td));
+       return (lockmgr(l, ap->a_flags | LK_RELEASE, ap->a_vlock, ap->a_td));
 }
 
 int
@@ -355,6 +356,7 @@ int
 vop_sharedlock(ap)
        struct vop_lock_args /* {
                struct vnode *a_vp;
+               lwkt_tokref_t a_vlock;
                int a_flags;
                struct proc *a_p;
        } */ *ap;
@@ -379,7 +381,7 @@ vop_sharedlock(ap)
 
        if (l == NULL) {
                if (ap->a_flags & LK_INTERLOCK)
-                       lwkt_reltoken(&ap->a_vp->v_interlock);
+                       lwkt_reltoken(ap->a_vlock);
                return 0;
        }
        switch (flags & LK_TYPE_MASK) {
@@ -409,9 +411,9 @@ vop_sharedlock(ap)
        if (flags & LK_INTERLOCK)
                vnflags |= LK_INTERLOCK;
 #ifndef        DEBUG_LOCKS
-       return (lockmgr(l, vnflags, &vp->v_interlock, ap->a_td));
+       return (lockmgr(l, vnflags, ap->a_vlock, ap->a_td));
 #else
-       return (debuglockmgr(l, vnflags, &vp->v_interlock, ap->a_td,
+       return (debuglockmgr(l, vnflags, ap->a_vlock, ap->a_td,
            "vop_sharedlock", vp->filename, vp->line));
 #endif
 }
@@ -426,6 +428,7 @@ int
 vop_nolock(ap)
        struct vop_lock_args /* {
                struct vnode *a_vp;
+               lwkt_tokref_t a_vlock;
                int a_flags;
                struct proc *a_p;
        } */ *ap;
@@ -466,14 +469,14 @@ vop_nolock(ap)
        }
        if (flags & LK_INTERLOCK)
                vnflags |= LK_INTERLOCK;
-       return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p));
+       return(lockmgr(vp->v_vnlock, vnflags, ap->a_vlock, ap->a_p));
 #else /* for now */
        /*
         * Since we are not using the lock manager, we must clear
         * the interlock here.
         */
        if (ap->a_flags & LK_INTERLOCK)
-               lwkt_reltoken(&ap->a_vp->v_interlock);
+               lwkt_reltoken(ap->a_vlock);
        return (0);
 #endif
 }
@@ -485,12 +488,13 @@ int
 vop_nounlock(ap)
        struct vop_unlock_args /* {
                struct vnode *a_vp;
+               lwkt_tokref_t a_vlock;
                int a_flags;
                struct proc *a_p;
        } */ *ap;
 {
        if (ap->a_flags & LK_INTERLOCK)
-               lwkt_reltoken(&ap->a_vp->v_interlock);
+               lwkt_reltoken(ap->a_vlock);
        return (0);
 }
 
@@ -547,9 +551,9 @@ retry:
                vp->v_usecount--;
        } else {
                if (object->flags & OBJ_DEAD) {
-                       VOP_UNLOCK(vp, 0, td);
+                       VOP_UNLOCK(vp, NULL, 0, td);
                        tsleep(object, 0, "vodead", 0);
-                       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+                       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
                        goto retry;
                }
        }
index 51fb99b..17bb8b6 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_lookup.c        8.4 (Berkeley) 2/16/94
  * $FreeBSD: src/sys/kern/vfs_lookup.c,v 1.38.2.3 2001/08/31 19:36:49 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_lookup.c,v 1.9 2003/11/09 20:29:59 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_lookup.c,v 1.10 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include "opt_ktrace.h"
@@ -182,7 +182,7 @@ namei(struct nameidata *ndp)
                        return (0);
                }
                if ((cnp->cn_flags & CNP_LOCKPARENT) && ndp->ni_pathlen == 1)
-                       VOP_UNLOCK(ndp->ni_dvp, 0, cnp->cn_td);
+                       VOP_UNLOCK(ndp->ni_dvp, NULL, 0, cnp->cn_td);
                if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
                        error = ELOOP;
                        break;
@@ -314,7 +314,7 @@ lookup(struct nameidata *ndp)
        cnp->cn_flags &= ~CNP_ISSYMLINK;
        dp = ndp->ni_startdir;
        ndp->ni_startdir = NULLVP;
-       vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 dirloop:
        /*
@@ -394,7 +394,7 @@ dirloop:
                }
                ndp->ni_vp = dp;
                if (!(cnp->cn_flags & (CNP_LOCKPARENT | CNP_LOCKLEAF)))
-                       VOP_UNLOCK(dp, 0, cnp->cn_td);
+                       VOP_UNLOCK(dp, NULL, 0, cnp->cn_td);
                /* XXX This should probably move to the top of function. */
                if (cnp->cn_flags & CNP_SAVESTART)
                        panic("lookup: CNP_SAVESTART");
@@ -434,7 +434,7 @@ dirloop:
                        dp = dp->v_mount->mnt_vnodecovered;
                        vput(tdp);
                        VREF(dp);
-                       vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+                       vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
                }
        }
 
@@ -461,7 +461,7 @@ unionlookup:
                        else
                                vput(tdp);
                        VREF(dp);
-                       vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+                       vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
                        goto unionlookup;
                }
 
@@ -516,9 +516,9 @@ unionlookup:
         */
        while (dp->v_type == VDIR && (mp = dp->v_mountedhere) &&
               (cnp->cn_flags & CNP_NOCROSSMOUNT) == 0) {
-               if (vfs_busy(mp, 0, 0, td))
+               if (vfs_busy(mp, 0, NULL, td))
                        continue;
-               VOP_UNLOCK(dp, 0, td);
+               VOP_UNLOCK(dp, NULL, 0, td);
                error = VFS_ROOT(mp, &tdp);
                vfs_unbusy(mp, td);
                if (error) {
@@ -590,13 +590,13 @@ nextname:
                vrele(ndp->ni_dvp);
 
        if ((cnp->cn_flags & CNP_LOCKLEAF) == 0)
-               VOP_UNLOCK(dp, 0, td);
+               VOP_UNLOCK(dp, NULL, 0, td);
        return (0);
 
 bad2:
        if ((cnp->cn_flags & (CNP_LOCKPARENT | CNP_PDIRUNLOCK)) == CNP_LOCKPARENT &&
            *ndp->ni_next == '\0')
-               VOP_UNLOCK(ndp->ni_dvp, 0, td);
+               VOP_UNLOCK(ndp->ni_dvp, NULL, 0, td);
        vrele(ndp->ni_dvp);
 bad:
        if (dpunlocked)
@@ -638,7 +638,7 @@ relookup(dvp, vpp, cnp)
        rdonly = cnp->cn_flags & CNP_RDONLY;
        cnp->cn_flags &= ~CNP_ISSYMLINK;
        dp = dvp;
-       vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(dp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
 /* dirloop: */
        /*
@@ -672,7 +672,7 @@ relookup(dvp, vpp, cnp)
                        goto bad;
                }
                if (!(cnp->cn_flags & CNP_LOCKLEAF))
-                       VOP_UNLOCK(dp, 0, td);
+                       VOP_UNLOCK(dp, NULL, 0, td);
                *vpp = dp;
                /* XXX This should probably move to the top of function. */
                if (cnp->cn_flags & CNP_SAVESTART)
@@ -736,12 +736,12 @@ relookup(dvp, vpp, cnp)
                vfs_object_create(dp, cnp->cn_td);
 
        if ((cnp->cn_flags & CNP_LOCKLEAF) == 0)
-               VOP_UNLOCK(dp, 0, td);
+               VOP_UNLOCK(dp, NULL, 0, td);
        return (0);
 
 bad2:
        if ((cnp->cn_flags & CNP_LOCKPARENT) && (cnp->cn_flags & CNP_ISLASTCN))
-               VOP_UNLOCK(dvp, 0, td);
+               VOP_UNLOCK(dvp, NULL, 0, td);
        vrele(dvp);
 bad:
        vput(dp);
index 543acee..97bc3db 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_subr.c  8.31 (Berkeley) 5/26/95
  * $FreeBSD: src/sys/kern/vfs_subr.c,v 1.249.2.30 2003/04/04 20:35:57 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_subr.c,v 1.25 2004/02/10 07:34:42 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_subr.c,v 1.26 2004/03/01 06:33:17 dillon Exp $
  */
 
 /*
@@ -87,9 +87,8 @@
 static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure");
 
 static void    insmntque (struct vnode *vp, struct mount *mp);
-static void    vclean (struct vnode *vp, int flags, struct thread *td);
+static void    vclean (struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td);
 static unsigned long   numvnodes;
-static void    vlruvp(struct vnode *vp);
 SYSCTL_INT(_debug, OID_AUTO, numvnodes, CTLFLAG_RD, &numvnodes, 0, "");
 
 enum vtype iftovt_tab[16] = {
@@ -175,6 +174,34 @@ static int vfs_free_netcred (struct radix_node *rn, void *w);
 static int     vfs_hang_addrlist (struct mount *mp, struct netexport *nep,
                                       struct export_args *argp);
 
+#define VSHOULDFREE(vp) \
+       (!((vp)->v_flag & (VFREE|VDOOMED)) && \
+        !(vp)->v_holdcnt && !(vp)->v_usecount && \
+        (!(vp)->v_object || \
+         !((vp)->v_object->ref_count || (vp)->v_object->resident_page_count)))
+#define VMIGHTFREE(vp) \
+       (((vp)->v_flag & (VFREE|VDOOMED|VXLOCK)) == 0 &&   \
+        cache_leaf_test(vp) == 0 && (vp)->v_usecount == 0)
+#define VSHOULDBUSY(vp) \
+       (((vp)->v_flag & VFREE) && \
+        ((vp)->v_holdcnt || (vp)->v_usecount))
+
+static void vbusy(struct vnode *vp);
+static void vfree(struct vnode *vp);
+static void vmaybefree(struct vnode *vp);
+
+/*
+ * NOTE: the vnode interlock must be held on call.
+ */
+static __inline void
+vmaybefree(struct vnode *vp)
+{
+       if (VSHOULDFREE(vp))
+               vfree(vp);
+}
 /*
  * Initialize the vnode management data structures.
  */
@@ -195,12 +222,12 @@ vntblinit()
                    (5 * (sizeof(struct vm_object) + sizeof(struct vnode))));
 
        minvnodes = desiredvnodes / 4;
-       lwkt_inittoken(&mountlist_token);
-       lwkt_inittoken(&mntvnode_token);
-       lwkt_inittoken(&mntid_token);
-       lwkt_inittoken(&spechash_token);
+       lwkt_token_init(&mountlist_token);
+       lwkt_token_init(&mntvnode_token);
+       lwkt_token_init(&mntid_token);
+       lwkt_token_init(&spechash_token);
        TAILQ_INIT(&vnode_free_list);
-       lwkt_inittoken(&vnode_free_list_token);
+       lwkt_token_init(&vnode_free_list_token);
        vnode_zone = zinit("VNODE", sizeof (struct vnode), 0, 0, 5);
        /*
         * Initialize the filesystem syncer.
@@ -215,8 +242,7 @@ vntblinit()
  * unmounting. Interlock is not released on failure.
  */
 int
-vfs_busy(struct mount *mp, int flags, struct lwkt_token *interlkp,
-       struct thread *td)
+vfs_busy(struct mount *mp, int flags, lwkt_tokref_t interlkp, struct thread *td)
 {
        int lkflags;
 
@@ -224,19 +250,16 @@ vfs_busy(struct mount *mp, int flags, struct lwkt_token *interlkp,
                if (flags & LK_NOWAIT)
                        return (ENOENT);
                mp->mnt_kern_flag |= MNTK_MWAIT;
-               if (interlkp) {
-                       lwkt_reltoken(interlkp);
-               }
                /*
                 * Since all busy locks are shared except the exclusive
                 * lock granted when unmounting, the only place that a
                 * wakeup needs to be done is at the release of the
                 * exclusive lock at the end of dounmount.
+                *
+                * note: interlkp is a serializer and thus can be safely
+                * held through any sleep
                 */
                tsleep((caddr_t)mp, 0, "vfs_busy", 0);
-               if (interlkp) {
-                       lwkt_gettoken(interlkp);
-               }
                return (ENOENT);
        }
        lkflags = LK_SHARED | LK_NOPAUSE;
@@ -279,7 +302,7 @@ vfs_rootmountalloc(char *fstypename, char *devname, struct mount **mpp)
        mp = malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
        bzero((char *)mp, (u_long)sizeof(struct mount));
        lockinit(&mp->mnt_lock, 0, "vfslock", VLKTIMEOUT, LK_NOPAUSE);
-       (void)vfs_busy(mp, LK_NOWAIT, 0, td);
+       vfs_busy(mp, LK_NOWAIT, NULL, td);
        TAILQ_INIT(&mp->mnt_nvnodelist);
        TAILQ_INIT(&mp->mnt_reservedvnlist);
        mp->mnt_nvnodelistsize = 0;
@@ -334,17 +357,17 @@ vfs_getvfs(fsid)
        fsid_t *fsid;
 {
        struct mount *mp;
+       lwkt_tokref ilock;
 
-       lwkt_gettoken(&mountlist_token);
+       lwkt_gettoken(&ilock, &mountlist_token);
        TAILQ_FOREACH(mp, &mountlist, mnt_list) {
                if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] &&
                    mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) {
-                       lwkt_reltoken(&mountlist_token);
-                       return (mp);
+                       break;
            }
        }
-       lwkt_reltoken(&mountlist_token);
-       return ((struct mount *) 0);
+       lwkt_reltoken(&ilock);
+       return (mp);
 }
 
 /*
@@ -364,10 +387,11 @@ vfs_getnewfsid(mp)
        struct mount *mp;
 {
        static u_int16_t mntid_base;
+       lwkt_tokref ilock;
        fsid_t tfsid;
        int mtype;
 
-       lwkt_gettoken(&mntid_token);
+       lwkt_gettoken(&ilock, &mntid_token);
        mtype = mp->mnt_vfc->vfc_typenum;
        tfsid.val[1] = mtype;
        mtype = (mtype & 0xFF) << 24;
@@ -380,7 +404,7 @@ vfs_getnewfsid(mp)
        }
        mp->mnt_stat.f_fsid.val[0] = tfsid.val[0];
        mp->mnt_stat.f_fsid.val[1] = tfsid.val[1];
-       lwkt_reltoken(&mntid_token);
+       lwkt_reltoken(&ilock);
 }
 
 /*
@@ -474,11 +498,12 @@ static int
 vlrureclaim(struct mount *mp)
 {
        struct vnode *vp;
+       lwkt_tokref ilock;
+       lwkt_tokref vlock;
        int done;
        int trigger;
        int usevnodes;
        int count;
-       int gen;
 
        /*
         * Calculate the trigger point, don't allow user
@@ -493,32 +518,61 @@ vlrureclaim(struct mount *mp)
        trigger = vmstats.v_page_count * 2 / usevnodes;
 
        done = 0;
-       gen = lwkt_gettoken(&mntvnode_token);
+       lwkt_gettoken(&ilock, &mntvnode_token);
        count = mp->mnt_nvnodelistsize / 10 + 1;
        while (count && (vp = TAILQ_FIRST(&mp->mnt_nvnodelist)) != NULL) {
+               /*
+                * __VNODESCAN__
+                *
+                * The VP will stick around while we hold mntvnode_token,
+                * at least until we block, so we can safely do an initial
+                * check.  But we have to check again after obtaining
+                * the vnode interlock.  vp->v_interlock points to stable
+                * storage so it's ok if the vp gets ripped out from
+                * under us while we are blocked.
+                */
+               if (vp->v_type == VNON ||
+                   vp->v_type == VBAD ||
+                   !VMIGHTFREE(vp) ||          /* critical path opt */
+                   (vp->v_object &&
+                    vp->v_object->resident_page_count >= trigger)
+               ) {
+                       TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
+                       TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist,vp, v_nmntvnodes);
+                       --count;
+                       continue;
+               }
+
+               /*
+                * Get the interlock, delay moving the node to the tail so
+                * we don't race against new additions to the mountlist.
+                */
+               lwkt_gettoken(&vlock, vp->v_interlock);
+               if (TAILQ_FIRST(&mp->mnt_nvnodelist) != vp) {
+                       lwkt_reltoken(&vlock);
+                       continue;
+               }
                TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
-               TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
+               TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist,vp, v_nmntvnodes);
 
-               if (vp->v_type != VNON &&
-                   vp->v_type != VBAD &&
-                   VMIGHTFREE(vp) &&           /* critical path opt */
-                   (vp->v_object == NULL || vp->v_object->resident_page_count < trigger)
+               /*
+                * Must check again
+                */
+               if (vp->v_type == VNON ||
+                   vp->v_type == VBAD ||
+                   !VMIGHTFREE(vp) ||          /* critical path opt */
+                   (vp->v_object &&
+                    vp->v_object->resident_page_count >= trigger)
                ) {
-                       lwkt_gettoken(&vp->v_interlock);
-                       if (lwkt_gentoken(&mntvnode_token, &gen) == 0) {
-                               if (VMIGHTFREE(vp)) {
-                                       vgonel(vp, curthread);
-                                       done++;
-                               } else {
-                                       lwkt_reltoken(&vp->v_interlock);
-                               }
-                       } else {
-                               lwkt_reltoken(&vp->v_interlock);
-                       }
+                       lwkt_reltoken(&vlock);
+                       --count;
+                       continue;
                }
+               vgonel(vp, &vlock, curthread);
+               ++done;
                --count;
        }
-       lwkt_reltoken(&mntvnode_token);
+       lwkt_reltoken(&ilock);
        return done;
 }
 
@@ -534,6 +588,7 @@ static void
 vnlru_proc(void)
 {
        struct mount *mp, *nmp;
+       lwkt_tokref ilock;
        int s;
        int done;
        struct thread *td = curthread;
@@ -551,18 +606,18 @@ vnlru_proc(void)
                        continue;
                }
                done = 0;
-               lwkt_gettoken(&mountlist_token);
+               lwkt_gettoken(&ilock, &mountlist_token);
                for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-                       if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, td)) {
+                       if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
                                nmp = TAILQ_NEXT(mp, mnt_list);
                                continue;
                        }
                        done += vlrureclaim(mp);
-                       lwkt_gettoken(&mountlist_token);
+                       lwkt_gettokref(&ilock);
                        nmp = TAILQ_NEXT(mp, mnt_list);
                        vfs_unbusy(mp, td);
                }
-               lwkt_reltoken(&mountlist_token);
+               lwkt_reltoken(&ilock);
                if (done == 0) {
                        vnlru_nowhere++;
                        tsleep(td, 0, "vlrup", hz * 3);
@@ -594,11 +649,12 @@ getnewvnode(tag, mp, vops, vpp)
        struct vnode **vpp;
 {
        int s;
-       int gen;
-       int vgen;
        struct thread *td = curthread;  /* XXX */
        struct vnode *vp = NULL;
+       struct vnode *xvp;
        vm_object_t object;
+       lwkt_tokref ilock;
+       lwkt_tokref vlock;
 
        s = splbio();
 
@@ -622,96 +678,114 @@ getnewvnode(tag, mp, vops, vpp)
         * a new vnode if we can't find one or if we have not reached a
         * good minimum for good LRU performance.
         */
-       gen = lwkt_gettoken(&vnode_free_list_token);
+       lwkt_gettoken(&ilock, &vnode_free_list_token);
        if (freevnodes >= wantfreevnodes && numvnodes >= minvnodes) {
                int count;
 
                for (count = 0; count < freevnodes; count++) {
+                       /*
+                        * __VNODESCAN__
+                        *
+                        * Pull the next vnode off the free list and do some
+                        * sanity checks.  Note that regardless of how we
+                        * block, if freevnodes is non-zero there had better
+                        * be something on the list.
+                        */
                        vp = TAILQ_FIRST(&vnode_free_list);
-                       if (vp == NULL || vp->v_usecount)
+                       if (vp == NULL)
                                panic("getnewvnode: free vnode isn't");
 
                        /*
-                        * Get the vnode's interlock, then re-obtain 
-                        * vnode_free_list_token in case we lost it.  If we
-                        * did lose it while getting the vnode interlock,
-                        * even if we got it back again, then retry.
+                        * Move the vnode to the end of the list so other
+                        * processes do not double-block trying to recycle
+                        * the same vnode (as an optimization), then get
+                        * the interlock.
                         */
-                       vgen = lwkt_gettoken(&vp->v_interlock);
-                       if (lwkt_gentoken(&vnode_free_list_token, &gen) != 0) {
-                               --count;
-                               lwkt_reltoken(&vp->v_interlock);
+                       TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
+                       TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+
+                       /*
+                        * Skip vnodes that are in the process of being
+                        * held or referenced.  Since the act of adding or
+                        * removing a vnode on the freelist requires a token
+                        * and may block, the ref count may be adjusted
+                        * prior to its addition or removal.
+                        */
+                       if (VSHOULDBUSY(vp)) {
                                vp = NULL;
                                continue;
                        }
 
+
                        /*
-                        * Whew!  We have both tokens.  Since we didn't lose
-                        * the free list VFREE had better still be set.  But
-                        * we aren't out of the woods yet.  We have to get
-                        * the object (may block).  If the vnode is not 
-                        * suitable then move it to the end of the list
-                        * if we can.  If we can't move it to the end of the
-                        * list retry again.
+                        * Obtain the vnode interlock and check that the
+                        * vnode is still on the free list.
+                        *
+                        * This normally devolves into a degenerate case so
+                        * it is optimal.   Loop up if it isn't.  Note that
+                        * the vnode could be in the middle of being moved
+                        * off the free list (the VSHOULDBUSY() check) and
+                        * must be skipped if so.
                         */
-                       if ((VOP_GETVOBJECT(vp, &object) == 0 &&
-                           (object->resident_page_count || object->ref_count))
-                       ) {
-                               if (lwkt_gentoken(&vp->v_interlock, &vgen) == 0 &&
-                                  lwkt_gentoken(&vnode_free_list_token, &gen) == 0
-                               ) {
-                                       TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
-                                       TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
-                               } else {
-                                       --count;
-                               }
-                               lwkt_reltoken(&vp->v_interlock);
+                       lwkt_gettoken(&vlock, vp->v_interlock);
+                       TAILQ_FOREACH_REVERSE(xvp, &vnode_free_list, 
+                           freelst, v_freelist) {
+                               if (vp == xvp)
+                                       break;
+                       }
+                       if (vp != xvp || VSHOULDBUSY(vp)) {
                                vp = NULL;
                                continue;
                        }
 
                        /*
-                        * Still not out of the woods.  VOBJECT might have
-                        * blocked, if we did not retain our tokens we have
-                        * to retry.
+                        * We now safely own the vnode.  If the vnode has
+                        * an object do not recycle it if its VM object
+                        * has resident pages or references.
                         */
-                       if (lwkt_gentoken(&vp->v_interlock, &vgen) != 0 ||
-                           lwkt_gentoken(&vnode_free_list_token, &gen) != 0) {
-                               --count;
+                       if ((VOP_GETVOBJECT(vp, &object) == 0 &&
+                           (object->resident_page_count || object->ref_count))
+                       ) {
+                               lwkt_reltoken(&vlock);
                                vp = NULL;
                                continue;
                        }
-                       TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
-                       KKASSERT(vp->v_flag & VFREE);
 
                        /*
-                        * If we have children in the namecache we cannot
-                        * reuse the vnode yet because it will break the
-                        * namecache chain (YYY use nc_refs for the check?)
+                        * We can almost reuse this vnode.  But we don't want
+                        * to recycle it if the vnode has children in the
+                        * namecache because that breaks the namecache's
+                        * path element chain.  (YYY use nc_refs for the
+                        * check?)
                         */
-                       if (TAILQ_FIRST(&vp->v_namecache)) {
-                               if (cache_leaf_test(vp) < 0) {
-                                       lwkt_reltoken(&vp->v_interlock);
-                                       TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
-                                       vp = NULL;
-                                       continue;
-                               }
+                       KKASSERT(vp->v_flag & VFREE);
+                       TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
+
+                       if (TAILQ_FIRST(&vp->v_namecache) == NULL ||
+                           cache_leaf_test(vp) >= 0) {
+                               /* ok, we can reuse this vnode */
+                               break;
                        }
-                       break;
+                       lwkt_reltoken(&vlock);
+                       TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+                       vp = NULL;
                }
        }
 
+       /*
+        * If vp is non-NULL we hold it's interlock.
+        */
        if (vp) {
                vp->v_flag |= VDOOMED;
                vp->v_flag &= ~VFREE;
                freevnodes--;
-               lwkt_reltoken(&vnode_free_list_token);
+               lwkt_reltoken(&ilock);
                cache_purge(vp);        /* YYY may block */
                vp->v_lease = NULL;
                if (vp->v_type != VBAD) {
-                       vgonel(vp, td);
+                       vgonel(vp, &vlock, td);
                } else {
-                       lwkt_reltoken(&vp->v_interlock);
+                       lwkt_reltoken(&vlock);
                }
 
 #ifdef INVARIANTS
@@ -734,11 +808,11 @@ getnewvnode(tag, mp, vops, vpp)
                vp->v_socket = 0;
                vp->v_writecount = 0;   /* XXX */
        } else {
-               lwkt_reltoken(&vnode_free_list_token);
-               vp = (struct vnode *) zalloc(vnode_zone);
-               bzero((char *) vp, sizeof *vp);
-               lwkt_inittoken(&vp->v_interlock);
-               lwkt_inittoken(&vp->v_pollinfo.vpi_token);
+               lwkt_reltoken(&ilock);
+               vp = zalloc(vnode_zone);
+               bzero(vp, sizeof(*vp));
+               vp->v_interlock = lwkt_token_pool_get(vp);
+               lwkt_token_init(&vp->v_pollinfo.vpi_token);
                vp->v_dd = vp;
                cache_purge(vp);
                TAILQ_INIT(&vp->v_namecache);
@@ -768,8 +842,9 @@ insmntque(vp, mp)
        struct vnode *vp;
        struct mount *mp;
 {
+       lwkt_tokref ilock;
 
-       lwkt_gettoken(&mntvnode_token);
+       lwkt_gettoken(&ilock, &mntvnode_token);
        /*
         * Delete from old mount point vnode list, if on one.
         */
@@ -783,12 +858,12 @@ insmntque(vp, mp)
         * Insert into list of vnodes for the new mount point, if available.
         */
        if ((vp->v_mount = mp) == NULL) {
-               lwkt_reltoken(&mntvnode_token);
+               lwkt_reltoken(&ilock);
                return;
        }
        TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
        mp->mnt_nvnodelistsize++;
-       lwkt_reltoken(&mntvnode_token);
+       lwkt_reltoken(&ilock);
 }
 
 /*
@@ -824,6 +899,7 @@ vinvalbuf(struct vnode *vp, int flags, struct thread *td,
        struct buf *nbp, *blist;
        int s, error;
        vm_object_t object;
+       lwkt_tokref vlock;
 
        if (flags & V_SAVE) {
                s = splbio();
@@ -920,12 +996,12 @@ vinvalbuf(struct vnode *vp, int flags, struct thread *td,
        /*
         * Destroy the copy in the VM cache, too.
         */
-       lwkt_gettoken(&vp->v_interlock);
+       lwkt_gettoken(&vlock, vp->v_interlock);
        if (VOP_GETVOBJECT(vp, &object) == 0) {
                vm_object_page_remove(object, 0, 0,
                        (flags & V_SAVE) ? TRUE : FALSE);
        }
-       lwkt_reltoken(&vp->v_interlock);
+       lwkt_reltoken(&vlock);
 
        if (!TAILQ_EMPTY(&vp->v_dirtyblkhd) || !TAILQ_EMPTY(&vp->v_cleanblkhd))
                panic("vinvalbuf: flush failed");
@@ -1186,9 +1262,9 @@ sched_sync(void)
 
                while ((vp = LIST_FIRST(slp)) != NULL) {
                        if (VOP_ISLOCKED(vp, NULL) == 0) {
-                               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+                               vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
                                (void) VOP_FSYNC(vp, MNT_LAZY, td);
-                               VOP_UNLOCK(vp, 0, td);
+                               VOP_UNLOCK(vp, NULL, 0, td);
                        }
                        s = splbio();
                        if (LIST_FIRST(slp) == vp) {
@@ -1516,14 +1592,15 @@ addaliasu(struct vnode *nvp, udev_t nvp_rdev)
 void
 addalias(struct vnode *nvp, dev_t dev)
 {
+       lwkt_tokref ilock;
 
        if (nvp->v_type != VBLK && nvp->v_type != VCHR)
                panic("addalias on non-special vnode");
 
        nvp->v_rdev = dev;
-       lwkt_gettoken(&spechash_token);
+       lwkt_gettoken(&ilock, &spechash_token);
        SLIST_INSERT_HEAD(&dev->si_hlist, nvp, v_specnext);
-       lwkt_reltoken(&spechash_token);
+       lwkt_reltoken(&ilock);
 }
 
 /*
@@ -1533,50 +1610,58 @@ addalias(struct vnode *nvp, dev_t dev)
  * when the transition is completed, and an error returned to
  * indicate that the vnode is no longer usable (possibly having
  * been changed to a new file system type).
+ *
+ * This code is very sensitive.  We are depending on the vnode interlock
+ * to be maintained through to the vn_lock() call, which means that we
+ * cannot block which means that we cannot call vbusy() until after vn_lock().
+ * If the interlock is not maintained, the VXLOCK check will not properly
+ * interlock against a vclean()'s LK_DRAIN operation on the lock.
  */
 int
-vget(vp, flags, td)
-       struct vnode *vp;
-       int flags;
-       struct thread *td;
+vget(struct vnode *vp, lwkt_tokref_t vlock, int flags, thread_t td)
 {
        int error;
+       lwkt_tokref vvlock;
+
+       /*
+        * We need the interlock to safely modify the v_ fields.  ZZZ it is
+        * only legal to pass (1) the vnode's interlock and (2) only pass
+        * NULL w/o LK_INTERLOCK if the vnode is *ALREADY* referenced or
+        * held.
+        */
+       if ((flags & LK_INTERLOCK) == 0) {
+               lwkt_gettoken(&vvlock, vp->v_interlock);
+               vlock = &vvlock;
+       }
 
        /*
         * If the vnode is in the process of being cleaned out for
         * another use, we wait for the cleaning to finish and then
         * return failure. Cleaning is determined by checking that
-        * the VXLOCK flag is set.
+        * the VXLOCK flag is set.  It is possible for the vnode to be
+        * self-referenced during the cleaning operation.
         */
        if (vp->v_flag & VXLOCK) {
-               if (vp->v_vxproc == curproc) {
+               if (vp->v_vxthread == curthread) {
 #if 0
                        /* this can now occur in normal operation */
                        log(LOG_INFO, "VXLOCK interlock avoided\n");
 #endif
                } else {
                        vp->v_flag |= VXWANT;
+                       lwkt_reltoken(vlock);
                        tsleep((caddr_t)vp, 0, "vget", 0);
                        return (ENOENT);
                }
        }
 
        /*
-        * Bump v_usecount to prevent the vnode from being cleaned.  If the
-        * vnode gets cleaned unexpectedly we could wind up calling lockmgr
-        * on a lock embedded in an inode which is then ripped out from
-        * it.
+        * Bump v_usecount to prevent the vnode from being recycled.  The
+        * usecount needs to be bumped before we successfully get our lock.
         */
-       vp->v_usecount++;       /* XXX MP */
-
-       if ((flags & LK_INTERLOCK) == 0) {
-               lwkt_gettoken(&vp->v_interlock);
-       }
-
-       if (VSHOULDBUSY(vp))
-               vbusy(vp);
+       vp->v_usecount++;
        if (flags & LK_TYPE_MASK) {
-               if ((error = vn_lock(vp, flags | LK_INTERLOCK, td)) != 0) {
+               if ((error = vn_lock(vp, vlock, flags | LK_INTERLOCK, td)) != 0) {
                        /*
                         * must expand vrele here because we do not want
                         * to call VOP_INACTIVE if the reference count
@@ -1585,17 +1670,16 @@ vget(vp, flags, td)
                         * before sleeping so that multiple processes do
                         * not try to recycle it.
                         */
-                       lwkt_gettoken(&vp->v_interlock);
+                       lwkt_gettokref(vlock);
                        vp->v_usecount--;
-                       if (VSHOULDFREE(vp))
-                               vfree(vp);
-                       else
-                               vlruvp(vp);
-                       lwkt_reltoken(&vp->v_interlock);
+                       vmaybefree(vp);
+                       lwkt_reltoken(vlock);
                }
                return (error);
        }
-       lwkt_reltoken(&vp->v_interlock);
+       if (VSHOULDBUSY(vp))
+               vbusy(vp);      /* interlock must be held on call */
+       lwkt_reltoken(vlock);
        return (0);
 }
 
@@ -1613,39 +1697,36 @@ void
 vrele(struct vnode *vp)
 {
        struct thread *td = curthread;  /* XXX */
+       lwkt_tokref vlock;
 
        KASSERT(vp != NULL, ("vrele: null vp"));
 
-       lwkt_gettoken(&vp->v_interlock);
+       lwkt_gettoken(&vlock, vp->v_interlock);
 
        if (vp->v_usecount > 1) {
-
                vp->v_usecount--;
-               lwkt_reltoken(&vp->v_interlock);
-
+               lwkt_reltoken(&vlock);
                return;
        }
 
        if (vp->v_usecount == 1) {
                vp->v_usecount--;
                /*
-                * We must call VOP_INACTIVE with the node locked.
-                * If we are doing a vpu, the node is already locked,
-                * but, in the case of vrele, we must explicitly lock
-                * the vnode before calling VOP_INACTIVE
+                * We must call VOP_INACTIVE with the node locked and the
+                * usecount 0.  If we are doing a vpu, the node is already
+                * locked, but, in the case of vrele, we must explicitly lock
+                * the vnode before calling VOP_INACTIVE.
                 */
 
-               if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, td) == 0)
+               if (vn_lock(vp, NULL, LK_EXCLUSIVE, td) == 0)
                        VOP_INACTIVE(vp, td);
-               if (VSHOULDFREE(vp))
-                       vfree(vp);
-               else
-                       vlruvp(vp);
+               vmaybefree(vp);
+               lwkt_reltoken(&vlock);
        } else {
 #ifdef DIAGNOSTIC
                vprint("vrele: negative ref count", vp);
-               lwkt_reltoken(&vp->v_interlock);
 #endif
+               lwkt_reltoken(&vlock);
                panic("vrele: negative ref cnt");
        }
 }
@@ -1654,14 +1735,15 @@ void
 vput(struct vnode *vp)
 {
        struct thread *td = curthread;  /* XXX */
+       lwkt_tokref vlock;
 
        KASSERT(vp != NULL, ("vput: null vp"));
 
-       lwkt_gettoken(&vp->v_interlock);
+       lwkt_gettoken(&vlock, vp->v_interlock);
 
        if (vp->v_usecount > 1) {
                vp->v_usecount--;
-               VOP_UNLOCK(vp, LK_INTERLOCK, td);
+               VOP_UNLOCK(vp, &vlock, LK_INTERLOCK, td);
                return;
        }
 
@@ -1672,22 +1754,21 @@ vput(struct vnode *vp)
                 * If we are doing a vpu, the node is already locked,
                 * so we just need to release the vnode mutex.
                 */
-               lwkt_reltoken(&vp->v_interlock);
                VOP_INACTIVE(vp, td);
-               if (VSHOULDFREE(vp))
-                       vfree(vp);
-               else
-                       vlruvp(vp);
+               vmaybefree(vp);
+               lwkt_reltoken(&vlock);
        } else {
 #ifdef DIAGNOSTIC
                vprint("vput: negative ref count", vp);
 #endif
+               lwkt_reltoken(&vlock);
                panic("vput: negative ref cnt");
        }
 }
 
 /*
- * Somebody doesn't want the vnode recycled.
+ * Somebody doesn't want the vnode recycled. ZZZ vnode interlock should
+ * be held but isn't.
  */
 void
 vhold(vp)
@@ -1698,7 +1779,7 @@ vhold(vp)
        s = splbio();
        vp->v_holdcnt++;
        if (VSHOULDBUSY(vp))
-               vbusy(vp);
+               vbusy(vp);      /* interlock must be held on call */
        splx(s);
 }
 
@@ -1709,15 +1790,86 @@ void
 vdrop(vp)
        struct vnode *vp;
 {
-       int s;
+       lwkt_tokref vlock;
 
-       s = splbio();
+       lwkt_gettoken(&vlock, vp->v_interlock);
        if (vp->v_holdcnt <= 0)
                panic("vdrop: holdcnt");
        vp->v_holdcnt--;
-       if (VSHOULDFREE(vp))
-               vfree(vp);
-       splx(s);
+       vmaybefree(vp);
+       lwkt_reltoken(&vlock);
+}
+
+int
+vmntvnodescan(
+    struct mount *mp, 
+    int (*fastfunc)(struct mount *mp, struct vnode *vp, void *data),
+    int (*slowfunc)(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data),
+    void *data
+) {
+       lwkt_tokref ilock;
+       lwkt_tokref vlock;
+       struct vnode *pvp;
+       struct vnode *vp;
+       int r = 0;
+
+       /*
+        * Scan the vnodes on the mount's vnode list.  Use a placemarker
+        */
+       pvp = zalloc(vnode_zone);
+       pvp->v_flag |= VPLACEMARKER;
+
+       lwkt_gettoken(&ilock, &mntvnode_token);
+       TAILQ_INSERT_HEAD(&mp->mnt_nvnodelist, pvp, v_nmntvnodes);
+
+       while ((vp = TAILQ_NEXT(pvp, v_nmntvnodes)) != NULL) {
+               /*
+                * Move the placemarker and skip other placemarkers we
+                * encounter.  The nothing can get in our way so the
+                * mount point on the vp must be valid.
+                */
+               TAILQ_REMOVE(&mp->mnt_nvnodelist, pvp, v_nmntvnodes);
+               TAILQ_INSERT_AFTER(&mp->mnt_nvnodelist, vp, pvp, v_nmntvnodes);
+               if (vp->v_flag & VPLACEMARKER)
+                       continue;
+               KKASSERT(vp->v_mount == mp);
+
+               /*
+                * Quick test
+                */
+               if (fastfunc) {
+                       if ((r = fastfunc(mp, vp, data)) < 0)
+                               continue;
+                       if (r)
+                               break;
+               }
+
+               /*
+                * Get the vnodes interlock and make sure it is still on the
+                * mount list.  Skip it if it has moved (we may encounter it
+                * later).  Then do the with-interlock test.  The callback
+                * is responsible for releasing the vnode interlock.
+                *
+                * The interlock is type-stable.
+                */
+               if (slowfunc) {
+                       lwkt_gettoken(&vlock, vp->v_interlock);
+                       if (vp != TAILQ_PREV(pvp, vnodelst, v_nmntvnodes)) {
+                               printf("vmntvnodescan (debug info only): f=%p vp=%p vnode ripped out from under us\n", slowfunc, vp);
+                               lwkt_reltoken(&vlock);
+                               continue;
+                       }
+                       if ((r = slowfunc(mp, vp, &vlock, data)) != 0) {
+                               KKASSERT(lwkt_havetokref(&vlock) == 0);
+                               break;
+                       }
+                       KKASSERT(lwkt_havetokref(&vlock) == 0);
+               }
+       }
+       TAILQ_REMOVE(&mp->mnt_nvnodelist, pvp, v_nmntvnodes);
+       zfree(vnode_zone, pvp);
+       lwkt_reltoken(&ilock);
+       return(r);
 }
 
 /*
@@ -1745,6 +1897,14 @@ static int busyprt = 0;          /* print out busy vnodes */
 SYSCTL_INT(_debug, OID_AUTO, busyprt, CTLFLAG_RW, &busyprt, 0, "");
 #endif
 
+static int vflush_scan(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data);
+
+struct vflush_info {
+       int flags;
+       int busy;
+       thread_t td;
+};
+
 int
 vflush(mp, rootrefs, flags)
        struct mount *mp;
@@ -1752,9 +1912,10 @@ vflush(mp, rootrefs, flags)
        int flags;
 {
        struct thread *td = curthread;  /* XXX */
-       struct vnode *vp, *nvp, *rootvp = NULL;
-       struct vattr vattr;
-       int busy = 0, error;
+       struct vnode *rootvp = NULL;
+       int error;
+       lwkt_tokref vlock;
+       struct vflush_info vflush_info;
 
        if (rootrefs > 0) {
                KASSERT((flags & (SKIPSYSTEM | WRITECLOSE)) == 0,
@@ -1767,90 +1928,28 @@ vflush(mp, rootrefs, flags)
                        return (error);
                vput(rootvp);
        }
-       lwkt_gettoken(&mntvnode_token);
-loop:
-       for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp; vp = nvp) {
-               /*
-                * Make sure this vnode wasn't reclaimed in getnewvnode().
-                * Start over if it has (it won't be on the list anymore).
-                */
-               if (vp->v_mount != mp)
-                       goto loop;
-               nvp = TAILQ_NEXT(vp, v_nmntvnodes);
 
-               lwkt_gettoken(&vp->v_interlock);
-               /*
-                * Skip over a vnodes marked VSYSTEM.
-                */
-               if ((flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) {
-                       lwkt_reltoken(&vp->v_interlock);
-                       continue;
-               }
-               /*
-                * If WRITECLOSE is set, flush out unlinked but still open
-                * files (even if open only for reading) and regular file
-                * vnodes open for writing. 
-                */
-               if ((flags & WRITECLOSE) &&
-                   (vp->v_type == VNON ||
-                   (VOP_GETATTR(vp, &vattr, td) == 0 &&
-                   vattr.va_nlink > 0)) &&
-                   (vp->v_writecount == 0 || vp->v_type != VREG)) {
-                       lwkt_reltoken(&vp->v_interlock);
-                       continue;
-               }
+       vflush_info.busy = 0;
+       vflush_info.flags = flags;
+       vflush_info.td = td;
+       vmntvnodescan(mp, NULL, vflush_scan, &vflush_info);
 
-               /*
-                * With v_usecount == 0, all we need to do is clear out the
-                * vnode data structures and we are done.
-                */
-               if (vp->v_usecount == 0) {
-                       lwkt_reltoken(&mntvnode_token);
-                       vgonel(vp, td);
-                       lwkt_gettoken(&mntvnode_token);
-                       continue;
-               }
-
-               /*
-                * If FORCECLOSE is set, forcibly close the vnode. For block
-                * or character devices, revert to an anonymous device. For
-                * all other files, just kill them.
-                */
-               if (flags & FORCECLOSE) {
-                       lwkt_reltoken(&mntvnode_token);
-                       if (vp->v_type != VBLK && vp->v_type != VCHR) {
-                               vgonel(vp, td);
-                       } else {
-                               vclean(vp, 0, td);
-                               vp->v_op = spec_vnodeop_p;
-                               insmntque(vp, (struct mount *) 0);
-                       }
-                       lwkt_gettoken(&mntvnode_token);
-                       continue;
-               }
-#ifdef DIAGNOSTIC
-               if (busyprt)
-                       vprint("vflush: busy vnode", vp);
-#endif
-               lwkt_reltoken(&vp->v_interlock);
-               busy++;
-       }
-       lwkt_reltoken(&mntvnode_token);
        if (rootrefs > 0 && (flags & FORCECLOSE) == 0) {
                /*
                 * If just the root vnode is busy, and if its refcount
                 * is equal to `rootrefs', then go ahead and kill it.
                 */
-               lwkt_gettoken(&rootvp->v_interlock);
-               KASSERT(busy > 0, ("vflush: not busy"));
+               lwkt_gettoken(&vlock, rootvp->v_interlock);
+               KASSERT(vflush_info.busy > 0, ("vflush: not busy"));
                KASSERT(rootvp->v_usecount >= rootrefs, ("vflush: rootrefs"));
-               if (busy == 1 && rootvp->v_usecount == rootrefs) {
-                       vgonel(rootvp, td);
-                       busy = 0;
-               } else
-                       lwkt_reltoken(&rootvp->v_interlock);
+               if (vflush_info.busy == 1 && rootvp->v_usecount == rootrefs) {
+                       vgonel(rootvp, &vlock, td);
+                       vflush_info.busy = 0;
+               } else {
+                       lwkt_reltoken(&vlock);
+               }
        }
-       if (busy)
+       if (vflush_info.busy)
                return (EBUSY);
        for (; rootrefs > 0; rootrefs--)
                vrele(rootvp);
@@ -1858,32 +1957,74 @@ loop:
 }
 
 /*
- * We do not want to recycle the vnode too quickly.
- *
- * XXX we can't move vp's around the nvnodelist without really screwing
- * up the efficiency of filesystem SYNC and friends.  This code is 
- * disabled until we fix the syncing code's scanning algorithm.
+ * The scan callback is made with an interlocked vnode.
  */
-static void
-vlruvp(struct vnode *vp)
+static int
+vflush_scan(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data)
 {
-#if 0
-       struct mount *mp;
+       struct vflush_info *info = data;
+       struct vattr vattr;
 
-       if ((mp = vp->v_mount) != NULL) {
-               lwkt_gettoken(&mntvnode_token);
-               TAILQ_REMOVE(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
-               TAILQ_INSERT_TAIL(&mp->mnt_nvnodelist, vp, v_nmntvnodes);
-               lwkt_reltoken(&mntvnode_token);
+       /*
+        * Skip over a vnodes marked VSYSTEM.
+        */
+       if ((info->flags & SKIPSYSTEM) && (vp->v_flag & VSYSTEM)) {
+               lwkt_reltoken(vlock);
+               return(0);
+       }
+
+       /*
+        * If WRITECLOSE is set, flush out unlinked but still open
+        * files (even if open only for reading) and regular file
+        * vnodes open for writing. 
+        */
+       if ((info->flags & WRITECLOSE) &&
+           (vp->v_type == VNON ||
+           (VOP_GETATTR(vp, &vattr, info->td) == 0 &&
+           vattr.va_nlink > 0)) &&
+           (vp->v_writecount == 0 || vp->v_type != VREG)) {
+               lwkt_reltoken(vlock);
+               return(0);
+       }
+
+       /*
+        * With v_usecount == 0, all we need to do is clear out the
+        * vnode data structures and we are done.
+        */
+       if (vp->v_usecount == 0) {
+               vgonel(vp, vlock, info->td);
+               return(0);
+       }
+
+       /*
+        * If FORCECLOSE is set, forcibly close the vnode. For block
+        * or character devices, revert to an anonymous device. For
+        * all other files, just kill them.
+        */
+       if (info->flags & FORCECLOSE) {
+               if (vp->v_type != VBLK && vp->v_type != VCHR) {
+                       vgonel(vp, vlock, info->td);
+               } else {
+                       vclean(vp, vlock, 0, info->td);
+                       vp->v_op = spec_vnodeop_p;
+                       insmntque(vp, (struct mount *) 0);
+               }
+               return(0);
        }
+#ifdef DIAGNOSTIC
+       if (busyprt)
+               vprint("vflush: busy vnode", vp);
 #endif
+       lwkt_reltoken(vlock);
+       ++info->busy;
+       return(0);
 }
 
 /*
  * Disassociate the underlying file system from a vnode.
  */
 static void
-vclean(struct vnode *vp, int flags, struct thread *td)
+vclean(struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td)
 {
        int active;
 
@@ -1902,21 +2043,24 @@ vclean(struct vnode *vp, int flags, struct thread *td)
        if (vp->v_flag & VXLOCK)
                panic("vclean: deadlock");
        vp->v_flag |= VXLOCK;
-       vp->v_vxproc = curproc;
+       vp->v_vxthread = curthread;
+
        /*
         * Even if the count is zero, the VOP_INACTIVE routine may still
         * have the object locked while it cleans it out. The VOP_LOCK
         * ensures that the VOP_INACTIVE routine is done with its work.
         * For active vnodes, it ensures that no other activity can
         * occur while the underlying object is being cleaned out.
+        *
+        * NOTE: we continue to hold the vnode interlock through to the
+        * end of vclean().
         */
-       VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, td);
+       VOP_LOCK(vp, NULL, LK_DRAIN, td);
 
        /*
         * Clean out any buffers associated with the vnode.
         */
        vinvalbuf(vp, V_SAVE, td, 0, 0);
-
        VOP_DESTROYVOBJECT(vp);
 
        /*
@@ -1933,7 +2077,7 @@ vclean(struct vnode *vp, int flags, struct thread *td)
                 * Any other processes trying to obtain this lock must first
                 * wait for VXLOCK to clear, then call the new lock operation.
                 */
-               VOP_UNLOCK(vp, 0, td);
+               VOP_UNLOCK(vp, NULL, 0, td);
        }
        /*
         * Reclaim the vnode.
@@ -1946,7 +2090,6 @@ vclean(struct vnode *vp, int flags, struct thread *td)
                 * Inline copy of vrele() since VOP_INACTIVE
                 * has already been called.
                 */
-               lwkt_gettoken(&vp->v_interlock);
                if (--vp->v_usecount <= 0) {
 #ifdef DIAGNOSTIC
                        if (vp->v_usecount < 0 || vp->v_writecount != 0) {
@@ -1956,14 +2099,11 @@ vclean(struct vnode *vp, int flags, struct thread *td)
 #endif
                        vfree(vp);
                }
-               lwkt_reltoken(&vp->v_interlock);
        }
 
        cache_purge(vp);
        vp->v_vnlock = NULL;
-
-       if (VSHOULDFREE(vp))
-               vfree(vp);
+       vmaybefree(vp);
        
        /*
         * Done with purge, notify sleepers of the grim news.
@@ -1972,11 +2112,12 @@ vclean(struct vnode *vp, int flags, struct thread *td)
        vn_pollgone(vp);
        vp->v_tag = VT_NON;
        vp->v_flag &= ~VXLOCK;
-       vp->v_vxproc = NULL;
+       vp->v_vxthread = NULL;
        if (vp->v_flag & VXWANT) {
                vp->v_flag &= ~VXWANT;
                wakeup((caddr_t) vp);
        }
+       lwkt_reltoken(vlock);
 }
 
 /*
@@ -1991,6 +2132,7 @@ vop_revoke(ap)
        } */ *ap;
 {
        struct vnode *vp, *vq;
+       lwkt_tokref ilock;
        dev_t dev;
 
        KASSERT((ap->a_flags & REVOKEALL) != 0, ("vop_revoke"));
@@ -2002,15 +2144,15 @@ vop_revoke(ap)
         */
        if (vp->v_flag & VXLOCK) {
                vp->v_flag |= VXWANT;
-               lwkt_reltoken(&vp->v_interlock);
+               /*lwkt_reltoken(vlock); ZZZ */
                tsleep((caddr_t)vp, 0, "vop_revokeall", 0);
                return (0);
        }
        dev = vp->v_rdev;
        for (;;) {
-               lwkt_gettoken(&spechash_token);
+               lwkt_gettoken(&ilock, &spechash_token);
                vq = SLIST_FIRST(&dev->si_hlist);
-               lwkt_reltoken(&spechash_token);
+               lwkt_reltoken(&ilock);
                if (!vq)
                        break;
                vgone(vq);
@@ -2023,17 +2165,18 @@ vop_revoke(ap)
  * Release the passed interlock if the vnode will be recycled.
  */
 int
-vrecycle(struct vnode *vp, struct lwkt_token *inter_lkp, struct thread *td)
+vrecycle(struct vnode *vp, lwkt_tokref_t inter_lkp, struct thread *td)
 {
-       lwkt_gettoken(&vp->v_interlock);
+       lwkt_tokref vlock;
+
+       lwkt_gettoken(&vlock, vp->v_interlock);
        if (vp->v_usecount == 0) {
-               if (inter_lkp) {
+               if (inter_lkp)
                        lwkt_reltoken(inter_lkp);
-               }
-               vgonel(vp, td);
+               vgonel(vp, &vlock, td);
                return (1);
        }
-       lwkt_reltoken(&vp->v_interlock);
+       lwkt_reltoken(&vlock);
        return (0);
 }
 
@@ -2045,17 +2188,19 @@ void
 vgone(struct vnode *vp)
 {
        struct thread *td = curthread;  /* XXX */
+       lwkt_tokref vlock;
 
-       lwkt_gettoken(&vp->v_interlock);
-       vgonel(vp, td);
+       lwkt_gettoken(&vlock, vp->v_interlock);
+       vgonel(vp, &vlock, td);
 }
 
 /*
  * vgone, with the vp interlock held.
  */
 void
-vgonel(struct vnode *vp, struct thread *td)
+vgonel(struct vnode *vp, lwkt_tokref_t vlock, struct thread *td)
 {
+       lwkt_tokref ilock;
        int s;
 
        /*
@@ -2064,7 +2209,7 @@ vgonel(struct vnode *vp, struct thread *td)
         */
        if (vp->v_flag & VXLOCK) {
                vp->v_flag |= VXWANT;
-               lwkt_reltoken(&vp->v_interlock);
+               lwkt_reltoken(vlock);
                tsleep((caddr_t)vp, 0, "vgone", 0);
                return;
        }
@@ -2072,8 +2217,8 @@ vgonel(struct vnode *vp, struct thread *td)
        /*
         * Clean out the filesystem specific data.
         */
-       vclean(vp, DOCLOSE, td);
-       lwkt_gettoken(&vp->v_interlock);
+       vclean(vp, vlock, DOCLOSE, td);
+       lwkt_gettokref(vlock);
 
        /*
         * Delete from old mount point vnode list, if on one.
@@ -2085,10 +2230,10 @@ vgonel(struct vnode *vp, struct thread *td)
         * if it is on one.
         */
        if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_rdev != NULL) {
-               lwkt_gettoken(&spechash_token);
+               lwkt_gettoken(&ilock, &spechash_token);
                SLIST_REMOVE(&vp->v_hashchain, vp, vnode, v_specnext);
                freedev(vp->v_rdev);
-               lwkt_reltoken(&spechash_token);
+               lwkt_reltoken(&ilock);
                vp->v_rdev = NULL;
        }
 
@@ -2104,19 +2249,18 @@ vgonel(struct vnode *vp, struct thread *td)
         */
        if (vp->v_usecount == 0 && !(vp->v_flag & VDOOMED)) {
                s = splbio();
-               lwkt_gettoken(&vnode_free_list_token);
+               lwkt_gettoken(&ilock, &vnode_free_list_token);
                if (vp->v_flag & VFREE)
                        TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
                else
                        freevnodes++;
                vp->v_flag |= VFREE;
                TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
-               lwkt_reltoken(&vnode_free_list_token);
+               lwkt_reltoken(&ilock);
                splx(s);
        }
-
        vp->v_type = VBAD;
-       lwkt_reltoken(&vp->v_interlock);
+       lwkt_reltoken(vlock);
 }
 
 /*
@@ -2128,17 +2272,18 @@ vfinddev(dev, type, vpp)
        enum vtype type;
        struct vnode **vpp;
 {
+       lwkt_tokref ilock;
        struct vnode *vp;
 
-       lwkt_gettoken(&spechash_token);
+       lwkt_gettoken(&ilock, &spechash_token);
        SLIST_FOREACH(vp, &dev->si_hlist, v_specnext) {
                if (type == vp->v_type) {
                        *vpp = vp;
-                       lwkt_reltoken(&spechash_token);
+                       lwkt_reltoken(&ilock);
                        return (1);
                }
        }
-       lwkt_reltoken(&spechash_token);
+       lwkt_reltoken(&ilock);
        return (0);
 }
 
@@ -2149,14 +2294,15 @@ int
 vcount(vp)
        struct vnode *vp;
 {
+       lwkt_tokref ilock;
        struct vnode *vq;
        int count;
 
        count = 0;
-       lwkt_gettoken(&spechash_token);
+       lwkt_gettoken(&ilock, &spechash_token);
        SLIST_FOREACH(vq, &vp->v_hashchain, v_specnext)
                count += vq->v_usecount;
-       lwkt_reltoken(&spechash_token);
+       lwkt_reltoken(&ilock);
        return (count);
 }
 
@@ -2234,13 +2380,14 @@ vprint(label, vp)
 DB_SHOW_COMMAND(lockedvnodes, lockedvnodes)
 {
        struct thread *td = curthread;  /* XXX */
+       lwkt_tokref ilock;
        struct mount *mp, *nmp;
        struct vnode *vp;
 
        printf("Locked vnodes\n");
-       lwkt_gettoken(&mountlist_token);
+       lwkt_gettoken(&ilock, &mountlist_token);
        for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-               if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, td)) {
+               if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
                        nmp = TAILQ_NEXT(mp, mnt_list);
                        continue;
                }
@@ -2248,11 +2395,11 @@ DB_SHOW_COMMAND(lockedvnodes, lockedvnodes)
                        if (VOP_ISLOCKED(vp, NULL))
                                vprint((char *)0, vp);
                }
-               lwkt_gettoken(&mountlist_token);
+               lwkt_gettokref(&ilock);
                nmp = TAILQ_NEXT(mp, mnt_list);
                vfs_unbusy(mp, td);
        }
-       lwkt_reltoken(&mountlist_token);
+       lwkt_reltoken(&ilock);
 }
 #endif
 
@@ -2346,6 +2493,8 @@ sysctl_vnode(SYSCTL_HANDLER_ARGS)
        struct proc *p = curproc;       /* XXX */
        struct mount *mp, *nmp;
        struct vnode *nvp, *vp;
+       lwkt_tokref ilock;
+       lwkt_tokref jlock;
        int error;
 
 #define VPTRSZ sizeof (struct vnode *)
@@ -2356,14 +2505,14 @@ sysctl_vnode(SYSCTL_HANDLER_ARGS)
                return (SYSCTL_OUT(req, 0,
                        (numvnodes + KINFO_VNODESLOP) * (VPTRSZ + VNODESZ)));
 
-       lwkt_gettoken(&mountlist_token);
+       lwkt_gettoken(&ilock, &mountlist_token);
        for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-               if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, p)) {
+               if (vfs_busy(mp, LK_NOWAIT, &ilock, p)) {
                        nmp = TAILQ_NEXT(mp, mnt_list);
                        continue;
                }
+               lwkt_gettoken(&jlock, &mntvnode_token);
 again:
-               lwkt_gettoken(&mntvnode_token);
                for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist);
                     vp != NULL;
                     vp = nvp) {
@@ -2372,23 +2521,21 @@ again:
                         * this filesystem.  RACE: could have been
                         * recycled onto the same filesystem.
                         */
-                       if (vp->v_mount != mp) {
-                               lwkt_reltoken(&mntvnode_token);
+                       if (vp->v_mount != mp)
                                goto again;
-                       }
                        nvp = TAILQ_NEXT(vp, v_nmntvnodes);
-                       lwkt_reltoken(&mntvnode_token);
                        if ((error = SYSCTL_OUT(req, &vp, VPTRSZ)) ||
-                           (error = SYSCTL_OUT(req, vp, VNODESZ)))
+                           (error = SYSCTL_OUT(req, vp, VNODESZ))) {
+                               lwkt_reltoken(&jlock);
                                return (error);
-                       lwkt_gettoken(&mntvnode_token);
+                       }
                }
-               lwkt_reltoken(&mntvnode_token);
-               lwkt_gettoken(&mountlist_token);
-               nmp = TAILQ_NEXT(mp, mnt_list);
+               lwkt_reltoken(&jlock);
+               lwkt_gettokref(&ilock);
+               nmp = TAILQ_NEXT(mp, mnt_list); /* ZZZ */
                vfs_unbusy(mp, p);
        }
-       lwkt_reltoken(&mountlist_token);
+       lwkt_reltoken(&ilock);
 
        return (0);
 }
@@ -2711,55 +2858,72 @@ vfs_export_lookup(mp, nep, nam)
 }
 
 /*
- * perform msync on all vnodes under a mount point
- * the mount point must be locked.
+ * perform msync on all vnodes under a mount point.  The mount point must
+ * be locked.  This code is also responsible for lazy-freeing unreferenced
+ * vnodes whos VM objects no longer contain pages.
+ *
+ * NOTE: MNT_WAIT still skips vnodes in the VXLOCK state.
  */
+static int vfs_msync_scan1(struct mount *mp, struct vnode *vp, void *data);
+static int vfs_msync_scan2(struct mount *mp, struct vnode *vp, 
+                               lwkt_tokref_t vlock, void *data);
+
 void
 vfs_msync(struct mount *mp, int flags) 
 {
-       struct thread *td = curthread;  /* XXX */
-       struct vnode *vp, *nvp;
-       struct vm_object *obj;
-       int tries;
-
-       tries = 5;
-       lwkt_gettoken(&mntvnode_token);
-loop:
-       for (vp = TAILQ_FIRST(&mp->mnt_nvnodelist); vp != NULL; vp = nvp) {
-               if (vp->v_mount != mp) {
-                       if (--tries > 0)
-                               goto loop;
-                       break;
-               }
-               nvp = TAILQ_NEXT(vp, v_nmntvnodes);
+       vmntvnodescan(mp, vfs_msync_scan1, vfs_msync_scan2, (void *)flags);
+}
 
-               if (vp->v_flag & VXLOCK)        /* XXX: what if MNT_WAIT? */
-                       continue;
+/*
+ * scan1 is a fast pre-check.  There could be hundreds of thousands of
+ * vnodes, we cannot afford to do anything heavy weight until we have a
+ * fairly good indication that there is work to do.
+ */
+static
+int
+vfs_msync_scan1(struct mount *mp, struct vnode *vp, void *data)
+{
+       int flags = (int)data;
 
-               /*
-                * There could be hundreds of thousands of vnodes, we cannot
-                * afford to do anything heavy-weight until we have a fairly
-                * good indication that there is something to do.
-                */
-               if ((vp->v_flag & VOBJDIRTY) &&
+       if ((vp->v_flag & VXLOCK) == 0) {
+               if (VSHOULDFREE(vp))
+                       return(0);
+               if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
+                   (vp->v_flag & VOBJDIRTY) &&
                    (flags == MNT_WAIT || VOP_ISLOCKED(vp, NULL) == 0)) {
-                       lwkt_reltoken(&mntvnode_token);
-                       if (!vget(vp,
-                           LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ, td)) {
-                               if (VOP_GETVOBJECT(vp, &obj) == 0) {
-                                       vm_object_page_clean(obj, 0, 0, flags == MNT_WAIT ? OBJPC_SYNC : OBJPC_NOSYNC);
-                               }
-                               vput(vp);
-                       }
-                       lwkt_gettoken(&mntvnode_token);
-                       if (TAILQ_NEXT(vp, v_nmntvnodes) != nvp) {
-                               if (--tries > 0)
-                                       goto loop;
-                               break;
+                       return(0);
+               }
+       }
+       return(-1);
+}
+
+static
+int
+vfs_msync_scan2(struct mount *mp, struct vnode *vp, lwkt_tokref_t vlock, void *data)
+{
+       vm_object_t obj;
+       int error;
+       int flags = (int)data;
+
+       if (vp->v_flag & VXLOCK)
+               return(0);
+
+       if ((mp->mnt_flag & MNT_RDONLY) == 0 &&
+           (vp->v_flag & VOBJDIRTY) &&
+           (flags == MNT_WAIT || VOP_ISLOCKED(vp, NULL) == 0)) {
+               error = vget(vp, vlock, LK_EXCLUSIVE | LK_RETRY | LK_NOOBJ | LK_INTERLOCK, curthread);
+               if (error == 0) {
+                       if (VOP_GETVOBJECT(vp, &obj) == 0) {
+                               vm_object_page_clean(obj, 0, 0, 
+                                flags == MNT_WAIT ? OBJPC_SYNC : OBJPC_NOSYNC);
                        }
+                       vput(vp);
                }
+               return(0);
        }
-       lwkt_reltoken(&mntvnode_token);
+       vmaybefree(vp);
+       lwkt_reltoken(vlock);
+       return(0);
 }
 
 /*
@@ -2776,43 +2940,56 @@ vfs_object_create(struct vnode *vp, struct thread *td)
        return (VOP_CREATEVOBJECT(vp, td));
 }
 
-void
-vfree(vp)
-       struct vnode *vp;
+/*
+ * NOTE: the vnode interlock must be held during the call.  We have to recheck
+ * the VFREE flag since the vnode may have been removed from the free list
+ * while we were blocked on vnode_free_list_token.  The use or hold count
+ * must have already been bumped by the caller.
+ */
+static void
+vbusy(struct vnode *vp)
 {
-       int s;
+       lwkt_tokref ilock;
 
-       s = splbio();
-       lwkt_gettoken(&vnode_free_list_token);
-       KASSERT((vp->v_flag & VFREE) == 0, ("vnode already free"));
-       if (vp->v_flag & VAGE) {
-               TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
-       } else {
-               TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+       lwkt_gettoken(&ilock, &vnode_free_list_token);
+       if ((vp->v_flag & VFREE) != 0) {
+           TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
+           freevnodes--;
+           vp->v_flag &= ~(VFREE|VAGE);
        }
-       freevnodes++;
-       lwkt_reltoken(&vnode_free_list_token);
-       vp->v_flag &= ~VAGE;
-       vp->v_flag |= VFREE;
-       splx(s);
+       lwkt_reltoken(&ilock);
 }
 
-void
-vbusy(vp)
-       struct vnode *vp;
+/*
+ * NOTE: the vnode interlock must be held during the call.  The use or hold
+ * count must have already been bumped by the caller.  We use a VINFREE to
+ * interlock against other calls to vfree() which might occur while we 
+ * are blocked.  The vnode cannot be reused until it has actually been
+ * placed on the free list, so there are no other races even though the
+ * use and hold counts are 0.
+ */
+static void
+vfree(struct vnode *vp)
 {
-       int s;
+       lwkt_tokref ilock;
 
-       s = splbio();
-       lwkt_gettoken(&vnode_free_list_token);
-       KASSERT((vp->v_flag & VFREE) != 0, ("vnode not free"));
-       TAILQ_REMOVE(&vnode_free_list, vp, v_freelist);
-       freevnodes--;
-       lwkt_reltoken(&vnode_free_list_token);
-       vp->v_flag &= ~(VFREE|VAGE);
-       splx(s);
+       if ((vp->v_flag & VINFREE) == 0) {
+               vp->v_flag |= VINFREE;
+               lwkt_gettoken(&ilock, &vnode_free_list_token); /* can block */
+               KASSERT((vp->v_flag & VFREE) == 0, ("vnode already free"));
+               if (vp->v_flag & VAGE) {
+                       TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist);
+               } else {
+                       TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist);
+               }
+               freevnodes++;
+               vp->v_flag &= ~(VAGE|VINFREE);
+               vp->v_flag |= VFREE;
+               lwkt_reltoken(&ilock);  /* can block */
+       }
 }
 
+
 /*
  * Record a process's interest in events which might happen to
  * a vnode.  Because poll uses the historic select-style interface
@@ -2824,7 +3001,9 @@ vbusy(vp)
 int
 vn_pollrecord(struct vnode *vp, struct thread *td, int events)
 {
-       lwkt_gettoken(&vp->v_pollinfo.vpi_token);
+       lwkt_tokref ilock;
+
+       lwkt_gettoken(&ilock, &vp->v_pollinfo.vpi_token);
        if (vp->v_pollinfo.vpi_revents & events) {
                /*
                 * This leaves events we are not interested
@@ -2836,12 +3015,12 @@ vn_pollrecord(struct vnode *vp, struct thread *td, int events)
                events &= vp->v_pollinfo.vpi_revents;
                vp->v_pollinfo.vpi_revents &= ~events;
 
-               lwkt_reltoken(&vp->v_pollinfo.vpi_token);
+               lwkt_reltoken(&ilock);
                return events;
        }
        vp->v_pollinfo.vpi_events |= events;
        selrecord(td, &vp->v_pollinfo.vpi_selinfo);
-       lwkt_reltoken(&vp->v_pollinfo.vpi_token);
+       lwkt_reltoken(&ilock);
        return 0;
 }
 
@@ -2856,7 +3035,9 @@ vn_pollevent(vp, events)
        struct vnode *vp;
        short events;
 {
-       lwkt_gettoken(&vp->v_pollinfo.vpi_token);
+       lwkt_tokref ilock;
+
+       lwkt_gettoken(&ilock, &vp->v_pollinfo.vpi_token);
        if (vp->v_pollinfo.vpi_events & events) {
                /*
                 * We clear vpi_events so that we don't
@@ -2873,7 +3054,7 @@ vn_pollevent(vp, events)
                vp->v_pollinfo.vpi_revents |= events;
                selwakeup(&vp->v_pollinfo.vpi_selinfo);
        }
-       lwkt_reltoken(&vp->v_pollinfo.vpi_token);
+       lwkt_reltoken(&ilock);
 }
 
 /*
@@ -2885,12 +3066,14 @@ void
 vn_pollgone(vp)
        struct vnode *vp;
 {
-       lwkt_gettoken(&vp->v_pollinfo.vpi_token);
+       lwkt_tokref ilock;
+
+       lwkt_gettoken(&ilock, &vp->v_pollinfo.vpi_token);
        if (vp->v_pollinfo.vpi_events) {
                vp->v_pollinfo.vpi_events = 0;
                selwakeup(&vp->v_pollinfo.vpi_selinfo);
        }
-       lwkt_reltoken(&vp->v_pollinfo.vpi_token);
+       lwkt_reltoken(&ilock);
 }
 
 
@@ -2927,10 +3110,14 @@ VNODEOP_SET(sync_vnodeop_opv_desc);
 
 /*
  * Create a new filesystem syncer vnode for the specified mount point.
+ * This vnode is placed on the worklist and is responsible for sync'ing
+ * the filesystem.
+ *
+ * NOTE: read-only mounts are also placed on the worklist.  The filesystem
+ * sync code is also responsible for cleaning up vnodes.
  */
 int
-vfs_allocate_syncvnode(mp)
-       struct mount *mp;
+vfs_allocate_syncvnode(struct mount *mp)
 {
        struct vnode *vp;
        static long start, incr, next;
@@ -2978,6 +3165,7 @@ sync_fsync(ap)
        struct vnode *syncvp = ap->a_vp;
        struct mount *mp = syncvp->v_mount;
        struct thread *td = ap->a_td;
+       lwkt_tokref ilock;
        int asyncflag;
 
        /*
@@ -2993,19 +3181,26 @@ sync_fsync(ap)
 
        /*
         * Walk the list of vnodes pushing all that are dirty and
-        * not already on the sync list.
+        * not already on the sync list, and freeing vnodes which have
+        * no refs and whos VM objects are empty.  vfs_msync() handles
+        * the VM issues and must be called whether the mount is readonly
+        * or not.
         */
-       lwkt_gettoken(&mountlist_token);
-       if (vfs_busy(mp, LK_EXCLUSIVE | LK_NOWAIT, &mountlist_token, td) != 0) {
-               lwkt_reltoken(&mountlist_token);
+       lwkt_gettoken(&ilock, &mountlist_token);
+       if (vfs_busy(mp, LK_EXCLUSIVE | LK_NOWAIT, &ilock, td) != 0) {
+               lwkt_reltoken(&ilock);
                return (0);
        }
-       asyncflag = mp->mnt_flag & MNT_ASYNC;
-       mp->mnt_flag &= ~MNT_ASYNC;
-       vfs_msync(mp, MNT_NOWAIT);
-       VFS_SYNC(mp, MNT_LAZY, td);
-       if (asyncflag)
-               mp->mnt_flag |= MNT_ASYNC;
+       if (mp->mnt_flag & MNT_RDONLY) {
+               vfs_msync(mp, MNT_NOWAIT);
+       } else {
+               asyncflag = mp->mnt_flag & MNT_ASYNC;
+               mp->mnt_flag &= ~MNT_ASYNC;     /* ZZZ hack */
+               vfs_msync(mp, MNT_NOWAIT);
+               VFS_SYNC(mp, MNT_LAZY, td);
+               if (asyncflag)
+                       mp->mnt_flag |= MNT_ASYNC;
+       }
        vfs_unbusy(mp, td);
        return (0);
 }
@@ -3138,7 +3333,7 @@ NDFREE(ndp, flags)
        if (!(flags & NDF_NO_DVP_UNLOCK) &&
            (ndp->ni_cnd.cn_flags & CNP_LOCKPARENT) &&
            ndp->ni_dvp != ndp->ni_vp) {
-               VOP_UNLOCK(ndp->ni_dvp, 0, ndp->ni_cnd.cn_td);
+               VOP_UNLOCK(ndp->ni_dvp, NULL, 0, ndp->ni_cnd.cn_td);
        }
        if (!(flags & NDF_NO_DVP_RELE) &&
            (ndp->ni_cnd.cn_flags & (CNP_LOCKPARENT|CNP_WANTPARENT))) {
@@ -3147,7 +3342,7 @@ NDFREE(ndp, flags)
        }
        if (!(flags & NDF_NO_VP_UNLOCK) &&
            (ndp->ni_cnd.cn_flags & CNP_LOCKLEAF) && ndp->ni_vp) {
-               VOP_UNLOCK(ndp->ni_vp, 0, ndp->ni_cnd.cn_td);
+               VOP_UNLOCK(ndp->ni_vp, NULL, 0, ndp->ni_cnd.cn_td);
        }
        if (!(flags & NDF_NO_VP_RELE) &&
            ndp->ni_vp) {
index 0885ae0..104a2dd 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_syscalls.c      8.13 (Berkeley) 4/15/94
  * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $
- * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.28 2003/11/14 19:31:22 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.29 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -108,6 +108,8 @@ mount(struct mount_args *uap)
        struct vattr va;
        struct nameidata nd;
        char fstypename[MFSNAMELEN];
+       lwkt_tokref vlock;
+       lwkt_tokref ilock;
 
        if (usermount == 0 && (error = suser(td)))
                return (error);
@@ -159,23 +161,23 @@ mount(struct mount_args *uap)
                        vput(vp);
                        return (error);
                }
-               if (vfs_busy(mp, LK_NOWAIT, 0, td)) {
+               if (vfs_busy(mp, LK_NOWAIT, NULL, td)) {
                        vput(vp);
                        return (EBUSY);
                }
-               lwkt_gettoken(&vp->v_interlock);
+               lwkt_gettoken(&vlock, vp->v_interlock);
                if ((vp->v_flag & VMOUNT) != 0 ||
                    vp->v_mountedhere != NULL) {
-                       lwkt_reltoken(&vp->v_interlock);
+                       lwkt_reltoken(&vlock);
                        vfs_unbusy(mp, td);
                        vput(vp);
                        return (EBUSY);
                }
                vp->v_flag |= VMOUNT;
-               lwkt_reltoken(&vp->v_interlock);
+               lwkt_reltoken(&vlock);
                mp->mnt_flag |=
                    SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
-               VOP_UNLOCK(vp, 0, td);
+               VOP_UNLOCK(vp, NULL, 0, td);
                goto update;
        }
        /*
@@ -230,15 +232,15 @@ mount(struct mount_args *uap)
                        return (ENODEV);
                }
        }
-       lwkt_gettoken(&vp->v_interlock);
+       lwkt_gettoken(&vlock, vp->v_interlock);
        if ((vp->v_flag & VMOUNT) != 0 ||
            vp->v_mountedhere != NULL) {
-               lwkt_reltoken(&vp->v_interlock);
+               lwkt_reltoken(&vlock);
                vput(vp);
                return (EBUSY);
        }
        vp->v_flag |= VMOUNT;
-       lwkt_reltoken(&vp->v_interlock);
+       lwkt_reltoken(&vlock);
 
        /*
         * Allocate and initialize the filesystem.
@@ -249,7 +251,7 @@ mount(struct mount_args *uap)
        TAILQ_INIT(&mp->mnt_reservedvnlist);
        mp->mnt_nvnodelistsize = 0;
        lockinit(&mp->mnt_lock, 0, "vfslock", 0, LK_NOPAUSE);
-       (void)vfs_busy(mp, LK_NOWAIT, 0, td);
+       vfs_busy(mp, LK_NOWAIT, NULL, td);
        mp->mnt_op = vfsp->vfc_vfsops;
        mp->mnt_vfc = vfsp;
        vfsp->vfc_refcount++;
@@ -259,7 +261,7 @@ mount(struct mount_args *uap)
        mp->mnt_vnodecovered = vp;
        mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
        mp->mnt_iosize_max = DFLTPHYS;
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
 update:
        /*
         * Set the mount level flags.
@@ -291,45 +293,36 @@ update:
                        mp->mnt_flag = flag;
                        mp->mnt_kern_flag = flag2;
                }
-               if ((mp->mnt_flag & MNT_RDONLY) == 0) {
-                       if (mp->mnt_syncer == NULL)
-                               error = vfs_allocate_syncvnode(mp);
-               } else {
-                       if (mp->mnt_syncer != NULL)
-                               vrele(mp->mnt_syncer);
-                       mp->mnt_syncer = NULL;
-               }
                vfs_unbusy(mp, td);
-               lwkt_gettoken(&vp->v_interlock);
+               lwkt_gettoken(&vlock, vp->v_interlock);
                vp->v_flag &= ~VMOUNT;
-               lwkt_reltoken(&vp->v_interlock);
+               lwkt_reltoken(&vlock);
                vrele(vp);
                return (error);
        }
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        /*
         * Put the new filesystem on the mount list after root.
         */
        cache_purge(vp);
        if (!error) {
-               lwkt_gettoken(&vp->v_interlock);
+               lwkt_gettoken(&vlock, vp->v_interlock);
                vp->v_flag &= ~VMOUNT;
                vp->v_mountedhere = mp;
-               lwkt_reltoken(&vp->v_interlock);
-               lwkt_gettoken(&mountlist_token);
+               lwkt_reltoken(&vlock);
+               lwkt_gettoken(&ilock, &mountlist_token);
                TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
-               lwkt_reltoken(&mountlist_token);
+               lwkt_reltoken(&ilock);
                checkdirs(vp);
-               VOP_UNLOCK(vp, 0, td);
-               if ((mp->mnt_flag & MNT_RDONLY) == 0)
-                       error = vfs_allocate_syncvnode(mp);
+               VOP_UNLOCK(vp, NULL, 0, td);
+               error = vfs_allocate_syncvnode(mp);
                vfs_unbusy(mp, td);
                if ((error = VFS_START(mp, 0, td)) != 0)
                        vrele(vp);
        } else {
-               lwkt_gettoken(&vp->v_interlock);
+               lwkt_gettoken(&vlock, vp->v_interlock);
                vp->v_flag &= ~VMOUNT;
-               lwkt_reltoken(&vp->v_interlock);
+               lwkt_reltoken(&vlock);
                mp->mnt_vfc->vfc_refcount--;
                vfs_unbusy(mp, td);
                free((caddr_t)mp, M_MOUNT);
@@ -443,10 +436,11 @@ dounmount(struct mount *mp, int flags, struct thread *td)
        struct vnode *coveredvp;
        int error;
        int async_flag;
+       lwkt_tokref ilock;
 
-       lwkt_gettoken(&mountlist_token);
+       lwkt_gettoken(&ilock, &mountlist_token);
        if (mp->mnt_kern_flag & MNTK_UNMOUNT) {
-               lwkt_reltoken(&mountlist_token);
+               lwkt_reltoken(&ilock);
                return (EBUSY);
        }
        mp->mnt_kern_flag |= MNTK_UNMOUNT;
@@ -454,7 +448,7 @@ dounmount(struct mount *mp, int flags, struct thread *td)
        if (flags & MNT_FORCE)
                mp->mnt_kern_flag |= MNTK_UNMOUNTF;
        error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK |
-           ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &mountlist_token, td);
+           ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &ilock, td);
        if (error) {
                mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
                if (mp->mnt_kern_flag & MNTK_MWAIT)
@@ -475,14 +469,14 @@ dounmount(struct mount *mp, int flags, struct thread *td)
             (error = VFS_SYNC(mp, MNT_WAIT, td)) == 0) ||
            (flags & MNT_FORCE))
                error = VFS_UNMOUNT(mp, flags, td);
-       lwkt_gettoken(&mountlist_token);
+       lwkt_gettokref(&ilock);
        if (error) {
-               if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL)
-                       (void) vfs_allocate_syncvnode(mp);
+               if (mp->mnt_syncer == NULL)
+                       vfs_allocate_syncvnode(mp);
                mp->mnt_kern_flag &= ~(MNTK_UNMOUNT | MNTK_UNMOUNTF);
                mp->mnt_flag |= async_flag;
                lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
-                   &mountlist_token, td);
+                   &ilock, td);
                if (mp->mnt_kern_flag & MNTK_MWAIT)
                        wakeup((caddr_t)mp);
                return (error);
@@ -495,7 +489,7 @@ dounmount(struct mount *mp, int flags, struct thread *td)
        mp->mnt_vfc->vfc_refcount--;
        if (!TAILQ_EMPTY(&mp->mnt_nvnodelist))
                panic("unmount: dangling vnode");
-       lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_token, td);
+       lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &ilock, td);
        if (mp->mnt_kern_flag & MNTK_MWAIT)
                wakeup((caddr_t)mp);
        free((caddr_t)mp, M_MOUNT);
@@ -517,11 +511,12 @@ sync(struct sync_args *uap)
 {
        struct thread *td = curthread;
        struct mount *mp, *nmp;
+       lwkt_tokref ilock;
        int asyncflag;
 
-       lwkt_gettoken(&mountlist_token);
+       lwkt_gettoken(&ilock, &mountlist_token);
        for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-               if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, td)) {
+               if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
                        nmp = TAILQ_NEXT(mp, mnt_list);
                        continue;
                }
@@ -532,11 +527,11 @@ sync(struct sync_args *uap)
                        VFS_SYNC(mp, MNT_NOWAIT, td);
                        mp->mnt_flag |= asyncflag;
                }
-               lwkt_gettoken(&mountlist_token);
+               lwkt_gettokref(&ilock);
                nmp = TAILQ_NEXT(mp, mnt_list);
                vfs_unbusy(mp, td);
        }
-       lwkt_reltoken(&mountlist_token);
+       lwkt_reltoken(&ilock);
 #if 0
 /*
  * XXX don't call vfs_bufstats() yet because that routine
@@ -693,14 +688,15 @@ getfsstat(struct getfsstat_args *uap)
        struct mount *mp, *nmp;
        struct statfs *sp;
        caddr_t sfsp;
+       lwkt_tokref ilock;
        long count, maxcount, error;
 
        maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
        sfsp = (caddr_t)SCARG(uap, buf);
        count = 0;
-       lwkt_gettoken(&mountlist_token);
+       lwkt_gettoken(&ilock, &mountlist_token);
        for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-               if (vfs_busy(mp, LK_NOWAIT, &mountlist_token, td)) {
+               if (vfs_busy(mp, LK_NOWAIT, &ilock, td)) {
                        nmp = TAILQ_NEXT(mp, mnt_list);
                        continue;
                }
@@ -714,7 +710,7 @@ getfsstat(struct getfsstat_args *uap)
                        if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 ||
                            (SCARG(uap, flags) & MNT_WAIT)) &&
                            (error = VFS_STATFS(mp, sp, td))) {
-                               lwkt_gettoken(&mountlist_token);
+                               lwkt_gettokref(&ilock);
                                nmp = TAILQ_NEXT(mp, mnt_list);
                                vfs_unbusy(mp, td);
                                continue;
@@ -728,11 +724,11 @@ getfsstat(struct getfsstat_args *uap)
                        sfsp += sizeof(*sp);
                }
                count++;
-               lwkt_gettoken(&mountlist_token);
+               lwkt_gettokref(&ilock);
                nmp = TAILQ_NEXT(mp, mnt_list);
                vfs_unbusy(mp, td);
        }
-       lwkt_reltoken(&mountlist_token);
+       lwkt_reltoken(&ilock);
        if (sfsp && count > maxcount)
                uap->sysmsg_result = maxcount;
        else
@@ -761,13 +757,13 @@ fchdir(struct fchdir_args *uap)
                return (error);
        vp = (struct vnode *)fp->f_data;
        VREF(vp);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        if (vp->v_type != VDIR)
                error = ENOTDIR;
        else
                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, td);
        while (!error && (mp = vp->v_mountedhere) != NULL) {
-               if (vfs_busy(mp, 0, 0, td))
+               if (vfs_busy(mp, 0, NULL, td))
                        continue;
                error = VFS_ROOT(mp, &tdp);
                vfs_unbusy(mp, td);
@@ -780,7 +776,7 @@ fchdir(struct fchdir_args *uap)
                vput(vp);
                return (error);
        }
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        vrele(fdp->fd_cdir);
        fdp->fd_cdir = vp;
        return (0);
@@ -919,7 +915,7 @@ change_dir(struct nameidata *ndp, struct thread *td)
        if (error)
                vput(vp);
        else
-               VOP_UNLOCK(vp, 0, td);
+               VOP_UNLOCK(vp, NULL, 0, td);
        return (error);
 }
 
@@ -997,7 +993,7 @@ kern_open(struct nameidata *nd, int oflags, int mode, int *res)
        if (fp->f_count == 1) {
                KASSERT(fdp->fd_ofiles[indx] != fp,
                    ("Open file descriptor lost all refs"));
-               VOP_UNLOCK(vp, 0, td);
+               VOP_UNLOCK(vp, NULL, 0, td);
                vn_close(vp, flags & FMASK, td);
                fdrop(fp, td);
                *res = indx;
@@ -1019,7 +1015,7 @@ kern_open(struct nameidata *nd, int oflags, int mode, int *res)
                type = F_FLOCK;
                if ((flags & FNONBLOCK) == 0)
                        type |= F_WAIT;
-               VOP_UNLOCK(vp, 0, td);
+               VOP_UNLOCK(vp, NULL, 0, td);
                if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
                        /*
                         * lock request failed.  Normally close the descriptor
@@ -1034,13 +1030,13 @@ kern_open(struct nameidata *nd, int oflags, int mode, int *res)
                        fdrop(fp, td);
                        return (error);
                }
-               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+               vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
                fp->f_flag |= FHASLOCK;
        }
        /* assert that vn_open created a backing object if one is needed */
        KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0,
                ("open: vmio vnode has no backing object after vn_open"));
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
 
        /*
         * release our private reference, leaving the one associated with the
@@ -1407,7 +1403,7 @@ kern_unlink(struct nameidata *nd)
                return (error);
        vp = nd->ni_vp;
        VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
 
        if (vp->v_type == VDIR)
                error = EPERM;          /* POSIX */
@@ -1818,11 +1814,11 @@ setfflags(struct vnode *vp, int flags)
                return (error);
 
        VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        VATTR_NULL(&vattr);
        vattr.va_flags = flags;
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return (error);
 }
 
@@ -1877,11 +1873,11 @@ setfmode(struct vnode *vp, int mode)
        struct vattr vattr;
 
        VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        VATTR_NULL(&vattr);
        vattr.va_mode = mode & ALLPERMS;
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return error;
 }
 
@@ -1969,12 +1965,12 @@ setfown(struct vnode *vp, uid_t uid, gid_t gid)
        struct vattr vattr;
 
        VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        VATTR_NULL(&vattr);
        vattr.va_uid = uid;
        vattr.va_gid = gid;
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return error;
 }
 
@@ -2075,14 +2071,14 @@ setutimes(struct vnode *vp, const struct timespec *ts, int nullflag)
        struct vattr vattr;
 
        VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        VATTR_NULL(&vattr);
        vattr.va_atime = ts[0];
        vattr.va_mtime = ts[1];
        if (nullflag)
                vattr.va_vaflags |= VA_UTIMES_NULL;
        error = VOP_SETATTR(vp, &vattr, p->p_ucred, td);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return error;
 }
 
@@ -2211,7 +2207,7 @@ kern_truncate(struct nameidata* nd, off_t length)
        vp = nd->ni_vp;
        NDFREE(nd, NDF_ONLY_PNBUF);
        VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        if (vp->v_type == VDIR)
                error = EISDIR;
        else if ((error = vn_writechk(vp)) == 0 &&
@@ -2261,7 +2257,7 @@ kern_ftruncate(int fd, off_t length)
                return (EINVAL);
        vp = (struct vnode *)fp->f_data;
        VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        if (vp->v_type == VDIR)
                error = EISDIR;
        else if ((error = vn_writechk(vp)) == 0) {
@@ -2269,7 +2265,7 @@ kern_ftruncate(int fd, off_t length)
                vattr.va_size = length;
                error = VOP_SETATTR(vp, &vattr, fp->f_cred, td);
        }
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return (error);
 }
 
@@ -2307,14 +2303,14 @@ fsync(struct fsync_args *uap)
        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
                return (error);
        vp = (struct vnode *)fp->f_data;
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        if (VOP_GETVOBJECT(vp, &obj) == 0)
                vm_object_page_clean(obj, 0, 0, 0);
        if ((error = VOP_FSYNC(vp, MNT_WAIT, td)) == 0 &&
            vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
            bioops.io_fsync)
                error = (*bioops.io_fsync)(vp);
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return (error);
 }
 
@@ -2583,12 +2579,12 @@ unionread:
        auio.uio_segflg = UIO_USERSPACE;
        auio.uio_td = td;
        auio.uio_resid = count;
-       /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       /* vn_lock(vp, NULL, LK_SHARED | LK_RETRY, td); */
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        loff = auio.uio_offset = fp->f_offset;
        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL);
        fp->f_offset = auio.uio_offset;
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        if (error)
                return (error);
        if (count == auio.uio_resid) {
@@ -2845,9 +2841,9 @@ fhopen(struct fhopen_args *uap)
                        goto bad;
        }
        if (fmode & O_TRUNC) {
-               VOP_UNLOCK(vp, 0, td);                          /* XXX */
+               VOP_UNLOCK(vp, NULL, 0, td);                    /* XXX */
                VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE);
-               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);       /* XXX */
+               vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */
                VATTR_NULL(vap);
                vap->va_size = 0;
                error = VOP_SETATTR(vp, vap, p->p_ucred, td);
@@ -2898,7 +2894,7 @@ fhopen(struct fhopen_args *uap)
                type = F_FLOCK;
                if ((fmode & FNONBLOCK) == 0)
                        type |= F_WAIT;
-               VOP_UNLOCK(vp, 0, td);
+               VOP_UNLOCK(vp, NULL, 0, td);
                if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) {
                        /*
                         * lock request failed.  Normally close the descriptor
@@ -2916,13 +2912,13 @@ fhopen(struct fhopen_args *uap)
                        fdrop(fp, td);
                        return (error);
                }
-               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+               vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
                fp->f_flag |= FHASLOCK;
        }
        if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0))
                vfs_object_create(vp, td);
 
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        fdrop(fp, td);
        uap->sysmsg_result = indx;
        return (0);
index 248b0ea..1cd02eb 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94
  * $FreeBSD: src/sys/kern/vfs_vnops.c,v 1.87.2.13 2002/12/29 18:19:53 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.15 2003/10/09 22:27:19 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_vnops.c,v 1.16 2004/03/01 06:33:17 dillon Exp $
  */
 
 #include <sys/param.h>
@@ -174,9 +174,9 @@ vn_open(ndp, fmode, cmode)
                }
        }
        if (fmode & O_TRUNC) {
-               VOP_UNLOCK(vp, 0, td);                          /* XXX */
+               VOP_UNLOCK(vp, NULL, 0, td);                    /* XXX */
                VOP_LEASE(vp, td, cred, LEASE_WRITE);
-               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);       /* XXX */
+               vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */
                VATTR_NULL(vap);
                vap->va_size = 0;
                error = VOP_SETATTR(vp, vap, cred, td);
@@ -291,7 +291,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, td)
        int error;
 
        if ((ioflg & IO_NODELOCKED) == 0)
-               vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+               vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        auio.uio_iov = &aiov;
        auio.uio_iovcnt = 1;
        aiov.iov_base = base;
@@ -312,7 +312,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, cred, aresid, td)
                if (auio.uio_resid && error == 0)
                        error = EIO;
        if ((ioflg & IO_NODELOCKED) == 0)
-               VOP_UNLOCK(vp, 0, td);
+               VOP_UNLOCK(vp, NULL, 0, td);
        return (error);
 }
 
@@ -380,7 +380,7 @@ vn_read(fp, uio, cred, flags, td)
        if (fp->f_flag & O_DIRECT)
                ioflag |= IO_DIRECT;
        VOP_LEASE(vp, td, cred, LEASE_READ);
-       vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_SHARED | LK_NOPAUSE | LK_RETRY, td);
        if ((flags & FOF_OFFSET) == 0)
                uio->uio_offset = fp->f_offset;
 
@@ -390,7 +390,7 @@ vn_read(fp, uio, cred, flags, td)
        if ((flags & FOF_OFFSET) == 0)
                fp->f_offset = uio->uio_offset;
        fp->f_nextoff = uio->uio_offset;
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return (error);
 }
 
@@ -425,7 +425,7 @@ vn_write(fp, uio, cred, flags, td)
            (vp->v_mount && (vp->v_mount->mnt_flag & MNT_SYNCHRONOUS)))
                ioflag |= IO_SYNC;
        VOP_LEASE(vp, td, cred, LEASE_WRITE);
-       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+       vn_lock(vp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
        if ((flags & FOF_OFFSET) == 0)
                uio->uio_offset = fp->f_offset;
        ioflag |= sequential_heuristic(uio, fp);
@@ -433,7 +433,7 @@ vn_write(fp, uio, cred, flags, td)
        if ((flags & FOF_OFFSET) == 0)
                fp->f_offset = uio->uio_offset;
        fp->f_nextoff = uio->uio_offset;
-       VOP_UNLOCK(vp, 0, td);
+       VOP_UNLOCK(vp, NULL, 0, td);
        return (error);
 }
 
@@ -626,33 +626,36 @@ vn_poll(struct file *fp, int events, struct ucred *cred, struct thread *td)
  */
 int
 #ifndef        DEBUG_LOCKS
-vn_lock(struct vnode *vp, int flags, struct thread *td)
+vn_lock(struct vnode *vp, lwkt_tokref_t vlock, int flags, struct thread *td)
 #else
-debug_vn_lock(struct vnode *vp, int flags, struct thread *td,
-               const char *filename, int line)
+debug_vn_lock(struct vnode *vp, lwkt_tokref_t vlock, int flags, 
+               struct thread *td, const char *filename, int line)
 #endif
 {
        int error;
+       lwkt_tokref vvlock;
        
        do {
-               if ((flags & LK_INTERLOCK) == 0)
-                       lwkt_gettoken(&vp->v_interlock);
-               if ((vp->v_flag & VXLOCK) && vp->v_vxproc != curproc) {
+               if ((flags & LK_INTERLOCK) == 0) {
+                       lwkt_gettoken(&vvlock, vp->v_interlock);
+                       vlock = &vvlock;
+               }
+               if ((vp->v_flag & VXLOCK) && vp->v_vxthread != curthread) {
                        vp->v_flag |= VXWANT;
-                       lwkt_reltoken(&vp->v_interlock);
+                       lwkt_reltoken(vlock);
                        tsleep((caddr_t)vp, 0, "vn_lock", 0);
                        error = ENOENT;
                } else {
 #if 0
                        /* this can now occur in normal operation */
-                       if (vp->v_vxproc != NULL)
+                       if (vp->v_vxthread != NULL)
                                log(LOG_INFO, "VXLOCK interlock avoided in vn_lock\n");
 #endif
 #ifdef DEBUG_LOCKS
                        vp->filename = filename;
                        vp->line = line;
 #endif
-                       error = VOP_LOCK(vp,
+                       error = VOP_LOCK(vp, vlock,
                                    flags | LK_NOPAUSE | LK_INTERLOCK, td);
                        if (error == 0)
                                return (error);
index 665a01d..fd3af3f 100644 (file)
@@ -32,7 +32,7 @@
 #
 #      @(#)vnode_if.src        8.12 (Berkeley) 5/14/95
 # $FreeBSD: src/sys/kern/vnode_if.src,v 1.29.2.3 2001/05/18 09:58:45 bp Exp $
-# $DragonFly: src/sys/kern/Attic/vnode_if.src,v 1.5 2003/10/09 22:27:19 dillon Exp $
+# $DragonFly: src/sys/kern/Attic/vnode_if.src,v 1.6 2004/03/01 06:33:17 dillon Exp $
 #
 
 #
@@ -379,6 +379,7 @@ vop_reclaim {
 #
 vop_lock {
        IN struct vnode *vp;
+       IN struct lwkt_tokref *vlock;
        IN int flags;
        IN struct thread *td;
 };
@@ -388,6 +389,7 @@ vop_lock {
 #
 vop_unlock {
        IN struct vnode *vp;
+       IN struct lwkt_tokref *vlock;
        IN int flags;
        IN struct thread *td;
 };
index 6614e56..f453b0f 100644 (file)
@@ -29,7 +29,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * $FreeBSD: src/sys/netncp/ncp_conn.c,v 1.3.2.5 2001/02/22 08:54:11 bp Exp $
- * $DragonFly: src/sys/netproto/ncp/ncp_conn.c,v 1.6 2003/11/10 06:12:14 dillon Exp $
+ * $DragonFly: src/sys/netproto/ncp/ncp_conn.c,v 1.7 2004/03/01 06:33:18 dillon Exp $
  *
  * Connection tables
  */
@@ -80,13 +80,13 @@ ncp_conn_init(void) {
 int
 ncp_conn_locklist(int flags, struct thread *td)
 {
-       return lockmgr(&listlock, flags | LK_CANRECURSE, 0, td);
+       return lockmgr(&listlock, flags | LK_CANRECURSE, NULL, td);
 }
 
 void
 ncp_conn_unlocklist(struct thread *td)
 {
-       lockmgr(&listlock, LK_RELEASE, 0, td);
+       lockmgr(&listlock, LK_RELEASE, NULL, td);
 }
 
 int
@@ -110,17 +110,17 @@ ncp_conn_lock_any(struct ncp_conn *conn, struct thread *td, struct ucred *cred)
        int error;
 
        if (conn->nc_id == 0) return EACCES;
-       error = lockmgr(&conn->nc_lock, LK_EXCLUSIVE | LK_CANRECURSE, 0, td);
+       error = lockmgr(&conn->nc_lock, LK_EXCLUSIVE | LK_CANRECURSE, NULL, td);
        if (error == ERESTART)
                return EINTR;
        error = ncp_chkintr(conn, td);
        if (error) {
-               lockmgr(&conn->nc_lock, LK_RELEASE, 0, td);
+               lockmgr(&conn->nc_lock, LK_RELEASE, NULL, td);
                return error;
        }
 
        if (conn->nc_id ==&n