mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-28 12:05:47 +08:00
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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
@ -375,6 +382,8 @@ pthread::setTlsSelfPointer(pthread *thisThread)
|
|||||||
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),
|
||||||
@ -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
|
||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user