[PATCH] for_each_zone / for_each_pgdat

Rik van Riel (riel@conectiva.com.br)
Thu, 11 Apr 2002 21:07:11 -0300 (BRT)


replace slightly obscure while loops with for_each_zone and
for_each_pgdat macros, this version has the added optimisation
of skipping empty zones (thanks to William Lee Irwin)

-- 
Please apply,

Rik

# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.388 -> # include/linux/mmzone.h 1.7 -> 1.9 # mm/page_alloc.c 1.43 -> 1.44 # mm/vmscan.c 1.59 -> 1.60 # mm/bootmem.c 1.6 -> 1.7 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/04/11 riel@duckman.distro.conectiva 1.389 # replace slightly obscure while loops with for_each_zone and # for_each_pgdat macros (thanks to William Lee Irwin) # -------------------------------------------- # 02/04/11 riel@duckman.distro.conectiva 1.390 # skip zones of size 0 # -------------------------------------------- # diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h --- a/include/linux/mmzone.h Thu Apr 11 21:05:52 2002 +++ b/include/linux/mmzone.h Thu Apr 11 21:05:52 2002 @@ -158,6 +158,62 @@

extern pg_data_t contig_page_data;

+/** + * for_each_pgdat - helper macro to iterate over all nodes + * @pgdat - pg_data_t * variable + * + * Meant to help with common loops of the form + * pgdat = pgdat_list; + * while(pgdat) { + * ... + * pgdat = pgdat->node_next; + * } + */ +#define for_each_pgdat(pgdat) \ + for (pgdat = pgdat_list; pgdat; pgdat = pgdat->node_next) + +/* + * next_zone - helper magic for for_each_zone() + * Thanks to William Lee Irwin III for this piece of ingenuity. + */ +static inline zone_t *next_zone(zone_t *zone) +{ + pg_data_t *pgdat = zone->zone_pgdat; + + do { + if (zone - pgdat->node_zones < MAX_NR_ZONES - 1) + zone++; + + else if (pgdat->node_next) { + pgdat = pgdat->node_next; + zone = pgdat->node_zones; + } else + zone = NULL; + /* Skip zones of size 0 ... */ + } while (zone && !zone->size); + + return zone; +} + +/** + * for_each_zone - helper macro to iterate over all memory zones + * @zone - zone_t * variable + * + * The user only needs to declare the zone variable, for_each_zone + * fills it in. This basically means for_each_zone() is an + * easier to read version of this piece of code: + * + * for(pgdat = pgdat_list; pgdat; pgdat = pgdat->node_next) + * for(i = 0; i < MAX_NR_ZONES; ++i) { + * zone_t * z = pgdat->node_zones + i; + * ... + * } + * } + */ +#define for_each_zone(zone) \ + for(zone = pgdat_list->node_zones; zone; zone = next_zone(zone)) + + #ifndef CONFIG_DISCONTIGMEM

#define NODE_DATA(nid) (&contig_page_data) diff -Nru a/mm/bootmem.c b/mm/bootmem.c --- a/mm/bootmem.c Thu Apr 11 21:05:52 2002 +++ b/mm/bootmem.c Thu Apr 11 21:05:52 2002 @@ -326,12 +326,11 @@ pg_data_t *pgdat = pgdat_list; void *ptr;

- while (pgdat) { + for_each_pgdat(pgdat) if ((ptr = __alloc_bootmem_core(pgdat->bdata, size, align, goal))) return(ptr); - pgdat = pgdat->node_next; - } + /* * Whoops, we cannot satisfy the allocation request. */ diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c --- a/mm/page_alloc.c Thu Apr 11 21:05:52 2002 +++ b/mm/page_alloc.c Thu Apr 11 21:05:52 2002 @@ -479,14 +479,10 @@ { unsigned int sum; zone_t *zone; - pg_data_t *pgdat = pgdat_list;

sum = 0; - while (pgdat) { - for (zone = pgdat->node_zones; zone < pgdat->node_zones + MAX_NR_ZONES; zone++) + for_each_zone(zone) sum += zone->free_pages; - pgdat = pgdat->node_next; - } return sum; }

@@ -498,7 +494,7 @@ pg_data_t *pgdat = pgdat_list; unsigned int sum = 0;

- do { + for_each_pgdat(pgdat) { zonelist_t *zonelist = pgdat->node_zonelists + (GFP_USER & GFP_ZONEMASK); zone_t **zonep = zonelist->zones; zone_t *zone; @@ -509,9 +505,7 @@ if (size > high) sum += size - high; } - - pgdat = pgdat->node_next; - } while (pgdat); + }

return sum; } @@ -519,13 +513,12 @@ #if CONFIG_HIGHMEM unsigned int nr_free_highpages (void) { - pg_data_t *pgdat = pgdat_list; + pg_data_t *pgdat; unsigned int pages = 0;

- while (pgdat) { + for_each_pgdat(pgdat) pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages; - pgdat = pgdat->node_next; - } + return pages; } #endif diff -Nru a/mm/vmscan.c b/mm/vmscan.c --- a/mm/vmscan.c Thu Apr 11 21:05:52 2002 +++ b/mm/vmscan.c Thu Apr 11 21:05:52 2002 @@ -649,10 +649,8 @@

do { need_more_balance = 0; - pgdat = pgdat_list; - do + for_each_pgdat(pgdat) need_more_balance |= kswapd_balance_pgdat(pgdat); - while ((pgdat = pgdat->node_next)); } while (need_more_balance); }

@@ -675,12 +673,11 @@ { pg_data_t * pgdat;

- pgdat = pgdat_list; - do { + for_each_pgdat(pgdat) { if (kswapd_can_sleep_pgdat(pgdat)) continue; return 0; - } while ((pgdat = pgdat->node_next)); + }

return 1; }

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/