From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 104749 invoked by alias); 11 Mar 2016 13:02:14 -0000 Mailing-List: contact cygwin-cvs-help@cygwin.com; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: cygwin-cvs-owner@cygwin.com Received: (qmail 104688 invoked by uid 9078); 11 Mar 2016 13:02:13 -0000 Date: Fri, 11 Mar 2016 13:02:00 -0000 Message-ID: <20160311130213.104686.qmail@sourceware.org> Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Corinna Vinschen To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Spinlock spin with pause instruction X-Act-Checkin: newlib-cygwin X-Git-Author: Václav Haisman X-Git-Refname: refs/heads/master X-Git-Oldrev: d0cf3b7c02ac5118ee8489db5737dd423689a2ca X-Git-Newrev: b5476c81d2ab27dd4a46064d3fa45556630fd3cf X-SW-Source: 2016-q1/txt/msg00124.txt.bz2 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=b5476c81d2ab27dd4a46064d3fa45556630fd3cf commit b5476c81d2ab27dd4a46064d3fa45556630fd3cf Author: Václav Haisman Date: Fri Mar 11 11:28:27 2016 +0100 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 Diff: --- winsup/cygwin/thread.cc | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 06a487a..531d6a8 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. */