#ifndef GMX_UTILITY_OMP_H
#define GMX_UTILITY_OMP_H
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
+
+#include <stdio.h>
#ifndef GMX_NATIVE_WINDOWS
/* Ugly hack because the openmp implementation below hacks into the SIMD
#include <windows.h>
#endif
-#include "types/commrec.h"
-#include "mdrun.h"
+#include "gromacs/utility/basedefinitions.h"
#ifdef __cplusplus
extern "C"
/*! \brief
* Check for externally set thread affinity to avoid conflicts with \Gromacs
* internal setting.
+ *
+ * \param[out] message Receives the message to be shown to the user.
+ * \returns `true` if we can set thread affinity ourselves.
+ *
+ * While GNU OpenMP does not set affinity by default, the Intel OpenMP library
+ * does. This conflicts with the internal affinity (especially thread-MPI)
+ * setting, results in incorrectly locked threads, and causes dreadful performance.
+ *
+ * The KMP_AFFINITY environment variable is used by Intel, GOMP_CPU_AFFINITY
+ * by the GNU compilers (Intel also honors it well). If any of the variables
+ * is set, we should honor it and disable the internal pinning.
+ * When using Intel OpenMP, we will disable affinity if the user did not set it
+ * manually through one of the aforementioned environment variables.
+ *
+ * Note that the Intel OpenMP affinity disabling will only take effect if this
+ * function is called before the OpenMP library gets initialized, which happens
+ * when the first call is made into a compilation unit that contains OpenMP
+ * pragmas.
+ *
+ * If this function returns `false`, the caller is responsible to disable the
+ * pinning, show the message from \p *message to the user, and free the memory
+ * allocated for \p *message.
+ * If the return value is `true`, \p *message is NULL.
*/
-void gmx_omp_check_thread_affinity(FILE *fplog, const t_commrec *cr,
- gmx_hw_opt_t *hw_opt);
+gmx_bool gmx_omp_check_thread_affinity(char **message);
/*! \brief
* Pause for use in a spin-wait loop.
*/
static gmx_inline void gmx_pause()
{
-#ifndef GMX_NATIVE_WINDOWS
+#ifndef _MSC_VER
/* Ugly hack because the openmp implementation below hacks into the SIMD
* settings to decide when to use _mm_pause(). This should eventually be
* changed into proper detection of the intrinsics uses, not SIMD.
*/
-#if (defined GMX_SIMD_X86_SSE2) || (defined GMX_SIMD_X86_SSE4_1) || \
+#if ((defined GMX_SIMD_X86_SSE2) || (defined GMX_SIMD_X86_SSE4_1) || \
(defined GMX_SIMD_X86_AVX_128_FMA) || (defined GMX_SIMD_X86_AVX_256) || \
- (defined GMX_SIMD_X86_AVX2_256)
+ (defined GMX_SIMD_X86_AVX2_256)) && !defined(__MINGW32__)
/* Replace with tbb::internal::atomic_backoff when/if we use TBB */
_mm_pause();
#elif defined __MIC__