]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - nptl/sysdeps/pthread/createthread.c
Use glibc_likely instead __builtin_expect.
[thirdparty/glibc.git] / nptl / sysdeps / pthread / createthread.c
index 88658a16e1ef9c8420336c3bdc9516d1d74a147c..93f93eebd4ab3a21013637da42331530a824f809 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2014 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -13,9 +13,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #include <sched.h>
 #include <setjmp.h>
 #include <atomic.h>
 #include <ldsodefs.h>
 #include <tls.h>
+#include <stdint.h>
 
 #include "kernel-features.h"
 
 
-#define CLONE_SIGNAL           (CLONE_SIGHAND | CLONE_THREAD)
+#define CLONE_SIGNAL           (CLONE_SIGHAND | CLONE_THREAD)
 
 /* Unless otherwise specified, the thread "register" is going to be
    initialized with a pointer to the TCB.  */
@@ -56,11 +56,11 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
   PREPARE_CREATE;
 #endif
 
-  if (stopped)
-    /* We Make sure the thread does not run far by forcing it to get a
+  if (__glibc_unlikely (stopped != 0))
+    /* We make sure the thread does not run far by forcing it to get a
        lock.  We lock it here too so that the new thread cannot continue
        until we tell it to.  */
-    lll_lock (pd->lock);
+    lll_lock (pd->lock, LLL_PRIVATE);
 
   /* One more thread.  We cannot have the thread do this itself, since it
      might exist but not have been scheduled yet by the time we've returned
@@ -72,23 +72,28 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
      that cares whether the thread count is correct.  */
   atomic_increment (&__nptl_nthreads);
 
-  if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
-                 pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
+  int rc = ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
+                      pd, &pd->tid, TLS_VALUE, &pd->tid);
+
+  if (__glibc_unlikely (rc == -1))
     {
       atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second.  */
 
-      /* Failed.  If the thread is detached, remove the TCB here since
-        the caller cannot do this.  The caller remembered the thread
-        as detached and cannot reverify that it is not since it must
-        not access the thread descriptor again.  */
-      if (IS_DETACHED (pd))
+      /* Perhaps a thread wants to change the IDs and if waiting
+        for this stillborn thread.  */
+      if (__builtin_expect (atomic_exchange_acq (&pd->setxid_futex, 0)
+                           == -2, 0))
+       lll_futex_wake (&pd->setxid_futex, 1, LLL_PRIVATE);
+
+      /* Free the resources.  */
        __deallocate_stack (pd);
 
-      return errno;
+      /* We have to translate error codes.  */
+      return errno == ENOMEM ? EAGAIN : errno;
     }
 
   /* Now we have the possibility to set scheduling parameters etc.  */
-  if (__builtin_expect (stopped != 0, 0))
+  if (__glibc_unlikely (stopped != 0))
     {
       INTERNAL_SYSCALL_DECL (err);
       int res = 0;
@@ -97,21 +102,20 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
       if (attr->cpuset != NULL)
        {
          res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid,
-                                 sizeof (cpu_set_t), attr->cpuset);
+                                 attr->cpusetsize, attr->cpuset);
 
-         if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
+         if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err)))
            {
              /* The operation failed.  We have to kill the thread.  First
                 send it the cancellation signal.  */
              INTERNAL_SYSCALL_DECL (err2);
            err_out:
-#if __ASSUME_TGKILL
              (void) INTERNAL_SYSCALL (tgkill, err2, 3,
                                       THREAD_GETMEM (THREAD_SELF, pid),
                                       pd->tid, SIGCANCEL);
-#else
-             (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL);
-#endif
+
+             /* We do not free the stack here because the canceled thread
+                itself will do this.  */
 
              return (INTERNAL_SYSCALL_ERROR_P (res, err)
                      ? INTERNAL_SYSCALL_ERRNO (res, err)
@@ -125,7 +129,7 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
          res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid,
                                  pd->schedpolicy, &pd->schedparam);
 
-         if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0))
+         if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (res, err)))
            goto err_out;
        }
     }
@@ -172,21 +176,14 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
        sys_exit() in the location pointed to by the seventh parameter
        to CLONE.
 
-     CLONE_DETACHED
-       No signal is generated if the thread exists and it is
-       automatically reaped.
-
      The termination signal is chosen to be zero which means no signal
      is sent.  */
   int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL
                     | CLONE_SETTLS | CLONE_PARENT_SETTID
                     | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM
-#if __ASSUME_NO_CLONE_DETACHED == 0
-                    | CLONE_DETACHED
-#endif
                     | 0);
 
-  if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
+  if (__glibc_unlikely (THREAD_GETMEM (THREAD_SELF, report_events)))
     {
       /* The parent thread is supposed to report events.  Check whether
         the TD_CREATE event is needed, too.  */
@@ -223,7 +220,7 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
              __nptl_create_event ();
 
              /* And finally restart the new thread.  */
-             lll_unlock (pd->lock);
+             lll_unlock (pd->lock, LLL_PRIVATE);
            }
 
          return res;
@@ -250,7 +247,7 @@ create_thread (struct pthread *pd, const struct pthread_attr *attr,
 
   if (res == 0 && stopped)
     /* And finally restart the new thread.  */
-    lll_unlock (pd->lock);
+    lll_unlock (pd->lock, LLL_PRIVATE);
 
   return res;
 }