From ce1622418ad86740b990af77050b5e5993c5c3b0 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Sat, 8 Jan 2022 20:36:14 -0600 Subject: system/musl: update to latest version. fixes #444. --- system/musl/APKBUILD | 18 ++- system/musl/CVE-2020-28928.patch | 112 --------------- system/musl/amalgamation.patch | 49 ++++--- system/musl/handle-aux-at_base.patch | 4 +- system/musl/threads_minus_1.patch | 267 ----------------------------------- 5 files changed, 39 insertions(+), 411 deletions(-) delete mode 100644 system/musl/CVE-2020-28928.patch delete mode 100644 system/musl/threads_minus_1.patch (limited to 'system') diff --git a/system/musl/APKBUILD b/system/musl/APKBUILD index 735541e51..56fadc5e2 100644 --- a/system/musl/APKBUILD +++ b/system/musl/APKBUILD @@ -1,7 +1,8 @@ # Maintainer: A. Wilcox pkgname=musl -pkgver=1.2.0 -pkgrel=2 +pkgver=1.2.3_pre1 +pkgrel=0 +pkgdate=20211129 pkgdesc="System library (libc) implementation" url="https://www.musl-libc.org/" arch="all" @@ -21,18 +22,17 @@ nolibc) ;; triggers="$pkgname-utils.trigger=/etc/ld.so.conf.d" ;; esac -source="https://musl.libc.org/releases/$pkgname-$pkgver.tar.gz +source="https://distfiles.adelielinux.org/source/$pkgname-$pkgver-$pkgdate.tar.xz amalgamation.patch 3001-make-real-lastlog-h.patch handle-aux-at_base.patch fgetspent_r.patch - threads_minus_1.patch - CVE-2020-28928.patch ldconfig getent.c iconv.c " +builddir="$srcdir/$pkgname-$pkgver-$pkgdate" # secfixes: # 1.1.15-r4: @@ -120,13 +120,11 @@ utils() { install -D -m755 "$srcdir"/ldconfig "$subpkgdir"/sbin } -sha512sums="58bd88189a6002356728cea1c6f6605a893fe54f7687595879add4eab283c8692c3b031eb9457ad00d1edd082cfe62fcc0eb5eb1d3bf4f1d749c0efa2a95fec1 musl-1.2.0.tar.gz -f01ab92b9d385c15369c0bb7d95e1bc06a009c8851e363517d0ba1bae3fc2647af69fc2f363b5d962d376c5d9a1994b5728fd88ccbfff5f0d3d0970a02df1512 amalgamation.patch +sha512sums="b8a9790a79571854a0a95cb4fcc2dcc9f705879fafdb9c3ec7088dd72649b60449a8370df9337a734af7198a39337684a7662d2ce411d284ca435ad597b900fc musl-1.2.3_pre1-20211129.tar.xz +f7b05d8c5f804ba3ad6998b3de5fa4d9dfceac4aca63dd67298c2d5f27cdd28a91eba74f6e428c258323da80635dd333bae2c47ff918894797cba92bd5700909 amalgamation.patch 88ae443dbb8e0a4368235bdc3a1c5c7b718495afa75e06deb8e01becc76cb1f0d6964589e2204fc749c9c1b3190b8b9ac1ae2c0099cab8e2ce3ec877103d4332 3001-make-real-lastlog-h.patch -6a7ff16d95b5d1be77e0a0fbb245491817db192176496a57b22ab037637d97a185ea0b0d19da687da66c2a2f5578e4343d230f399d49fe377d8f008410974238 handle-aux-at_base.patch +1f4e9aea5a546015c75f77aa0dec10d56fc14831ccc15cf71ff27fc15ac5230ffeadb382ebe1c87c1ea07a462620e16ed01cd36252d997d1a9c2af11cb5c9ff3 handle-aux-at_base.patch ded41235148930f8cf781538f7d63ecb0c65ea4e8ce792565f3649ee2523592a76b2a166785f0b145fc79f5852fd1fb1729a7a09110b3b8f85cba3912e790807 fgetspent_r.patch -68830961e297d9a499f3b609be84848ad5d3326a1af56e9e54a40ecd972c48da11532c51da572d45e0df3574d63191e7ae0d3a1b84a029365f8d00691de96952 threads_minus_1.patch -343ac5e5365cf98a5d5b7bc192c671733fdba27f06b83484f1ac7647154228745415f62dd676029de538460f8b35e0a70ca453a0f8b73226ed1c420099b1cf90 CVE-2020-28928.patch cb71d29a87f334c75ecbc911becde7be825ab30d8f39fa6d64cb53812a7c9abaf91d9804c72540e5be3ddd3c84cfe7fd9632274309005cb8bcdf9a9b09b4b923 ldconfig 378d70e65bcc65bb4e1415354cecfa54b0c1146dfb24474b69e418cdbf7ad730472cd09f6f103e1c99ba6c324c9560bccdf287f5889bbc3ef0bdf0e08da47413 getent.c 9d42d66fb1facce2b85dad919be5be819ee290bd26ca2db00982b2f8e055a0196290a008711cbe2b18ec9eee8d2270e3b3a4692c5a1b807013baa5c2b70a2bbf iconv.c" diff --git a/system/musl/CVE-2020-28928.patch b/system/musl/CVE-2020-28928.patch deleted file mode 100644 index cc668e149..000000000 --- a/system/musl/CVE-2020-28928.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 3ab2a4e02682df1382955071919d8aa3c3ec40d4 Mon Sep 17 00:00:00 2001 -From: Rich Felker -Date: Thu, 19 Nov 2020 17:12:43 -0500 -Subject: [PATCH] rewrite wcsnrtombs to fix buffer overflow and other bugs - -the original wcsnrtombs implementation, which has been largely -untouched since 0.5.0, attempted to build input-length-limiting -conversion on top of wcsrtombs, which only limits output length. as -best I recall, this choice was made out of a mix of disdain over -having yet another variant function to implement (added in POSIX 2008; -not standard C) and preference not to switch things around and -implement the wcsrtombs in terms of the more general new function, -probably over namespace issues. the strategy employed was to impose -output limits that would ensure the input limit wasn't exceeded, then -finish up the tail character-at-a-time. unfortunately, none of that -worked correctly. - -first, the logic in the wcsrtombs loop was wrong in that it could -easily get stuck making no forward progress, by imposing an output -limit too small to convert even one character. - -the character-at-a-time loop that followed was even worse. it made no -effort to ensure that the converted multibyte character would fit in -the remaining output space, only that there was a nonzero amount of -output space remaining. it also employed an incorrect interpretation -of wcrtomb's interface contract for converting the null character, -thereby failing to act on end of input, and remaining space accounting -was subject to unsigned wrap-around. together these errors allow -unbounded overflow of the destination buffer, controlled by input -length limit and input wchar_t string contents. - -given the extent to which this function was broken, it's plausible -that most applications that would have been rendered exploitable were -sufficiently broken not to be usable in the first place. however, it's -also plausible that common (especially ASCII-only) inputs succeeded in -the wcsrtombs loop, which mostly worked, while leaving the wildly -erroneous code in the second loop exposed to particular non-ASCII -inputs. - -CVE-2020-28928 has been assigned for this issue. ---- - src/multibyte/wcsnrtombs.c | 46 ++++++++++++++++---------------------- - 1 file changed, 19 insertions(+), 27 deletions(-) - -diff --git a/src/multibyte/wcsnrtombs.c b/src/multibyte/wcsnrtombs.c -index 676932b5..95e25e70 100644 ---- a/src/multibyte/wcsnrtombs.c -+++ b/src/multibyte/wcsnrtombs.c -@@ -1,41 +1,33 @@ - #include -+#include -+#include - - size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict st) - { -- size_t l, cnt=0, n2; -- char *s, buf[256]; - const wchar_t *ws = *wcs; -- const wchar_t *tmp_ws; -- -- if (!dst) s = buf, n = sizeof buf; -- else s = dst; -- -- while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) { -- if (n2>=n) n2=n; -- tmp_ws = ws; -- l = wcsrtombs(s, &ws, n2, 0); -- if (!(l+1)) { -- cnt = l; -- n = 0; -+ size_t cnt = 0; -+ if (!dst) n=0; -+ while (ws && wn) { -+ char tmp[MB_LEN_MAX]; -+ size_t l = wcrtomb(nn) break; -+ memcpy(dst, tmp, l); -+ } -+ dst += l; - n -= l; - } -- wn = ws ? wn - (ws - tmp_ws) : 0; -- cnt += l; -- } -- if (ws) while (n && wn) { -- l = wcrtomb(s, *ws, 0); -- if ((l+1)<=1) { -- if (!l) ws = 0; -- else cnt = l; -+ if (!*ws) { -+ ws = 0; - break; - } -- ws++; wn--; -- /* safe - this loop runs fewer than sizeof(buf) times */ -- s+=l; n-=l; -+ ws++; -+ wn--; - cnt += l; - } - if (dst) *wcs = ws; --- -2.25.4 - diff --git a/system/musl/amalgamation.patch b/system/musl/amalgamation.patch index 5918c3be6..5e273ce7f 100644 --- a/system/musl/amalgamation.patch +++ b/system/musl/amalgamation.patch @@ -8,14 +8,14 @@ index e9ca94cb..b39b12ee 100644 #include #include diff --git a/include/stdlib.h b/include/stdlib.h -index 194c2033..5734b1f0 100644 +index b507ca33..5e14b07c 100644 --- a/include/stdlib.h +++ b/include/stdlib.h -@@ -39,14 +39,18 @@ void *malloc (size_t); +@@ -41,14 +41,18 @@ void *malloc (size_t); void *calloc (size_t, size_t); void *realloc (void *, size_t); void free (void *); -+#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L ++#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) void *aligned_alloc(size_t, size_t); +#endif @@ -23,14 +23,14 @@ index 194c2033..5734b1f0 100644 int atexit (void (*) (void)); _Noreturn void exit (int); _Noreturn void _Exit (int); -+#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L ++#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || defined(_BSD_SOURCE) || defined(_GNU_SOURCE) int at_quick_exit (void (*) (void)); _Noreturn void quick_exit (int); +#endif char *getenv (const char *); -@@ -100,7 +104,6 @@ int posix_memalign (void **, size_t, size_t); +@@ -102,7 +106,6 @@ int posix_memalign (void **, size_t, size_t); int setenv (const char *, const char *, int); int unsetenv (const char *); int mkstemp (char *); @@ -38,7 +38,7 @@ index 194c2033..5734b1f0 100644 char *mkdtemp (char *); int getsubopt (char **, char *const *, char **); int rand_r (unsigned *); -@@ -138,6 +141,7 @@ void lcong48 (unsigned short [7]); +@@ -140,6 +143,7 @@ void lcong48 (unsigned short [7]); #include char *mktemp (char *); int mkstemps (char *, int); @@ -59,10 +59,10 @@ index cdc67ef6..fd773896 100644 struct itimerval { struct timeval it_interval; diff --git a/include/time.h b/include/time.h -index 5494df18..2412fe22 100644 +index 3d948372..deb4a450 100644 --- a/include/time.h +++ b/include/time.h -@@ -58,11 +58,14 @@ struct tm *gmtime (const time_t *); +@@ -60,11 +60,14 @@ struct tm *gmtime (const time_t *); struct tm *localtime (const time_t *); char *asctime (const struct tm *); char *ctime (const time_t *); @@ -79,7 +79,7 @@ index 5494df18..2412fe22 100644 #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ -@@ -137,7 +140,10 @@ __REDIR(mktime, __mktime64); +@@ -139,7 +142,10 @@ __REDIR(mktime, __mktime64); __REDIR(gmtime, __gmtime64); __REDIR(localtime, __localtime64); __REDIR(ctime, __ctime64); @@ -91,10 +91,10 @@ index 5494df18..2412fe22 100644 || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \ || defined(_BSD_SOURCE) diff --git a/include/unistd.h b/include/unistd.h -index 7bcbff94..6fd67160 100644 +index ee2dbe8a..ed75e578 100644 --- a/include/unistd.h +++ b/include/unistd.h -@@ -33,16 +33,23 @@ extern "C" { +@@ -35,16 +35,23 @@ extern "C" { #include int pipe(int [2]); @@ -121,7 +121,7 @@ index 7bcbff94..6fd67160 100644 ssize_t read(int, void *, size_t); ssize_t write(int, const void *, size_t); ssize_t pread(int, void *, size_t, off_t); -@@ -202,8 +209,6 @@ ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned); +@@ -206,8 +213,6 @@ pid_t gettid(void); #define off64_t off_t #endif @@ -130,7 +130,7 @@ index 7bcbff94..6fd67160 100644 #define _XOPEN_VERSION 700 #define _XOPEN_UNIX 1 #define _XOPEN_ENH_I18N 1 -@@ -276,6 +281,7 @@ ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned); +@@ -280,6 +285,7 @@ pid_t gettid(void); #define _PC_ALLOC_SIZE_MIN 18 #define _PC_SYMLINK_MAX 19 #define _PC_2_SYMLINKS 20 @@ -138,7 +138,7 @@ index 7bcbff94..6fd67160 100644 #define _SC_ARG_MAX 0 #define _SC_CHILD_MAX 1 -@@ -419,6 +425,7 @@ ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned); +@@ -423,6 +429,7 @@ pid_t gettid(void); #define _SC_XOPEN_STREAMS 246 #define _SC_THREAD_ROBUST_PRIO_INHERIT 247 #define _SC_THREAD_ROBUST_PRIO_PROTECT 248 @@ -146,7 +146,7 @@ index 7bcbff94..6fd67160 100644 #define _CS_PATH 0 #define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS 1 -@@ -461,6 +468,8 @@ ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned); +@@ -465,6 +472,8 @@ pid_t gettid(void); #define _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS 1147 #define _CS_V6_ENV 1148 #define _CS_V7_ENV 1149 @@ -208,18 +208,27 @@ index 3baaed32..04369596 100644 if (name >= sizeof(values)/sizeof(values[0]) || !values[name]) { diff --git a/src/locale/setlocale.c b/src/locale/setlocale.c -index 2bc7b500..4a601eaf 100644 +index 360c4437..76dbfc37 100644 --- a/src/locale/setlocale.c +++ b/src/locale/setlocale.c -@@ -14,6 +14,8 @@ char *setlocale(int cat, const char *name) +@@ -13,6 +13,8 @@ char *setlocale(int cat, const char *name) if ((unsigned)cat > LC_ALL) return 0; + if (name && (!strncmp(name, "VSX4L", 5))) return 0; + - LOCK(lock); + LOCK(__locale_lock); /* For LC_ALL, setlocale is required to return a string which +diff --git a/src/malloc/posix_memalign.c b/src/malloc/posix_memalign.c +index ad4d8f47..3318f86a 100644 +--- a/src/malloc/posix_memalign.c ++++ b/src/malloc/posix_memalign.c +@@ -1,3 +1,4 @@ ++#define _BSD_SOURCE + #include + #include + diff --git a/src/misc/forkpty.c b/src/misc/forkpty.c index caf13adb..43494b96 100644 --- a/src/misc/forkpty.c @@ -331,7 +340,7 @@ index 5af59b80..3f61d278 100644 sigaction(SIGINT, &sa, &oldint); sigaction(SIGQUIT, &sa, &oldquit); diff --git a/src/stdio/popen.c b/src/stdio/popen.c -index 92cb57ee..70c5d6ec 100644 +index 3ec83394..58883b11 100644 --- a/src/stdio/popen.c +++ b/src/stdio/popen.c @@ -1,3 +1,4 @@ @@ -387,7 +396,7 @@ index 40ea9c1c..e396da09 100644 /* There is no other implemented value than TIME_UTC; all other values diff --git a/src/unistd/faccessat.c b/src/unistd/faccessat.c -index 76bbd4c7..0b4564f9 100644 +index 557503eb..756a7bc4 100644 --- a/src/unistd/faccessat.c +++ b/src/unistd/faccessat.c @@ -1,3 +1,4 @@ diff --git a/system/musl/handle-aux-at_base.patch b/system/musl/handle-aux-at_base.patch index c16463824..697c82bbb 100644 --- a/system/musl/handle-aux-at_base.patch +++ b/system/musl/handle-aux-at_base.patch @@ -2,7 +2,7 @@ diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c index b125eb1..616c6a6 100644 --- a/src/env/__init_tls.c +++ b/src/env/__init_tls.c -@@ -66,8 +66,10 @@ void *__copy_tls(unsigned char *mem) +@@ -72,8 +72,10 @@ void *__copy_tls(unsigned char *mem) } #if ULONG_MAX == 0xffffffff @@ -13,7 +13,7 @@ index b125eb1..616c6a6 100644 typedef Elf64_Phdr Phdr; #endif -@@ -77,15 +79,23 @@ extern const size_t _DYNAMIC[]; +@@ -82,15 +84,23 @@ extern const size_t _DYNAMIC[]; static void static_init_tls(size_t *aux) { unsigned char *p; diff --git a/system/musl/threads_minus_1.patch b/system/musl/threads_minus_1.patch deleted file mode 100644 index 05307d97c..000000000 --- a/system/musl/threads_minus_1.patch +++ /dev/null @@ -1,267 +0,0 @@ -https://www.openwall.com/lists/musl/2020/05/22/10 - -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(-) - -diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c -index 5f491092..6a3b0c21 100644 ---- a/src/thread/pthread_create.c -+++ b/src/thread/pthread_create.c -@@ -90,14 +90,7 @@ _Noreturn void __pthread_exit(void *result) - 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 *result) - __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); --- -2.21.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(-) - -diff --git a/src/internal/libc.h b/src/internal/libc.h -index ac97dc7e..c0614852 100644 ---- 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; -diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c -index 96982596..2553a62e 100644 ---- 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); - } - -diff --git a/src/thread/__lock.c b/src/thread/__lock.c -index 45557c88..5b9b144e 100644 ---- 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; --- -2.21.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(-) - -diff --git a/src/internal/libc.h b/src/internal/libc.h -index c0614852..d47f58e0 100644 ---- 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; --- -2.21.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(-) - -diff --git a/src/internal/libc.h b/src/internal/libc.h -index d47f58e0..619bba86 100644 ---- 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; -diff --git a/src/malloc/malloc.c b/src/malloc/malloc.c -index 2553a62e..a803d4c9 100644 ---- 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) -diff --git a/src/thread/__lock.c b/src/thread/__lock.c -index 5b9b144e..60eece49 100644 ---- 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) { -diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c -index 6a3b0c21..6bdfb44f 100644 ---- a/src/thread/pthread_create.c -+++ b/src/thread/pthread_create.c -@@ -118,8 +118,8 @@ _Noreturn void __pthread_exit(void *result) - * 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 res, const pthread_attr_t *restrict att - ~(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 res, const pthread_attr_t *restrict att - 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); --- -2.21.0 - -- cgit v1.2.3-60-g2f50