public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] for_each_zone / for_each_pgdat
@ 2002-04-15 15:49 Rik van Riel
  2002-04-15 20:49 ` Linus Torvalds
  0 siblings, 1 reply; 27+ messages in thread
From: Rik van Riel @ 2002-04-15 15:49 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

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)

-- 
Hi Linus,                                  [retransmit #1]

this patch cleans up the VM a little bit and has a microoptimisation
to skip zones of size zero.  You can apply this mail or pull the
changes from:

	bk://linuxvm.bkbits.net/linux-2.5-for-linus/

please apply,

thanks,

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.456   -> 1.457
#	include/linux/mmzone.h	1.8     -> 1.9
#	     mm/page_alloc.c	1.44    -> 1.45
#	         mm/vmscan.c	1.59    -> 1.60
#	        mm/bootmem.c	1.8     -> 1.9
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/04/11	riel@duckman.distro.conectiva	1.457
# 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)
# --------------------------------------------
#
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	Thu Apr 11 21:23:50 2002
+++ b/include/linux/mmzone.h	Thu Apr 11 21:23:50 2002
@@ -157,6 +157,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:23:50 2002
+++ b/mm/bootmem.c	Thu Apr 11 21:23:50 2002
@@ -338,12 +338,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:23:50 2002
+++ b/mm/page_alloc.c	Thu Apr 11 21:23:50 2002
@@ -482,14 +482,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;
 }

@@ -501,7 +497,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;
@@ -512,9 +508,7 @@
 			if (size > high)
 				sum += size - high;
 		}
-
-		pgdat = pgdat->node_next;
-	} while (pgdat);
+	}

 	return sum;
 }
@@ -522,13 +516,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:23:50 2002
+++ b/mm/vmscan.c	Thu Apr 11 21:23:50 2002
@@ -655,10 +655,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);
 }

@@ -681,12 +679,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;
 }



^ permalink raw reply	[flat|nested] 27+ messages in thread
* [PATCH] for_each_zone / for_each_pgdat
@ 2002-04-12  0:25 Rik van Riel
  2002-04-18  9:41 ` Pavel Machek
  0 siblings, 1 reply; 27+ messages in thread
From: Rik van Riel @ 2002-04-12  0:25 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

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)

-- 
Hi Linus,

this patch cleans up the VM a little bit and has a microoptimisation
to skip zones of size zero.  You can apply this mail or pull the
changes from:

	bk://linuxvm.bkbits.net/linux-2.5-for-linus/

please apply,

thanks,

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.456   -> 1.457
#	include/linux/mmzone.h	1.8     -> 1.9
#	     mm/page_alloc.c	1.44    -> 1.45
#	         mm/vmscan.c	1.59    -> 1.60
#	        mm/bootmem.c	1.8     -> 1.9
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/04/11	riel@duckman.distro.conectiva	1.457
# 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)
# --------------------------------------------
#
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	Thu Apr 11 21:23:50 2002
+++ b/include/linux/mmzone.h	Thu Apr 11 21:23:50 2002
@@ -157,6 +157,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:23:50 2002
+++ b/mm/bootmem.c	Thu Apr 11 21:23:50 2002
@@ -338,12 +338,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:23:50 2002
+++ b/mm/page_alloc.c	Thu Apr 11 21:23:50 2002
@@ -482,14 +482,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;
 }

@@ -501,7 +497,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;
@@ -512,9 +508,7 @@
 			if (size > high)
 				sum += size - high;
 		}
-
-		pgdat = pgdat->node_next;
-	} while (pgdat);
+	}

 	return sum;
 }
@@ -522,13 +516,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:23:50 2002
+++ b/mm/vmscan.c	Thu Apr 11 21:23:50 2002
@@ -655,10 +655,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);
 }

@@ -681,12 +679,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;
 }


^ permalink raw reply	[flat|nested] 27+ messages in thread
* [PATCH] for_each_zone / for_each_pgdat
@ 2002-04-11 18:23 Rik van Riel
  2002-04-11 18:54 ` Rik van Riel
  2002-04-12  0:07 ` Rik van Riel
  0 siblings, 2 replies; 27+ messages in thread
From: Rik van Riel @ 2002-04-11 18:23 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: linux-kernel

replace slightly obscure while loops with for_each_zone and
for_each_pgdat macros  (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   -> 1.389
#	include/linux/mmzone.h	1.7     -> 1.8
#	     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)
# --------------------------------------------
#
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	Thu Apr 11 15:22:01 2002
+++ b/include/linux/mmzone.h	Thu Apr 11 15:22:01 2002
@@ -158,6 +158,59 @@

 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;
+
+	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;
+
+	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 15:22:02 2002
+++ b/mm/bootmem.c	Thu Apr 11 15:22:02 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 15:22:01 2002
+++ b/mm/page_alloc.c	Thu Apr 11 15:22:01 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 15:22:01 2002
+++ b/mm/vmscan.c	Thu Apr 11 15:22:02 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;
 }


^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2002-04-18 10:03 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-04-15 15:49 [PATCH] for_each_zone / for_each_pgdat Rik van Riel
2002-04-15 20:49 ` Linus Torvalds
2002-04-15 20:58   ` Rik van Riel
2002-04-15 21:08     ` Linus Torvalds
2002-04-15 21:17       ` Linus Torvalds
2002-04-15 23:20         ` William Lee Irwin III
2002-04-16  0:44           ` Andrea Arcangeli
2002-04-16  1:30             ` Mike Fedyk
2002-04-16  4:27               ` Rik van Riel
2002-04-16 13:36                 ` Andrea Arcangeli
2002-04-16 13:44               ` Andrea Arcangeli
2002-04-16 16:39                 ` Mike Fedyk
2002-04-16 14:00               ` Bill Davidsen
2002-04-16 18:19                 ` Mike Fedyk
2002-04-16  4:22             ` Marcelo Tosatti
2002-04-16 14:50         ` Oliver Xymoron
2002-04-16 14:56           ` Rik van Riel
2002-04-16 15:26             ` Oliver Xymoron
2002-04-16 15:46             ` J.A. Magallon
2002-04-15 21:18       ` Christoph Hellwig
2002-04-15 21:47       ` Rik van Riel
2002-04-15 22:19     ` Martin J. Bligh
  -- strict thread matches above, loose matches on Subject: below --
2002-04-12  0:25 Rik van Riel
2002-04-18  9:41 ` Pavel Machek
2002-04-11 18:23 Rik van Riel
2002-04-11 18:54 ` Rik van Riel
2002-04-12  0:07 ` Rik van Riel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox