[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] xen memory allocator: Dynamically allocate per-numa-node metadata.



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1172319562 0
# Node ID 8afe591c272ba27b0aca7943ce58cfdab16630cb
# Parent  e9bd3267ff237c4435c14aada17397230b42b377
xen memory allocator: Dynamically allocate per-numa-node metadata.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/common/page_alloc.c |  107 ++++++++++++++++++++++++++----------------------
 1 files changed, 58 insertions(+), 49 deletions(-)

diff -r e9bd3267ff23 -r 8afe591c272b xen/common/page_alloc.c
--- a/xen/common/page_alloc.c   Fri Feb 23 17:26:07 2007 -0800
+++ b/xen/common/page_alloc.c   Sat Feb 24 12:19:22 2007 +0000
@@ -319,11 +319,23 @@ unsigned long alloc_boot_pages(
 
 #define pfn_dom_zone_type(_pfn) (fls(_pfn) - 1)
 
-static struct list_head heap[NR_ZONES][MAX_NUMNODES][MAX_ORDER+1];
-
-static unsigned long avail[NR_ZONES][MAX_NUMNODES];
+typedef struct list_head heap_by_zone_and_order_t[NR_ZONES][MAX_ORDER+1];
+static heap_by_zone_and_order_t _heap0;
+static heap_by_zone_and_order_t *_heap[MAX_NUMNODES];
+#define heap(node, zone, order) ((*_heap[node])[zone][order])
+
+static unsigned long avail0[NR_ZONES];
+static unsigned long *avail[MAX_NUMNODES];
 
 static DEFINE_SPINLOCK(heap_lock);
+
+static void init_heap_block(heap_by_zone_and_order_t *heap_block)
+{
+    int i, j;
+    for ( i = 0; i < NR_ZONES; i++ )
+        for ( j = 0; j <= MAX_ORDER; j++ )
+            INIT_LIST_HEAD(&(*heap_block)[i][j]);
+}
 
 /* Allocate 2^@order contiguous pages. */
 static struct page_info *alloc_heap_pages(
@@ -353,17 +365,18 @@ static struct page_info *alloc_heap_page
         for ( zone = zone_hi; zone >= zone_lo; --zone )
         {
             /* check if target node can support the allocation */
-            if ( avail[zone][node] >= request )
+            if ( avail[node] && (avail[node][zone] >= request) )
             {
                 /* Find smallest order which can satisfy the request. */
                 for ( j = order; j <= MAX_ORDER; j++ )
                 {
-                    if ( !list_empty(&heap[zone][node][j]) )
+                    if ( !list_empty(&heap(node, zone, j)) )
                         goto found;
                 }
             }
         }
-        /* pick next node, wrapping around if needed */
+
+        /* Pick next node, wrapping around if needed. */
         if ( ++node == num_nodes )
             node = 0;
     }
@@ -373,20 +386,20 @@ static struct page_info *alloc_heap_page
     return NULL;
 
  found: 
-    pg = list_entry(heap[zone][node][j].next, struct page_info, list);
+    pg = list_entry(heap(node, zone, j).next, struct page_info, list);
     list_del(&pg->list);
 
     /* We may have to halve the chunk a number of times. */
     while ( j != order )
     {
         PFN_ORDER(pg) = --j;
-        list_add_tail(&pg->list, &heap[zone][node][j]);
+        list_add_tail(&pg->list, &heap(node, zone, j));
         pg += 1 << j;
     }
     
     map_alloc(page_to_mfn(pg), request);
-    ASSERT(avail[zone][node] >= request);
-    avail[zone][node] -= request;
+    ASSERT(avail[node][zone] >= request);
+    avail[node][zone] -= request;
 
     spin_unlock(&heap_lock);
 
@@ -408,8 +421,8 @@ static void free_heap_pages(
     spin_lock(&heap_lock);
 
     map_free(page_to_mfn(pg), 1 << order);
-    avail[zone][node] += 1 << order;
-    
+    avail[node][zone] += 1 << order;
+
     /* Merge chunks as far as possible. */
     while ( order < MAX_ORDER )
     {
@@ -435,12 +448,12 @@ static void free_heap_pages(
         
         order++;
 
-        /* after merging, pg should be in the same node */
-        ASSERT(phys_to_nid(page_to_maddr(pg)) == node );
+        /* After merging, pg should remain in the same node. */
+        ASSERT(phys_to_nid(page_to_maddr(pg)) == node);
     }
 
     PFN_ORDER(pg) = order;
-    list_add_tail(&pg->list, &heap[zone][node][order]);
+    list_add_tail(&pg->list, &heap(node, zone, order));
 
     spin_unlock(&heap_lock);
 }
@@ -468,6 +481,14 @@ void init_heap_pages(
     for ( i = 0; i < nr_pages; i++ )
     {
         nid_curr = phys_to_nid(page_to_maddr(pg+i));
+
+        if ( !avail[nid_curr] )
+        {
+            avail[nid_curr] = xmalloc_array(unsigned long, NR_ZONES);
+            memset(avail[nid_curr], 0, NR_ZONES * sizeof(long));
+            _heap[nid_curr] = xmalloc(heap_by_zone_and_order_t);
+            init_heap_block(_heap[nid_curr]);
+        }
 
         /*
          * free pages of the same node, or if they differ, but are on a
@@ -492,25 +513,27 @@ static unsigned long avail_heap_pages(
 
     if ( zone_hi >= NR_ZONES )
         zone_hi = NR_ZONES - 1;
-    for ( zone = zone_lo; zone <= zone_hi; zone++ )
-        for ( i = 0; i < num_nodes; i++ )
+
+    for ( i = 0; i < num_nodes; i++ )
+    {
+        if ( !avail[i] )
+            continue;
+        for ( zone = zone_lo; zone <= zone_hi; zone++ )
             if ( (node == -1) || (node == i) )
-                free_pages += avail[zone][i];
+                free_pages += avail[i][zone];
+    }
 
     return free_pages;
 }
 
 void end_boot_allocator(void)
 {
-    unsigned long i, j, k;
+    unsigned long i;
     int curr_free, next_free;
 
-    memset(avail, 0, sizeof(avail));
-
-    for ( i = 0; i < NR_ZONES; i++ )
-        for ( j = 0; j < MAX_NUMNODES; j++ )
-            for ( k = 0; k <= MAX_ORDER; k++ )
-                INIT_LIST_HEAD(&heap[i][j][k]);
+    init_heap_block(&_heap0);
+    _heap[0] = &_heap0;
+    avail[0] = avail0;
 
     /* Pages that are free now go to the domain sub-allocator. */
     if ( (curr_free = next_free = !allocated_in_map(first_valid_mfn)) )
@@ -1007,36 +1030,22 @@ unsigned long avail_scrub_pages(void)
     return scrub_pages;
 }
 
-static unsigned long count_bucket(struct list_head* l, int order)
-{
-    unsigned long total_pages = 0;
-    int pages = 1 << order;
-    struct page_info *pg;
-
-    list_for_each_entry(pg, l, list)
-        total_pages += pages;
-
-    return total_pages;
-}
-
 static void dump_heap(unsigned char key)
 {
-    s_time_t       now = NOW();
-    int i,j,k;
-    unsigned long total;
+    s_time_t      now = NOW();
+    int           i, j;
 
     printk("'%c' pressed -> dumping heap info (now-0x%X:%08X)\n", key,
            (u32)(now>>32), (u32)now);
 
-    for (i=0; i<NR_ZONES; i++ )
-        for (j=0;j<MAX_NUMNODES;j++)
-            for (k=0;k<=MAX_ORDER;k++)
-                if ( !list_empty(&heap[i][j][k]) )
-                {
-                    total = count_bucket(&heap[i][j][k], k);
-                    printk("heap[%d][%d][%d]-> %lu pages\n",
-                            i, j, k, total);
-                }
+    for ( i = 0; i < MAX_NUMNODES; i++ )
+    {
+        if ( !avail[i] )
+            continue;
+        for ( j = 0; j < NR_ZONES; j++ )
+            printk("heap[node=%d][zone=%d] -> %lu pages\n",
+                   i, j, avail[i][j]);
+    }
 }
 
 static __init int register_heap_trigger(void)

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.