From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14257 invoked by alias); 18 Mar 2018 20:04:45 -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 14240 invoked by uid 9078); 18 Mar 2018 20:04:45 -0000 Date: Sun, 18 Mar 2018 20:04:00 -0000 Message-ID: <20180318200445.14238.qmail@sourceware.org> Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Corinna Vinschen To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin] Cygwin: AF_UNIX: Use spinlock rather than SRWLOCKs X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/master X-Git-Oldrev: 1f41bc16f1f07768702010c5a2f7c1a64d0ce7fc X-Git-Newrev: 60ca1c1359e4b5b133a685623c99e14cc44507f0 X-SW-Source: 2018-q1/txt/msg00127.txt.bz2 https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=60ca1c1359e4b5b133a685623c99e14cc44507f0 commit 60ca1c1359e4b5b133a685623c99e14cc44507f0 Author: Corinna Vinschen Date: Sun Mar 18 18:46:15 2018 +0100 Cygwin: AF_UNIX: Use spinlock rather than SRWLOCKs We need to share socket info between threads *and* processes. SRWLOCKs are single-process only, unfortunately. Provide a sharable low-profile spinlock instead. Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/fhandler.h | 56 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 2e50208..0b04d7a 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -825,6 +825,32 @@ class fhandler_socket_local: public fhandler_socket_wsock } }; +/* Sharable spinlock with low CPU profile. These locks are NOT recursive! */ +class af_unix_spinlock_t +{ + LONG locked; /* 0 oder 1 */ + +public: + void lock () + { + LONG ret = InterlockedExchange (&locked, 1); + if (ret) + { + /* This loop counts the ms Sleep up from 0 to 45 in loop, 15ms steps, + with 256 iterations each, . */ + for (uint16_t i = 0; ret; i += 64) + { + Sleep (15 * (i >> 14)); + ret = InterlockedExchange (&locked, 1); + } + } + } + void unlock () + { + InterlockedExchange (&locked, 0); + } +}; + class sun_name_t { public: @@ -855,9 +881,13 @@ enum shut_state { in socket, socketpair or accept4 and reopened by dup, fork or exec. */ class af_unix_shmem_t { - SRWLOCK _bind_lock; - SRWLOCK _conn_lock; - SRWLOCK _io_lock; + /* Don't use SRWLOCKs here. They are not sharable. If you must lock + multiple locks at the same time, always lock in the order bind -> + conn -> state -> io and unlock io -> state -> conn -> bind to avoid + deadlocks. */ + af_unix_spinlock_t _bind_lock; + af_unix_spinlock_t _conn_lock; + af_unix_spinlock_t _io_lock; LONG _connection_state; /* conn_state */ LONG _binding_state; /* bind_state */ LONG _shutdown; /* shut_state */ @@ -865,20 +895,12 @@ class af_unix_shmem_t LONG _reuseaddr; /* dummy */ public: - af_unix_shmem_t () - : _connection_state (unconnected), _binding_state (unbound), - _shutdown (0), _so_error (0) - { - InitializeSRWLock (&_bind_lock); - InitializeSRWLock (&_conn_lock); - InitializeSRWLock (&_io_lock); - } - void bind_lock () { AcquireSRWLockExclusive (&_bind_lock); } - void bind_unlock () { ReleaseSRWLockExclusive (&_bind_lock); } - void conn_lock () { AcquireSRWLockExclusive (&_conn_lock); } - void conn_unlock () { ReleaseSRWLockExclusive (&_conn_lock); } - void io_lock () { AcquireSRWLockExclusive (&_io_lock); } - void io_unlock () { ReleaseSRWLockExclusive (&_io_lock); } + void bind_lock () { _bind_lock.lock (); } + void bind_unlock () { _bind_lock.unlock (); } + void conn_lock () { _conn_lock.lock (); } + void conn_unlock () { _conn_lock.unlock (); } + void io_lock () { _io_lock.lock (); } + void io_unlock () { _io_lock.unlock (); } conn_state connect_state (conn_state val) { return (conn_state) InterlockedExchange (&_connection_state, val); }