aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--include/alloca.h13
-rw-r--r--nscd/mem.c21
-rw-r--r--sysdeps/x86_64/stackinfo.h12
4 files changed, 38 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 257d1e8254..36d09f734c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2009-01-28 Ulrich Drepper <drepper@redhat.com>
+ [BZ #9750]
+ * nscd/mem.c (gc): Use alloca_count to get the real stack usage.
+ * include/alloca.h (alloca_account): Define.
+ * sysdeps/x86_64/stackinfo.h (stackinfo_get_sp): Define.
+ (stackinfo_sub_sp): Define.
+
* nscd/connections.c (nscd_init): If database file access be
opened check whether this is due to permission problems and bail
in that case.
diff --git a/include/alloca.h b/include/alloca.h
index 563d7868bd..7d243fd4ac 100644
--- a/include/alloca.h
+++ b/include/alloca.h
@@ -46,4 +46,17 @@ extern int __libc_alloca_cutoff (size_t size) __attribute__ ((const));
__alloca (((len) = (newlen)))
#endif
+#if defined stackinfo_get_sp && defined stackinfo_sub_sp
+# define alloca_account(size, avar) \
+ ({ void *old__ = stackinfo_get_sp (); \
+ void *m__ = __alloca (size); \
+ avar += stackinfo_sub_sp (old__); \
+ m__; })
+#else
+# define alloca_account(size, avar) \
+ ({ size_t s__ = (size); \
+ avar += size__; \
+ __alloca (size__); })
+#endif
+
#endif
diff --git a/nscd/mem.c b/nscd/mem.c
index 5f4c4dd00f..7f3ea06f4a 100644
--- a/nscd/mem.c
+++ b/nscd/mem.c
@@ -134,12 +134,11 @@ gc (struct database_dyn *db)
stack_used = 0;
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)
+ if (__builtin_expect (stack_used + memory_needed <= MAX_STACK_USE, 1))
{
- mark = (BITMAP_T *) alloca (memory_needed);
+ mark = (BITMAP_T *) alloca_account (memory_needed, stack_used);
mark_use_malloc = false;
memset (mark, '\0', memory_needed);
- stack_used += memory_needed;
}
else
{
@@ -153,19 +152,17 @@ gc (struct database_dyn *db)
struct hashentry **he;
struct hashentry **he_data;
bool he_use_malloc;
- if (stack_used + memory_needed <= MAX_STACK_USE)
+ if (__builtin_expect (stack_used + memory_needed <= MAX_STACK_USE, 1))
{
- he = alloca (db->head->nentries * sizeof (struct hashentry *));
- he_data = alloca (db->head->nentries * sizeof (struct hashentry *));
+ he = alloca_account (memory_needed, stack_used);
he_use_malloc = false;
- stack_used += memory_needed;
}
else
{
he = xmalloc (memory_needed);
- he_data = &he[db->head->nentries];
he_use_malloc = true;
}
+ he_data = &he[db->head->nentries];
size_t cnt = 0;
for (size_t idx = 0; idx < db->head->module; ++idx)
@@ -373,11 +370,9 @@ gc (struct database_dyn *db)
ref_t disp = off_alloc - off_free;
struct moveinfo *new_move;
- if (stack_used + sizeof (*new_move) <= MAX_STACK_USE)
- {
- new_move = alloca (sizeof (*new_move));
- stack_used += sizeof (*new_move);
- }
+ if (__builtin_expect (stack_used + sizeof (*new_move) <= MAX_STACK_USE,
+ 1))
+ new_move = alloca_account (sizeof (*new_move), stack_used);
else
new_move = obstack_alloc (&ob, sizeof (*new_move));
new_move->from = db->data + off_alloc;
diff --git a/sysdeps/x86_64/stackinfo.h b/sysdeps/x86_64/stackinfo.h
index 60668d10b1..b11849d9ab 100644
--- a/sysdeps/x86_64/stackinfo.h
+++ b/sysdeps/x86_64/stackinfo.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2009 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,4 +25,14 @@
/* On x86_64 the stack grows down. */
#define _STACK_GROWS_DOWN 1
+/* Access to the stack pointer. The macros are used in alloca_account
+ for which they need to act as barriers as well, hence the additional
+ (unnecessary) parameters. */
+#define stackinfo_get_sp() \
+ ({ void *p__; asm volatile ("mov %%rsp, %0" : "=r" (p__)); p__; })
+#define stackinfo_sub_sp(ptr) \
+ ({ ptrdiff_t d__; \
+ asm volatile ("sub %%rsp, %0" : "=r" (d__) : "0" (ptr)); \
+ d__; })
+
#endif /* stackinfo.h */