* 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>
+
+ 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.
--- /dev/null
+/* 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
+}
--- /dev/null
+/* 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 */
--- /dev/null
+# 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])
+])
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)