@@ -296,6 +296,7 @@ libiscsi=""
libnfs=""
coroutine=""
coroutine_pool=""
+debug_stack_usage="no"
seccomp=""
glusterfs=""
glusterfs_xlator_opt="no"
@@ -1004,6 +1005,8 @@ for opt do
;;
--enable-coroutine-pool) coroutine_pool="yes"
;;
+ --enable-debug-stack-usage) debug_stack_usage="yes"
+ ;;
--disable-docs) docs="no"
;;
--enable-docs) docs="yes"
@@ -4298,6 +4301,13 @@ fi
if test "$coroutine" = "gthread" -a "$coroutine_pool" = "yes"; then
error_exit "'gthread' coroutine backend does not support pool (use --disable-coroutine-pool)"
fi
+if test "$debug_stack_usage" = "yes"; then
+ if test "$coroutine_pool" = "yes"; then
+ echo "WARN: disabling coroutine pool for stack usage debugging"
+ coroutine_pool=no
+ fi
+fi
+
##########################################
# check if we have open_by_handle_at
@@ -4866,6 +4876,7 @@ echo "QGA MSI support $guest_agent_msi"
echo "seccomp support $seccomp"
echo "coroutine backend $coroutine"
echo "coroutine pool $coroutine_pool"
+echo "debug stack usage $debug_stack_usage"
echo "GlusterFS support $glusterfs"
echo "Archipelago support $archipelago"
echo "gcov $gcov_tool"
@@ -5336,6 +5347,10 @@ else
echo "CONFIG_COROUTINE_POOL=0" >> $config_host_mak
fi
+if test "$debug_stack_usage" = "yes" ; then
+ echo "CONFIG_DEBUG_STACK_USAGE=y" >> $config_host_mak
+fi
+
if test "$open_by_handle_at" = "yes" ; then
echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak
fi
@@ -50,6 +50,10 @@
#include <qemu/mmap-alloc.h>
+#ifdef CONFIG_DEBUG_STACK_USAGE
+#include "qemu/error-report.h"
+#endif
+
int qemu_get_thread_id(void)
{
#if defined(__linux__)
@@ -500,6 +504,9 @@ pid_t qemu_fork(Error **errp)
void *qemu_alloc_stack(size_t sz)
{
+#ifdef CONFIG_DEBUG_STACK_USAGE
+ void *ptr2;
+#endif
/* allocate sz bytes plus one extra page for a guard
* page at the bottom of the stack */
void *ptr = mmap(NULL, sz + getpagesize(), PROT_NONE,
@@ -511,11 +518,37 @@ void *qemu_alloc_stack(size_t sz)
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0) == MAP_FAILED) {
abort();
}
- return ptr + getpagesize();
+ ptr += getpagesize();
+#ifdef CONFIG_DEBUG_STACK_USAGE
+ for (ptr2 = ptr; ptr2 < ptr + sz; ptr2 += sizeof(u_int32_t)) {
+ *(u_int32_t *)ptr2 = 0xdeadbeaf;
+ }
+#endif
+ return ptr;
}
+#ifdef CONFIG_DEBUG_STACK_USAGE
+static __thread unsigned int max_stack_usage;
+#endif
+
void qemu_free_stack(void *stack, size_t sz)
{
+#ifdef CONFIG_DEBUG_STACK_USAGE
+ void *ptr;
+ unsigned int usage;
+ for (ptr = stack; ptr < stack + sz; ptr += sizeof(u_int32_t)) {
+ if (*(u_int32_t *)ptr != 0xdeadbeaf) {
+ break;
+ }
+ }
+ usage = sz - (uintptr_t) (ptr - stack);
+ if (usage > max_stack_usage) {
+ error_report("thread %d max stack usage increased from %u to %u",
+ qemu_get_thread_id(), max_stack_usage, usage);
+ max_stack_usage = usage;
+ }
+#endif
+
/* unmap the stack plus the extra guard page */
munmap(stack - getpagesize(), sz + getpagesize());
}
this adds a knob to track the maximum stack usage of stacks created by qemu_alloc_stack. Signed-off-by: Peter Lieven <pl@kamp.de> --- configure | 15 +++++++++++++++ util/oslib-posix.c | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-)