The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/mm/numa.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Written by Kanoj Sarcar, SGI, Aug 1999
    3  */
    4 #include <linux/config.h>
    5 #include <linux/kernel.h>
    6 #include <linux/mm.h>
    7 #include <linux/init.h>
    8 #include <linux/bootmem.h>
    9 #include <linux/mmzone.h>
   10 #include <linux/spinlock.h>
   11 
   12 int numnodes = 1;       /* Initialized for UMA platforms */
   13 
   14 static bootmem_data_t contig_bootmem_data;
   15 pg_data_t contig_page_data = { bdata: &contig_bootmem_data };
   16 
   17 #ifndef CONFIG_DISCONTIGMEM
   18 
   19 /*
   20  * This is meant to be invoked by platforms whose physical memory starts
   21  * at a considerably higher value than 0. Examples are Super-H, ARM, m68k.
   22  * Should be invoked with paramters (0, 0, unsigned long *[], start_paddr).
   23  */
   24 void __init free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
   25         unsigned long *zones_size, unsigned long zone_start_paddr, 
   26         unsigned long *zholes_size)
   27 {
   28         free_area_init_core(0, &contig_page_data, &mem_map, zones_size, 
   29                                 zone_start_paddr, zholes_size, pmap);
   30 }
   31 
   32 #endif /* !CONFIG_DISCONTIGMEM */
   33 
   34 struct page * alloc_pages_node(int nid, unsigned int gfp_mask, unsigned int order)
   35 {
   36 #ifdef CONFIG_NUMA
   37         return __alloc_pages(gfp_mask, order, NODE_DATA(nid)->node_zonelists + (gfp_mask & GFP_ZONEMASK));
   38 #else
   39         return alloc_pages(gfp_mask, order);
   40 #endif
   41 }
   42 
   43 #ifdef CONFIG_DISCONTIGMEM
   44 
   45 #define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
   46 
   47 static spinlock_t node_lock = SPIN_LOCK_UNLOCKED;
   48 
   49 void show_free_areas_node(pg_data_t *pgdat)
   50 {
   51         unsigned long flags;
   52 
   53         spin_lock_irqsave(&node_lock, flags);
   54         show_free_areas_core(pgdat);
   55         spin_unlock_irqrestore(&node_lock, flags);
   56 }
   57 
   58 /*
   59  * Nodes can be initialized parallely, in no particular order.
   60  */
   61 void __init free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
   62         unsigned long *zones_size, unsigned long zone_start_paddr, 
   63         unsigned long *zholes_size)
   64 {
   65         int i, size = 0;
   66         struct page *discard;
   67 
   68         if (mem_map == (mem_map_t *)NULL)
   69                 mem_map = (mem_map_t *)PAGE_OFFSET;
   70 
   71         free_area_init_core(nid, pgdat, &discard, zones_size, zone_start_paddr,
   72                                         zholes_size, pmap);
   73         pgdat->node_id = nid;
   74 
   75         /*
   76          * Get space for the valid bitmap.
   77          */
   78         for (i = 0; i < MAX_NR_ZONES; i++)
   79                 size += zones_size[i];
   80         size = LONG_ALIGN((size + 7) >> 3);
   81         pgdat->valid_addr_bitmap = (unsigned long *)alloc_bootmem_node(pgdat, size);
   82         memset(pgdat->valid_addr_bitmap, 0, size);
   83 }
   84 
   85 static struct page * alloc_pages_pgdat(pg_data_t *pgdat, unsigned int gfp_mask,
   86         unsigned int order)
   87 {
   88         return __alloc_pages(gfp_mask, order, pgdat->node_zonelists + (gfp_mask & GFP_ZONEMASK));
   89 }
   90 
   91 /*
   92  * This can be refined. Currently, tries to do round robin, instead
   93  * should do concentratic circle search, starting from current node.
   94  */
   95 struct page * _alloc_pages(unsigned int gfp_mask, unsigned int order)
   96 {
   97         struct page *ret = 0;
   98         pg_data_t *start, *temp;
   99 #ifndef CONFIG_NUMA
  100         unsigned long flags;
  101         static pg_data_t *next = 0;
  102 #endif
  103 
  104         if (order >= MAX_ORDER)
  105                 return NULL;
  106 #ifdef CONFIG_NUMA
  107         temp = NODE_DATA(numa_node_id());
  108 #else
  109         spin_lock_irqsave(&node_lock, flags);
  110         if (!next) next = pgdat_list;
  111         temp = next;
  112         next = next->node_next;
  113         spin_unlock_irqrestore(&node_lock, flags);
  114 #endif
  115         start = temp;
  116         while (temp) {
  117                 if ((ret = alloc_pages_pgdat(temp, gfp_mask, order)))
  118                         return(ret);
  119                 temp = temp->node_next;
  120         }
  121         temp = pgdat_list;
  122         while (temp != start) {
  123                 if ((ret = alloc_pages_pgdat(temp, gfp_mask, order)))
  124                         return(ret);
  125                 temp = temp->node_next;
  126         }
  127         return(0);
  128 }
  129 
  130 #endif /* CONFIG_DISCONTIGMEM */

Cache object: 36214e51cf28bdcfbb5011353a1440eb


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.