diff --git a/ompi/mpi/c/init.c.in b/ompi/mpi/c/init.c.in index b9e5d513482..16a4d5525cc 100644 --- a/ompi/mpi/c/init.c.in +++ b/ompi/mpi/c/init.c.in @@ -15,6 +15,7 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2025 Advanced Micro Devices, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -46,7 +47,12 @@ PROTOTYPE INT init(INT_OUT argc, ARGV argv) if (NULL != (env = getenv("OMPI_MPI_THREAD_LEVEL"))) { required = atoi(env); - if (required < MPI_THREAD_SINGLE || required > MPI_THREAD_MULTIPLE) { + /* In the future we may have to contend with non-sequential (MPI ABI) values + * If you are implementing MPI ABI changes please refer to + * https://github.com/open-mpi/ompi/pull/13211#discussion_r2085086844 + */ + if (required != MPI_THREAD_SINGLE && required != MPI_THREAD_FUNNELED && + required != MPI_THREAD_SERIALIZED && required != MPI_THREAD_MULTIPLE) { required = MPI_THREAD_MULTIPLE; } } diff --git a/ompi/mpi/c/init_thread.c.in b/ompi/mpi/c/init_thread.c.in index f56728ee262..1e18b66040f 100644 --- a/ompi/mpi/c/init_thread.c.in +++ b/ompi/mpi/c/init_thread.c.in @@ -18,6 +18,7 @@ * reserved. * Copyright (c) 2024 Triad National Security, LLC. All rights * reserved. + * Copyright (c) 2025 Advanced Micro Devices, Inc. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -40,6 +41,7 @@ PROTOTYPE ERROR_CLASS init_thread(INT_OUT argc, ARGV argv, INT required, INT_OUT provided) { int err, safe_required = MPI_THREAD_SERIALIZED; + bool err_arg_required = false; char *env; ompi_hook_base_mpi_init_thread_top(argc, argv, required, provided); @@ -47,14 +49,28 @@ PROTOTYPE ERROR_CLASS init_thread(INT_OUT argc, ARGV argv, INT required, /* Detect an incorrect thread support level, but dont report until we have the minimum * infrastructure setup. */ - if( (MPI_THREAD_SINGLE == required) || (MPI_THREAD_SERIALIZED == required) || - (MPI_THREAD_FUNNELED == required) || (MPI_THREAD_MULTIPLE == required) ) { + err_arg_required = (required != MPI_THREAD_SINGLE && required != MPI_THREAD_FUNNELED && + required != MPI_THREAD_SERIALIZED && required != MPI_THREAD_MULTIPLE); + if (!err_arg_required) { + safe_required = required; + } - if (NULL != (env = getenv("OMPI_MPI_THREAD_LEVEL"))) { - safe_required = atoi(env); - } - else { - safe_required = required; + /* check for environment overrides for required thread level. If + * there is, check to see that it is a valid/supported thread level. + * If valid, the environment variable always override the provided thread + * level (even if lower than argument `required`). A user program can + * check `provided != required` to check if `required` has been overruled. + */ + if (NULL != (env = getenv("OMPI_MPI_THREAD_LEVEL"))) { + int env_required = atoi(env); + /* In the future we may have to contend with non-sequential (MPI ABI) values + * If you are implementing MPI ABI changes please refer to + * https://github.com/open-mpi/ompi/pull/13211#discussion_r2085086844 + */ + err_arg_required |= (env_required != MPI_THREAD_SINGLE && env_required != MPI_THREAD_FUNNELED && + env_required != MPI_THREAD_SERIALIZED && env_required != MPI_THREAD_MULTIPLE); + if (!err_arg_required) { + safe_required = env_required; } } @@ -70,7 +86,7 @@ PROTOTYPE ERROR_CLASS init_thread(INT_OUT argc, ARGV argv, INT required, err = ompi_mpi_init(0, NULL, safe_required, provided, false); } - if( safe_required != required ) { + if (err_arg_required) { /* Trigger the error handler for the incorrect argument. Keep it separate from the * check on the ompi_mpi_init return and report a nice, meaningful error message to * the user. */