From c5f0dcf72ba10434685abeec356de313acba294f Mon Sep 17 00:00:00 2001 From: Ivan K Date: Wed, 19 Feb 2025 16:55:49 +0300 Subject: [PATCH 1/3] c_check: test for omp_pause_resource_all() Assume that the ctest3.c program successfully compiling and linking means that the function is available. --- c_check | 10 ++++++++++ c_check.pl | 10 ++++++++++ ctest3.c | 2 ++ 3 files changed, 22 insertions(+) create mode 100644 ctest3.c diff --git a/c_check b/c_check index 9801b87783..a29256d160 100755 --- a/c_check +++ b/c_check @@ -412,6 +412,14 @@ fi [ "$USE_OPENMP" != 1 ] && openmp='' +have_omp_pause_resource_all=0 +if [ "$USE_OPENMP" = 1 ]; then + if $compiler_name $flags $openmp -o ctest3 ctest3.c; then + have_omp_pause_resource_all=1 + fi + rm -f ctest3.o ctest3 ctest3.exe +fi + linker_L="" linker_l="" linker_a="" @@ -501,6 +509,7 @@ done [ "$oldgcc" -eq 1 ] && printf "OLDGCC=1\n" [ "$no_lsx" -eq 1 ] && printf "NO_LSX=1\n" [ "$no_lasx" -eq 1 ] && printf "NO_LASX=1\n" + [ "$have_omp_pause_resource_all" -eq 1 ] && printf "HAVE_OMP_PAUSE_RESOURCE_ALL=1\n" } >> "$makefile" os=`echo "$os" | tr '[[:lower:]]' '[[:upper:]]'/ ` @@ -518,6 +527,7 @@ compiler=`echo "$compiler" | tr '[[:lower:]]' '[[:upper:]]' ` [ "$c11_atomics" -eq 1 ] && printf "#define HAVE_C11\t1\n" [ "$no_lsx" -eq 1 ] && printf "#define NO_LSX\t1\n" [ "$no_lasx" -eq 1 ] && printf "#define NO_LASX\t1\n" + [ "$have_omp_pause_resource_all" -eq 1 ] && printf "#define HAVE_OMP_PAUSE_RESOURCE_ALL\t1\n" } >> "$config" diff --git a/c_check.pl b/c_check.pl index 6b89f06eb3..ecae09c60d 100644 --- a/c_check.pl +++ b/c_check.pl @@ -394,6 +394,14 @@ $openmp = "" if $ENV{USE_OPENMP} != 1; +$have_omp_pause_resource_all=0; +if ($ENV{USE_OPENMP} == 1) { + if (system("$compiler_name $flags $openmp -o ctest3 ctest3.c") == 0) { + $have_omp_pause_resource_all=1; + } + unlink "ctest3.o", "ctest3", "ctest3.exe"; +} + $linker_L = ""; $linker_l = ""; $linker_a = ""; @@ -472,6 +480,7 @@ print MAKEFILE "OLDGCC=1\n" if $oldgcc eq 1; print MAKEFILE "NO_LSX=1\n" if $no_lsx eq 1; print MAKEFILE "NO_LASX=1\n" if $no_lasx eq 1; +print MAKEFILE "HAVE_OMP_PAUSE_RESOURCE_ALL=1\n" if $have_omp_pause_resource_all eq 1; $os =~ tr/[a-z]/[A-Z]/; $architecture =~ tr/[a-z]/[A-Z]/; @@ -487,6 +496,7 @@ print CONFFILE "#define HAVE_C11\t1\n" if $c11_atomics eq 1; print CONFFILE "#define NO_LSX\t1\n" if $no_lsx eq 1; print CONFFILE "#define NO_LASX\t1\n" if $no_lasx eq 1; +print CONFFILE "#define HAVE_OMP_PAUSE_RESOURCE_ALL\t1\n" if $have_omp_pause_resource_all eq 1; if ($os eq "LINUX") { diff --git a/ctest3.c b/ctest3.c new file mode 100644 index 0000000000..3ac3e929c2 --- /dev/null +++ b/ctest3.c @@ -0,0 +1,2 @@ +#include +int main(void) { return omp_pause_resource_all(omp_pause_hard); } From f677f4f29b59e5b7aae0a62965689f7586a28563 Mon Sep 17 00:00:00 2001 From: Ivan K Date: Sat, 10 Jun 2023 20:35:59 +0300 Subject: [PATCH 2/3] blas_thread_shutdown: release OpenMP resources too OpenMP 5.0 introduced the function omp_pause_resource_all that instructs the runtime to "relinquish resources used by OpenMP on all devices". In practice, these resources include the locks that would otherwise trip up the runtime after a fork(). Releasing these resources in a function called by pthread_atfork() makes it possible for the child process to continue functioning after the runtime automatically re-acquires its resources. Thread safety: blas_thread_shutdown doesn't check whether there are other BLAS operations running in parallel, so this isn't any less safe than before with respect to OpenBLAS function calls. On the other hand, if there are other OpenMP operations in progress, asking the runtime to pause may result in unspecified behaviour. A hard pause is allowed to deallocate threadprivate variables too. --- driver/others/blas_server_omp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/driver/others/blas_server_omp.c b/driver/others/blas_server_omp.c index 38b48fc842..32bd995a2a 100644 --- a/driver/others/blas_server_omp.c +++ b/driver/others/blas_server_omp.c @@ -48,6 +48,7 @@ #else +#include #ifndef likely #ifdef __GNUC__ #define likely(x) __builtin_expect(!!(x), 1) @@ -172,6 +173,9 @@ int BLASFUNC(blas_thread_shutdown)(void){ } } } +#if HAVE_OMP_PAUSE_RESOURCE_ALL + omp_pause_resource_all(omp_pause_hard); +#endif return 0; } From 806073ccbc8de53fffd762038c3a88f118320ae8 Mon Sep 17 00:00:00 2001 From: Ivan K Date: Sat, 10 Jun 2023 21:20:58 +0300 Subject: [PATCH 3/3] utest: test fork safety on OpenMP >= 5 In addition to testing fork safety on non-OpenMP builds, test it when omp_pause_resource_all() is available to release the locks. --- utest/Makefile | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/utest/Makefile b/utest/Makefile index b82937093f..40dc551ed9 100644 --- a/utest/Makefile +++ b/utest/Makefile @@ -44,10 +44,14 @@ endif #this does not work with OpenMP nor with native Windows or Android threads # FIXME TBD if this works on OSX, SunOS, POWER and zarch ifeq ($(OSNAME), $(filter $(OSNAME),Linux CYGWIN_NT)) -ifneq ($(USE_OPENMP), 1) -OBJS += test_fork.o +ifeq ($(USE_OPENMP), 1) +ifeq ($(HAVE_OMP_PAUSE_RESOURCE_ALL), 1) + OBJS += test_fork.o endif -OBJS += test_post_fork.o +else + OBJS += test_fork.o +endif + OBJS += test_post_fork.o endif ifeq ($(C_COMPILER), PGI)