about summary refs log tree commit diff
path: root/nscd/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'nscd/mem.c')
-rw-r--r--nscd/mem.c53
1 files changed, 35 insertions, 18 deletions
diff --git a/nscd/mem.c b/nscd/mem.c
index 14928d633c..96ff03f0df 100644
--- a/nscd/mem.c
+++ b/nscd/mem.c
@@ -24,6 +24,7 @@
 #include <inttypes.h>
 #include <libintl.h>
 #include <limits.h>
+#include <obstack.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -79,6 +80,7 @@ static void
 markrange (BITMAP_T *mark, ref_t start, size_t len)
 {
   /* Adjust parameters for block alignment.  */
+  assert ((start & BLOCK_ALIGN_M1) == 0);
   start /= BLOCK_ALIGN;
   len = (len + BLOCK_ALIGN_M1) / BLOCK_ALIGN;
 
@@ -93,7 +95,7 @@ markrange (BITMAP_T *mark, ref_t start, size_t len)
 	  return;
 	}
 
-      mark[elem++] |= 0xff << (start % BITS);
+      mark[elem++] |= ALLBITS << (start % BITS);
       len -= BITS - (start % BITS);
     }
 
@@ -130,14 +132,14 @@ gc (struct database_dyn *db)
   size_t stack_used = sizeof (bool) * db->head->module;
   if (__builtin_expect (stack_used > MAX_STACK_USE, 0))
     stack_used = 0;
-  size_t memory_needed = ((db->head->first_free / BLOCK_ALIGN + BITS - 1)
-			  / BITS) * sizeof (BITMAP_T);
-  if (memory_needed <= MAX_STACK_USE)
+  size_t nmark = (db->head->first_free / BLOCK_ALIGN + BITS - 1) / BITS;
+  size_t memory_needed = nmark * sizeof (BITMAP_T);
+  if (stack_used + memory_needed <= MAX_STACK_USE)
     {
       mark = (BITMAP_T *) alloca (memory_needed);
       mark_use_malloc = false;
       memset (mark, '\0', memory_needed);
-      stack_used = memory_needed;
+      stack_used += memory_needed;
     }
   else
     {
@@ -156,6 +158,7 @@ gc (struct database_dyn *db)
       he = alloca (db->head->nentries * sizeof (struct hashentry *));
       he_data = alloca (db->head->nentries * sizeof (struct hashentry *));
       he_use_malloc = false;
+      stack_used += memory_needed;
     }
   else
     {
@@ -212,11 +215,12 @@ gc (struct database_dyn *db)
       for (enum in_flight idx = IDX_result_data;
 	   idx < IDX_last && mrunp->block[idx].dbidx == db - dbs; ++idx)
 	{
-	 assert ((char *) mrunp->block[idx].blockaddr > db->data);
-	 assert ((char *) mrunp->block[idx].blockaddr
-		 + mrunp->block[0].blocklen <= db->data + db->memsize);
-	 markrange (mark, (char *) mrunp->block[idx].blockaddr -  db->data,
-		    mrunp->block[idx].blocklen);
+	  assert (mrunp->block[idx].blockoff >= 0);
+	  assert (mrunp->block[idx].blocklen < db->memsize);
+	  assert (mrunp->block[idx].blockoff
+		  + mrunp->block[0].blocklen <= db->memsize);
+	  markrange (mark, mrunp->block[idx].blockoff,
+		     mrunp->block[idx].blocklen);
 	}
 
       mrunp = mrunp->next;
@@ -232,7 +236,7 @@ gc (struct database_dyn *db)
   qsort (he, cnt, sizeof (struct hashentry *), sort_he);
 
   /* Determine the highest used address.  */
-  size_t high = sizeof (mark);
+  size_t high = nmark;
   while (high > 0 && mark[high - 1] == 0)
     --high;
 
@@ -303,6 +307,10 @@ gc (struct database_dyn *db)
     size_t size;
     struct moveinfo *next;
   } *moves = NULL;
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+  struct obstack ob;
+  obstack_init (&ob);
 
   while (byte < high)
     {
@@ -363,8 +371,14 @@ gc (struct database_dyn *db)
 	 displacement.  */
       ref_t disp = off_alloc - off_free;
 
-      struct moveinfo *new_move
-	= (struct moveinfo *) alloca (sizeof (*new_move));
+      struct moveinfo *new_move;
+      if (stack_used + sizeof (*new_move) <= MAX_STACK_USE)
+	{
+	  new_move = alloca (sizeof (*new_move));
+	  stack_used += sizeof (*new_move);
+	}
+      else
+	new_move = obstack_alloc (&ob, sizeof (*new_move));
       new_move->from = db->data + off_alloc;
       new_move->to = db->data + off_free;
       new_move->size = off_allocend - off_alloc;
@@ -524,6 +538,8 @@ gc (struct database_dyn *db)
     free (he);
   if (mark_use_malloc)
     free (mark);
+
+  obstack_free (&ob, NULL);
 }
 
 
@@ -589,15 +605,16 @@ mempool_alloc (struct database_dyn *db, size_t len, enum in_flight idx)
     }
   else
     {
-      db->head->first_free += len;
-
-      db->last_alloc_failed = false;
-
       /* Remember that we have allocated this memory.  */
       assert (idx >= 0 && idx < IDX_last);
       mem_in_flight.block[idx].dbidx = db - dbs;
       mem_in_flight.block[idx].blocklen = len;
-      mem_in_flight.block[idx].blockaddr = res;
+      mem_in_flight.block[idx].blockoff = db->head->first_free;
+
+      db->head->first_free += len;
+
+      db->last_alloc_failed = false;
+
     }
 
   pthread_mutex_unlock (&db->memlock);