diff --git a/nptl/Makefile b/nptl/Makefile
index 0567e77a790..990315c292f 100644
--- a/nptl/Makefile
+++ b/nptl/Makefile
@@ -68,6 +68,7 @@ libpthread-routines = nptl-init nptlfreeres vars 
events version pt-interp \
 Â Â Â Â  Â Â Â  Â Â Â Â Â  pthread_getattr_np \
 Â Â Â Â  Â Â Â  Â Â Â Â Â  pthread_mutex_init pthread_mutex_destroy \
 Â Â Â Â  Â Â Â  Â Â Â Â Â  pthread_mutex_lock pthread_mutex_trylock \
+Â Â Â  Â Â Â  Â Â Â Â Â  pthread_mutex_lock_any pthread_mutex_timedlock_any \
 Â Â Â Â  Â Â Â  Â Â Â Â Â  pthread_mutex_timedlock pthread_mutex_unlock \
 Â Â Â Â  Â Â Â  Â Â Â Â Â  pthread_mutex_cond_lock \
 Â Â Â Â  Â Â Â  Â Â Â Â Â  pthread_mutexattr_init pthread_mutexattr_destroy \
diff --git a/nptl/Versions b/nptl/Versions
index f2ea2b32a1b..1ec7ffffeb6 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -274,6 +274,8 @@ libpthread {
 Â Â Â Â  mtx_init; mtx_lock; mtx_timedlock; mtx_trylock; mtx_unlock; 
mtx_destroy;
 Â Â Â Â  call_once; cnd_broadcast; cnd_destroy; cnd_init; cnd_signal;
 Â Â Â Â  cnd_timedwait; cnd_wait; tss_create; tss_delete; tss_get; tss_set;
+
+Â Â Â  pthread_mutex_lock_any; pthread_mutex_timedlock_any;
 Â Â  }

 Â Â  GLIBC_2.30 {
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index d80662ab07b..d6e89c0a53d 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -390,6 +390,11 @@ extern int __pthread_mutex_trylock (pthread_mutex_t 
*_mutex);
 Â extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
 Â extern int __pthread_mutex_timedlock (pthread_mutex_t *__mutex,
 Â Â Â Â Â  const struct timespec *__abstime);
+extern int __pthread_mutex_lock_any (pthread_mutex_t *__mutex, int 
mutexcount,
+Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â Â  int *outlocked);
+extern int __pthread_mutex_timedlock_any (pthread_mutex_t *__mutex, int 
count,
+Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â  const struct timespec *__abstime,
+Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â  int *outlocked);
 Â extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex)
 Â Â Â Â Â  attribute_hidden;
 Â extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex)
diff --git a/nptl/pthread_mutex_lock_any.c b/nptl/pthread_mutex_lock_any.c
new file mode 100644
index 00000000000..485c213a172
--- /dev/null
+++ b/nptl/pthread_mutex_lock_any.c
@@ -0,0 +1,37 @@
+/* Copyright (C) 2002-2019 Free Software Foundation, Inc.
+Â Â  This file is part of the GNU C Library.
+Â Â  Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+Â Â  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 <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <not-cancel.h>
+#include "pthreadP.h"
+#include <atomic.h>
+#include <lowlevellock.h>
+#include <stap-probe.h>
+
+int
+__pthread_mutex_lock_any (pthread_mutex_t *mutexlist, int mutexcount,
+Â Â Â  Â Â Â  Â Â Â  Â  int *outlocked)
+{
+Â  return __pthread_mutex_timedlock_any(mutexlist, mutexcount, NULL, 
outlocked);
+}
+
+weak_alias (__pthread_mutex_lock_any, pthread_mutex_lock_any)
diff --git a/nptl/pthread_mutex_timedlock_any.c 
b/nptl/pthread_mutex_timedlock_any.c
new file mode 100644
index 00000000000..a95687ce8e1
--- /dev/null
+++ b/nptl/pthread_mutex_timedlock_any.c
@@ -0,0 +1,193 @@
+/* Copyright (C) 2002-2019 Free Software Foundation, Inc.
+Â Â  This file is part of the GNU C Library.
+Â Â  Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+Â Â  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 <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <not-cancel.h>
+#include "pthreadP.h"
+#include <atomic.h>
+#include <lowlevellock.h>
+#include <stap-probe.h>
+
+/* TODO: this probably comes from a kernel header when upstream? */
+struct futex_wait_block {
+Â Â Â  int *uaddr;
+Â Â Â  int val;
+Â Â Â  int bitset;
+} __attribute__((packed));
+
+int
+__pthread_mutex_timedlock_any (pthread_mutex_t *mutexlist, int mutexcount,
+Â Â Â  Â Â Â  Â Â Â  Â Â Â Â Â Â  const struct timespec *abstime, int *outlocked)
+{
+Â  /* This requires futex support */
+#ifndef __NR_futex
+Â  return ENOTSUP;
+#endif
+
+Â  if (mutexlist == NULL)
+Â  {
+Â Â Â  /* User is asking us if kernel supports the feature. */
+
+Â Â Â  /* TODO: how does one check if supported?
+Â Â Â Â  * I was thinking of trying the ioctl once and then returning the 
static
+Â Â Â Â  * cached value, is that OK?
+Â Â Â Â  */
+Â Â Â  return 0;
+Â  }
+
+Â  if (mutexlist != NULL && mutexcount <= 0)
+Â Â Â  return EINVAL;
+
+Â  if (outlocked == NULL)
+Â Â Â  return EINVAL;
+
+Â  int type = PTHREAD_MUTEX_TYPE (mutexlist);
+
+Â  for (int i = 1; i < mutexcount; i++)
+Â  {
+Â Â Â  /* Types have to match, since the PRIVATE flag is OP-global. */
+Â Â Â  if (PTHREAD_MUTEX_TYPE (&mutexlist[i]) != type)
+Â Â Â Â Â  return EINVAL;
+Â  }
+
+Â  int kind = type & PTHREAD_MUTEX_KIND_MASK_NP;
+
+Â  /* TODO: implement recursive, errorcheck and adaptive. */
+Â  if (kind != PTHREAD_MUTEX_NORMAL)
+Â Â Â  return EINVAL;
+
+Â  /* TODO: implement robust. */
+Â  if (type & PTHREAD_MUTEX_ROBUST_NORMAL_NP)
+Â Â Â  return EINVAL;
+
+Â  /* TODO: implement PI. */
+Â  if (type & PTHREAD_MUTEX_PRIO_INHERIT_NP)
+Â Â Â  return EINVAL;
+
+Â  /* TODO: implement PP. */
+Â  if (type & PTHREAD_MUTEX_PRIO_PROTECT_NP)
+Â Â Â  return EINVAL;
+
+Â  pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
+Â  int result;
+
+Â  result = -1;
+
+Â  for (int i = 0; i < mutexcount; i++)
+Â  {
+Â Â Â  if (__lll_trylock (&mutexlist[i].__data.__lock) == 0)
+Â Â Â  {
+Â Â Â Â Â  result = i;
+Â Â Â Â Â  break;
+Â Â Â  }
+Â  }
+
+Â  while (result == -1)
+Â  {
+Â Â Â  for (int i = 0; i < mutexcount; i++)
+Â Â Â  {
+Â Â Â Â Â  int oldval = atomic_exchange_acq (&mutexlist[i].__data.__lock, 2);
+
+Â Â Â Â Â  if (oldval == 0)
+Â Â Â Â Â  {
+Â Â Â  result = i;
+Â Â Â  break;
+Â Â Â Â Â  }
+Â Â Â  }
+
+Â Â Â  if (result == -1)
+Â Â Â  {
+Â Â Â Â Â  /* Couldn't get one of the locks immediately, we have to sleep 
now. */
+Â Â Â Â Â  struct timespec *timeout = NULL;
+Â Â Â Â Â  struct timespec rt;
+
+Â Â Â Â Â  if (abstime != NULL)
+Â Â Â Â Â  {
+Â Â Â  /* Reject invalid timeouts. */
+Â Â Â  if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
+Â Â Â  Â  return EINVAL;
+
+Â Â Â  struct timeval tv;
+
+Â Â Â  /* Get the current time.Â  */
+Â Â Â  (void) __gettimeofday (&tv, NULL);
+
+Â Â Â  /* Compute relative timeout.Â  */
+Â Â Â  rt.tv_sec = abstime->tv_sec - tv.tv_sec;
+Â Â Â  rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
+Â Â Â  if (rt.tv_nsec < 0)
+Â Â Â  {
+Â Â Â  Â  rt.tv_nsec += 1000000000;
+Â Â Â  Â  --rt.tv_sec;
+Â Â Â  }
+
+Â Â Â  if (rt.tv_sec < 0)
+Â Â Â  Â  return ETIMEDOUT;
+
+Â Â Â  timeout = &rt;
+Â Â Â Â Â  }
+
+Â Â Â Â Â  struct futex_wait_block waitblock[mutexcount];
+
+Â Â Â Â Â  for (int i = 0; i < mutexcount; i++)
+Â Â Â Â Â  {
+Â Â Â  waitblock[i].uaddr = &mutexlist[i].__data.__lock;
+Â Â Â  waitblock[i].val = 2;
+Â Â Â  waitblock[i].bitset = ~0;
+Â Â Â Â Â  }
+
+Â Â Â Â Â  long int __ret;
+
+Â Â Â Â Â  /* Safe to use the flag for the first one, since all their types 
match. */
+Â Â Â Â Â  int private_flag = PTHREAD_MUTEX_PSHARED (&mutexlist[0]);
+
+Â Â Â Â Â  __ret = lll_futex_timed_wait_multiple (waitblock, mutexcount, 
timeout,
+Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â  private_flag);
+
+Â Â Â Â Â  if (__ret < 0)
+Â Â Â  return -__ret; /* TODO is this correct? */
+
+Â Â Â Â Â  /* Have slept, try grabbing the one that woke us up? */
+Â Â Â Â Â  if (atomic_exchange_acq (&mutexlist[__ret].__data.__lock, 2) == 0)
+Â Â Â Â Â  {
+Â Â Â  /* We got it, done, loop will end below. */
+Â Â Â  result = __ret;
+Â Â Â Â Â  }
+Â Â Â  }
+Â  }
+
+Â  if (result != -1)
+Â  {
+Â Â Â  /* Record the ownership. */
+Â Â Â  mutexlist[result].__data.__owner = id;
+Â Â Â  ++mutexlist[result].__data.__nusers;
+
+Â Â Â  /* Let the user know which mutex is now locked. */
+Â Â Â  *outlocked = result;
+
+Â Â Â  result = 0;
+Â  }
+
+Â  return result;
+}
+
+weak_alias (__pthread_mutex_timedlock_any, pthread_mutex_timedlock_any)
diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
index a767d6f1808..d9e500f9877 100644
--- a/sysdeps/nptl/pthread.h
+++ b/sysdeps/nptl/pthread.h
@@ -763,7 +763,17 @@ extern int pthread_mutex_trylock (pthread_mutex_t 
*__mutex)
 Â extern int pthread_mutex_lock (pthread_mutex_t *__mutex)
 Â Â Â Â Â  __THROWNL __nonnull ((1));

+/* Lock any one of several mutexes.Â  */
+extern int pthread_mutex_lock_any (pthread_mutex_t *__mutexlist,
+Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â  int mutexcount, int *outlocked);
+
 Â #ifdef __USE_XOPEN2K
+/* Lock any one of several mutexes, with timeout.Â  */
+extern int pthread_mutex_timedlock_any (pthread_mutex_t *__mutexlist,
+Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â  int mutexcount,
+Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â  const struct timespec *__restrict
+Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â  __abstime, int *outlocked);
+
 Â /* Wait until lock becomes available, or specified time passes. */
 Â extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
 Â Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â  const struct timespec *__restrict
diff --git a/sysdeps/unix/sysv/linux/lowlevellock-futex.h 
b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
index cfa796be2bd..28140721648 100644
--- a/sysdeps/unix/sysv/linux/lowlevellock-futex.h
+++ b/sysdeps/unix/sysv/linux/lowlevellock-futex.h
@@ -38,6 +38,7 @@
 Â #define FUTEX_WAKE_BITSETÂ Â Â  10
 Â #define FUTEX_WAIT_REQUEUE_PIÂ Â  11
 Â #define FUTEX_CMP_REQUEUE_PIÂ Â Â  12
+#define FUTEX_WAIT_MULTIPLEÂ Â Â Â  13
 Â #define FUTEX_PRIVATE_FLAGÂ Â Â  128
 Â #define FUTEX_CLOCK_REALTIMEÂ Â Â  256

@@ -74,6 +75,15 @@
 Â Â Â Â Â  ? -INTERNAL_SYSCALL_ERRNO (__ret, __err) : 0);Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  \
 Â Â  })

+#define lll_futex_syscall_ret(nargs, futexp, op, ...)Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  \
+ ({ \
+Â Â Â  INTERNAL_SYSCALL_DECL (__err);Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  \
+Â Â Â  long int __ret = INTERNAL_SYSCALL (futex, __err, nargs, futexp, op, \
+Â Â Â  Â Â Â  Â Â Â  Â Â Â  Â Â Â Â Â Â  __VA_ARGS__);Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  \
+Â Â Â  (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (__ret, __err))Â Â Â Â Â Â Â Â  \
+Â Â Â Â  ? -INTERNAL_SYSCALL_ERRNO (__ret, __err) : __ret);Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  \
+Â  })
+
 Â #define lll_futex_wait(futexp, val, private) \
 Â Â  lll_futex_timed_wait (futexp, val, NULL, private)

@@ -82,6 +92,11 @@
 Â Â Â Â  Â Â Â  Â Â Â Â  __lll_private_flag (FUTEX_WAIT, private),Â  \
 Â Â Â Â  Â Â Â  Â Â Â Â  val, timeout)

+#define lll_futex_timed_wait_multiple(futexp, val, timeout, private)Â Â Â Â  \
+Â  lll_futex_syscall_ret (4, futexp,Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â  \
+Â Â Â  Â Â Â  Â Â Â Â  __lll_private_flag (FUTEX_WAIT_MULTIPLE, private), \
+Â Â Â  Â Â Â  Â Â Â Â  val, timeout)
+
 Â /* Verify whether the supplied clockid is supported by
 Â Â Â  lll_futex_clock_wait_bitset.Â  */
 Â #define lll_futex_supported_clockid(clockid)Â Â Â  Â Â Â  Â Â Â  \
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist 
b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
index 297fec9686d..f9bf1a40509 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libpthread.abilist
@@ -126,6 +126,7 @@ GLIBC_2.2.5 pthread_kill_other_threads_np F
 Â GLIBC_2.2.5 pthread_mutex_destroy F
 Â GLIBC_2.2.5 pthread_mutex_init F
 Â GLIBC_2.2.5 pthread_mutex_lock F
+GLIBC_2.2.5 pthread_mutex_lock_any F
 Â GLIBC_2.2.5 pthread_mutex_timedlock F
 Â GLIBC_2.2.5 pthread_mutex_trylock F
 Â GLIBC_2.2.5 pthread_mutex_unlock F
