diff options
| author | riastradh <riastradh@NetBSD.org> | 2022-05-31 14:23:39 +0000 |
|---|---|---|
| committer | riastradh <riastradh@NetBSD.org> | 2022-05-31 14:23:39 +0000 |
| commit | 83ff393703f8d6dee921b7bd128dcd02b93d8d92 (patch) | |
| tree | af9c5b1a575406732d011558594f14e64adc5905 /lib/libpthread | |
| parent | 1462931797b2339ec25828f24a6876aaa9fd116f (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.c | 32 |
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. */ |
