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.
This commit is contained in:
Jason Evans 2017-02-08 10:30:44 -08:00
parent 5f11830754
commit de8a68e853
3 changed files with 28 additions and 6 deletions

View File

@ -189,6 +189,7 @@ TESTS_UNIT := \
$(srcroot)test/unit/size_classes.c \ $(srcroot)test/unit/size_classes.c \
$(srcroot)test/unit/slab.c \ $(srcroot)test/unit/slab.c \
$(srcroot)test/unit/smoothstep.c \ $(srcroot)test/unit/smoothstep.c \
$(srcroot)test/unit/spin.c \
$(srcroot)test/unit/stats.c \ $(srcroot)test/unit/stats.c \
$(srcroot)test/unit/stats_print.c \ $(srcroot)test/unit/stats_print.c \
$(srcroot)test/unit/ticker.c \ $(srcroot)test/unit/ticker.c \

View File

@ -8,14 +8,19 @@ void spin_adaptive(spin_t *spin);
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_SPIN_C_)) #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_SPIN_C_))
JEMALLOC_INLINE void JEMALLOC_INLINE void
spin_adaptive(spin_t *spin) { spin_adaptive(spin_t *spin) {
volatile uint64_t i; volatile uint32_t i;
for (i = 0; i < (KQU(1) << spin->iteration); i++) { if (spin->iteration < 5) {
CPU_SPINWAIT; for (i = 0; i < (1U << spin->iteration); i++) {
} CPU_SPINWAIT;
}
if (spin->iteration < 63) {
spin->iteration++; spin->iteration++;
} else {
#ifdef _WIN32
SwitchToThread();
#else
sched_yield();
#endif
} }
} }

16
test/unit/spin.c Normal file
View File

@ -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);
}