Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 03 Oct 2001 21:05:36 -0400
From:      Brian Fundakowski Feldman <green@FreeBSD.org>
To:        arch@FreeBSD.org
Subject:   sx-ifying src/sys/vm
Message-ID:  <200110040105.f9415av15297@green.bikeshed.org>

next in thread | raw e-mail | index | archive | help
I've taken a shot at changing the vm_map locking from using lockmgr() locks 
(EAAARGHH...) to sx locks.  Already I can tell that it 1. seems to work and 
2. seems to not give me bogus lock ordering messages like lockmgr() used to.
I'd appreciate if people took a look at it and told me of any concerns, 
whether it also looks fine to more than just myself, etc.

I added a few more vm_map locking operations than were there already for the 
purpose of removing the hard-coded lockmgr() ops that were in a few places 
previously.  Instead of having a sx_locked() operation I used 
sx_try_xlock(), and instead of recursion I saved the state of the one case 
where a lock was attempted to be "recursed" upon, and removed the actual 
recursion on the lock.

I also used EWOULDBLOCK instead of EBUSY as a return value for operations 
that would block on attempting to acquire a lock, which I think makes more 
sense, but in any case is not used currently in any of the code.  I could go 
either way on that :)

Here are all the changes for review:

Index: vm_fault.c
===================================================================
RCS file: /home/freebsd/ncvs/src/sys/vm/vm_fault.c,v
retrieving revision 1.125
diff -u -r1.125 vm_fault.c
--- vm_fault.c	2001/09/12 08:38:11	1.125
+++ vm_fault.c	2001/10/04 00:41:36
@@ -114,6 +114,7 @@
 	vm_map_entry_t entry;
 	int lookup_still_valid;
 	struct vnode *vp;
+	int lockheld;
 };
 
 static __inline void
@@ -127,7 +128,7 @@
 static __inline void
 unlock_map(struct faultstate *fs)
 {
-	if (fs->lookup_still_valid) {
+	if (fs->lookup_still_valid && !fs->lockheld) {
 		vm_map_lookup_done(fs->map, fs->entry);
 		fs->lookup_still_valid = FALSE;
 	}
@@ -213,12 +214,16 @@
 	int hardfault;
 	int faultcount;
 	struct faultstate fs;
+	boolean_t user_wire;
 
 	GIANT_REQUIRED;
 
 	cnt.v_vm_faults++;
 	hardfault = 0;
+	user_wire = (fault_flags & VM_FAULT_WIRE_MASK) == VM_FAULT_USER_WIRE;
+	fs.lockheld = user_wire;
 
+
 RetryFault:;
 
 	/*
@@ -226,13 +231,11 @@
 	 * search.
 	 */
 	fs.map = map;
-	if ((result = vm_map_lookup(&fs.map, vaddr,
+	if ((result = vm_map_lookup2(&fs.map, vaddr,
 		fault_type, &fs.entry, &fs.first_object,
-		&fs.first_pindex, &prot, &wired)) != KERN_SUCCESS) {
-		if ((result != KERN_PROTECTION_FAILURE) ||
-			((fault_flags & VM_FAULT_WIRE_MASK) != VM_FAULT_USER_WIRE)) {
+		&fs.first_pindex, &prot, &wired, user_wire)) != KERN_SUCCESS) {
+		if (result != KERN_PROTECTION_FAILURE || !user_wire)
 			return result;
-		}
 
 		/*
    		 * If we are user-wiring a r/w segment, and it is COW, then
@@ -241,9 +244,10 @@
    		 * to COW .text.  We simply keep .text from ever being COW'ed
    		 * and take the heat that one cannot debug wired .text sections.
    		 */
-		result = vm_map_lookup(&fs.map, vaddr,
+		result = vm_map_lookup2(&fs.map, vaddr,
 			VM_PROT_READ|VM_PROT_WRITE|VM_PROT_OVERRIDE_WRITE,
-			&fs.entry, &fs.first_object, &fs.first_pindex, &prot, &wired);
+			&fs.entry, &fs.first_object, &fs.first_pindex, &prot,
+			&wired, user_wire);
 		if (result != KERN_SUCCESS) {
 			return result;
 		}
@@ -666,7 +670,7 @@
 				 * grab the lock if we need to
 				 */
 				(fs.lookup_still_valid ||
-				 lockmgr(&fs.map->lock, LK_EXCLUSIVE|LK_NOWAIT, (void *)0, curthread) == 0)
+				 vm_map_lock_upgrade(fs.map) == 0)
 			    ) {
 				
 				fs.lookup_still_valid = 1;
Index: vm_glue.c
===================================================================
RCS file: /home/freebsd/ncvs/src/sys/vm/vm_glue.c,v
retrieving revision 1.119
diff -u -r1.119 vm_glue.c
--- vm_glue.c	2001/09/12 08:38:11	1.119
+++ vm_glue.c	2001/10/04 00:41:37
@@ -577,9 +577,7 @@
 			 * data structures there is a
 			 * possible deadlock.
 			 */
-			if (lockmgr(&vm->vm_map.lock,
-					LK_EXCLUSIVE | LK_NOWAIT,
-					NULL, curthread)) {
+			if (vm_map_trylock(&vm->vm_map)) {
 				vmspace_free(vm);
 				PROC_UNLOCK(p);
 				goto nextproc;
Index: vm_map.c
===================================================================
RCS file: /home/freebsd/ncvs/src/sys/vm/vm_map.c,v
retrieving revision 1.207
diff -u -r1.207 vm_map.c
--- vm_map.c	2001/09/12 08:38:11	1.207
+++ vm_map.c	2001/10/04 00:41:44
@@ -266,70 +266,59 @@
 vm_map_lock(vm_map_t map)
 {
 	vm_map_printf("locking map LK_EXCLUSIVE: %p\n", map);
-	if (lockmgr(&map->lock, LK_EXCLUSIVE, NULL, curthread) != 0)
-		panic("vm_map_lock: failed to get lock");
+	sx_xlock(&map->lock);
 	map->timestamp++;
 }
 
+int
+vm_map_trylock(vm_map_t map)
+{
+	vm_map_printf("trying to lock map LK_EXCLUSIVE: %p\n", map);
+	if (sx_try_xlock(&map->lock)) {
+		map->timestamp++;
+		return (0);
+	}
+	return (EWOULDBLOCK);
+}
+
 void
 vm_map_unlock(vm_map_t map)
 {
 	vm_map_printf("locking map LK_RELEASE: %p\n", map);
-	lockmgr(&(map)->lock, LK_RELEASE, NULL, curthread);
+	sx_xunlock(&map->lock);
 }
 
 void
 vm_map_lock_read(vm_map_t map)
 {
 	vm_map_printf("locking map LK_SHARED: %p\n", map);
-	lockmgr(&(map)->lock, LK_SHARED, NULL, curthread);
+	sx_slock(&map->lock);
 }
 
 void
 vm_map_unlock_read(vm_map_t map)
 {
 	vm_map_printf("locking map LK_RELEASE: %p\n", map);
-	lockmgr(&(map)->lock, LK_RELEASE, NULL, curthread);
-}
-
-static __inline__ int
-_vm_map_lock_upgrade(vm_map_t map, struct thread *td) {
-	int error;
-
-	vm_map_printf("locking map LK_EXCLUPGRADE: %p\n", map); 
-	error = lockmgr(&map->lock, LK_EXCLUPGRADE, NULL, td);
-	if (error == 0)
-		map->timestamp++;
-	return error;
+	sx_sunlock(&map->lock);
 }
 
 int
 vm_map_lock_upgrade(vm_map_t map)
 {
-    return(_vm_map_lock_upgrade(map, curthread));
+	vm_map_printf("locking map LK_EXCLUPGRADE: %p\n", map); 
+	if (sx_try_upgrade(&map->lock)) {
+		map->timestamp++;
+		return (0);
+	}
+	sx_sunlock(&map->lock);
+	return (EWOULDBLOCK);
 }
 
 void
 vm_map_lock_downgrade(vm_map_t map)
 {
 	vm_map_printf("locking map LK_DOWNGRADE: %p\n", map);
-	lockmgr(&map->lock, LK_DOWNGRADE, NULL, curthread);
-}
-
-void
-vm_map_set_recursive(vm_map_t map)
-{
-	mtx_lock((map)->lock.lk_interlock);
-	map->lock.lk_flags |= LK_CANRECURSE;
-	mtx_unlock((map)->lock.lk_interlock);
-}
-
-void
-vm_map_clear_recursive(vm_map_t map)
-{
-	mtx_lock((map)->lock.lk_interlock);
-	map->lock.lk_flags &= ~LK_CANRECURSE;
-	mtx_unlock((map)->lock.lk_interlock);
+	sx_downgrade(&map->lock);
 }
 
 vm_offset_t
@@ -403,7 +392,7 @@
 	map->first_free = &map->header;
 	map->hint = &map->header;
 	map->timestamp = 0;
-	lockinit(&map->lock, PVM, "thrd_sleep", 0, LK_NOPAUSE);
+	sx_init(&map->lock, "thrd_sleep");
 }
 
 void
@@ -411,7 +400,7 @@
 	struct vm_map *map;
 {
 	GIANT_REQUIRED;
-	lockdestroy(&map->lock);
+	sx_destroy(&map->lock);
 }
 
 /*
@@ -1490,7 +1479,6 @@
 			estart = entry->start;
 
 			/* First we need to allow map modifications */
-			vm_map_set_recursive(map);
 			vm_map_lock_downgrade(map);
 			map->timestamp++;
 
@@ -1500,14 +1488,12 @@
 				entry->wired_count--;
 				entry->eflags &= ~MAP_ENTRY_USER_WIRED;
 
-				vm_map_clear_recursive(map);
-				vm_map_unlock(map);
+				vm_map_unlock_read(map);
 				
 				(void) vm_map_user_pageable(map, start, entry->start, TRUE);
 				return rv;
 			}
 
-			vm_map_clear_recursive(map);
 			if (vm_map_lock_upgrade(map)) {
 				vm_map_lock(map);
 				if (vm_map_lookup_entry(map, estart, &entry) 
@@ -1748,14 +1734,20 @@
 			vm_map_lock(map);
 		}
 		if (rv) {
-			vm_map_unlock(map);
+			if (vm_map_pmap(map) == kernel_pmap)
+				vm_map_unlock(map);
+			else
+				vm_map_unlock_read(map);
 			(void) vm_map_pageable(map, start, failed, TRUE);
 			return (rv);
 		}
 		vm_map_simplify_entry(map, start_entry);
 	}
 
-	vm_map_unlock(map);
+	if (new_pageable || vm_map_pmap(map) == kernel_pmap)
+		vm_map_unlock(map);
+	else
+		vm_map_unlock_read(map);
 
 	return (KERN_SUCCESS);
 }
@@ -2678,6 +2670,22 @@
 	      vm_prot_t *out_prot,		/* OUT */
 	      boolean_t *wired)			/* OUT */
 {
+	
+	return (vm_map_lookup2(var_map, vaddr, fault_typea, out_entry,
+	    object, pindex, out_prot, wired, 0));
+}
+
+int
+vm_map_lookup2(vm_map_t *var_map,		/* IN/OUT */
+	      vm_offset_t vaddr,
+	      vm_prot_t fault_typea,
+	      vm_map_entry_t *out_entry,	/* OUT */
+	      vm_object_t *object,		/* OUT */
+	      vm_pindex_t *pindex,		/* OUT */
+	      vm_prot_t *out_prot,		/* OUT */
+	      boolean_t *wired,			/* OUT */
+	      boolean_t lockheld)
+{
 	vm_map_entry_t entry;
 	vm_map_t map = *var_map;
 	vm_prot_t prot;
@@ -2690,11 +2698,13 @@
 	 * Lookup the faulting address.
 	 */
 
-	vm_map_lock_read(map);
+	if (!lockheld)
+		vm_map_lock_read(map);
 
 #define	RETURN(why) \
 		{ \
-		vm_map_unlock_read(map); \
+		if (!lockheld) \
+			vm_map_unlock_read(map); \
 		return(why); \
 		}
 
@@ -2730,7 +2740,8 @@
 		vm_map_t old_map = map;
 
 		*var_map = map = entry->object.sub_map;
-		vm_map_unlock_read(old_map);
+		if (!lockheld)
+			vm_map_unlock_read(old_map);
 		goto RetryLookup;
 	}
 
Index: vm_map.h
===================================================================
RCS file: /home/freebsd/ncvs/src/sys/vm/vm_map.h,v
retrieving revision 1.67
diff -u -r1.67 vm_map.h
--- vm_map.h	2001/09/12 08:38:11	1.67
+++ vm_map.h	2001/10/04 00:41:44
@@ -71,7 +71,8 @@
 #ifndef	_VM_MAP_
 #define	_VM_MAP_
 
-#include <sys/lockmgr.h>
+#include <sys/lock.h>
+#include <sys/sx.h>
 
 #ifdef MAP_LOCK_DIAGNOSTIC
 #include <sys/systm.h>
@@ -154,7 +155,7 @@
  */
 struct vm_map {
 	struct vm_map_entry header;	/* List of entries */
-	struct lock lock;		/* Lock for map data */
+	struct sx lock;			/* Lock for map data */
 	int nentries;			/* Number of entries */
 	vm_size_t size;			/* virtual size */
 	u_char system_map;		/* Am I a system map? */
@@ -216,13 +217,12 @@
 #endif
 
 void vm_map_lock(vm_map_t map);
+int vm_map_trylock(vm_map_t map);
 void vm_map_unlock(vm_map_t map);
 void vm_map_lock_read(vm_map_t map);
 void vm_map_unlock_read(vm_map_t map);
 int vm_map_lock_upgrade(vm_map_t map);
 void vm_map_lock_downgrade(vm_map_t map);
-void vm_map_set_recursive(vm_map_t map);
-void vm_map_clear_recursive(vm_map_t map);
 vm_offset_t vm_map_min(vm_map_t map);
 vm_offset_t vm_map_max(vm_map_t map);
 struct pmap *vm_map_pmap(vm_map_t map);
@@ -272,6 +272,8 @@
 int vm_map_insert (vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t, vm_offset_t, vm_prot_t, vm_prot_t, int);
 int vm_map_lookup (vm_map_t *, vm_offset_t, vm_prot_t, vm_map_entry_t *, vm_object_t *,
     vm_pindex_t *, vm_prot_t *, boolean_t *);
+int vm_map_lookup2 (vm_map_t *, vm_offset_t, vm_prot_t, vm_map_entry_t *, vm_object_t *,
+    vm_pindex_t *, vm_prot_t *, boolean_t *, boolean_t);
 void vm_map_lookup_done (vm_map_t, vm_map_entry_t);
 boolean_t vm_map_lookup_entry (vm_map_t, vm_offset_t, vm_map_entry_t *);
 int vm_map_pageable (vm_map_t, vm_offset_t, vm_offset_t, boolean_t);
Index: vm_pageout.c
===================================================================
RCS file: /home/freebsd/ncvs/src/sys/vm/vm_pageout.c,v
retrieving revision 1.183
diff -u -r1.183 vm_pageout.c
--- vm_pageout.c	2001/09/12 08:38:11	1.183
+++ vm_pageout.c	2001/10/04 00:41:47
@@ -546,9 +546,8 @@
 	vm_object_t obj, bigobj;
 
 	GIANT_REQUIRED;
-	if (lockmgr(&map->lock, LK_EXCLUSIVE | LK_NOWAIT, (void *)0, curthread)) {
+	if (vm_map_trylock(map))
 		return;
-	}
 
 	bigobj = NULL;
 
Index: vm_zone.c
===================================================================
RCS file: /home/freebsd/ncvs/src/sys/vm/vm_zone.c,v
retrieving revision 1.48
diff -u -r1.48 vm_zone.c
--- vm_zone.c	2001/08/05 03:55:02	1.48
+++ vm_zone.c	2001/10/04 00:41:48
@@ -409,11 +409,12 @@
 		 * map.
 		 */
 		mtx_unlock(&z->zmtx);
-		if (lockstatus(&kernel_map->lock, NULL)) {
+		if (vm_map_trylock(kernel_map)) {
 			item = (void *) kmem_malloc(kmem_map, nbytes, M_WAITOK);
 			if (item != NULL)
 				atomic_add_int(&zone_kmem_pages, z->zalloc);
 		} else {
+			vm_map_unlock(kernel_map);
 			item = (void *) kmem_alloc(kernel_map, nbytes);
 			if (item != NULL)
 				atomic_add_int(&zone_kern_pages, z->zalloc);


-- 
 Brian Fundakowski Feldman           \  FreeBSD: The Power to Serve!  /
 green@FreeBSD.org                    `------------------------------'



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200110040105.f9415av15297>