* 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.
This commit is contained in:
@ -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
|
||||
|
Reference in New Issue
Block a user