about summary refs log tree commit diff
path: root/sysdeps/mach/hurd/htl
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/hurd/htl')
-rw-r--r--sysdeps/mach/hurd/htl/Implies2
-rw-r--r--sysdeps/mach/hurd/htl/bits/pthread-np.h37
-rw-r--r--sysdeps/mach/hurd/htl/bits/types/struct___pthread_mutex.h49
-rw-r--r--sysdeps/mach/hurd/htl/pt-attr-setstackaddr.c27
-rw-r--r--sysdeps/mach/hurd/htl/pt-attr-setstacksize.c27
-rw-r--r--sysdeps/mach/hurd/htl/pt-docancel.c65
-rw-r--r--sysdeps/mach/hurd/htl/pt-hurd-cond-timedwait.c169
-rw-r--r--sysdeps/mach/hurd/htl/pt-hurd-cond-wait.c40
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex-consistent.c48
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex-destroy.c38
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex-getprioceiling.c35
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex-init.c56
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex-lock.c81
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex-setprioceiling.c36
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex-timedlock.c79
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex-transfer-np.c77
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex-trylock.c85
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex-unlock.c92
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutex.h90
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-destroy.c34
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-getprioceiling.c35
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-getprotocol.c32
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-getpshared.c32
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-getrobust.c35
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-gettype.c32
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-init.c40
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-setprioceiling.c35
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-setprotocol.c34
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-setpshared.c35
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-setrobust.c37
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr-settype.c36
-rw-r--r--sysdeps/mach/hurd/htl/pt-mutexattr.c1
-rw-r--r--sysdeps/mach/hurd/htl/pt-sigstate-destroy.c26
-rw-r--r--sysdeps/mach/hurd/htl/pt-sigstate-init.c44
-rw-r--r--sysdeps/mach/hurd/htl/pt-sigstate.c70
-rw-r--r--sysdeps/mach/hurd/htl/pt-sysdep.c99
-rw-r--r--sysdeps/mach/hurd/htl/pt-sysdep.h65
37 files changed, 1855 insertions, 0 deletions
diff --git a/sysdeps/mach/hurd/htl/Implies b/sysdeps/mach/hurd/htl/Implies
new file mode 100644
index 0000000000..64daad184a
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/Implies
@@ -0,0 +1,2 @@
+hurd/htl
+mach/htl
diff --git a/sysdeps/mach/hurd/htl/bits/pthread-np.h b/sysdeps/mach/hurd/htl/bits/pthread-np.h
new file mode 100644
index 0000000000..0acee62186
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/bits/pthread-np.h
@@ -0,0 +1,37 @@
+/* Non-portable functions. Hurd on Mach version.
+   Copyright (C) 2008-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*
+ * Never include this file directly; use <pthread.h> or <cthreads.h> instead.
+ */
+
+#ifndef _BITS_PTHREAD_NP_H
+#define _BITS_PTHREAD_NP_H	1
+
+/* Same as pthread_cond_wait, but for Hurd-specific cancellation.
+   See hurd_thread_cancel.  */
+extern int pthread_hurd_cond_wait_np (pthread_cond_t *__restrict __cond,
+				      pthread_mutex_t *__restrict __mutex);
+
+/* Same as pthread_cond_timedwait, but for Hurd-specific cancellation.
+   See hurd_thread_cancel.  */
+extern int pthread_hurd_cond_timedwait_np (pthread_cond_t *__restrict __cond,
+					   pthread_mutex_t *__restrict __mutex,
+					   const struct timespec *__abstime);
+
+#endif /* bits/pthread-np.h */
diff --git a/sysdeps/mach/hurd/htl/bits/types/struct___pthread_mutex.h b/sysdeps/mach/hurd/htl/bits/types/struct___pthread_mutex.h
new file mode 100644
index 0000000000..4fe87cc5f5
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/bits/types/struct___pthread_mutex.h
@@ -0,0 +1,49 @@
+/* Mutex type.  Generic version.
+   Copyright (C) 2000-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _BITS_TYPES_STRUCT___PTHREAD_MUTEX_H
+#define _BITS_TYPES_STRUCT___PTHREAD_MUTEX_H	1
+
+#include <bits/types/struct___pthread_mutexattr.h>
+
+/* User visible part of a mutex.  */
+struct __pthread_mutex
+{
+  unsigned int __lock;
+  unsigned int __owner_id;
+  unsigned int __cnt;
+  int __shpid;
+  int __type;
+  int __flags;
+  unsigned int __reserved1;
+  unsigned int __reserved2;
+};
+
+/* Static mutex initializers. */
+#define __PTHREAD_MUTEX_INITIALIZER   \
+  { 0, 0, 0, 0, __PTHREAD_MUTEX_TIMED, 0, 0, 0 }
+
+/* The +1 is to mantain binary compatibility with the old
+ * libpthread implementation. */
+#define __PTHREAD_ERRORCHECK_MUTEX_INITIALIZER   \
+  { 0, 0, 0, 0, __PTHREAD_MUTEX_ERRORCHECK + 1, 0, 0, 0 }
+
+#define __PTHREAD_RECURSIVE_MUTEX_INITIALIZER   \
+  { 0, 0, 0, 0, __PTHREAD_MUTEX_RECURSIVE + 1, 0, 0, 0 }
+
+#endif /* bits/types/struct___pthread_mutex.h */
diff --git a/sysdeps/mach/hurd/htl/pt-attr-setstackaddr.c b/sysdeps/mach/hurd/htl/pt-attr-setstackaddr.c
new file mode 100644
index 0000000000..711ae67043
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-attr-setstackaddr.c
@@ -0,0 +1,27 @@
+/* pthread_attr_setstackaddr.  Hurd on Mach version.
+   Copyright (C) 2002-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <pt-internal.h>
+
+int
+pthread_attr_setstackaddr (pthread_attr_t *attr, void *stackaddr)
+{
+  attr->__stackaddr = stackaddr;
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-attr-setstacksize.c b/sysdeps/mach/hurd/htl/pt-attr-setstacksize.c
new file mode 100644
index 0000000000..6a96370ebe
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-attr-setstacksize.c
@@ -0,0 +1,27 @@
+/* pthread_attr_setstacksize.  Hurd on Mach version.
+   Copyright (C) 2002-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <pt-internal.h>
+
+int
+pthread_attr_setstacksize (pthread_attr_t *attr, size_t stacksize)
+{
+  attr->__stacksize = stacksize;
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-docancel.c b/sysdeps/mach/hurd/htl/pt-docancel.c
new file mode 100644
index 0000000000..a8bcb24cdb
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-docancel.c
@@ -0,0 +1,65 @@
+/* Cancel a thread.
+   Copyright (C) 2002-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+
+#include <pt-internal.h>
+
+static void
+call_exit (void)
+{
+  pthread_exit (0);
+}
+
+int
+__pthread_do_cancel (struct __pthread *p)
+{
+  mach_port_t ktid;
+  int me;
+
+  assert (p->cancel_pending == 1);
+  assert (p->cancel_state == PTHREAD_CANCEL_ENABLE);
+
+  __pthread_mutex_unlock (&p->cancel_lock);
+
+  ktid = __mach_thread_self ();
+  me = p->kernel_thread == ktid;
+  __mach_port_deallocate (__mach_task_self (), ktid);
+
+  if (me)
+    call_exit ();
+  else
+    {
+      error_t err;
+
+      err = __thread_suspend (p->kernel_thread);
+      assert_perror (err);
+
+      err = __thread_abort (p->kernel_thread);
+      assert_perror (err);
+
+      err = __thread_set_pcsptp (p->kernel_thread,
+				 1, (void *) call_exit, 0, 0, 0, 0);
+      assert_perror (err);
+
+      err = __thread_resume (p->kernel_thread);
+      assert_perror (err);
+    }
+
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-hurd-cond-timedwait.c b/sysdeps/mach/hurd/htl/pt-hurd-cond-timedwait.c
new file mode 100644
index 0000000000..41792e3711
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-hurd-cond-timedwait.c
@@ -0,0 +1,169 @@
+/* pthread_hurd_cond_timedwait_np.  Hurd-specific wait on a condition.
+   Copyright (C) 2012-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <assert.h>
+#include <hurd/signal.h>
+
+#include <pt-internal.h>
+
+extern int __pthread_hurd_cond_timedwait_internal (pthread_cond_t *cond,
+						   pthread_mutex_t *mutex,
+						   const struct timespec
+						   *abstime);
+
+int
+__pthread_hurd_cond_timedwait_np (pthread_cond_t *cond,
+				  pthread_mutex_t *mutex,
+				  const struct timespec *abstime)
+{
+  return __pthread_hurd_cond_timedwait_internal (cond, mutex, abstime);
+}
+
+strong_alias (__pthread_hurd_cond_timedwait_np, pthread_hurd_cond_timedwait_np);
+
+int
+__pthread_hurd_cond_timedwait_internal (pthread_cond_t *cond,
+					pthread_mutex_t *mutex,
+					const struct timespec *abstime)
+{
+  struct hurd_sigstate *ss = _hurd_self_sigstate ();
+  struct __pthread *self = _pthread_self ();
+  error_t err = 0;
+  int cancel, drain;
+  clockid_t clock_id = __pthread_default_condattr.__clock;
+
+  /* This function will be called by hurd_thread_cancel while we are blocked
+     We wake up our thread if it's still blocking or about to block, so it will
+     progress and notice the cancellation flag.  */
+  void cancel_me (void)
+  {
+    int unblock;
+
+    __pthread_spin_lock (&cond->__lock);
+    /* The thread only needs to be awaken if it's blocking or about to block.
+       If it was already unblocked, it's not queued any more.  */
+    unblock = self->prevp != NULL;
+    if (unblock)
+      __pthread_dequeue (self);
+    __pthread_spin_unlock (&cond->__lock);
+
+    if (unblock)
+      __pthread_wakeup (self);
+  }
+
+  assert (ss->intr_port == MACH_PORT_NULL);	/* Sanity check for signal bugs. */
+
+  if (abstime != NULL && (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000))
+    return EINVAL;
+
+  /* Atomically enqueue our thread on the condition variable's queue of
+     waiters, and mark our sigstate to indicate that `cancel_me' must be
+     called to wake us up.  We must hold the sigstate lock while acquiring
+     the condition variable's lock and tweaking it, so that
+     hurd_thread_cancel can never suspend us and then deadlock waiting for
+     the condition variable's lock.  */
+
+  __spin_lock (&ss->lock);
+  __pthread_spin_lock (&cond->__lock);
+  cancel = ss->cancel;
+  if (cancel)
+    /* We were cancelled before doing anything.  Don't block at all.  */
+    ss->cancel = 0;
+  else
+    {
+      /* Put us on the queue so that pthread_cond_broadcast will know to wake
+         us up.  */
+      __pthread_enqueue (&cond->__queue, self);
+      if (cond->__attr)
+	clock_id = cond->__attr->__clock;
+      /* Tell hurd_thread_cancel how to unblock us.  */
+      ss->cancel_hook = &cancel_me;
+    }
+  __pthread_spin_unlock (&cond->__lock);
+  __spin_unlock (&ss->lock);
+
+  if (cancel)
+    {
+      /* Cancelled on entry.  Just leave the mutex locked.  */
+      mutex = NULL;
+
+      __spin_lock (&ss->lock);
+    }
+  else
+    {
+      /* Release MUTEX before blocking.  */
+      __pthread_mutex_unlock (mutex);
+
+      /* Block the thread.  */
+      if (abstime != NULL)
+	err = __pthread_timedblock (self, abstime, clock_id);
+      else
+	{
+	  err = 0;
+	  __pthread_block (self);
+	}
+
+      /* As it was done when enqueueing, prevent hurd_thread_cancel from
+         suspending us while the condition lock is held.  */
+      __spin_lock (&ss->lock);
+      __pthread_spin_lock (&cond->__lock);
+      if (self->prevp == NULL)
+	/* Another thread removed us from the list of waiters, which means
+	   a wakeup message has been sent.  It was either consumed while
+	   we were blocking, or queued after we timed out and before we
+	   acquired the condition lock, in which case the message queue
+	   must be drained.  */
+	drain = err ? 1 : 0;
+      else
+	{
+	  /* We're still in the list of waiters.  Noone attempted to wake us
+	     up, i.e. we timed out.  */
+	  __pthread_dequeue (self);
+	  drain = 0;
+	}
+      __pthread_spin_unlock (&cond->__lock);
+
+      if (drain)
+	__pthread_block (self);
+    }
+
+  /* Clear the hook, now that we are done blocking.  */
+  ss->cancel_hook = NULL;
+  /* Check the cancellation flag; we might have unblocked due to
+     cancellation rather than a normal pthread_cond_signal or
+     pthread_cond_broadcast (or we might have just happened to get cancelled
+     right after waking up).  */
+  cancel |= ss->cancel;
+  ss->cancel = 0;
+  __spin_unlock (&ss->lock);
+
+  if (mutex != NULL)
+    /* Reacquire the mutex and return.  */
+    __pthread_mutex_lock (mutex);
+
+  if (cancel)
+    return EINTR;
+  else if (err)
+    {
+      assert (err == ETIMEDOUT);
+      return err;
+    }
+
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-hurd-cond-wait.c b/sysdeps/mach/hurd/htl/pt-hurd-cond-wait.c
new file mode 100644
index 0000000000..2f2b6c293f
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-hurd-cond-wait.c
@@ -0,0 +1,40 @@
+/* pthread_hurd_cond_wait.  Hurd-specific wait on a condition.
+   Copyright (C) 2012-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <assert.h>
+#include <hurd/signal.h>
+
+#include <pt-internal.h>
+
+/* Implemented in pt-hurd-cond-timedwait.c.  */
+extern int __pthread_hurd_cond_timedwait_internal (pthread_cond_t *cond,
+						   pthread_mutex_t *mutex,
+						   const struct timespec
+						   *abstime);
+
+int
+__pthread_hurd_cond_wait_np (pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+  error_t err;
+
+  err = __pthread_hurd_cond_timedwait_internal (cond, mutex, NULL);
+  return err == EINTR;
+}
+
+strong_alias (__pthread_hurd_cond_wait_np, pthread_hurd_cond_wait_np);
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-consistent.c b/sysdeps/mach/hurd/htl/pt-mutex-consistent.c
new file mode 100644
index 0000000000..9fd6342be4
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex-consistent.c
@@ -0,0 +1,48 @@
+/* pthread_mutex_consistent.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutex_consistent (pthread_mutex_t *mtxp)
+{
+  int ret = EINVAL;
+  unsigned int val = mtxp->__lock;
+
+  if ((mtxp->__flags & PTHREAD_MUTEX_ROBUST) != 0 &&
+      (val & LLL_DEAD_OWNER) != 0 &&
+      atomic_compare_and_exchange_bool_acq (&mtxp->__lock,
+					    __getpid () | LLL_WAITERS,
+					    val) == 0)
+    {
+      /* The mutex is now ours, and it's consistent. */
+      mtxp->__owner_id = _pthread_self ()->thread;
+      mtxp->__cnt = 1;
+      ret = 0;
+    }
+
+  return ret;
+}
+
+weak_alias (pthread_mutex_consistent, pthread_mutex_consistent_np)
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-destroy.c b/sysdeps/mach/hurd/htl/pt-mutex-destroy.c
new file mode 100644
index 0000000000..89b4916eb6
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex-destroy.c
@@ -0,0 +1,38 @@
+/* pthread_mutex_destroy.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+_pthread_mutex_destroy (pthread_mutex_t *mtxp)
+{
+  atomic_read_barrier ();
+  if (*(volatile unsigned int *) &mtxp->__lock != 0)
+    return EBUSY;
+
+  mtxp->__type = -1;
+  return 0;
+}
+
+strong_alias (_pthread_mutex_destroy, pthread_mutex_destroy)
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-getprioceiling.c b/sysdeps/mach/hurd/htl/pt-mutex-getprioceiling.c
new file mode 100644
index 0000000000..fa6b82b667
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex-getprioceiling.c
@@ -0,0 +1,35 @@
+/* pthread_mutex_getprioceiling.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutex_getprioceiling (const pthread_mutex_t *mtxp, int *clp)
+{
+  (void) mtxp;
+  (void) clp;
+  return ENOSYS;
+}
+
+stub_warning (pthread_mutex_getprioceiling)
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-init.c b/sysdeps/mach/hurd/htl/pt-mutex-init.c
new file mode 100644
index 0000000000..8218eb150e
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex-init.c
@@ -0,0 +1,56 @@
+/* pthread_mutex_init.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+static const pthread_mutexattr_t dfl_attr = {
+  .__prioceiling = 0,
+  .__protocol = PTHREAD_PRIO_NONE,
+  .__pshared = PTHREAD_PROCESS_PRIVATE,
+  .__mutex_type = __PTHREAD_MUTEX_TIMED
+};
+
+int
+_pthread_mutex_init (pthread_mutex_t *mtxp, const pthread_mutexattr_t *attrp)
+{
+  if (attrp == NULL)
+    attrp = &dfl_attr;
+
+  mtxp->__flags = (attrp->__pshared == PTHREAD_PROCESS_SHARED ?
+		   GSYNC_SHARED : 0) | ((attrp->
+					 __prioceiling & PTHREAD_MUTEX_ROBUST) ?
+					PTHREAD_MUTEX_ROBUST : 0);
+
+  mtxp->__type = attrp->__mutex_type +
+      (attrp->__mutex_type != __PTHREAD_MUTEX_TIMED);
+
+  mtxp->__owner_id = 0;
+  mtxp->__shpid = 0;
+  mtxp->__cnt = 0;
+  mtxp->__lock = 0;
+
+  return 0;
+}
+
+strong_alias (_pthread_mutex_init, pthread_mutex_init)
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-lock.c b/sysdeps/mach/hurd/htl/pt-mutex-lock.c
new file mode 100644
index 0000000000..e4a86f0e49
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex-lock.c
@@ -0,0 +1,81 @@
+/* pthread_mutex_lock.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+__pthread_mutex_lock (pthread_mutex_t *mtxp)
+{
+  struct __pthread *self;
+  int flags = mtxp->__flags & GSYNC_SHARED;
+  int ret = 0;
+
+  switch (MTX_TYPE (mtxp))
+    {
+    case PT_MTX_NORMAL:
+      lll_lock (&mtxp->__lock, flags);
+      break;
+
+    case PT_MTX_RECURSIVE:
+      self = _pthread_self ();
+      if (mtx_owned_p (mtxp, self, flags))
+	{
+	  if (__glibc_unlikely (mtxp->__cnt + 1 == 0))
+	    return EAGAIN;
+
+	  ++mtxp->__cnt;
+	  return ret;
+	}
+
+      lll_lock (&mtxp->__lock, flags);
+      mtx_set_owner (mtxp, self, flags);
+      mtxp->__cnt = 1;
+      break;
+
+    case PT_MTX_ERRORCHECK:
+      self = _pthread_self ();
+      if (mtx_owned_p (mtxp, self, flags))
+	return EDEADLK;
+
+      lll_lock (&mtxp->__lock, flags);
+      mtx_set_owner (mtxp, self, flags);
+      break;
+
+    case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST:
+    case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST:
+    case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST:
+      self = _pthread_self ();
+      ROBUST_LOCK (self, mtxp, __lll_robust_lock, flags);
+      break;
+
+    default:
+      ret = EINVAL;
+      break;
+    }
+
+  return ret;
+}
+
+strong_alias (__pthread_mutex_lock, _pthread_mutex_lock)
+strong_alias (__pthread_mutex_lock, pthread_mutex_lock)
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-setprioceiling.c b/sysdeps/mach/hurd/htl/pt-mutex-setprioceiling.c
new file mode 100644
index 0000000000..5f39ebb959
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex-setprioceiling.c
@@ -0,0 +1,36 @@
+/* pthread_mutex_setprioceiling.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutex_setprioceiling (pthread_mutex_t *mtxp, int cl, int *prp)
+{
+  (void) mtxp;
+  (void) cl;
+  (void) prp;
+  return ENOSYS;
+}
+
+stub_warning (pthread_mutex_setprioceiling)
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-timedlock.c b/sysdeps/mach/hurd/htl/pt-mutex-timedlock.c
new file mode 100644
index 0000000000..0457445c86
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex-timedlock.c
@@ -0,0 +1,79 @@
+/* pthread_mutex_timedlock.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutex_timedlock (pthread_mutex_t *mtxp, const struct timespec *tsp)
+{
+  struct __pthread *self;
+  int ret, flags = mtxp->__flags & GSYNC_SHARED;
+
+  switch (MTX_TYPE (mtxp))
+    {
+    case PT_MTX_NORMAL:
+      ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags);
+      break;
+
+    case PT_MTX_RECURSIVE:
+      self = _pthread_self ();
+      if (mtx_owned_p (mtxp, self, flags))
+	{
+	  if (__glibc_unlikely (mtxp->__cnt + 1 == 0))
+	    return EAGAIN;
+
+	  ++mtxp->__cnt;
+	  ret = 0;
+	}
+      else if ((ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags)) == 0)
+	{
+	  mtx_set_owner (mtxp, self, flags);
+	  mtxp->__cnt = 1;
+	}
+
+      break;
+
+    case PT_MTX_ERRORCHECK:
+      self = _pthread_self ();
+      if (mtx_owned_p (mtxp, self, flags))
+	ret = EDEADLK;
+      else if ((ret = lll_abstimed_lock (&mtxp->__lock, tsp, flags)) == 0)
+	mtx_set_owner (mtxp, self, flags);
+
+      break;
+
+    case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST:
+    case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST:
+    case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST:
+      self = _pthread_self ();
+      ROBUST_LOCK (self, mtxp, lll_robust_abstimed_lock, tsp, flags);
+      break;
+
+    default:
+      ret = EINVAL;
+      break;
+    }
+
+  return ret;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-transfer-np.c b/sysdeps/mach/hurd/htl/pt-mutex-transfer-np.c
new file mode 100644
index 0000000000..e89c8dcac7
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex-transfer-np.c
@@ -0,0 +1,77 @@
+/* pthread_mutex_transfer_np.  Transfer mutex ownership to another thread.
+   Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+__pthread_mutex_transfer_np (pthread_mutex_t *mtxp, pthread_t th)
+{
+  struct __pthread *self = _pthread_self ();
+  struct __pthread *pt = __pthread_getid (th);
+
+  if (pt == NULL)
+    return ESRCH;
+  else if (pt == self)
+    return 0;
+
+  int ret = 0;
+  int flags = mtxp->__flags & GSYNC_SHARED;
+
+  switch (MTX_TYPE (mtxp))
+    {
+    case PT_MTX_NORMAL:
+      break;
+
+    case PT_MTX_RECURSIVE:
+    case PT_MTX_ERRORCHECK:
+      if (!mtx_owned_p (mtxp, self, flags))
+	ret = EPERM;
+      else
+	mtx_set_owner (mtxp, pt, flags);
+
+      break;
+
+    case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST:
+    case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST:
+    case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST:
+      /* Note that this can be used to transfer an inconsistent
+       * mutex as well. The new owner will still have the same
+       * flags as the original. */
+      if (mtxp->__owner_id != self->thread ||
+	  (int) (mtxp->__lock & LLL_OWNER_MASK) != __getpid ())
+	ret = EPERM;
+      else
+	mtxp->__owner_id = pt->thread;
+
+      break;
+
+    default:
+      ret = EINVAL;
+    }
+
+  return ret;
+}
+
+weak_alias (__pthread_mutex_transfer_np, pthread_mutex_transfer_np)
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-trylock.c b/sysdeps/mach/hurd/htl/pt-mutex-trylock.c
new file mode 100644
index 0000000000..36d4f5921c
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex-trylock.c
@@ -0,0 +1,85 @@
+/* pthread_mutex_trylock.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+__pthread_mutex_trylock (pthread_mutex_t *mtxp)
+{
+  struct __pthread *self;
+  int ret;
+
+  switch (MTX_TYPE (mtxp))
+    {
+    case PT_MTX_NORMAL:
+      ret = lll_trylock (&mtxp->__lock);
+      if (ret)
+	ret = EBUSY;
+      break;
+
+    case PT_MTX_RECURSIVE:
+      self = _pthread_self ();
+      if (mtx_owned_p (mtxp, self, mtxp->__flags))
+	{
+	  if (__glibc_unlikely (mtxp->__cnt + 1 == 0))
+	    return EAGAIN;
+
+	  ++mtxp->__cnt;
+	  ret = 0;
+	}
+      else if ((ret = lll_trylock (&mtxp->__lock)) == 0)
+	{
+	  mtx_set_owner (mtxp, self, mtxp->__flags);
+	  mtxp->__cnt = 1;
+	}
+      else
+	ret = EBUSY;
+
+      break;
+
+    case PT_MTX_ERRORCHECK:
+      self = _pthread_self ();
+      if ((ret = lll_trylock (&mtxp->__lock)) == 0)
+	mtx_set_owner (mtxp, self, mtxp->__flags);
+      else
+	ret = EBUSY;
+      break;
+
+    case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST:
+    case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST:
+    case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST:
+      self = _pthread_self ();
+      ROBUST_LOCK (self, mtxp, __lll_robust_trylock);
+      break;
+
+    default:
+      ret = EINVAL;
+      break;
+    }
+
+  return ret;
+}
+
+strong_alias (__pthread_mutex_trylock, _pthread_mutex_trylock)
+strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock)
diff --git a/sysdeps/mach/hurd/htl/pt-mutex-unlock.c b/sysdeps/mach/hurd/htl/pt-mutex-unlock.c
new file mode 100644
index 0000000000..30c62fcb24
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex-unlock.c
@@ -0,0 +1,92 @@
+/* pthread_mutex_unlock.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+__pthread_mutex_unlock (pthread_mutex_t *mtxp)
+{
+  struct __pthread *self;
+  int ret = 0, flags = mtxp->__flags & GSYNC_SHARED;
+
+  switch (MTX_TYPE (mtxp))
+    {
+    case PT_MTX_NORMAL:
+      lll_unlock (&mtxp->__lock, flags);
+      break;
+
+    case PT_MTX_RECURSIVE:
+      self = _pthread_self ();
+      if (!mtx_owned_p (mtxp, self, flags))
+	ret = EPERM;
+      else if (--mtxp->__cnt == 0)
+	{
+	  mtxp->__owner_id = mtxp->__shpid = 0;
+	  lll_unlock (&mtxp->__lock, flags);
+	}
+
+      break;
+
+    case PT_MTX_ERRORCHECK:
+      self = _pthread_self ();
+      if (!mtx_owned_p (mtxp, self, flags))
+	ret = EPERM;
+      else
+	{
+	  mtxp->__owner_id = mtxp->__shpid = 0;
+	  lll_unlock (&mtxp->__lock, flags);
+	}
+
+      break;
+
+    case PT_MTX_NORMAL | PTHREAD_MUTEX_ROBUST:
+    case PT_MTX_RECURSIVE | PTHREAD_MUTEX_ROBUST:
+    case PT_MTX_ERRORCHECK | PTHREAD_MUTEX_ROBUST:
+      self = _pthread_self ();
+      if (mtxp->__owner_id == NOTRECOVERABLE_ID)
+	;			/* Nothing to do. */
+      else if (mtxp->__owner_id != self->thread ||
+	       (int) (mtxp->__lock & LLL_OWNER_MASK) != __getpid ())
+	ret = EPERM;
+      else if (--mtxp->__cnt == 0)
+	{
+	  /* Release the lock. If it's in an inconsistent
+	   * state, mark it as irrecoverable. */
+	  mtxp->__owner_id = (mtxp->__lock & LLL_DEAD_OWNER) ?
+	      NOTRECOVERABLE_ID : 0;
+	  __lll_robust_unlock (&mtxp->__lock, flags);
+	}
+
+      break;
+
+    default:
+      ret = EINVAL;
+      break;
+    }
+
+  return ret;
+}
+
+strong_alias (__pthread_mutex_unlock, _pthread_mutex_unlock)
+strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
diff --git a/sysdeps/mach/hurd/htl/pt-mutex.h b/sysdeps/mach/hurd/htl/pt-mutex.h
new file mode 100644
index 0000000000..2daf63e986
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutex.h
@@ -0,0 +1,90 @@
+/* Internal definitions for pthreads library.
+   Copyright (C) 2016-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_MUTEX_H
+#define _PT_MUTEX_H	1
+
+/* Special ID used to signal an unrecoverable robust mutex. */
+#define NOTRECOVERABLE_ID   (1U << 31)
+
+/* Common path for robust mutexes. Assumes the variable 'ret'
+ * is bound in the function this is called from. */
+#define ROBUST_LOCK(self, mtxp, cb, ...)   \
+  if (mtxp->__owner_id == NOTRECOVERABLE_ID)   \
+    return ENOTRECOVERABLE;   \
+  else if (mtxp->__owner_id == self->thread &&   \
+      __getpid () == (int)(mtxp->__lock & LLL_OWNER_MASK))   \
+    {   \
+      if (mtxp->__type == PT_MTX_RECURSIVE)   \
+        {   \
+          if (__glibc_unlikely (mtxp->__cnt + 1 == 0))   \
+            return EAGAIN;   \
+          \
+          ++mtxp->__cnt;   \
+          return 0;   \
+        }   \
+      else if (mtxp->__type == PT_MTX_ERRORCHECK)   \
+        return EDEADLK;   \
+    }   \
+  \
+  ret = cb (&mtxp->__lock, ##__VA_ARGS__);   \
+  if (ret == 0 || ret == EOWNERDEAD)   \
+    {   \
+      if (mtxp->__owner_id == ENOTRECOVERABLE)   \
+        ret = ENOTRECOVERABLE;   \
+      else   \
+        {   \
+          mtxp->__owner_id = self->thread;   \
+          mtxp->__cnt = 1;   \
+          if (ret == EOWNERDEAD)   \
+            {   \
+              mtxp->__lock = mtxp->__lock | LLL_DEAD_OWNER;   \
+              atomic_write_barrier ();   \
+            }   \
+        }   \
+    }   \
+  (void)0
+
+/* Check that a thread owns the mutex. For non-robust, task-shared
+ * objects, we have to check the thread *and* process-id. */
+#define mtx_owned_p(mtx, pt, flags)   \
+  ((mtx)->__owner_id == (pt)->thread &&   \
+    (((flags) & GSYNC_SHARED) == 0 ||   \
+      (mtx)->__shpid == __getpid ()))
+
+/* Record a thread as the owner of the mutex. */
+#define mtx_set_owner(mtx, pt, flags)   \
+  (void)   \
+    ({   \
+       (mtx)->__owner_id = (pt)->thread;   \
+       if ((flags) & GSYNC_SHARED)   \
+         (mtx)->__shpid = __getpid ();   \
+     })
+
+/* Redefined mutex types. The +1 is for binary compatibility. */
+#define PT_MTX_NORMAL       __PTHREAD_MUTEX_TIMED
+#define PT_MTX_RECURSIVE    (__PTHREAD_MUTEX_RECURSIVE + 1)
+#define PT_MTX_ERRORCHECK   (__PTHREAD_MUTEX_ERRORCHECK + 1)
+
+/* Mutex type, including robustness. */
+#define MTX_TYPE(mtxp)   \
+  ((mtxp)->__type | ((mtxp)->__flags & PTHREAD_MUTEX_ROBUST))
+
+extern int __getpid (void) __attribute__ ((const));
+
+#endif /* pt-mutex.h */
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-destroy.c b/sysdeps/mach/hurd/htl/pt-mutexattr-destroy.c
new file mode 100644
index 0000000000..9c6cffc5bd
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-destroy.c
@@ -0,0 +1,34 @@
+/* pthread_mutexattr_destroy.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+__pthread_mutexattr_destroy (pthread_mutexattr_t *attrp)
+{
+  (void) attrp;
+  return 0;
+}
+
+weak_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy)
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-getprioceiling.c b/sysdeps/mach/hurd/htl/pt-mutexattr-getprioceiling.c
new file mode 100644
index 0000000000..4532eca989
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-getprioceiling.c
@@ -0,0 +1,35 @@
+/* pthread_mutexattr_getprioceiling.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *ap, int *clp)
+{
+  (void) ap;
+  (void) clp;
+  return ENOSYS;
+}
+
+stub_warning (pthread_mutexattr_getprioceiling)
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-getprotocol.c b/sysdeps/mach/hurd/htl/pt-mutexattr-getprotocol.c
new file mode 100644
index 0000000000..33cdc158b2
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-getprotocol.c
@@ -0,0 +1,32 @@
+/* pthread_mutexattr_getprotocol.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutexattr_getprotocol (const pthread_mutexattr_t *attrp, int *ptp)
+{
+  *ptp = attrp->__protocol;
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-getpshared.c b/sysdeps/mach/hurd/htl/pt-mutexattr-getpshared.c
new file mode 100644
index 0000000000..d393b4bb7f
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-getpshared.c
@@ -0,0 +1,32 @@
+/* pthread_mutexattr_getpshared.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutexattr_getpshared (const pthread_mutexattr_t *attrp, int *outp)
+{
+  *outp = attrp->__pshared;
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-getrobust.c b/sysdeps/mach/hurd/htl/pt-mutexattr-getrobust.c
new file mode 100644
index 0000000000..0999db02d7
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-getrobust.c
@@ -0,0 +1,35 @@
+/* pthread_mutexattr_getrobust.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutexattr_getrobust (const pthread_mutexattr_t *attrp, int *outp)
+{
+  *outp = (attrp->__prioceiling & PTHREAD_MUTEX_ROBUST) ?
+      PTHREAD_MUTEX_ROBUST : PTHREAD_MUTEX_STALLED;
+  return 0;
+}
+
+weak_alias (pthread_mutexattr_getrobust, pthread_mutexattr_getrobust_np)
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-gettype.c b/sysdeps/mach/hurd/htl/pt-mutexattr-gettype.c
new file mode 100644
index 0000000000..6881a5b816
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-gettype.c
@@ -0,0 +1,32 @@
+/* pthread_mutexattr_gettype.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutexattr_gettype (const pthread_mutexattr_t *attrp, int *outp)
+{
+  *outp = attrp->__mutex_type;
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-init.c b/sysdeps/mach/hurd/htl/pt-mutexattr-init.c
new file mode 100644
index 0000000000..b135126553
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-init.c
@@ -0,0 +1,40 @@
+/* pthread_mutexattr_init.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+static const pthread_mutexattr_t dfl_attr = {
+  .__prioceiling = 0,
+  .__protocol = PTHREAD_PRIO_NONE,
+  .__pshared = PTHREAD_PROCESS_PRIVATE,
+  .__mutex_type = __PTHREAD_MUTEX_TIMED
+};
+
+int
+__pthread_mutexattr_init (pthread_mutexattr_t *attrp)
+{
+  *attrp = dfl_attr;
+  return 0;
+}
+weak_alias (__pthread_mutexattr_init, pthread_mutexattr_init)
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-setprioceiling.c b/sysdeps/mach/hurd/htl/pt-mutexattr-setprioceiling.c
new file mode 100644
index 0000000000..6011ffb94e
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-setprioceiling.c
@@ -0,0 +1,35 @@
+/* pthread_mutexattr_setprioceiling.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attrp, int cl)
+{
+  (void) attrp;
+  (void) cl;
+  return ENOSYS;
+}
+
+stub_warning (pthread_mutexattr_setprioceiling)
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-setprotocol.c b/sysdeps/mach/hurd/htl/pt-mutexattr-setprotocol.c
new file mode 100644
index 0000000000..5173a487c4
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-setprotocol.c
@@ -0,0 +1,34 @@
+/* pthread_mutexattr_setprotocol.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutexattr_setprotocol (pthread_mutexattr_t *attrp, int proto)
+{
+  (void) attrp;
+  return proto == PTHREAD_PRIO_NONE ? 0 :
+	 proto != PTHREAD_PRIO_INHERIT &&
+	 proto != PTHREAD_PRIO_PROTECT ? EINVAL : ENOTSUP;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-setpshared.c b/sysdeps/mach/hurd/htl/pt-mutexattr-setpshared.c
new file mode 100644
index 0000000000..7e0e607151
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-setpshared.c
@@ -0,0 +1,35 @@
+/* pthread_mutexattr_setpshared.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutexattr_setpshared (pthread_mutexattr_t *attrp, int pshared)
+{
+  if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED)
+    return EINVAL;
+
+  attrp->__pshared = pshared;
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-setrobust.c b/sysdeps/mach/hurd/htl/pt-mutexattr-setrobust.c
new file mode 100644
index 0000000000..f38c7a747e
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-setrobust.c
@@ -0,0 +1,37 @@
+/* pthread_mutexattr_setrobust.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+pthread_mutexattr_setrobust (pthread_mutexattr_t *attrp, int robust)
+{
+  if (robust != PTHREAD_MUTEX_ROBUST && robust != PTHREAD_MUTEX_STALLED)
+    return EINVAL;
+
+  attrp->__prioceiling |= robust;
+  return 0;
+}
+
+weak_alias (pthread_mutexattr_setrobust, pthread_mutexattr_setrobust_np)
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr-settype.c b/sysdeps/mach/hurd/htl/pt-mutexattr-settype.c
new file mode 100644
index 0000000000..c856fd7859
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr-settype.c
@@ -0,0 +1,36 @@
+/* pthread_mutexattr_settype.  Hurd version.
+   Copyright (C) 2016-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License
+   as published by the Free Software Foundation; either
+   version 2 of the license, or (at your option) any later version.
+
+   This program 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 Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this program; if not, see
+   <http://www.gnu.org/licenses/>.
+*/
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <pt-internal.h>
+#include "pt-mutex.h"
+#include <hurdlock.h>
+
+int
+__pthread_mutexattr_settype (pthread_mutexattr_t *attrp, int type)
+{
+  if (type < 0 || type > __PTHREAD_MUTEX_RECURSIVE)
+    return EINVAL;
+
+  attrp->__mutex_type = type;
+  return 0;
+}
+weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype)
diff --git a/sysdeps/mach/hurd/htl/pt-mutexattr.c b/sysdeps/mach/hurd/htl/pt-mutexattr.c
new file mode 100644
index 0000000000..40a8c178f1
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-mutexattr.c
@@ -0,0 +1 @@
+/* empty */
diff --git a/sysdeps/mach/hurd/htl/pt-sigstate-destroy.c b/sysdeps/mach/hurd/htl/pt-sigstate-destroy.c
new file mode 100644
index 0000000000..69de5cad01
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-sigstate-destroy.c
@@ -0,0 +1,26 @@
+/* Destroy the signal state.  Hurd on Mach version.
+   Copyright (C) 2002-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+
+#include <pt-internal.h>
+
+void
+__pthread_sigstate_destroy (struct __pthread *thread)
+{
+}
diff --git a/sysdeps/mach/hurd/htl/pt-sigstate-init.c b/sysdeps/mach/hurd/htl/pt-sigstate-init.c
new file mode 100644
index 0000000000..a6b4f76b25
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-sigstate-init.c
@@ -0,0 +1,44 @@
+/* Initialize the signal state.  Hurd on Mach version.
+   Copyright (C) 2002-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <pt-internal.h>
+#include <hurd/signal.h>
+
+error_t
+__pthread_sigstate_init (struct __pthread *thread)
+{
+  static int do_init_global;
+
+  /* Mark the thread as a global signal receiver so as to conform with
+     the pthread semantics.  However, we must be careful.  The first
+     pthread created is the main thread, during libpthread initialization.
+     We must not mark it, otherwise the sigprocmask call in
+     __pthread_create would try to access _hurd_global_sigstate,
+     which is not initialized yet.  When glibc runs _hurdsig_init later
+     on, the message thread is created, which must not be marked either.  */
+  if (do_init_global)
+    {
+      struct hurd_sigstate *ss = _hurd_thread_sigstate (thread->kernel_thread);
+      (void) ss;
+    }
+  else if (__pthread_num_threads >= 2)
+    do_init_global = 1;
+
+  return 0;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-sigstate.c b/sysdeps/mach/hurd/htl/pt-sigstate.c
new file mode 100644
index 0000000000..5f0a1b4f9a
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-sigstate.c
@@ -0,0 +1,70 @@
+/* Set a thread's signal state.  Hurd on Mach version.
+   Copyright (C) 2002-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <pthread.h>
+#include <assert.h>
+#include <signal.h>
+#include <hurd/signal.h>
+
+#include <pt-internal.h>
+
+error_t
+__pthread_sigstate (struct __pthread *thread, int how,
+		    const sigset_t *set, sigset_t *oset, int clear_pending)
+{
+  error_t err = 0;
+  struct hurd_sigstate *ss;
+
+  ss = _hurd_thread_sigstate (thread->kernel_thread);
+  assert (ss);
+
+  __spin_lock (&ss->lock);
+
+  if (oset != NULL)
+    *oset = ss->blocked;
+
+  if (set != NULL)
+    {
+      switch (how)
+	{
+	case SIG_BLOCK:
+	  ss->blocked |= *set;
+	  break;
+
+	case SIG_SETMASK:
+	  ss->blocked = *set;
+	  break;
+
+	case SIG_UNBLOCK:
+	  ss->blocked &= ~*set;
+	  break;
+
+	default:
+	  err = EINVAL;
+	  break;
+	}
+      ss->blocked &= ~_SIG_CANT_MASK;
+    }
+
+  if (!err && clear_pending)
+    __sigemptyset (&ss->pending);
+
+  __spin_unlock (&ss->lock);
+
+  return err;
+}
diff --git a/sysdeps/mach/hurd/htl/pt-sysdep.c b/sysdeps/mach/hurd/htl/pt-sysdep.c
new file mode 100644
index 0000000000..40ebc8e6d6
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-sysdep.c
@@ -0,0 +1,99 @@
+/* System dependent pthreads code.  Hurd version.
+   Copyright (C) 2000-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <mach.h>
+#include <mach/mig_support.h>
+
+#include <pt-internal.h>
+
+__thread struct __pthread *___pthread_self;
+
+/* Forward.  */
+static void *init_routine (void);
+
+/* OK, the name of this variable isn't really appropriate, but I don't
+   want to change it yet.  */
+void *(*_cthread_init_routine) (void) = &init_routine;
+
+/* This function is called from the Hurd-specific startup code.  It
+   should return a new stack pointer for the main thread.  The caller
+   will switch to this new stack before doing anything serious.  */
+static void *
+_init_routine (void *stack)
+{
+  struct __pthread *thread;
+  int err;
+  pthread_attr_t attr, *attrp = 0;
+
+  if (__pthread_threads != NULL)
+    /* Already initialized */
+    return 0;
+
+  /* Initialize the library.  */
+  ___pthread_init ();
+
+  if (stack != NULL)
+    {
+      /* We are getting initialized due to dlopening a library using libpthread
+         while the main program was not linked against libpthread.  */
+      /* Avoid allocating another stack */
+      attrp = &attr;
+      pthread_attr_init (attrp);
+      pthread_attr_setstack (attrp, stack, __vm_page_size);
+    }
+
+  /* Create the pthread structure for the main thread (i.e. us).  */
+  err = __pthread_create_internal (&thread, attrp, 0, 0);
+  assert_perror (err);
+
+  /* XXX The caller copies the command line arguments and the environment
+     to the new stack.  Pretend it wasn't allocated so that it remains
+     valid if the main thread terminates.  */
+  thread->stack = 0;
+
+  ___pthread_self = thread;
+
+  /* Decrease the number of threads, to take into account that the
+     signal thread (which will be created by the glibc startup code
+     when we return from here) shouldn't be seen as a user thread.  */
+  __pthread_total--;
+
+  /* Make MiG code thread aware.  */
+  __mig_init (thread->stackaddr);
+
+  return thread->mcontext.sp;
+}
+
+static void *
+init_routine (void)
+{
+  return _init_routine (0);
+}
+
+#ifdef SHARED
+__attribute__ ((constructor))
+static void
+dynamic_init_routine (void)
+{
+  _init_routine (__libc_stack_end);
+}
+#endif
diff --git a/sysdeps/mach/hurd/htl/pt-sysdep.h b/sysdeps/mach/hurd/htl/pt-sysdep.h
new file mode 100644
index 0000000000..09778068b7
--- /dev/null
+++ b/sysdeps/mach/hurd/htl/pt-sysdep.h
@@ -0,0 +1,65 @@
+/* Internal definitions for pthreads library.
+   Copyright (C) 2000-2018 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 Library General Public License as
+   published by the Free Software Foundation; either version 2 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
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _PT_SYSDEP_H
+#define _PT_SYSDEP_H	1
+
+#include <mach.h>
+
+/* XXX */
+#define _POSIX_THREAD_THREADS_MAX	64
+
+/* The default stack size.  */
+#define PTHREAD_STACK_DEFAULT	(8 * 1024 * 1024)
+
+#define PTHREAD_SYSDEP_MEMBERS \
+  thread_t kernel_thread;      \
+  mach_msg_header_t wakeupmsg;
+
+extern __thread struct __pthread *___pthread_self;
+#define _pthread_self()                                            \
+	({                                                         \
+	  struct __pthread *thread;                                \
+	                                                           \
+	  assert (__pthread_threads);                              \
+	  thread = ___pthread_self;                                \
+	                                                           \
+	  assert (thread);                                         \
+	  assert (({ mach_port_t ktid = __mach_thread_self ();     \
+                     int ok = thread->kernel_thread == ktid;       \
+                     __mach_port_deallocate (__mach_task_self (), ktid);\
+                     ok; }));                                      \
+          thread;                                                  \
+         })
+
+extern inline void
+__attribute__ ((__always_inline__))
+__pthread_stack_dealloc (void *stackaddr, size_t stacksize)
+{
+  __vm_deallocate (__mach_task_self (), (vm_offset_t) stackaddr, stacksize);
+}
+
+/* Change thread THREAD's program counter to PC if SET_PC is true,
+   its stack pointer to SP if SET_IP is true, and its thread pointer
+   to TP if SET_TP is true.  */
+extern int __thread_set_pcsptp (thread_t thread,
+				int set_pc, void *pc,
+				int set_sp, void *sp, int set_tp, void *tp);
+
+
+#endif /* pt-sysdep.h */