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. */