PERFORCE change 85860 for review

Alan Cox alc at FreeBSD.org
Tue Oct 25 19:24:40 PDT 2005


http://perforce.freebsd.org/chv.cgi?CH=85860

Change 85860 by alc at alc_sp01 on 2005/10/26 02:24:09

	Properly synchronize the preemption of reservations.

Affected files ...

.. //depot/projects/superpages/src/sys/vm/vm_reserve.c#8 edit

Differences ...

==== //depot/projects/superpages/src/sys/vm/vm_reserve.c#8 (text+ko) ====

@@ -512,8 +512,10 @@
 preempt_contig_alloc(int *level, int free_pool)
 {
 	int l, lev = level ? *level : -1;
+	vm_object_t object;
 	vm_page_t m = NULL;
-	reservation_t sp;
+	reservation_t sp, sp_next;
+	boolean_t was_trylocked;
 
 retry:
 	if (free_pool) {
@@ -531,13 +533,26 @@
 
 	/* 3. try rres at level lev or higher */
 	for (l = lev; l <= SP_LEVELS - 2; l++) {
-		while ( (sp = TAILQ_FIRST(&rres[l])) ) {
+		mtx_lock(&rres_mtx);
+		TAILQ_FOREACH_SAFE(sp, &rres[l], next, sp_next) {
 			KASSERT(sp->rql==l && sp->rql<sp->level,("preempt_contig_alloc: rql invalid"));
-			preempt(sp, lev, NULL);
-			m = buddy_alloc(SP_ORDER(lev), FALSE);
-			if (m != NULL)
-				goto done;
+                        object = sp->object;
+                        was_trylocked = VM_OBJECT_TRYLOCK(object);
+                        if (was_trylocked || VM_OBJECT_LOCKED(object)) {
+				TAILQ_REMOVE(&rres[l], sp, next);
+				mtx_unlock(&rres_mtx);
+				sp->rql = NO_RESQ;
+				preempt(sp, lev, NULL);
+				if (was_trylocked)
+					VM_OBJECT_UNLOCK(object);
+				m = buddy_alloc(SP_ORDER(lev), FALSE);
+				if (m != NULL)
+					goto done;
+				mtx_lock(&rres_mtx);
+				sp_next = TAILQ_FIRST(&rres[l]);
+			}
 		}
+		mtx_unlock(&rres_mtx);
 	}
 
 	/* Downgrade level, retry free, rres... */
@@ -552,13 +567,26 @@
 		}
 
 		/* 5, 7, 9... */
-		while ( (sp = TAILQ_FIRST(&rres[lev])) ) {
+		mtx_lock(&rres_mtx);
+		TAILQ_FOREACH_SAFE(sp, &rres[lev], next, sp_next) {
 			KASSERT(sp->rql==lev && sp->rql<sp->level,("preempt_alloc_contig"));
-			preempt(sp, lev, NULL);
-			m = buddy_alloc(SP_ORDER(lev), FALSE);
-			if (m != NULL)
-				goto done;
+                        object = sp->object;
+                        was_trylocked = VM_OBJECT_TRYLOCK(object);
+                        if (was_trylocked || VM_OBJECT_LOCKED(object)) {
+				TAILQ_REMOVE(&rres[lev], sp, next);
+				mtx_unlock(&rres_mtx);
+				sp->rql = NO_RESQ;
+				preempt(sp, lev, NULL);
+				if (was_trylocked)
+					VM_OBJECT_UNLOCK(object);
+				m = buddy_alloc(SP_ORDER(lev), FALSE);
+				if (m != NULL)
+					goto done;
+				mtx_lock(&rres_mtx);
+				sp_next = TAILQ_FIRST(&rres[lev]);
+			}
 		}
+		mtx_unlock(&rres_mtx);
 	}
 done:		
 	KASSERT(*level>= -1,("preempt_alloc_contig"));


More information about the p4-projects mailing list