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

Darren Hart dvhltc@us.ibm.com
Fri May 28 22:06:00 GMT 2010


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



More information about the Libc-alpha mailing list