Update.
authorUlrich Drepper <drepper@redhat.com>
Fri, 28 Mar 2003 06:27:21 +0000 (06:27 +0000)
committerUlrich Drepper <drepper@redhat.com>
Fri, 28 Mar 2003 06:27:21 +0000 (06:27 +0000)
* sysdeps/unix/sysv/linux/kernel-posix-timers.h: Don't declare
__timer_helper_thread.  Declare __start_helper_thread, __helper_once,
and __helper_tid.
(struct timer): Remove th and bar field.
* sysdeps/unix/sysv/linux/timer_create.c (timer_create): Remove
debugging code.  Create only one helper thread.
* sysdeps/unix/sysv/linux/timer_delete.c (timer_delete): Don't kill
helper thread.
* sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread):
Renamed.  Define statically.  Use thread info from siginfo.
(__helper_once): New variable.
(__helper_tid): New variable.
(__reset_helper_control): New function.
(__start_helper_thread): New function.

nptl/ChangeLog
nptl/sysdeps/unix/sysv/linux/timer_create.c
nptl/sysdeps/unix/sysv/linux/timer_delete.c
nptl/sysdeps/unix/sysv/linux/timer_routines.c

index 9490f86..3bf0064 100644 (file)
@@ -1,5 +1,20 @@
 2003-03-27  Ulrich Drepper  <drepper@redhat.com>
 
+       * sysdeps/unix/sysv/linux/kernel-posix-timers.h: Don't declare
+       __timer_helper_thread.  Declare __start_helper_thread, __helper_once,
+       and __helper_tid.
+       (struct timer): Remove th and bar field.
+       * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Remove
+       debugging code.  Create only one helper thread.
+       * sysdeps/unix/sysv/linux/timer_delete.c (timer_delete): Don't kill
+       helper thread.
+       * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread):
+       Renamed.  Define statically.  Use thread info from siginfo.
+       (__helper_once): New variable.
+       (__helper_tid): New variable.
+       (__reset_helper_control): New function.
+       (__start_helper_thread): New function.
+
        * pthread_create.c (start_thread): Don't use setjmp inside
        __builtin_expect to work around gcc bug.
 
index 97ffb6d..915fa81 100644 (file)
@@ -26,6 +26,7 @@
 #include <sysdep.h>
 #include <kernel-features.h>
 #include <internaltypes.h>
+#include <nptl/pthreadP.h>
 #include "kernel-posix-timers.h"
 
 
@@ -138,12 +139,16 @@ timer_create (clock_id, evp, timerid)
          if (__no_posix_timers > 0)
 # endif
            {
-                 sigset_t ss;
-                 sigemptyset (&ss);
-                 sigaddset (&ss, TIMER_SIG);
-                 pthread_sigmask (SIG_BLOCK, &ss, NULL);
-             struct timer *newp;
+             /* Create the helper thread.  */
+             pthread_once (&__helper_once, __start_helper_thread);
+             if (__helper_tid == 0)
+               {
+                 /* No resources to start the helper thread.  */
+                 __set_errno (EAGAIN);
+                 return -1;
+               }
 
+             struct timer *newp;
              newp = (struct timer *) malloc (sizeof (struct timer));
              if (newp == NULL)
                return -1;
@@ -176,57 +181,29 @@ timer_create (clock_id, evp, timerid)
              (void) pthread_attr_setdetachstate (&newp->attr,
                                                  PTHREAD_CREATE_DETACHED);
 
-             /* Set up the barrier for sychronization.  */
-             (void) pthread_barrier_init (&newp->bar, NULL, 2);
-
-             /* The helper thread needs only very little resources
-                and should go away automatically when canceled.  */
-             pthread_attr_t attr;
-             (void) pthread_attr_init (&attr);
-             (void) pthread_attr_setdetachstate (&attr,
-                                                 PTHREAD_CREATE_DETACHED);
-             (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
-
-             /* Create the helper thread for this timer.  */
-             int res = pthread_create (&newp->th, &attr,
-                                       __timer_helper_thread, newp);
-             if (res != 0)
-               goto err_out;
-
-             /* No need for the attribute anymore.  */
-             (void) pthread_attr_destroy (&attr);
-
              /* Create the event structure for the kernel timer.  */
              struct sigevent sev;
              sev.sigev_value.sival_ptr = newp;
-             sev.sigev_signo = TIMER_SIG;
+             sev.sigev_signo = SIGTIMER;
              sev.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID;
              /* This is the thread ID of the helper thread.  */
-             sev._sigev_un._pad[0] = ((struct pthread *) newp->th)->tid;
-
-             /* Wait until the helper thread is set up.  */
-             (void) pthread_barrier_wait (&newp->bar);
-
-             /* No need for the barrier anymore.  */
-             (void) pthread_barrier_destroy (&newp->bar);
+             sev._sigev_un._pad[0] = __helper_tid;
 
              /* Create the timer.  */
              INTERNAL_SYSCALL_DECL (err);
-             res = INTERNAL_SYSCALL (timer_create, err, 3, clock_id, &sev,
-                                     &newp->ktimerid);
+             int res = INTERNAL_SYSCALL (timer_create, err, 3, clock_id, &sev,
+                                         &newp->ktimerid);
              if (! INTERNAL_SYSCALL_ERROR_P (res, err))
                {
                  *timerid = (timer_t) newp;
                  return 0;
                }
 
-             /* Something went wrong.  Kill the thread.  */
-             pthread_cancel (newp->th);
              /* Free the resources.  */
-             res = INTERNAL_SYSCALL_ERRNO (res, err);
-           err_out:
              free (newp);
-             __set_errno (res);
+
+             __set_errno (INTERNAL_SYSCALL_ERRNO (res, err));
+
              return -1;
            }
        }
index 9028dc4..106e1ae 100644 (file)
@@ -58,10 +58,6 @@ timer_delete (timerid)
          __no_posix_timers = 1;
 # endif
 
-         /* We have to get rid of the helper thread if we created one.  */
-         if (kt->sigev_notify == SIGEV_THREAD)
-           (void) pthread_cancel (kt->th);
-
          /* Free the memory.  */
          (void) free (kt);
 
index 3f69aa6..e9ece9f 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdbool.h>
 #include <sysdep.h>
 #include <kernel-features.h>
+#include <nptl/pthreadP.h>
 #include "kernel-posix-timers.h"
 
 
@@ -40,24 +41,14 @@ timer_sigev_thread (void *arg)
 
 
 /* Helper function to support starting threads for SIGEV_THREAD.  */
-void *
-attribute_hidden
-__timer_helper_thread (void *arg)
+static void *
+timer_helper_thread (void *arg)
 {
-  /* Block all signals.  */
+  /* Block all signals.  We will only wait for the signal the kernel
+     will send.  */
   sigset_t ss;
-
-  sigfillset (&ss);
-  (void) pthread_sigmask (SIG_BLOCK, &ss, NULL);
-
-  struct timer *tk = (struct timer *) arg;
-
-  /* Synchronize with the parent.  */
-  (void) pthread_barrier_wait (&tk->bar);
-
-  /* We will only wait for the signal the kernel will send.  */
   sigemptyset (&ss);
-  sigaddset (&ss, TIMER_SIG);
+  sigaddset (&ss, SIGTIMER);
 
   /* Endless loop of waiting for signals.  The loop is only ended when
      the thread is canceled.  */
@@ -65,15 +56,60 @@ __timer_helper_thread (void *arg)
     {
       siginfo_t si;
 
-      if (sigwaitinfo (&ss, &si) > 0 && si.si_timerid == tk->ktimerid)
+      if (sigwaitinfo (&ss, &si) > 0 && si.si_code == SI_TIMER)
        {
+
+         struct timer *tk = (struct timer *) si.si_ptr;
+
          /* That the signal we are waiting for.  */
          pthread_t th;
-         (void) pthread_create (&th, &tk->attr, timer_sigev_thread, arg);
+         (void) pthread_create (&th, &tk->attr, timer_sigev_thread, tk);
        }
     }
 }
 
+
+/* Control variable for helper thread creation.  */
+pthread_once_t __helper_once attribute_hidden;
+
+
+/* TID of the helper thread.  */
+pid_t __helper_tid attribute_hidden;
+
+
+/* Reset variables so that after a fork a new helper thread gets started.  */
+static void
+reset_helper_control (void)
+{
+  __helper_once = PTHREAD_ONCE_INIT;
+  __helper_tid = 0;
+}
+
+
+void
+attribute_hidden
+__start_helper_thread (void)
+{
+  /* The helper thread needs only very little resources
+     and should go away automatically when canceled.  */
+  pthread_attr_t attr;
+  (void) pthread_attr_init (&attr);
+  (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
+
+  /* Create the helper thread for this timer.  */
+  pthread_t th;
+  int res = pthread_create (&th, &attr, timer_helper_thread, NULL);
+  if (res == 0)
+    /* We managed to start the helper thread.  */
+    __helper_tid = ((struct pthread *) th)->tid;
+
+  /* No need for the attribute anymore.  */
+  (void) pthread_attr_destroy (&attr);
+
+  /* We have to make sure that after fork()ing a new helper thread can
+     be created.  */
+  pthread_atfork (NULL, NULL, reset_helper_control);
+}
 #endif
 
 #ifndef __ASSUME_POSIX_TIMERS