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]

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


On 05/27/2010 04:14 PM, Darren Hart wrote:
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>

Apologies, this should also contain:


[BZ 11588]

--
Darren

	* ../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. */


--
Darren Hart
IBM Linux Technology Center
Real-Time Linux Team


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