* fork.cc (fork_child): Call the __pthread_atforkchild function.
(fork_parent): Call the __pthread_atforkparent function. * cygwin.din: Export pthread_atfork. * thread.h (callback): New class. (MTinterface): Use it. * thread.cc (__pthread_atforkprepare): New function. (__pthread_atforkparent): New function. (__pthread_atforkchild): New function. (__pthread_atfork): New function. * pthread.cc (pthread_atfork): New function.
This commit is contained in:
parent
e61cead397
commit
39b6859a28
@ -1,3 +1,16 @@
|
|||||||
|
Fri Apr 13 2001 Robert Collins <rbtcollins@hotmail.com>
|
||||||
|
|
||||||
|
* fork.cc (fork_child): Call the __pthread_atforkchild function.
|
||||||
|
(fork_parent): Call the __pthread_atforkparent function.
|
||||||
|
* cygwin.din: Export pthread_atfork.
|
||||||
|
* thread.h (callback): New class.
|
||||||
|
(MTinterface): Use it.
|
||||||
|
* thread.cc (__pthread_atforkprepare): New function.
|
||||||
|
(__pthread_atforkparent): New function.
|
||||||
|
(__pthread_atforkchild): New function.
|
||||||
|
(__pthread_atfork): New function.
|
||||||
|
* pthread.cc (pthread_atfork): New function.
|
||||||
|
|
||||||
Fri Apr 13 9:52:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
Fri Apr 13 9:52:00 2001 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* path.cc (add_ext_from_sym): New define evaluating `known'suffix'.
|
* path.cc (add_ext_from_sym): New define evaluating `known'suffix'.
|
||||||
|
@ -1076,6 +1076,7 @@ cygwin_attach_handle_to_fd
|
|||||||
cygwin32_attach_handle_to_fd = cygwin_attach_handle_to_fd
|
cygwin32_attach_handle_to_fd = cygwin_attach_handle_to_fd
|
||||||
cygwin_internal
|
cygwin_internal
|
||||||
cygwin32_internal = cygwin_internal
|
cygwin32_internal = cygwin_internal
|
||||||
|
pthread_atfork
|
||||||
pthread_attr_destroy
|
pthread_attr_destroy
|
||||||
pthread_attr_getdetachstate
|
pthread_attr_getdetachstate
|
||||||
pthread_attr_getinheritsched
|
pthread_attr_getinheritsched
|
||||||
|
@ -370,9 +370,8 @@ fhandler_base::open (int flags, mode_t mode)
|
|||||||
file_attributes,
|
file_attributes,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
syscall_printf ("%d = CreateFileA (%s, %p, %p, %p, %p, %p, 0)",
|
syscall_printf ("%p = CreateFileA (%s, %p, %p, %p, %p, %p, 0)",
|
||||||
x,
|
x, get_win32_name (), access_, shared,
|
||||||
get_win32_name (), access_, shared,
|
|
||||||
&sec_none, creation_distribution,
|
&sec_none, creation_distribution,
|
||||||
file_attributes);
|
file_attributes);
|
||||||
|
|
||||||
|
@ -307,6 +307,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
|
|||||||
|
|
||||||
/* Initialize signal/process handling */
|
/* Initialize signal/process handling */
|
||||||
sigproc_init ();
|
sigproc_init ();
|
||||||
|
__pthread_atforkchild();
|
||||||
cygbench ("fork-child");
|
cygbench ("fork-child");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -597,6 +598,7 @@ out:
|
|||||||
ForceCloseHandle (forker_finished);
|
ForceCloseHandle (forker_finished);
|
||||||
forker_finished = NULL;
|
forker_finished = NULL;
|
||||||
pi.hThread = NULL;
|
pi.hThread = NULL;
|
||||||
|
__pthread_atforkparent();
|
||||||
|
|
||||||
return forked->pid;
|
return forked->pid;
|
||||||
|
|
||||||
@ -640,6 +642,9 @@ fork ()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* call the pthread_atfork prepare functions */
|
||||||
|
__pthread_atforkprepare();
|
||||||
|
|
||||||
void *esp;
|
void *esp;
|
||||||
__asm ("movl %%esp,%0": "=r" (esp));
|
__asm ("movl %%esp,%0": "=r" (esp));
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void))
|
|||||||
return __pthread_once (once_control, init_routine);
|
return __pthread_once (once_control, init_routine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
|
||||||
|
{
|
||||||
|
return __pthread_atfork(prepare, parent, child);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pthread_attr_init (pthread_attr_t * attr)
|
pthread_attr_init (pthread_attr_t * attr)
|
||||||
{
|
{
|
||||||
|
@ -935,6 +935,124 @@ __pthread_testcancel (void)
|
|||||||
* does something*/
|
* does something*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Races in pthread_atfork:
|
||||||
|
* We are race safe in that any additions to the lists are made via
|
||||||
|
* InterlockedExchangePointer.
|
||||||
|
* However, if the user application doesn't perform syncronisation of some sort
|
||||||
|
* It's not guaranteed that a near simultaneous call to pthread_atfork and fork
|
||||||
|
* will result in the new atfork handlers being calls.
|
||||||
|
* More rigorous internal syncronisation isn't needed as the user program isn't
|
||||||
|
* guaranteeing their own state.
|
||||||
|
*
|
||||||
|
* as far as multiple calls to pthread_atfork, the worst case is simultaneous calls
|
||||||
|
* will result in an indeterminate order for parent and child calls (what gets inserted
|
||||||
|
* first isn't guaranteed.)
|
||||||
|
*
|
||||||
|
* There is one potential race... Does the result of InterlockedExchangePointer
|
||||||
|
* get committed to the return location _before_ any context switches can occur?
|
||||||
|
* If yes, we're safe, if no, we're not.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
__pthread_atforkprepare(void)
|
||||||
|
{
|
||||||
|
callback *cb=MT_INTERFACE->pthread_prepare;
|
||||||
|
while (cb)
|
||||||
|
{
|
||||||
|
cb->cb();
|
||||||
|
cb=cb->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__pthread_atforkparent(void)
|
||||||
|
{
|
||||||
|
callback *cb=MT_INTERFACE->pthread_parent;
|
||||||
|
while (cb)
|
||||||
|
{
|
||||||
|
cb->cb();
|
||||||
|
cb=cb->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__pthread_atforkchild(void)
|
||||||
|
{
|
||||||
|
callback *cb=MT_INTERFACE->pthread_child;
|
||||||
|
while (cb)
|
||||||
|
{
|
||||||
|
cb->cb();
|
||||||
|
cb=cb->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: implement InterlockExchangePointer and get rid of the silly typecasts below
|
||||||
|
*/
|
||||||
|
#define InterlockedExchangePointer InterlockedExchange
|
||||||
|
|
||||||
|
/* Register a set of functions to run before and after fork.
|
||||||
|
* prepare calls are called in LI-FC order.
|
||||||
|
* parent and child calls are called in FI-FC order.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
__pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
|
||||||
|
{
|
||||||
|
callback * prepcb=NULL, * parentcb=NULL, * childcb=NULL;
|
||||||
|
if (prepare)
|
||||||
|
{
|
||||||
|
prepcb = new callback;
|
||||||
|
if (!prepcb)
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
if (parent)
|
||||||
|
{
|
||||||
|
parentcb = new callback;
|
||||||
|
if (!parentcb)
|
||||||
|
{
|
||||||
|
if (prepcb)
|
||||||
|
delete prepcb;
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (child)
|
||||||
|
{
|
||||||
|
childcb = new callback;
|
||||||
|
if (!childcb)
|
||||||
|
{
|
||||||
|
if (prepcb)
|
||||||
|
delete prepcb;
|
||||||
|
if (parentcb)
|
||||||
|
delete parentcb;
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prepcb)
|
||||||
|
{
|
||||||
|
prepcb->cb = prepare;
|
||||||
|
prepcb->next=(callback *)InterlockedExchangePointer((LONG *) &MT_INTERFACE->pthread_prepare, (long int) prepcb);
|
||||||
|
}
|
||||||
|
if (parentcb)
|
||||||
|
{
|
||||||
|
parentcb->cb = parent;
|
||||||
|
callback ** t = &MT_INTERFACE->pthread_parent;
|
||||||
|
while (*t)
|
||||||
|
t = &(*t)->next;
|
||||||
|
/* t = pointer to last next in the list */
|
||||||
|
parentcb->next=(callback *)InterlockedExchangePointer((LONG *)t, (long int) parentcb);
|
||||||
|
}
|
||||||
|
if (childcb)
|
||||||
|
{
|
||||||
|
childcb->cb = child;
|
||||||
|
callback ** t = &MT_INTERFACE->pthread_child;
|
||||||
|
while (*t)
|
||||||
|
t = &(*t)->next;
|
||||||
|
/* t = pointer to last next in the list */
|
||||||
|
childcb->next=(callback *)InterlockedExchangePointer((LONG *)t, (long int) childcb);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
__pthread_attr_init (pthread_attr_t * attr)
|
__pthread_attr_init (pthread_attr_t * attr)
|
||||||
{
|
{
|
||||||
|
@ -317,6 +317,13 @@ public:
|
|||||||
~semaphore ();
|
~semaphore ();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class callback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void (*cb)(void);
|
||||||
|
class callback * next;
|
||||||
|
};
|
||||||
|
|
||||||
class MTinterface
|
class MTinterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -333,14 +340,23 @@ public:
|
|||||||
pthread mainthread;
|
pthread mainthread;
|
||||||
|
|
||||||
pthread_key_destructor_list destructors;
|
pthread_key_destructor_list destructors;
|
||||||
|
callback *pthread_prepare;
|
||||||
|
callback *pthread_child;
|
||||||
|
callback *pthread_parent;
|
||||||
|
|
||||||
void Init (int);
|
void Init (int);
|
||||||
|
|
||||||
MTinterface ():reent_index (0), indexallocated (0)
|
MTinterface ():reent_index (0), indexallocated (0)
|
||||||
{
|
{
|
||||||
|
pthread_prepare = NULL;
|
||||||
|
pthread_child = NULL;
|
||||||
|
pthread_parent = NULL;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void __pthread_atforkprepare(void);
|
||||||
|
void __pthread_atforkparent(void);
|
||||||
|
void __pthread_atforkchild(void);
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
@ -350,6 +366,7 @@ void *thread_init_wrapper (void *);
|
|||||||
int __pthread_create (pthread_t * thread, const pthread_attr_t * attr,
|
int __pthread_create (pthread_t * thread, const pthread_attr_t * attr,
|
||||||
void *(*start_routine) (void *), void *arg);
|
void *(*start_routine) (void *), void *arg);
|
||||||
int __pthread_once (pthread_once_t *, void (*)(void));
|
int __pthread_once (pthread_once_t *, void (*)(void));
|
||||||
|
int __pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
|
||||||
|
|
||||||
int __pthread_attr_init (pthread_attr_t * attr);
|
int __pthread_attr_init (pthread_attr_t * attr);
|
||||||
int __pthread_attr_destroy (pthread_attr_t * attr);
|
int __pthread_attr_destroy (pthread_attr_t * attr);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user