summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_pipe.c
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2002-07-13 04:09:45 +0000
committeralc <alc@FreeBSD.org>2002-07-13 04:09:45 +0000
commit41fc8114c091411a45564a858af8e7b3cc3af5b7 (patch)
tree5e444afa69050e763c5282ba5c919210b25abec4 /sys/kern/sys_pipe.c
parent11a8bfb92369446efa4603ca160d80657e9a4f67 (diff)
downloadFreeBSD-src-41fc8114c091411a45564a858af8e7b3cc3af5b7.zip
FreeBSD-src-41fc8114c091411a45564a858af8e7b3cc3af5b7.tar.gz
o Lock accesses to the page queues.
o Add a comment explaining why hoisting the page queue lock outside of a particular loop is not possible.
Diffstat (limited to 'sys/kern/sys_pipe.c')
-rw-r--r--sys/kern/sys_pipe.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 289bc37..135d5eb 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -616,18 +616,27 @@ pipe_build_write_buffer(wpipe, uio)
for (i = 0; addr < endaddr; addr += PAGE_SIZE, i++) {
vm_page_t m;
+ /*
+ * vm_fault_quick() can sleep. Consequently,
+ * vm_page_lock_queue() and vm_page_unlock_queue()
+ * should not be performed outside of this loop.
+ */
if (vm_fault_quick((caddr_t)addr, VM_PROT_READ) < 0 ||
(paddr = pmap_extract(vmspace_pmap(curproc->p_vmspace),
addr)) == 0) {
int j;
+ vm_page_lock_queues();
for (j = 0; j < i; j++)
vm_page_unwire(wpipe->pipe_map.ms[j], 1);
+ vm_page_unlock_queues();
return (EFAULT);
}
m = PHYS_TO_VM_PAGE(paddr);
+ vm_page_lock_queues();
vm_page_wire(m);
+ vm_page_unlock_queues();
wpipe->pipe_map.ms[i] = m;
}
@@ -690,8 +699,10 @@ pipe_destroy_write_buffer(wpipe)
amountpipekva -= wpipe->pipe_buffer.size + PAGE_SIZE;
}
}
+ vm_page_lock_queues();
for (i = 0; i < wpipe->pipe_map.npages; i++)
vm_page_unwire(wpipe->pipe_map.ms[i], 1);
+ vm_page_unlock_queues();
wpipe->pipe_map.npages = 0;
}
OpenPOWER on IntegriCloud