This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 1/4] pi-condvars: add protocol support to pthread_condattr_t


When using a PTHREAD_PRIO_INHERIT mutex with a condvar, the pthread_cond* calls
can still cause an unbounded priority inversion via the internal condvar lock.
The POSIX specification doesn't provide a mechanism to specify the protocol of
the condvar. We would like to do this at runtime, but unfortunately it is legal
to call pthread_cond_signal() or pthread_cond_broadcast() without first waiting
on the lock, so the mutex type may not be known the first time the condvar is
used. A new API, pthread_condattr_setprotocol_np() and
pthread_condattr_getprotocol_np() allow the user to create a
PTHREAD_PRIO_INHERIT condvar. This uses a PTHREAD_PRIO_INHERIT mutex for the
internal condvar lock, eliminating the potential for hitting an unbounded
priority inversion on that lock.

V3: Extricate the pi-condvars work from the C implementation of requeue-pi.

2010-05-21  Darren Hart  <dvhltc@us.ibm.com>
	* ../Versions.def: Define GLIBC_2.13
	* Makefile (libpthread-routines): Add
	pthread_condattr_getprotocol_np and pthread_condattr_setprotocol_np.
	* Versions: Export pthread_condattr_getprotocol_np and
	pthread_condattr_setprotocol_np.
	* pthread_cond_broadcast.c: Use cond_lock and cond_unlock.
	* pthread_cond_init.c: Set the condvar protocol from the condattr.
	* pthread_cond_signal.c: Use cond_lock and cond_unlock.
	* pthread_cond_timedwait.c: Use cond_lock and cond_unlock.
	* pthread_cond_wait.c: Use cond_lock and cond_unlock.
	FIXME: also defines lll_pi_(un)?lock - unused.
	* pthread_condattr_getclock.c: Use new protocol shift values.
	* pthread_condattr_getprotocol_np.c: New file.
	* pthread_condattr_setclock.c: Use new protocol shift values.
	* pthread_condattr_setprotocol_np.c: New file.
	* sysdeps/pthread/pthread.h: Declare
	pthread_condattr_getprotocol_np and pthread_condattr_setprotocol_np.
	* sysdeps/unix/sysv/linux/internaltypes.h: Define bits, masks, and
	shift for the pthread_condattr.value.
---
 Versions.def                                 |    1 +
 nptl/Makefile                                |    1 +
 nptl/Versions                                |    4 ++
 nptl/pthread_cond_broadcast.c                |   11 +++--
 nptl/pthread_cond_init.c                     |   23 ++++++++-
 nptl/pthread_cond_signal.c                   |    9 +++-
 nptl/pthread_cond_timedwait.c                |   16 ++++---
 nptl/pthread_cond_wait.c                     |   61 ++++++++++++++++++++++----
 nptl/pthread_condattr_getclock.c             |    7 ++-
 nptl/pthread_condattr_getprotocol_np.c       |   34 ++++++++++++++
 nptl/pthread_condattr_setclock.c             |    6 +-
 nptl/pthread_condattr_setprotocol_np.c       |   39 ++++++++++++++++
 nptl/sysdeps/pthread/cond-lock.h             |   59 +++++++++++++++++++++++++
 nptl/sysdeps/pthread/pthread.h               |   12 +++++
 nptl/sysdeps/unix/sysv/linux/internaltypes.h |   30 ++++++++++---
 15 files changed, 276 insertions(+), 37 deletions(-)
 create mode 100644 nptl/pthread_condattr_getprotocol_np.c
 create mode 100644 nptl/pthread_condattr_setprotocol_np.c
 create mode 100644 nptl/sysdeps/pthread/cond-lock.h

diff --git a/Versions.def b/Versions.def
index eab006b..26535b5 100644
--- a/Versions.def
+++ b/Versions.def
@@ -92,6 +92,7 @@ libpthread {
   GLIBC_2.6
   GLIBC_2.11
   GLIBC_2.12
+  GLIBC_2.13
   GLIBC_PRIVATE
 }
 libresolv {
diff --git a/nptl/Makefile b/nptl/Makefile
index 982db8e..6d1913e 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -75,6 +75,7 @@ libpthread-routines = nptl-init vars events version \
 		      old_pthread_cond_signal old_pthread_cond_broadcast \
 		      pthread_condattr_init pthread_condattr_destroy \
 		      pthread_condattr_getpshared pthread_condattr_setpshared \
+		      pthread_condattr_getprotocol_np pthread_condattr_setprotocol_np \
 		      pthread_condattr_getclock pthread_condattr_setclock \
 		      pthread_spin_init pthread_spin_destroy \
 		      pthread_spin_lock pthread_spin_trylock \
diff --git a/nptl/Versions b/nptl/Versions
index f74941f..49a89e8 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -251,6 +251,10 @@ libpthread {
     pthread_setname_np; pthread_getname_np;
   };
 
+  GLIBC_2.13 {
+    pthread_condattr_getprotocol_np; pthread_condattr_setprotocol_np;
+  }
+
   GLIBC_PRIVATE {
     __pthread_initialize_minimal;
     __pthread_clock_gettime; __pthread_clock_settime;
diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c
index 22523c2..40611a5 100644
--- a/nptl/pthread_cond_broadcast.c
+++ b/nptl/pthread_cond_broadcast.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2006, 2007, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
 
@@ -27,6 +27,8 @@
 #include <shlib-compat.h>
 #include <kernel-features.h>
 
+#include "cond-lock.h"
+
 
 int
 __pthread_cond_broadcast (cond)
@@ -34,8 +36,9 @@ __pthread_cond_broadcast (cond)
 {
   int pshared = (cond->__data.__mutex == (void *) ~0l)
 		? LLL_SHARED : LLL_PRIVATE;
+
   /* Make sure we are alone.  */
-  lll_lock (cond->__data.__lock, pshared);
+  cond_lock (cond, pshared);
 
   /* Are there any waiters to be woken?  */
   if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
@@ -49,7 +52,7 @@ __pthread_cond_broadcast (cond)
       ++cond->__data.__broadcast_seq;
 
       /* We are done.  */
-      lll_unlock (cond->__data.__lock, pshared);
+      cond_unlock (cond, pshared);
 
       /* Do not use requeue for pshared condvars.  */
       if (cond->__data.__mutex == (void *) ~0l)
@@ -82,7 +85,7 @@ __pthread_cond_broadcast (cond)
     }
 
   /* We are done.  */
-  lll_unlock (cond->__data.__lock, pshared);
+  cond_unlock (cond, pshared);
 
   return 0;
 }
diff --git a/nptl/pthread_cond_init.c b/nptl/pthread_cond_init.c
index 65c01b1..33bb6bb 100644
--- a/nptl/pthread_cond_init.c
+++ b/nptl/pthread_cond_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008
+/* Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2010
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -32,9 +32,26 @@ __pthread_cond_init (cond, cond_attr)
   cond->__data.__lock = LLL_LOCK_INITIALIZER;
   cond->__data.__futex = 0;
   cond->__data.__nwaiters = (icond_attr != NULL
-			     ? ((icond_attr->value >> 1)
-				& ((1 << COND_NWAITERS_SHIFT) - 1))
+			     ? ((icond_attr->value >> CONDATTR_CLOCKID_SHIFT)
+				& ((1 << COND_PROTOCOL_SHIFT) - 1))
 			     : CLOCK_REALTIME);
+  if (icond_attr != NULL)
+   {
+    switch (icond_attr->value & CONDATTR_PROTOCOL_MASK)
+     {
+     case PTHREAD_PRIO_INHERIT << CONDATTR_PROTOCOL_SHIFT:
+       cond->__data.__nwaiters |= COND_PRIO_INHERIT;
+       break;
+
+     case PTHREAD_PRIO_PROTECT << CONDATTR_PROTOCOL_SHIFT:
+       cond->__data.__nwaiters |= COND_PRIO_PROTECT;
+       break;
+
+     default:
+       break;
+     }
+   }
+
   cond->__data.__total_seq = 0;
   cond->__data.__wakeup_seq = 0;
   cond->__data.__woken_seq = 0;
diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c
index 023bbb5..114158c 100644
--- a/nptl/pthread_cond_signal.c
+++ b/nptl/pthread_cond_signal.c
@@ -27,6 +27,8 @@
 #include <shlib-compat.h>
 #include <kernel-features.h>
 
+#include "cond-lock.h"
+
 
 int
 __pthread_cond_signal (cond)
@@ -36,7 +38,7 @@ __pthread_cond_signal (cond)
 		? LLL_SHARED : LLL_PRIVATE;
 
   /* Make sure we are alone.  */
-  lll_lock (cond->__data.__lock, pshared);
+  cond_lock(cond, pshared);
 
   /* Are there any waiters to be woken?  */
   if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
@@ -45,17 +47,20 @@ __pthread_cond_signal (cond)
       ++cond->__data.__wakeup_seq;
       ++cond->__data.__futex;
 
+#if 0
+      /* This is not needed for the x86_64 or i686 arches */
       /* Wake one.  */
       if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex, 1,
 						     1, &cond->__data.__lock,
 						     pshared), 0))
 	return 0;
+#endif
 
       lll_futex_wake (&cond->__data.__futex, 1, pshared);
     }
 
   /* We are done.  */
-  lll_unlock (cond->__data.__lock, pshared);
+  cond_unlock(cond, pshared);
 
   return 0;
 }
diff --git a/nptl/pthread_cond_timedwait.c b/nptl/pthread_cond_timedwait.c
index 7278ec4..21e3afe 100644
--- a/nptl/pthread_cond_timedwait.c
+++ b/nptl/pthread_cond_timedwait.c
@@ -27,6 +27,8 @@
 
 #include <shlib-compat.h>
 
+#include "cond-lock.h"
+
 #ifndef HAVE_CLOCK_GETTIME_VSYSCALL
 # undef INTERNAL_VSYSCALL
 # define INTERNAL_VSYSCALL INTERNAL_SYSCALL
@@ -65,14 +67,14 @@ __pthread_cond_timedwait (cond, mutex, abstime)
   int pshared = (cond->__data.__mutex == (void *) ~0l)
 		? LLL_SHARED : LLL_PRIVATE;
 
-  /* Make sure we are along.  */
-  lll_lock (cond->__data.__lock, pshared);
+  /* Make sure we are alone.  */
+  cond_lock(cond, pshared);
 
   /* Now we can release the mutex.  */
   int err = __pthread_mutex_unlock_usercnt (mutex, 0);
   if (err)
     {
-      lll_unlock (cond->__data.__lock, pshared);
+      cond_unlock(cond, pshared);
       return err;
     }
 
@@ -112,7 +114,7 @@ __pthread_cond_timedwait (cond, mutex, abstime)
 	int ret;
 	ret = INTERNAL_VSYSCALL (clock_gettime, err, 2,
 				(cond->__data.__nwaiters
-				 & ((1 << COND_NWAITERS_SHIFT) - 1)),
+				 & ((1 << COND_PROTOCOL_SHIFT) - 1)),
 				&rt);
 # ifndef __ASSUME_POSIX_TIMERS
 	if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0))
@@ -158,7 +160,7 @@ __pthread_cond_timedwait (cond, mutex, abstime)
       unsigned int futex_val = cond->__data.__futex;
 
       /* Prepare to wait.  Release the condvar futex.  */
-      lll_unlock (cond->__data.__lock, pshared);
+      cond_unlock(cond, pshared);
 
       /* Enable asynchronous cancellation.  Required by the standard.  */
       cbuffer.oldtype = __pthread_enable_asynccancel ();
@@ -171,7 +173,7 @@ __pthread_cond_timedwait (cond, mutex, abstime)
       __pthread_disable_asynccancel (cbuffer.oldtype);
 
       /* We are going to look at shared data again, so get the lock.  */
-      lll_lock (cond->__data.__lock, pshared);
+      cond_lock(cond, pshared);
 
       /* If a broadcast happened, we are done.  */
       if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
@@ -211,7 +213,7 @@ __pthread_cond_timedwait (cond, mutex, abstime)
     lll_futex_wake (&cond->__data.__nwaiters, 1, pshared);
 
   /* We are done with the condvar.  */
-  lll_unlock (cond->__data.__lock, pshared);
+  cond_unlock(cond, pshared);
 
   /* The cancellation handling is back to normal, remove the handler.  */
   __pthread_cleanup_pop (&buffer, 0);
diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
index 670fba5..43893b7 100644
--- a/nptl/pthread_cond_wait.c
+++ b/nptl/pthread_cond_wait.c
@@ -17,15 +17,19 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
+#include <assert.h>
 #include <endian.h>
 #include <errno.h>
 #include <sysdep.h>
 #include <lowlevellock.h>
+#include <not-cancel.h>
 #include <pthread.h>
 #include <pthreadP.h>
 
 #include <shlib-compat.h>
 
+#include "cond-lock.h"
+
 
 struct _condvar_cleanup_buffer
 {
@@ -38,16 +42,55 @@ struct _condvar_cleanup_buffer
 
 void
 __attribute__ ((visibility ("hidden")))
+lll_pi_lock(int *futexp, int private)
+{
+  pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+  int newval = id;
+  int ret;
+
+  newval |= FUTEX_WAITERS;
+  ret = atomic_compare_and_exchange_val_acq (futexp, newval, 0);
+
+  if (ret != 0)
+    {
+      /* The mutex is locked.  The kernel will now take care of
+	 everything.  */
+      INTERNAL_SYSCALL_DECL (__err);
+      int e = INTERNAL_SYSCALL (futex, __err, 4, futexp,
+				__lll_private_flag (FUTEX_LOCK_PI, private),
+				1, 0);
+    }
+}
+
+
+void
+__attribute__ ((visibility ("hidden")))
+lll_pi_unlock(int *futexp, int private)
+{
+
+  if ((*futexp & FUTEX_WAITERS) != 0
+      || atomic_compare_and_exchange_bool_acq (futexp, 0,
+					       THREAD_GETMEM (THREAD_SELF,
+							      tid)))
+    {
+      INTERNAL_SYSCALL_DECL (__err);
+      INTERNAL_SYSCALL (futex, __err, 2, futexp,
+			__lll_private_flag (FUTEX_UNLOCK_PI, private));
+    }
+}
+
+
+void
+__attribute__ ((visibility ("hidden")))
 __condvar_cleanup (void *arg)
 {
   struct _condvar_cleanup_buffer *cbuffer =
     (struct _condvar_cleanup_buffer *) arg;
   unsigned int destroying;
-  int pshared = (cbuffer->cond->__data.__mutex == (void *) ~0l)
-  		? LLL_SHARED : LLL_PRIVATE;
+  int pshared = (cbuffer->mutex == (void *) ~0l) ? LLL_SHARED : LLL_PRIVATE;
 
   /* We are going to modify shared data.  */
-  lll_lock (cbuffer->cond->__data.__lock, pshared);
+  cond_lock(cbuffer->cond, pshared);
 
   if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq)
     {
@@ -78,7 +121,7 @@ __condvar_cleanup (void *arg)
     }
 
   /* We are done.  */
-  lll_unlock (cbuffer->cond->__data.__lock, pshared);
+  cond_unlock(cbuffer->cond, pshared);
 
   /* Wake everybody to make sure no condvar signal gets lost.  */
   if (! destroying)
@@ -102,13 +145,13 @@ __pthread_cond_wait (cond, mutex)
   		? LLL_SHARED : LLL_PRIVATE;
 
   /* Make sure we are along.  */
-  lll_lock (cond->__data.__lock, pshared);
+  cond_lock(cond, pshared);
 
   /* Now we can release the mutex.  */
   err = __pthread_mutex_unlock_usercnt (mutex, 0);
   if (__builtin_expect (err, 0))
     {
-      lll_unlock (cond->__data.__lock, pshared);
+      cond_unlock(cond, pshared);
       return err;
     }
 
@@ -144,7 +187,7 @@ __pthread_cond_wait (cond, mutex)
       unsigned int futex_val = cond->__data.__futex;
 
       /* Prepare to wait.  Release the condvar futex.  */
-      lll_unlock (cond->__data.__lock, pshared);
+      cond_unlock(cond, pshared);
 
       /* Enable asynchronous cancellation.  Required by the standard.  */
       cbuffer.oldtype = __pthread_enable_asynccancel ();
@@ -156,7 +199,7 @@ __pthread_cond_wait (cond, mutex)
       __pthread_disable_asynccancel (cbuffer.oldtype);
 
       /* We are going to look at shared data again, so get the lock.  */
-      lll_lock (cond->__data.__lock, pshared);
+      cond_lock(cond, pshared);
 
       /* If a broadcast happened, we are done.  */
       if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
@@ -182,7 +225,7 @@ __pthread_cond_wait (cond, mutex)
     lll_futex_wake (&cond->__data.__nwaiters, 1, pshared);
 
   /* We are done with the condvar.  */
-  lll_unlock (cond->__data.__lock, pshared);
+  cond_unlock(cond, pshared);
 
   /* The cancellation handling is back to normal, remove the handler.  */
   __pthread_cleanup_pop (&buffer, 0);
diff --git a/nptl/pthread_condattr_getclock.c b/nptl/pthread_condattr_getclock.c
index 3eedeb1..9f034b3 100644
--- a/nptl/pthread_condattr_getclock.c
+++ b/nptl/pthread_condattr_getclock.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2003,2004,2007,2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -25,7 +25,8 @@ pthread_condattr_getclock (attr, clock_id)
      const pthread_condattr_t *attr;
      clockid_t *clock_id;
 {
-  *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1)
-	       & ((1 << COND_NWAITERS_SHIFT) - 1));
+  *clock_id = (((((const struct pthread_condattr *) attr)->value)
+	       >> CONDATTR_CLOCKID_SHIFT)
+	       & ((1 << COND_PROTOCOL_SHIFT) - 1));
   return 0;
 }
diff --git a/nptl/pthread_condattr_getprotocol_np.c b/nptl/pthread_condattr_getprotocol_np.c
new file mode 100644
index 0000000..18e099d
--- /dev/null
+++ b/nptl/pthread_condattr_getprotocol_np.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2010 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Dinakar Guniguntala <dino@in.ibm.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   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.  */
+
+#include "pthreadP.h"
+
+
+int
+pthread_condattr_getprotocol_np (attr, protocol)
+     const pthread_condattr_t *attr;
+     int *protocol;
+{
+  *protocol = ((const struct pthread_condattr *) attr)->value;
+
+  *protocol = ((*protocol & CONDATTR_PROTOCOL_MASK)
+	       >> CONDATTR_PROTOCOL_SHIFT);
+
+  return 0;
+}
diff --git a/nptl/pthread_condattr_setclock.c b/nptl/pthread_condattr_setclock.c
index 5c54f76..97e9595 100644
--- a/nptl/pthread_condattr_setclock.c
+++ b/nptl/pthread_condattr_setclock.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc.
+/* Copyright (C) 2003,2004,2007,2008,2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
 
@@ -62,11 +62,11 @@ pthread_condattr_setclock (attr, clock_id)
     return EINVAL;
 
   /* Make sure the value fits in the bits we reserved.  */
-  assert (clock_id < (1 << COND_NWAITERS_SHIFT));
+  assert (clock_id < (1 << COND_PROTOCOL_SHIFT));
 
   int *valuep = &((struct pthread_condattr *) attr)->value;
 
-  *valuep = ((*valuep & ~(((1 << COND_NWAITERS_SHIFT) - 1) << 1))
+  *valuep = ((*valuep & ~(((1 << COND_PROTOCOL_SHIFT) - 1) << 1))
 	     | (clock_id << 1));
 
   return 0;
diff --git a/nptl/pthread_condattr_setprotocol_np.c b/nptl/pthread_condattr_setprotocol_np.c
new file mode 100644
index 0000000..250a196
--- /dev/null
+++ b/nptl/pthread_condattr_setprotocol_np.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 2010 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Dinakar Guniguntala <dino@in.ibm.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   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.  */
+
+#include <errno.h>
+#include <pthreadP.h>
+
+int
+pthread_condattr_setprotocol_np (attr, protocol)
+     pthread_condattr_t *attr;
+     int protocol;
+{
+  if (protocol != PTHREAD_PRIO_NONE
+      && protocol != PTHREAD_PRIO_INHERIT
+      && __builtin_expect (protocol != PTHREAD_PRIO_PROTECT, 0))
+    return EINVAL;
+
+  int *valuep = &((struct pthread_condattr *) attr)->value;
+
+  *valuep = ((*valuep & ~CONDATTR_PROTOCOL_MASK)
+	     | (protocol << CONDATTR_PROTOCOL_SHIFT));
+
+  return 0;
+}
diff --git a/nptl/sysdeps/pthread/cond-lock.h b/nptl/sysdeps/pthread/cond-lock.h
new file mode 100644
index 0000000..9031a00
--- /dev/null
+++ b/nptl/sysdeps/pthread/cond-lock.h
@@ -0,0 +1,59 @@
+/* Copyright (C) 2010 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Dinakar Guniguntala <dino@in.ibm.com>.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   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.  */
+
+#ifndef _COND_LOCK_H
+#define _COND_LOCK_H 1
+
+
+extern void lll_pi_lock (int *futex, int pshared)
+     __attribute__ ((visibility ("hidden")));
+extern void lll_pi_unlock (int *futex, int pshared)
+     __attribute__ ((visibility ("hidden")));
+
+static inline void cond_lock(pthread_cond_t *cond,
+			     int pshared);
+
+static inline void cond_unlock(pthread_cond_t *cond,
+			       int pshared);
+
+static inline void cond_lock(cond, pshared)
+     pthread_cond_t *cond;
+     int pshared;
+{
+  if (pshared == LLL_PRIVATE
+      && ((cond->__data.__nwaiters & COND_PROTOCOL_MASK)
+	  == COND_PRIO_INHERIT))
+    lll_pi_lock (&cond->__data.__lock, pshared);
+  else
+    lll_lock (cond->__data.__lock, pshared);
+}
+
+static inline void cond_unlock(cond, pshared)
+     pthread_cond_t *cond;
+     int pshared;
+{
+  if (pshared == LLL_PRIVATE
+      && ((cond->__data.__nwaiters & COND_PROTOCOL_MASK)
+	  == COND_PRIO_INHERIT))
+    lll_pi_unlock (&cond->__data.__lock, pshared);
+  else
+    lll_unlock (cond->__data.__lock, pshared);
+}
+
+#endif
diff --git a/nptl/sysdeps/pthread/pthread.h b/nptl/sysdeps/pthread/pthread.h
index 44cf9f0..ef5e093 100644
--- a/nptl/sysdeps/pthread/pthread.h
+++ b/nptl/sysdeps/pthread/pthread.h
@@ -1006,6 +1006,18 @@ extern int pthread_condattr_getpshared (__const pthread_condattr_t *
 extern int pthread_condattr_setpshared (pthread_condattr_t *__attr,
 					int __pshared) __THROW __nonnull ((1));
 
+/* Get the protocol flag of the condition variable attribute ATTR.  */
+extern int pthread_condattr_getprotocol_np (__const pthread_condattr_t *
+                                            __restrict __attr,
+                                            int *__restrict __protocol)
+     __THROW __nonnull ((1, 2));
+
+/* Set the cond protocol attribute in ATTR to protocol (one of
+   PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT or PTHREAD_PRIO_PROTECT).  */
+extern int pthread_condattr_setprotocol_np (pthread_condattr_t *__attr,
+                                            int __protocol)
+     __THROW __nonnull ((1));
+
 #ifdef __USE_XOPEN2K
 /* Get the clock selected for the conditon variable attribute ATTR.  */
 extern int pthread_condattr_getclock (__const pthread_condattr_t *
diff --git a/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/nptl/sysdeps/unix/sysv/linux/internaltypes.h
index add20b6..876ca79 100644
--- a/nptl/sysdeps/unix/sysv/linux/internaltypes.h
+++ b/nptl/sysdeps/unix/sysv/linux/internaltypes.h
@@ -67,20 +67,38 @@ struct pthread_condattr
 {
   /* Combination of values:
 
-     Bit 0  : flag whether coditional variable will be shareable between
+     Bit 0  : flag whether conditional variable will be shareable between
 	      processes.
 
-     Bit 1-7: clock ID.  */
+     Bit 1-7: clock ID.
+     Bit 8-9: protocol. One of PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT
+              or PTHREAD_PRIO_PROTECT.  */
   int value;
 };
 
 
+#define CONDATTR_PSHARED_MASK	0x00000001
+#define CONDATTR_CLOCKID_MASK	0x000000FE
+#define CONDATTR_CLOCKID_SHIFT	1
+#define CONDATTR_PROTOCOL_MASK	0x00000300
+#define CONDATTR_PROTOCOL_SHIFT	8
+
+
+enum {
+  COND_PRIO_INHERIT = 2,
+  COND_PRIO_PROTECT
+};
+
+
 /* The __NWAITERS field is used as a counter and to house the number
-   of bits for other purposes.  COND_CLOCK_BITS is the number
-   of bits needed to represent the ID of the clock.  COND_NWAITERS_SHIFT
+   of bits for other purposes.  COND_CLOCK_MASK defines the bits used
+   to represent the ID of the clock.  COND_PROTOCOL_MASK defines the
+   bits used to represent cond protocol attrbutes. COND_NWAITERS_SHIFT
    is the number of bits reserved for other purposes like the clock.  */
-#define COND_CLOCK_BITS		1
-#define COND_NWAITERS_SHIFT	1
+#define COND_CLOCK_MASK		0x00000001
+#define COND_PROTOCOL_SHIFT	1
+#define COND_PROTOCOL_MASK	0x00000006
+#define COND_NWAITERS_SHIFT	3
 
 
 /* Read-write lock variable attribute data structure.  */
-- 
1.7.0.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]