From patchwork Sat Aug 29 03:28:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rosen Penev X-Patchwork-Id: 1353590 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.openwrt.org (client-ip=2001:8b0:10b:1231::1; helo=merlin.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=lists.infradead.org header.i=@lists.infradead.org header.a=rsa-sha256 header.s=merlin.20170209 header.b=jeyDaVXV; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=e7ooaY/J; dkim-atps=neutral Received: from merlin.infradead.org (merlin.infradead.org [IPv6:2001:8b0:10b:1231::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Bdhm83d7Yz9sTC for ; Sat, 29 Aug 2020 13:29:44 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:List-Subscribe:List-Help:List-Post:List-Archive:List-Unsubscribe :List-Id:MIME-Version:Message-Id:Date:Subject:To:From:Reply-To:Cc:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:In-Reply-To:References:List-Owner; bh=T8w9GH4OB4Kbbcb55BbKP3vXKiKIEygQsDPG45I2ELY=; b=jeyDaVXVCmLX8iGEcVHD7wkP84 h9DkMJefswXOn20zdEmHbj1UfOXANP16fpYMrXTJmyXYKAfJ52siM2jo3W6/lXWH4ZAdPeeF8822v Zx+BeuJzNiqSXU0g2R/r+tg6G2ykx2DUqCWCdAZPRgfp0+W/G/WoA/TzxBqLG4mF5ZcK8TXRd5cP3 ICTrAdI8ItMgP2chfShQWoRgutQxWEAO/t81kiAoCffhO3FC2cKqbNFuJqcoG+W9ABlAbQDDBVgSK X81Nj3XbmGEdROMaOxzowGVF0bZydCivvSkmxTUSXAfOeltDjWQVvzh6XS+9emLF/sRTESjm1HXik XcKV3MMQ==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kBrXY-0001JC-Hw; Sat, 29 Aug 2020 03:28:28 +0000 Received: from mail-pl1-x644.google.com ([2607:f8b0:4864:20::644]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kBrXV-0001Ia-OF for openwrt-devel@lists.openwrt.org; Sat, 29 Aug 2020 03:28:27 +0000 Received: by mail-pl1-x644.google.com with SMTP id y6so538899plt.3 for ; Fri, 28 Aug 2020 20:28:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=/THHPD/shigcQWElGOImvUbl5tgK5J+BmXm4rBbxfvw=; b=e7ooaY/J2a7KpMIdwEIdxs30uA+/+0h8lKpAkdw6S0E8I7r4V5QBFtn7GQyQ30dIMp lzzYtvQaRH9rx0ddocO6oJBP86AV56Jod36G9MHJZv03K4Mw39FvfZ9ZVZMuwp2lOxiK u7JQ8YlaqZoQo1sWMV0MNjD+OudT7aK1ZnSnwuPkNg5H6v/JJnreOA+VvYd6ywdz2JZu qn361KzJbGuM8yYBRlFjr45k2MvFXLa7LM6HTOT3C+zb13ZTaWZKW53MtBoOViORrK5I AqXuZ+nCNJOELmuCBN6LiIfnUE2FvHgyo2XKmw7M23HMT9Sxth3sAKJK/G2nMT4bPukD Q/jA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=/THHPD/shigcQWElGOImvUbl5tgK5J+BmXm4rBbxfvw=; b=GAlfaPODVsVB+dU69E5/MmewkIjQFc/h8Lc41YcIzNQ1Jg248HlK3bo14ABK8VcdRx qH6eXwYAkmKyidnc4FU/pT4fBCqQwptSXeVpHKQ6h9fsDzH7kLrue2+QzcI3XIRouVFZ yFNVxLr7CTVlNxET6ZngqTCkUtfpgvUGQV+7I0F8/biU+kH4Vj1Qq20/f3P4ZFaPm9UB Y8Ro4VtEXGBEESBoUmWjKftupw0RD+WNTv1QUZ2RqFafon+vUd+d6N07DWmaqCuLiExR I0g4Em84b4axVI0Lb2iYBR5AdgrkuFcb5tQQnuxeoUjf+9c56UwWZ337eIrK0l9vXRve J/nQ== X-Gm-Message-State: AOAM530Wr3V99Rm1pkXWMV0Z1RwozgJm0HUWf8LabtUVDFatAEiNClhG jJ11u3HCgd0aM7F7Z5o6+kQDk6/BSql5Iw== X-Google-Smtp-Source: ABdhPJwQdQjHRCptKFOyxn7WZ0Wvagyr19vAgUr7xZ0gRPR8rDOMfaRd1JW5U9rYgbaTdqL4+1gPaQ== X-Received: by 2002:a17:902:a985:: with SMTP id bh5mr1468242plb.175.1598671703025; Fri, 28 Aug 2020 20:28:23 -0700 (PDT) Received: from mangix-trapnet.lan ([2001:470:1f05:79e::a89]) by smtp.gmail.com with ESMTPSA id g129sm862489pfb.33.2020.08.28.20.28.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 28 Aug 2020 20:28:22 -0700 (PDT) From: Rosen Penev To: openwrt-devel@lists.openwrt.org Subject: [PATCH 1/2] toolchain/musl: update to 1.2.1 Date: Fri, 28 Aug 2020 20:28:20 -0700 Message-Id: <20200829032821.252703-1-rosenp@gmail.com> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200828_232825_847199_32DB1D82 X-CRM114-Status: GOOD ( 33.70 ) X-Spam-Score: 1.5 (+) X-Spam-Report: SpamAssassin version 3.4.4 on merlin.infradead.org summary: Content analysis details: (1.5 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [2607:f8b0:4864:20:0:0:0:644 listed in] [list.dnswl.org] 1.7 URIBL_BLACK Contains an URL listed in the URIBL blacklist [URIs: libc.so] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider [rosenp[at]gmail.com] -0.0 SPF_PASS SPF: sender matches SPF record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org This release introduces 64-bit time_t, which is needed to avoid the year 2038 problem. Remove upstream patches. Rebased features.h file based on latest musl. Signed-off-by: Rosen Penev --- v4: remove sys/cdefs.h as well. v3: rebase and split commit between version update and header removal. v2: removed more glibc headers. toolchain/musl/common.mk | 4 +- toolchain/musl/include/features.h | 10 ++- .../patches/200-add_libssp_nonshared.patch | 8 +- toolchain/musl/patches/300-relative.patch | 2 +- ...ist-unlink-in-pthread_exit-after-all.patch | 51 ----------- ...hreads_minus_1-as-relaxed-atomic-for.patch | 69 -------------- ...own-size-of-some-libc-struct-members.patch | 25 ------ ...pping-for-processes-that-return-to-s.patch | 90 ------------------- 8 files changed, 16 insertions(+), 243 deletions(-) delete mode 100644 toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch delete mode 100644 toolchain/musl/patches/500-0002-don-t-use-libc.threads_minus_1-as-relaxed-atomic-for.patch delete mode 100644 toolchain/musl/patches/500-0003-cut-down-size-of-some-libc-struct-members.patch delete mode 100644 toolchain/musl/patches/500-0004-restore-lock-skipping-for-processes-that-return-to-s.patch diff --git a/toolchain/musl/common.mk b/toolchain/musl/common.mk index 6a59577108..44d2ed5603 100644 --- a/toolchain/musl/common.mk +++ b/toolchain/musl/common.mk @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/target.mk PKG_NAME:=musl -PKG_VERSION:=1.1.24 +PKG_VERSION:=1.2.1 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://musl.libc.org/releases/ -PKG_HASH:=1370c9a812b2cf2a7d92802510cca0058cc37e66a7bedd70051f0a34015022a3 +PKG_HASH:=68af6e18539f646f9c41a3a2bb25be4a5cfa5a8f65f0bb647fd2bbfdf877e84b LIBC_SO_VERSION:=$(PKG_VERSION) PATCH_DIR:=$(PATH_PREFIX)/patches diff --git a/toolchain/musl/include/features.h b/toolchain/musl/include/features.h index edb8cc72d4..e801e2299a 100644 --- a/toolchain/musl/include/features.h +++ b/toolchain/musl/include/features.h @@ -1,10 +1,14 @@ #ifndef _FEATURES_H #define _FEATURES_H -#ifdef _ALL_SOURCE +#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) #define _GNU_SOURCE 1 #endif +#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) +#define _BSD_SOURCE 1 +#endif + #if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) @@ -20,6 +24,8 @@ #if __STDC_VERSION__ >= 199901L || defined(__cplusplus) #define __inline inline +#elif !defined(__GNUC__) +#define __inline #endif #if __STDC_VERSION__ >= 201112L @@ -29,6 +35,8 @@ #define _Noreturn #endif +#define __REDIR(x,y) __typeof__(x) x __asm__(#y) + /* Convenience macros to test the versions of glibc and gcc. Use them like this: #if __GNUC_PREREQ (2,8) diff --git a/toolchain/musl/patches/200-add_libssp_nonshared.patch b/toolchain/musl/patches/200-add_libssp_nonshared.patch index 05bd2fe54a..26a9bfebea 100644 --- a/toolchain/musl/patches/200-add_libssp_nonshared.patch +++ b/toolchain/musl/patches/200-add_libssp_nonshared.patch @@ -7,7 +7,7 @@ Signed-off-by: Steven Barth --- a/Makefile +++ b/Makefile -@@ -66,7 +66,7 @@ CRT_LIBS = $(addprefix lib/,$(notdir $(C +@@ -67,7 +67,7 @@ CRT_LIBS = $(addprefix lib/,$(notdir $(C STATIC_LIBS = lib/libc.a SHARED_LIBS = lib/libc.so TOOL_LIBS = lib/musl-gcc.specs @@ -16,7 +16,7 @@ Signed-off-by: Steven Barth ALL_TOOLS = obj/musl-gcc WRAPCC_GCC = gcc -@@ -86,7 +86,7 @@ else +@@ -88,7 +88,7 @@ else all: $(ALL_LIBS) $(ALL_TOOLS) @@ -25,7 +25,7 @@ Signed-off-by: Steven Barth $(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(ALL_OBJS:%.o=%.lo) $(GENH) $(GENH_INT): | $(OBJ_DIRS) -@@ -113,6 +113,8 @@ obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart. +@@ -115,6 +115,8 @@ obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart. obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC @@ -34,7 +34,7 @@ Signed-off-by: Steven Barth OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%)) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3 -@@ -165,6 +167,11 @@ lib/libc.a: $(AOBJS) +@@ -167,6 +169,11 @@ lib/libc.a: $(AOBJS) $(AR) rc $@ $(AOBJS) $(RANLIB) $@ diff --git a/toolchain/musl/patches/300-relative.patch b/toolchain/musl/patches/300-relative.patch index e34e60a09d..7e1eb7d6bc 100644 --- a/toolchain/musl/patches/300-relative.patch +++ b/toolchain/musl/patches/300-relative.patch @@ -1,6 +1,6 @@ --- a/Makefile +++ b/Makefile -@@ -215,7 +215,7 @@ $(DESTDIR)$(includedir)/%: $(srcdir)/inc +@@ -217,7 +217,7 @@ $(DESTDIR)$(includedir)/%: $(srcdir)/inc $(INSTALL) -D -m 644 $< $@ $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so diff --git a/toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch b/toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch deleted file mode 100644 index d47f2f4108..0000000000 --- a/toolchain/musl/patches/500-0001-reorder-thread-list-unlink-in-pthread_exit-after-all.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 4d5aa20a94a2d3fae3e69289dc23ecafbd0c16c4 Mon Sep 17 00:00:00 2001 -From: Rich Felker -Date: Fri, 22 May 2020 17:35:14 -0400 -Subject: [PATCH 1/4] reorder thread list unlink in pthread_exit after all - locks - -since the backend for LOCK() skips locking if single-threaded, it's -unsafe to make the process appear single-threaded before the last use -of lock. - -this fixes potential unsynchronized access to a linked list via -__dl_thread_cleanup. ---- - src/thread/pthread_create.c | 19 +++++++++++-------- - 1 file changed, 11 insertions(+), 8 deletions(-) - ---- a/src/thread/pthread_create.c -+++ b/src/thread/pthread_create.c -@@ -90,14 +90,7 @@ _Noreturn void __pthread_exit(void *resu - exit(0); - } - -- /* At this point we are committed to thread termination. Unlink -- * the thread from the list. This change will not be visible -- * until the lock is released, which only happens after SYS_exit -- * has been called, via the exit futex address pointing at the lock. */ -- libc.threads_minus_1--; -- self->next->prev = self->prev; -- self->prev->next = self->next; -- self->prev = self->next = self; -+ /* At this point we are committed to thread termination. */ - - /* Process robust list in userspace to handle non-pshared mutexes - * and the detached thread case where the robust list head will -@@ -121,6 +114,16 @@ _Noreturn void __pthread_exit(void *resu - __do_orphaned_stdio_locks(); - __dl_thread_cleanup(); - -+ /* Last, unlink thread from the list. This change will not be visible -+ * until the lock is released, which only happens after SYS_exit -+ * has been called, via the exit futex address pointing at the lock. -+ * This needs to happen after any possible calls to LOCK() that might -+ * skip locking if libc.threads_minus_1 is zero. */ -+ libc.threads_minus_1--; -+ self->next->prev = self->prev; -+ self->prev->next = self->next; -+ self->prev = self->next = self; -+ - /* This atomic potentially competes with a concurrent pthread_detach - * call; the loser is responsible for freeing thread resources. */ - int state = a_cas(&self->detach_state, DT_JOINABLE, DT_EXITING); diff --git a/toolchain/musl/patches/500-0002-don-t-use-libc.threads_minus_1-as-relaxed-atomic-for.patch b/toolchain/musl/patches/500-0002-don-t-use-libc.threads_minus_1-as-relaxed-atomic-for.patch deleted file mode 100644 index 4ca51b0be0..0000000000 --- a/toolchain/musl/patches/500-0002-don-t-use-libc.threads_minus_1-as-relaxed-atomic-for.patch +++ /dev/null @@ -1,69 +0,0 @@ -From e01b5939b38aea5ecbe41670643199825874b26c Mon Sep 17 00:00:00 2001 -From: Rich Felker -Date: Thu, 21 May 2020 23:32:45 -0400 -Subject: [PATCH 2/4] don't use libc.threads_minus_1 as relaxed atomic for - skipping locks - -after all but the last thread exits, the next thread to observe -libc.threads_minus_1==0 and conclude that it can skip locking fails to -synchronize with any changes to memory that were made by the -last-exiting thread. this can produce data races. - -on some archs, at least x86, memory synchronization is unlikely to be -a problem; however, with the inline locks in malloc, skipping the lock -also eliminated the compiler barrier, and caused code that needed to -re-check chunk in-use bits after obtaining the lock to reuse a stale -value, possibly from before the process became single-threaded. this -in turn produced corruption of the heap state. - -some uses of libc.threads_minus_1 remain, especially for allocation of -new TLS in the dynamic linker; otherwise, it could be removed -entirely. it's made non-volatile to reflect that the remaining -accesses are only made under lock on the thread list. - -instead of libc.threads_minus_1, libc.threaded is now used for -skipping locks. the difference is that libc.threaded is permanently -true once an additional thread has been created. this will produce -some performance regression in processes that are mostly -single-threaded but occasionally creating threads. in the future it -may be possible to bring back the full lock-skipping, but more care -needs to be taken to produce a safe design. ---- - src/internal/libc.h | 2 +- - src/malloc/malloc.c | 2 +- - src/thread/__lock.c | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - ---- a/src/internal/libc.h -+++ b/src/internal/libc.h -@@ -21,7 +21,7 @@ struct __libc { - int can_do_threads; - int threaded; - int secure; -- volatile int threads_minus_1; -+ int threads_minus_1; - size_t *auxv; - struct tls_module *tls_head; - size_t tls_size, tls_align, tls_cnt; ---- a/src/malloc/malloc.c -+++ b/src/malloc/malloc.c -@@ -26,7 +26,7 @@ int __malloc_replaced; - - static inline void lock(volatile int *lk) - { -- if (libc.threads_minus_1) -+ if (libc.threaded) - while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1); - } - ---- a/src/thread/__lock.c -+++ b/src/thread/__lock.c -@@ -18,7 +18,7 @@ - - void __lock(volatile int *l) - { -- if (!libc.threads_minus_1) return; -+ if (!libc.threaded) return; - /* fast path: INT_MIN for the lock, +1 for the congestion */ - int current = a_cas(l, 0, INT_MIN + 1); - if (!current) return; diff --git a/toolchain/musl/patches/500-0003-cut-down-size-of-some-libc-struct-members.patch b/toolchain/musl/patches/500-0003-cut-down-size-of-some-libc-struct-members.patch deleted file mode 100644 index 6650434397..0000000000 --- a/toolchain/musl/patches/500-0003-cut-down-size-of-some-libc-struct-members.patch +++ /dev/null @@ -1,25 +0,0 @@ -From f12888e9eb9eed60cc266b899dcafecb4752964a Mon Sep 17 00:00:00 2001 -From: Rich Felker -Date: Fri, 22 May 2020 17:25:38 -0400 -Subject: [PATCH 3/4] cut down size of some libc struct members - -these are all flags that can be single-byte values. ---- - src/internal/libc.h | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/src/internal/libc.h -+++ b/src/internal/libc.h -@@ -18,9 +18,9 @@ struct tls_module { - }; - - struct __libc { -- int can_do_threads; -- int threaded; -- int secure; -+ char can_do_threads; -+ char threaded; -+ char secure; - int threads_minus_1; - size_t *auxv; - struct tls_module *tls_head; diff --git a/toolchain/musl/patches/500-0004-restore-lock-skipping-for-processes-that-return-to-s.patch b/toolchain/musl/patches/500-0004-restore-lock-skipping-for-processes-that-return-to-s.patch deleted file mode 100644 index 83a6d0247a..0000000000 --- a/toolchain/musl/patches/500-0004-restore-lock-skipping-for-processes-that-return-to-s.patch +++ /dev/null @@ -1,90 +0,0 @@ -From 8d81ba8c0bc6fe31136cb15c9c82ef4c24965040 Mon Sep 17 00:00:00 2001 -From: Rich Felker -Date: Fri, 22 May 2020 17:45:47 -0400 -Subject: [PATCH 4/4] restore lock-skipping for processes that return to - single-threaded state - -the design used here relies on the barrier provided by the first lock -operation after the process returns to single-threaded state to -synchronize with actions by the last thread that exited. by storing -the intent to change modes in the same object used to detect whether -locking is needed, it's possible to avoid an extra (possibly costly) -memory load after the lock is taken. ---- - src/internal/libc.h | 1 + - src/malloc/malloc.c | 5 ++++- - src/thread/__lock.c | 4 +++- - src/thread/pthread_create.c | 8 ++++---- - 4 files changed, 12 insertions(+), 6 deletions(-) - ---- a/src/internal/libc.h -+++ b/src/internal/libc.h -@@ -21,6 +21,7 @@ struct __libc { - char can_do_threads; - char threaded; - char secure; -+ volatile signed char need_locks; - int threads_minus_1; - size_t *auxv; - struct tls_module *tls_head; ---- a/src/malloc/malloc.c -+++ b/src/malloc/malloc.c -@@ -26,8 +26,11 @@ int __malloc_replaced; - - static inline void lock(volatile int *lk) - { -- if (libc.threaded) -+ int need_locks = libc.need_locks; -+ if (need_locks) { - while(a_swap(lk, 1)) __wait(lk, lk+1, 1, 1); -+ if (need_locks < 0) libc.need_locks = 0; -+ } - } - - static inline void unlock(volatile int *lk) ---- a/src/thread/__lock.c -+++ b/src/thread/__lock.c -@@ -18,9 +18,11 @@ - - void __lock(volatile int *l) - { -- if (!libc.threaded) return; -+ int need_locks = libc.need_locks; -+ if (!need_locks) return; - /* fast path: INT_MIN for the lock, +1 for the congestion */ - int current = a_cas(l, 0, INT_MIN + 1); -+ if (need_locks < 0) libc.need_locks = 0; - if (!current) return; - /* A first spin loop, for medium congestion. */ - for (unsigned i = 0; i < 10; ++i) { ---- a/src/thread/pthread_create.c -+++ b/src/thread/pthread_create.c -@@ -118,8 +118,8 @@ _Noreturn void __pthread_exit(void *resu - * until the lock is released, which only happens after SYS_exit - * has been called, via the exit futex address pointing at the lock. - * This needs to happen after any possible calls to LOCK() that might -- * skip locking if libc.threads_minus_1 is zero. */ -- libc.threads_minus_1--; -+ * skip locking if process appears single-threaded. */ -+ if (!--libc.threads_minus_1) libc.need_locks = -1; - self->next->prev = self->prev; - self->prev->next = self->next; - self->prev = self->next = self; -@@ -339,7 +339,7 @@ int __pthread_create(pthread_t *restrict - ~(1UL<<((SIGCANCEL-1)%(8*sizeof(long)))); - - __tl_lock(); -- libc.threads_minus_1++; -+ if (!libc.threads_minus_1++) libc.need_locks = 1; - ret = __clone((c11 ? start_c11 : start), stack, flags, args, &new->tid, TP_ADJ(new), &__thread_list_lock); - - /* All clone failures translate to EAGAIN. If explicit scheduling -@@ -363,7 +363,7 @@ int __pthread_create(pthread_t *restrict - new->next->prev = new; - new->prev->next = new; - } else { -- libc.threads_minus_1--; -+ if (!--libc.threads_minus_1) libc.need_locks = 0; - } - __tl_unlock(); - __restore_sigs(&set);