[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