2002-09-17 Robert Collins <rbtcollins@hotmail.com>
This work inspires by Thomas Pfaff's pthread_fork patch (1). * fork.cc (fork_child): Remove MTinterface fixup call, it's adsorbed by pthread::atforkchild. Rename __pthread_atforkchild to pthread::atforkchild to give access to private members. (fork_parent): Rename __pthread_atforkparent to pthread::atforkparent to give it access to private members. Ditto for __pthread_atforkprepare. * thread.cc: Fix some formatting problems throughout. (MTinterface::fixup_before_fork): Implement. (MTinterface::fixup_after_fork): Fix pthread_keys. (pthread_key::keys): Implement. (pthread_key::fixup_before_fork): Ditto. (pthread_key::fixup_after_fork): Ditto. (pthread_key::pthread_key): Add to pthread_key::keys. (pthread_key::~pthread_key): Remove from pthread_key::keys. (pthread_key::saveKeyToBuffer): Implement. (pthread_key::recreateKeyFromBuffer): Ditto. (pthread::atforkprepare): Prepare all MT classes for fork. (pthread::atforkchild): And fix them up afterwards. * thread.h (pthread_key): Buffer the key value during fork in fork_buf. List the keys needing to be fixed up in a linked list with head pthread_key::keys. (pthread): Move atfork cygwin internal calls into the class. (MTInterface): Provide a fixup_before_fork for objecst that need to save state. (__pthread_atforkprepare): Remove. (__pthread_atforkparent): Remove. (__pthread_atforkchild): Remove.
This commit is contained in:
parent
cbb704cf60
commit
f1f1379560
|
@ -1,3 +1,36 @@
|
||||||
|
2002-09-17 Robert Collins <rbtcollins@hotmail.com>
|
||||||
|
|
||||||
|
This work inspires by Thomas Pfaff's pthread_fork patch (1).
|
||||||
|
* fork.cc (fork_child): Remove MTinterface fixup call, it's
|
||||||
|
adsorbed by pthread::atforkchild.
|
||||||
|
Rename __pthread_atforkchild to pthread::atforkchild to give
|
||||||
|
access to private members.
|
||||||
|
(fork_parent): Rename __pthread_atforkparent to
|
||||||
|
pthread::atforkparent to give it access to private members.
|
||||||
|
Ditto for __pthread_atforkprepare.
|
||||||
|
* thread.cc: Fix some formatting problems throughout.
|
||||||
|
(MTinterface::fixup_before_fork): Implement.
|
||||||
|
(MTinterface::fixup_after_fork): Fix pthread_keys.
|
||||||
|
(pthread_key::keys): Implement.
|
||||||
|
(pthread_key::fixup_before_fork): Ditto.
|
||||||
|
(pthread_key::fixup_after_fork): Ditto.
|
||||||
|
(pthread_key::pthread_key): Add to pthread_key::keys.
|
||||||
|
(pthread_key::~pthread_key): Remove from pthread_key::keys.
|
||||||
|
(pthread_key::saveKeyToBuffer): Implement.
|
||||||
|
(pthread_key::recreateKeyFromBuffer): Ditto.
|
||||||
|
(pthread::atforkprepare): Prepare all MT classes for fork.
|
||||||
|
(pthread::atforkchild): And fix them up afterwards.
|
||||||
|
* thread.h (pthread_key): Buffer the key value during
|
||||||
|
fork in fork_buf.
|
||||||
|
List the keys needing to be fixed up in a linked list with
|
||||||
|
head pthread_key::keys.
|
||||||
|
(pthread): Move atfork cygwin internal calls into the class.
|
||||||
|
(MTInterface): Provide a fixup_before_fork for objecst that
|
||||||
|
need to save state.
|
||||||
|
(__pthread_atforkprepare): Remove.
|
||||||
|
(__pthread_atforkparent): Remove.
|
||||||
|
(__pthread_atforkchild): Remove.
|
||||||
|
|
||||||
2002-09-16 Christopher Faylor <cgf@redhat.com>
|
2002-09-16 Christopher Faylor <cgf@redhat.com>
|
||||||
|
|
||||||
* init.cc: Cleanup slightly and remove obsolete code.
|
* init.cc: Cleanup slightly and remove obsolete code.
|
||||||
|
|
|
@ -313,10 +313,8 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
|
||||||
if ((*t)->clear_on_fork ())
|
if ((*t)->clear_on_fork ())
|
||||||
(*t)->set ();
|
(*t)->set ();
|
||||||
|
|
||||||
user_data->threadinterface->fixup_after_fork ();
|
|
||||||
|
|
||||||
wait_for_sigthread ();
|
wait_for_sigthread ();
|
||||||
__pthread_atforkchild ();
|
pthread::atforkchild ();
|
||||||
cygbench ("fork-child");
|
cygbench ("fork-child");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -354,8 +352,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
|
||||||
DWORD rc;
|
DWORD rc;
|
||||||
PROCESS_INFORMATION pi = {0, NULL, 0, 0};
|
PROCESS_INFORMATION pi = {0, NULL, 0, 0};
|
||||||
|
|
||||||
/* call the pthread_atfork prepare functions */
|
pthread::atforkprepare ();
|
||||||
__pthread_atforkprepare ();
|
|
||||||
|
|
||||||
subproc_init ();
|
subproc_init ();
|
||||||
|
|
||||||
|
@ -601,7 +598,7 @@ fork_parent (HANDLE& hParent, dll *&first_dll,
|
||||||
ForceCloseHandle (forker_finished);
|
ForceCloseHandle (forker_finished);
|
||||||
forker_finished = NULL;
|
forker_finished = NULL;
|
||||||
pi.hThread = NULL;
|
pi.hThread = NULL;
|
||||||
__pthread_atforkparent ();
|
pthread::atforkparent ();
|
||||||
|
|
||||||
return forked->pid;
|
return forked->pid;
|
||||||
|
|
||||||
|
|
|
@ -294,7 +294,7 @@ MTinterface::Init (int forked)
|
||||||
concurrency = 0;
|
concurrency = 0;
|
||||||
threadcount = 1; /*1 current thread when Init occurs.*/
|
threadcount = 1; /*1 current thread when Init occurs.*/
|
||||||
|
|
||||||
pthread::initMainThread(&mainthread, myself->hProcess);
|
pthread::initMainThread (&mainthread, myself->hProcess);
|
||||||
|
|
||||||
if (forked)
|
if (forked)
|
||||||
return;
|
return;
|
||||||
|
@ -314,10 +314,17 @@ MTinterface::Init (int forked)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MTinterface::fixup_before_fork (void)
|
||||||
|
{
|
||||||
|
pthread_key::fixup_before_fork ();
|
||||||
|
}
|
||||||
|
|
||||||
/* This function is called from a single threaded process */
|
/* This function is called from a single threaded process */
|
||||||
void
|
void
|
||||||
MTinterface::fixup_after_fork (void)
|
MTinterface::fixup_after_fork (void)
|
||||||
{
|
{
|
||||||
|
pthread_key::fixup_after_fork ();
|
||||||
pthread_mutex *mutex = mutexs;
|
pthread_mutex *mutex = mutexs;
|
||||||
debug_printf ("mutexs is %x",mutexs);
|
debug_printf ("mutexs is %x",mutexs);
|
||||||
while (mutex)
|
while (mutex)
|
||||||
|
@ -345,11 +352,11 @@ MTinterface::fixup_after_fork (void)
|
||||||
|
|
||||||
/* static methods */
|
/* static methods */
|
||||||
void
|
void
|
||||||
pthread::initMainThread(pthread *mainThread, HANDLE win32_obj_id)
|
pthread::initMainThread (pthread *mainThread, HANDLE win32_obj_id)
|
||||||
{
|
{
|
||||||
mainThread->win32_obj_id = win32_obj_id;
|
mainThread->win32_obj_id = win32_obj_id;
|
||||||
mainThread->setThreadIdtoCurrent ();
|
mainThread->setThreadIdtoCurrent ();
|
||||||
setTlsSelfPointer(mainThread);
|
setTlsSelfPointer (mainThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread *
|
pthread *
|
||||||
|
@ -362,23 +369,25 @@ pthread::self ()
|
||||||
temp->precreate (NULL);
|
temp->precreate (NULL);
|
||||||
if (!temp->magic) {
|
if (!temp->magic) {
|
||||||
delete temp;
|
delete temp;
|
||||||
return pthreadNull::getNullpthread();
|
return pthreadNull::getNullpthread ();
|
||||||
}
|
}
|
||||||
temp->postcreate ();
|
temp->postcreate ();
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread::setTlsSelfPointer(pthread *thisThread)
|
pthread::setTlsSelfPointer (pthread *thisThread)
|
||||||
{
|
{
|
||||||
/*the OS doesn't check this for <= 64 Tls entries (pre win2k) */
|
/*the OS doesn't check this for <= 64 Tls entries (pre win2k) */
|
||||||
TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thisThread);
|
TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thisThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* member methods */
|
/* member methods */
|
||||||
pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
|
pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
|
||||||
cancelstate (0), canceltype (0), cancel_event(0),
|
cancelstate (0), canceltype (0), cancel_event (0),
|
||||||
joiner (NULL), cleanup_stack(NULL)
|
joiner (NULL), cleanup_stack (NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,7 +489,7 @@ pthread::exit (void *value_ptr)
|
||||||
|
|
||||||
mutex.Lock ();
|
mutex.Lock ();
|
||||||
// cleanup if thread is in detached state and not joined
|
// cleanup if thread is in detached state and not joined
|
||||||
if( __pthread_equal(&joiner, &thread ) )
|
if (__pthread_equal (&joiner, &thread ) )
|
||||||
delete this;
|
delete this;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -489,7 +498,7 @@ pthread::exit (void *value_ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent DLL_THREAD_DETACH Attempting to clean us up */
|
/* Prevent DLL_THREAD_DETACH Attempting to clean us up */
|
||||||
setTlsSelfPointer(0);
|
setTlsSelfPointer (0);
|
||||||
|
|
||||||
if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0)
|
if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0)
|
||||||
::exit (0);
|
::exit (0);
|
||||||
|
@ -514,7 +523,7 @@ pthread::cancel (void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (__pthread_equal(&thread, &self))
|
else if (__pthread_equal (&thread, &self))
|
||||||
{
|
{
|
||||||
mutex.UnLock ();
|
mutex.UnLock ();
|
||||||
cancel_self ();
|
cancel_self ();
|
||||||
|
@ -716,14 +725,14 @@ pthread::testcancel (void)
|
||||||
if (cancelstate == PTHREAD_CANCEL_DISABLE)
|
if (cancelstate == PTHREAD_CANCEL_DISABLE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( WAIT_OBJECT_0 == WaitForSingleObject (cancel_event, 0 ) )
|
if (WAIT_OBJECT_0 == WaitForSingleObject (cancel_event, 0 ) )
|
||||||
cancel_self ();
|
cancel_self ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread::static_cancel_self (void)
|
pthread::static_cancel_self (void)
|
||||||
{
|
{
|
||||||
pthread::self()->cancel_self ();
|
pthread::self ()->cancel_self ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -776,7 +785,7 @@ pthread::push_cleanup_handler (__pthread_cleanup_handler *handler)
|
||||||
// TODO: do it?
|
// TODO: do it?
|
||||||
api_fatal ("Attempt to push a cleanup handler across threads");
|
api_fatal ("Attempt to push a cleanup handler across threads");
|
||||||
handler->next = cleanup_stack;
|
handler->next = cleanup_stack;
|
||||||
InterlockedExchangePointer( &cleanup_stack, handler );
|
InterlockedExchangePointer (&cleanup_stack, handler );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -808,13 +817,13 @@ pthread::pop_all_cleanup_handlers ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread::cancel_self()
|
pthread::cancel_self ()
|
||||||
{
|
{
|
||||||
exit (PTHREAD_CANCELED);
|
exit (PTHREAD_CANCELED);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
pthread::getThreadId()
|
pthread::getThreadId ()
|
||||||
{
|
{
|
||||||
return thread_id;
|
return thread_id;
|
||||||
}
|
}
|
||||||
|
@ -1018,6 +1027,35 @@ pthread_cond::fixup_after_fork ()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* pthread_key */
|
||||||
|
/* static members */
|
||||||
|
pthread_key *pthread_key::keys = NULL;
|
||||||
|
|
||||||
|
void
|
||||||
|
pthread_key::fixup_before_fork ()
|
||||||
|
{
|
||||||
|
pthread_key *key = keys;
|
||||||
|
debug_printf ("keys is %x",keys);
|
||||||
|
while (key)
|
||||||
|
{
|
||||||
|
key->saveKeyToBuffer ();
|
||||||
|
key = key->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pthread_key::fixup_after_fork ()
|
||||||
|
{
|
||||||
|
pthread_key *key = keys;
|
||||||
|
debug_printf ("keys is %x",keys);
|
||||||
|
while (key)
|
||||||
|
{
|
||||||
|
key->recreateKeyFromBuffer ();
|
||||||
|
key = key->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* non-static members */
|
||||||
|
|
||||||
pthread_key::pthread_key (void (*destructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC)
|
pthread_key::pthread_key (void (*destructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC)
|
||||||
{
|
{
|
||||||
|
@ -1029,6 +1067,8 @@ pthread_key::pthread_key (void (*destructor) (void *)):verifyable_object (PTHREA
|
||||||
MT_INTERFACE->destructors.
|
MT_INTERFACE->destructors.
|
||||||
Insert (new pthread_key_destructor (destructor, this));
|
Insert (new pthread_key_destructor (destructor, this));
|
||||||
}
|
}
|
||||||
|
/* threadsafe addition is easy */
|
||||||
|
next = (pthread_key *) InterlockedExchangePointer (&keys, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_key::~pthread_key ()
|
pthread_key::~pthread_key ()
|
||||||
|
@ -1036,6 +1076,18 @@ pthread_key::~pthread_key ()
|
||||||
if (pthread_key_destructor *dest = MT_INTERFACE->destructors.Remove (this))
|
if (pthread_key_destructor *dest = MT_INTERFACE->destructors.Remove (this))
|
||||||
delete dest;
|
delete dest;
|
||||||
TlsFree (dwTlsIndex);
|
TlsFree (dwTlsIndex);
|
||||||
|
|
||||||
|
/* I'm not 100% sure the next bit is threadsafe. I think it is... */
|
||||||
|
if (keys == this)
|
||||||
|
InterlockedExchangePointer (keys, this->next);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pthread_key *tempkey = keys;
|
||||||
|
while (tempkey->next && tempkey->next != this)
|
||||||
|
tempkey = tempkey->next;
|
||||||
|
/* but there may be a race between the loop above and this statement */
|
||||||
|
InterlockedExchangePointer (&tempkey->next, this->next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1053,6 +1105,21 @@ pthread_key::get ()
|
||||||
return TlsGetValue (dwTlsIndex);
|
return TlsGetValue (dwTlsIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pthread_key::saveKeyToBuffer ()
|
||||||
|
{
|
||||||
|
fork_buf = get ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pthread_key::recreateKeyFromBuffer ()
|
||||||
|
{
|
||||||
|
dwTlsIndex = TlsAlloc ();
|
||||||
|
if (dwTlsIndex == TLS_OUT_OF_INDEXES)
|
||||||
|
api_fatal ("pthread_key::recreateKeyFromBuffer () failed to reallocate Tls storage");
|
||||||
|
set (fork_buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*pshared mutexs:
|
/*pshared mutexs:
|
||||||
|
|
||||||
* REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
|
* REMOVED FROM CURRENT. These can be reinstated with the daemon, when all the
|
||||||
|
@ -1311,7 +1378,7 @@ pthread::thread_init_wrapper (void *_arg)
|
||||||
pthread *thread = (pthread *) _arg;
|
pthread *thread = (pthread *) _arg;
|
||||||
struct __reent_t local_reent;
|
struct __reent_t local_reent;
|
||||||
struct _winsup_t local_winsup;
|
struct _winsup_t local_winsup;
|
||||||
struct _reent local_clib = _REENT_INIT(local_clib);
|
struct _reent local_clib = _REENT_INIT (local_clib);
|
||||||
|
|
||||||
struct sigaction _sigs[NSIG];
|
struct sigaction _sigs[NSIG];
|
||||||
sigset_t _sig_mask; /*one set for everything to ignore. */
|
sigset_t _sig_mask; /*one set for everything to ignore. */
|
||||||
|
@ -1333,7 +1400,7 @@ pthread::thread_init_wrapper (void *_arg)
|
||||||
if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent))
|
if (!TlsSetValue (MT_INTERFACE->reent_index, &local_reent))
|
||||||
system_printf ("local storage for thread couldn't be set");
|
system_printf ("local storage for thread couldn't be set");
|
||||||
|
|
||||||
setTlsSelfPointer(thread);
|
setTlsSelfPointer (thread);
|
||||||
|
|
||||||
thread->mutex.Lock ();
|
thread->mutex.Lock ();
|
||||||
// if thread is detached force cleanup on exit
|
// if thread is detached force cleanup on exit
|
||||||
|
@ -1448,8 +1515,10 @@ __pthread_cancel (pthread_t thread)
|
||||||
*If yes, we're safe, if no, we're not.
|
*If yes, we're safe, if no, we're not.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
__pthread_atforkprepare (void)
|
pthread::atforkprepare (void)
|
||||||
{
|
{
|
||||||
|
MT_INTERFACE->fixup_before_fork ();
|
||||||
|
|
||||||
callback *cb = MT_INTERFACE->pthread_prepare;
|
callback *cb = MT_INTERFACE->pthread_prepare;
|
||||||
while (cb)
|
while (cb)
|
||||||
{
|
{
|
||||||
|
@ -1459,7 +1528,7 @@ __pthread_atforkprepare (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
__pthread_atforkparent (void)
|
pthread::atforkparent (void)
|
||||||
{
|
{
|
||||||
callback *cb = MT_INTERFACE->pthread_parent;
|
callback *cb = MT_INTERFACE->pthread_parent;
|
||||||
while (cb)
|
while (cb)
|
||||||
|
@ -1470,8 +1539,10 @@ __pthread_atforkparent (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
__pthread_atforkchild (void)
|
pthread::atforkchild (void)
|
||||||
{
|
{
|
||||||
|
MT_INTERFACE->fixup_after_fork ();
|
||||||
|
|
||||||
callback *cb = MT_INTERFACE->pthread_child;
|
callback *cb = MT_INTERFACE->pthread_child;
|
||||||
while (cb)
|
while (cb)
|
||||||
{
|
{
|
||||||
|
@ -1713,12 +1784,12 @@ __pthread_join (pthread_t *thread, void **return_val)
|
||||||
if (!pthread::isGoodObject (thread))
|
if (!pthread::isGoodObject (thread))
|
||||||
return ESRCH;
|
return ESRCH;
|
||||||
|
|
||||||
if (__pthread_equal(thread,&joiner))
|
if (__pthread_equal (thread,&joiner))
|
||||||
return EDEADLK;
|
return EDEADLK;
|
||||||
|
|
||||||
(*thread)->mutex.Lock ();
|
(*thread)->mutex.Lock ();
|
||||||
|
|
||||||
if((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
|
if ((*thread)->attr.joinable == PTHREAD_CREATE_DETACHED)
|
||||||
{
|
{
|
||||||
(*thread)->mutex.UnLock ();
|
(*thread)->mutex.UnLock ();
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
@ -2462,20 +2533,20 @@ __sem_post (sem_t *sem)
|
||||||
|
|
||||||
/* pthreadNull */
|
/* pthreadNull */
|
||||||
pthread *
|
pthread *
|
||||||
pthreadNull::getNullpthread()
|
pthreadNull::getNullpthread ()
|
||||||
{
|
{
|
||||||
/* because of weird entry points */
|
/* because of weird entry points */
|
||||||
_instance.magic = 0;
|
_instance.magic = 0;
|
||||||
return &_instance;
|
return &_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthreadNull::pthreadNull()
|
pthreadNull::pthreadNull ()
|
||||||
{
|
{
|
||||||
/* Mark ourselves as invalid */
|
/* Mark ourselves as invalid */
|
||||||
magic = 0;
|
magic = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthreadNull::~pthreadNull()
|
pthreadNull::~pthreadNull ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2522,7 +2593,7 @@ pthreadNull::pop_cleanup_handler (int const execute)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
unsigned long
|
unsigned long
|
||||||
pthreadNull::getsequence_np()
|
pthreadNull::getsequence_np ()
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,11 +178,21 @@ class pthread_key:public verifyable_object
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DWORD dwTlsIndex;
|
DWORD dwTlsIndex;
|
||||||
|
void *fork_buf;
|
||||||
|
class pthread_key *next;
|
||||||
|
|
||||||
int set (const void *);
|
int set (const void *);
|
||||||
void *get ();
|
void *get ();
|
||||||
|
|
||||||
pthread_key (void (*)(void *));
|
pthread_key (void (*)(void *));
|
||||||
~pthread_key ();
|
~pthread_key ();
|
||||||
|
static void fixup_before_fork();
|
||||||
|
static void fixup_after_fork();
|
||||||
|
private:
|
||||||
|
// lists of objects. USE THREADSAFE INSERTS AND DELETES.
|
||||||
|
static pthread_key * keys;
|
||||||
|
void saveKeyToBuffer ();
|
||||||
|
void recreateKeyFromBuffer ();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FIXME: test using multiple inheritance and merging key_destructor into pthread_key
|
/* FIXME: test using multiple inheritance and merging key_destructor into pthread_key
|
||||||
|
@ -281,6 +291,9 @@ public:
|
||||||
|
|
||||||
static void initMainThread(pthread *, HANDLE);
|
static void initMainThread(pthread *, HANDLE);
|
||||||
static bool isGoodObject(pthread_t *);
|
static bool isGoodObject(pthread_t *);
|
||||||
|
static void atforkprepare();
|
||||||
|
static void atforkparent();
|
||||||
|
static void atforkchild();
|
||||||
|
|
||||||
virtual void exit (void *value_ptr);
|
virtual void exit (void *value_ptr);
|
||||||
|
|
||||||
|
@ -421,12 +434,13 @@ public:
|
||||||
callback *pthread_child;
|
callback *pthread_child;
|
||||||
callback *pthread_parent;
|
callback *pthread_parent;
|
||||||
|
|
||||||
// list of mutex's. USE THREADSAFE INSERTS AND DELETES.
|
// lists of pthread objects. USE THREADSAFE INSERTS AND DELETES.
|
||||||
class pthread_mutex * mutexs;
|
class pthread_mutex * mutexs;
|
||||||
class pthread_cond * conds;
|
class pthread_cond * conds;
|
||||||
class semaphore * semaphores;
|
class semaphore * semaphores;
|
||||||
|
|
||||||
void Init (int);
|
void Init (int);
|
||||||
|
void fixup_before_fork (void);
|
||||||
void fixup_after_fork (void);
|
void fixup_after_fork (void);
|
||||||
|
|
||||||
MTinterface ():reent_index (0), indexallocated (0), threadcount (1)
|
MTinterface ():reent_index (0), indexallocated (0), threadcount (1)
|
||||||
|
@ -437,10 +451,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void __pthread_atforkprepare(void);
|
|
||||||
void __pthread_atforkparent(void);
|
|
||||||
void __pthread_atforkchild(void);
|
|
||||||
|
|
||||||
/* Cancellation */
|
/* Cancellation */
|
||||||
int __pthread_cancel (pthread_t thread);
|
int __pthread_cancel (pthread_t thread);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue