diff options
author | Václav Haisman <vhaisman@gmail.com> | 2016-03-11 11:28:27 +0100 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2016-03-11 14:01:25 +0100 |
commit | b5476c81d2ab27dd4a46064d3fa45556630fd3cf (patch) | |
tree | 810c0e143aa619ce92ba38eb9465fc630ffe4508 | |
parent | d0cf3b7c02ac5118ee8489db5737dd423689a2ca (diff) | |
download | cygnal-b5476c81d2ab27dd4a46064d3fa45556630fd3cf.tar.gz cygnal-b5476c81d2ab27dd4a46064d3fa45556630fd3cf.tar.bz2 cygnal-b5476c81d2ab27dd4a46064d3fa45556630fd3cf.zip |
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
-rw-r--r-- | winsup/cygwin/thread.cc | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 06a487aab..531d6a846 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -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. */ |