Index: configure.in
===================================================================
RCS file: /cvs/gnome/glib/configure.in,v
retrieving revision 1.437
diff -u -p -r1.437 configure.in
--- configure.in	24 Feb 2005 04:24:16 -0000	1.437
+++ configure.in	6 Mar 2005 15:44:38 -0000
@@ -813,6 +813,15 @@ AC_CHECK_FUNCS(lstat strerror strsignal 
 AC_FUNC_VSNPRINTF_C99
 AC_FUNC_PRINTF_UNIX98
 
+AC_ARG_ENABLE(memalign,
+	      [AC_HELP_STRING([--enable-memalign],
+	                      [use posix_memalign() to speed up memchunks, if available [default=yes]])],
+              enable_memalign="$enableval",
+	      enable_memalign="yes")
+if test "x$enable_memalign" = "xyes" ; then
+  AC_CHECK_FUNCS(posix_memalign)
+fi
+
 #
 # Check whether to use an included printf
 #
Index: glib/gmem.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gmem.c,v
retrieving revision 1.45
diff -u -p -r1.45 gmem.c
--- glib/gmem.c	4 Oct 2004 20:19:30 -0000	1.45
+++ glib/gmem.c	6 Mar 2005 15:44:39 -0000
@@ -30,6 +30,7 @@
 
 #include "config.h"
 
+#define _GNU_SOURCE
 #include <stdlib.h>
 #include <string.h>
 #include <signal.h>
@@ -624,23 +625,30 @@ struct _GMemChunk
   gint num_marked_areas;     /* the number of areas marked for deletion */
   guint atom_size;           /* the size of an atom */
   gulong area_size;          /* the size of a memory area */
+  guint area_shift;          /* 2^area_shift == area_size */
   GMemArea *mem_area;        /* the current memory area */
   GMemArea *mem_areas;       /* a list of all the mem areas owned by this chunk */
   GMemArea *free_mem_area;   /* the free area...which is about to be destroyed */
   GFreeAtom *free_atoms;     /* the free atoms list */
+#ifndef HAVE_POSIX_MEMALIGN
   GTree *mem_tree;           /* tree of mem areas sorted by memory address */
+#endif
   GMemChunk *next;           /* pointer to the next chunk */
   GMemChunk *prev;           /* pointer to the previous chunk */
 };
 
 
 #ifndef DISABLE_MEM_POOLS
-static gulong g_mem_chunk_compute_size (gulong    size,
-					gulong    min_size) G_GNUC_CONST;
+static void   g_mem_chunk_compute_size (GMemChunk *chunk,
+                                        gulong     size,
+					gulong     min_size);
+static GMemArea *g_mem_chunk_area_find (GMemChunk *mem_chunk,
+                                        gpointer mem) G_GNUC_CONST;
+
+#ifndef HAVE_POSIX_MEMALIGN
 static gint   g_mem_chunk_area_compare (GMemArea *a,
 					GMemArea *b);
-static gint   g_mem_chunk_area_search  (GMemArea *a,
-					gchar    *addr);
+#endif
 
 /* here we can't use StaticMutexes, as they depend upon a working
  * g_malloc, the same holds true for StaticPrivate
@@ -673,19 +681,21 @@ g_mem_chunk_new (const gchar  *name,
   mem_chunk->mem_area = NULL;
   mem_chunk->free_mem_area = NULL;
   mem_chunk->free_atoms = NULL;
-  mem_chunk->mem_tree = NULL;
   mem_chunk->mem_areas = NULL;
   mem_chunk->atom_size = atom_size;
-  
+
+#ifndef HAVE_POSIX_MEMALIGN
   if (mem_chunk->type == G_ALLOC_AND_FREE)
     mem_chunk->mem_tree = g_tree_new ((GCompareFunc) g_mem_chunk_area_compare);
+  else
+      mem_chunk->mem_tree = NULL;
+#endif
   
   if (mem_chunk->atom_size % G_MEM_ALIGN)
     mem_chunk->atom_size += G_MEM_ALIGN - (mem_chunk->atom_size % G_MEM_ALIGN);
 
   rarea_size = area_size + sizeof (GMemArea) - MEM_AREA_SIZE;
-  rarea_size = g_mem_chunk_compute_size (rarea_size, atom_size + sizeof (GMemArea) - MEM_AREA_SIZE);
-  mem_chunk->area_size = rarea_size - (sizeof (GMemArea) - MEM_AREA_SIZE);
+  g_mem_chunk_compute_size (mem_chunk, rarea_size, atom_size + sizeof (GMemArea) - MEM_AREA_SIZE);
 
   g_mutex_lock (mem_chunks_lock);
   mem_chunk->next = mem_chunks;
@@ -727,10 +737,12 @@ g_mem_chunk_destroy (GMemChunk *mem_chun
   if (mem_chunk == mem_chunks)
     mem_chunks = mem_chunks->next;
   g_mutex_unlock (mem_chunks_lock);
-  
+
+#ifndef HAVE_POSIX_MEMALIGN
   if (mem_chunk->type == G_ALLOC_AND_FREE)
     g_tree_destroy (mem_chunk->mem_tree);  
-
+#endif
+  
   g_free (mem_chunk);
 
   LEAVE_MEM_CHUNK_ROUTINE ();
@@ -757,9 +769,7 @@ g_mem_chunk_alloc (GMemChunk *mem_chunk)
       mem_chunk->free_atoms = mem_chunk->free_atoms->next;
       
       /* Determine which area this piece of memory is allocated from */
-      temp_area = g_tree_search (mem_chunk->mem_tree,
-				 (GCompareFunc) g_mem_chunk_area_search,
-				 mem);
+      temp_area = g_mem_chunk_area_find (mem_chunk, mem);
       
       /* If the area has been marked, then it is being destroyed.
        *  (ie marked to be destroyed).
@@ -793,9 +803,11 @@ g_mem_chunk_alloc (GMemChunk *mem_chunk)
                     temp_area->prev->next = temp_area->next;
                   if (temp_area == mem_chunk->mem_areas)
                     mem_chunk->mem_areas = mem_chunk->mem_areas->next;
-		  
+
+#ifndef HAVE_POSIX_MEMALIGN
 		  if (mem_chunk->type == G_ALLOC_AND_FREE)
 		    g_tree_remove (mem_chunk->mem_tree, temp_area);
+#endif
                   g_free (temp_area);
                 }
               else
@@ -830,15 +842,22 @@ g_mem_chunk_alloc (GMemChunk *mem_chunk)
         }
       else
         {
-#ifdef ENABLE_GC_FRIENDLY
+#ifdef HAVE_POSIX_MEMALIGN
+          g_assert (0 == posix_memalign (&mem_chunk->mem_area,
+                                         1 << mem_chunk->area_shift,
+                                         sizeof (GMemArea) - MEM_AREA_SIZE +
+                                         mem_chunk->area_size));
+#else
+#  ifdef ENABLE_GC_FRIENDLY
 	  mem_chunk->mem_area = (GMemArea*) g_malloc0 (sizeof (GMemArea) -
 						       MEM_AREA_SIZE +
 						       mem_chunk->area_size); 
-#else /* !ENABLE_GC_FRIENDLY */
+#  else /* !ENABLE_GC_FRIENDLY */
 	  mem_chunk->mem_area = (GMemArea*) g_malloc (sizeof (GMemArea) -
 						      MEM_AREA_SIZE +
 						      mem_chunk->area_size);
-#endif /* ENABLE_GC_FRIENDLY */
+#  endif /* ENABLE_GC_FRIENDLY */
+#endif
 	  
 	  mem_chunk->num_mem_areas += 1;
 	  mem_chunk->mem_area->next = mem_chunk->mem_areas;
@@ -848,8 +867,10 @@ g_mem_chunk_alloc (GMemChunk *mem_chunk)
 	    mem_chunk->mem_areas->prev = mem_chunk->mem_area;
 	  mem_chunk->mem_areas = mem_chunk->mem_area;
 	  
+#ifndef HAVE_POSIX_MEMALIGN
 	  if (mem_chunk->type == G_ALLOC_AND_FREE)
 	    g_tree_insert (mem_chunk->mem_tree, mem_chunk->mem_area, mem_chunk->mem_area);
+#endif
         }
       
       mem_chunk->mem_area->index = 0;
@@ -911,11 +932,8 @@ g_mem_chunk_free (GMemChunk *mem_chunk,
       free_atom = (GFreeAtom*) mem;
       free_atom->next = mem_chunk->free_atoms;
       mem_chunk->free_atoms = free_atom;
-      
-      temp_area = g_tree_search (mem_chunk->mem_tree,
-				 (GCompareFunc) g_mem_chunk_area_search,
-				 mem);
-      
+      temp_area = g_mem_chunk_area_find (mem_chunk, mem);
+
       temp_area->allocated -= 1;
       
       if (temp_area->allocated == 0)
@@ -950,9 +968,7 @@ g_mem_chunk_clean (GMemChunk *mem_chunk)
 	{
 	  mem = (gpointer) temp_free_atom;
 	  
-	  mem_area = g_tree_search (mem_chunk->mem_tree,
-				    (GCompareFunc) g_mem_chunk_area_search,
-				    mem);
+	  mem_area = g_mem_chunk_area_find (mem_chunk, mem);
 	  
           /* If this mem area is marked for destruction then delete the
 	   *  area and list node and decrement the free mem.
@@ -979,9 +995,11 @@ g_mem_chunk_clean (GMemChunk *mem_chunk)
 		    mem_chunk->mem_areas = mem_chunk->mem_areas->next;
 		  if (mem_area == mem_chunk->mem_area)
 		    mem_chunk->mem_area = NULL;
-		  
+
+#ifndef HAVE_POSIX_MEMALIGN
 		  if (mem_chunk->type == G_ALLOC_AND_FREE)
 		    g_tree_remove (mem_chunk->mem_tree, mem_area);
+#endif
 		  g_free (mem_area);
 		}
 	    }
@@ -1018,12 +1036,14 @@ g_mem_chunk_reset (GMemChunk *mem_chunk)
     }
   
   mem_chunk->free_atoms = NULL;
-  
+
+#ifndef HAVE_POSIX_MEMALIGN
   if (mem_chunk->mem_tree)
     {
       g_tree_destroy (mem_chunk->mem_tree);
       mem_chunk->mem_tree = g_tree_new ((GCompareFunc) g_mem_chunk_area_compare);
     }
+#endif
 
   LEAVE_MEM_CHUNK_ROUTINE ();
 }
@@ -1094,26 +1114,42 @@ g_blow_chunks (void)
     }
 }
 
-static gulong
-g_mem_chunk_compute_size (gulong size,
+static void
+g_mem_chunk_compute_size (GMemChunk *mem_chunk,
+                          gulong size,
 			  gulong min_size)
 {
   gulong power_of_2;
   gulong lower, upper;
+  guint shift;
   
   power_of_2 = 16;
-  while (power_of_2 < size)
+  for (shift = 4; power_of_2 < size; shift++)
     power_of_2 <<= 1;
   
   lower = power_of_2 >> 1;
   upper = power_of_2;
   
   if (size - lower < upper - size && lower >= min_size)
-    return lower;
+    mem_chunk->area_size = lower;
   else
-    return upper;
+    mem_chunk->area_size = upper;
+  mem_chunk->area_shift = shift;
+  
+  mem_chunk->area_size -= (sizeof (GMemArea) - MEM_AREA_SIZE);
 }
 
+#ifdef HAVE_POSIX_MEMALIGN
+
+static GMemArea *
+g_mem_chunk_area_find (GMemChunk *mem_chunk,
+                       gpointer mem)
+{
+  return (GMemArea *)(((gulong)mem & (~0UL << mem_chunk->area_shift)));
+}
+
+#else /* no posix_memalign() */
+
 static gint
 g_mem_chunk_area_compare (GMemArea *a,
 			  GMemArea *b)
@@ -1137,6 +1173,16 @@ g_mem_chunk_area_search (GMemArea *a,
     }
   return -1;
 }
+
+static GMemArea *
+g_mem_chunk_area_find (GMemChunk *mem_chunk,
+                       gpointer mem)
+{
+  return g_tree_search (mem_chunk->mem_tree,
+                        (GCompareFunc) g_mem_chunk_area_search,
+                        mem);
+}
+#endif      
 
 #else /* DISABLE_MEM_POOLS */
 
Index: tests/Makefile.am
===================================================================
RCS file: /cvs/gnome/glib/tests/Makefile.am,v
retrieving revision 1.68
diff -u -p -r1.68 Makefile.am
--- tests/Makefile.am	8 Feb 2005 15:14:31 -0000	1.68
+++ tests/Makefile.am	6 Mar 2005 15:44:39 -0000
@@ -49,7 +49,7 @@ endif
 if ENABLE_TIMELOOP
 timeloop = timeloop timeloop-closure
 endif
-noinst_PROGRAMS = testglib testgdate testgdateparser unicode-normalize unicode-collate $(timeloop)
+noinst_PROGRAMS = testglib testgdate testgdateparser unicode-normalize unicode-collate $(timeloop) memchunk-speed
 testglib_LDADD = $(libglib)
 patterntest_LDADD = $(libglib)
 testgdate_LDADD = $(libglib)
@@ -157,6 +157,7 @@ unicode_encoding_LDADD = $(progs_ldadd)
 unicode_caseconv_LDADD = $(progs_ldadd)
 utf8_validate_LDADD = $(progs_ldadd)
 uri_test_LDADD = $(progs_ldadd)
+memchunk_speed_LDADD = $(progs_ldadd)
 
 lib_LTLIBRARIES = libmoduletestplugin_a.la libmoduletestplugin_b.la
 
