]> Savannah Git Hosting - gnulib.git/commitdiff
openmp: Add workaround for 32-bit programs on AIX.
authorBruno Haible <bruno@clisp.org>
Tue, 9 Apr 2019 19:02:35 +0000 (21:02 +0200)
committerBruno Haible <bruno@clisp.org>
Tue, 9 Apr 2019 19:03:38 +0000 (21:03 +0200)
* lib/omp.in.h: New file.
* lib/omp-init.c: New file, based on lib/nproc.c.
* m4/omp_h.m4: New file.
* modules/openmp (Files): Add them.
(Depends-on): Add include_next, c-ctype, setenv.
(configure.ac): Invoke gl_OMP_H.
(Makefile.am): Add rules to create omp.h and compile omp-init.c.
(Include): Mention <omp.h>.

ChangeLog
lib/omp-init.c [new file with mode: 0644]
lib/omp.in.h [new file with mode: 0644]
m4/omp_h.m4 [new file with mode: 0644]
modules/openmp

index 035e411552fe1b2e2dc8dc1addab3836ca4530af..87d95ed9934361ca3e82ac8450f6609bed8677b9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2019-04-09  Bruno Haible  <bruno@clisp.org>
+
+       openmp: Add workaround for 32-bit programs on AIX.
+       * lib/omp.in.h: New file.
+       * lib/omp-init.c: New file, based on lib/nproc.c.
+       * m4/omp_h.m4: New file.
+       * modules/openmp (Files): Add them.
+       (Depends-on): Add include_next, c-ctype, setenv.
+       (configure.ac): Invoke gl_OMP_H.
+       (Makefile.am): Add rules to create omp.h and compile omp-init.c.
+       (Include): Mention <omp.h>.
+
 2019-04-09  Bruno Haible  <bruno@clisp.org>
 
        nproc: Fix return value for privileged processes.
diff --git a/lib/omp-init.c b/lib/omp-init.c
new file mode 100644 (file)
index 0000000..f849067
--- /dev/null
@@ -0,0 +1,88 @@
+/* Initialize OpenMP.
+
+   Copyright (C) 2017-2019 Free Software Foundation, Inc.
+
+   This program 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 2, or (at your option)
+   any later version.
+
+   This program 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <omp.h>
+
+#include <stdlib.h>
+
+#include "c-ctype.h"
+
+#if defined _AIX
+
+/* Parse OMP environment variables without dependence on OMP.
+   Return 0 for invalid values.  */
+static unsigned long int
+parse_omp_threads (char const* threads)
+{
+  unsigned long int ret = 0;
+
+  if (threads == NULL)
+    return ret;
+
+  /* The OpenMP spec says that the value assigned to the environment variables
+     "may have leading and trailing white space".  */
+  while (*threads != '\0' && c_isspace (*threads))
+    threads++;
+
+  /* Convert it from positive decimal to 'unsigned long'.  */
+  if (c_isdigit (*threads))
+    {
+      char *endptr = NULL;
+      unsigned long int value = strtoul (threads, &endptr, 10);
+
+      if (endptr != NULL)
+        {
+          while (*endptr != '\0' && c_isspace (*endptr))
+            endptr++;
+          if (*endptr == '\0')
+            return value;
+          /* Also accept the first value in a nesting level,
+             since we can't determine the nesting level from env vars.  */
+          else if (*endptr == ',')
+            return value;
+        }
+    }
+
+  return ret;
+}
+
+#endif
+
+void
+openmp_init (void)
+{
+  /* On AIX 7.2, in 32-bit mode, use of OpenMP on machines with 64 or 128
+     processors makes the program fail with an error message
+     "1587-120 SMP runtime library error. Memory allocation failed when creating thread number 62.".
+     The workaround is to tell the OpenMP library to create fewer than 62
+     threads.  This can be done through the OMP_THREAD_LIMIT environment
+     variable.  */
+#if defined _AIX
+  if (sizeof (long) == sizeof (int))
+    {
+      /* Ensure that OMP_THREAD_LIMIT has a value <= 32.  */
+      unsigned long int omp_env_limit =
+        parse_omp_threads (getenv ("OMP_THREAD_LIMIT"));
+
+      if (!(omp_env_limit > 0 && omp_env_limit <= 32))
+        setenv ("OMP_THREAD_LIMIT", "32", 1);
+    }
+#endif
+}
diff --git a/lib/omp.in.h b/lib/omp.in.h
new file mode 100644 (file)
index 0000000..46d2587
--- /dev/null
@@ -0,0 +1,43 @@
+/* OpenMP declarations.
+
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This program 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.
+
+   This program 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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#if __GNUC__ >= 3
+@PRAGMA_SYSTEM_HEADER@
+#endif
+@PRAGMA_COLUMNS@
+
+#ifndef _@GUARD_PREFIX@_OMP_H
+
+/* The include_next requires a split double-inclusion guard.  */
+#@INCLUDE_NEXT@ @NEXT_OMP_H@
+
+#ifndef _@GUARD_PREFIX@_OMP_H
+#define _@GUARD_PREFIX@_OMP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Initializes environment variables necessary for OpenMP.  */
+extern void openmp_init (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _@GUARD_PREFIX@_OMP_H */
+#endif /* _@GUARD_PREFIX@_OMP_H */
diff --git a/m4/omp_h.m4 b/m4/omp_h.m4
new file mode 100644 (file)
index 0000000..87905bb
--- /dev/null
@@ -0,0 +1,10 @@
+# omp_h.m4 serial 1
+dnl Copyright (C) 2019 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_OMP_H],
+[
+  gl_NEXT_HEADERS([omp.h])
+])
index 76f012d2d6dc32d3d581aa596337e37eecebcb88..ef8e605fe88dbbac13f1890c4b015866e1b324f1 100644 (file)
@@ -2,15 +2,43 @@ Description:
 Detection of OpenMP support.
 
 Files:
+lib/omp.in.h
+lib/omp-init.c
+m4/omp_h.m4
 
 Depends-on:
+include_next
+c-ctype
+setenv
 
 configure.ac:
 AC_OPENMP
+gl_OMP_H
 
 Makefile.am:
+BUILT_SOURCES += omp.h
+
+# We need the following in order to create <omp.h> when the system
+# doesn't have one that works with the given compiler.
+omp.h: omp.in.h $(top_builddir)/config.status $(CXXDEFS_H) \
+  $(_NORETURN_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
+       $(AM_V_GEN)rm -f $@-t $@ && \
+       { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \
+         sed -e 's|@''GUARD_PREFIX''@|${gl_include_guard_prefix}|g' \
+             -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
+             -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
+             -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
+             -e 's|@''NEXT_OMP_H''@|$(NEXT_OMP_H)|g' \
+             < $(srcdir)/omp.in.h; \
+       } > $@-t && \
+       mv $@-t $@
+MOSTLYCLEANFILES += omp.h omp.h-t
+lib_SOURCES += omp-init.c
 
 Include:
+#ifdef _OPENMP
+# include <omp.h>
+#endif
 
 Link:
 $(OPENMP_CFLAGS)