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 ();
|
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. */
|
||||||
|
|
Loading…
Reference in New Issue