Skip to content

Commit

Permalink
Require C11
Browse files Browse the repository at this point in the history
Error out if the compiler does not support C11.

Removes support for `__thread` since we now rely on C11 `_Thread_local`.

*Auxilliary fixes required to build with C11:*

Replace typeof() with size_t in loop header
All uses of the `PREPARE_REQUESTS_WITH_NO_FREE` macro map to size_t.

Add feature test macro _POSIX_C_SOURCE to enable fileno()
Flex prior to 2.6.6 uses fileno() but does not define the needed
feature test macros.
See westes/flex#263 for details.

Add feature test macro to enable pthread_mutexattr_settype()

Enable nanosleep with _POSIX_C_SOURCE
Move calls to nanosleep out of headers and add the feature test macro
_POSIX_C_SOURCE to enable its use. This should not cause
any significant overheads.

Reduce_local test: Add feature test macros
Needed for strsep(), posix_memalign(), and getopt().
Also fix the min/max macros. There is no need to cache the variables
as these macros are used without producing side-effects.

Include ompi_config.h in reduce_local.c

Signed-off-by: Joseph Schuchart <[email protected]>
  • Loading branch information
devreal committed Dec 17, 2024
1 parent 28c2e47 commit eaea24f
Show file tree
Hide file tree
Showing 12 changed files with 97 additions and 101 deletions.
33 changes: 4 additions & 29 deletions config/opal_setup_cc.m4
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ AC_DEFUN([OPAL_SETUP_CC],[
AC_REQUIRE([_OPAL_PROG_CC])
AC_REQUIRE([AM_PROG_CC_C_O])

OPAL_VAR_SCOPE_PUSH([opal_prog_cc_c11_helper__Thread_local_available opal_prog_cc_c11_helper_atomic_var_available opal_prog_cc_c11_helper__Atomic_available opal_prog_cc_c11_helper__static_assert_available opal_prog_cc_c11_helper__Generic_available opal_prog_cc__thread_available opal_prog_cc_c11_helper_atomic_fetch_xor_explicit_available opal_prog_cc_c11_helper_proper__Atomic_support_in_atomics])
OPAL_VAR_SCOPE_PUSH([opal_prog_cc_c11_helper__Thread_local_available opal_prog_cc_c11_helper_atomic_var_available opal_prog_cc_c11_helper__Atomic_available opal_prog_cc_c11_helper__static_assert_available opal_prog_cc_c11_helper__Generic_available opal_prog_cc_c11_helper_atomic_fetch_xor_explicit_available opal_prog_cc_c11_helper_proper__Atomic_support_in_atomics])

OPAL_PROG_CC_C11

Expand All @@ -179,33 +179,11 @@ AC_DEFUN([OPAL_SETUP_CC],[
OPAL_C_COMPILER_VENDOR([opal_c_vendor])

if test $opal_cv_c11_supported = no ; then
# It is not currently an error if C11 support is not available. Uncomment the
# following lines and update the warning when we require a C11 compiler.
# AC_MSG_WARNING([Open MPI requires a C11 (or newer) compiler])
# AC_MSG_ERROR([Aborting.])
# From Open MPI 1.7 on we require a C99 compliant compiler
dnl with autoconf 2.70 AC_PROG_CC makes AC_PROG_CC_C99 obsolete
m4_version_prereq([2.70],
[],
[AC_PROG_CC_C99])
# The result of AC_PROG_CC_C99 is stored in ac_cv_prog_cc_c99
if test "x$ac_cv_prog_cc_c99" = xno ; then
AC_MSG_WARN([Open MPI requires a C99 (or newer) compiler. C11 is recommended.])
AC_MSG_ERROR([Aborting.])
fi

# Get the correct result for C11 support flags now that the compiler flags have
# changed
OPAL_PROG_CC_C11_HELPER([], [], [])
# C11 is required
AC_MSG_WARN([Open MPI requires a C11 (or newer) compiler. C11 is required.])
AC_MSG_ERROR([Aborting.])
fi

# Check if compiler support __thread
OPAL_CC_HELPER([if $CC $1 supports __thread], [opal_prog_cc__thread_available],
[],[[static __thread int foo = 1;++foo;]])

OPAL_CC_HELPER([if $CC $1 supports C11 _Thread_local], [opal_prog_cc_c11_helper__Thread_local_available],
[],[[static _Thread_local int foo = 1;++foo;]])

dnl At this time Open MPI only needs thread local and the atomic convenience types for C11 support. These
dnl will likely be required in the future.
AC_DEFINE_UNQUOTED([OPAL_C_HAVE__THREAD_LOCAL], [$opal_prog_cc_c11_helper__Thread_local_available],
Expand All @@ -223,9 +201,6 @@ AC_DEFUN([OPAL_SETUP_CC],[
AC_DEFINE_UNQUOTED([OPAL_C_HAVE__STATIC_ASSERT], [$opal_prog_cc_c11_helper__static_assert_available],
[Whether C compiler support _Static_assert keyword])

AC_DEFINE_UNQUOTED([OPAL_C_HAVE___THREAD], [$opal_prog_cc__thread_available],
[Whether C compiler supports __thread])

# Check for standard headers, needed here because needed before
# the types checks. This is only necessary for Autoconf < v2.70.
m4_version_prereq([2.70],
Expand Down
2 changes: 1 addition & 1 deletion ompi/mca/vprotocol/pessimist/vprotocol_pessimist_wait.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ static int vprotocol_pessimist_request_no_free(ompi_request_t **req) {
}

#define PREPARE_REQUESTS_WITH_NO_FREE(count, requests) do { \
for (typeof(count) i = 0; i < count; i++) \
for (size_t i = 0; i < count; i++) \
{ \
if(requests[i] == MPI_REQUEST_NULL) continue; \
requests[i]->req_free = vprotocol_pessimist_request_no_free; \
Expand Down
2 changes: 1 addition & 1 deletion opal/class/opal_fifo.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ static inline opal_list_item_t *opal_fifo_pop_atomic(opal_fifo_t *fifo)
if (++attempt == 5) {
/* deliberately suspend this thread to allow other threads to run. this should
* only occur during periods of contention on the lifo. */
_opal_lifo_release_cpu();
opal_lifo_release_cpu();
attempt = 0;
}

Expand Down
17 changes: 17 additions & 0 deletions opal/class/opal_lifo.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@
* $HEADER$
*/

/* needed for nanosleep() */
#define _POSIX_C_SOURCE 200809L

#include "opal_config.h"
#include <time.h>
#include "opal/class/opal_lifo.h"

static void opal_lifo_construct(opal_lifo_t *lifo)
Expand All @@ -31,3 +35,16 @@ static void opal_lifo_construct(opal_lifo_t *lifo)
}

OBJ_CLASS_INSTANCE(opal_lifo_t, opal_object_t, opal_lifo_construct, NULL);


void opal_lifo_release_cpu(void)
{
/* NTH: there are many ways to cause the current thread to be suspended. This one
* should work well in most cases. Another approach would be to use poll (NULL, 0, ) but
* the interval will be forced to be in ms (instead of ns or us). Note that there
* is a performance improvement for the lifo test when this call is made on detection
* of contention but it may not translate into actually MPI or application performance
* improvements. */
static struct timespec interval = {.tv_sec = 0, .tv_nsec = 100};
nanosleep(&interval, NULL);
}
15 changes: 2 additions & 13 deletions opal/class/opal_lifo.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

#include "opal_config.h"
#include "opal/class/opal_list.h"
#include <time.h>

#include "opal/mca/threads/mutex.h"
#include "opal/sys/atomic.h"
Expand Down Expand Up @@ -92,17 +91,7 @@ opal_read_counted_pointer(volatile opal_counted_pointer_t *volatile addr,
/**
* @brief Helper function for lifo/fifo to sleep this thread if excessive contention is detected
*/
static inline void _opal_lifo_release_cpu(void)
{
/* NTH: there are many ways to cause the current thread to be suspended. This one
* should work well in most cases. Another approach would be to use poll (NULL, 0, ) but
* the interval will be forced to be in ms (instead of ns or us). Note that there
* is a performance improvement for the lifo test when this call is made on detection
* of contention but it may not translate into actually MPI or application performance
* improvements. */
static struct timespec interval = {.tv_sec = 0, .tv_nsec = 100};
nanosleep(&interval, NULL);
}
void opal_lifo_release_cpu(void);

/* Atomic Last In First Out lists. If we are in a multi-threaded environment then the
* atomicity is insured via the compare-and-swap operation, if not we simply do a read
Expand Down Expand Up @@ -225,7 +214,7 @@ static inline opal_list_item_t *opal_lifo_pop_atomic(opal_lifo_t *lifo)
if (++attempt == 5) {
/* deliberately suspend this thread to allow other threads to run. this should
* only occur during periods of contention on the lifo. */
_opal_lifo_release_cpu();
opal_lifo_release_cpu();
attempt = 0;
}

Expand Down
40 changes: 40 additions & 0 deletions opal/mca/threads/pthreads/threads_pthreads_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
* $HEADER$
*/

/* needed for pthread_mutexattr_settype */
#define _GNU_SOURCE

#include <unistd.h>
#include <pthread.h>

#include "opal/constants.h"
#include "opal/mca/threads/threads.h"
Expand All @@ -38,3 +42,39 @@ int opal_tsd_key_create(opal_tsd_key_t *key, opal_tsd_destructor_t destructor)
rc = pthread_key_create(key, destructor);
return 0 == rc ? OPAL_SUCCESS : OPAL_ERR_IN_ERRNO;
}


int opal_thread_internal_mutex_init_recursive(opal_thread_internal_mutex_t *p_mutex)
{
int ret;
#if OPAL_ENABLE_DEBUG
pthread_mutexattr_t mutex_attr;
ret = pthread_mutexattr_init(&mutex_attr);
if (0 != ret)
return OPAL_ERR_IN_ERRNO;
ret = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
if (0 != ret) {
ret = pthread_mutexattr_destroy(&mutex_attr);
assert(0 == ret);
return OPAL_ERR_IN_ERRNO;
}
ret = pthread_mutex_init(p_mutex, &mutex_attr);
if (0 != ret) {
ret = pthread_mutexattr_destroy(&mutex_attr);
assert(0 == ret);
return OPAL_ERR_IN_ERRNO;
}
ret = pthread_mutexattr_destroy(&mutex_attr);
assert(0 == ret);
#else
pthread_mutexattr_t mutex_attr;
ret = pthread_mutexattr_init(&mutex_attr);
if (0 != ret) {
return OPAL_ERR_IN_ERRNO;
}
pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
ret = pthread_mutex_init(p_mutex, &mutex_attr);
pthread_mutexattr_destroy(&mutex_attr);
#endif
return 0 == ret ? OPAL_SUCCESS : OPAL_ERR_IN_ERRNO;
}
39 changes: 5 additions & 34 deletions opal/mca/threads/pthreads/threads_pthreads_mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,48 +61,19 @@ typedef pthread_mutex_t opal_thread_internal_mutex_t;
# define OPAL_THREAD_INTERNAL_RECURSIVE_MUTEX_INITIALIZER PTHREAD_RECURSIVE_MUTEX_INITIALIZER
#endif


int opal_thread_internal_mutex_init_recursive(opal_thread_internal_mutex_t *p_mutex);

static inline int opal_thread_internal_mutex_init(opal_thread_internal_mutex_t *p_mutex,
bool recursive)
{
int ret;
#if OPAL_ENABLE_DEBUG
if (recursive) {
pthread_mutexattr_t mutex_attr;
ret = pthread_mutexattr_init(&mutex_attr);
if (0 != ret)
return OPAL_ERR_IN_ERRNO;
ret = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
if (0 != ret) {
ret = pthread_mutexattr_destroy(&mutex_attr);
assert(0 == ret);
return OPAL_ERR_IN_ERRNO;
}
ret = pthread_mutex_init(p_mutex, &mutex_attr);
if (0 != ret) {
ret = pthread_mutexattr_destroy(&mutex_attr);
assert(0 == ret);
return OPAL_ERR_IN_ERRNO;
}
ret = pthread_mutexattr_destroy(&mutex_attr);
assert(0 == ret);
} else {
ret = pthread_mutex_init(p_mutex, NULL);
}
#else
if (recursive) {
pthread_mutexattr_t mutex_attr;
ret = pthread_mutexattr_init(&mutex_attr);
if (0 != ret) {
return OPAL_ERR_IN_ERRNO;
}
pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
ret = pthread_mutex_init(p_mutex, &mutex_attr);
pthread_mutexattr_destroy(&mutex_attr);
return opal_thread_internal_mutex_init_recursive(p_mutex);
} else {
ret = pthread_mutex_init(p_mutex, NULL);
return 0 == ret ? OPAL_SUCCESS : OPAL_ERR_IN_ERRNO;
}
#endif
return 0 == ret ? OPAL_SUCCESS : OPAL_ERR_IN_ERRNO;
}

static inline void opal_thread_internal_mutex_lock(opal_thread_internal_mutex_t *p_mutex)
Expand Down
3 changes: 3 additions & 0 deletions opal/mca/threads/pthreads/threads_pthreads_yield.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
* $HEADER$
*/

/* needed for nanosleep() */
#define _POSIX_C_SOURCE 200809L

#include "opal_config.h"
#include <time.h>
#ifdef HAVE_SCHED_H
Expand Down
10 changes: 0 additions & 10 deletions opal/mca/threads/thread_usage.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,17 +250,7 @@ OPAL_THREAD_DEFINE_ATOMIC_SWAP(int64_t, int64_t, 64)
# define OPAL_ATOMIC_SWAP_64 opal_thread_swap_64

/* thread local storage */
#if OPAL_C_HAVE__THREAD_LOCAL
# define opal_thread_local _Thread_local
# define OPAL_HAVE_THREAD_LOCAL 1

#elif OPAL_C_HAVE___THREAD /* OPAL_C_HAVE__THREAD_LOCAL */
# define opal_thread_local __thread
# define OPAL_HAVE_THREAD_LOCAL 1
#endif /* OPAL_C_HAVE___THREAD */

#if !defined(OPAL_HAVE_THREAD_LOCAL)
# define OPAL_HAVE_THREAD_LOCAL 0
#endif /* !defined(OPAL_HAVE_THREAD_LOCAL) */

#endif /* OPAL_MCA_THREADS_THREAD_USAGE_H */
6 changes: 6 additions & 0 deletions opal/util/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ libopalutil_core_la_DEPENDENCIES = \
json/libopalutil_json.la \
keyval/libopalutilkeyval.la

# flex prior to version 2.6.6 uses the POSIX extension fileno()
# without providing the proper feature test macro, so
# we add the _POSIX_C_SOURCE macro here.
# See https://github.com/westes/flex/issues/263
libopalutil_core_la_CFLAGS = -D_POSIX_C_SOURCE=200809L

# Conditionally install the header files

if WANT_INSTALL_HEADERS
Expand Down
6 changes: 6 additions & 0 deletions opal/util/keyval/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,11 @@ libopalutilkeyval_la_SOURCES = \
keyval_lex.h \
keyval_lex.l

# flex prior to version 2.6.6 uses the POSIX extension fileno()
# without providing the proper feature test macro, so
# we add the _POSIX_C_SOURCE macro here.
# See https://github.com/westes/flex/issues/263
libopalutilkeyval_la_CFLAGS = -D_POSIX_C_SOURCE=200809L

maintainer-clean-local:
rm -f keyval_lex.c
25 changes: 12 additions & 13 deletions test/datatype/reduce_local.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,22 @@
* reserved.
* Copyright (c) 2020 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2024 Stony Brook University. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/

/* needed for strsep() */
#define _DEFAULT_SOURCE
#define _BSD_SOURCE

/* needed for posix_memalign() and getopt() */
#define _POSIX_C_SOURCE 200809L

#include "ompi_config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
Expand Down Expand Up @@ -50,19 +59,9 @@ static int do_ops[12] = {
static int verbose = 0;
static int total_errors = 0;

#define max(a, b) \
({ \
__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_a > _b ? _a : _b; \
})

#define min(a, b) \
({ \
__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_a < _b ? _a : _b; \
})
#define max(a, b) (a) > (b) ? (a) : (b)

#define min(a, b) (a) < (b) ? (a) : (b)

static void print_status(char *op, char *type, int type_size, int count, int max_shift,
double *duration, int repeats, int correct)
Expand Down

0 comments on commit eaea24f

Please sign in to comment.