summaryrefslogtreecommitdiffstats
path: root/sys/vm/phys_pager.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2007-08-18 16:40:33 +0000
committerkib <kib@FreeBSD.org>2007-08-18 16:40:33 +0000
commitba6ef6eccaefee0eb05036b28d4e1074aa92ea5c (patch)
tree8d3069975564b76f59783f6cab8fa5fed278be76 /sys/vm/phys_pager.c
parentc58bdad9f2ec03ff531566782125fee5182ff68f (diff)
downloadFreeBSD-src-ba6ef6eccaefee0eb05036b28d4e1074aa92ea5c.zip
FreeBSD-src-ba6ef6eccaefee0eb05036b28d4e1074aa92ea5c.tar.gz
Fix the phys_pager in the way similar to the rev. 1.83 of the
sys/vm/device_pager.c: Protect the creation of the phys pager with non-NULL handle with the phys_pager_mtx. Lookup of phys pager in the pagers list by handle is now synchronized with its removal from the list, and phys_pager_mtx is put before vm object lock in lock order. Dispose the phys_pager_alloc_lock and tsleep calls, together with acquiring Giant, since phys_pager_mtx now covers the same block. Reviewed by: alc Approved by: re (kensmith)
Diffstat (limited to 'sys/vm/phys_pager.c')
-rw-r--r--sys/vm/phys_pager.c47
1 files changed, 25 insertions, 22 deletions
diff --git a/sys/vm/phys_pager.c b/sys/vm/phys_pager.c
index 626e888..c699b8f 100644
--- a/sys/vm/phys_pager.c
+++ b/sys/vm/phys_pager.c
@@ -42,8 +42,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_page.h>
#include <vm/vm_pager.h>
-/* prevent concurrent creation races */
-static int phys_pager_alloc_lock;
/* list of device pager objects */
static struct pagerlst phys_pager_object_list;
/* protect access to phys_pager_object_list */
@@ -64,7 +62,7 @@ static vm_object_t
phys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
vm_ooffset_t foff)
{
- vm_object_t object;
+ vm_object_t object, object1;
vm_pindex_t pindex;
/*
@@ -76,38 +74,41 @@ phys_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot,
pindex = OFF_TO_IDX(foff + PAGE_MASK + size);
if (handle != NULL) {
- mtx_lock(&Giant);
- /*
- * Lock to prevent object creation race condition.
- */
- while (phys_pager_alloc_lock) {
- phys_pager_alloc_lock = -1;
- tsleep(&phys_pager_alloc_lock, PVM, "swpalc", 0);
- }
- phys_pager_alloc_lock = 1;
-
+ mtx_lock(&phys_pager_mtx);
/*
* Look up pager, creating as necessary.
*/
+ object1 = NULL;
object = vm_pager_object_lookup(&phys_pager_object_list, handle);
if (object == NULL) {
/*
* Allocate object and associate it with the pager.
*/
- object = vm_object_allocate(OBJT_PHYS, pindex);
- object->handle = handle;
- mtx_lock(&phys_pager_mtx);
- TAILQ_INSERT_TAIL(&phys_pager_object_list, object,
- pager_object_list);
mtx_unlock(&phys_pager_mtx);
+ object1 = vm_object_allocate(OBJT_PHYS, pindex);
+ mtx_lock(&phys_pager_mtx);
+ object = vm_pager_object_lookup(&phys_pager_object_list,
+ handle);
+ if (object != NULL) {
+ /*
+ * We raced with other thread while
+ * allocating object.
+ */
+ if (pindex > object->size)
+ object->size = pindex;
+ } else {
+ object = object1;
+ object1 = NULL;
+ object->handle = handle;
+ TAILQ_INSERT_TAIL(&phys_pager_object_list, object,
+ pager_object_list);
+ }
} else {
if (pindex > object->size)
object->size = pindex;
}
- if (phys_pager_alloc_lock == -1)
- wakeup(&phys_pager_alloc_lock);
- phys_pager_alloc_lock = 0;
- mtx_unlock(&Giant);
+ mtx_unlock(&phys_pager_mtx);
+ vm_object_deallocate(object1);
} else {
object = vm_object_allocate(OBJT_PHYS, pindex);
}
@@ -123,9 +124,11 @@ phys_pager_dealloc(vm_object_t object)
{
if (object->handle != NULL) {
+ VM_OBJECT_UNLOCK(object);
mtx_lock(&phys_pager_mtx);
TAILQ_REMOVE(&phys_pager_object_list, object, pager_object_list);
mtx_unlock(&phys_pager_mtx);
+ VM_OBJECT_LOCK(object);
}
}
OpenPOWER on IntegriCloud