checked nix/port/page.c. your duppage() is wrong.

        /* don't dup pages with no image */
        if(p->ref == 0 || p->image == nil || p->image->notext)
                return 0;

        /*
         *  normal lock ordering is to call
         *  lock(&pga) before lock(p).
         *  To avoid deadlock, we have to drop
         *  our locks and try again.
         */
        if(!canlock(&pga)){
                unlock(p);
                if(up)
                        sched();
                lock(p);
                goto retry;
        }

you need to check p->ref != 1 instead of p->ref == 0. the page
passed to duppage() is still cached. after you unlock(p), someone
can come in and take a reference to the page from the image
cache (lookpage()), making p->ref > 1 once you get the lock back.

put an assert or print in there after the if(!canlock(&pga){} block
to check p->ref.

when this happens, the caller to duppage() (fixfault) must not
modify the page or use it in his procs segment (on copy on write)
but make a copy for itself because the other processes that
grabbed the reference is (commited to) reading it (outside of the
page lock of course, so you already lost when p->ref != 1).

--
cinap

Reply via email to