Commit 3f4349dc authored by Kevin Wolf's avatar Kevin Wolf
Browse files

coroutine-ucontext: Help valgrind understand coroutines



valgrind tends to get confused and report false positives when you
switch stacks and don't tell it about it.

Signed-off-by: default avatarKevin Wolf <kwolf@redhat.com>
Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 9e559533
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -2870,6 +2870,22 @@ if compile_prog "" "" ; then
    linux_magic_h=yes
fi

########################################
# check if we have valgrind/valgrind.h

valgrind_h=no
cat > $TMPC << EOF
#include <valgrind/valgrind.h>
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
int main(void) {
  VALGRIND_STACK_DEREGISTER(0);
  return 0;
}
EOF
if compile_prog "" "" ; then
    valgrind_h=yes
fi

########################################
# check if environ is declared

@@ -3379,6 +3395,10 @@ if test "$linux_magic_h" = "yes" ; then
  echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
fi

if test "$valgrind_h" = "yes" ; then
  echo "CONFIG_VALGRIND_H=y" >> $config_host_mak
fi

if test "$has_environ" = "yes" ; then
  echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak
fi
+28 −0
Original line number Diff line number Diff line
@@ -30,6 +30,10 @@
#include "qemu-common.h"
#include "qemu-coroutine-int.h"

#ifdef CONFIG_VALGRIND_H
#include <valgrind/valgrind.h>
#endif

enum {
    /* Maximum free pool size prevents holding too many freed coroutines */
    POOL_MAX_SIZE = 64,
@@ -43,6 +47,11 @@ typedef struct {
    Coroutine base;
    void *stack;
    jmp_buf env;

#ifdef CONFIG_VALGRIND_H
    unsigned int valgrind_stack_id;
#endif

} CoroutineUContext;

/**
@@ -159,6 +168,11 @@ static Coroutine *coroutine_new(void)
    uc.uc_stack.ss_size = stack_size;
    uc.uc_stack.ss_flags = 0;

#ifdef CONFIG_VALGRIND_H
    co->valgrind_stack_id =
        VALGRIND_STACK_REGISTER(co->stack, co->stack + stack_size);
#endif

    arg.p = co;

    makecontext(&uc, (void (*)(void))coroutine_trampoline,
@@ -185,6 +199,16 @@ Coroutine *qemu_coroutine_new(void)
    return co;
}

#ifdef CONFIG_VALGRIND_H
/* Work around an unused variable in the valgrind.h macro... */
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
static inline void valgrind_stack_deregister(CoroutineUContext *co)
{
    VALGRIND_STACK_DEREGISTER(co->valgrind_stack_id);
}
#pragma GCC diagnostic error "-Wunused-but-set-variable"
#endif

void qemu_coroutine_delete(Coroutine *co_)
{
    CoroutineUContext *co = DO_UPCAST(CoroutineUContext, base, co_);
@@ -196,6 +220,10 @@ void qemu_coroutine_delete(Coroutine *co_)
        return;
    }

#ifdef CONFIG_VALGRIND_H
    valgrind_stack_deregister(co);
#endif

    g_free(co->stack);
    g_free(co);
}