mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-19 04:49:25 +08:00
* include/sys/strace.h: Define _STRACE_SPECIAL.
(strace_printf_wrap): Fix NOSTRACE definitions. (strace_printf_wrap1): Fix NOSTRACE definitions. (special_printf): Define. * thread.cc: Perform minor syntax fix in a comment. Rename "is_good_initialzer*" to "is_initializer*" throughout. Use pthread_printf rather than debug_printf throughout. Add extra pthread_printf debugging throughout. (pthread_mutex::_new_mutex): New constant value. (pthread_mutex::_unlocked_mutex): Ditto. (pthread_mutex::_destroyed_mutex): Ditto. (pthread_mutex::no_owner): Define new function. (pthread_mutex::can_be_unlocked): Detect no_owner situation. Handle PTHREAD_MUTEX_NORMAL as a special case. (pthread::create_cancel_event): Use C++ boolean values. (pthread::precreate): Use method to set mutex type. (pthread_cond::pthread_cond): Ditto. (pthread_rwlock::pthread_rwlock): Ditto. (pthread_mutex::pthread_mutex): Set owner to _new_mutex initially. (pthread_mutex::~pthread_mutex): Reset various elements to make it clearer if they are incorrectly reused. (pthread_mutex::lock): Add clarifying comment. (pthread_mutex::unlock): Attempt to handle various mutex types correctly. In particular, reinstate ability to have one thread unlock another thread's mutex if type == PTHREAD_MUTEX_NORMAL. (semaphore::_fixup_after_fork): Avoid redundancy. (pthread_mutex::_fixup_after_fork): Ditto. Fix debugging statement. (__pthread_cond_dowait): Accommodate changes to remove previously inexplicable use can_be_unblocked() as a static function. * thread.h: Rename "is_good_initialzer*" to "is_initializer*" throughout. (pthread_mutex): Reorganize. Make many things private. (pthread_mutex::no_owner): Define new method. (pthread_mutex::_new_mutex): Define new constant. (pthread_mutex::_unlocked_mutex): Ditto. (pthread_mutex::_destroyed_mutex): Ditto.
This commit is contained in:
parent
80206d7f71
commit
478ea460eb
@ -1,3 +1,43 @@
|
||||
2010-02-22 Christopher Faylor <me+cygwin@cgf.cx>
|
||||
|
||||
* include/sys/strace.h: Define _STRACE_SPECIAL.
|
||||
(strace_printf_wrap): Fix NOSTRACE definitions.
|
||||
(strace_printf_wrap1): Fix NOSTRACE definitions.
|
||||
(special_printf): Define.
|
||||
|
||||
* thread.cc: Perform minor syntax fix in a comment. Rename
|
||||
"is_good_initialzer*" to "is_initializer*" throughout. Use
|
||||
pthread_printf rather than debug_printf throughout. Add extra
|
||||
pthread_printf debugging throughout.
|
||||
(pthread_mutex::_new_mutex): New constant value.
|
||||
(pthread_mutex::_unlocked_mutex): Ditto.
|
||||
(pthread_mutex::_destroyed_mutex): Ditto.
|
||||
(pthread_mutex::no_owner): Define new function.
|
||||
(pthread_mutex::can_be_unlocked): Detect no_owner situation. Handle
|
||||
PTHREAD_MUTEX_NORMAL as a special case.
|
||||
(pthread::create_cancel_event): Use C++ boolean values.
|
||||
(pthread::precreate): Use method to set mutex type.
|
||||
(pthread_cond::pthread_cond): Ditto.
|
||||
(pthread_rwlock::pthread_rwlock): Ditto.
|
||||
(pthread_mutex::pthread_mutex): Set owner to _new_mutex initially.
|
||||
(pthread_mutex::~pthread_mutex): Reset various elements to make it
|
||||
clearer if they are incorrectly reused.
|
||||
(pthread_mutex::lock): Add clarifying comment.
|
||||
(pthread_mutex::unlock): Attempt to handle various mutex types
|
||||
correctly. In particular, reinstate ability to have one thread unlock
|
||||
another thread's mutex if type == PTHREAD_MUTEX_NORMAL.
|
||||
(semaphore::_fixup_after_fork): Avoid redundancy.
|
||||
(pthread_mutex::_fixup_after_fork): Ditto. Fix debugging statement.
|
||||
(__pthread_cond_dowait): Accommodate changes to remove previously
|
||||
inexplicable use can_be_unblocked() as a static function.
|
||||
* thread.h: Rename "is_good_initialzer*" to "is_initializer*"
|
||||
throughout.
|
||||
(pthread_mutex): Reorganize. Make many things private.
|
||||
(pthread_mutex::no_owner): Define new method.
|
||||
(pthread_mutex::_new_mutex): Define new constant.
|
||||
(pthread_mutex::_unlocked_mutex): Ditto.
|
||||
(pthread_mutex::_destroyed_mutex): Ditto.
|
||||
|
||||
2010-02-22 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* lc_era.h: Redefine lc_era_t to keep
|
||||
|
@ -64,26 +64,27 @@ extern strace strace;
|
||||
|
||||
/* Bitmasks of tracing messages to print. */
|
||||
|
||||
#define _STRACE_ALL 0x00001 // so behaviour of strace=1 is unchanged
|
||||
#define _STRACE_FLUSH 0x00002 // flush output buffer after every message
|
||||
#define _STRACE_INHERIT 0x00004 // children inherit mask from parent
|
||||
#define _STRACE_UHOH 0x00008 // unusual or weird phenomenon
|
||||
#define _STRACE_SYSCALL 0x00010 // system calls
|
||||
#define _STRACE_STARTUP 0x00020 // argc/envp printout at startup
|
||||
#define _STRACE_DEBUG 0x00040 // info to help debugging
|
||||
#define _STRACE_PARANOID 0x00080 // paranoid info
|
||||
#define _STRACE_TERMIOS 0x00100 // info for debugging termios stuff
|
||||
#define _STRACE_SELECT 0x00200 // info on ugly select internals
|
||||
#define _STRACE_WM 0x00400 // trace windows messages (enable _strace_wm)
|
||||
#define _STRACE_SIGP 0x00800 // trace signal and process handling
|
||||
#define _STRACE_MINIMAL 0x01000 // very minimal strace output
|
||||
#define _STRACE_PTHREAD 0x02000 // pthread calls
|
||||
#define _STRACE_EXITDUMP 0x04000 // dump strace cache on exit
|
||||
#define _STRACE_SYSTEM 0x08000 // cache strace messages
|
||||
#define _STRACE_NOMUTEX 0x10000 // don't use mutex for synchronization
|
||||
#define _STRACE_MALLOC 0x20000 // trace malloc calls
|
||||
#define _STRACE_THREAD 0x40000 // cygthread calls
|
||||
#define _STRACE_NOTALL 0x80000 // don't include if _STRACE_ALL
|
||||
#define _STRACE_ALL 0x000001 // so behaviour of strace=1 is unchanged
|
||||
#define _STRACE_FLUSH 0x000002 // flush output buffer after every message
|
||||
#define _STRACE_INHERIT 0x000004 // children inherit mask from parent
|
||||
#define _STRACE_UHOH 0x000008 // unusual or weird phenomenon
|
||||
#define _STRACE_SYSCALL 0x000010 // system calls
|
||||
#define _STRACE_STARTUP 0x000020 // argc/envp printout at startup
|
||||
#define _STRACE_DEBUG 0x000040 // info to help debugging
|
||||
#define _STRACE_PARANOID 0x000080 // paranoid info
|
||||
#define _STRACE_TERMIOS 0x000100 // info for debugging termios stuff
|
||||
#define _STRACE_SELECT 0x000200 // info on ugly select internals
|
||||
#define _STRACE_WM 0x000400 // trace windows messages (enable _strace_wm)
|
||||
#define _STRACE_SIGP 0x000800 // trace signal and process handling
|
||||
#define _STRACE_MINIMAL 0x001000 // very minimal strace output
|
||||
#define _STRACE_PTHREAD 0x002000 // pthread calls
|
||||
#define _STRACE_EXITDUMP 0x004000 // dump strace cache on exit
|
||||
#define _STRACE_SYSTEM 0x008000 // cache strace messages
|
||||
#define _STRACE_NOMUTEX 0x010000 // don't use mutex for synchronization
|
||||
#define _STRACE_MALLOC 0x020000 // trace malloc calls
|
||||
#define _STRACE_THREAD 0x040000 // cygthread calls
|
||||
#define _STRACE_NOTALL 0x080000 // don't include if _STRACE_ALL
|
||||
#define _STRACE_SPECIAL 0x100000 // special case, only for debugging - do not check in
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -99,8 +100,8 @@ void strace_printf (unsigned, const char *func, const char *, ...);
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifdef NOSTRACE
|
||||
#define define_strace(c, f)
|
||||
#define define_strace1(c, f)
|
||||
#define strace_printf_wrap(what, fmt, args...)
|
||||
#define strace_printf_wrap1(what, fmt, args...)
|
||||
#else
|
||||
#define strace_printf_wrap(what, fmt, args...) \
|
||||
((void) ({\
|
||||
@ -114,6 +115,7 @@ void strace_printf (unsigned, const char *func, const char *, ...);
|
||||
strace.prntf((_STRACE_ ## what) | _STRACE_NOTALL, __PRETTY_FUNCTION__, fmt, ## args); \
|
||||
0; \
|
||||
}))
|
||||
#endif /*NOSTRACE*/
|
||||
|
||||
#define debug_printf(fmt, args...) strace_printf_wrap(DEBUG, fmt , ## args)
|
||||
#define malloc_printf(fmt, args...) strace_printf_wrap1(MALLOC, fmt , ## args)
|
||||
@ -126,7 +128,7 @@ void strace_printf (unsigned, const char *func, const char *, ...);
|
||||
#define system_printf(fmt, args...) strace_printf_wrap(SYSTEM, fmt , ## args)
|
||||
#define termios_printf(fmt, args...) strace_printf_wrap(TERMIOS, fmt , ## args)
|
||||
#define thread_printf(fmt, args...) strace_printf_wrap1(THREAD, fmt , ## args)
|
||||
#define special_printf(fmt, args...) strace_printf_wrap1(SPECIAL, fmt , ## args)
|
||||
#define wm_printf(fmt, args...) strace_printf_wrap(WM, fmt , ## args)
|
||||
#endif /*NOSTRACE*/
|
||||
#endif /* __cplusplus */
|
||||
#endif /* _SYS_STRACE_H */
|
||||
|
@ -16,7 +16,7 @@ details. */
|
||||
the constraints we either pretend to be conformant, or return an error
|
||||
code.
|
||||
|
||||
Some caveats: PROCESS_SHARED objects while they pretend to be process
|
||||
Some caveats: PROCESS_SHARED objects, while they pretend to be process
|
||||
shared, may not actually work. Some test cases are needed to determine
|
||||
win32's behaviour. My suspicion is that the win32 handle needs to be
|
||||
opened with different flags for proper operation.
|
||||
@ -48,6 +48,31 @@ static inline verifyable_object_state
|
||||
|
||||
extern int threadsafe;
|
||||
|
||||
const pthread_t pthread_mutex::_new_mutex = (pthread_t) 1;
|
||||
const pthread_t pthread_mutex::_unlocked_mutex = (pthread_t) 2;
|
||||
const pthread_t pthread_mutex::_destroyed_mutex = (pthread_t) 3;
|
||||
|
||||
inline bool
|
||||
pthread_mutex::no_owner()
|
||||
{
|
||||
int res;
|
||||
if (!owner)
|
||||
{
|
||||
debug_printf ("NULL owner value");
|
||||
res = 1;
|
||||
}
|
||||
else if (owner == _destroyed_mutex)
|
||||
{
|
||||
paranoid_printf ("attempt to use destroyed mutex");
|
||||
res = 1;
|
||||
}
|
||||
else if (owner == _new_mutex || owner == _unlocked_mutex)
|
||||
res = 1;
|
||||
else
|
||||
res = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef __getreent
|
||||
extern "C" struct _reent *
|
||||
__getreent ()
|
||||
@ -157,7 +182,7 @@ pthread_mutex::is_good_object (pthread_mutex_t const *mutex)
|
||||
}
|
||||
|
||||
inline bool
|
||||
pthread_mutex::is_good_initializer (pthread_mutex_t const *mutex)
|
||||
pthread_mutex::is_initializer (pthread_mutex_t const *mutex)
|
||||
{
|
||||
if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC,
|
||||
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
|
||||
@ -168,7 +193,7 @@ pthread_mutex::is_good_initializer (pthread_mutex_t const *mutex)
|
||||
}
|
||||
|
||||
inline bool
|
||||
pthread_mutex::is_good_initializer_or_object (pthread_mutex_t const *mutex)
|
||||
pthread_mutex::is_initializer_or_object (pthread_mutex_t const *mutex)
|
||||
{
|
||||
if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC,
|
||||
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
|
||||
@ -178,17 +203,17 @@ pthread_mutex::is_good_initializer_or_object (pthread_mutex_t const *mutex)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* FIXME: Accommodate PTHREAD_MUTEX_ERRORCHECK */
|
||||
inline bool
|
||||
pthread_mutex::can_be_unlocked (pthread_mutex_t const *mutex)
|
||||
pthread_mutex::can_be_unlocked ()
|
||||
{
|
||||
pthread_t self = pthread::self ();
|
||||
|
||||
if (!is_good_object (mutex))
|
||||
return false;
|
||||
/* Check if the mutex is owned by the current thread and can be unlocked.
|
||||
* Also check for the ANONYMOUS owner to cover NORMAL mutexes as well. */
|
||||
return (*mutex)->recursion_counter == 1
|
||||
&& pthread::equal ((*mutex)->owner, self);
|
||||
bool res = type == PTHREAD_MUTEX_NORMAL || no_owner ()
|
||||
|| (recursion_counter == 1 && pthread::equal (owner, self));
|
||||
pthread_printf ("recursion_counter %d res %d", recursion_counter, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -217,7 +242,7 @@ pthread_cond::is_good_object (pthread_cond_t const *cond)
|
||||
}
|
||||
|
||||
inline bool
|
||||
pthread_cond::is_good_initializer (pthread_cond_t const *cond)
|
||||
pthread_cond::is_initializer (pthread_cond_t const *cond)
|
||||
{
|
||||
if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) != VALID_STATIC_OBJECT)
|
||||
return false;
|
||||
@ -225,7 +250,7 @@ pthread_cond::is_good_initializer (pthread_cond_t const *cond)
|
||||
}
|
||||
|
||||
inline bool
|
||||
pthread_cond::is_good_initializer_or_object (pthread_cond_t const *cond)
|
||||
pthread_cond::is_initializer_or_object (pthread_cond_t const *cond)
|
||||
{
|
||||
if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) == INVALID_OBJECT)
|
||||
return false;
|
||||
@ -242,7 +267,7 @@ pthread_rwlock::is_good_object (pthread_rwlock_t const *rwlock)
|
||||
}
|
||||
|
||||
inline bool
|
||||
pthread_rwlock::is_good_initializer (pthread_rwlock_t const *rwlock)
|
||||
pthread_rwlock::is_initializer (pthread_rwlock_t const *rwlock)
|
||||
{
|
||||
if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER) != VALID_STATIC_OBJECT)
|
||||
return false;
|
||||
@ -250,7 +275,7 @@ pthread_rwlock::is_good_initializer (pthread_rwlock_t const *rwlock)
|
||||
}
|
||||
|
||||
inline bool
|
||||
pthread_rwlock::is_good_initializer_or_object (pthread_rwlock_t const *rwlock)
|
||||
pthread_rwlock::is_initializer_or_object (pthread_rwlock_t const *rwlock)
|
||||
{
|
||||
if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER) == INVALID_OBJECT)
|
||||
return false;
|
||||
@ -367,7 +392,7 @@ pthread::~pthread ()
|
||||
bool
|
||||
pthread::create_cancel_event ()
|
||||
{
|
||||
cancel_event = ::CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
|
||||
cancel_event = ::CreateEvent (&sec_none_nih, true, false, NULL);
|
||||
if (!cancel_event)
|
||||
{
|
||||
system_printf ("couldn't create cancel event, %E");
|
||||
@ -402,7 +427,7 @@ pthread::precreate (pthread_attr *newattr)
|
||||
return;
|
||||
}
|
||||
/* Change the mutex type to NORMAL to speed up mutex operations */
|
||||
mutex.type = PTHREAD_MUTEX_NORMAL;
|
||||
mutex.set_type (PTHREAD_MUTEX_NORMAL);
|
||||
if (!create_cancel_event ())
|
||||
magic = 0;
|
||||
}
|
||||
@ -957,7 +982,7 @@ pthread_cond::pthread_cond (pthread_condattr *attr) :
|
||||
* Change the mutex type to NORMAL.
|
||||
* This mutex MUST be of type normal
|
||||
*/
|
||||
mtx_in.type = PTHREAD_MUTEX_NORMAL;
|
||||
mtx_in.set_type (PTHREAD_MUTEX_NORMAL);
|
||||
|
||||
verifyable_mutex_obj = &mtx_out;
|
||||
if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
|
||||
@ -967,12 +992,12 @@ pthread_cond::pthread_cond (pthread_condattr *attr) :
|
||||
return;
|
||||
}
|
||||
/* Change the mutex type to NORMAL to speed up mutex operations */
|
||||
mtx_out.type = PTHREAD_MUTEX_NORMAL;
|
||||
mtx_out.set_type (PTHREAD_MUTEX_NORMAL);
|
||||
|
||||
sem_wait = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL);
|
||||
if (!sem_wait)
|
||||
{
|
||||
debug_printf ("CreateSemaphore failed. %E");
|
||||
pthread_printf ("CreateSemaphore failed. %E");
|
||||
magic = 0;
|
||||
return;
|
||||
}
|
||||
@ -1171,7 +1196,7 @@ pthread_rwlock::pthread_rwlock (pthread_rwlockattr *attr) :
|
||||
return;
|
||||
}
|
||||
/* Change the mutex type to NORMAL to speed up mutex operations */
|
||||
mtx.type = PTHREAD_MUTEX_NORMAL;
|
||||
mtx.set_type (PTHREAD_MUTEX_NORMAL);
|
||||
|
||||
verifyable_cond_obj = &cond_readers;
|
||||
if (!pthread_cond::is_good_object (&verifyable_cond_obj))
|
||||
@ -1523,7 +1548,7 @@ 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 (NULL),
|
||||
condwaits (0), owner (_new_mutex),
|
||||
#ifdef DEBUGGING
|
||||
tid (0),
|
||||
#endif
|
||||
@ -1548,9 +1573,14 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr) :
|
||||
pthread_mutex::~pthread_mutex ()
|
||||
{
|
||||
if (win32_obj_id)
|
||||
CloseHandle (win32_obj_id);
|
||||
{
|
||||
CloseHandle (win32_obj_id);
|
||||
win32_obj_id = NULL;
|
||||
}
|
||||
|
||||
mutexes.remove (this);
|
||||
owner = _destroyed_mutex;
|
||||
magic = 0;
|
||||
}
|
||||
|
||||
int
|
||||
@ -1559,9 +1589,10 @@ pthread_mutex::lock ()
|
||||
pthread_t self = ::pthread_self ();
|
||||
int result = 0;
|
||||
|
||||
if (InterlockedIncrement ((long *)&lock_counter) == 1)
|
||||
if (InterlockedIncrement ((long *) &lock_counter) == 1)
|
||||
set_owner (self);
|
||||
else if (type == PTHREAD_MUTEX_NORMAL || !pthread::equal (owner, self))
|
||||
else if (type == PTHREAD_MUTEX_NORMAL /* potentially causes deadlock */
|
||||
|| !pthread::equal (owner, self))
|
||||
{
|
||||
cancelable_wait (win32_obj_id, INFINITE, cw_no_cancel, cw_sig_resume);
|
||||
set_owner (self);
|
||||
@ -1575,29 +1606,38 @@ pthread_mutex::lock ()
|
||||
result = EDEADLK;
|
||||
}
|
||||
|
||||
pthread_printf ("mutex %p, self %p, owner %p, lock_counter %d, recursion_counter %d",
|
||||
this, self, owner, lock_counter, recursion_counter);
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
pthread_mutex::unlock ()
|
||||
{
|
||||
int res;
|
||||
pthread_t self = ::pthread_self ();
|
||||
if (!pthread::equal (owner, self))
|
||||
return EPERM;
|
||||
|
||||
/* Don't try to unlock anything if recursion_counter == 0 initially.
|
||||
That means that we've forked. */
|
||||
if (type == PTHREAD_MUTEX_NORMAL)
|
||||
/* no error checking */;
|
||||
else if (no_owner ())
|
||||
return type == PTHREAD_MUTEX_ERRORCHECK ? EINVAL : 0;
|
||||
else if (!pthread::equal (owner, self))
|
||||
res = EPERM;
|
||||
if (recursion_counter > 0 && --recursion_counter == 0)
|
||||
/* Don't try to unlock anything if recursion_counter == 0.
|
||||
This means the mutex was never locked or that we've forked. */
|
||||
{
|
||||
owner = NULL;
|
||||
owner = (pthread_t) _unlocked_mutex;
|
||||
#ifdef DEBUGGING
|
||||
tid = 0;
|
||||
#endif
|
||||
if (InterlockedDecrement ((long *) &lock_counter))
|
||||
::SetEvent (win32_obj_id); // Another thread is waiting
|
||||
res = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
pthread_printf ("mutex %p, owner %p, self %p, lock_counter %d, recursion_counter %d, res %d",
|
||||
this, owner, self, lock_counter, recursion_counter, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
int
|
||||
@ -1636,7 +1676,7 @@ pthread_mutex::destroy ()
|
||||
void
|
||||
pthread_mutex::_fixup_after_fork ()
|
||||
{
|
||||
debug_printf ("mutex %p in _fixup_after_fork", this);
|
||||
pthread_printf ("mutex %p", this);
|
||||
if (pshared != PTHREAD_PROCESS_PRIVATE)
|
||||
api_fatal ("pthread_mutex::_fixup_after_fork () doesn't understand PROCESS_SHARED mutex's");
|
||||
|
||||
@ -1649,7 +1689,7 @@ pthread_mutex::_fixup_after_fork ()
|
||||
#endif
|
||||
win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL);
|
||||
if (!win32_obj_id)
|
||||
api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 semaphore for mutex");
|
||||
api_fatal ("pthread_mutex::_fixup_after_fork () failed to recreate win32 event for mutex");
|
||||
}
|
||||
|
||||
pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC),
|
||||
@ -2222,7 +2262,7 @@ pthread_getspecific (pthread_key_t key)
|
||||
extern "C" int
|
||||
pthread_cond_destroy (pthread_cond_t *cond)
|
||||
{
|
||||
if (pthread_cond::is_good_initializer (cond))
|
||||
if (pthread_cond::is_initializer (cond))
|
||||
return 0;
|
||||
if (!pthread_cond::is_good_object (cond))
|
||||
return EINVAL;
|
||||
@ -2272,7 +2312,7 @@ pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr)
|
||||
extern "C" int
|
||||
pthread_cond_broadcast (pthread_cond_t *cond)
|
||||
{
|
||||
if (pthread_cond::is_good_initializer (cond))
|
||||
if (pthread_cond::is_initializer (cond))
|
||||
return 0;
|
||||
if (!pthread_cond::is_good_object (cond))
|
||||
return EINVAL;
|
||||
@ -2285,7 +2325,7 @@ pthread_cond_broadcast (pthread_cond_t *cond)
|
||||
extern "C" int
|
||||
pthread_cond_signal (pthread_cond_t *cond)
|
||||
{
|
||||
if (pthread_cond::is_good_initializer (cond))
|
||||
if (pthread_cond::is_initializer (cond))
|
||||
return 0;
|
||||
if (!pthread_cond::is_good_object (cond))
|
||||
return EINVAL;
|
||||
@ -2301,10 +2341,10 @@ __pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
{
|
||||
if (!pthread_mutex::is_good_object (mutex))
|
||||
return EINVAL;
|
||||
if (!pthread_mutex::can_be_unlocked (mutex))
|
||||
if (!(*mutex)->can_be_unlocked ())
|
||||
return EPERM;
|
||||
|
||||
if (pthread_cond::is_good_initializer (cond))
|
||||
if (pthread_cond::is_initializer (cond))
|
||||
pthread_cond::init (cond, NULL);
|
||||
if (!pthread_cond::is_good_object (cond))
|
||||
return EINVAL;
|
||||
@ -2405,7 +2445,7 @@ pthread_condattr_destroy (pthread_condattr_t *condattr)
|
||||
extern "C" int
|
||||
pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
if (pthread_rwlock::is_good_initializer (rwlock))
|
||||
if (pthread_rwlock::is_initializer (rwlock))
|
||||
return 0;
|
||||
if (!pthread_rwlock::is_good_object (rwlock))
|
||||
return EINVAL;
|
||||
@ -2457,7 +2497,7 @@ pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
pthread_testcancel ();
|
||||
|
||||
if (pthread_rwlock::is_good_initializer (rwlock))
|
||||
if (pthread_rwlock::is_initializer (rwlock))
|
||||
pthread_rwlock::init (rwlock, NULL);
|
||||
if (!pthread_rwlock::is_good_object (rwlock))
|
||||
return EINVAL;
|
||||
@ -2468,7 +2508,7 @@ pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
|
||||
extern "C" int
|
||||
pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
if (pthread_rwlock::is_good_initializer (rwlock))
|
||||
if (pthread_rwlock::is_initializer (rwlock))
|
||||
pthread_rwlock::init (rwlock, NULL);
|
||||
if (!pthread_rwlock::is_good_object (rwlock))
|
||||
return EINVAL;
|
||||
@ -2481,7 +2521,7 @@ pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
pthread_testcancel ();
|
||||
|
||||
if (pthread_rwlock::is_good_initializer (rwlock))
|
||||
if (pthread_rwlock::is_initializer (rwlock))
|
||||
pthread_rwlock::init (rwlock, NULL);
|
||||
if (!pthread_rwlock::is_good_object (rwlock))
|
||||
return EINVAL;
|
||||
@ -2492,7 +2532,7 @@ pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
||||
extern "C" int
|
||||
pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
if (pthread_rwlock::is_good_initializer (rwlock))
|
||||
if (pthread_rwlock::is_initializer (rwlock))
|
||||
pthread_rwlock::init (rwlock, NULL);
|
||||
if (!pthread_rwlock::is_good_object (rwlock))
|
||||
return EINVAL;
|
||||
@ -2503,7 +2543,7 @@ pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
|
||||
extern "C" int
|
||||
pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
|
||||
{
|
||||
if (pthread_rwlock::is_good_initializer (rwlock))
|
||||
if (pthread_rwlock::is_initializer (rwlock))
|
||||
return 0;
|
||||
if (!pthread_rwlock::is_good_object (rwlock))
|
||||
return EINVAL;
|
||||
@ -2623,7 +2663,7 @@ pthread_mutex::init (pthread_mutex_t *mutex,
|
||||
return EINVAL;
|
||||
|
||||
mutex_initialization_lock.lock ();
|
||||
if (initializer == NULL || pthread_mutex::is_good_initializer (mutex))
|
||||
if (initializer == NULL || pthread_mutex::is_initializer (mutex))
|
||||
{
|
||||
pthread_mutex_t new_mutex = new pthread_mutex (attr ? (*attr) : NULL);
|
||||
if (!is_good_object (&new_mutex))
|
||||
@ -2654,6 +2694,7 @@ pthread_mutex::init (pthread_mutex_t *mutex,
|
||||
*mutex = new_mutex;
|
||||
}
|
||||
mutex_initialization_lock.unlock ();
|
||||
pthread_printf ("*mutex %p, attr %p, initializer %p", *mutex, attr, initializer);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2675,7 +2716,7 @@ pthread_mutex_getprioceiling (const pthread_mutex_t *mutex,
|
||||
extern "C" int
|
||||
pthread_mutex_lock (pthread_mutex_t *mutex)
|
||||
{
|
||||
if (pthread_mutex::is_good_initializer (mutex))
|
||||
if (pthread_mutex::is_initializer (mutex))
|
||||
pthread_mutex::init (mutex, NULL, *mutex);
|
||||
if (!pthread_mutex::is_good_object (mutex))
|
||||
return EINVAL;
|
||||
@ -2685,7 +2726,7 @@ pthread_mutex_lock (pthread_mutex_t *mutex)
|
||||
extern "C" int
|
||||
pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
{
|
||||
if (pthread_mutex::is_good_initializer (mutex))
|
||||
if (pthread_mutex::is_initializer (mutex))
|
||||
pthread_mutex::init (mutex, NULL, *mutex);
|
||||
if (!pthread_mutex::is_good_object (mutex))
|
||||
return EINVAL;
|
||||
@ -2695,7 +2736,7 @@ pthread_mutex_trylock (pthread_mutex_t *mutex)
|
||||
extern "C" int
|
||||
pthread_mutex_unlock (pthread_mutex_t *mutex)
|
||||
{
|
||||
if (pthread_mutex::is_good_initializer (mutex))
|
||||
if (pthread_mutex::is_initializer (mutex))
|
||||
return EPERM;
|
||||
if (!pthread_mutex::is_good_object (mutex))
|
||||
return EINVAL;
|
||||
@ -2707,7 +2748,7 @@ pthread_mutex_destroy (pthread_mutex_t *mutex)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if (pthread_mutex::is_good_initializer (mutex))
|
||||
if (pthread_mutex::is_initializer (mutex))
|
||||
return 0;
|
||||
if (!pthread_mutex::is_good_object (mutex))
|
||||
return EINVAL;
|
||||
@ -2980,7 +3021,7 @@ semaphore::_timedwait (const struct timespec *abstime)
|
||||
set_errno (ETIMEDOUT);
|
||||
return -1;
|
||||
default:
|
||||
debug_printf ("cancelable_wait failed. %E");
|
||||
pthread_printf ("cancelable_wait failed. %E");
|
||||
__seterrno ();
|
||||
return -1;
|
||||
}
|
||||
@ -2999,7 +3040,7 @@ semaphore::_wait ()
|
||||
set_errno (EINTR);
|
||||
return -1;
|
||||
default:
|
||||
debug_printf ("cancelable_wait failed. %E");
|
||||
pthread_printf ("cancelable_wait failed. %E");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@ -3010,7 +3051,7 @@ semaphore::_fixup_after_fork ()
|
||||
{
|
||||
if (shared == PTHREAD_PROCESS_PRIVATE)
|
||||
{
|
||||
debug_printf ("sem %x in _fixup_after_fork", this);
|
||||
pthread_printf ("sem %x", this);
|
||||
/* FIXME: duplicate code here and in the constructor. */
|
||||
this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, currentvalue,
|
||||
LONG_MAX, NULL);
|
||||
|
@ -267,15 +267,42 @@ public:
|
||||
class pthread_mutex: public verifyable_object
|
||||
{
|
||||
public:
|
||||
static bool is_good_object (pthread_mutex_t const *);
|
||||
static bool is_good_initializer (pthread_mutex_t const *);
|
||||
static bool is_good_initializer_or_object (pthread_mutex_t const *);
|
||||
static bool is_good_initializer_or_bad_object (pthread_mutex_t const *);
|
||||
static bool can_be_unlocked (pthread_mutex_t const *);
|
||||
static void init_mutex ();
|
||||
static int init (pthread_mutex_t *, const pthread_mutexattr_t *attr,
|
||||
const pthread_mutex_t);
|
||||
static bool is_good_object (pthread_mutex_t const *);
|
||||
static bool is_initializer (pthread_mutex_t const *);
|
||||
static bool is_initializer_or_object (pthread_mutex_t const *);
|
||||
static bool is_initializer_or_bad_object (pthread_mutex_t const *);
|
||||
|
||||
int lock ();
|
||||
int trylock ();
|
||||
int unlock ();
|
||||
int destroy ();
|
||||
void set_type (int in_type) {type = in_type;}
|
||||
|
||||
int lock_recursive ()
|
||||
{
|
||||
if (recursion_counter == UINT_MAX)
|
||||
return EAGAIN;
|
||||
recursion_counter++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool can_be_unlocked ();
|
||||
|
||||
pthread_mutex (pthread_mutexattr * = NULL);
|
||||
pthread_mutex (pthread_mutex_t *, pthread_mutexattr *);
|
||||
~pthread_mutex ();
|
||||
|
||||
class pthread_mutex *next;
|
||||
static void fixup_after_fork ()
|
||||
{
|
||||
mutexes.fixup_after_fork ();
|
||||
mutexes.for_each (&pthread_mutex::_fixup_after_fork);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned long lock_counter;
|
||||
HANDLE win32_obj_id;
|
||||
unsigned int recursion_counter;
|
||||
@ -287,10 +314,6 @@ public:
|
||||
int type;
|
||||
int pshared;
|
||||
|
||||
int lock ();
|
||||
int trylock ();
|
||||
int unlock ();
|
||||
int destroy ();
|
||||
void set_owner (pthread_t self)
|
||||
{
|
||||
recursion_counter = 1;
|
||||
@ -299,31 +322,16 @@ public:
|
||||
tid = GetCurrentThreadId ();
|
||||
#endif
|
||||
}
|
||||
static const pthread_t _new_mutex;
|
||||
static const pthread_t _unlocked_mutex;
|
||||
static const pthread_t _destroyed_mutex;
|
||||
|
||||
int lock_recursive ()
|
||||
{
|
||||
if (UINT_MAX == recursion_counter)
|
||||
return EAGAIN;
|
||||
++recursion_counter;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pthread_mutex (pthread_mutexattr * = NULL);
|
||||
pthread_mutex (pthread_mutex_t *, pthread_mutexattr *);
|
||||
~pthread_mutex ();
|
||||
|
||||
class pthread_mutex * next;
|
||||
static void fixup_after_fork ()
|
||||
{
|
||||
mutexes.fixup_after_fork ();
|
||||
mutexes.for_each (&pthread_mutex::_fixup_after_fork);
|
||||
}
|
||||
|
||||
private:
|
||||
bool no_owner ();
|
||||
void _fixup_after_fork ();
|
||||
|
||||
static List<pthread_mutex> mutexes;
|
||||
static fast_mutex mutex_initialization_lock;
|
||||
friend class pthread_cond;
|
||||
};
|
||||
|
||||
#define WAIT_CANCELED (WAIT_OBJECT_0 + 1)
|
||||
@ -467,9 +475,9 @@ class pthread_cond: public verifyable_object
|
||||
{
|
||||
public:
|
||||
static bool is_good_object (pthread_cond_t const *);
|
||||
static bool is_good_initializer (pthread_cond_t const *);
|
||||
static bool is_good_initializer_or_object (pthread_cond_t const *);
|
||||
static bool is_good_initializer_or_bad_object (pthread_cond_t const *);
|
||||
static bool is_initializer (pthread_cond_t const *);
|
||||
static bool is_initializer_or_object (pthread_cond_t const *);
|
||||
static bool is_initializer_or_bad_object (pthread_cond_t const *);
|
||||
static void init_mutex ();
|
||||
static int init (pthread_cond_t *, const pthread_condattr_t *);
|
||||
|
||||
@ -518,9 +526,9 @@ class pthread_rwlock: public verifyable_object
|
||||
{
|
||||
public:
|
||||
static bool is_good_object (pthread_rwlock_t const *);
|
||||
static bool is_good_initializer (pthread_rwlock_t const *);
|
||||
static bool is_good_initializer_or_object (pthread_rwlock_t const *);
|
||||
static bool is_good_initializer_or_bad_object (pthread_rwlock_t const *);
|
||||
static bool is_initializer (pthread_rwlock_t const *);
|
||||
static bool is_initializer_or_object (pthread_rwlock_t const *);
|
||||
static bool is_initializer_or_bad_object (pthread_rwlock_t const *);
|
||||
static void init_mutex ();
|
||||
static int init (pthread_rwlock_t *, const pthread_rwlockattr_t *);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user