summaryrefslogtreecommitdiff
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);