Only support ifunc in nptl/pt-vfork.c
[platform/upstream/linaro-glibc.git] / nptl / pthread_cond_signal.c
index 5a9bbca..22bef3d 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003-2014 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
 
@@ -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 <endian.h>
 #include <errno.h>
 
 #include <shlib-compat.h>
 #include <kernel-features.h>
+#include <stap-probe.h>
 
 
 int
 __pthread_cond_signal (cond)
      pthread_cond_t *cond;
 {
+  int pshared = (cond->__data.__mutex == (void *) ~0l)
+               ? LLL_SHARED : LLL_PRIVATE;
+
+  LIBC_PROBE (cond_signal, 1, cond);
+
   /* Make sure we are alone.  */
-  lll_mutex_lock (cond->__data.__lock);
+  lll_lock (cond->__data.__lock, pshared);
 
   /* Are there any waiters to be woken?  */
   if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
@@ -42,17 +47,35 @@ __pthread_cond_signal (cond)
       ++cond->__data.__wakeup_seq;
       ++cond->__data.__futex;
 
-      /* Wake one.  */
-      if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex, 1,
-                                                    1, &cond->__data.__lock),
-                                                    0))
-       return 0;
+#if (defined lll_futex_cmp_requeue_pi \
+     && defined __ASSUME_REQUEUE_PI)
+      pthread_mutex_t *mut = cond->__data.__mutex;
+
+      if (USE_REQUEUE_PI (mut)
+       /* This can only really fail with a ENOSYS, since nobody can modify
+          futex while we have the cond_lock.  */
+         && lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, 0,
+                                      &mut->__data.__lock,
+                                      cond->__data.__futex, pshared) == 0)
+       {
+         lll_unlock (cond->__data.__lock, pshared);
+         return 0;
+       }
+      else
+#endif
+       /* Wake one.  */
+       if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex,
+                                                      1, 1,
+                                                      &cond->__data.__lock,
+                                                      pshared), 0))
+         return 0;
 
-      lll_futex_wake (&cond->__data.__futex, 1);
+      /* Fallback if neither of them work.  */
+      lll_futex_wake (&cond->__data.__futex, 1, pshared);
     }
 
   /* We are done.  */
-  lll_mutex_unlock (cond->__data.__lock);
+  lll_unlock (cond->__data.__lock, pshared);
 
   return 0;
 }