summaryrefslogtreecommitdiff
path: root/lib/libpthread
diff options
context:
space:
mode:
authorriastradh <riastradh@NetBSD.org>2022-05-31 14:23:39 +0000
committerriastradh <riastradh@NetBSD.org>2022-05-31 14:23:39 +0000
commit83ff393703f8d6dee921b7bd128dcd02b93d8d92 (patch)
treeaf9c5b1a575406732d011558594f14e64adc5905 /lib/libpthread
parent1462931797b2339ec25828f24a6876aaa9fd116f (diff)
libpthread(3): Fix a marvellous interaction with rtld.
Patch from chs@. Comment explaining the story by me. This patch may not be optimal -- maybe it would be better in pthread__init, or better for rtld to call _lwp_unpark after _lwp_park in the contened case -- but we've tested this version and it's annoying to reproduce, so let's take this version and worry about testing improvements later.
Diffstat (limited to 'lib/libpthread')
-rw-r--r--lib/libpthread/pthread.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/lib/libpthread/pthread.c b/lib/libpthread/pthread.c
index 7efd65993cf..80f775a34aa 100644
--- a/lib/libpthread/pthread.c
+++ b/lib/libpthread/pthread.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread.c,v 1.180 2022/02/12 14:59:32 riastradh Exp $ */
+/* $NetBSD: pthread.c,v 1.181 2022/05/31 14:23:39 riastradh Exp $ */
/*-
* Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008, 2020
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread.c,v 1.180 2022/02/12 14:59:32 riastradh Exp $");
+__RCSID("$NetBSD: pthread.c,v 1.181 2022/05/31 14:23:39 riastradh Exp $");
#define __EXPOSE_STACK 1
@@ -414,6 +414,34 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
else
return EINVAL;
+ if (!pthread__started) {
+ /*
+ * Force the _lwp_park symbol to be resolved before we
+ * begin any activity that might rely on concurrent
+ * wakeups.
+ *
+ * This is necessary because rtld itself uses _lwp_park
+ * and _lwp_unpark internally for its own locking: If
+ * we wait to resolve _lwp_park until there is an
+ * _lwp_unpark from another thread pending in the
+ * current lwp (for example, pthread_mutex_unlock or
+ * pthread_cond_signal), rtld's internal use of
+ * _lwp_park might consume the pending unpark. The
+ * result is a deadlock where libpthread and rtld have
+ * both correctly used _lwp_park and _lwp_unpark for
+ * themselves, but rtld has consumed the wakeup meant
+ * for libpthread so it is lost to libpthread.
+ *
+ * For the very first thread, before pthread__started
+ * is set to true, pthread__self()->pt_lid should have
+ * been initialized in pthread__init by the time we get
+ * here to the correct lid so we go to sleep and wake
+ * ourselves at the same time as a no-op.
+ */
+ _lwp_park(CLOCK_REALTIME, 0, NULL, pthread__self()->pt_lid,
+ NULL, NULL);
+ }
+
pthread__started = 1;
/* Fetch misc. attributes from the attr structure. */