Spinlock spin with pause instruction

Hi.

I have noticed that Cygwin's spinlock goes into heavy sleeping code
for each spin. It seems it would be a good idea to actually try to
spin a bit first. There is this 'pause' instruction which let's the
CPU make such busy loops be less busy. Here is a patch to do this.

--
VH
This commit is contained in:
Václav Haisman 2016-03-11 11:28:27 +01:00 committed by Corinna Vinschen
parent d0cf3b7c02
commit b5476c81d2
1 changed files with 19 additions and 1 deletions

View File

@ -1916,6 +1916,19 @@ pthread_spinlock::lock ()
{ {
pthread_t self = ::pthread_self (); pthread_t self = ::pthread_self ();
int result = -1; int result = -1;
unsigned spins = 0;
/*
We want to spin using 'pause' instruction on multi-core system but we
want to avoid this on single-core systems.
The limit of 1000 spins is semi-arbitrary. Microsoft suggests (in their
InitializeCriticalSectionAndSpinCount documentation on MSDN) they are
using spin count limit 4000 for their heap manager critical
sections. Other source suggest spin count as small as 200 for fast path
of mutex locking.
*/
unsigned const FAST_SPINS_LIMIT = wincap.cpu_count () != 1 ? 1000 : 0;
do do
{ {
@ -1924,8 +1937,13 @@ pthread_spinlock::lock ()
set_owner (self); set_owner (self);
result = 0; result = 0;
} }
else if (pthread::equal (owner, self)) else if (unlikely(pthread::equal (owner, self)))
result = EDEADLK; result = EDEADLK;
else if (spins < FAST_SPINS_LIMIT)
{
++spins;
__asm__ volatile ("pause":::);
}
else else
{ {
/* Minimal timeout to minimize CPU usage while still spinning. */ /* Minimal timeout to minimize CPU usage while still spinning. */