By default GCC uses "simple" coverage counter update mechanism. It is perfectly fine for single-threaded (or single CPU in our case) setups, but will cause race conditions on SMP systems.
For example, I observed that counters are going backwards when running Xen inside QEMU. GCC starting from version 7 and LLVM/Clang starting from version 11 support -fprofile-update=atomic option, which forces coverage counter updates to be atomic, which resolves the issue. As Xen runs mostly on SMP systems, force use this option if it is supported by a compiler. Signed-off-by: Volodymyr Babchuk <volodymyr_babc...@epam.com> --- xen/Kconfig | 4 ++++ xen/Rules.mk | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/xen/Kconfig b/xen/Kconfig index 07c4accf88..3a6635ac74 100644 --- a/xen/Kconfig +++ b/xen/Kconfig @@ -55,6 +55,10 @@ config CC_HAS_ASM_GOTO_OUTPUT config CC_HAS_MCDC def_bool $(cc-option,-fcondition-coverage) +# Compiler supports -fprofile-update=atomic for correct SMP handling +config CC_HAS_ATOMIC_PROFILE + def_bool $(cc-option,-fprofile-update=atomic) + # Set code alignment. # # Allow setting on a boolean basis, and then convert such selection to an diff --git a/xen/Rules.mk b/xen/Rules.mk index da21850926..7219a3033f 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -141,6 +141,10 @@ else cov-cflags-$(CONFIG_CONDITION_COVERAGE) += -fcondition-coverage endif +ifeq ($(CONFIG_CC_HAS_ATOMIC_PROFILE),y) + cov-cflags-$(CONFIG_COVERAGE) += -fprofile-update=atomic +endif + # Reset cov-cflags-y in cases where an objects has another one as prerequisite $(nocov-y) $(filter %.init.o, $(obj-y) $(obj-bin-y) $(extra-y)): \ cov-cflags-y := -- 2.50.0