Wed Sep 12 13:03:00 2001 Robert Collins <rbtcollins@hotmail.com>

* autoload.cc (LoadDLLfuncEx): Auto load TryEnterCriticalSection - its a
n NT only call.
        * thread.cc (pthread_cond::TimedWait): Use critical sections for NT.
        (pthread_cond::fixup_after_fork): Don't detect bad apps.
        (pthread_mutex::pthread_mutex): Use critical sections for NT.
        (pthread_mutex::~pthread_mutex): Ditto.
        (pthread_mutex::Lock): Ditto.
        (pthread_mutex::TryLock): Ditto.
        (pthread_mutex::UnLock): Ditto.
        (pthread_mutex::fixup_after_fork): Ditto. Also do not detect bad apps.
        (__pthread_mutex_trylock): Move WIN32 specific test into the class metho
d.
        (__pthread_mutex_destroy): Prevent dereferencing passed pointer without
valid address.
        * thread.h (pthread_mutex): Use critical sections for NT.
This commit is contained in:
Robert Collins 2001-09-12 03:18:05 +00:00
parent 101f820da2
commit 8e4d969260
4 changed files with 82 additions and 17 deletions

View File

@ -1,3 +1,18 @@
Wed Sep 12 13:03:00 2001 Robert Collins <rbtcollins@hotmail.com>
* autoload.cc (LoadDLLfuncEx): Auto load TryEnterCriticalSection - its an NT only call.
* thread.cc (pthread_cond::TimedWait): Use critical sections for NT.
(pthread_cond::fixup_after_fork): Don't detect bad apps.
(pthread_mutex::pthread_mutex): Use critical sections for NT.
(pthread_mutex::~pthread_mutex): Ditto.
(pthread_mutex::Lock): Ditto.
(pthread_mutex::TryLock): Ditto.
(pthread_mutex::UnLock): Ditto.
(pthread_mutex::fixup_after_fork): Ditto. Also do not detect bad apps.
(__pthread_mutex_trylock): Move WIN32 specific test into the class method.
(__pthread_mutex_destroy): Prevent dereferencing passed pointer without valid address.
* thread.h (pthread_mutex): Use critical sections for NT.
Tue Sep 11 21:55:37 2001 Christopher Faylor <cgf@cygnus.com> Tue Sep 11 21:55:37 2001 Christopher Faylor <cgf@cygnus.com>
* sigproc.h (sigframe::unregister): Return true/false whether this * sigproc.h (sigframe::unregister): Return true/false whether this

View File

@ -478,6 +478,7 @@ LoadDLLfuncEx (CancelIo, 4, kernel32, 1)
LoadDLLfuncEx (Process32First, 8, kernel32, 1) LoadDLLfuncEx (Process32First, 8, kernel32, 1)
LoadDLLfuncEx (Process32Next, 8, kernel32, 1) LoadDLLfuncEx (Process32Next, 8, kernel32, 1)
LoadDLLfuncEx (CreateToolhelp32Snapshot, 8, kernel32, 1) LoadDLLfuncEx (CreateToolhelp32Snapshot, 8, kernel32, 1)
LoadDLLfunc (TryEnterCriticalSection, 4, kernel32)
LoadDLLfuncEx (waveOutGetNumDevs, 0, winmm, 1) LoadDLLfuncEx (waveOutGetNumDevs, 0, winmm, 1)
LoadDLLfuncEx (waveOutOpen, 24, winmm, 1) LoadDLLfuncEx (waveOutOpen, 24, winmm, 1)

View File

@ -506,8 +506,19 @@ pthread_cond::TimedWait (DWORD dwMilliseconds)
rv = WaitForSingleObject (win32_obj_id, dwMilliseconds); rv = WaitForSingleObject (win32_obj_id, dwMilliseconds);
} }
else else
{
LeaveCriticalSection (&mutex->criticalsection);
rv = WaitForSingleObject (win32_obj_id, dwMilliseconds);
#if 0
/* we need to use native win32 mutex's here, because the cygwin ones now use
* critical sections, which are faster, but introduce a race _here_. Until then
* The NT variant of the code is redundant.
*/
rv = SignalObjectAndWait (mutex->win32_obj_id, win32_obj_id, dwMilliseconds, rv = SignalObjectAndWait (mutex->win32_obj_id, win32_obj_id, dwMilliseconds,
false); false);
#endif
}
switch (rv) switch (rv)
{ {
case WAIT_FAILED: case WAIT_FAILED:
@ -532,8 +543,13 @@ pthread_cond::fixup_after_fork ()
this->win32_obj_id =::CreateEvent (&sec_none_nih, false, false, NULL); this->win32_obj_id =::CreateEvent (&sec_none_nih, false, false, NULL);
if (!win32_obj_id) if (!win32_obj_id)
api_fatal("failed to create new win32 mutex\n"); api_fatal("failed to create new win32 mutex\n");
#if DETECT_BAD_APPS
if (waiting) if (waiting)
api_fatal("Forked() while a condition variable has waiting threads.\nReport to cygwin@cygwin.com\n"); api_fatal("Forked() while a condition variable has waiting threads.\nReport to cygwin@cygwin.com\n");
#else
waiting = 0;
mutex = NULL;
#endif
} }
@ -604,11 +620,14 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr):verifyable_object (PTHREA
magic = 0; magic = 0;
return; return;
} }
if (iswinnt)
this->win32_obj_id =::CreateMutex (&sec_none_nih, false, NULL); InitializeCriticalSection (&criticalsection);
else
if (!win32_obj_id) {
magic = 0; this->win32_obj_id =::CreateMutex (&sec_none_nih, false, NULL);
if (!win32_obj_id)
magic = 0;
}
condwaits = 0; condwaits = 0;
pshared = PTHREAD_PROCESS_PRIVATE; pshared = PTHREAD_PROCESS_PRIVATE;
/* threadsafe addition is easy */ /* threadsafe addition is easy */
@ -617,18 +636,25 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr):verifyable_object (PTHREA
pthread_mutex::~pthread_mutex () pthread_mutex::~pthread_mutex ()
{ {
if (win32_obj_id) if (iswinnt)
CloseHandle (win32_obj_id); DeleteCriticalSection (&criticalsection);
win32_obj_id = NULL; else
{
if (win32_obj_id)
CloseHandle (win32_obj_id);
win32_obj_id = NULL;
}
/* I'm not 100% sure the next bit is threadsafe. I think it is... */ /* I'm not 100% sure the next bit is threadsafe. I think it is... */
if (MT_INTERFACE->mutexs == this) if (MT_INTERFACE->mutexs == this)
InterlockedExchangePointer (&MT_INTERFACE->mutexs, this->next); /* TODO: printf an error if the return value != this */
InterlockedExchangePointer (&MT_INTERFACE->mutexs, next);
else else
{ {
pthread_mutex *tempmutex = MT_INTERFACE->mutexs; pthread_mutex *tempmutex = MT_INTERFACE->mutexs;
while (tempmutex->next && tempmutex->next != this) while (tempmutex->next && tempmutex->next != this)
tempmutex = tempmutex->next; tempmutex = tempmutex->next;
/* but there may be a race between the loop above and this statement */ /* but there may be a race between the loop above and this statement */
/* TODO: printf an error if the return value != this */
InterlockedExchangePointer (&tempmutex->next, this->next); InterlockedExchangePointer (&tempmutex->next, this->next);
} }
} }
@ -636,19 +662,33 @@ pthread_mutex::~pthread_mutex ()
int int
pthread_mutex::Lock () pthread_mutex::Lock ()
{ {
if (iswinnt)
{
EnterCriticalSection (&criticalsection);
return 0;
}
/* FIXME: Return 0 on success */
return WaitForSingleObject (win32_obj_id, INFINITE); return WaitForSingleObject (win32_obj_id, INFINITE);
} }
/* returns non-zero on failure */
int int
pthread_mutex::TryLock () pthread_mutex::TryLock ()
{ {
return WaitForSingleObject (win32_obj_id, 0); if (iswinnt)
return (!TryEnterCriticalSection (&criticalsection));
return (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT);
} }
int int
pthread_mutex::UnLock () pthread_mutex::UnLock ()
{ {
return ReleaseMutex (win32_obj_id); if (iswinnt)
{
LeaveCriticalSection (&criticalsection);
return 0;
}
return (!ReleaseMutex (win32_obj_id));
} }
void void
@ -658,12 +698,20 @@ pthread_mutex::fixup_after_fork ()
if (pshared != PTHREAD_PROCESS_PRIVATE) if (pshared != PTHREAD_PROCESS_PRIVATE)
api_fatal("pthread_mutex::fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's\n"); api_fatal("pthread_mutex::fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's\n");
/* FIXME: duplicate code here and in the constructor. */ /* FIXME: duplicate code here and in the constructor. */
this->win32_obj_id =::CreateMutex (&sec_none_nih, false, NULL); if (iswinnt)
InitializeCriticalSection(&criticalsection);
if (!win32_obj_id) else
api_fatal("pthread_mutex::fixup_after_fork() failed to create new win32 mutex\n"); {
win32_obj_id =::CreateMutex (&sec_none_nih, false, NULL);
if (!win32_obj_id)
api_fatal("pthread_mutex::fixup_after_fork() failed to create new win32 mutex\n");
}
#if DETECT_BAD_APPS
if (condwaits) if (condwaits)
api_fatal("Forked() while a mutex has condition variables waiting on it.\nReport to cygwin@cygwin.com\n"); api_fatal("Forked() while a mutex has condition variables waiting on it.\nReport to cygwin@cygwin.com\n");
#else
condwaits = 0;
#endif
} }
pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC), pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC),
@ -1908,7 +1956,7 @@ __pthread_mutex_trylock (pthread_mutex_t *mutex)
__pthread_mutex_init (mutex, NULL); __pthread_mutex_init (mutex, NULL);
if (!verifyable_object_isvalid (*themutex, PTHREAD_MUTEX_MAGIC)) if (!verifyable_object_isvalid (*themutex, PTHREAD_MUTEX_MAGIC))
return EINVAL; return EINVAL;
if ((*themutex)->TryLock () == WAIT_TIMEOUT) if ((*themutex)->TryLock ())
return EBUSY; return EBUSY;
return 0; return 0;
} }
@ -1927,7 +1975,7 @@ __pthread_mutex_unlock (pthread_mutex_t *mutex)
int int
__pthread_mutex_destroy (pthread_mutex_t *mutex) __pthread_mutex_destroy (pthread_mutex_t *mutex)
{ {
if (*mutex == PTHREAD_MUTEX_INITIALIZER) if (check_valid_pointer (mutex) && (*mutex == PTHREAD_MUTEX_INITIALIZER))
return 0; return 0;
if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC)) if (!verifyable_object_isvalid (*mutex, PTHREAD_MUTEX_MAGIC))
return EINVAL; return EINVAL;

View File

@ -267,6 +267,7 @@ public:
class pthread_mutex:public verifyable_object class pthread_mutex:public verifyable_object
{ {
public: public:
CRITICAL_SECTION criticalsection;
HANDLE win32_obj_id; HANDLE win32_obj_id;
LONG condwaits; LONG condwaits;
int pshared; int pshared;