From de8a68e85304848189643fb48100c18aa9d60e32 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Wed, 8 Feb 2017 10:30:44 -0800 Subject: [PATCH] Enhance spin_adaptive() to yield after several iterations. This avoids worst case behavior if e.g. another thread is preempted while owning the resource the spinning thread is waiting for. --- Makefile.in | 1 + include/jemalloc/internal/spin_inlines.h | 17 +++++++++++------ test/unit/spin.c | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 test/unit/spin.c diff --git a/Makefile.in b/Makefile.in index acd31f73..23056f78 100644 --- a/Makefile.in +++ b/Makefile.in @@ -189,6 +189,7 @@ TESTS_UNIT := \ $(srcroot)test/unit/size_classes.c \ $(srcroot)test/unit/slab.c \ $(srcroot)test/unit/smoothstep.c \ + $(srcroot)test/unit/spin.c \ $(srcroot)test/unit/stats.c \ $(srcroot)test/unit/stats_print.c \ $(srcroot)test/unit/ticker.c \ diff --git a/include/jemalloc/internal/spin_inlines.h b/include/jemalloc/internal/spin_inlines.h index 03beeada..16573261 100644 --- a/include/jemalloc/internal/spin_inlines.h +++ b/include/jemalloc/internal/spin_inlines.h @@ -8,14 +8,19 @@ void spin_adaptive(spin_t *spin); #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_SPIN_C_)) JEMALLOC_INLINE void spin_adaptive(spin_t *spin) { - volatile uint64_t i; + volatile uint32_t i; - for (i = 0; i < (KQU(1) << spin->iteration); i++) { - CPU_SPINWAIT; - } - - if (spin->iteration < 63) { + if (spin->iteration < 5) { + for (i = 0; i < (1U << spin->iteration); i++) { + CPU_SPINWAIT; + } spin->iteration++; + } else { +#ifdef _WIN32 + SwitchToThread(); +#else + sched_yield(); +#endif } } diff --git a/test/unit/spin.c b/test/unit/spin.c new file mode 100644 index 00000000..bd368b3d --- /dev/null +++ b/test/unit/spin.c @@ -0,0 +1,16 @@ +#include "test/jemalloc_test.h" + +TEST_BEGIN(test_spin) { + spin_t spinner = SPIN_INITIALIZER; + + for (unsigned i = 0; i < 100; i++) { + spin_adaptive(&spinner); + } +} +TEST_END + +int +main(void) { + return test( + test_spin); +}