libatomic: Provide gthr.h default implementation

Message ID 20221219160245.55745-1-sebastian.huber@embedded-brains.de
State New
Headers
Series libatomic: Provide gthr.h default implementation |

Commit Message

Sebastian Huber Dec. 19, 2022, 4:02 p.m. UTC
  Build libatomic for all targets.  Use gthr.h to provide a default
implementation.  If the thread model is "single", then this implementation will
not work if for example atomic operations are used for thread/interrupt
synchronization.

libatomic/ChangeLog:

	* Makefile.am (BUILT_SOURCES): New.
	(gthr.h): Link from libgcc source file if USE_CONFIG_GTHR is enabled.
	(gthr-default.h): Likewise.
	* Makefile.in: Regenerate.
	* configure: Likewise.
	* configure.ac: Map thread model to thread header.
	(thread_header): New substitution.
	(USE_CONFIG_GTHR): New automake conditional.
	* configure.tgt (*-*-elf*): Delete.
	(UNSUPPORTED): Likewise.
	(USE_CONFIG_GTHR): Define as default.
	* testsuite/Makefile.in: Regenerate.
	* config/gthr/host-config.h: New file.
	* config/gthr/lock.c: Likewise.
---
 libatomic/Makefile.am               |  12 +++
 libatomic/Makefile.in               |  40 +++++---
 libatomic/config/gthr/host-config.h |  55 +++++++++++
 libatomic/config/gthr/lock.c        | 136 ++++++++++++++++++++++++++++
 libatomic/configure                 |  40 +++++++-
 libatomic/configure.ac              |  10 +-
 libatomic/configure.tgt             |  16 +---
 libatomic/testsuite/Makefile.in     |   4 +-
 8 files changed, 281 insertions(+), 32 deletions(-)
 create mode 100644 libatomic/config/gthr/host-config.h
 create mode 100644 libatomic/config/gthr/lock.c
  

Comments

Sebastian Huber Jan. 10, 2023, 3:38 p.m. UTC | #1
On 19/12/2022 17:02, Sebastian Huber wrote:
> Build libatomic for all targets.  Use gthr.h to provide a default
> implementation.  If the thread model is "single", then this implementation will
> not work if for example atomic operations are used for thread/interrupt
> synchronization.

Is this and the related -fprofile-update=atomic patch something for GCC 14?
  
Sebastian Huber May 23, 2023, 9:27 a.m. UTC | #2
On 10.01.23 16:38, Sebastian Huber wrote:
> On 19/12/2022 17:02, Sebastian Huber wrote:
>> Build libatomic for all targets.  Use gthr.h to provide a default
>> implementation.  If the thread model is "single", then this 
>> implementation will
>> not work if for example atomic operations are used for thread/interrupt
>> synchronization.
> 
> Is this and the related -fprofile-update=atomic patch something for GCC 14?

Now that the GCC 14 development is in progress, what about this patch?
  
Richard Biener May 30, 2023, 9:53 a.m. UTC | #3
On Tue, May 23, 2023 at 11:28 AM Sebastian Huber
<sebastian.huber@embedded-brains.de> wrote:
>
> On 10.01.23 16:38, Sebastian Huber wrote:
> > On 19/12/2022 17:02, Sebastian Huber wrote:
> >> Build libatomic for all targets.  Use gthr.h to provide a default
> >> implementation.  If the thread model is "single", then this
> >> implementation will
> >> not work if for example atomic operations are used for thread/interrupt
> >> synchronization.
> >
> > Is this and the related -fprofile-update=atomic patch something for GCC 14?
>
> Now that the GCC 14 development is in progress, what about this patch?

Sorry, there doesn't seem to be a main maintainer for libatomic and your patch
touches targets which didn't have it before.

Can you explain how this affects the ABI of targets not having (needing?!)
libatomic?  It might help if you can say this is still opt-in and targets not
building libatomic right now would not with your patch and targets already
building libatomic have no changes with your patch.

That said - what kind of ABI implications has providing libatomic support
for a target that didn't do so before?

Richard.

> --
> embedded brains GmbH
> Herr Sebastian HUBER
> Dornierstr. 4
> 82178 Puchheim
> Germany
> email: sebastian.huber@embedded-brains.de
> phone: +49-89-18 94 741 - 16
> fax:   +49-89-18 94 741 - 08
>
> Registergericht: Amtsgericht München
> Registernummer: HRB 157899
> Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
> Unsere Datenschutzerklärung finden Sie hier:
> https://embedded-brains.de/datenschutzerklaerung/
  
Sebastian Huber May 30, 2023, 10:17 a.m. UTC | #4
On 30.05.23 11:53, Richard Biener wrote:
> On Tue, May 23, 2023 at 11:28 AM Sebastian Huber
> <sebastian.huber@embedded-brains.de>  wrote:
>> On 10.01.23 16:38, Sebastian Huber wrote:
>>> On 19/12/2022 17:02, Sebastian Huber wrote:
>>>> Build libatomic for all targets.  Use gthr.h to provide a default
>>>> implementation.  If the thread model is "single", then this
>>>> implementation will
>>>> not work if for example atomic operations are used for thread/interrupt
>>>> synchronization.
>>> Is this and the related -fprofile-update=atomic patch something for GCC 14?
>> Now that the GCC 14 development is in progress, what about this patch?
> Sorry, there doesn't seem to be a main maintainer for libatomic and your patch
> touches targets which didn't have it before.
> 
> Can you explain how this affects the ABI of targets not having (needing?!)
> libatomic?  It might help if you can say this is still opt-in and targets not
> building libatomic right now would not with your patch and targets already
> building libatomic have no changes with your patch.
> 
> That said - what kind of ABI implications has providing libatomic support
> for a target that didn't do so before?

Sorry for the missing context. The root problem I want to solve is 
getting gcov support for multi-threaded applications. For this we need 
atomic 64-bit operations, see also:

https://gcc.gnu.org/pipermail/gcc-patches/2022-December/608620.html

The libatomic patch lets it build for every target. Targets with no 
explicit support will use the gthr.h API to provide a default 
implementation.

An alternative would be to use the RTEMS approach which uses the 
following API (provided by Newlib <machine/_libatomic.h> for RTEMS):

#include <sys/cdefs.h>
#include <sys/_types.h>

__BEGIN_DECLS

__uint32_t _Libatomic_Protect_start(void *);

void _Libatomic_Protect_end(void *, __uint32_t);

void _Libatomic_Lock_n(void *, __size_t);

void _Libatomic_Unlock_n(void *, __size_t);

__END_DECLS

We could also leave libatomic as is, but then you may get unresolved 
references if you use -fprofile-update=atomic with the patch mentioned 
above.
  
Richard Biener May 30, 2023, 11:17 a.m. UTC | #5
On Tue, May 30, 2023 at 12:17 PM Sebastian Huber
<sebastian.huber@embedded-brains.de> wrote:
>
> On 30.05.23 11:53, Richard Biener wrote:
> > On Tue, May 23, 2023 at 11:28 AM Sebastian Huber
> > <sebastian.huber@embedded-brains.de>  wrote:
> >> On 10.01.23 16:38, Sebastian Huber wrote:
> >>> On 19/12/2022 17:02, Sebastian Huber wrote:
> >>>> Build libatomic for all targets.  Use gthr.h to provide a default
> >>>> implementation.  If the thread model is "single", then this
> >>>> implementation will
> >>>> not work if for example atomic operations are used for thread/interrupt
> >>>> synchronization.
> >>> Is this and the related -fprofile-update=atomic patch something for GCC 14?
> >> Now that the GCC 14 development is in progress, what about this patch?
> > Sorry, there doesn't seem to be a main maintainer for libatomic and your patch
> > touches targets which didn't have it before.
> >
> > Can you explain how this affects the ABI of targets not having (needing?!)
> > libatomic?  It might help if you can say this is still opt-in and targets not
> > building libatomic right now would not with your patch and targets already
> > building libatomic have no changes with your patch.
> >
> > That said - what kind of ABI implications has providing libatomic support
> > for a target that didn't do so before?
>
> Sorry for the missing context. The root problem I want to solve is
> getting gcov support for multi-threaded applications. For this we need
> atomic 64-bit operations, see also:

I was aware of the context but still worry about the ABI implications.
A target that doesn't build libatomic but would need one currently
has "unsupported" (aka fail to link) atomic operations that require
libatomic support.  After your patch such targets suddenly have
a new ABI (and supported atomic ops) - this ABI they need to
maintain for compatibility reasons I think but it would be (likely)
not documented anywhere.

I think that's undesirable, esp. without buy-in from the affected
target maintainers.

> https://gcc.gnu.org/pipermail/gcc-patches/2022-December/608620.html
>
> The libatomic patch lets it build for every target. Targets with no
> explicit support will use the gthr.h API to provide a default
> implementation.
>
> An alternative would be to use the RTEMS approach which uses the
> following API (provided by Newlib <machine/_libatomic.h> for RTEMS):
>
> #include <sys/cdefs.h>
> #include <sys/_types.h>
>
> __BEGIN_DECLS
>
> __uint32_t _Libatomic_Protect_start(void *);
>
> void _Libatomic_Protect_end(void *, __uint32_t);
>
> void _Libatomic_Lock_n(void *, __size_t);
>
> void _Libatomic_Unlock_n(void *, __size_t);
>
> __END_DECLS
>
> We could also leave libatomic as is, but then you may get unresolved
> references if you use -fprofile-update=atomic with the patch mentioned
> above.

The alternative would be to provide the required subset of atomic
library functions from libgcov.a and emit calls to that directly?
The locked data isn't part of any ABI so no compatibility guarantee
needs to be maintained?

Richard.

>
> --
> embedded brains GmbH
> Herr Sebastian HUBER
> Dornierstr. 4
> 82178 Puchheim
> Germany
> email: sebastian.huber@embedded-brains.de
> phone: +49-89-18 94 741 - 16
> fax:   +49-89-18 94 741 - 08
>
> Registergericht: Amtsgericht München
> Registernummer: HRB 157899
> Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
> Unsere Datenschutzerklärung finden Sie hier:
> https://embedded-brains.de/datenschutzerklaerung/
  
Sebastian Huber May 31, 2023, 5:31 a.m. UTC | #6
On 30.05.23 13:17, Richard Biener wrote:
> The alternative would be to provide the required subset of atomic
> library functions from libgcov.a and emit calls to that directly?
> The locked data isn't part of any ABI so no compatibility guarantee
> needs to be maintained?

So, if atomic operations are not available in hardware, then I should 
emit calls to libgcov.a which would use gthr.h to implement them? I 
guess that I can to this, but it needs a bit of time.

Should I add the libgcov functions to builtin_decl_explicit()?
  
Richard Biener May 31, 2023, 7:27 a.m. UTC | #7
On Wed, May 31, 2023 at 7:31 AM Sebastian Huber
<sebastian.huber@embedded-brains.de> wrote:
>
> On 30.05.23 13:17, Richard Biener wrote:
> > The alternative would be to provide the required subset of atomic
> > library functions from libgcov.a and emit calls to that directly?
> > The locked data isn't part of any ABI so no compatibility guarantee
> > needs to be maintained?
>
> So, if atomic operations are not available in hardware, then I should
> emit calls to libgcov.a which would use gthr.h to implement them? I
> guess that I can to this, but it needs a bit of time.

Before doing that it would be nice to get buy-in from others - maybe
my ABI concern for libatomic isn't shared by others.

> Should I add the libgcov functions to builtin_decl_explicit()?

No, they shouldn't be any different from other libgcov functions.

Richard.

>
> --
> embedded brains GmbH
> Herr Sebastian HUBER
> Dornierstr. 4
> 82178 Puchheim
> Germany
> email: sebastian.huber@embedded-brains.de
> phone: +49-89-18 94 741 - 16
> fax:   +49-89-18 94 741 - 08
>
> Registergericht: Amtsgericht München
> Registernummer: HRB 157899
> Vertretungsberechtigte Geschäftsführer: Peter Rasmussen, Thomas Dörfler
> Unsere Datenschutzerklärung finden Sie hier:
> https://embedded-brains.de/datenschutzerklaerung/
  
Sebastian Huber Sept. 11, 2023, 1:02 p.m. UTC | #8
On 31.05.23 09:27, Richard Biener wrote:
> On Wed, May 31, 2023 at 7:31 AM Sebastian Huber
> <sebastian.huber@embedded-brains.de> wrote:
>>
>> On 30.05.23 13:17, Richard Biener wrote:
>>> The alternative would be to provide the required subset of atomic
>>> library functions from libgcov.a and emit calls to that directly?
>>> The locked data isn't part of any ABI so no compatibility guarantee
>>> needs to be maintained?
>>
>> So, if atomic operations are not available in hardware, then I should
>> emit calls to libgcov.a which would use gthr.h to implement them? I
>> guess that I can to this, but it needs a bit of time.
> 
> Before doing that it would be nice to get buy-in from others - maybe
> my ABI concern for libatomic isn't shared by others.

I would be nice if I could add the multi-threaded gcov support for 
targets lacking atomic operations in GCC 14 (for example 32-bit RISC-V). 
I need a direction how to implement this. Should it be done through a 
generic libatomic implementation based on gthr.h or through a special 
function provided by libgcov?

> 
>> Should I add the libgcov functions to builtin_decl_explicit()?
> 
> No, they shouldn't be any different from other libgcov functions.

Ok.
  

Patch

diff --git a/libatomic/Makefile.am b/libatomic/Makefile.am
index 41e5da28512..d56d553c9d5 100644
--- a/libatomic/Makefile.am
+++ b/libatomic/Makefile.am
@@ -34,6 +34,18 @@  search_path = $(addprefix $(top_srcdir)/config/, $(config_path)) \
 
 vpath % $(strip $(search_path))
 
+BUILT_SOURCES =
+
+if USE_CONFIG_GTHR
+gthr.h: $(top_srcdir)/../libgcc/gthr.h
+	-$(LN_S) $< $@
+
+gthr-default.h: $(top_srcdir)/../libgcc/$(thread_header)
+	-$(LN_S) $< $@
+
+BUILT_SOURCES += gthr.h gthr-default.h
+endif
+
 DEFAULT_INCLUDES = $(addprefix -I, $(search_path))
 AM_CFLAGS = $(XCFLAGS)
 AM_CCASFLAGS = $(XCFLAGS)
diff --git a/libatomic/Makefile.in b/libatomic/Makefile.in
index a0fa3dfc8cc..2e3ddd014f8 100644
--- a/libatomic/Makefile.in
+++ b/libatomic/Makefile.in
@@ -89,15 +89,16 @@  POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 target_triplet = @target@
-@ARCH_AARCH64_LINUX_TRUE@@HAVE_IFUNC_TRUE@am__append_1 = $(foreach s,$(SIZES),$(addsuffix _$(s)_1_.lo,$(SIZEOBJS)))
-@ARCH_AARCH64_LINUX_TRUE@@HAVE_IFUNC_TRUE@am__append_2 = atomic_16.S
-@ARCH_ARM_LINUX_TRUE@@HAVE_IFUNC_TRUE@am__append_3 = $(foreach \
+@USE_CONFIG_GTHR_TRUE@am__append_1 = gthr.h gthr-default.h
+@ARCH_AARCH64_LINUX_TRUE@@HAVE_IFUNC_TRUE@am__append_2 = $(foreach s,$(SIZES),$(addsuffix _$(s)_1_.lo,$(SIZEOBJS)))
+@ARCH_AARCH64_LINUX_TRUE@@HAVE_IFUNC_TRUE@am__append_3 = atomic_16.S
+@ARCH_ARM_LINUX_TRUE@@HAVE_IFUNC_TRUE@am__append_4 = $(foreach \
 @ARCH_ARM_LINUX_TRUE@@HAVE_IFUNC_TRUE@	s,$(SIZES),$(addsuffix \
 @ARCH_ARM_LINUX_TRUE@@HAVE_IFUNC_TRUE@	_$(s)_1_.lo,$(SIZEOBJS))) \
 @ARCH_ARM_LINUX_TRUE@@HAVE_IFUNC_TRUE@	$(addsuffix \
 @ARCH_ARM_LINUX_TRUE@@HAVE_IFUNC_TRUE@	_8_2_.lo,$(SIZEOBJS))
-@ARCH_I386_TRUE@@HAVE_IFUNC_TRUE@am__append_4 = $(addsuffix _8_1_.lo,$(SIZEOBJS))
-@ARCH_X86_64_TRUE@@HAVE_IFUNC_TRUE@am__append_5 = $(addsuffix _16_1_.lo,$(SIZEOBJS)) \
+@ARCH_I386_TRUE@@HAVE_IFUNC_TRUE@am__append_5 = $(addsuffix _8_1_.lo,$(SIZEOBJS))
+@ARCH_X86_64_TRUE@@HAVE_IFUNC_TRUE@am__append_6 = $(addsuffix _16_1_.lo,$(SIZEOBJS)) \
 @ARCH_X86_64_TRUE@@HAVE_IFUNC_TRUE@		       $(addsuffix _16_2_.lo,$(SIZEOBJS))
 
 subdir = .
@@ -115,7 +116,8 @@  am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
 	$(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
 	$(top_srcdir)/acinclude.m4 $(top_srcdir)/../libtool.m4 \
 	$(top_srcdir)/../config/enable.m4 \
-	$(top_srcdir)/../config/cet.m4 $(top_srcdir)/configure.ac
+	$(top_srcdir)/../config/cet.m4 $(top_srcdir)/../config/gthr.m4 \
+	$(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
@@ -392,6 +394,7 @@  target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
+thread_header = @thread_header@
 tmake_file = @tmake_file@
 toolexecdir = @toolexecdir@
 toolexeclibdir = @toolexeclibdir@
@@ -404,6 +407,7 @@  gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER)
 search_path = $(addprefix $(top_srcdir)/config/, $(config_path)) \
 	$(top_srcdir) $(top_builddir)
 
+BUILT_SOURCES = $(am__append_1)
 DEFAULT_INCLUDES = $(addprefix -I, $(search_path))
 AM_CFLAGS = $(XCFLAGS)
 AM_CCASFLAGS = $(XCFLAGS)
@@ -419,7 +423,7 @@  noinst_LTLIBRARIES = libatomic_convenience.la
 libatomic_version_info = -version-info $(libtool_VERSION)
 libatomic_la_LDFLAGS = $(libatomic_version_info) $(libatomic_version_script) $(lt_host_flags)
 libatomic_la_SOURCES = gload.c gstore.c gcas.c gexch.c glfree.c lock.c \
-	init.c fenv.c fence.c flag.c $(am__append_2)
+	init.c fenv.c fence.c flag.c $(am__append_3)
 SIZEOBJS = load store cas exch fadd fsub fand fior fxor fnand tas
 EXTRA_libatomic_la_SOURCES = $(addsuffix _n.c,$(SIZEOBJS))
 libatomic_la_DEPENDENCIES = $(libatomic_la_LIBADD) $(libatomic_version_dep)
@@ -445,8 +449,8 @@  all_c_files := $(foreach dir,$(search_path),$(wildcard $(dir)/*.c))
 # Then sort through them to find the one we want, and select the first.
 M_SRC = $(firstword $(filter %/$(M_FILE), $(all_c_files)))
 libatomic_la_LIBADD = $(foreach s,$(SIZES),$(addsuffix \
-	_$(s)_.lo,$(SIZEOBJS))) $(am__append_1) $(am__append_3) \
-	$(am__append_4) $(am__append_5)
+	_$(s)_.lo,$(SIZEOBJS))) $(am__append_2) $(am__append_4) \
+	$(am__append_5) $(am__append_6)
 @ARCH_AARCH64_LINUX_TRUE@@HAVE_IFUNC_TRUE@IFUNC_OPTIONS = -march=armv8-a+lse
 @ARCH_ARM_LINUX_TRUE@@HAVE_IFUNC_TRUE@IFUNC_OPTIONS = -march=armv7-a+fp -DHAVE_KERNEL64
 @ARCH_I386_TRUE@@HAVE_IFUNC_TRUE@IFUNC_OPTIONS = -march=i586
@@ -459,7 +463,7 @@  MULTIDIRS =
 MULTISUBDIR = 
 MULTIDO = true
 MULTICLEAN = true
-all: auto-config.h
+all: $(BUILT_SOURCES) auto-config.h
 	$(MAKE) $(AM_MAKEFLAGS) all-recursive
 
 .SUFFIXES:
@@ -741,14 +745,16 @@  distclean-tags:
 	-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 	-rm -f cscope.out cscope.in.out cscope.po.out cscope.files
 check-am: all-am
-check: check-recursive
+check: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) check-recursive
 all-am: Makefile $(LTLIBRARIES) auto-config.h all-local
 installdirs: installdirs-recursive
 installdirs-am:
 	for dir in "$(DESTDIR)$(toolexeclibdir)"; do \
 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
 	done
-install: install-recursive
+install: $(BUILT_SOURCES)
+	$(MAKE) $(AM_MAKEFLAGS) install-recursive
 install-exec: install-exec-recursive
 install-data: install-data-recursive
 uninstall: uninstall-recursive
@@ -778,6 +784,7 @@  distclean-generic:
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
+	-test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
 clean: clean-recursive
 
 clean-am: clean-generic clean-libtool clean-local \
@@ -854,7 +861,8 @@  ps-am:
 
 uninstall-am: uninstall-toolexeclibLTLIBRARIES
 
-.MAKE: $(am__recursive_targets) all install-am install-strip
+.MAKE: $(am__recursive_targets) all check install install-am \
+	install-strip
 
 .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \
 	am--refresh check check-am clean clean-cscope clean-generic \
@@ -878,6 +886,12 @@  uninstall-am: uninstall-toolexeclibLTLIBRARIES
 
 
 vpath % $(strip $(search_path))
+
+@USE_CONFIG_GTHR_TRUE@gthr.h: $(top_srcdir)/../libgcc/gthr.h
+@USE_CONFIG_GTHR_TRUE@	-$(LN_S) $< $@
+
+@USE_CONFIG_GTHR_TRUE@gthr-default.h: $(top_srcdir)/../libgcc/$(thread_header)
+@USE_CONFIG_GTHR_TRUE@	-$(LN_S) $< $@
 @LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@libatomic.map-sun : $(top_srcdir)/libatomic.map \
 @LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@		$(top_srcdir)/../contrib/make_sunver.pl \
 @LIBAT_BUILD_VERSIONED_SHLIB_SUN_TRUE@@LIBAT_BUILD_VERSIONED_SHLIB_TRUE@		$(libatomic_la_OBJECTS) $(libatomic_la_LIBADD)
diff --git a/libatomic/config/gthr/host-config.h b/libatomic/config/gthr/host-config.h
new file mode 100644
index 00000000000..5e529945eee
--- /dev/null
+++ b/libatomic/config/gthr/host-config.h
@@ -0,0 +1,55 @@ 
+/* Copyright (C) 2012-2022 Free Software Foundation, Inc.
+   Contributed by Richard Henderson <rth@redhat.com>.
+
+   This file is part of the GNU Atomic Library (libatomic).
+
+   Libatomic is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   Libatomic is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+   more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+/* Included after all more target-specific host-config.h.  */
+
+
+#ifndef protect_start_end
+# ifdef HAVE_ATTRIBUTE_VISIBILITY
+#  pragma GCC visibility push(hidden)
+# endif
+
+void libat_lock_1 (void *ptr);
+void libat_unlock_1 (void *ptr);
+
+static inline UWORD
+protect_start (void *ptr)
+{
+  libat_lock_1 (ptr);
+  return 0;
+}
+
+static inline void
+protect_end (void *ptr, UWORD dummy UNUSED)
+{
+  libat_unlock_1 (ptr);
+}
+
+# define protect_start_end 1
+# ifdef HAVE_ATTRIBUTE_VISIBILITY
+#  pragma GCC visibility pop
+# endif
+#endif /* protect_start_end */
+
+#include_next <host-config.h>
diff --git a/libatomic/config/gthr/lock.c b/libatomic/config/gthr/lock.c
new file mode 100644
index 00000000000..2d495ed3b56
--- /dev/null
+++ b/libatomic/config/gthr/lock.c
@@ -0,0 +1,136 @@ 
+/* Copyright (C) 2012-2022 Free Software Foundation, Inc.
+   Contributed by Richard Henderson <rth@redhat.com>.
+
+   This file is part of the GNU Atomic Library (libatomic).
+
+   Libatomic is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   Libatomic is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+   more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "libatomic_i.h"
+#include "gthr.h"
+
+
+/* The target page size.  Must be no larger than the runtime page size,
+   lest locking fail with virtual address aliasing (i.e. a page mmaped
+   at two locations).  */
+#ifndef PAGE_SIZE
+#define PAGE_SIZE	4096
+#endif
+
+/* The target cacheline size.  This is an optimization; the padding that
+   should be applied to the locks to keep them from interfering.  */
+#ifndef CACHLINE_SIZE
+#define CACHLINE_SIZE	64
+#endif
+
+/* The granularity at which locks are applied.  Almost certainly the
+   cachline size is the right thing to use here.  */
+#ifndef WATCH_SIZE
+#define WATCH_SIZE	CACHLINE_SIZE
+#endif
+
+struct lock
+{
+  __gthread_mutex_t mutex;
+  char pad[sizeof(__gthread_mutex_t) < CACHLINE_SIZE
+	   ? CACHLINE_SIZE - sizeof(__gthread_mutex_t)
+	   : 0];
+};
+
+#define NLOCKS		(PAGE_SIZE / WATCH_SIZE)
+#ifdef __GTHREAD_MUTEX_INIT
+static struct lock locks[NLOCKS] = {
+  [0 ... NLOCKS-1].mutex = __GTHREAD_MUTEX_INIT
+};
+#else
+static __gthread_once_t locks_once = __GTHREAD_ONCE_INIT;
+
+static struct lock locks[NLOCKS];
+
+static void
+locks_init (void)
+{
+  size_t i;
+  for (i = 0; i < NLOCKS; ++i)
+    __GTHREAD_MUTEX_INIT_FUNCTION (&locks[i].mutex);
+}
+#endif
+
+static inline uintptr_t
+addr_hash (void *ptr)
+{
+  return ((uintptr_t)ptr / WATCH_SIZE) % NLOCKS;
+}
+
+void
+libat_lock_1 (void *ptr)
+{
+#ifndef __GTHREAD_MUTEX_INIT
+  __gthread_once (&locks_once, locks_init);
+#endif
+  __gthread_mutex_lock (&locks[addr_hash (ptr)].mutex);
+}
+
+void
+libat_unlock_1 (void *ptr)
+{
+  __gthread_mutex_unlock (&locks[addr_hash (ptr)].mutex);
+}
+
+void
+libat_lock_n (void *ptr, size_t n)
+{
+  uintptr_t h = addr_hash (ptr);
+  size_t i = 0;
+
+  /* Don't lock more than all the locks we have.  */
+  if (n > PAGE_SIZE)
+    n = PAGE_SIZE;
+
+  do
+    {
+#ifndef __GTHREAD_MUTEX_INIT
+      __gthread_once (&locks_once, locks_init);
+#endif
+      __gthread_mutex_lock (&locks[h].mutex);
+      if (++h == NLOCKS)
+	h = 0;
+      i += WATCH_SIZE;
+    }
+  while (i < n);
+}
+
+void
+libat_unlock_n (void *ptr, size_t n)
+{
+  uintptr_t h = addr_hash (ptr);
+  size_t i = 0;
+
+  if (n > PAGE_SIZE)
+    n = PAGE_SIZE;
+
+  do
+    {
+      __gthread_mutex_unlock (&locks[h].mutex);
+      if (++h == NLOCKS)
+	h = 0;
+      i += WATCH_SIZE;
+    }
+  while (i < n);
+}
diff --git a/libatomic/configure b/libatomic/configure
index e47d2d7fb35..cec874ebabe 100755
--- a/libatomic/configure
+++ b/libatomic/configure
@@ -656,7 +656,10 @@  LIBAT_BUILD_VERSIONED_SHLIB_FALSE
 LIBAT_BUILD_VERSIONED_SHLIB_TRUE
 OPT_LDFLAGS
 SECTION_LDFLAGS
+USE_CONFIG_GTHR_FALSE
+USE_CONFIG_GTHR_TRUE
 enable_aarch64_lse
+thread_header
 libtool_VERSION
 MAINT
 MAINTAINER_MODE_FALSE
@@ -11406,7 +11409,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11409 "configure"
+#line 11412 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11512,7 +11515,7 @@  else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11515 "configure"
+#line 11518 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11808,6 +11811,26 @@  target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $target_thread_file" >&5
 $as_echo "$target_thread_file" >&6; }
 
+# Map from thread model to thread header.
+
+case $target_thread_file in
+    aix)	thread_header=config/rs6000/gthr-aix.h ;;
+    dce)	thread_header=config/pa/gthr-dce.h ;;
+    gcn)	thread_header=config/gcn/gthr-gcn.h ;;
+    lynx)	thread_header=config/gthr-lynx.h ;;
+    mipssde)	thread_header=config/mips/gthr-mipssde.h ;;
+    posix)	thread_header=gthr-posix.h ;;
+    rtems)	thread_header=config/gthr-rtems.h ;;
+    single)	thread_header=gthr-single.h ;;
+    tpf)	thread_header=config/s390/gthr-tpf.h ;;
+    vxworks)	thread_header=config/gthr-vxworks.h ;;
+    win32)	thread_header=config/i386/gthr-win32.h ;;
+    mcf)	thread_header=config/i386/gthr-mcf.h ;;
+esac
+
+
+
+
 case "$target" in
  *aarch64*)
     ac_ext=c
@@ -11872,10 +11895,15 @@  esac
 
 # Get target configury.
 . ${srcdir}/configure.tgt
-if test -n "$UNSUPPORTED"; then
-  as_fn_error $? "Configuration ${target} is unsupported." "$LINENO" 5
+ if test -n "$USE_CONFIG_GTHR"; then
+  USE_CONFIG_GTHR_TRUE=
+  USE_CONFIG_GTHR_FALSE='#'
+else
+  USE_CONFIG_GTHR_TRUE='#'
+  USE_CONFIG_GTHR_FALSE=
 fi
 
+
 # Write out the ifunc resolver arg type.
 
 cat >>confdefs.h <<_ACEOF
@@ -15924,6 +15952,10 @@  if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
   as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_CONFIG_GTHR_TRUE}" && test -z "${USE_CONFIG_GTHR_FALSE}"; then
+  as_fn_error $? "conditional \"USE_CONFIG_GTHR\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 
 if test -z "${LIBAT_BUILD_VERSIONED_SHLIB_TRUE}" && test -z "${LIBAT_BUILD_VERSIONED_SHLIB_FALSE}"; then
   as_fn_error $? "conditional \"LIBAT_BUILD_VERSIONED_SHLIB\" was never defined.
diff --git a/libatomic/configure.ac b/libatomic/configure.ac
index 5563551aaae..78a0b533c79 100644
--- a/libatomic/configure.ac
+++ b/libatomic/configure.ac
@@ -22,6 +22,8 @@ 
 #  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #  <http://www.gnu.org/licenses/>.
 
+sinclude(../config/gthr.m4)
+
 AC_INIT([GNU Atomic Library], 1.0,,[libatomic])
 AC_CONFIG_HEADER(auto-config.h)
 
@@ -165,6 +167,10 @@  AC_MSG_CHECKING([for thread model used by GCC])
 target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
 AC_MSG_RESULT([$target_thread_file])
 
+# Map from thread model to thread header.
+GCC_AC_THREAD_HEADER([$target_thread_file])
+AC_SUBST(thread_header)
+
 case "$target" in
  *aarch64*)
     ACX_PROG_CC_WARNING_OPTS([-march=armv8-a+lse],[enable_aarch64_lse])
@@ -173,9 +179,7 @@  esac
 
 # Get target configury.
 . ${srcdir}/configure.tgt
-if test -n "$UNSUPPORTED"; then
-  AC_MSG_ERROR([Configuration ${target} is unsupported.])
-fi
+AM_CONDITIONAL(USE_CONFIG_GTHR, test -n "$USE_CONFIG_GTHR")
 
 # Write out the ifunc resolver arg type.
 AC_DEFINE_UNQUOTED(IFUNC_RESOLVER_ARGS, $IFUNC_RESOLVER_ARGS,
diff --git a/libatomic/configure.tgt b/libatomic/configure.tgt
index 57f093603bb..a4463c5a7cb 100644
--- a/libatomic/configure.tgt
+++ b/libatomic/configure.tgt
@@ -174,21 +174,15 @@  case "${target}" in
 	config_path="rtems"
 	;;
 
-  *-*-elf*)
-	# ??? No target OS.  We could be targeting bare-metal kernel-mode,
-	# or user-mode for some custom OS.  If the target supports TAS,
-	# we can build our own spinlocks, given there are no signals.
-	# If the target supports disabling interrupts, we can work in
-	# kernel-mode, given the system is not multi-processor.
-	UNSUPPORTED=1
-	;;
-
   nvptx*-*-*)
 	;;
 
   *)
-	# Who are you?
-	UNSUPPORTED=1
+	# Use gthr.h by default.  If the thread model is "single", then this
+	# implementation will not work if for example atomic operations are
+	# used for thread/interrupt synchronization.
+	config_path="${config_path} gthr"
+	USE_CONFIG_GTHR=1
 	;;
 esac
 
diff --git a/libatomic/testsuite/Makefile.in b/libatomic/testsuite/Makefile.in
index 8bc70562e5b..80652d1ffb1 100644
--- a/libatomic/testsuite/Makefile.in
+++ b/libatomic/testsuite/Makefile.in
@@ -103,7 +103,8 @@  am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \
 	$(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \
 	$(top_srcdir)/acinclude.m4 $(top_srcdir)/../libtool.m4 \
 	$(top_srcdir)/../config/enable.m4 \
-	$(top_srcdir)/../config/cet.m4 $(top_srcdir)/configure.ac
+	$(top_srcdir)/../config/cet.m4 $(top_srcdir)/../config/gthr.m4 \
+	$(top_srcdir)/configure.ac
 am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
 	$(ACLOCAL_M4)
 DIST_COMMON = $(srcdir)/Makefile.am
@@ -262,6 +263,7 @@  target_alias = @target_alias@
 target_cpu = @target_cpu@
 target_os = @target_os@
 target_vendor = @target_vendor@
+thread_header = @thread_header@
 tmake_file = @tmake_file@
 toolexecdir = @toolexecdir@
 toolexeclibdir = @toolexeclibdir@