diff options
Diffstat (limited to 'nscd/mem.c')
-rw-r--r-- | nscd/mem.c | 53 |
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); |