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;
}