]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Update.
authorUlrich Drepper <drepper@redhat.com>
Mon, 8 May 2000 00:03:03 +0000 (00:03 +0000)
committerUlrich Drepper <drepper@redhat.com>
Mon, 8 May 2000 00:03:03 +0000 (00:03 +0000)
2000-05-07  H.J. Lu  <hjl@gnu.org>

* csu/initfini.c: Moved to ....
* sysdeps/generic/initfini.c: ...here.

* csu/Makefile (initfini.c): Set vpath to $(full_config_sysdirs).

ChangeLog
csu/Makefile
linuxthreads/ChangeLog
linuxthreads/internals.h
linuxthreads/linuxthreads.texi
linuxthreads/mutex.c
linuxthreads/ptfork.c
sysdeps/generic/initfini.c [moved from csu/initfini.c with 100% similarity]

index 7e145f15631b29aa311dd1470d5719d915c04c41..a955b275c4104177baa58291885095af12dbce0e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2000-05-07  H.J. Lu  <hjl@gnu.org>
+
+       * csu/initfini.c: Moved to ....
+       * sysdeps/generic/initfini.c: ...here.
+
+       * csu/Makefile (initfini.c): Set vpath to $(full_config_sysdirs).
+
 2000-05-07  Ulrich Drepper  <drepper@redhat.com>
 
        * manual/resource.texi: Document POSIX scheduling functions.
index 1fb2e8f96bcf853461b1ded67a13c86b19aa0e67..9937a9186d8ff4a6e4d9748bc6a3c44e2d993091 100644 (file)
@@ -85,6 +85,8 @@ $(objpfx)crt%.o: $(objpfx)crt%.S $(objpfx)defs.h
 
 CFLAGS-initfini.s = -g0 -fPIC -fno-inline-functions
 
+vpath initfini.c $(full_config_sysdirs)
+
 $(objpfx)initfini.s: initfini.c
        $(compile.c) -S $(CFLAGS-initfini.s) -finhibit-size-directive \
                $(patsubst -f%,-fno-%,$(exceptions)) -o $@
index 8a0310dadbf6a0bb6d73ad929af0738d8ecfafd6..551fbce21b5fa55f759a16189205fd9a936dadad 100644 (file)
@@ -1,3 +1,21 @@
+2000-05-06  Kaz Kylheku  <kaz@ashi.footprints.net>
+
+       * mutex.c (pthread_once): IN_PROGRESS state of pthread_once_t
+       object state is represented with additional bits which distinguish
+       whether that state was set up in the current process, or
+       in an ancestor process. If that state was set in an ancestor,
+       it means that a fork happened while thread was executing the init
+       function. In that case, the state is reset to NEVER.
+       * mutex.c (__pthread_once_fork_prepare): New function.
+       (__pthread_once_fork_child): Likewise
+       (__pthread_once_fork_parent): Likewise
+       (__pthread_reset_pthread_once): Removed.
+       * ptfork.c (__fork): Call new handlers in mutex.c.
+       * internals.h: Declarations of new mutex.c functions added.
+       Declaration of removed function deleted.
+       * linuxthreads.texi: Updated documentation about pthread_once
+       to clarify what happens under cancellation and forking.
+
 2000-05-06  Kaz Kylheku  <kaz@ashi.footprints.net>
 
        * internals.h: New thread manager request type, REQ_KICK.
index e4cda4b66c280569e7664f6c675aa177edb01c46..4d273f891750610e4d9458b46e84d0b751b32441 100644 (file)
@@ -414,7 +414,9 @@ int __pthread_manager(void *reqfd);
 int __pthread_manager_event(void *reqfd);
 void __pthread_manager_sighandler(int sig);
 void __pthread_reset_main_thread(void);
-void __pthread_reset_pthread_once(void);
+void __pthread_once_fork_prepare(void);
+void __pthread_once_fork_parent(void);
+void __pthread_once_fork_child(void);
 void __fresetlockfiles(void);
 void __pthread_manager_adjust_prio(int thread_prio);
 void __pthread_set_own_extricate_if(pthread_descr self, pthread_extricate_if *peif);
index 7a98103b3ea63d833b752ad8abaf2e881de55e15..2b3647aed015f600ca9dd899528007df43af22ae 100644 (file)
@@ -1368,6 +1368,15 @@ record that initialization has been performed. Subsequent calls to
 @code{pthread_once} with the same @code{once_control} argument do
 nothing.
 
+If a thread is cancelled while executing @var{init_routine}
+the state of the @var{once_control} variable is reset so that
+a future call to @code{pthread_once} will call the routine again.
+
+If the process forks while one or more threads are executing
+@code{pthread_once} initialization routines, the states of their respective
+@var{once_control} variables will appear to be reset in the child process so
+that if the child calls @code{pthread_once}, the routines will be executed.
+
 @code{pthread_once} always returns 0.
 @end deftypefun
 
index 4d9019ec4ec0d61bcc7e8b98f4c14bd569dd2d75..a42167cce0a7852ab263a6b4f39c22751ce60b60 100644 (file)
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include <sched.h>
 #include <stddef.h>
+#include <limits.h>
 #include "pthread.h"
 #include "internals.h"
 #include "spinlock.h"
@@ -170,6 +171,7 @@ weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np)
 
 static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER;
 static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER;
+static int fork_generation = 0;        /* Child process increments this after fork. */
 
 enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 };
 
@@ -199,14 +201,20 @@ int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
   state_changed = 0;
 
   pthread_mutex_lock(&once_masterlock);
+
+  /* If this object was left in an IN_PROGRESS state in a parent
+     process (indicated by stale generation field), reset it to NEVER. */
+  if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation)
+    *once_control = NEVER;
+
   /* If init_routine is being called from another routine, wait until
      it completes. */
-  while (*once_control == IN_PROGRESS) {
+  while ((*once_control & 3) == IN_PROGRESS) {
     pthread_cond_wait(&once_finished, &once_masterlock);
   }
   /* Here *once_control is stable and either NEVER or DONE. */
   if (*once_control == NEVER) {
-    *once_control = IN_PROGRESS;
+    *once_control = IN_PROGRESS | fork_generation;
     pthread_mutex_unlock(&once_masterlock);
     pthread_cleanup_push(pthread_once_cancelhandler, once_control);
     init_routine();
@@ -225,13 +233,31 @@ int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void))
 strong_alias (__pthread_once, pthread_once)
 
 /*
- * This is called in the child process after a fork to make
- * sure that the global mutex pthread_once is not held,
- * and that the condition variable is reset to an initial state.
+ * Handle the state of the pthread_once mechanism across forks.  The
+ * once_masterlock is acquired in the parent process prior to a fork to ensure
+ * that no thread is in the critical region protected by the lock.  After the
+ * fork, the lock is released. In the child, the lock and the condition
+ * variable are simply reset.  The child also increments its generation
+ * counter which lets pthread_once calls detect stale IN_PROGRESS states
+ * and reset them back to NEVER.
  */
 
-void __pthread_reset_pthread_once(void)
+void __pthread_once_fork_prepare(void)
+{
+  pthread_mutex_lock(&once_masterlock);
+}
+
+void __pthread_once_fork_parent(void)
+{
+  pthread_mutex_unlock(&once_masterlock);
+}
+
+void __pthread_once_fork_child(void)
 {
   pthread_mutex_init(&once_masterlock, NULL);
   pthread_cond_init(&once_finished, NULL);
+  if (fork_generation <= INT_MAX - 4)
+    fork_generation += 4;      /* leave least significant two bits zero */
+  else
+    fork_generation = 0;
 }
index 4cd883fd239b3da9d4abc1fd2d490fb0322e4430..cb6d46db8c095f33ca4a3b8bb55da367bf2746a3 100644 (file)
@@ -86,14 +86,16 @@ pid_t __fork(void)
   parent = pthread_atfork_parent;
   pthread_mutex_unlock(&pthread_atfork_lock);
   pthread_call_handlers(prepare);
+  __pthread_once_fork_prepare();
   pid = __libc_fork();
   if (pid == 0) {
     __pthread_reset_main_thread();
-    __pthread_reset_pthread_once();
     __fresetlockfiles();
     pthread_call_handlers(child);
+    __pthread_once_fork_child();
   } else {
     pthread_call_handlers(parent);
+    __pthread_once_fork_parent();
   }
   return pid;
 }
similarity index 100%
rename from csu/initfini.c
rename to sysdeps/generic/initfini.c