aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2001-04-13 15:28:20 +0000
committerChristopher Faylor <me@cgf.cx>2001-04-13 15:28:20 +0000
commit39b6859a28b8b50d73fe6ae080ea42f4ef1bdea3 (patch)
tree6e6cc0afd7868c2a935f16c4e10a3d20ebf532b3 /winsup
parente61cead397205b61dafed0d725cf9dcd89aead76 (diff)
downloadnewlib-39b6859a28b8b50d73fe6ae080ea42f4ef1bdea3.zip
newlib-39b6859a28b8b50d73fe6ae080ea42f4ef1bdea3.tar.gz
newlib-39b6859a28b8b50d73fe6ae080ea42f4ef1bdea3.tar.bz2
* 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.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog13
-rw-r--r--winsup/cygwin/cygwin.din1
-rw-r--r--winsup/cygwin/fhandler.cc5
-rw-r--r--winsup/cygwin/fork.cc5
-rw-r--r--winsup/cygwin/pthread.cc6
-rw-r--r--winsup/cygwin/thread.cc118
-rw-r--r--winsup/cygwin/thread.h19
7 files changed, 163 insertions, 4 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index f94ec6e..451a0c9 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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>
* path.cc (add_ext_from_sym): New define evaluating `known'suffix'.
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index a94af5e..285f724 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -1076,6 +1076,7 @@ cygwin_attach_handle_to_fd
cygwin32_attach_handle_to_fd = cygwin_attach_handle_to_fd
cygwin_internal
cygwin32_internal = cygwin_internal
+pthread_atfork
pthread_attr_destroy
pthread_attr_getdetachstate
pthread_attr_getinheritsched
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index ff9a9df..df2fd22 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -370,9 +370,8 @@ fhandler_base::open (int flags, mode_t mode)
file_attributes,
0);
- syscall_printf ("%d = CreateFileA (%s, %p, %p, %p, %p, %p, 0)",
- x,
- get_win32_name (), access_, shared,
+ syscall_printf ("%p = CreateFileA (%s, %p, %p, %p, %p, %p, 0)",
+ x, get_win32_name (), access_, shared,
&sec_none, creation_distribution,
file_attributes);
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 6d6f10b..de85c1d 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -307,6 +307,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
/* Initialize signal/process handling */
sigproc_init ();
+ __pthread_atforkchild();
cygbench ("fork-child");
return 0;
}
@@ -597,6 +598,7 @@ out:
ForceCloseHandle (forker_finished);
forker_finished = NULL;
pi.hThread = NULL;
+ __pthread_atforkparent();
return forked->pid;
@@ -640,6 +642,9 @@ fork ()
return -1;
}
+ /* call the pthread_atfork prepare functions */
+ __pthread_atforkprepare();
+
void *esp;
__asm ("movl %%esp,%0": "=r" (esp));
diff --git a/winsup/cygwin/pthread.cc b/winsup/cygwin/pthread.cc
index c9f0bb2..74cce7c 100644
--- a/winsup/cygwin/pthread.cc
+++ b/winsup/cygwin/pthread.cc
@@ -30,6 +30,12 @@ pthread_once (pthread_once_t * once_control, void (*init_routine) (void))
}
int
+pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
+{
+ return __pthread_atfork(prepare, parent, child);
+}
+
+int
pthread_attr_init (pthread_attr_t * attr)
{
return __pthread_attr_init (attr);
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index e870c31..1bcfd4e 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -935,6 +935,124 @@ __pthread_testcancel (void)
* 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
__pthread_attr_init (pthread_attr_t * attr)
{
diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index 00c10b2..2b6e7d7 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -317,6 +317,13 @@ public:
~semaphore ();
};
+class callback
+{
+public:
+ void (*cb)(void);
+ class callback * next;
+};
+
class MTinterface
{
public:
@@ -333,14 +340,23 @@ public:
pthread mainthread;
pthread_key_destructor_list destructors;
+ callback *pthread_prepare;
+ callback *pthread_child;
+ callback *pthread_parent;
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"
{
@@ -350,6 +366,7 @@ void *thread_init_wrapper (void *);
int __pthread_create (pthread_t * thread, const pthread_attr_t * attr,
void *(*start_routine) (void *), void *arg);
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_destroy (pthread_attr_t * attr);