The core of the umtx code in the kernel is this:

    umtx_sleep:

        acquire and hold VM page
        tsleep loop using the page's physical address as the sleep address
        release page

    umtx_wakeup:

        acquire and hold the VM page
        lookup the physical address
        wakeup based on physical address.
        release page

    The page is not supposed to be reassigned while a thread is sleeping
    in umtx_sleep on that page, so the physical address shouldn't change
    between the sleep and the wakeup.

    There are two possibilities that I can think of:

    * Firefox is remapping the underyling virtual address

    * There is a bug in the kernel implementation somewhere
      that is causing the underlying page to get reassigned somehow.

    I have two patches for you to try.  Please try each one separately
    (not both together) and tell me which ones fix the problem, or that
    neither of them fixes the problem.

                                                -Matt

                                PATCH #1

Index: kern_umtx.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_umtx.c,v
retrieving revision 1.7
diff -u -p -r1.7 kern_umtx.c
--- kern_umtx.c 2 Jul 2007 01:30:07 -0000       1.7
+++ kern_umtx.c 12 Apr 2008 18:12:12 -0000
@@ -105,6 +105,7 @@     return (EFAULT);
     m = vm_fault_page_quick((vm_offset_t)uap->ptr, VM_PROT_READ, &error);
     if (m == NULL)
        return (EFAULT);
+    vm_page_wire(m);
     sf = sf_buf_alloc(m, SFB_CPUPRIVATE);
     offset = (vm_offset_t)uap->ptr & PAGE_MASK;
 
@@ -121,6 +122,7 @@     error = EBUSY;
     }
 
     sf_buf_free(sf);
+    vm_page_unwire(m, 1);
     vm_page_unhold(m);
     return(error);
 }

                                PATCH #2

Index: vm_object.c
===================================================================
RCS file: /cvs/src/sys/vm/vm_object.c,v
retrieving revision 1.31
diff -u -p -r1.31 vm_object.c
--- vm_object.c 8 Jun 2007 02:00:47 -0000       1.31
+++ vm_object.c 12 Apr 2008 18:16:54 -0000
@@ -1605,12 +1605,15 @@         }
 
        /*
         * limit is our clean_only flag.  If set and the page is dirty, do
+        * not free it.  If set and the page is being held by someone, do
         * not free it.
         */
        if (info->limit && p->valid) {
                vm_page_test_dirty(p);
                if (p->valid & p->dirty)
                        return(0);
+               if (p->hold_count)
+                       return(0);
        }
 
        /*

Reply via email to