* thread.h (class List): Move inline code inside class
declaration. (List::forEach): Change callback parameter to template class member functionpointer. (pthread_keys::fixup_before_fork): Change to inline. Use List::forEach to fixup keys. (pthread_keys::fixup_after_fork): Ditto. (pthread_keys::runAllDestructors): Ditto. (pthread_key::saveAKey): Remove. (pthread_key::restoreAKey): Ditto. (pthread_key::destroyAKey): Ditto. (pthread_key::run_destructor): Rename to runDestructor. (pthread_mutex::fixup_after_fork): Change to inline. Use List::forEach to fixup mutexes after a fork. (pthread_mutex::FixupAfterFork): New method. (pthread_mutex::mutexes): New member. (pthread_cond::fixup_after_fork): Change to inline. Use List::forEach to fixup conds after a fork. (pthread_cond::FixupAfterFork): New method. (pthread_cond::conds): New member. (pthread_rwlock::fixup_after_fork): Change to inline. Use List::forEach to fixup rwlocks after a fork. (pthread_rwlock::FixupAfterFork): New method. (pthread_rwlock::rwlocks): New member. (semaphore::fixup_after_fork): Change to inline. Use List::forEach to fixup mutexes after a fork. (semaphore::FixupAfterFork): New method. (semaphore::semaphores): New member. (MTinterface::mutexs): Remove. (MTinterface::conds): Ditto. (MTinterface::rwlocks): Ditto. (MTinterface::semaphores): Ditto. (pthread_equal): Add extern "C". (pthread_mutex_lock): Ditto. * thread.cc (MTinterface::fixup_after_fork): Change fixup_after_fork calls for pthread objects. (semaphore::conds): Instantiate. (pthread_cond::pthread_cond): Use List::Insert rather than custom list code. (pthread_cond::~pthread_cond): Use List::Remove rather than custom list code. (pthread_cond::fixup_after_fork): Rename to FixupAfterFork. (pthread_rwlock::rwlocks): Instantiate. (pthread_rwlock::pthread_crwlock): Use List::Insert rather than custom list code. (pthread_rwlock::~pthread_rwlock): Use List::Remove rather than custom list code. (pthread_rwlock::fixup_after_fork): Rename to FixupAfterFork. (pthread_key::saveAKey): Remove. (pthread_key::fixup_before_fork): Ditto. (pthread_key::restoreAKey): Ditto. (pthread_key::fixup_after_fork): Ditto. (pthread_key::destroyAKey): Ditto. (pthread_key::runAllDestructors): Ditto. (pthread_key::run_destructor): Rename to runDestructor. (pthread_mutex::mutexes): Instantiate. (pthread_mutex::pthread_mutex): Use List::Insert rather than custom list code. (pthread_mutex::~pthread_mutex): Use List::Remove rather than custom list code. (pthread_mutex::fixup_after_fork): Rename to FixupAfterFork. (semaphore::conds): Instantiate. (semaphore::semaphore): Use List::Insert rather than custom list code. (semaphores::~semaphore): Use List::Remove rather than custom list code. (semaphore::fixup_after_fork): Rename to FixupAfterFork.
This commit is contained in:
parent
522fcf1615
commit
9306ba2ee4
|
@ -1,3 +1,74 @@
|
||||||
|
2003-03-23 Thomas Pfaff <tpfaff@gmx.net>
|
||||||
|
|
||||||
|
* thread.h (class List): Move inline code inside class
|
||||||
|
declaration.
|
||||||
|
(List::forEach): Change callback parameter to template class
|
||||||
|
member function pointer.
|
||||||
|
(pthread_keys::fixup_before_fork): Change to inline. Use
|
||||||
|
List::forEach to fixup keys.
|
||||||
|
(pthread_keys::fixup_after_fork): Ditto.
|
||||||
|
(pthread_keys::runAllDestructors): Ditto.
|
||||||
|
(pthread_key::saveAKey): Remove.
|
||||||
|
(pthread_key::restoreAKey): Ditto.
|
||||||
|
(pthread_key::destroyAKey): Ditto.
|
||||||
|
(pthread_key::run_destructor): Rename to runDestructor.
|
||||||
|
(pthread_mutex::fixup_after_fork): Change to inline. Use
|
||||||
|
List::forEach to fixup mutexes after a fork.
|
||||||
|
(pthread_mutex::FixupAfterFork): New method.
|
||||||
|
(pthread_mutex::mutexes): New member.
|
||||||
|
(pthread_cond::fixup_after_fork): Change to inline. Use
|
||||||
|
List::forEach to fixup conds after a fork.
|
||||||
|
(pthread_cond::FixupAfterFork): New method.
|
||||||
|
(pthread_cond::conds): New member.
|
||||||
|
(pthread_rwlock::fixup_after_fork): Change to inline. Use
|
||||||
|
List::forEach to fixup rwlocks after a fork.
|
||||||
|
(pthread_rwlock::FixupAfterFork): New method.
|
||||||
|
(pthread_rwlock::rwlocks): New member.
|
||||||
|
(semaphore::fixup_after_fork): Change to inline. Use
|
||||||
|
List::forEach to fixup mutexes after a fork.
|
||||||
|
(semaphore::FixupAfterFork): New method.
|
||||||
|
(semaphore::semaphores): New member.
|
||||||
|
(MTinterface::mutexs): Remove.
|
||||||
|
(MTinterface::conds): Ditto.
|
||||||
|
(MTinterface::rwlocks): Ditto.
|
||||||
|
(MTinterface::semaphores): Ditto.
|
||||||
|
(pthread_equal): Add extern "C".
|
||||||
|
(pthread_mutex_lock): Ditto.
|
||||||
|
|
||||||
|
* thread.cc (MTinterface::fixup_after_fork): Change
|
||||||
|
fixup_after_fork calls for pthread objects.
|
||||||
|
(semaphore::conds): Instantiate.
|
||||||
|
(pthread_cond::pthread_cond): Use List::Insert rather than
|
||||||
|
custom list code.
|
||||||
|
(pthread_cond::~pthread_cond): Use List::Remove rather than
|
||||||
|
custom list code.
|
||||||
|
(pthread_cond::fixup_after_fork): Rename to FixupAfterFork.
|
||||||
|
(pthread_rwlock::rwlocks): Instantiate.
|
||||||
|
(pthread_rwlock::pthread_crwlock): Use List::Insert rather than
|
||||||
|
custom list code.
|
||||||
|
(pthread_rwlock::~pthread_rwlock): Use List::Remove rather than
|
||||||
|
custom list code.
|
||||||
|
(pthread_rwlock::fixup_after_fork): Rename to FixupAfterFork.
|
||||||
|
(pthread_key::saveAKey): Remove.
|
||||||
|
(pthread_key::fixup_before_fork): Ditto.
|
||||||
|
(pthread_key::restoreAKey): Ditto.
|
||||||
|
(pthread_key::fixup_after_fork): Ditto.
|
||||||
|
(pthread_key::destroyAKey): Ditto.
|
||||||
|
(pthread_key::runAllDestructors): Ditto.
|
||||||
|
(pthread_key::run_destructor): Rename to runDestructor.
|
||||||
|
(pthread_mutex::mutexes): Instantiate.
|
||||||
|
(pthread_mutex::pthread_mutex): Use List::Insert rather than
|
||||||
|
custom list code.
|
||||||
|
(pthread_mutex::~pthread_mutex): Use List::Remove rather than
|
||||||
|
custom list code.
|
||||||
|
(pthread_mutex::fixup_after_fork): Rename to FixupAfterFork.
|
||||||
|
(semaphore::conds): Instantiate.
|
||||||
|
(semaphore::semaphore): Use List::Insert rather than custom list
|
||||||
|
code.
|
||||||
|
(semaphores::~semaphore): Use List::Remove rather than custom
|
||||||
|
list code.
|
||||||
|
(semaphore::fixup_after_fork): Rename to FixupAfterFork.
|
||||||
|
|
||||||
2003-03-22 Christopher Faylor <cgf@redhat.com>
|
2003-03-22 Christopher Faylor <cgf@redhat.com>
|
||||||
|
|
||||||
* pipe.cc (fhandler_pipe::dup): Don't dup input_handle if it doesn't
|
* pipe.cc (fhandler_pipe::dup): Don't dup input_handle if it doesn't
|
||||||
|
|
|
@ -217,34 +217,10 @@ MTinterface::fixup_after_fork (void)
|
||||||
threadcount = 1;
|
threadcount = 1;
|
||||||
pthread::initMainThread (true);
|
pthread::initMainThread (true);
|
||||||
|
|
||||||
pthread_mutex *mutex = mutexs;
|
pthread_mutex::fixup_after_fork ();
|
||||||
debug_printf ("mutexs is %x",mutexs);
|
pthread_cond::fixup_after_fork ();
|
||||||
while (mutex)
|
pthread_rwlock::fixup_after_fork ();
|
||||||
{
|
semaphore::fixup_after_fork ();
|
||||||
mutex->fixup_after_fork ();
|
|
||||||
mutex = mutex->next;
|
|
||||||
}
|
|
||||||
pthread_cond *cond = conds;
|
|
||||||
debug_printf ("conds is %x",conds);
|
|
||||||
while (cond)
|
|
||||||
{
|
|
||||||
cond->fixup_after_fork ();
|
|
||||||
cond = cond->next;
|
|
||||||
}
|
|
||||||
pthread_rwlock *rwlock = rwlocks;
|
|
||||||
debug_printf ("rwlocks is %x",rwlocks);
|
|
||||||
while (rwlock)
|
|
||||||
{
|
|
||||||
rwlock->fixup_after_fork ();
|
|
||||||
rwlock = rwlock->next;
|
|
||||||
}
|
|
||||||
semaphore *sem = semaphores;
|
|
||||||
debug_printf ("semaphores is %x",semaphores);
|
|
||||||
while (sem)
|
|
||||||
{
|
|
||||||
sem->fixup_after_fork ();
|
|
||||||
sem = sem->next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pthread calls */
|
/* pthread calls */
|
||||||
|
@ -807,6 +783,8 @@ pthread_condattr::~pthread_condattr ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<pthread_cond> pthread_cond::conds;
|
||||||
|
|
||||||
/* This is used for cond creation protection within a single process only */
|
/* This is used for cond creation protection within a single process only */
|
||||||
nativeMutex NO_COPY pthread_cond::condInitializationLock;
|
nativeMutex NO_COPY pthread_cond::condInitializationLock;
|
||||||
|
|
||||||
|
@ -862,8 +840,7 @@ pthread_cond::pthread_cond (pthread_condattr *attr) :
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* threadsafe addition is easy */
|
conds.Insert (this);
|
||||||
next = (pthread_cond *) InterlockedExchangePointer (&MT_INTERFACE->conds, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_cond::~pthread_cond ()
|
pthread_cond::~pthread_cond ()
|
||||||
|
@ -871,17 +848,7 @@ pthread_cond::~pthread_cond ()
|
||||||
if (semWait)
|
if (semWait)
|
||||||
CloseHandle (semWait);
|
CloseHandle (semWait);
|
||||||
|
|
||||||
/* I'm not 100% sure the next bit is threadsafe. I think it is... */
|
conds.Remove (this);
|
||||||
if (MT_INTERFACE->conds == this)
|
|
||||||
InterlockedExchangePointer (&MT_INTERFACE->conds, this->next);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pthread_cond *tempcond = MT_INTERFACE->conds;
|
|
||||||
while (tempcond->next && tempcond->next != this)
|
|
||||||
tempcond = tempcond->next;
|
|
||||||
/* but there may be a race between the loop above and this statement */
|
|
||||||
InterlockedExchangePointer (&tempcond->next, this->next);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -992,7 +959,7 @@ pthread_cond::Wait (pthread_mutex_t mutex, DWORD dwMilliseconds)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread_cond::fixup_after_fork ()
|
pthread_cond::FixupAfterFork ()
|
||||||
{
|
{
|
||||||
waiting = pending = 0;
|
waiting = pending = 0;
|
||||||
mtxCond = NULL;
|
mtxCond = NULL;
|
||||||
|
@ -1003,7 +970,7 @@ pthread_cond::fixup_after_fork ()
|
||||||
|
|
||||||
semWait = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL);
|
semWait = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL);
|
||||||
if (!semWait)
|
if (!semWait)
|
||||||
api_fatal ("pthread_cond::fixup_after_fork () failed to recreate win32 semaphore");
|
api_fatal ("pthread_cond::FixupAfterFork () failed to recreate win32 semaphore");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -1023,6 +990,8 @@ pthread_rwlockattr::~pthread_rwlockattr ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<pthread_rwlock> pthread_rwlock::rwlocks;
|
||||||
|
|
||||||
/* This is used for rwlock creation protection within a single process only */
|
/* This is used for rwlock creation protection within a single process only */
|
||||||
nativeMutex NO_COPY pthread_rwlock::rwlockInitializationLock;
|
nativeMutex NO_COPY pthread_rwlock::rwlockInitializationLock;
|
||||||
|
|
||||||
|
@ -1078,23 +1047,12 @@ pthread_rwlock::pthread_rwlock (pthread_rwlockattr *attr) :
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* threadsafe addition is easy */
|
rwlocks.Insert (this);
|
||||||
next = (pthread_rwlock *) InterlockedExchangePointer (&MT_INTERFACE->rwlocks, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_rwlock::~pthread_rwlock ()
|
pthread_rwlock::~pthread_rwlock ()
|
||||||
{
|
{
|
||||||
/* I'm not 100% sure the next bit is threadsafe. I think it is... */
|
rwlocks.Remove (this);
|
||||||
if (MT_INTERFACE->rwlocks == this)
|
|
||||||
InterlockedExchangePointer (&MT_INTERFACE->rwlocks, this->next);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pthread_rwlock *temprwlock = MT_INTERFACE->rwlocks;
|
|
||||||
while (temprwlock->next && temprwlock->next != this)
|
|
||||||
temprwlock = temprwlock->next;
|
|
||||||
/* but there may be a race between the loop above and this statement */
|
|
||||||
InterlockedExchangePointer (&temprwlock->next, this->next);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1315,7 +1273,7 @@ pthread_rwlock::WrLockCleanup (void *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread_rwlock::fixup_after_fork ()
|
pthread_rwlock::FixupAfterFork ()
|
||||||
{
|
{
|
||||||
pthread_t self = pthread::self ();
|
pthread_t self = pthread::self ();
|
||||||
struct RWLOCK_READER **temp = &readers;
|
struct RWLOCK_READER **temp = &readers;
|
||||||
|
@ -1346,42 +1304,6 @@ pthread_rwlock::fixup_after_fork ()
|
||||||
/* This stores pthread_key information across fork() boundaries */
|
/* This stores pthread_key information across fork() boundaries */
|
||||||
List<pthread_key> pthread_key::keys;
|
List<pthread_key> pthread_key::keys;
|
||||||
|
|
||||||
void
|
|
||||||
pthread_key::saveAKey (pthread_key *key)
|
|
||||||
{
|
|
||||||
key->saveKeyToBuffer ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pthread_key::fixup_before_fork ()
|
|
||||||
{
|
|
||||||
keys.forEach (saveAKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pthread_key::restoreAKey (pthread_key *key)
|
|
||||||
{
|
|
||||||
key->recreateKeyFromBuffer ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pthread_key::fixup_after_fork ()
|
|
||||||
{
|
|
||||||
keys.forEach (restoreAKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pthread_key::destroyAKey (pthread_key *key)
|
|
||||||
{
|
|
||||||
key->run_destructor ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
pthread_key::runAllDestructors ()
|
|
||||||
{
|
|
||||||
keys.forEach (destroyAKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
pthread_key::isGoodObject (pthread_key_t const *key)
|
pthread_key::isGoodObject (pthread_key_t const *key)
|
||||||
{
|
{
|
||||||
|
@ -1445,7 +1367,7 @@ pthread_key::recreateKeyFromBuffer ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread_key::run_destructor ()
|
pthread_key::runDestructor ()
|
||||||
{
|
{
|
||||||
if (destructor)
|
if (destructor)
|
||||||
{
|
{
|
||||||
|
@ -1528,6 +1450,8 @@ pthread_mutex::canBeUnlocked (pthread_mutex_t const *mutex)
|
||||||
return (pthread_equal ((*mutex)->owner, self)) && 1 == (*mutex)->recursion_counter;
|
return (pthread_equal ((*mutex)->owner, self)) && 1 == (*mutex)->recursion_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<pthread_mutex> pthread_mutex::mutexes;
|
||||||
|
|
||||||
/* This is used for mutex creation protection within a single process only */
|
/* This is used for mutex creation protection within a single process only */
|
||||||
nativeMutex NO_COPY pthread_mutex::mutexInitializationLock;
|
nativeMutex NO_COPY pthread_mutex::mutexInitializationLock;
|
||||||
|
|
||||||
|
@ -1567,8 +1491,7 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr) :
|
||||||
type = attr->mutextype;
|
type = attr->mutextype;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* threadsafe addition is easy */
|
mutexes.Insert (this);
|
||||||
next = (pthread_mutex *) InterlockedExchangePointer (&MT_INTERFACE->mutexs, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex::~pthread_mutex ()
|
pthread_mutex::~pthread_mutex ()
|
||||||
|
@ -1576,19 +1499,7 @@ pthread_mutex::~pthread_mutex ()
|
||||||
if (win32_obj_id)
|
if (win32_obj_id)
|
||||||
CloseHandle (win32_obj_id);
|
CloseHandle (win32_obj_id);
|
||||||
|
|
||||||
/* I'm not 100% sure the next bit is threadsafe. I think it is... */
|
mutexes.Remove (this);
|
||||||
if (MT_INTERFACE->mutexs == this)
|
|
||||||
/* TODO: printf an error if the return value != this */
|
|
||||||
InterlockedExchangePointer (&MT_INTERFACE->mutexs, next);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pthread_mutex *tempmutex = MT_INTERFACE->mutexs;
|
|
||||||
while (tempmutex->next && tempmutex->next != this)
|
|
||||||
tempmutex = tempmutex->next;
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1665,11 +1576,11 @@ pthread_mutex::_Destroy (pthread_t self)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread_mutex::fixup_after_fork ()
|
pthread_mutex::FixupAfterFork ()
|
||||||
{
|
{
|
||||||
debug_printf ("mutex %x in fixup_after_fork", this);
|
debug_printf ("mutex %x in FixupAfterFork", this);
|
||||||
if (pshared != PTHREAD_PROCESS_PRIVATE)
|
if (pshared != PTHREAD_PROCESS_PRIVATE)
|
||||||
api_fatal ("pthread_mutex::fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's");
|
api_fatal ("pthread_mutex::FixupAfterFork () doesn'tunderstand PROCESS_SHARED mutex's");
|
||||||
|
|
||||||
if (NULL == owner)
|
if (NULL == owner)
|
||||||
/* mutex has no owner, reset to initial */
|
/* mutex has no owner, reset to initial */
|
||||||
|
@ -1680,7 +1591,7 @@ pthread_mutex::fixup_after_fork ()
|
||||||
|
|
||||||
win32_obj_id = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL);
|
win32_obj_id = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, 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::FixupAfterFork () failed to recreate win32 semaphore for mutex");
|
||||||
|
|
||||||
condwaits = 0;
|
condwaits = 0;
|
||||||
}
|
}
|
||||||
|
@ -1702,6 +1613,8 @@ pthread_mutexattr::~pthread_mutexattr ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<semaphore> semaphore::semaphores;
|
||||||
|
|
||||||
semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MAGIC)
|
semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MAGIC)
|
||||||
{
|
{
|
||||||
this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, value, LONG_MAX,
|
this->win32_obj_id = ::CreateSemaphore (&sec_none_nih, value, LONG_MAX,
|
||||||
|
@ -1710,25 +1623,16 @@ semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MA
|
||||||
magic = 0;
|
magic = 0;
|
||||||
this->shared = pshared;
|
this->shared = pshared;
|
||||||
currentvalue = value;
|
currentvalue = value;
|
||||||
/* threadsafe addition is easy */
|
|
||||||
next = (semaphore *) InterlockedExchangePointer (&MT_INTERFACE->semaphores, this);
|
semaphores.Insert (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
semaphore::~semaphore ()
|
semaphore::~semaphore ()
|
||||||
{
|
{
|
||||||
if (win32_obj_id)
|
if (win32_obj_id)
|
||||||
CloseHandle (win32_obj_id);
|
CloseHandle (win32_obj_id);
|
||||||
/* I'm not 100% sure the next bit is threadsafe. I think it is... */
|
|
||||||
if (MT_INTERFACE->semaphores == this)
|
semaphores.Remove (this);
|
||||||
InterlockedExchangePointer (&MT_INTERFACE->semaphores, this->next);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
semaphore *tempsem = MT_INTERFACE->semaphores;
|
|
||||||
while (tempsem->next && tempsem->next != this)
|
|
||||||
tempsem = tempsem->next;
|
|
||||||
/* but there may be a race between the loop above and this statement */
|
|
||||||
InterlockedExchangePointer (&tempsem->next, this->next);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -1769,9 +1673,9 @@ semaphore::Wait ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
semaphore::fixup_after_fork ()
|
semaphore::FixupAfterFork ()
|
||||||
{
|
{
|
||||||
debug_printf ("sem %x in fixup_after_fork", this);
|
debug_printf ("sem %x in FixupAfterFork", this);
|
||||||
if (shared != PTHREAD_PROCESS_PRIVATE)
|
if (shared != PTHREAD_PROCESS_PRIVATE)
|
||||||
api_fatal ("doesn't understand PROCESS_SHARED semaphores variables");
|
api_fatal ("doesn't understand PROCESS_SHARED semaphores variables");
|
||||||
/* FIXME: duplicate code here and in the constructor. */
|
/* FIXME: duplicate code here and in the constructor. */
|
||||||
|
@ -2859,7 +2763,7 @@ pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set)
|
||||||
|
|
||||||
/* ID */
|
/* ID */
|
||||||
|
|
||||||
int
|
extern "C" int
|
||||||
pthread_equal (pthread_t t1, pthread_t t2)
|
pthread_equal (pthread_t t1, pthread_t t2)
|
||||||
{
|
{
|
||||||
return t1 == t2;
|
return t1 == t2;
|
||||||
|
@ -2921,7 +2825,7 @@ pthread_mutex_getprioceiling (const pthread_mutex_t *mutex,
|
||||||
return ENOSYS;
|
return ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
extern "C" int
|
||||||
pthread_mutex_lock (pthread_mutex_t *mutex)
|
pthread_mutex_lock (pthread_mutex_t *mutex)
|
||||||
{
|
{
|
||||||
pthread_mutex_t *themutex = mutex;
|
pthread_mutex_t *themutex = mutex;
|
||||||
|
|
|
@ -189,14 +189,50 @@ typedef enum
|
||||||
verifyable_object_state verifyable_object_isvalid (void const *, long);
|
verifyable_object_state verifyable_object_isvalid (void const *, long);
|
||||||
verifyable_object_state verifyable_object_isvalid (void const *, long, void *);
|
verifyable_object_state verifyable_object_isvalid (void const *, long, void *);
|
||||||
|
|
||||||
/* interface */
|
|
||||||
template <class ListNode> class List {
|
template <class ListNode> class List {
|
||||||
public:
|
public:
|
||||||
List();
|
List() : head(NULL)
|
||||||
void Insert (ListNode *aNode);
|
{
|
||||||
ListNode *Remove ( ListNode *aNode);
|
}
|
||||||
ListNode *Pop ();
|
|
||||||
void forEach (void (*)(ListNode *aNode));
|
void Insert (ListNode *aNode)
|
||||||
|
{
|
||||||
|
if (!aNode)
|
||||||
|
return;
|
||||||
|
aNode->next = (ListNode *) InterlockedExchangePointer (&head, aNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListNode *Remove ( ListNode *aNode)
|
||||||
|
{
|
||||||
|
if (!aNode || !head)
|
||||||
|
return NULL;
|
||||||
|
if (aNode == head)
|
||||||
|
return Pop ();
|
||||||
|
|
||||||
|
ListNode *resultPrev = head;
|
||||||
|
while (resultPrev && resultPrev->next && !(aNode == resultPrev->next))
|
||||||
|
resultPrev = resultPrev->next;
|
||||||
|
if (resultPrev)
|
||||||
|
return (ListNode *)InterlockedExchangePointer (&resultPrev->next, resultPrev->next->next);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListNode *Pop ()
|
||||||
|
{
|
||||||
|
return (ListNode *) InterlockedExchangePointer (&head, head->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* poor mans generic programming. */
|
||||||
|
void forEach (void (ListNode::*callback) ())
|
||||||
|
{
|
||||||
|
ListNode *aNode = head;
|
||||||
|
while (aNode)
|
||||||
|
{
|
||||||
|
(aNode->*callback) ();
|
||||||
|
aNode = aNode->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ListNode *head;
|
ListNode *head;
|
||||||
};
|
};
|
||||||
|
@ -205,8 +241,6 @@ class pthread_key:public verifyable_object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static bool isGoodObject (pthread_key_t const *);
|
static bool isGoodObject (pthread_key_t const *);
|
||||||
static void runAllDestructors ();
|
|
||||||
|
|
||||||
DWORD dwTlsIndex;
|
DWORD dwTlsIndex;
|
||||||
|
|
||||||
int set (const void *);
|
int set (const void *);
|
||||||
|
@ -214,69 +248,32 @@ public:
|
||||||
|
|
||||||
pthread_key (void (*)(void *));
|
pthread_key (void (*)(void *));
|
||||||
~pthread_key ();
|
~pthread_key ();
|
||||||
static void fixup_before_fork();
|
static void fixup_before_fork()
|
||||||
static void fixup_after_fork();
|
{
|
||||||
|
keys.forEach (&pthread_key::saveKeyToBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fixup_after_fork()
|
||||||
|
{
|
||||||
|
keys.forEach (&pthread_key::recreateKeyFromBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void runAllDestructors ()
|
||||||
|
{
|
||||||
|
keys.forEach (&pthread_key::runDestructor);
|
||||||
|
}
|
||||||
|
|
||||||
/* List support calls */
|
/* List support calls */
|
||||||
class pthread_key *next;
|
class pthread_key *next;
|
||||||
private:
|
private:
|
||||||
// lists of objects. USE THREADSAFE INSERTS AND DELETES.
|
|
||||||
static List<pthread_key> keys;
|
static List<pthread_key> keys;
|
||||||
static void saveAKey (pthread_key *);
|
|
||||||
static void restoreAKey (pthread_key *);
|
|
||||||
static void destroyAKey (pthread_key *);
|
|
||||||
void saveKeyToBuffer ();
|
void saveKeyToBuffer ();
|
||||||
void recreateKeyFromBuffer ();
|
void recreateKeyFromBuffer ();
|
||||||
void (*destructor) (void *);
|
void (*destructor) (void *);
|
||||||
void run_destructor ();
|
void runDestructor ();
|
||||||
void *fork_buf;
|
void *fork_buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* implementation */
|
|
||||||
template <class ListNode>
|
|
||||||
List<ListNode>::List<ListNode> () : head(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
template <class ListNode> void
|
|
||||||
List<ListNode>::Insert (ListNode *aNode)
|
|
||||||
{
|
|
||||||
if (!aNode)
|
|
||||||
return;
|
|
||||||
aNode->next = (ListNode *) InterlockedExchangePointer (&head, aNode);
|
|
||||||
}
|
|
||||||
template <class ListNode> ListNode *
|
|
||||||
List<ListNode>::Remove ( ListNode *aNode)
|
|
||||||
{
|
|
||||||
if (!aNode)
|
|
||||||
return NULL;
|
|
||||||
if (!head)
|
|
||||||
return NULL;
|
|
||||||
if (aNode == head)
|
|
||||||
return Pop ();
|
|
||||||
ListNode *resultPrev = head;
|
|
||||||
while (resultPrev && resultPrev->next && !(aNode == resultPrev->next))
|
|
||||||
resultPrev = resultPrev->next;
|
|
||||||
if (resultPrev)
|
|
||||||
return (ListNode *)InterlockedExchangePointer (&resultPrev->next, resultPrev->next->next);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
template <class ListNode> ListNode *
|
|
||||||
List<ListNode>::Pop ()
|
|
||||||
{
|
|
||||||
return (ListNode *) InterlockedExchangePointer (&head, head->next);
|
|
||||||
}
|
|
||||||
/* poor mans generic programming. */
|
|
||||||
template <class ListNode> void
|
|
||||||
List<ListNode>::forEach (void (*callback)(ListNode *))
|
|
||||||
{
|
|
||||||
ListNode *aNode = head;
|
|
||||||
while (aNode)
|
|
||||||
{
|
|
||||||
callback (aNode);
|
|
||||||
aNode = aNode->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class pthread_attr:public verifyable_object
|
class pthread_attr:public verifyable_object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -319,7 +316,6 @@ public:
|
||||||
pthread_t owner;
|
pthread_t owner;
|
||||||
int type;
|
int type;
|
||||||
int pshared;
|
int pshared;
|
||||||
class pthread_mutex * next;
|
|
||||||
|
|
||||||
pthread_t GetPthreadSelf () const
|
pthread_t GetPthreadSelf () const
|
||||||
{
|
{
|
||||||
|
@ -358,18 +354,25 @@ public:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fixup_after_fork ();
|
|
||||||
|
|
||||||
pthread_mutex (pthread_mutexattr * = NULL);
|
pthread_mutex (pthread_mutexattr * = NULL);
|
||||||
pthread_mutex (pthread_mutex_t *, pthread_mutexattr *);
|
pthread_mutex (pthread_mutex_t *, pthread_mutexattr *);
|
||||||
~pthread_mutex ();
|
~pthread_mutex ();
|
||||||
|
|
||||||
|
class pthread_mutex * next;
|
||||||
|
static void fixup_after_fork ()
|
||||||
|
{
|
||||||
|
mutexes.forEach (&pthread_mutex::FixupAfterFork);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixupAfterFork ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _Lock (pthread_t self);
|
int _Lock (pthread_t self);
|
||||||
int _TryLock (pthread_t self);
|
int _TryLock (pthread_t self);
|
||||||
int _UnLock (pthread_t self);
|
int _UnLock (pthread_t self);
|
||||||
int _Destroy (pthread_t self);
|
int _Destroy (pthread_t self);
|
||||||
|
|
||||||
|
static List<pthread_mutex> mutexes;
|
||||||
static nativeMutex mutexInitializationLock;
|
static nativeMutex mutexInitializationLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -506,16 +509,22 @@ public:
|
||||||
|
|
||||||
pthread_mutex_t mtxCond;
|
pthread_mutex_t mtxCond;
|
||||||
|
|
||||||
class pthread_cond * next;
|
|
||||||
|
|
||||||
void UnBlock (const bool all);
|
void UnBlock (const bool all);
|
||||||
int Wait (pthread_mutex_t mutex, DWORD dwMilliseconds = INFINITE);
|
int Wait (pthread_mutex_t mutex, DWORD dwMilliseconds = INFINITE);
|
||||||
void fixup_after_fork ();
|
|
||||||
|
|
||||||
pthread_cond (pthread_condattr *);
|
pthread_cond (pthread_condattr *);
|
||||||
~pthread_cond ();
|
~pthread_cond ();
|
||||||
|
|
||||||
|
class pthread_cond * next;
|
||||||
|
static void fixup_after_fork ()
|
||||||
|
{
|
||||||
|
conds.forEach (&pthread_cond::FixupAfterFork);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixupAfterFork ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static List<pthread_cond> conds;
|
||||||
static nativeMutex condInitializationLock;
|
static nativeMutex condInitializationLock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -562,14 +571,20 @@ public:
|
||||||
pthread_cond condReaders;
|
pthread_cond condReaders;
|
||||||
pthread_cond condWriters;
|
pthread_cond condWriters;
|
||||||
|
|
||||||
class pthread_rwlock * next;
|
|
||||||
|
|
||||||
void fixup_after_fork ();
|
|
||||||
|
|
||||||
pthread_rwlock (pthread_rwlockattr *);
|
pthread_rwlock (pthread_rwlockattr *);
|
||||||
~pthread_rwlock ();
|
~pthread_rwlock ();
|
||||||
|
|
||||||
|
class pthread_rwlock * next;
|
||||||
|
static void fixup_after_fork ()
|
||||||
|
{
|
||||||
|
rwlocks.forEach (&pthread_rwlock::FixupAfterFork);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixupAfterFork ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static List<pthread_rwlock> rwlocks;
|
||||||
|
|
||||||
void addReader (struct RWLOCK_READER *rd);
|
void addReader (struct RWLOCK_READER *rd);
|
||||||
void removeReader (struct RWLOCK_READER *rd);
|
void removeReader (struct RWLOCK_READER *rd);
|
||||||
struct RWLOCK_READER *lookupReader (pthread_t thread);
|
struct RWLOCK_READER *lookupReader (pthread_t thread);
|
||||||
|
@ -600,16 +615,25 @@ public:
|
||||||
static int post (sem_t * sem);
|
static int post (sem_t * sem);
|
||||||
|
|
||||||
HANDLE win32_obj_id;
|
HANDLE win32_obj_id;
|
||||||
class semaphore * next;
|
|
||||||
int shared;
|
int shared;
|
||||||
long currentvalue;
|
long currentvalue;
|
||||||
void Wait ();
|
void Wait ();
|
||||||
void Post ();
|
void Post ();
|
||||||
int TryWait ();
|
int TryWait ();
|
||||||
void fixup_after_fork ();
|
|
||||||
|
|
||||||
semaphore (int, unsigned int);
|
semaphore (int, unsigned int);
|
||||||
~semaphore ();
|
~semaphore ();
|
||||||
|
|
||||||
|
class semaphore * next;
|
||||||
|
static void fixup_after_fork ()
|
||||||
|
{
|
||||||
|
semaphores.forEach (&semaphore::FixupAfterFork);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixupAfterFork ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static List<semaphore> semaphores;
|
||||||
};
|
};
|
||||||
|
|
||||||
class callback
|
class callback
|
||||||
|
@ -634,12 +658,6 @@ public:
|
||||||
callback *pthread_child;
|
callback *pthread_child;
|
||||||
callback *pthread_parent;
|
callback *pthread_parent;
|
||||||
|
|
||||||
// lists of pthread objects. USE THREADSAFE INSERTS AND DELETES.
|
|
||||||
class pthread_mutex * mutexs;
|
|
||||||
class pthread_cond * conds;
|
|
||||||
class pthread_rwlock * rwlocks;
|
|
||||||
class semaphore * semaphores;
|
|
||||||
|
|
||||||
pthread_key reent_key;
|
pthread_key reent_key;
|
||||||
pthread_key thread_self_key;
|
pthread_key thread_self_key;
|
||||||
|
|
||||||
|
@ -650,7 +668,6 @@ public:
|
||||||
MTinterface () :
|
MTinterface () :
|
||||||
concurrency (0), threadcount (1),
|
concurrency (0), threadcount (1),
|
||||||
pthread_prepare (NULL), pthread_child (NULL), pthread_parent (NULL),
|
pthread_prepare (NULL), pthread_child (NULL), pthread_parent (NULL),
|
||||||
mutexs (NULL), conds (NULL), rwlocks (NULL), semaphores (NULL),
|
|
||||||
reent_key (NULL), thread_self_key (NULL)
|
reent_key (NULL), thread_self_key (NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue