? glib/gfreelist.h
Index: glib/ghash.c
===================================================================
RCS file: /cvs/gnome/glib/glib/ghash.c,v
retrieving revision 1.40
diff -u -r1.40 ghash.c
--- glib/ghash.c	26 Jul 2005 15:49:15 -0000	1.40
+++ glib/ghash.c	13 Sep 2005 04:35:56 -0000
@@ -43,8 +43,8 @@
 struct _GHashNode
 {
   gpointer   key;
-  gpointer   value;
   GHashNode *next;
+  gpointer   value;
 };
 
 struct _GHashTable
@@ -84,12 +84,7 @@
                                                    gboolean        notify);
 
 
-#ifndef DISABLE_MEM_POOLS
-G_LOCK_DEFINE_STATIC (g_hash_global);
-
-static GMemChunk *node_mem_chunk = NULL;
-static GHashNode *node_free_list = NULL;
-#endif
+static GMemChunk *g_hash_node_mem_chunk = NULL;
 
 /**
  * g_hash_table_new:
@@ -645,32 +640,25 @@
   hash_table->size = new_size;
 }
 
+static inline void 
+g_hash_node_mem_chunk_init (void)
+{
+  if (!g_hash_node_mem_chunk)
+    g_hash_node_mem_chunk = g_mem_chunk_new_list ("hash node mem chunk",
+						  sizeof (GHashNode),
+						  sizeof (GHashNode) * 128, 
+						  G_ALLOC_ONLY);
+}
+
 static GHashNode*
 g_hash_node_new (gpointer key,
 		 gpointer value)
 {
   GHashNode *hash_node;
-  
-#ifdef DISABLE_MEM_POOLS
-  hash_node = g_new (GHashNode, 1);
-#else
-  G_LOCK (g_hash_global);
-  if (node_free_list)
-    {
-      hash_node = node_free_list;
-      node_free_list = node_free_list->next;
-    }
-  else
-    {
-      if (!node_mem_chunk)
-	node_mem_chunk = g_mem_chunk_new ("hash node mem chunk",
-					  sizeof (GHashNode),
-					  1024, G_ALLOC_ONLY);
-      
-      hash_node = g_chunk_new (GHashNode, node_mem_chunk);
-    }
-  G_UNLOCK (g_hash_global);
-#endif
+
+  g_hash_node_mem_chunk_init ();
+
+  hash_node = g_chunk_new (GHashNode, g_hash_node_mem_chunk);
   
   hash_node->key = key;
   hash_node->value = value;
@@ -689,19 +677,8 @@
   if (value_destroy_func)
     value_destroy_func (hash_node->value);
   
-#ifdef ENABLE_GC_FRIENDLY
-  hash_node->key = NULL;
-  hash_node->value = NULL;
-#endif /* ENABLE_GC_FRIENDLY */
-
-#ifdef DISABLE_MEM_POOLS
-  g_free (hash_node);
-#else
-  G_LOCK (g_hash_global);
-  hash_node->next = node_free_list;
-  node_free_list = hash_node;
-  G_UNLOCK (g_hash_global);
-#endif
+  hash_node->next = NULL;
+  g_mem_chunk_free (g_hash_node_mem_chunk, hash_node);
 }
 
 static void
@@ -709,55 +686,29 @@
 		      GFreeFunc  key_destroy_func,
 		      GFreeFunc  value_destroy_func)
 {
-#ifdef DISABLE_MEM_POOLS
-  while (hash_node)
-    {
-      GHashNode *next = hash_node->next;
-
-      if (key_destroy_func)
-	key_destroy_func (hash_node->key);
-      if (value_destroy_func)
-	value_destroy_func (hash_node->value);
-
-      g_free (hash_node);
-      hash_node = next;
-    }  
-#else
   if (hash_node)
     {
-      GHashNode *node = hash_node;
-  
-      while (node->next)
-	{
-	  if (key_destroy_func)
-	    key_destroy_func (node->key);
-	  if (value_destroy_func)
-	    value_destroy_func (node->value);
-
-#ifdef ENABLE_GC_FRIENDLY
-	  node->key = NULL;
-	  node->value = NULL;
-#endif /* ENABLE_GC_FRIENDLY */
+      GHashNode *node;
 
-	  node = node->next;
+      if (key_destroy_func || value_destroy_func)
+	{
+	  for (node = hash_node; node; node = node->next)
+	    {
+	      if (key_destroy_func)
+		key_destroy_func (node->key);
+	      if (value_destroy_func)
+		value_destroy_func (node->value);
+	    }
 	}
 
-      if (key_destroy_func)
-	key_destroy_func (node->key);
-      if (value_destroy_func)
-	value_destroy_func (node->value);
-
-#ifdef ENABLE_GC_FRIENDLY
-      node->key = NULL;
-      node->value = NULL;
-#endif /* ENABLE_GC_FRIENDLY */
- 
-      G_LOCK (g_hash_global);
-      node->next = node_free_list;
-      node_free_list = hash_node;
-      G_UNLOCK (g_hash_global);
+      g_mem_chunk_free (g_hash_node_mem_chunk, hash_node);
     }
-#endif
+}
+
+void
+_g_hash_thread_init (void)
+{
+  g_hash_node_mem_chunk_init ();
 }
 
 #define __G_HASH_C__
Index: glib/glib.symbols
===================================================================
RCS file: /cvs/gnome/glib/glib/glib.symbols,v
retrieving revision 1.38
diff -u -r1.38 glib.symbols
--- glib/glib.symbols	31 Aug 2005 14:25:43 -0000	1.38
+++ glib/glib.symbols	13 Sep 2005 04:35:56 -0000
@@ -461,10 +461,6 @@
 g_list_nth
 g_list_nth_data
 g_list_nth_prev
-#ifndef DISABLE_MEM_POOLS
-g_list_pop_allocator
-g_list_push_allocator
-#endif
 g_list_position
 g_list_prepend
 g_list_remove
@@ -574,6 +570,7 @@
 g_mem_chunk_free
 g_mem_chunk_info
 g_mem_chunk_new
+g_mem_chunk_new_list
 g_mem_chunk_print
 g_mem_chunk_reset
 g_malloc G_GNUC_MALLOC
@@ -635,10 +632,6 @@
 g_node_new
 g_node_n_nodes
 g_node_nth_child
-#ifndef DISABLE_MEM_POOLS
-g_node_pop_allocator
-g_node_push_allocator
-#endif
 g_node_prepend
 g_node_reverse_children
 g_node_traverse
@@ -841,10 +834,6 @@
 g_slist_length
 g_slist_nth
 g_slist_nth_data
-#ifndef DISABLE_MEM_POOLS
-g_slist_pop_allocator
-g_slist_push_allocator
-#endif
 g_slist_position
 g_slist_prepend
 g_slist_remove
Index: glib/glist.c
===================================================================
RCS file: /cvs/gnome/glib/glib/glist.c,v
retrieving revision 1.30
diff -u -r1.30 glist.c
--- glib/glist.c	14 Mar 2005 04:26:57 -0000	1.30
+++ glib/glist.c	13 Sep 2005 04:35:56 -0000
@@ -34,74 +34,16 @@
 #include "galias.h"
 
 
-#ifndef DISABLE_MEM_POOLS
-struct _GAllocator /* from gmem.c */
-{
-  gchar         *name;
-  guint16        n_preallocs;
-  guint          is_unused : 1;
-  guint          type : 4;
-  GAllocator    *last;
-  GMemChunk     *mem_chunk;
-  GList		*free_lists; /* implementation specific */
-};
-
-static GAllocator	*current_allocator = NULL;
-G_LOCK_DEFINE_STATIC (current_allocator);
-
-/* HOLDS: current_allocator_lock */
-static void
-g_list_validate_allocator (GAllocator *allocator)
-{
-  g_return_if_fail (allocator != NULL);
-  g_return_if_fail (allocator->is_unused == TRUE);
-
-  if (allocator->type != G_ALLOCATOR_LIST)
-    {
-      allocator->type = G_ALLOCATOR_LIST;
-      if (allocator->mem_chunk)
-	{
-	  g_mem_chunk_destroy (allocator->mem_chunk);
-	  allocator->mem_chunk = NULL;
-	}
-    }
-
-  if (!allocator->mem_chunk)
-    {
-      allocator->mem_chunk = g_mem_chunk_new (allocator->name,
-					      sizeof (GList),
-					      sizeof (GList) * allocator->n_preallocs,
-					      G_ALLOC_ONLY);
-      allocator->free_lists = NULL;
-    }
-
-  allocator->is_unused = FALSE;
-}
+static GMemChunk *g_list_mem_chunk = NULL;
 
-void
-g_list_push_allocator(GAllocator *allocator)
-{
-  G_LOCK (current_allocator);
-  g_list_validate_allocator (allocator);
-  allocator->last = current_allocator;
-  current_allocator = allocator;
-  G_UNLOCK (current_allocator);
-}
-
-void
-g_list_pop_allocator (void)
+static inline void
+g_list_mem_chunk_init (void)
 {
-  G_LOCK (current_allocator);
-  if (current_allocator)
-    {
-      GAllocator *allocator;
-
-      allocator = current_allocator;
-      current_allocator = allocator->last;
-      allocator->last = NULL;
-      allocator->is_unused = TRUE;
-    }
-  G_UNLOCK (current_allocator);
+  if (!g_list_mem_chunk)
+    g_list_mem_chunk = g_mem_chunk_new_list ("GList mem chunk",
+					     sizeof (GList),
+					     sizeof (GList) * 128,
+					     G_ALLOC_ONLY);
 }
 
 static inline GList*
@@ -109,35 +51,10 @@
 {
   GList *list;
 
-  G_LOCK (current_allocator);
-  if (!current_allocator)
-    {
-      GAllocator *allocator = g_allocator_new ("GLib default GList allocator",
-					       128);
-      g_list_validate_allocator (allocator);
-      allocator->last = NULL;
-      current_allocator = allocator;
-    }
-  if (!current_allocator->free_lists)
-    {
-      list = g_chunk_new (GList, current_allocator->mem_chunk);
-      list->data = NULL;
-    }
-  else
-    {
-      if (current_allocator->free_lists->data)
-	{
-	  list = current_allocator->free_lists->data;
-	  current_allocator->free_lists->data = list->next;
-	  list->data = NULL;
-	}
-      else
-	{
-	  list = current_allocator->free_lists;
-	  current_allocator->free_lists = list->next;
-	}
-    }
-  G_UNLOCK (current_allocator);
+  g_list_mem_chunk_init ();
+  
+  list = g_chunk_new (GList, g_list_mem_chunk);
+  list->data = NULL;
   list->next = NULL;
   list->prev = NULL;
   
@@ -154,27 +71,7 @@
 g_list_free (GList *list)
 {
   if (list)
-    {
-      GList *last_node = list;
-
-#ifdef ENABLE_GC_FRIENDLY
-      while (last_node->next)
-        {
-          last_node->data = NULL;
-          last_node->prev = NULL;
-          last_node = last_node->next;
-        }
-      last_node->data = NULL;
-      last_node->prev = NULL;
-#else /* !ENABLE_GC_FRIENDLY */
-      list->data = list->next;  
-#endif /* ENABLE_GC_FRIENDLY */
-
-      G_LOCK (current_allocator);
-      last_node->next = current_allocator->free_lists;
-      current_allocator->free_lists = list;
-      G_UNLOCK (current_allocator);
-    }
+    g_mem_chunk_free (g_list_mem_chunk, list);
 }
 
 static inline void
@@ -182,16 +79,8 @@
 {
   if (list)
     {
-      list->data = NULL;  
-
-#ifdef ENABLE_GC_FRIENDLY
-      list->prev = NULL;  
-#endif /* ENABLE_GC_FRIENDLY */
-
-      G_LOCK (current_allocator);
-      list->next = current_allocator->free_lists;
-      current_allocator->free_lists = list;
-      G_UNLOCK (current_allocator);
+      list->next = NULL;
+      g_mem_chunk_free (g_list_mem_chunk, list);
     }
 }
 
@@ -201,41 +90,6 @@
   _g_list_free_1 (list);
 }
 
-#else /* DISABLE_MEM_POOLS */
-
-#define _g_list_alloc g_list_alloc
-GList*
-g_list_alloc (void)
-{
-  GList *list;
-  
-  list = g_new0 (GList, 1);
-  
-  return list;
-}
-
-void
-g_list_free (GList *list)
-{
-  GList *last;
-  
-  while (list)
-    {
-      last = list;
-      list = list->next;
-      g_free (last);
-    }
-}
-
-#define _g_list_free_1 g_list_free_1
-void
-g_list_free_1 (GList *list)
-{
-  g_free (list);
-}
-
-#endif
-
 GList*
 g_list_append (GList	*list,
 	       gpointer	 data)
@@ -249,7 +103,6 @@
   if (list)
     {
       last = g_list_last (list);
-      /* g_assert (last != NULL); */
       last->next = new_list;
       new_list->prev = last;
 
@@ -367,7 +220,8 @@
 }
 
 GList *
-g_list_concat (GList *list1, GList *list2)
+g_list_concat (GList *list1, 
+	       GList *list2)
 {
   GList *tmp_list;
   
@@ -812,6 +666,12 @@
 		       gpointer          user_data)
 {
   return g_list_sort_real (list, (GFunc) compare_func, TRUE, user_data);
+}
+
+void
+_g_list_thread_init (void)
+{
+  g_list_mem_chunk_init ();
 }
 
 #define __G_LIST_C__
Index: glib/glist.h
===================================================================
RCS file: /cvs/gnome/glib/glib/glist.h,v
retrieving revision 1.8
diff -u -r1.8 glist.h
--- glib/glist.h	8 Nov 2002 18:47:54 -0000	1.8
+++ glib/glist.h	13 Sep 2005 04:35:56 -0000
@@ -42,8 +42,6 @@
 
 /* Doubly linked lists
  */
-void     g_list_push_allocator (GAllocator       *allocator);
-void     g_list_pop_allocator  (void);
 GList*   g_list_alloc          (void);
 void     g_list_free           (GList            *list);
 void     g_list_free_1         (GList            *list);
Index: glib/gmem.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gmem.c,v
retrieving revision 1.47
diff -u -r1.47 gmem.c
--- glib/gmem.c	22 Mar 2005 04:09:16 -0000	1.47
+++ glib/gmem.c	13 Sep 2005 04:35:56 -0000
@@ -604,610 +604,362 @@
 
 
 /* --- MemChunks --- */
-typedef struct _GFreeAtom      GFreeAtom;
-typedef struct _GMemArea       GMemArea;
+/* FIXME configure */
+#define USE_FAST_FREE_LIST
 
-struct _GFreeAtom
+typedef struct _GMemArea GMemArea;
+typedef struct _GFreeList GFreeList;
+typedef struct _GFreeListElement GFreeListElement;
+
+struct _GFreeListElement 
+{
+  GFreeListElement *next;
+  gpointer *list_next;
+};
+
+struct _GFreeList 
 {
-  GFreeAtom *next;
+  volatile gpointer head;
+#if defined (USE_FAST_FREE_LIST)
+  volatile gulong   count;		/* for the ABA problem */
+#else
+  GMutex           *lock;		/* lock for C fallback */
+#endif
 };
 
 struct _GMemArea
 {
-  GMemArea *next;            /* the next mem area */
-  GMemArea *prev;            /* the previous mem area */
-  gulong index;              /* the current index into the "mem" array */
-  gulong free;               /* the number of free bytes in this mem area */
-  gulong allocated;          /* the number of atoms allocated from this area */
-  gulong mark;               /* is this mem area marked for deletion */
-  gchar mem[MEM_AREA_SIZE];  /* the mem array from which atoms get allocated
-			      * the actual size of this array is determined by
-			      *  the mem chunk "area_size". ANSI says that it
-			      *  must be declared to be the maximum size it
-			      *  can possibly be (even though the actual size
-			      *  may be less).
-			      */
+  GMemArea *next;
+  gpointer area;
 };
 
 struct _GMemChunk
 {
-  const gchar *name;         /* name of this MemChunk...used for debugging output */
-  gint type;                 /* the type of MemChunk: ALLOC_ONLY or ALLOC_AND_FREE */
-  gint num_mem_areas;        /* the number of memory areas */
-  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 */
-  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 */
-  GTree *mem_tree;           /* tree of mem areas sorted by memory address */
-  GMemChunk *next;           /* pointer to the next chunk */
-  GMemChunk *prev;           /* pointer to the previous chunk */
-};
+  GFreeList stack;
 
+  gchar *name;
+  gulong area_size;
+  gulong chunk_size;
+  GMemArea *mem_areas;
+  gboolean list;
 
-#ifndef DISABLE_MEM_POOLS
-static gulong g_mem_chunk_compute_size (gulong    size,
-					gulong    min_size) G_GNUC_CONST;
-static gint   g_mem_chunk_area_compare (GMemArea *a,
-					GMemArea *b);
-static gint   g_mem_chunk_area_search  (GMemArea *a,
-					gchar    *addr);
+  gboolean cleanup;
+};
 
-/* here we can't use StaticMutexes, as they depend upon a working
- * g_malloc, the same holds true for StaticPrivate
+/* --- atomic free list --- */
+static inline GFreeList* g_free_list_new	(void);
+static inline void	 g_free_list_init	(GFreeList *stack);
+static inline void	 g_free_list_destroy (GFreeList *stack);
+static inline void	 g_free_list_free	(GFreeList *stack); 
+
+static inline void	 g_free_list_push	(GFreeList *stack, gpointer mem);
+static inline gpointer	 g_free_list_pop	(GFreeList *stack, gboolean list);
+
+#if defined (USE_FAST_FREE_LIST)
+/*
+ * Intel ia32 optimized lockfree implementations
  */
-static GMutex        *mem_chunks_lock = NULL;
-static GMemChunk     *mem_chunks = NULL;
+#define SMP_LOCK "lock ; "
 
-GMemChunk*
-g_mem_chunk_new (const gchar  *name,
-		 gint          atom_size,
-		 gulong        area_size,
-		 gint          type)
+static inline void
+g_free_list_init (GFreeList *stack)
 {
-  GMemChunk *mem_chunk;
-  gulong rarea_size;
+  stack->head = NULL;
+  stack->count = 0;
+}
 
-  g_return_val_if_fail (atom_size > 0, NULL);
-  g_return_val_if_fail (area_size >= atom_size, NULL);
+static inline void
+g_free_list_destroy (GFreeList *stack)
+{
+}
 
-  ENTER_MEM_CHUNK_ROUTINE ();
+static inline void
+g_free_list_push (GFreeList *stack, gpointer mem)
+{
+ __asm__ __volatile__ (
+   "1:                         \n\t"
+   "  movl %2, (%1);           \n\t"	/* mem->next == stack->head */
+   SMP_LOCK "cmpxchg %1, %0;   \n\t"	/* if head unchanged, move mem into it */
+   "  jnz 1b;                  \n"	/* head changed, retry */
+     :
+     : "m" (*stack),
+       "r" (mem),
+       "a" (stack->head)
+  );
+}
 
-  area_size = (area_size + atom_size - 1) / atom_size;
-  area_size *= atom_size;
+static inline gpointer
+g_free_list_pop (GFreeList *stack, gboolean list)
+{
+  GFreeListElement *head;
 
-  mem_chunk = g_new (GMemChunk, 1);
-  mem_chunk->name = name;
-  mem_chunk->type = type;
-  mem_chunk->num_mem_areas = 0;
-  mem_chunk->num_marked_areas = 0;
-  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;
-  
-  if (mem_chunk->type == G_ALLOC_AND_FREE)
-    mem_chunk->mem_tree = g_tree_new ((GCompareFunc) g_mem_chunk_area_compare);
-  
-  if (mem_chunk->atom_size % G_MEM_ALIGN)
-    mem_chunk->atom_size += G_MEM_ALIGN - (mem_chunk->atom_size % G_MEM_ALIGN);
+  /* pop is a little more complicated as we need to avoid the so called ABA
+   * problem that arises when a pop and push of the same element happens
+   * right between when we read head->next and try to swing the new pointer
+   * into place. This is usually solved using a counter which makes it highly
+   * unlikely that we manage to grab the wrong head->next value.
+   */
+  __asm__ __volatile__ (
+    "  pushl %%ebx;             \n\t"
+    "  testl %%eax, %%eax;      \n\t"	/* if (head == NULL) return */
+    "  jz 20f;                  \n\t"
+    "10:                        \n\t"
+    "  movl (%%eax), %%ebx;     \n\t"	/* take value pointed to by head (head->next) */
+    "  movl %%edx, %%ecx;       \n\t"	/* take counter */
+    "  incl %%ecx;              \n\t"	/* and increment */
+    SMP_LOCK "cmpxchg8b %1;     \n\t"	/* if eax:edx == *stack, move ebx:ecx to *stack,
+					 * else *stack is moved into eax:edx again... */
+    "  jz 20f;                  \n\t"   /* success */
+    "  testl %%eax, %%eax;      \n\t"   /* if (head == NULL) return */
+    "  jnz 10b;                 \n\t"   /* else we retry */
+    "20:                        \n\t"
+    "  popl %%ebx               \n"
+      : "=a" (head)
+      :  "m" (*stack),
+         "a" (stack->head),
+         "d" (stack->count)
+      :  "ecx"
+  );
+
+  if (list && head->list_next)
+    g_free_list_push (stack, head->list_next);
 
-  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_mutex_lock (mem_chunks_lock);
-  mem_chunk->next = mem_chunks;
-  mem_chunk->prev = NULL;
-  if (mem_chunks)
-    mem_chunks->prev = mem_chunk;
-  mem_chunks = mem_chunk;
-  g_mutex_unlock (mem_chunks_lock);
+  return head;
+}
 
-  LEAVE_MEM_CHUNK_ROUTINE ();
+#else
 
-  return mem_chunk;
+/*
+ * generic implementation
+ */
+static inline void
+g_free_list_init (GFreeList *stack)
+{
+  stack->head = NULL;
+  stack->lock = g_mutex_new();
 }
 
-void
-g_mem_chunk_destroy (GMemChunk *mem_chunk)
+static inline void
+g_free_list_destroy (GFreeList *stack)
 {
-  GMemArea *mem_areas;
-  GMemArea *temp_area;
-  
-  g_return_if_fail (mem_chunk != NULL);
-
-  ENTER_MEM_CHUNK_ROUTINE ();
-
-  mem_areas = mem_chunk->mem_areas;
-  while (mem_areas)
-    {
-      temp_area = mem_areas;
-      mem_areas = mem_areas->next;
-      g_free (temp_area);
-    }
-  
-  g_mutex_lock (mem_chunks_lock);
-  if (mem_chunk->next)
-    mem_chunk->next->prev = mem_chunk->prev;
-  if (mem_chunk->prev)
-    mem_chunk->prev->next = mem_chunk->next;
-  
-  if (mem_chunk == mem_chunks)
-    mem_chunks = mem_chunks->next;
-  g_mutex_unlock (mem_chunks_lock);
-  
-  if (mem_chunk->type == G_ALLOC_AND_FREE)
-    g_tree_destroy (mem_chunk->mem_tree);  
+  g_mutex_free (stack->lock);
+}
 
-  g_free (mem_chunk);
+static inline void
+g_free_list_push (GFreeList *stack, gpointer mem)
+{
+  GFreeListElement *elem = (GFreeListElement *) mem;
 
-  LEAVE_MEM_CHUNK_ROUTINE ();
+  g_mutex_lock (stack->lock);
+  elem->next = stack->head;
+  stack->head = elem;
+  g_mutex_unlock (stack->lock);
 }
 
-gpointer
-g_mem_chunk_alloc (GMemChunk *mem_chunk)
+static inline gpointer
+g_free_list_pop (GFreeList *stack, gboolean list)
 {
-  GMemArea *temp_area;
-  gpointer mem;
+  GFreeListElement *head;
 
-  ENTER_MEM_CHUNK_ROUTINE ();
-
-  g_return_val_if_fail (mem_chunk != NULL, NULL);
+  g_mutex_lock (stack->lock);
+  head = (GFreeListElement *) stack->head;
+  if (head)
+    stack->head = head->next;
   
-  while (mem_chunk->free_atoms)
+  /* push the list tail back onto the stack */
+  if (list && head->list_next)
     {
-      /* Get the first piece of memory on the "free_atoms" list.
-       * We can go ahead and destroy the list node we used to keep
-       *  track of it with and to update the "free_atoms" list to
-       *  point to its next element.
-       */
-      mem = mem_chunk->free_atoms;
-      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);
-      
-      /* If the area has been marked, then it is being destroyed.
-       *  (ie marked to be destroyed).
-       * We check to see if all of the segments on the free list that
-       *  reference this area have been removed. This occurs when
-       *  the ammount of free memory is less than the allocatable size.
-       * If the chunk should be freed, then we place it in the "free_mem_area".
-       * This is so we make sure not to free the mem area here and then
-       *  allocate it again a few lines down.
-       * If we don't allocate a chunk a few lines down then the "free_mem_area"
-       *  will be freed.
-       * If there is already a "free_mem_area" then we'll just free this mem area.
-       */
-      if (temp_area->mark)
-        {
-          /* Update the "free" memory available in that area */
-          temp_area->free += mem_chunk->atom_size;
-	  
-          if (temp_area->free == mem_chunk->area_size)
-            {
-              if (temp_area == mem_chunk->mem_area)
-                mem_chunk->mem_area = NULL;
-	      
-              if (mem_chunk->free_mem_area)
-                {
-                  mem_chunk->num_mem_areas -= 1;
-		  
-                  if (temp_area->next)
-                    temp_area->next->prev = temp_area->prev;
-                  if (temp_area->prev)
-                    temp_area->prev->next = temp_area->next;
-                  if (temp_area == mem_chunk->mem_areas)
-                    mem_chunk->mem_areas = mem_chunk->mem_areas->next;
-		  
-		  if (mem_chunk->type == G_ALLOC_AND_FREE)
-		    g_tree_remove (mem_chunk->mem_tree, temp_area);
-                  g_free (temp_area);
-                }
-              else
-                mem_chunk->free_mem_area = temp_area;
-	      
-	      mem_chunk->num_marked_areas -= 1;
-	    }
-	}
-      else
-        {
-          /* Update the number of allocated atoms count.
-	   */
-          temp_area->allocated += 1;
-	  
-          /* The area wasn't marked...return the memory
-	   */
-	  goto outa_here;
-        }
-    }
-  
-  /* If there isn't a current mem area or the current mem area is out of space
-   *  then allocate a new mem area. We'll first check and see if we can use
-   *  the "free_mem_area". Otherwise we'll just malloc the mem area.
-   */
-  if ((!mem_chunk->mem_area) ||
-      ((mem_chunk->mem_area->index + mem_chunk->atom_size) > mem_chunk->area_size))
-    {
-      if (mem_chunk->free_mem_area)
-        {
-          mem_chunk->mem_area = mem_chunk->free_mem_area;
-	  mem_chunk->free_mem_area = NULL;
-        }
-      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 */
-	  mem_chunk->mem_area = (GMemArea*) g_malloc (sizeof (GMemArea) -
-						      MEM_AREA_SIZE +
-						      mem_chunk->area_size);
-#endif /* ENABLE_GC_FRIENDLY */
-	  
-	  mem_chunk->num_mem_areas += 1;
-	  mem_chunk->mem_area->next = mem_chunk->mem_areas;
-	  mem_chunk->mem_area->prev = NULL;
-	  
-	  if (mem_chunk->mem_areas)
-	    mem_chunk->mem_areas->prev = mem_chunk->mem_area;
-	  mem_chunk->mem_areas = mem_chunk->mem_area;
-	  
-	  if (mem_chunk->type == G_ALLOC_AND_FREE)
-	    g_tree_insert (mem_chunk->mem_tree, mem_chunk->mem_area, mem_chunk->mem_area);
-        }
-      
-      mem_chunk->mem_area->index = 0;
-      mem_chunk->mem_area->free = mem_chunk->area_size;
-      mem_chunk->mem_area->allocated = 0;
-      mem_chunk->mem_area->mark = 0;
-    }
-  
-  /* Get the memory and modify the state variables appropriately.
-   */
-  mem = (gpointer) &mem_chunk->mem_area->mem[mem_chunk->mem_area->index];
-  mem_chunk->mem_area->index += mem_chunk->atom_size;
-  mem_chunk->mem_area->free -= mem_chunk->atom_size;
-  mem_chunk->mem_area->allocated += 1;
-
-outa_here:
+      GFreeListElement *elem = (GFreeListElement *)head->list_next;
 
-  LEAVE_MEM_CHUNK_ROUTINE ();
+      elem->next = stack->head;
+      stack->head = elem;      
+    }
+  g_mutex_unlock (stack->lock);
 
-  return mem;
+  return head;
 }
 
-gpointer
-g_mem_chunk_alloc0 (GMemChunk *mem_chunk)
+#endif
+
+/*
+ * common functions
+ */
+static inline GFreeList*
+g_free_list_new (void)
 {
-  gpointer mem;
+  GFreeList *stack;
 
-  mem = g_mem_chunk_alloc (mem_chunk);
-  if (mem)
-    {
-      memset (mem, 0, mem_chunk->atom_size);
-    }
+  stack = g_new (GFreeList, 1);
+  g_free_list_init (stack);
 
-  return mem;
+  return stack;
 }
 
-void
-g_mem_chunk_free (GMemChunk *mem_chunk,
-		  gpointer   mem)
+static inline void
+g_free_list_free (GFreeList *stack)
 {
-  GMemArea *temp_area;
-  GFreeAtom *free_atom;
-  
-  g_return_if_fail (mem_chunk != NULL);
-  g_return_if_fail (mem != NULL);
+  g_free_list_destroy (stack);
+  g_free (stack);
+}
 
-  ENTER_MEM_CHUNK_ROUTINE ();
 
-#ifdef ENABLE_GC_FRIENDLY
-  memset (mem, 0, mem_chunk->atom_size);
-#endif /* ENABLE_GC_FRIENDLY */
+/* --- mem chunk implementation --- */
+#ifndef G_DISABLE_MEM_POOLS
+static gboolean
+populate (GMemChunk *mem_chunk)
+{
+  GMemArea *new_area;
+  gint i;
 
-  /* Don't do anything if this is an ALLOC_ONLY chunk
-   */
-  if (mem_chunk->type == G_ALLOC_AND_FREE)
-    {
-      /* Place the memory on the "free_atoms" list
-       */
-      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->allocated -= 1;
-      
-      if (temp_area->allocated == 0)
-	{
-	  temp_area->mark = 1;
-	  mem_chunk->num_marked_areas += 1;
-	}
-    }
+  if (mem_chunk->cleanup)
+    return FALSE;
 
-  LEAVE_MEM_CHUNK_ROUTINE ();
-}
+  new_area = g_new0 (GMemArea, 1);
+  new_area->area = g_malloc0 (mem_chunk->area_size);
+  new_area->next = mem_chunk->mem_areas;
 
-/* This doesn't free the free_area if there is one */
-void
-g_mem_chunk_clean (GMemChunk *mem_chunk)
-{
-  GMemArea *mem_area;
-  GFreeAtom *prev_free_atom;
-  GFreeAtom *temp_free_atom;
-  gpointer mem;
-  
-  g_return_if_fail (mem_chunk != NULL);
-  
-  ENTER_MEM_CHUNK_ROUTINE ();
+  mem_chunk->mem_areas = new_area;
 
-  if (mem_chunk->type == G_ALLOC_AND_FREE)
-    {
-      prev_free_atom = NULL;
-      temp_free_atom = mem_chunk->free_atoms;
-      
-      while (temp_free_atom)
-	{
-	  mem = (gpointer) temp_free_atom;
-	  
-	  mem_area = g_tree_search (mem_chunk->mem_tree,
-				    (GCompareFunc) g_mem_chunk_area_search,
-				    mem);
-	  
-          /* If this mem area is marked for destruction then delete the
-	   *  area and list node and decrement the free mem.
-           */
-	  if (mem_area->mark)
-	    {
-	      if (prev_free_atom)
-		prev_free_atom->next = temp_free_atom->next;
-	      else
-		mem_chunk->free_atoms = temp_free_atom->next;
-	      temp_free_atom = temp_free_atom->next;
-	      
-	      mem_area->free += mem_chunk->atom_size;
-	      if (mem_area->free == mem_chunk->area_size)
-		{
-		  mem_chunk->num_mem_areas -= 1;
-		  mem_chunk->num_marked_areas -= 1;
-		  
-		  if (mem_area->next)
-		    mem_area->next->prev = mem_area->prev;
-		  if (mem_area->prev)
-		    mem_area->prev->next = mem_area->next;
-		  if (mem_area == mem_chunk->mem_areas)
-		    mem_chunk->mem_areas = mem_chunk->mem_areas->next;
-		  if (mem_area == mem_chunk->mem_area)
-		    mem_chunk->mem_area = NULL;
-		  
-		  if (mem_chunk->type == G_ALLOC_AND_FREE)
-		    g_tree_remove (mem_chunk->mem_tree, mem_area);
-		  g_free (mem_area);
-		}
-	    }
-	  else
-	    {
-	      prev_free_atom = temp_free_atom;
-	      temp_free_atom = temp_free_atom->next;
-	    }
-	}
-    }
-  LEAVE_MEM_CHUNK_ROUTINE ();
+  for (i = 0; i < mem_chunk->area_size; i += mem_chunk->chunk_size)
+    g_free_list_push (&mem_chunk->stack, new_area->area + i);
+  
+  return TRUE;
 }
+#endif
 
-void
-g_mem_chunk_reset (GMemChunk *mem_chunk)
+GMemChunk *
+g_mem_chunk_new (const gchar *name, 
+		 gint         atom_size, 
+		 gulong       area_size, 
+		 gint         type)
 {
-  GMemArea *mem_areas;
-  GMemArea *temp_area;
-  
-  g_return_if_fail (mem_chunk != NULL);
-  
-  ENTER_MEM_CHUNK_ROUTINE ();
+  GMemChunk *mem_chunk;
+
+  g_return_val_if_fail (atom_size > 0, NULL);
+  g_return_val_if_fail (area_size >= atom_size, NULL);
+
+  mem_chunk = g_malloc (sizeof (GMemChunk));
 
-  mem_areas = mem_chunk->mem_areas;
-  mem_chunk->num_mem_areas = 0;
+  mem_chunk->name = g_strdup (name);
+  mem_chunk->chunk_size = atom_size;
+  mem_chunk->area_size = (area_size / atom_size) * atom_size;
   mem_chunk->mem_areas = NULL;
-  mem_chunk->mem_area = NULL;
-  
-  while (mem_areas)
-    {
-      temp_area = mem_areas;
-      mem_areas = mem_areas->next;
-      g_free (temp_area);
-    }
-  
-  mem_chunk->free_atoms = NULL;
-  
-  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);
-    }
+  mem_chunk->list = FALSE;
+  mem_chunk->cleanup = FALSE;
 
-  LEAVE_MEM_CHUNK_ROUTINE ();
-}
+  g_free_list_init (&mem_chunk->stack);
 
-void
-g_mem_chunk_print (GMemChunk *mem_chunk)
-{
-  GMemArea *mem_areas;
-  gulong mem;
-  
-  g_return_if_fail (mem_chunk != NULL);
-  
-  mem_areas = mem_chunk->mem_areas;
-  mem = 0;
-  
-  while (mem_areas)
-    {
-      mem += mem_chunk->area_size - mem_areas->free;
-      mem_areas = mem_areas->next;
-    }
+#ifndef G_DISABLE_MEM_POOLS
+  populate (mem_chunk);
+#endif
 
-  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO,
-	 "%s: %ld bytes using %d mem areas",
-	 mem_chunk->name, mem, mem_chunk->num_mem_areas);
+  return mem_chunk;
 }
 
-void
-g_mem_chunk_info (void)
+GMemChunk *
+g_mem_chunk_new_list (const gchar *name, 
+		      gint         atom_size, 
+		      gulong       area_size, 
+		      gint         type)
 {
   GMemChunk *mem_chunk;
-  gint count;
-  
-  count = 0;
-  g_mutex_lock (mem_chunks_lock);
-  mem_chunk = mem_chunks;
-  while (mem_chunk)
-    {
-      count += 1;
-      mem_chunk = mem_chunk->next;
-    }
-  g_mutex_unlock (mem_chunks_lock);
-  
-  g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "%d mem chunks", count);
-  
-  g_mutex_lock (mem_chunks_lock);
-  mem_chunk = mem_chunks;
-  g_mutex_unlock (mem_chunks_lock);
 
-  while (mem_chunk)
-    {
-      g_mem_chunk_print ((GMemChunk*) mem_chunk);
-      mem_chunk = mem_chunk->next;
-    }  
-}
+  mem_chunk = g_mem_chunk_new (name, atom_size, area_size, type);
 
-void
-g_blow_chunks (void)
-{
-  GMemChunk *mem_chunk;
-  
-  g_mutex_lock (mem_chunks_lock);
-  mem_chunk = mem_chunks;
-  g_mutex_unlock (mem_chunks_lock);
-  while (mem_chunk)
-    {
-      g_mem_chunk_clean ((GMemChunk*) mem_chunk);
-      mem_chunk = mem_chunk->next;
-    }
-}
+  mem_chunk->list = TRUE;
 
-static gulong
-g_mem_chunk_compute_size (gulong size,
-			  gulong min_size)
-{
-  gulong power_of_2;
-  gulong lower, upper;
-  
-  power_of_2 = 16;
-  while (power_of_2 < size)
-    power_of_2 <<= 1;
-  
-  lower = power_of_2 >> 1;
-  upper = power_of_2;
-  
-  if (size - lower < upper - size && lower >= min_size)
-    return lower;
-  else
-    return upper;
+  return mem_chunk;
 }
 
-static gint
-g_mem_chunk_area_compare (GMemArea *a,
-			  GMemArea *b)
+void
+g_mem_chunk_destroy (GMemChunk *mem_chunk)
 {
-  if (a->mem > b->mem)
-    return 1;
-  else if (a->mem < b->mem)
-    return -1;
-  return 0;
-}
+  GMemArea *mem_area, *next;
 
-static gint
-g_mem_chunk_area_search (GMemArea *a,
-			 gchar    *addr)
-{
-  if (a->mem <= addr)
+  mem_chunk->cleanup = TRUE;
+
+  mem_area = mem_chunk->mem_areas; 
+  while (mem_area)
     {
-      if (addr < &a->mem[a->index])
-	return 0;
-      return 1;
+      next = mem_area->next;
+
+      g_free (mem_area->area);
+      g_free (mem_area);
+
+      mem_area = next;
     }
-  return -1;
-}
 
-#else /* DISABLE_MEM_POOLS */
+  g_free_list_destroy (&mem_chunk->stack);
+
+  g_free (mem_chunk->name);
+  g_free (mem_chunk);
+}
 
-typedef struct {
-  guint alloc_size;           /* the size of an atom */
-}  GMinimalMemChunk;
+#ifndef G_DISABLE_MEM_POOLS
 
-GMemChunk*
-g_mem_chunk_new (const gchar  *name,
-		 gint          atom_size,
-		 gulong        area_size,
-		 gint          type)
+gpointer
+g_mem_chunk_alloc (GMemChunk *mem_chunk)
 {
-  GMinimalMemChunk *mem_chunk;
+  gpointer chunk;
 
-  g_return_val_if_fail (atom_size > 0, NULL);
+  g_return_val_if_fail (mem_chunk != NULL, NULL);
 
-  mem_chunk = g_new (GMinimalMemChunk, 1);
-  mem_chunk->alloc_size = atom_size;
+again:
+  chunk = g_free_list_pop (&mem_chunk->stack, mem_chunk->list);
 
-  return ((GMemChunk*) mem_chunk);
-}
+  /* chunk is empty, try to refill */
+  if (G_UNLIKELY (!chunk)) 
+    {
+      if (G_LIKELY (populate (mem_chunk))) 
+	goto again;
+      else 
+	/* this happens when we are in cleanup mode and we
+	 * allocate all remaining chunks for cleanup 
+	 */
+	return NULL;
+    }
 
-void
-g_mem_chunk_destroy (GMemChunk *mem_chunk)
-{
-  g_return_if_fail (mem_chunk != NULL);
-  
-  g_free (mem_chunk);
+  return chunk;
 }
 
+#else
+
 gpointer
 g_mem_chunk_alloc (GMemChunk *mem_chunk)
 {
-  GMinimalMemChunk *minimal = (GMinimalMemChunk *)mem_chunk;
-  
+  gpointer chunk;
+
   g_return_val_if_fail (mem_chunk != NULL, NULL);
-  
-  return g_malloc (minimal->alloc_size);
+
+  chunk = g_free_list_pop (&mem_chunk->stack, mem_chunk->list);
+
+  if (G_UNLIKELY (!chunk)) 
+    chunk = g_malloc (mem_chunk->chunk_size);
+
+  return chunk;
 }
 
+#endif
+
 gpointer
 g_mem_chunk_alloc0 (GMemChunk *mem_chunk)
 {
-  GMinimalMemChunk *minimal = (GMinimalMemChunk *)mem_chunk;
-  
-  g_return_val_if_fail (mem_chunk != NULL, NULL);
-  
-  return g_malloc0 (minimal->alloc_size);
+  gpointer mem = g_mem_chunk_alloc (mem_chunk);
+
+  if (G_LIKELY (mem))
+    memset (mem, 0, mem_chunk->chunk_size);
+
+  return mem;
 }
 
 void
-g_mem_chunk_free (GMemChunk *mem_chunk,
+g_mem_chunk_free (GMemChunk *mem_chunk, 
 		  gpointer   mem)
 {
   g_return_if_fail (mem_chunk != NULL);
+  g_return_if_fail (mem != NULL);
   
-  g_free (mem);
+  g_free_list_push (&mem_chunk->stack, mem);
 }
 
 void	g_mem_chunk_clean	(GMemChunk *mem_chunk)	{}
@@ -1216,8 +968,6 @@
 void	g_mem_chunk_info	(void)			{}
 void	g_blow_chunks		(void)			{}
 
-#endif /* DISABLE_MEM_POOLS */
-
 
 /* generic allocators
  */
@@ -1265,12 +1015,11 @@
   g_free (allocator);
 }
 
+extern GMemChunk *_list_mem_chunk;
+
 void
 _g_mem_thread_init (void)
 {
-#ifndef DISABLE_MEM_POOLS
-  mem_chunks_lock = g_mutex_new ();
-#endif
 #ifndef G_DISABLE_CHECKS
   g_profile_mutex = g_mutex_new ();
 #endif
Index: glib/gmem.h
===================================================================
RCS file: /cvs/gnome/glib/glib/gmem.h,v
retrieving revision 1.12
diff -u -r1.12 gmem.h
--- glib/gmem.h	22 Mar 2005 04:09:16 -0000	1.12
+++ glib/gmem.h	13 Sep 2005 04:35:56 -0000
@@ -144,6 +144,10 @@
 				gint         atom_size,
 				gulong       area_size,
 				gint         type);
+GMemChunk* g_mem_chunk_new_list (const gchar *name,
+				 gint         atom_size,
+				 gulong       area_size,
+				 gint         type);
 void       g_mem_chunk_destroy (GMemChunk   *mem_chunk);
 gpointer   g_mem_chunk_alloc   (GMemChunk   *mem_chunk);
 gpointer   g_mem_chunk_alloc0  (GMemChunk   *mem_chunk);
Index: glib/gnode.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gnode.c,v
retrieving revision 1.21
diff -u -r1.21 gnode.c
--- glib/gnode.c	14 Mar 2005 04:26:57 -0000	1.21
+++ glib/gnode.c	13 Sep 2005 04:35:56 -0000
@@ -36,103 +36,26 @@
 #include "glib.h"
 #include "galias.h"
 
-#ifndef DISABLE_MEM_POOLS
-/* node allocation
- */
-struct _GAllocator /* from gmem.c */
-{
-  gchar         *name;
-  guint16        n_preallocs;
-  guint          is_unused : 1;
-  guint          type : 4;
-  GAllocator    *last;
-  GMemChunk     *mem_chunk;
-  GNode         *free_nodes; /* implementation specific */
-};
-
-G_LOCK_DEFINE_STATIC (current_allocator);
-static GAllocator *current_allocator = NULL;
-
-/* HOLDS: current_allocator_lock */
-static void
-g_node_validate_allocator (GAllocator *allocator)
-{
-  g_return_if_fail (allocator != NULL);
-  g_return_if_fail (allocator->is_unused == TRUE);
-
-  if (allocator->type != G_ALLOCATOR_NODE)
-    {
-      allocator->type = G_ALLOCATOR_NODE;
-      if (allocator->mem_chunk)
-	{
-	  g_mem_chunk_destroy (allocator->mem_chunk);
-	  allocator->mem_chunk = NULL;
-	}
-    }
-
-  if (!allocator->mem_chunk)
-    {
-      allocator->mem_chunk = g_mem_chunk_new (allocator->name,
-					      sizeof (GNode),
-					      sizeof (GNode) * allocator->n_preallocs,
-					      G_ALLOC_ONLY);
-      allocator->free_nodes = NULL;
-    }
+static GMemChunk *g_node_mem_chunk = NULL;
 
-  allocator->is_unused = FALSE;
-}
-
-void
-g_node_push_allocator (GAllocator *allocator)
-{
-  G_LOCK (current_allocator);
-  g_node_validate_allocator (allocator);
-  allocator->last = current_allocator;
-  current_allocator = allocator;
-  G_UNLOCK (current_allocator);
-}
-
-void
-g_node_pop_allocator (void)
+static inline void
+g_node_mem_chunk_init (void)
 {
-  G_LOCK (current_allocator);
-  if (current_allocator)
-    {
-      GAllocator *allocator;
-
-      allocator = current_allocator;
-      current_allocator = allocator->last;
-      allocator->last = NULL;
-      allocator->is_unused = TRUE;
-    }
-  G_UNLOCK (current_allocator);
+  if (!g_node_mem_chunk)
+    g_node_mem_chunk = g_mem_chunk_new_list ("GNode mem chunk",
+					     sizeof (GNode),
+					     sizeof (GNode) * 128,
+					     G_ALLOC_ONLY);
 }
 
-
 /* --- functions --- */
 GNode*
 g_node_new (gpointer data)
 {
   GNode *node;
 
-  G_LOCK (current_allocator);
-  if (!current_allocator)
-    {
-       GAllocator *allocator = g_allocator_new ("GLib default GNode allocator",
-						128);
-       g_node_validate_allocator (allocator);
-       allocator->last = NULL;
-       current_allocator = allocator;
-    }
-  if (!current_allocator->free_nodes)
-    node = g_chunk_new (GNode, current_allocator->mem_chunk);
-  else
-    {
-      node = current_allocator->free_nodes;
-      current_allocator->free_nodes = node->next;
-    }
-  G_UNLOCK (current_allocator);
-  
+  g_node_mem_chunk_init ();
+
   node->data = data;
   node->next = NULL;
   node->prev = NULL;
@@ -153,54 +76,15 @@
       if (parent->children)
 	g_nodes_free (parent->children);
 
-#ifdef ENABLE_GC_FRIENDLY
-      parent->data = NULL;
-      parent->prev = NULL;
-      parent->parent = NULL;
-      parent->children = NULL;
-#endif /* ENABLE_GC_FRIENDLY */
-
       if (parent->next)
 	parent = parent->next;
       else
 	break;
     }
-  
-  G_LOCK (current_allocator);
-  parent->next = current_allocator->free_nodes;
-  current_allocator->free_nodes = node;
-  G_UNLOCK (current_allocator);
-}
-#else /* DISABLE_MEM_POOLS */
 
-GNode*
-g_node_new (gpointer data)
-{
-  GNode *node;
-
-  node = g_new0 (GNode, 1);
-  
-  node->data = data;
-  
-  return node;
+  g_mem_chunk_free (g_node_mem_chunk, node);
 }
 
-static void
-g_nodes_free (GNode *root)
-{
-  GNode *node, *next;
-  
-  node = root;
-  while (node != NULL)
-    {
-      next = node->next;
-      g_nodes_free (node->children);
-      g_free (node);
-      node = next;
-    }
-}
-#endif
-
 void
 g_node_destroy (GNode *root)
 {
@@ -1047,6 +931,12 @@
 	    func (current, data);
 	}
     }
+}
+
+void
+_g_node_thread_init (void)
+{
+  g_node_mem_chunk_init ();
 }
 
 #define __G_NODE_C__
Index: glib/gnode.h
===================================================================
RCS file: /cvs/gnome/glib/glib/gnode.h,v
retrieving revision 1.5
diff -u -r1.5 gnode.h
--- glib/gnode.h	8 Nov 2004 19:14:04 -0000	1.5
+++ glib/gnode.h	13 Sep 2005 04:35:56 -0000
@@ -76,8 +76,6 @@
 				 ((GNode*) (node))->next == NULL)
 #define	 G_NODE_IS_LEAF(node)	(((GNode*) (node))->children == NULL)
 
-void     g_node_push_allocator  (GAllocator       *allocator);
-void     g_node_pop_allocator   (void);
 GNode*	 g_node_new		(gpointer	   data);
 void	 g_node_destroy		(GNode		  *root);
 void	 g_node_unlink		(GNode		  *node);
Index: glib/gslist.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gslist.c,v
retrieving revision 1.27
diff -u -r1.27 gslist.c
--- glib/gslist.c	14 Mar 2005 04:26:57 -0000	1.27
+++ glib/gslist.c	13 Sep 2005 04:35:56 -0000
@@ -33,75 +33,16 @@
 #include "glib.h"
 #include "galias.h"
 
+static GMemChunk *g_slist_mem_chunk = NULL;
 
-#ifndef DISABLE_MEM_POOLS
-struct _GAllocator /* from gmem.c */
-{
-  gchar         *name;
-  guint16        n_preallocs;
-  guint          is_unused : 1;
-  guint          type : 4;
-  GAllocator    *last;
-  GMemChunk     *mem_chunk;
-  GSList        *free_lists; /* implementation specific */
-};
-
-G_LOCK_DEFINE_STATIC (current_allocator);
-static GAllocator       *current_allocator = NULL;
-
-/* HOLDS: current_allocator_lock */
-static void
-g_slist_validate_allocator (GAllocator *allocator)
+static inline void
+g_slist_mem_chunk_init (void)
 {
-  g_return_if_fail (allocator != NULL);
-  g_return_if_fail (allocator->is_unused == TRUE);
-
-  if (allocator->type != G_ALLOCATOR_SLIST)
-    {
-      allocator->type = G_ALLOCATOR_SLIST;
-      if (allocator->mem_chunk)
-	{
-	  g_mem_chunk_destroy (allocator->mem_chunk);
-	  allocator->mem_chunk = NULL;
-	}
-    }
-
-  if (!allocator->mem_chunk)
-    {
-      allocator->mem_chunk = g_mem_chunk_new (allocator->name,
+  if (!g_slist_mem_chunk)
+    g_slist_mem_chunk = g_mem_chunk_new_list ("GSList mem chunk",
 					      sizeof (GSList),
-					      sizeof (GSList) * allocator->n_preallocs,
+					      sizeof (GSList) * 128,
 					      G_ALLOC_ONLY);
-      allocator->free_lists = NULL;
-    }
-
-  allocator->is_unused = FALSE;
-}
-
-void
-g_slist_push_allocator (GAllocator *allocator)
-{
-  G_LOCK (current_allocator);
-  g_slist_validate_allocator (allocator);
-  allocator->last = current_allocator;
-  current_allocator = allocator;
-  G_UNLOCK (current_allocator);
-}
-
-void
-g_slist_pop_allocator (void)
-{
-  G_LOCK (current_allocator);
-  if (current_allocator)
-    {
-      GAllocator *allocator;
-
-      allocator = current_allocator;
-      current_allocator = allocator->last;
-      allocator->last = NULL;
-      allocator->is_unused = TRUE;
-    }
-  G_UNLOCK (current_allocator);
 }
 
 static inline GSList*
@@ -109,36 +50,10 @@
 {
   GSList *list;
 
-  G_LOCK (current_allocator);
-  if (!current_allocator)
-    {
-      GAllocator *allocator = g_allocator_new ("GLib default GSList allocator",
-					       128);
-      g_slist_validate_allocator (allocator);
-      allocator->last = NULL;
-      current_allocator = allocator; 
-    }
-  if (!current_allocator->free_lists)
-    {
-      list = g_chunk_new (GSList, current_allocator->mem_chunk);
-      list->data = NULL;
-    }
-  else
-    {
-      if (current_allocator->free_lists->data)
-	{
-	  list = current_allocator->free_lists->data;
-	  current_allocator->free_lists->data = list->next;
-	  list->data = NULL;
-	}
-      else
-	{
-	  list = current_allocator->free_lists;
-	  current_allocator->free_lists = list->next;
-	}
-    }
-  G_UNLOCK (current_allocator);
-  
+  g_slist_mem_chunk_init ();
+
+  list = g_chunk_new (GSList, g_slist_mem_chunk);
+  list->data = NULL;
   list->next = NULL;
 
   return list;
@@ -154,25 +69,7 @@
 g_slist_free (GSList *list)
 {
   if (list)
-    {
-      GSList *last_node = list;
-  
-#ifdef ENABLE_GC_FRIENDLY
-      while (last_node->next)
-	{
-	  last_node->data = NULL;
-	  last_node = last_node->next;
-	}
-      last_node->data = NULL;
-#else /* !ENABLE_GC_FRIENDLY */
-      list->data = list->next;  
-#endif /* ENABLE_GC_FRIENDLY */
-	
-      G_LOCK (current_allocator);
-      last_node->next = current_allocator->free_lists;
-      current_allocator->free_lists = list;
-      G_UNLOCK (current_allocator);
-    }
+    g_mem_chunk_free (g_slist_mem_chunk, list);
 }
 
 static inline void
@@ -180,11 +77,8 @@
 {
   if (list)
     {
-      list->data = NULL;
-      G_LOCK (current_allocator);
-      list->next = current_allocator->free_lists;
-      current_allocator->free_lists = list;
-      G_UNLOCK (current_allocator);
+      list->next = NULL;
+      g_mem_chunk_free (g_slist_mem_chunk, list);
     }
 }
 
@@ -193,40 +87,6 @@
 {
   _g_slist_free_1 (list);
 }
-#else /* DISABLE_MEM_POOLS */
-
-#define _g_slist_alloc g_slist_alloc
-GSList*
-g_slist_alloc (void)
-{
-  GSList *list;
-  
-  list = g_new0 (GSList, 1);
-  
-  return list;
-}
-
-void
-g_slist_free (GSList *list)
-{
-  GSList *last;
-  
-  while (list)
-    {
-      last = list;
-      list = list->next;
-      g_free (last);
-    }
-}
-
-#define _g_slist_free_1 g_slist_free_1
-void
-g_slist_free_1 (GSList *list)
-{
-  g_free (list);
-}
-
-#endif
 
 GSList*
 g_slist_append (GSList   *list,
@@ -241,7 +101,6 @@
   if (list)
     {
       last = g_slist_last (list);
-      /* g_assert (last != NULL); */
       last->next = new_list;
 
       return list;
@@ -346,7 +205,8 @@
 }
 
 GSList *
-g_slist_concat (GSList *list1, GSList *list2)
+g_slist_concat (GSList *list1, 
+		GSList *list2)
 {
   if (list2)
     {
@@ -763,6 +623,12 @@
 			gpointer          user_data)
 {
   return g_slist_sort_real (list, (GFunc) compare_func, TRUE, user_data);
+}
+
+void
+_g_slist_thread_init (void)
+{
+  g_slist_mem_chunk_init ();
 }
 
 #define __G_SLIST_C__
Index: glib/gslist.h
===================================================================
RCS file: /cvs/gnome/glib/glib/gslist.h,v
retrieving revision 1.6
diff -u -r1.6 gslist.h
--- glib/gslist.h	8 Nov 2002 18:47:54 -0000	1.6
+++ glib/gslist.h	13 Sep 2005 04:35:56 -0000
@@ -41,8 +41,6 @@
 
 /* Singly linked lists
  */
-void     g_slist_push_allocator (GAllocator       *allocator);
-void     g_slist_pop_allocator  (void);
 GSList*  g_slist_alloc          (void);
 void     g_slist_free           (GSList           *list);
 void     g_slist_free_1         (GSList           *list);
Index: glib/gthread.c
===================================================================
RCS file: /cvs/gnome/glib/glib/gthread.c,v
retrieving revision 1.45
diff -u -r1.45 gthread.c
--- glib/gthread.c	12 Jul 2005 16:56:51 -0000	1.45
+++ glib/gthread.c	13 Sep 2005 04:35:56 -0000
@@ -156,6 +156,10 @@
 #ifdef G_OS_WIN32
   _g_win32_thread_init ();
 #endif
+  _g_list_thread_init ();
+  _g_slist_thread_init ();
+  _g_node_thread_init ();
+  _g_hash_thread_init ();
 
   g_threads_got_initialized = TRUE;
 
Index: glib/gthreadinit.h
===================================================================
RCS file: /cvs/gnome/glib/glib/gthreadinit.h,v
retrieving revision 1.6
diff -u -r1.6 gthreadinit.h
--- glib/gthreadinit.h	7 Dec 2004 15:20:15 -0000	1.6
+++ glib/gthreadinit.h	13 Sep 2005 04:35:56 -0000
@@ -37,6 +37,10 @@
 #ifdef G_OS_WIN32
 void _g_win32_thread_init (void) G_GNUC_INTERNAL;
 #endif
+void _g_list_thread_init (void) G_GNUC_INTERNAL;
+void _g_slist_thread_init (void) G_GNUC_INTERNAL;
+void _g_node_thread_init (void) G_GNUC_INTERNAL;
+void _g_hash_thread_init (void) G_GNUC_INTERNAL;
 
 /* Are called from glib/gthread.c. Must only contain g_private_new calls */
 void _g_mem_thread_private_init (void) G_GNUC_INTERNAL;
