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:
parent
d0cf3b7c02
commit
b5476c81d2
|
@ -1916,6 +1916,19 @@ pthread_spinlock::lock ()
|
|||
{
|
||||
pthread_t self = ::pthread_self ();
|
||||
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
|
||||
{
|
||||
|
@ -1924,8 +1937,13 @@ pthread_spinlock::lock ()
|
|||
set_owner (self);
|
||||
result = 0;
|
||||
}
|
||||
else if (pthread::equal (owner, self))
|
||||
else if (unlikely(pthread::equal (owner, self)))
|
||||
result = EDEADLK;
|
||||
else if (spins < FAST_SPINS_LIMIT)
|
||||
{
|
||||
++spins;
|
||||
__asm__ volatile ("pause":::);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Minimal timeout to minimize CPU usage while still spinning. */
|
||||
|
|
Loading…
Reference in New Issue