Chung-Lin Tang 5283f9c926 OpenMP: requires unified_shared_memory patch, insert USM allocators into libgfortran
(This is a backport of
 https://gcc.gnu.org/pipermail/gcc-patches/2022-September/601059.html)

After the prior libgfortran memory allocator preparation patch, this is the
actual patch that organizes unified_shared_memory allocation into libgfortran.

In the current OpenMP requires implementation, the requires_mask is collected
through offload LTO processing, and presented to libgomp when registering
offload images through GOMP_offload_register_ver() (called by the mkoffload
generated constructor linked into the program binary)

This means that the only reliable place to access omp_requires_mask is in
GOMP_offload_register_ver, however since it is called through an ELF constructor
in the *main program*, this runs later than libgfortran/runtime/main.c:init()
constructor, and because some libgfortran init actions there start allocating
memory, this can cause more deallocation errors later.

Another issue is that CUDA appears to be registering some cleanup actions using
atexit(), which forces libgomp to register gomp_target_fini() using atexit as
well (to properly run before the underlying CUDA stuff disappears). This happens
to us here as well.

In summary we need to: (1) order libgfortran init actions after
omp_requires_mask processing is done, and (2) order libgfortran cleanup actions
before gomp_target_fini, to properly deallocate stuff without crashing.

We implement this by creating callback registering functions exported from
libgomp to libgfortran, basically to register libgfortran init/fini actions
into libgomp to run.

Inside GOMP_offload_register_ver, after omp_requires_mask processing is done,
we call into libgfortran through a new _gfortran_mem_allocators_init function
to insert the omp_free/alloc/etc. based allocators into the Fortran runtime,
when GOMP_REQUIRES_UNIFIED_SHARED_MEMORY is set.

All symbol references between libgfortran/libgomp are defined with weak
symbols. Test of the weak symbols are also used to determine if the other
library exists in this program.

For the final case where we have an OpenMP program that does NOT have
offloading, we cannot passively determine in libgomp/libgfortran whether
offloading exists or not, only the main program itself can, by seeing if the
hidden __OFFLOAD_TABLE__ exists. But those with no offloading will not have
those callback properly run (because of no offload image loading)
Therefore the solution here is a constructor added into the crtoffloadend.o
fragment that does a "null" call of GOMP_offload_register_ver, solely for
triggering the post-offload_register callbacks when __OFFLOAD_TABLE__ is NULL.
(crtoffloadend.o Makefile rule is adjusted to compile with PIC due to this)

libgcc/ChangeLog:
	* Makefile.in (crtoffloadend$(objext)): Add $(PICFLAG) to compile rule.
	* offloadstuff.c (GOMP_offload_register_ver): Add declaration of weak
	symbol.
	(__OFFLOAD_TABLE__): Likewise.
	(init_non_offload): New function.

libgfortran/ChangeLog:
	* gfortran.map (GFORTRAN_13): New namespace.
	(_gfortran_mem_allocators_init): New name inside GFORTRAN_14.
	* libgfortran.h (mem_allocators_init): New exported declaration.
	* runtime/main.c (do_init): Rename from init, add run-once guard code.
	(cleanup): Add run-once guard code.
	(GOMP_post_offload_register_callback): Declare weak symbol.
	(GOMP_pre_gomp_target_fini_callback): Likewise.
	(init): New constructor to register offload callbacks, or call do_init
	when not OpenMP.
	* runtime/memory.c (gfortran_malloc): New pointer variable.
	(gfortran_calloc): Likewise.
	(gfortran_realloc): Likewise.
	(gfortran_free): Likewise.
	(mem_allocators_init): New function.
	(xmalloc): Use gfortran_malloc.
	(xmallocarray): Use gfortran_malloc.
	(xcalloc): Use gfortran_calloc.
	(xrealloc): Use gfortran_realloc.
	(xfree): Use gfortran_free.

libgomp/ChangeLog:
	* libgomp.map (GOMP_5.1.2): New version namespace.
	(GOMP_post_offload_register_callback): New name inside GOMP_5.1.2.
	(GOMP_pre_gomp_target_fini_callback): Likewise.
	(GOMP_DEFINE_CALLBACK_SET): Macro to define callback set.
	(post_offload_register): Define callback set for after offload image
	register.
	(pre_gomp_target_fini): Define callback set for before gomp_target_fini
	is called.
	(libgfortran_malloc_usm): New function.
	(libgfortran_calloc_usm): Likewise
	(libgfortran_realloc_usm): Likewise
	(libgfortran_free_usm): Likewise.
	(_gfortran_mem_allocators_init): Declare weak symbol.
	(gomp_libgfortran_omp_allocators_init): New function.
	(GOMP_offload_register_ver): Add handling of host_table == NULL, calling
	into libgfortran to set unified_shared_memory allocators, and execution
	of post_offload_register callbacks.
	(gomp_target_init): Register all pre_gomp_target_fini callbacks to run
	at end of main using atexit().

	* testsuite/libgomp.fortran/target-unified_shared_memory-1.f90: New test.
2023-08-21 07:47:29 -07:00
2023-08-04 00:19:47 +00:00
2023-08-13 00:20:08 +00:00
2023-08-08 00:20:39 +00:00
2022-07-19 17:07:04 +03:00

This directory contains the GNU Compiler Collection (GCC).

The GNU Compiler Collection is free software.  See the files whose
names start with COPYING for copying permission.  The manuals, and
some of the runtime libraries, are under different terms; see the
individual source files for details.

The directory INSTALL contains copies of the installation information
as HTML and plain text.  The source of this information is
gcc/doc/install.texi.  The installation information includes details
of what is included in the GCC sources and what files GCC installs.

See the file gcc/doc/gcc.texi (together with other files that it
includes) for usage and porting information.  An online readable
version of the manual is in the files gcc/doc/gcc.info*.

See http://gcc.gnu.org/bugs/ for how to report bugs usefully.

Copyright years on GCC source files may be listed using range
notation, e.g., 1987-2012, indicating that every year in the range,
inclusive, is a copyrightable year that could otherwise be listed
individually.
Description
No description provided
Readme 2.7 GiB
Languages
C++ 30.7%
C 30.1%
Ada 14.4%
D 6.1%
Go 5.7%
Other 12.5%