From: Tetsu Yamamoto <tyamamot@redhat.com> Date: Tue, 12 Aug 2008 16:07:40 -0400 Subject: [xen] page scrub: serialise softirq with a new lock Message-id: 20080812200740.4832.40135.sendpatchset@pq0-1.lab.bos.redhat.com O-Subject: [RHEL5.3 PATCH 7/7] xen: page scrub: Serialise softirq with a new lock. Bugzilla: 456171 RH-Acked-by: Chris Lalancette <clalance@redhat.com> RH-Acked-by: Bill Burns <bburns@redhat.com> bz456171 # HG changeset patch # User Keir Fraser <keir.fraser@citrix.com> # Date 1218453611 -3600 # Node ID 32aa43364f5d8e19389d1f72d9b0bf51e198152f # Parent ce085fc0d2e423aa1c602ce117cc775b000470ba 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> diff --git a/common/page_alloc.c b/common/page_alloc.c index 7a54dbe..834e09e 100644 --- a/common/page_alloc.c +++ b/common/page_alloc.c @@ -1017,9 +1017,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; @@ -1027,10 +1028,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. */ @@ -1046,6 +1049,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 ) { @@ -1058,9 +1063,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)