aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-08-11 12:20:11 +0100
committerKeir Fraser <keir.fraser@citrix.com>2008-08-11 12:20:11 +0100
commit42b54bfe29e05563b5bd17182d4b8c2dd5cb1dc6 (patch)
tree63ecc3f622682b515977513eea0706584bb0ad39
parent3ca259a393756ab0a00ce0a332184d596b37b8b1 (diff)
downloadxen-42b54bfe29e05563b5bd17182d4b8c2dd5cb1dc6.tar.gz
xen-42b54bfe29e05563b5bd17182d4b8c2dd5cb1dc6.tar.bz2
xen-42b54bfe29e05563b5bd17182d4b8c2dd5cb1dc6.zip
page scrub: Serialise softirq with a new lock.
Avoids holding up acquiring page_scrub_lock in free_domheap_pages(). Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
-rw-r--r--xen/common/page_alloc.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index b202570a0f..d9e0a2946a 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -950,9 +950,10 @@ static void page_scrub_softirq(void)
void *p;
int i;
s_time_t start = NOW();
+ static spinlock_t serialise_lock = SPIN_LOCK_UNLOCKED;
/* free_heap_pages() does not parallelise well. Serialise this function. */
- if ( !spin_trylock(&page_scrub_lock) )
+ if ( !spin_trylock(&serialise_lock) )
{
set_timer(&this_cpu(page_scrub_timer), NOW() + MILLISECS(1));
return;
@@ -960,10 +961,12 @@ static void page_scrub_softirq(void)
/* Aim to do 1ms of work every 10ms. */
do {
+ spin_lock(&page_scrub_lock);
+
if ( unlikely((ent = page_scrub_list.next) == &page_scrub_list) )
{
spin_unlock(&page_scrub_lock);
- return;
+ goto out;
}
/* Peel up to 16 pages from the list. */
@@ -979,6 +982,8 @@ static void page_scrub_softirq(void)
page_scrub_list.next = ent->next;
scrub_pages -= (i+1);
+ spin_unlock(&page_scrub_lock);
+
/* Working backwards, scrub each page in turn. */
while ( ent != &page_scrub_list )
{
@@ -991,9 +996,10 @@ static void page_scrub_softirq(void)
}
} while ( (NOW() - start) < MILLISECS(1) );
- spin_unlock(&page_scrub_lock);
-
set_timer(&this_cpu(page_scrub_timer), NOW() + MILLISECS(10));
+
+ out:
+ spin_unlock(&serialise_lock);
}
static void page_scrub_timer_fn(void *unused)