kern/78179: bus_dmamem_alloc() with BUS_DMA_NOWAIT can block
Mark Tinguely
tinguely at casselton.net
Thu May 11 17:20:36 UTC 2006
The following reply was made to PR kern/78179; it has been noted by GNATS.
From: Mark Tinguely <tinguely at casselton.net>
To: bug-followup at FreeBSD.org, PeterJeremy at optushome.com.au
Cc:
Subject: Re: kern/78179: bus_dmamem_alloc() with BUS_DMA_NOWAIT can block
Date: Thu, 11 May 2006 11:56:06 -0500 (CDT)
I stated in the -current mailing list that my original patch to
sys/vm/vm_contig.c was wrong. The following is closer to what should
be done.
--- vm_contig.c.orig Fri Mar 10 14:30:07 2006
+++ vm_contig.c Thu May 11 11:50:14 2006
@@ -86,7 +86,7 @@
#include <vm/vm_extern.h>
static int
-vm_contig_launder_page(vm_page_t m)
+vm_contig_launder_page(vm_page_t m, int flags)
{
vm_object_t object;
vm_page_t m_tmp;
@@ -96,6 +96,20 @@
object = m->object;
if (!VM_OBJECT_TRYLOCK(object))
return (EAGAIN);
+
+ if (flags & M_NOWAIT) { /* cannot sleep in interrupt mode */
+ if ((m->flags & PG_BUSY) || m->busy) {
+ VM_OBJECT_UNLOCK(object);
+ return (EBUSY);
+ } else {
+ vm_page_test_dirty(m);
+ if (m->dirty) {
+ VM_OBJECT_UNLOCK(object);
+ return (EAGAIN);
+ }
+ }
+ }
+
if (vm_page_sleep_if_busy(m, TRUE, "vpctw0")) {
VM_OBJECT_UNLOCK(object);
vm_page_lock_queues();
@@ -138,7 +152,7 @@
}
static int
-vm_contig_launder(int queue)
+vm_contig_launder(int queue, int flags)
{
vm_page_t m, next;
int error;
@@ -152,7 +166,7 @@
KASSERT(VM_PAGE_INQUEUE2(m, queue),
("vm_contig_launder: page %p's queue is not %d", m, queue));
- error = vm_contig_launder_page(m);
+ error = vm_contig_launder_page(m, flags);
if (error == 0)
return (TRUE);
if (error == EBUSY)
@@ -233,12 +247,12 @@
actmax = vm_page_queues[PQ_ACTIVE].lcnt;
again1:
if (inactl < inactmax &&
- vm_contig_launder(PQ_INACTIVE)) {
+ vm_contig_launder(PQ_INACTIVE, flags)) {
inactl++;
goto again1;
}
if (actl < actmax &&
- vm_contig_launder(PQ_ACTIVE)) {
+ vm_contig_launder(PQ_ACTIVE, flags)) {
actl++;
goto again1;
}
@@ -390,7 +404,7 @@
vm_page_t
vm_page_alloc_contig(vm_pindex_t npages, vm_paddr_t low, vm_paddr_t high,
- vm_offset_t alignment, vm_offset_t boundary)
+ vm_offset_t alignment, vm_offset_t boundary, int flags)
{
vm_object_t object;
vm_offset_t size;
@@ -483,7 +497,7 @@
pqtype != PQ_CACHE) {
if (m->queue == PQ_ACTIVE ||
m->queue == PQ_INACTIVE) {
- if (vm_contig_launder_page(m) != 0)
+ if (vm_contig_launder_page(m, flags) != 0)
goto cleanup_freed;
pqtype = m->queue - m->pc;
if (pqtype != PQ_FREE &&
@@ -590,7 +604,7 @@
boundary, kernel_map);
} else {
pages = vm_page_alloc_contig(npgs, low, high,
- alignment, boundary);
+ alignment, boundary, flags);
if (pages == NULL) {
ret = NULL;
} else {
More information about the freebsd-bugs
mailing list