Module Name:    src
Committed By:   riastradh
Date:           Tue May 31 14:23:39 UTC 2022

Modified Files:
        src/lib/libpthread: pthread.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.180 -r1.181 src/lib/libpthread/pthread.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libpthread/pthread.c
diff -u src/lib/libpthread/pthread.c:1.180 src/lib/libpthread/pthread.c:1.181
--- src/lib/libpthread/pthread.c:1.180	Sat Feb 12 14:59:32 2022
+++ src/lib/libpthread/pthread.c	Tue May 31 14:23:39 2022
@@ -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 
 	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. */

Reply via email to