shithub: riscv

Download patch

ref: a43321946e0f661f51290988c7e7567262d403bd
parent: 98a7eae9c0cdb31a48c79b34c5f263916a8c1390
author: cinap_lenrek <[email protected]>
date: Sun Apr 12 14:08:06 EDT 2015

segment: speed up fixedseg() doing single pass over freelist

walking the freelist for every page is too slow. as we
are freeing a range, we can do a single pass unlinking all
pages in our range and at the end, check if all pages
where freed, if not put the pages that we did free back
and retry, otherwise we'r done.

--- a/sys/src/9/port/devsegment.c
+++ b/sys/src/9/port/devsegment.c
@@ -580,8 +580,8 @@
 {
 	KMap *k;
 	Segment *s;
-	Page **f, *p;
-	ulong n, i, j;
+	Page **f, *p, *l, *h;
+	ulong n, i;
 	int color;
 
 	s = newseg(SG_FIXED, va, len);
@@ -591,10 +591,10 @@
 	}
 	lock(&palloc);
 	i = 0;
-	p = palloc.pages;
+	l = palloc.pages;
 	color = getpgcolor(va);
-	for(n = palloc.user; n >= len; n--, p++){
-		if(p->ref != 0 || i != 0 && (p[-1].pa+BY2PG) != p->pa || i == 0 && p->color != color){
+	for(n = palloc.user; n >= len; n--, l++){
+		if(l->ref != 0 || i != 0 && (l[-1].pa+BY2PG) != l->pa || i == 0 && l->color != color){
 		Retry:
 			i = 0;
 			continue;
@@ -601,22 +601,34 @@
 		}
 		if(++i < len)
 			continue;
-		for(j = 0; j < i; j++, p--){
-			for(f = &palloc.head; *f != nil; f = &((*f)->next)){
-				if(*f == p){
-					*f = p->next;
-					goto Freed;
-				}
+
+		i = 0;
+		h = nil;
+		f = &palloc.head;
+		while((p = *f) != nil){
+			if(p > &l[-len] && p <= l){
+				*f = p->next;
+				p->next = h;
+				h = p;
+				if(++i < len)
+					continue;
+				break;
 			}
-			while(j-- > 0)
-				pagechainhead(++p);
+			f = &p->next;
+		}
+		palloc.freecount -= i;
+
+		if(i != len){
+			while((p = h) != nil){
+				h = h->next;
+				pagechainhead(p);
+			}
 			goto Retry;
-		Freed:
-			palloc.freecount--;
 		}
 		unlock(&palloc);
 
-		while(i-- > 0){
+		p = &l[-len];
+		do {
 			p++;
 			p->ref = 1;
 			p->va = va;
@@ -629,7 +641,7 @@
 			
 			segpage(s, p);
 			va += BY2PG;
-		}
+		} while(p != l);
 		poperror();
 		return s;
 	}