* 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>
|
2010-02-22 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* lc_era.h: Redefine lc_era_t to keep
|
* lc_era.h: Redefine lc_era_t to keep
|
||||||
|
@ -64,26 +64,27 @@ extern strace strace;
|
|||||||
|
|
||||||
/* Bitmasks of tracing messages to print. */
|
/* Bitmasks of tracing messages to print. */
|
||||||
|
|
||||||
#define _STRACE_ALL 0x00001 // so behaviour of strace=1 is unchanged
|
#define _STRACE_ALL 0x000001 // so behaviour of strace=1 is unchanged
|
||||||
#define _STRACE_FLUSH 0x00002 // flush output buffer after every message
|
#define _STRACE_FLUSH 0x000002 // flush output buffer after every message
|
||||||
#define _STRACE_INHERIT 0x00004 // children inherit mask from parent
|
#define _STRACE_INHERIT 0x000004 // children inherit mask from parent
|
||||||
#define _STRACE_UHOH 0x00008 // unusual or weird phenomenon
|
#define _STRACE_UHOH 0x000008 // unusual or weird phenomenon
|
||||||
#define _STRACE_SYSCALL 0x00010 // system calls
|
#define _STRACE_SYSCALL 0x000010 // system calls
|
||||||
#define _STRACE_STARTUP 0x00020 // argc/envp printout at startup
|
#define _STRACE_STARTUP 0x000020 // argc/envp printout at startup
|
||||||
#define _STRACE_DEBUG 0x00040 // info to help debugging
|
#define _STRACE_DEBUG 0x000040 // info to help debugging
|
||||||
#define _STRACE_PARANOID 0x00080 // paranoid info
|
#define _STRACE_PARANOID 0x000080 // paranoid info
|
||||||
#define _STRACE_TERMIOS 0x00100 // info for debugging termios stuff
|
#define _STRACE_TERMIOS 0x000100 // info for debugging termios stuff
|
||||||
#define _STRACE_SELECT 0x00200 // info on ugly select internals
|
#define _STRACE_SELECT 0x000200 // info on ugly select internals
|
||||||
#define _STRACE_WM 0x00400 // trace windows messages (enable _strace_wm)
|
#define _STRACE_WM 0x000400 // trace windows messages (enable _strace_wm)
|
||||||
#define _STRACE_SIGP 0x00800 // trace signal and process handling
|
#define _STRACE_SIGP 0x000800 // trace signal and process handling
|
||||||
#define _STRACE_MINIMAL 0x01000 // very minimal strace output
|
#define _STRACE_MINIMAL 0x001000 // very minimal strace output
|
||||||
#define _STRACE_PTHREAD 0x02000 // pthread calls
|
#define _STRACE_PTHREAD 0x002000 // pthread calls
|
||||||
#define _STRACE_EXITDUMP 0x04000 // dump strace cache on exit
|
#define _STRACE_EXITDUMP 0x004000 // dump strace cache on exit
|
||||||
#define _STRACE_SYSTEM 0x08000 // cache strace messages
|
#define _STRACE_SYSTEM 0x008000 // cache strace messages
|
||||||
#define _STRACE_NOMUTEX 0x10000 // don't use mutex for synchronization
|
#define _STRACE_NOMUTEX 0x010000 // don't use mutex for synchronization
|
||||||
#define _STRACE_MALLOC 0x20000 // trace malloc calls
|
#define _STRACE_MALLOC 0x020000 // trace malloc calls
|
||||||
#define _STRACE_THREAD 0x40000 // cygthread calls
|
#define _STRACE_THREAD 0x040000 // cygthread calls
|
||||||
#define _STRACE_NOTALL 0x80000 // don't include if _STRACE_ALL
|
#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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -99,8 +100,8 @@ void strace_printf (unsigned, const char *func, const char *, ...);
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
#ifdef NOSTRACE
|
#ifdef NOSTRACE
|
||||||
#define define_strace(c, f)
|
#define strace_printf_wrap(what, fmt, args...)
|
||||||
#define define_strace1(c, f)
|
#define strace_printf_wrap1(what, fmt, args...)
|
||||||
#else
|
#else
|
||||||
#define strace_printf_wrap(what, fmt, args...) \
|
#define strace_printf_wrap(what, fmt, args...) \
|
||||||
((void) ({\
|
((void) ({\
|
||||||
@ -114,6 +115,7 @@ void strace_printf (unsigned, const char *func, const char *, ...);
|
|||||||
strace.prntf((_STRACE_ ## what) | _STRACE_NOTALL, __PRETTY_FUNCTION__, fmt, ## args); \
|
strace.prntf((_STRACE_ ## what) | _STRACE_NOTALL, __PRETTY_FUNCTION__, fmt, ## args); \
|
||||||
0; \
|
0; \
|
||||||
}))
|
}))
|
||||||
|
#endif /*NOSTRACE*/
|
||||||
|
|
||||||
#define debug_printf(fmt, args...) strace_printf_wrap(DEBUG, fmt , ## args)
|
#define debug_printf(fmt, args...) strace_printf_wrap(DEBUG, fmt , ## args)
|
||||||
#define malloc_printf(fmt, args...) strace_printf_wrap1(MALLOC, 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 system_printf(fmt, args...) strace_printf_wrap(SYSTEM, fmt , ## args)
|
||||||
#define termios_printf(fmt, args...) strace_printf_wrap(TERMIOS, 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 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)
|
#define wm_printf(fmt, args...) strace_printf_wrap(WM, fmt , ## args)
|
||||||
#endif /*NOSTRACE*/
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif /* _SYS_STRACE_H */
|
#endif /* _SYS_STRACE_H */
|
||||||
|
@ -16,7 +16,7 @@ details. */
|
|||||||
the constraints we either pretend to be conformant, or return an error
|
the constraints we either pretend to be conformant, or return an error
|
||||||
code.
|
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
|
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
|
win32's behaviour. My suspicion is that the win32 handle needs to be
|
||||||
opened with different flags for proper operation.
|
opened with different flags for proper operation.
|
||||||
@ -48,6 +48,31 @@ static inline verifyable_object_state
|
|||||||
|
|
||||||
extern int threadsafe;
|
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
|
#undef __getreent
|
||||||
extern "C" struct _reent *
|
extern "C" struct _reent *
|
||||||
__getreent ()
|
__getreent ()
|
||||||
@ -157,7 +182,7 @@ pthread_mutex::is_good_object (pthread_mutex_t const *mutex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
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,
|
if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC,
|
||||||
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
|
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
|
||||||
@ -168,7 +193,7 @@ pthread_mutex::is_good_initializer (pthread_mutex_t const *mutex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
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,
|
if (verifyable_object_isvalid (mutex, PTHREAD_MUTEX_MAGIC,
|
||||||
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
|
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
|
||||||
@ -178,17 +203,17 @@ pthread_mutex::is_good_initializer_or_object (pthread_mutex_t const *mutex)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: Accommodate PTHREAD_MUTEX_ERRORCHECK */
|
||||||
inline bool
|
inline bool
|
||||||
pthread_mutex::can_be_unlocked (pthread_mutex_t const *mutex)
|
pthread_mutex::can_be_unlocked ()
|
||||||
{
|
{
|
||||||
pthread_t self = pthread::self ();
|
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.
|
/* 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. */
|
* Also check for the ANONYMOUS owner to cover NORMAL mutexes as well. */
|
||||||
return (*mutex)->recursion_counter == 1
|
bool res = type == PTHREAD_MUTEX_NORMAL || no_owner ()
|
||||||
&& pthread::equal ((*mutex)->owner, self);
|
|| (recursion_counter == 1 && pthread::equal (owner, self));
|
||||||
|
pthread_printf ("recursion_counter %d res %d", recursion_counter, res);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
@ -217,7 +242,7 @@ pthread_cond::is_good_object (pthread_cond_t const *cond)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
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)
|
if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) != VALID_STATIC_OBJECT)
|
||||||
return false;
|
return false;
|
||||||
@ -225,7 +250,7 @@ pthread_cond::is_good_initializer (pthread_cond_t const *cond)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
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)
|
if (verifyable_object_isvalid (cond, PTHREAD_COND_MAGIC, PTHREAD_COND_INITIALIZER) == INVALID_OBJECT)
|
||||||
return false;
|
return false;
|
||||||
@ -242,7 +267,7 @@ pthread_rwlock::is_good_object (pthread_rwlock_t const *rwlock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
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)
|
if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER) != VALID_STATIC_OBJECT)
|
||||||
return false;
|
return false;
|
||||||
@ -250,7 +275,7 @@ pthread_rwlock::is_good_initializer (pthread_rwlock_t const *rwlock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
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)
|
if (verifyable_object_isvalid (rwlock, PTHREAD_RWLOCK_MAGIC, PTHREAD_RWLOCK_INITIALIZER) == INVALID_OBJECT)
|
||||||
return false;
|
return false;
|
||||||
@ -367,7 +392,7 @@ pthread::~pthread ()
|
|||||||
bool
|
bool
|
||||||
pthread::create_cancel_event ()
|
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)
|
if (!cancel_event)
|
||||||
{
|
{
|
||||||
system_printf ("couldn't create cancel event, %E");
|
system_printf ("couldn't create cancel event, %E");
|
||||||
@ -402,7 +427,7 @@ pthread::precreate (pthread_attr *newattr)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Change the mutex type to NORMAL to speed up mutex operations */
|
/* 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 ())
|
if (!create_cancel_event ())
|
||||||
magic = 0;
|
magic = 0;
|
||||||
}
|
}
|
||||||
@ -957,7 +982,7 @@ pthread_cond::pthread_cond (pthread_condattr *attr) :
|
|||||||
* Change the mutex type to NORMAL.
|
* Change the mutex type to NORMAL.
|
||||||
* This mutex MUST be of type 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;
|
verifyable_mutex_obj = &mtx_out;
|
||||||
if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
|
if (!pthread_mutex::is_good_object (&verifyable_mutex_obj))
|
||||||
@ -967,12 +992,12 @@ pthread_cond::pthread_cond (pthread_condattr *attr) :
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Change the mutex type to NORMAL to speed up mutex operations */
|
/* 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);
|
sem_wait = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL);
|
||||||
if (!sem_wait)
|
if (!sem_wait)
|
||||||
{
|
{
|
||||||
debug_printf ("CreateSemaphore failed. %E");
|
pthread_printf ("CreateSemaphore failed. %E");
|
||||||
magic = 0;
|
magic = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1171,7 +1196,7 @@ pthread_rwlock::pthread_rwlock (pthread_rwlockattr *attr) :
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Change the mutex type to NORMAL to speed up mutex operations */
|
/* 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;
|
verifyable_cond_obj = &cond_readers;
|
||||||
if (!pthread_cond::is_good_object (&verifyable_cond_obj))
|
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 */
|
verifyable_object (0), /* set magic to zero initially */
|
||||||
lock_counter (0),
|
lock_counter (0),
|
||||||
win32_obj_id (NULL), recursion_counter (0),
|
win32_obj_id (NULL), recursion_counter (0),
|
||||||
condwaits (0), owner (NULL),
|
condwaits (0), owner (_new_mutex),
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
tid (0),
|
tid (0),
|
||||||
#endif
|
#endif
|
||||||
@ -1548,9 +1573,14 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr) :
|
|||||||
pthread_mutex::~pthread_mutex ()
|
pthread_mutex::~pthread_mutex ()
|
||||||
{
|
{
|
||||||
if (win32_obj_id)
|
if (win32_obj_id)
|
||||||
CloseHandle (win32_obj_id);
|
{
|
||||||
|
CloseHandle (win32_obj_id);
|
||||||
|
win32_obj_id = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
mutexes.remove (this);
|
mutexes.remove (this);
|
||||||
|
owner = _destroyed_mutex;
|
||||||
|
magic = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1559,9 +1589,10 @@ pthread_mutex::lock ()
|
|||||||
pthread_t self = ::pthread_self ();
|
pthread_t self = ::pthread_self ();
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
if (InterlockedIncrement ((long *)&lock_counter) == 1)
|
if (InterlockedIncrement ((long *) &lock_counter) == 1)
|
||||||
set_owner (self);
|
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);
|
cancelable_wait (win32_obj_id, INFINITE, cw_no_cancel, cw_sig_resume);
|
||||||
set_owner (self);
|
set_owner (self);
|
||||||
@ -1575,29 +1606,38 @@ pthread_mutex::lock ()
|
|||||||
result = EDEADLK;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pthread_mutex::unlock ()
|
pthread_mutex::unlock ()
|
||||||
{
|
{
|
||||||
|
int res;
|
||||||
pthread_t self = ::pthread_self ();
|
pthread_t self = ::pthread_self ();
|
||||||
if (!pthread::equal (owner, self))
|
if (type == PTHREAD_MUTEX_NORMAL)
|
||||||
return EPERM;
|
/* no error checking */;
|
||||||
|
else if (no_owner ())
|
||||||
/* Don't try to unlock anything if recursion_counter == 0 initially.
|
return type == PTHREAD_MUTEX_ERRORCHECK ? EINVAL : 0;
|
||||||
That means that we've forked. */
|
else if (!pthread::equal (owner, self))
|
||||||
|
res = EPERM;
|
||||||
if (recursion_counter > 0 && --recursion_counter == 0)
|
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
|
#ifdef DEBUGGING
|
||||||
tid = 0;
|
tid = 0;
|
||||||
#endif
|
#endif
|
||||||
if (InterlockedDecrement ((long *) &lock_counter))
|
if (InterlockedDecrement ((long *) &lock_counter))
|
||||||
::SetEvent (win32_obj_id); // Another thread is waiting
|
::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
|
int
|
||||||
@ -1636,7 +1676,7 @@ pthread_mutex::destroy ()
|
|||||||
void
|
void
|
||||||
pthread_mutex::_fixup_after_fork ()
|
pthread_mutex::_fixup_after_fork ()
|
||||||
{
|
{
|
||||||
debug_printf ("mutex %p in _fixup_after_fork", this);
|
pthread_printf ("mutex %p", this);
|
||||||
if (pshared != PTHREAD_PROCESS_PRIVATE)
|
if (pshared != PTHREAD_PROCESS_PRIVATE)
|
||||||
api_fatal ("pthread_mutex::_fixup_after_fork () doesn't understand PROCESS_SHARED mutex's");
|
api_fatal ("pthread_mutex::_fixup_after_fork () doesn't understand PROCESS_SHARED mutex's");
|
||||||
|
|
||||||
@ -1649,7 +1689,7 @@ pthread_mutex::_fixup_after_fork ()
|
|||||||
#endif
|
#endif
|
||||||
win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL);
|
win32_obj_id = ::CreateEvent (&sec_none_nih, false, false, NULL);
|
||||||
if (!win32_obj_id)
|
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),
|
pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC),
|
||||||
@ -2222,7 +2262,7 @@ pthread_getspecific (pthread_key_t key)
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
pthread_cond_destroy (pthread_cond_t *cond)
|
pthread_cond_destroy (pthread_cond_t *cond)
|
||||||
{
|
{
|
||||||
if (pthread_cond::is_good_initializer (cond))
|
if (pthread_cond::is_initializer (cond))
|
||||||
return 0;
|
return 0;
|
||||||
if (!pthread_cond::is_good_object (cond))
|
if (!pthread_cond::is_good_object (cond))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2272,7 +2312,7 @@ pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr)
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
pthread_cond_broadcast (pthread_cond_t *cond)
|
pthread_cond_broadcast (pthread_cond_t *cond)
|
||||||
{
|
{
|
||||||
if (pthread_cond::is_good_initializer (cond))
|
if (pthread_cond::is_initializer (cond))
|
||||||
return 0;
|
return 0;
|
||||||
if (!pthread_cond::is_good_object (cond))
|
if (!pthread_cond::is_good_object (cond))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2285,7 +2325,7 @@ pthread_cond_broadcast (pthread_cond_t *cond)
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
pthread_cond_signal (pthread_cond_t *cond)
|
pthread_cond_signal (pthread_cond_t *cond)
|
||||||
{
|
{
|
||||||
if (pthread_cond::is_good_initializer (cond))
|
if (pthread_cond::is_initializer (cond))
|
||||||
return 0;
|
return 0;
|
||||||
if (!pthread_cond::is_good_object (cond))
|
if (!pthread_cond::is_good_object (cond))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2301,10 +2341,10 @@ __pthread_cond_dowait (pthread_cond_t *cond, pthread_mutex_t *mutex,
|
|||||||
{
|
{
|
||||||
if (!pthread_mutex::is_good_object (mutex))
|
if (!pthread_mutex::is_good_object (mutex))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
if (!pthread_mutex::can_be_unlocked (mutex))
|
if (!(*mutex)->can_be_unlocked ())
|
||||||
return EPERM;
|
return EPERM;
|
||||||
|
|
||||||
if (pthread_cond::is_good_initializer (cond))
|
if (pthread_cond::is_initializer (cond))
|
||||||
pthread_cond::init (cond, NULL);
|
pthread_cond::init (cond, NULL);
|
||||||
if (!pthread_cond::is_good_object (cond))
|
if (!pthread_cond::is_good_object (cond))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2405,7 +2445,7 @@ pthread_condattr_destroy (pthread_condattr_t *condattr)
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
|
pthread_rwlock_destroy (pthread_rwlock_t *rwlock)
|
||||||
{
|
{
|
||||||
if (pthread_rwlock::is_good_initializer (rwlock))
|
if (pthread_rwlock::is_initializer (rwlock))
|
||||||
return 0;
|
return 0;
|
||||||
if (!pthread_rwlock::is_good_object (rwlock))
|
if (!pthread_rwlock::is_good_object (rwlock))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2457,7 +2497,7 @@ pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
|
|||||||
{
|
{
|
||||||
pthread_testcancel ();
|
pthread_testcancel ();
|
||||||
|
|
||||||
if (pthread_rwlock::is_good_initializer (rwlock))
|
if (pthread_rwlock::is_initializer (rwlock))
|
||||||
pthread_rwlock::init (rwlock, NULL);
|
pthread_rwlock::init (rwlock, NULL);
|
||||||
if (!pthread_rwlock::is_good_object (rwlock))
|
if (!pthread_rwlock::is_good_object (rwlock))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2468,7 +2508,7 @@ pthread_rwlock_rdlock (pthread_rwlock_t *rwlock)
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock)
|
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);
|
pthread_rwlock::init (rwlock, NULL);
|
||||||
if (!pthread_rwlock::is_good_object (rwlock))
|
if (!pthread_rwlock::is_good_object (rwlock))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2481,7 +2521,7 @@ pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
|||||||
{
|
{
|
||||||
pthread_testcancel ();
|
pthread_testcancel ();
|
||||||
|
|
||||||
if (pthread_rwlock::is_good_initializer (rwlock))
|
if (pthread_rwlock::is_initializer (rwlock))
|
||||||
pthread_rwlock::init (rwlock, NULL);
|
pthread_rwlock::init (rwlock, NULL);
|
||||||
if (!pthread_rwlock::is_good_object (rwlock))
|
if (!pthread_rwlock::is_good_object (rwlock))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2492,7 +2532,7 @@ pthread_rwlock_wrlock (pthread_rwlock_t *rwlock)
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
|
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);
|
pthread_rwlock::init (rwlock, NULL);
|
||||||
if (!pthread_rwlock::is_good_object (rwlock))
|
if (!pthread_rwlock::is_good_object (rwlock))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2503,7 +2543,7 @@ pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock)
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
|
pthread_rwlock_unlock (pthread_rwlock_t *rwlock)
|
||||||
{
|
{
|
||||||
if (pthread_rwlock::is_good_initializer (rwlock))
|
if (pthread_rwlock::is_initializer (rwlock))
|
||||||
return 0;
|
return 0;
|
||||||
if (!pthread_rwlock::is_good_object (rwlock))
|
if (!pthread_rwlock::is_good_object (rwlock))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2623,7 +2663,7 @@ pthread_mutex::init (pthread_mutex_t *mutex,
|
|||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
mutex_initialization_lock.lock ();
|
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);
|
pthread_mutex_t new_mutex = new pthread_mutex (attr ? (*attr) : NULL);
|
||||||
if (!is_good_object (&new_mutex))
|
if (!is_good_object (&new_mutex))
|
||||||
@ -2654,6 +2694,7 @@ pthread_mutex::init (pthread_mutex_t *mutex,
|
|||||||
*mutex = new_mutex;
|
*mutex = new_mutex;
|
||||||
}
|
}
|
||||||
mutex_initialization_lock.unlock ();
|
mutex_initialization_lock.unlock ();
|
||||||
|
pthread_printf ("*mutex %p, attr %p, initializer %p", *mutex, attr, initializer);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2675,7 +2716,7 @@ pthread_mutex_getprioceiling (const pthread_mutex_t *mutex,
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
pthread_mutex_lock (pthread_mutex_t *mutex)
|
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);
|
pthread_mutex::init (mutex, NULL, *mutex);
|
||||||
if (!pthread_mutex::is_good_object (mutex))
|
if (!pthread_mutex::is_good_object (mutex))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2685,7 +2726,7 @@ pthread_mutex_lock (pthread_mutex_t *mutex)
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
pthread_mutex_trylock (pthread_mutex_t *mutex)
|
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);
|
pthread_mutex::init (mutex, NULL, *mutex);
|
||||||
if (!pthread_mutex::is_good_object (mutex))
|
if (!pthread_mutex::is_good_object (mutex))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2695,7 +2736,7 @@ pthread_mutex_trylock (pthread_mutex_t *mutex)
|
|||||||
extern "C" int
|
extern "C" int
|
||||||
pthread_mutex_unlock (pthread_mutex_t *mutex)
|
pthread_mutex_unlock (pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
if (pthread_mutex::is_good_initializer (mutex))
|
if (pthread_mutex::is_initializer (mutex))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
if (!pthread_mutex::is_good_object (mutex))
|
if (!pthread_mutex::is_good_object (mutex))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2707,7 +2748,7 @@ pthread_mutex_destroy (pthread_mutex_t *mutex)
|
|||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if (pthread_mutex::is_good_initializer (mutex))
|
if (pthread_mutex::is_initializer (mutex))
|
||||||
return 0;
|
return 0;
|
||||||
if (!pthread_mutex::is_good_object (mutex))
|
if (!pthread_mutex::is_good_object (mutex))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
@ -2980,7 +3021,7 @@ semaphore::_timedwait (const struct timespec *abstime)
|
|||||||
set_errno (ETIMEDOUT);
|
set_errno (ETIMEDOUT);
|
||||||
return -1;
|
return -1;
|
||||||
default:
|
default:
|
||||||
debug_printf ("cancelable_wait failed. %E");
|
pthread_printf ("cancelable_wait failed. %E");
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -2999,7 +3040,7 @@ semaphore::_wait ()
|
|||||||
set_errno (EINTR);
|
set_errno (EINTR);
|
||||||
return -1;
|
return -1;
|
||||||
default:
|
default:
|
||||||
debug_printf ("cancelable_wait failed. %E");
|
pthread_printf ("cancelable_wait failed. %E");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -3010,7 +3051,7 @@ semaphore::_fixup_after_fork ()
|
|||||||
{
|
{
|
||||||
if (shared == PTHREAD_PROCESS_PRIVATE)
|
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. */
|
/* FIXME: duplicate code here and in the constructor. */
|
||||||
this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, currentvalue,
|
this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, currentvalue,
|
||||||
LONG_MAX, NULL);
|
LONG_MAX, NULL);
|
||||||
|
@ -267,15 +267,42 @@ public:
|
|||||||
class pthread_mutex: public verifyable_object
|
class pthread_mutex: public verifyable_object
|
||||||
{
|
{
|
||||||
public:
|
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 void init_mutex ();
|
||||||
static int init (pthread_mutex_t *, const pthread_mutexattr_t *attr,
|
static int init (pthread_mutex_t *, const pthread_mutexattr_t *attr,
|
||||||
const pthread_mutex_t);
|
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;
|
unsigned long lock_counter;
|
||||||
HANDLE win32_obj_id;
|
HANDLE win32_obj_id;
|
||||||
unsigned int recursion_counter;
|
unsigned int recursion_counter;
|
||||||
@ -287,10 +314,6 @@ public:
|
|||||||
int type;
|
int type;
|
||||||
int pshared;
|
int pshared;
|
||||||
|
|
||||||
int lock ();
|
|
||||||
int trylock ();
|
|
||||||
int unlock ();
|
|
||||||
int destroy ();
|
|
||||||
void set_owner (pthread_t self)
|
void set_owner (pthread_t self)
|
||||||
{
|
{
|
||||||
recursion_counter = 1;
|
recursion_counter = 1;
|
||||||
@ -299,31 +322,16 @@ public:
|
|||||||
tid = GetCurrentThreadId ();
|
tid = GetCurrentThreadId ();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
static const pthread_t _new_mutex;
|
||||||
|
static const pthread_t _unlocked_mutex;
|
||||||
|
static const pthread_t _destroyed_mutex;
|
||||||
|
|
||||||
int lock_recursive ()
|
bool no_owner ();
|
||||||
{
|
|
||||||
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:
|
|
||||||
void _fixup_after_fork ();
|
void _fixup_after_fork ();
|
||||||
|
|
||||||
static List<pthread_mutex> mutexes;
|
static List<pthread_mutex> mutexes;
|
||||||
static fast_mutex mutex_initialization_lock;
|
static fast_mutex mutex_initialization_lock;
|
||||||
|
friend class pthread_cond;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define WAIT_CANCELED (WAIT_OBJECT_0 + 1)
|
#define WAIT_CANCELED (WAIT_OBJECT_0 + 1)
|
||||||
@ -467,9 +475,9 @@ class pthread_cond: public verifyable_object
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool is_good_object (pthread_cond_t const *);
|
static bool is_good_object (pthread_cond_t const *);
|
||||||
static bool is_good_initializer (pthread_cond_t const *);
|
static bool is_initializer (pthread_cond_t const *);
|
||||||
static bool is_good_initializer_or_object (pthread_cond_t const *);
|
static bool is_initializer_or_object (pthread_cond_t const *);
|
||||||
static bool is_good_initializer_or_bad_object (pthread_cond_t const *);
|
static bool is_initializer_or_bad_object (pthread_cond_t const *);
|
||||||
static void init_mutex ();
|
static void init_mutex ();
|
||||||
static int init (pthread_cond_t *, const pthread_condattr_t *);
|
static int init (pthread_cond_t *, const pthread_condattr_t *);
|
||||||
|
|
||||||
@ -518,9 +526,9 @@ class pthread_rwlock: public verifyable_object
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool is_good_object (pthread_rwlock_t const *);
|
static bool is_good_object (pthread_rwlock_t const *);
|
||||||
static bool is_good_initializer (pthread_rwlock_t const *);
|
static bool is_initializer (pthread_rwlock_t const *);
|
||||||
static bool is_good_initializer_or_object (pthread_rwlock_t const *);
|
static bool is_initializer_or_object (pthread_rwlock_t const *);
|
||||||
static bool is_good_initializer_or_bad_object (pthread_rwlock_t const *);
|
static bool is_initializer_or_bad_object (pthread_rwlock_t const *);
|
||||||
static void init_mutex ();
|
static void init_mutex ();
|
||||||
static int init (pthread_rwlock_t *, const pthread_rwlockattr_t *);
|
static int init (pthread_rwlock_t *, const pthread_rwlockattr_t *);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user