@@ -84,6 +84,8 @@ the standard.
@menu
* Default Thread Attributes:: Setting default attributes for
threads in a process.
+* Conditional Variable Attributes:: Specifying the protocol attribute
+ for a conditional variable.
@end menu
@node Default Thread Attributes
@@ -132,6 +134,44 @@ The system does not have sufficient memory.
@end table
@end deftypefun
+@node Conditional Variable Attributes
+@subsection Specifying the protocol attribute for a conditional variable
+
+@Theglibc{} provides non-standard API functions to set and get the protocol
+attribute for a conditional variable.
+
+@deftypefun int pthread_condattr_getprotocol_np (const pthread_condattr_t *@var{attr}, int *@var{protocol})
+Get the protocol attribute of a conditional variable attributes object
+pointed to by @var{attr} and set @var{protocol} to match.
+@end deftypefun
+
+@deftypefun int pthread_condattr_setprotocol_np (pthread_condattr_t *@var{attr}, int @var{protocol})
+Set the @var{protocol} attribute of a conditional variable attributes object
+pointed to by @var{attr} which was previously created by the function
+pthread_condattr_init().
+
+The @var{protocol} attribute defines the protocol to be followed in utilizing
+conditional variables. The value of protocol may be one of:
+
+@table @code
+@item PTHREAD_PRIO_NONE
+@item PTHREAD_PRIO_INHERIT
+@item PTHREAD_PRIO_PROTECT
+@end table
+
+which are defined in the @file{pthread.h} header.
+@pindex pthread.h
+
+Upon successful completion, the @code{pthread_condattr_setprotocol_np}
+function returns @math{0}; otherwise non-zero error code is returned. The
+following error codes are defined:
+
+@table @code
+@item EINVAL
+The value specified by @var{protocol} is invalid.
+@end table
+@end deftypefun
+
@c FIXME these are undocumented:
@c pthread_atfork
@c pthread_attr_destroy
@@ -78,6 +78,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 \
@@ -104,7 +105,7 @@ libpthread-routines = nptl-init vars events version \
cleanup_defer_compat unwind \
pt-longjmp pt-cleanup\
cancellation \
- lowlevellock lowlevelrobustlock \
+ lowlevellock lowlevelrobustlock lowlevelpilock \
pt-fork pt-vfork \
ptw-write ptw-read ptw-close ptw-fcntl ptw-accept \
ptw-connect ptw-recv ptw-recvfrom ptw-recvmsg ptw-send \
@@ -264,6 +264,8 @@ libpthread {
}
GLIBC_2.20 {
+ pthread_condattr_getprotocol_np;
+ pthread_condattr_setprotocol_np;
}
GLIBC_PRIVATE {
@@ -27,6 +27,7 @@
#include <shlib-compat.h>
#include <kernel-features.h>
+#include "cond-lock.h"
int
__pthread_cond_broadcast (cond)
@@ -37,7 +38,7 @@ __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)
@@ -51,7 +52,7 @@ __pthread_cond_broadcast (cond)
++cond->__data.__broadcast_seq;
/* We are done. */
- lll_unlock (cond->__data.__lock, pshared);
+ cond_unlock (cond, pshared);
/* Wake everybody. */
pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
@@ -85,7 +86,7 @@ wake_all:
}
/* We are done. */
- lll_unlock (cond->__data.__lock, pshared);
+ cond_unlock (cond, pshared);
return 0;
}
@@ -21,6 +21,7 @@
#include "pthreadP.h"
#include <stap-probe.h>
+#include "cond-lock.h"
int
__pthread_cond_destroy (cond)
@@ -32,13 +33,13 @@ __pthread_cond_destroy (cond)
LIBC_PROBE (cond_destroy, 1, cond);
/* Make sure we are alone. */
- lll_lock (cond->__data.__lock, pshared);
+ cond_lock (cond, pshared);
if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
{
/* If there are still some waiters which have not been
woken up, this is an application bug. */
- lll_unlock (cond->__data.__lock, pshared);
+ cond_unlock (cond, pshared);
return EBUSY;
}
@@ -70,11 +71,11 @@ __pthread_cond_destroy (cond)
do
{
- lll_unlock (cond->__data.__lock, pshared);
+ cond_unlock (cond, pshared);
lll_futex_wait (&cond->__data.__nwaiters, nwaiters, pshared);
- lll_lock (cond->__data.__lock, pshared);
+ cond_lock (cond, pshared);
nwaiters = cond->__data.__nwaiters;
}
@@ -31,9 +31,27 @@ __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_MASK)
+ >> CONDATTR_CLOCKID_SHIFT)
: CLOCK_REALTIME);
+ if (icond_attr != NULL)
+ {
+ switch ((icond_attr->value & CONDATTR_PROTOCOL_MASK)
+ >> CONDATTR_PROTOCOL_SHIFT)
+ {
+ case PTHREAD_PRIO_INHERIT:
+ cond->__data.__nwaiters |= COND_PRIO_INHERIT << COND_PROTOCOL_SHIFT;
+ break;
+
+ case PTHREAD_PRIO_PROTECT:
+ cond->__data.__nwaiters |= COND_PRIO_PROTECT << COND_PROTOCOL_SHIFT;
+ break;
+
+ default:
+ break;
+ }
+ }
+
cond->__data.__total_seq = 0;
cond->__data.__wakeup_seq = 0;
cond->__data.__woken_seq = 0;
@@ -27,6 +27,7 @@
#include <kernel-features.h>
#include <stap-probe.h>
+#include "cond-lock.h"
int
__pthread_cond_signal (cond)
@@ -38,7 +39,7 @@ __pthread_cond_signal (cond)
LIBC_PROBE (cond_signal, 1, cond);
/* 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)
@@ -58,7 +59,7 @@ __pthread_cond_signal (cond)
&mut->__data.__lock,
cond->__data.__futex, pshared) == 0)
{
- lll_unlock (cond->__data.__lock, pshared);
+ cond_unlock (cond, pshared);
return 0;
}
else
@@ -75,7 +76,7 @@ __pthread_cond_signal (cond)
}
/* We are done. */
- lll_unlock (cond->__data.__lock, pshared);
+ cond_unlock (cond, pshared);
return 0;
}
@@ -26,6 +26,8 @@
#include <shlib-compat.h>
+#include "cond-lock.h"
+
#ifndef HAVE_CLOCK_GETTIME_VSYSCALL
# undef INTERNAL_VSYSCALL
# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
@@ -70,13 +72,13 @@ __pthread_cond_timedwait (cond, mutex, abstime)
#endif
/* Make sure we are alone. */
- lll_lock (cond->__data.__lock, pshared);
+ 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;
}
@@ -121,8 +123,7 @@ __pthread_cond_timedwait (cond, mutex, abstime)
# ifdef __NR_clock_gettime
INTERNAL_SYSCALL_DECL (err);
(void) INTERNAL_VSYSCALL (clock_gettime, err, 2,
- (cond->__data.__nwaiters
- & ((1 << COND_NWAITERS_SHIFT) - 1)),
+ cond->__data.__nwaiters & COND_CLOCKID_MASK,
&rt);
/* Convert the absolute timeout value to a relative timeout. */
rt.tv_sec = abstime->tv_sec - rt.tv_sec;
@@ -155,7 +156,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 ();
@@ -205,7 +206,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)
@@ -245,7 +246,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);
@@ -27,6 +27,8 @@
#include <shlib-compat.h>
#include <stap-probe.h>
+#include "cond-lock.h"
+
struct _condvar_cleanup_buffer
{
int oldtype;
@@ -47,7 +49,7 @@ __condvar_cleanup (void *arg)
? 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 +80,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)
@@ -116,13 +118,13 @@ __pthread_cond_wait (cond, mutex)
LIBC_PROBE (cond_wait, 2, cond, mutex);
/* Make sure we are alone. */
- lll_lock (cond->__data.__lock, pshared);
+ cond_lock (cond, pshared);
/* Now we can release the mutex. */
err = __pthread_mutex_unlock_usercnt (mutex, 0);
if (__glibc_unlikely (err))
{
- lll_unlock (cond->__data.__lock, pshared);
+ cond_unlock (cond, pshared);
return err;
}
@@ -157,7 +159,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 ();
@@ -191,7 +193,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)
@@ -217,7 +219,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);
@@ -24,7 +24,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_MASK) >> CONDATTR_CLOCKID_SHIFT);
+
return 0;
}
new file mode 100644
@@ -0,0 +1,28 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <pthreadP.h>
+
+
+int
+pthread_condattr_getprotocol_np (const pthread_condattr_t *attr, int *protocol)
+{
+ *protocol = ((((const struct pthread_condattr *) attr)->value
+ & CONDATTR_PROTOCOL_MASK) >> CONDATTR_PROTOCOL_SHIFT);
+
+ return 0;
+}
@@ -24,7 +24,8 @@ pthread_condattr_getpshared (attr, pshared)
const pthread_condattr_t *attr;
int *pshared;
{
- *pshared = ((const struct pthread_condattr *) attr)->value & 1;
+ *pshared = (((const struct pthread_condattr *) attr)->value
+ & CONDATTR_PSHARED_MASK);
return 0;
}
@@ -36,12 +36,12 @@ 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))
- | (clock_id << 1));
+ *valuep = ((*valuep & ~CONDATTR_CLOCKID_MASK)
+ | (clock_id << CONDATTR_CLOCKID_SHIFT));
return 0;
}
new file mode 100644
@@ -0,0 +1,36 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <pthreadP.h>
+
+
+int
+pthread_condattr_setprotocol_np (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;
+}
@@ -30,7 +30,8 @@ pthread_condattr_setpshared (attr, pshared)
int *valuep = &((struct pthread_condattr *) attr)->value;
- *valuep = (*valuep & ~1) | (pshared != PTHREAD_PROCESS_PRIVATE);
+ *valuep = ((*valuep & ~CONDATTR_PSHARED_MASK)
+ | (pshared != PTHREAD_PROCESS_PRIVATE));
return 0;
}
new file mode 100644
@@ -0,0 +1,58 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _COND_LOCK_H
+#define _COND_LOCK_H 1
+
+#ifdef __ASSUME_FUTEX_LOCK_PI
+extern void __lll_pi_lock (int *futex, int private) attribute_hidden;
+extern void __lll_pi_unlock (int *futex, int private) attribute_hidden;
+
+#define lll_pi_lock(futex, private) __lll_pi_lock (&(futex), private)
+#define lll_pi_unlock(futex, private) __lll_pi_unlock (&(futex), private)
+#else
+#define lll_pi_lock(futex, private) lll_lock (futex, private)
+#define lll_pi_unlock(futex, private) lll_unlock (futex, private)
+#endif
+
+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(pthread_cond_t *cond, int pshared)
+{
+ if (pshared == LLL_PRIVATE &&
+ (((cond->__data.__nwaiters & COND_PROTOCOL_MASK) >> COND_PROTOCOL_SHIFT)
+ == COND_PRIO_INHERIT))
+ lll_pi_lock (cond->__data.__lock, pshared);
+ else
+ lll_lock (cond->__data.__lock, pshared);
+}
+
+static inline void
+cond_unlock(pthread_cond_t *cond, int pshared)
+{
+ if (pshared == LLL_PRIVATE &&
+ (((cond->__data.__nwaiters & COND_PROTOCOL_MASK) >> COND_PROTOCOL_SHIFT)
+ == COND_PRIO_INHERIT))
+ lll_pi_unlock (cond->__data.__lock, pshared);
+ else
+ lll_unlock (cond->__data.__lock, pshared);
+}
+
+#endif
new file mode 100644
@@ -0,0 +1,61 @@
+/* Copyright (C) 2013 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ 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, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <sysdep.h>
+#include <lowlevellock.h>
+#include <sys/time.h>
+#include <pthreadP.h>
+
+
+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);
+ 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));
+ }
+}
@@ -69,18 +69,36 @@ struct pthread_condattr
Bit 0 : flag whether conditional variable will be sharable between
processes.
- Bit 1-7: clock ID. */
+ Bit 1 : clock ID.
+ Bit 2-3: protocol. One of PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT
+ or PTHREAD_PRIO_PROTECT. */
int value;
};
+#define CONDATTR_PSHARED_MASK 0x00000001
+#define CONDATTR_CLOCKID_MASK 0x00000002
+#define CONDATTR_CLOCKID_SHIFT 1
+#define CONDATTR_PROTOCOL_MASK 0x0000000C
+#define CONDATTR_PROTOCOL_SHIFT 2
+
+
+enum {
+ COND_PRIO_NONE,
+ COND_PRIO_INHERIT,
+ 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_CLOCKID_MASK defines the bits used
+ to represent the ID of the clock. COND_PROTOCOL_MASK defines the
+ bits used to represent cond protocol attributes. 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_CLOCKID_MASK 0x00000001
+#define COND_PROTOCOL_SHIFT 1
+#define COND_PROTOCOL_MASK 0x00000006
+#define COND_NWAITERS_SHIFT 3
/* Read-write lock variable attribute data structure. */
struct pthread_rwlockattr
@@ -823,6 +823,20 @@ extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr,
int __pshared)
__THROW __nonnull ((1));
+#ifdef __USE_GNU
+/* 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));
+#endif
+
#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
/* Return in *KIND the mutex kind attribute in *ATTR. */
extern int pthread_mutexattr_gettype (const pthread_mutexattr_t *__restrict
@@ -226,3 +226,7 @@ GLIBC_2.18
GLIBC_2.18 A
pthread_getattr_default_np F
pthread_setattr_default_np F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
@@ -226,6 +226,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -12,6 +12,10 @@ GLIBC_2.18
GLIBC_2.18 A
pthread_getattr_default_np F
pthread_setattr_default_np F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.4
GLIBC_2.4 A
_IO_flockfile F
@@ -226,6 +226,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -210,6 +210,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -12,6 +12,10 @@ GLIBC_2.18
GLIBC_2.18 A
pthread_getattr_default_np F
pthread_setattr_default_np F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.4
GLIBC_2.4 A
_IO_flockfile F
@@ -226,6 +226,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -224,3 +224,7 @@ GLIBC_2.18
wait F
waitpid F
write F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
@@ -220,6 +220,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -220,6 +220,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -226,6 +226,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -12,6 +12,10 @@ GLIBC_2.18
GLIBC_2.18 A
pthread_getattr_default_np F
pthread_setattr_default_np F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3
GLIBC_2.3 A
_IO_flockfile F
@@ -230,6 +230,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -214,6 +214,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -210,6 +210,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -226,6 +226,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -210,6 +210,10 @@ GLIBC_2.2.3
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -226,3 +226,7 @@ GLIBC_2.18
GLIBC_2.18 A
pthread_getattr_default_np F
pthread_setattr_default_np F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
@@ -226,3 +226,7 @@ GLIBC_2.18
GLIBC_2.18 A
pthread_getattr_default_np F
pthread_setattr_default_np F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
@@ -226,3 +226,7 @@ GLIBC_2.18
GLIBC_2.18 A
pthread_getattr_default_np F
pthread_setattr_default_np F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
@@ -208,6 +208,10 @@ GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.2.6 A
__nanosleep F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F
GLIBC_2.3.2
GLIBC_2.3.2 A
pthread_cond_broadcast F
@@ -124,6 +124,17 @@
__status; \
})
+#define lll_futex_timed_wait_bitset(futexp, val, timespec, clockbit, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ int __op = FUTEX_WAIT_BITSET | clockbit; \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (__op, private), \
+ (val), (timespec), NULL /* Unused. */, \
+ FUTEX_BITSET_MATCH_ANY); \
+ __ret; \
+ })
#define lll_futex_wake(futex, nr, private) \
({ \
@@ -393,6 +404,43 @@ extern int __lll_timedlock_elision (int *futex, short *adapt_count,
: "cx", "r11", "cc", "memory"); \
__res < 0; })
+/* Returns non-zero if error happened, zero if success. */
+#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_WAKE_OP, private), \
+ (nr_wake), (nr_wake2), (futexp2), \
+ FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+
+#define lll_futex_wait_requeue_pi(futexp, val, mutex, private) \
+ lll_futex_timed_wait_requeue_pi (futexp, val, NULL, 0, mutex, private)
+
+#define lll_futex_timed_wait_requeue_pi(futexp, val, timespec, clockbit, \
+ mutex, private) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ int __op = FUTEX_WAIT_REQUEUE_PI | clockbit; \
+ \
+ INTERNAL_SYSCALL (futex, __err, 5, (futexp), \
+ __lll_private_flag (__op, private), \
+ (val), (timespec), mutex); \
+ })
+
+#define lll_futex_cmp_requeue_pi(futexp, nr_wake, nr_move, mutex, val, priv) \
+ ({ \
+ INTERNAL_SYSCALL_DECL (__err); \
+ long int __ret; \
+ \
+ __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \
+ __lll_private_flag (FUTEX_CMP_REQUEUE_PI, priv),\
+ (nr_wake), (nr_move), (mutex), (val)); \
+ INTERNAL_SYSCALL_ERROR_P (__ret, __err); \
+ })
+
#define lll_islocked(futex) \
(futex != LLL_LOCK_INITIALIZER)
@@ -226,3 +226,7 @@ GLIBC_2.18
GLIBC_2.18 A
pthread_getattr_default_np F
pthread_setattr_default_np F
+GLIBC_2.20
+ GLIBC_2.20 A
+ pthread_condattr_getprotocol_np F
+ pthread_condattr_setprotocol_np F