aboutsummaryrefslogtreecommitdiff
path: root/nscd/mem.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-11-23 06:37:58 +0000
committerUlrich Drepper <drepper@redhat.com>2007-11-23 06:37:58 +0000
commit7ea8eb02b0f6965926cb029c8567c418f548e798 (patch)
treebf3fa47ea6091901ff990e5514f07d18c8fd9602 /nscd/mem.c
parent5c3a3dba227808f16a1dc2676c9fc49f66945b08 (diff)
downloadglibc-7ea8eb02b0f6965926cb029c8567c418f548e798.tar
glibc-7ea8eb02b0f6965926cb029c8567c418f548e798.tar.gz
glibc-7ea8eb02b0f6965926cb029c8567c418f548e798.tar.bz2
glibc-7ea8eb02b0f6965926cb029c8567c418f548e798.zip
[BZ #5382]
* nscd/nscd.h (NSCD_THREAD_STACKSIZE): Define. * nscd/connections.c (start_threads): Use NSCD_THREAD_STACKSIZE. * nscd/mem.c (gc): Don't allocate arrays on stack if it can overflow it. * sysdeps/unix/sysv/linux/nscd_setup_thread.c (setup_thread): Return zero in case thread library is not NPTL.
Diffstat (limited to 'nscd/mem.c')
-rw-r--r--nscd/mem.c55
1 files changed, 50 insertions, 5 deletions
diff --git a/nscd/mem.c b/nscd/mem.c
index d7c59244aa..5c269219b3 100644
--- a/nscd/mem.c
+++ b/nscd/mem.c
@@ -34,6 +34,11 @@
#include "nscd.h"
+/* Wrapper functions with error checking for standard functions. */
+extern void *xmalloc (size_t n);
+extern void *xcalloc (size_t n, size_t s);
+
+
static int
sort_he (const void *p1, const void *p2)
{
@@ -69,6 +74,10 @@ sort_he_data (const void *p1, const void *p2)
#define ALLBITS ((((BITMAP_T) 1) << BITS) - 1)
#define HIGHBIT (((BITMAP_T) 1) << (BITS - 1))
+/* Maximum size of stack frames we allow the thread to use. We use
+ 80% of the thread stack size. */
+#define MAX_STACK_USE ((8 * NSCD_THREAD_STACKSIZE) / 10)
+
static void
markrange (BITMAP_T *mark, ref_t start, size_t len)
@@ -117,13 +126,43 @@ gc (struct database_dyn *db)
we have to look at the memory. We use a mark and sweep algorithm
where the marks are placed in this array. */
assert (db->head->first_free % BLOCK_ALIGN == 0);
- BITMAP_T mark[(db->head->first_free / BLOCK_ALIGN + BITS - 1) / BITS];
- memset (mark, '\0', sizeof (mark));
+
+ BITMAP_T *mark;
+ bool mark_use_malloc;
+ size_t 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)
+ {
+ mark = (BITMAP_T *) alloca (memory_needed);
+ mark_use_malloc = false;
+ memset (mark, '\0', memory_needed);
+ stack_used = memory_needed;
+ }
+ else
+ {
+ mark = (BITMAP_T *) xcalloc (1, memory_needed);
+ mark_use_malloc = true;
+ }
/* Create an array which can hold pointer to all the entries in hash
entries. */
- struct hashentry *he[db->head->nentries];
- struct hashentry *he_data[db->head->nentries];
+ memory_needed = 2 * db->head->nentries * sizeof (struct hashentry *);
+ struct hashentry **he;
+ struct hashentry **he_data;
+ bool he_use_malloc;
+ if (stack_used + memory_needed <= MAX_STACK_USE)
+ {
+ he = alloca (db->head->nentries * sizeof (struct hashentry *));
+ he_data = alloca (db->head->nentries * sizeof (struct hashentry *));
+ he_use_malloc = false;
+ }
+ else
+ {
+ he = xmalloc (memory_needed);
+ he_data = &he[db->head->nentries * sizeof (struct hashentry *)];
+ he_use_malloc = true;
+ }
size_t cnt = 0;
for (size_t idx = 0; idx < db->head->module; ++idx)
@@ -455,6 +494,11 @@ gc (struct database_dyn *db)
out:
pthread_mutex_unlock (&db->memlock);
pthread_rwlock_unlock (&db->lock);
+
+ if (he_use_malloc)
+ free (he);
+ if (mark_use_malloc)
+ free (mark);
}
@@ -481,7 +525,8 @@ mempool_alloc (struct database_dyn *db, size_t len)
{
/* Try to resize the database. Grow size of 1/8th. */
size_t oldtotal = (sizeof (struct database_pers_head)
- + roundup (db->head->module * sizeof (ref_t), ALIGN)
+ + roundup (db->head->module * sizeof (ref_t),
+ ALIGN)
+ db->head->data_size);
size_t new_data_size = (db->head->data_size
+ MAX (2 * len, db->head->data_size / 8));