git: 8271d9b99a3b - main - libsys: remove usage of pthread_once and _once_stub

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Wed, 21 Feb 2024 00:29:24 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=8271d9b99a3b98c662ee9a6257a144284b7e1728

commit 8271d9b99a3b98c662ee9a6257a144284b7e1728
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2024-02-20 14:45:29 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2024-02-21 00:26:11 +0000

    libsys: remove usage of pthread_once and _once_stub
    
    that existed in auxv.c, use simple bool gate instead. This leaves a
    small window if two threads try to call _elf_aux_info(3) simultaneously.
    The situation is safe because auxv parsing is really idempotent. The
    parsed data is the same, and we store atomic types (int/long/ptr) so
    double-init does not matter.
    
    Reviewed by:    brooks, imp
    Sponsored by:   The FreeBSD Foundation
    Differential revision:  https://reviews.freebsd.org/D43985
---
 lib/libc/gen/Makefile.inc             |  1 +
 lib/{libsys => libc/gen}/_once_stub.c |  0
 lib/libsys/Makefile.sys               |  1 -
 lib/libsys/auxv.c                     | 20 ++++++++++++++++++--
 4 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index 8d30e06cfed9..ce7a34d0e58e 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -9,6 +9,7 @@ CONFSPACKAGE=   runtime
 SRCS+= \
 	__pthread_mutex_init_calloc_cb_stub.c \
 	__xuname.c \
+	_once_stub.c \
 	_pthread_stubs.c \
 	_rand48.c \
 	_spinlock_stub.c \
diff --git a/lib/libsys/_once_stub.c b/lib/libc/gen/_once_stub.c
similarity index 100%
rename from lib/libsys/_once_stub.c
rename to lib/libc/gen/_once_stub.c
diff --git a/lib/libsys/Makefile.sys b/lib/libsys/Makefile.sys
index cb9ca1749ba8..e33a11bacb57 100644
--- a/lib/libsys/Makefile.sys
+++ b/lib/libsys/Makefile.sys
@@ -33,7 +33,6 @@ PSEUDO+= _clock_gettime.o _gettimeofday.o
 SRCS+=	\
 	__error.c \
 	__getosreldate.c \
-	_once_stub.c \
 	getpagesize.c \
 	getpagesizes.c \
 	interposing_table.c
diff --git a/lib/libsys/auxv.c b/lib/libsys/auxv.c
index b0b3a8ed708b..88f49ef53be1 100644
--- a/lib/libsys/auxv.c
+++ b/lib/libsys/auxv.c
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <link.h>
 #include <pthread.h>
+#include <stdbool.h>
 #include <string.h>
 #include <sys/auxv.h>
 #include "un-namespace.h"
@@ -40,6 +41,8 @@ extern int _DYNAMIC;
 #pragma weak _DYNAMIC
 
 void *__elf_aux_vector;
+
+#ifndef PIC
 static pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT;
 
 static void
@@ -61,8 +64,9 @@ __init_elf_aux_vector(void)
 		return;
 	_once(&aux_vector_once, init_aux_vector_once);
 }
+#endif
 
-static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
+static bool aux_once = false;
 static int pagesize, osreldate, canary_len, ncpus, pagesizes_len, bsdflags;
 static int hwcap_present, hwcap2_present;
 static char *canary, *pagesizes, *execpath;
@@ -77,11 +81,19 @@ static void _init_aux_powerpc_fixup(void);
 int _powerpc_elf_aux_info(int, void *, int);
 #endif
 
+/*
+ * This function might be called and actual body executed more than
+ * once in multithreading environment.  Due to this, it is and must
+ * continue to be idempotent.  All stores are atomic (no store
+ * tearing), because we only assign to int/long/ptr.
+ */
 static void
 init_aux(void)
 {
 	Elf_Auxinfo *aux;
 
+	if (aux_once)
+		return;
 	for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
 		switch (aux->a_type) {
 		case AT_BSDFLAGS:
@@ -166,6 +178,8 @@ init_aux(void)
 	if (!powerpc_new_auxv_format)
 		_init_aux_powerpc_fixup();
 #endif
+
+	aux_once = true;
 }
 
 #ifdef __powerpc__
@@ -256,10 +270,12 @@ _elf_aux_info(int aux, void *buf, int buflen)
 {
 	int res;
 
+#ifndef PIC
 	__init_elf_aux_vector();
+#endif
 	if (__elf_aux_vector == NULL)
 		return (ENOSYS);
-	_once(&aux_once, init_aux);
+	init_aux();	/* idempotent */
 
 	if (buflen < 0)
 		return (EINVAL);