From 60ca1c1359e4b5b133a685623c99e14cc44507f0 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Sun, 18 Mar 2018 18:46:15 +0100 Subject: [PATCH] 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 --- 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 2e5020860..0b04d7a55 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); }