From f00fe1b8e7bf295a0ca87ac472ead52f50037c09 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 29 Mar 2011 10:32:40 +0000 Subject: * cygwin.din (pthread_spin_destroy): Export. (pthread_spin_init): Export. (pthread_spin_lock): Export. (pthread_spin_trylock): Export. (pthread_spin_unlock): Export. * posix.sgml (std-susv4): Add pthread_spin_destroy, pthread_spin_init, pthread_spin_lock, pthread_spin_trylock, pthread_spin_unlock. (std-notimpl): Remove pthread_spin_[...]. * pthread.cc (pthread_spin_init): New function. * thread.cc (pthread_spinlock::is_good_object): New function. (pthread_mutex::pthread_mutex): Rearrange initializers to accommodate protected data in pthread_mutex. (pthread_spinlock::pthread_spinlock): New constructor. (pthread_spinlock::lock): New method. (pthread_spinlock::unlock): New method. (pthread_spinlock::init): New method. (pthread_spin_lock): New function. (pthread_spin_trylock): New function. (pthread_spin_unlock): New function. (pthread_spin_destroy): New function. * thread.h (PTHREAD_SPINLOCK_MAGIC): Define. (class pthread_mutex): Change access level of members shared with derived classes to protected. (pthread_mutex::set_shared): New protected method. (class pthread_spinlock): New class, derived class of pthread_mutex. * include/pthread.h (pthread_spin_destroy): Declare. (pthread_spin_init): Declare. (pthread_spin_lock): Declare. (pthread_spin_trylock): Declare. (pthread_spin_unlock): Declare. * include/cygwin/types.h (pthread_spinlock_t): New typedef. * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. --- winsup/cygwin/ChangeLog | 35 +++++++++ winsup/cygwin/cygwin.din | 5 ++ winsup/cygwin/include/cygwin/types.h | 4 +- winsup/cygwin/include/cygwin/version.h | 4 +- winsup/cygwin/include/pthread.h | 7 ++ winsup/cygwin/posix.sgml | 6 +- winsup/cygwin/pthread.cc | 10 ++- winsup/cygwin/thread.cc | 130 ++++++++++++++++++++++++++++++++- winsup/cygwin/thread.h | 29 ++++++-- 9 files changed, 217 insertions(+), 13 deletions(-) (limited to 'winsup') diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 0c1a61075..fc9aac203 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,38 @@ +2011-03-29 Corinna Vinschen + + * cygwin.din (pthread_spin_destroy): Export. + (pthread_spin_init): Export. + (pthread_spin_lock): Export. + (pthread_spin_trylock): Export. + (pthread_spin_unlock): Export. + * posix.sgml (std-susv4): Add pthread_spin_destroy, pthread_spin_init, + pthread_spin_lock, pthread_spin_trylock, pthread_spin_unlock. + (std-notimpl): Remove pthread_spin_[...]. + * pthread.cc (pthread_spin_init): New function. + * thread.cc (pthread_spinlock::is_good_object): New function. + (pthread_mutex::pthread_mutex): Rearrange initializers to accommodate + protected data in pthread_mutex. + (pthread_spinlock::pthread_spinlock): New constructor. + (pthread_spinlock::lock): New method. + (pthread_spinlock::unlock): New method. + (pthread_spinlock::init): New method. + (pthread_spin_lock): New function. + (pthread_spin_trylock): New function. + (pthread_spin_unlock): New function. + (pthread_spin_destroy): New function. + * thread.h (PTHREAD_SPINLOCK_MAGIC): Define. + (class pthread_mutex): Change access level of members shared with + derived classes to protected. + (pthread_mutex::set_shared): New protected method. + (class pthread_spinlock): New class, derived class of pthread_mutex. + * include/pthread.h (pthread_spin_destroy): Declare. + (pthread_spin_init): Declare. + (pthread_spin_lock): Declare. + (pthread_spin_trylock): Declare. + (pthread_spin_unlock): Declare. + * include/cygwin/types.h (pthread_spinlock_t): New typedef. + * include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. + 2011-03-29 Corinna Vinschen * net.cc (SIO_BASE_HANDLE): Define. diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index e1dcea75b..10565adeb 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -1244,6 +1244,11 @@ pthread_setschedparam SIGFE pthread_setspecific SIGFE pthread_sigmask SIGFE pthread_suspend SIGFE +pthread_spin_destroy SIGFE +pthread_spin_init SIGFE +pthread_spin_lock SIGFE +pthread_spin_trylock SIGFE +pthread_spin_unlock SIGFE pthread_testcancel SIGFE pthread_yield = sched_yield SIGFE ptsname SIGFE diff --git a/winsup/cygwin/include/cygwin/types.h b/winsup/cygwin/include/cygwin/types.h index a202d958d..efc076a45 100644 --- a/winsup/cygwin/include/cygwin/types.h +++ b/winsup/cygwin/include/cygwin/types.h @@ -1,6 +1,6 @@ /* types.h - Copyright 2001, 2002, 2003, 2005, 2006, 2010 Red Hat Inc. + Copyright 2001, 2002, 2003, 2005, 2006, 2010, 2011 Red Hat Inc. Written by Robert Collins This file is part of Cygwin. @@ -195,6 +195,7 @@ typedef struct int state; } pthread_once_t; +typedef struct __pthread_spinlock_t {char __dummy;} *pthread_spinlock_t; typedef struct __pthread_rwlock_t {char __dummy;} *pthread_rwlock_t; typedef struct __pthread_rwlockattr_t {char __dummy;} *pthread_rwlockattr_t; @@ -210,6 +211,7 @@ typedef class pthread_mutexattr *pthread_mutexattr_t; typedef class pthread_condattr *pthread_condattr_t; typedef class pthread_cond *pthread_cond_t; typedef class pthread_once pthread_once_t; +typedef class pthread_spinlock *pthread_spinlock_t; typedef class pthread_rwlock *pthread_rwlock_t; typedef class pthread_rwlockattr *pthread_rwlockattr_t; diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 91c3c53d9..58c55f6e3 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -401,12 +401,14 @@ details. */ 235: Export madvise. 236: Export pthread_yield, __xpg_strerror_r. 237: Export strchrnul. + 238: Export pthread_spin_destroy, pthread_spin_init, pthread_spin_lock, + pthread_spin_trylock, pthread_spin_unlock. */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 237 +#define CYGWIN_VERSION_API_MINOR 238 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h index 8e35808e1..10a53f3fd 100644 --- a/winsup/cygwin/include/pthread.h +++ b/winsup/cygwin/include/pthread.h @@ -162,6 +162,13 @@ int pthread_mutexattr_setprotocol (pthread_mutexattr_t *, int); int pthread_mutexattr_setpshared (pthread_mutexattr_t *, int); int pthread_mutexattr_settype (pthread_mutexattr_t *, int); +/* Spinlocks */ +int pthread_spin_destroy (pthread_spinlock_t *); +int pthread_spin_init (pthread_spinlock_t *, int); +int pthread_spin_lock (pthread_spinlock_t *); +int pthread_spin_trylock (pthread_spinlock_t *); +int pthread_spin_unlock (pthread_spinlock_t *); + /* RW Locks */ int pthread_rwlock_destroy (pthread_rwlock_t *rwlock); int pthread_rwlock_init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); diff --git a/winsup/cygwin/posix.sgml b/winsup/cygwin/posix.sgml index 393a2bcb7..53e760633 100644 --- a/winsup/cygwin/posix.sgml +++ b/winsup/cygwin/posix.sgml @@ -600,6 +600,11 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008). pthread_setschedparam pthread_setspecific pthread_sigmask + pthread_spin_destroy + pthread_spin_init + pthread_spin_lock + pthread_spin_trylock + pthread_spin_unlock pthread_testcancel ptsname putc @@ -1384,7 +1389,6 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008). pthread_rwlock_timedrdlock pthread_rwlock_timedwrlock pthread_setschedprio - pthread_spin_[...] putmsg reminderl remquol diff --git a/winsup/cygwin/pthread.cc b/winsup/cygwin/pthread.cc index 18f2aea5d..3dddf48b1 100644 --- a/winsup/cygwin/pthread.cc +++ b/winsup/cygwin/pthread.cc @@ -1,6 +1,6 @@ /* pthread.cc: posix pthread interface for Cygwin - Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007 Red Hat, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2011 Red Hat, Inc. Originally written by Marco Fuykschot @@ -91,6 +91,14 @@ pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t * attr) return pthread_mutex::init (mutex, attr, NULL); } +/* Spinlocks */ +int +pthread_spin_init (pthread_spinlock_t *spinlock, int pshared) +{ + return pthread_spinlock::init (spinlock, pshared); +} + + /* Synchronisation */ int pthread_cond_init (pthread_cond_t * cond, const pthread_condattr_t * attr) diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 891b43fb9..29674d4ed 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -1,7 +1,7 @@ /* thread.cc: Locking and threading module functions Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009, 2010 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. This file is part of Cygwin. @@ -173,6 +173,14 @@ pthread_key::is_good_object (pthread_key_t const *key) return true; } +inline bool +pthread_spinlock::is_good_object (pthread_spinlock_t const *mutex) +{ + if (verifyable_object_isvalid (mutex, PTHREAD_SPINLOCK_MAGIC) != VALID_OBJECT) + return false; + return true; +} + inline bool pthread_mutex::is_good_object (pthread_mutex_t const *mutex) { @@ -1547,11 +1555,11 @@ pthread_mutex::init_mutex () pthread_mutex::pthread_mutex (pthread_mutexattr *attr) : verifyable_object (0), /* set magic to zero initially */ lock_counter (0), - win32_obj_id (NULL), recursion_counter (0), - condwaits (0), owner (_new_mutex), + win32_obj_id (NULL), owner (_new_mutex), #ifdef DEBUGGING tid (0), #endif + recursion_counter (0), condwaits (0), type (PTHREAD_MUTEX_ERRORCHECK), pshared (PTHREAD_PROCESS_PRIVATE) { @@ -1701,6 +1709,65 @@ pthread_mutexattr::~pthread_mutexattr () { } +/* pshared spinlocks + + The infrastructure is provided by the underlying pthread_mutex class. + The rest is a simplification implementing spin locking. */ + +pthread_spinlock::pthread_spinlock (int pshared) : + pthread_mutex (NULL) +{ + magic = PTHREAD_SPINLOCK_MAGIC; + set_type (PTHREAD_MUTEX_NORMAL); + set_shared (pshared); +} + +int +pthread_spinlock::lock () +{ + pthread_t self = ::pthread_self (); + int result = -1; + + do + { + if (InterlockedExchange ((long *) &lock_counter, 1) == 0) + { + set_owner (self); + result = 0; + } + else if (pthread::equal (owner, self)) + result = EDEADLK; + else /* Minimal timeout to minimize CPU usage while still spinning. */ + cancelable_wait (win32_obj_id, 1L, cw_no_cancel, cw_sig_resume); + } + while (result == -1); + pthread_printf ("spinlock %p, self %p, owner %p", this, self, owner); + return result; +} + +int +pthread_spinlock::unlock () +{ + pthread_t self = ::pthread_self (); + int result = 0; + + if (!pthread::equal (owner, self)) + result = EPERM; + else + { + owner = (pthread_t) _unlocked_mutex; +#ifdef DEBUGGING + tid = 0; +#endif + InterlockedExchange ((long *) &lock_counter, 0); + ::SetEvent (win32_obj_id); + result = 0; + } + pthread_printf ("spinlock %p, owner %p, self %p, res %d", + this, owner, self, result); + return result; +} + DWORD WINAPI pthread::thread_init_wrapper (void *arg) { @@ -2768,6 +2835,63 @@ pthread_mutex_setprioceiling (pthread_mutex_t *mutex, int prioceiling, return ENOSYS; } +/* Spinlocks */ + +int +pthread_spinlock::init (pthread_spinlock_t *spinlock, int pshared) +{ + pthread_spinlock_t new_spinlock = new pthread_spinlock (pshared); + if (!is_good_object (&new_spinlock)) + { + delete new_spinlock; + return EAGAIN; + } + + myfault efault; + if (efault.faulted ()) + { + delete new_spinlock; + return EINVAL; + } + + *spinlock = new_spinlock; + pthread_printf ("*spinlock %p, pshared %d", *spinlock, pshared); + + return 0; +} + +extern "C" int +pthread_spin_lock (pthread_spinlock_t *spinlock) +{ + if (!pthread_spinlock::is_good_object (spinlock)) + return EINVAL; + return (*spinlock)->lock (); +} + +extern "C" int +pthread_spin_trylock (pthread_spinlock_t *spinlock) +{ + if (!pthread_spinlock::is_good_object (spinlock)) + return EINVAL; + return (*spinlock)->trylock (); +} + +extern "C" int +pthread_spin_unlock (pthread_spinlock_t *spinlock) +{ + if (!pthread_spinlock::is_good_object (spinlock)) + return EINVAL; + return (*spinlock)->unlock (); +} + +extern "C" int +pthread_spin_destroy (pthread_spinlock_t *spinlock) +{ + if (!pthread_spinlock::is_good_object (spinlock)) + return EINVAL; + return (*spinlock)->destroy (); +} + /* Win32 doesn't support mutex priorities - see __pthread_mutex_getprioceiling for more detail */ extern "C" int diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h index bea8e2aa3..f96714f49 100644 --- a/winsup/cygwin/thread.h +++ b/winsup/cygwin/thread.h @@ -1,7 +1,7 @@ /* thread.h: Locking and threading module definitions Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, - 2008, 2009, 2010 Red Hat, Inc. + 2008, 2009, 2010, 2011 Red Hat, Inc. This file is part of Cygwin. @@ -98,6 +98,7 @@ class pinfo; #define PTHREAD_ONCE_MAGIC PTHREAD_MAGIC+8 #define PTHREAD_RWLOCK_MAGIC PTHREAD_MAGIC+9 #define PTHREAD_RWLOCKATTR_MAGIC PTHREAD_MAGIC+10 +#define PTHREAD_SPINLOCK_MAGIC PTHREAD_MAGIC+11 #define MUTEX_OWNER_ANONYMOUS ((pthread_t) -1) @@ -303,18 +304,15 @@ public: mutexes.for_each (&pthread_mutex::_fixup_after_fork); } -private: +protected: unsigned long lock_counter; HANDLE win32_obj_id; - unsigned int recursion_counter; - LONG condwaits; pthread_t owner; #ifdef DEBUGGING DWORD tid; /* the thread id of the owner */ #endif - int type; - int pshared; + void set_shared (int in_shared) { pshared = in_shared; } void set_owner (pthread_t self) { recursion_counter = 1; @@ -323,10 +321,17 @@ private: tid = GetCurrentThreadId (); #endif } + static const pthread_t _new_mutex; static const pthread_t _unlocked_mutex; static const pthread_t _destroyed_mutex; +private: + unsigned int recursion_counter; + LONG condwaits; + int type; + int pshared; + bool no_owner (); void _fixup_after_fork (); @@ -335,6 +340,18 @@ private: friend class pthread_cond; }; +class pthread_spinlock: public pthread_mutex +{ +public: + static bool is_good_object (pthread_spinlock_t const *); + static int init (pthread_spinlock_t *, int); + + int lock (); + int unlock (); + + pthread_spinlock (int); +}; + #define WAIT_CANCELED (WAIT_OBJECT_0 + 1) #define WAIT_SIGNALED (WAIT_OBJECT_0 + 2) -- cgit v1.2.3