[OpenMP] Ignore teams ICV setters in restricted contexts (#194428)

This patch prevents `omp_set_num_teams()` and
`omp_set_teams_thread_limit()` from updating teams-related ICVs when
called from restricted runtime contexts.

The non-implicit parallel-region case follows the OpenMP 5.1
restriction. The active `teams`-region case is handled defensively
because these ICVs are device-scoped and updating them during an active
`teams` region can affect later teams execution.

The calls now warn and return without updating the ICVs. 

Fixes #194426.
This commit is contained in:
Sairudra More 2026-06-09 22:01:17 +05:30 committed by GitHub
parent e0d0d3db9d
commit 5adc7ddc15
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 102 additions and 0 deletions

View file

@ -482,6 +482,8 @@ AffHWSubsetIgnoringAttr "KMP_HW_SUBSET: ignoring %1$s attribute. This machi
TargetMemNotAvailable "Target memory not available, will use default allocator."
AffIgnoringNonHybrid "%1$s ignored: This machine is not a hybrid architecutre. Using \"%2$s\" instead."
AffIgnoringNotAvailable "%1$s ignored: %2$s is not available. Using \"%3$s\" instead."
SetNumTeamsInParOrTeamsRegion "%1$s() called inside a parallel or teams region; call ignored."
SetTeamsThreadLimitInParOrTeamsRegion "%1$s() called inside a parallel or teams region; call ignored."
# --------------------------------------------------------------------------------------------------
-*- HINTS -*-

View file

@ -1636,9 +1636,23 @@ void FTN_STDCALL FTN_SET_NUM_TEAMS(int KMP_DEREF num_teams) {
if (!__kmp_init_serial) {
__kmp_serial_initialize();
}
kmp_info_t *th = __kmp_entry_thread();
// OpenMP 5.1, Section 3.4.3: omp_set_num_teams may not be called from
// within a parallel region other than the implicit parallel region.
// Also guard against calls from within a teams region: nteams-var is a
// device-scoped ICV and concurrent modification from multiple team initial
// threads may race.
// t_level counts both active and serialized parallel levels (0 at the
// implicit top-level parallel region), so this catches all non-implicit
// parallel regions.
if (th->th.th_teams_microtask || th->th.th_team->t.t_level > 0) {
KMP_WARNING(SetNumTeamsInParOrTeamsRegion, "omp_set_num_teams");
return;
}
__kmp_set_num_teams(KMP_DEREF num_teams);
#endif
}
int FTN_STDCALL FTN_GET_MAX_TEAMS(void) {
#ifdef KMP_STUB
return 1;
@ -1657,9 +1671,24 @@ void FTN_STDCALL FTN_SET_TEAMS_THREAD_LIMIT(int KMP_DEREF limit) {
if (!__kmp_init_serial) {
__kmp_serial_initialize();
}
kmp_info_t *th = __kmp_entry_thread();
// OpenMP 5.1, Section 3.4.5: omp_set_teams_thread_limit may not be called
// from within a parallel region other than the implicit parallel region.
// Also guard against calls from within a teams region:
// teams-thread-limit-var is a device-scoped ICV and concurrent modification
// from multiple team initial threads may race.
// t_level counts both active and serialized parallel levels (0 at the
// implicit top-level parallel region), so this catches all non-implicit
// parallel regions.
if (th->th.th_teams_microtask || th->th.th_team->t.t_level > 0) {
KMP_WARNING(SetTeamsThreadLimitInParOrTeamsRegion,
"omp_set_teams_thread_limit");
return;
}
__kmp_set_teams_thread_limit(KMP_DEREF limit);
#endif
}
int FTN_STDCALL FTN_GET_TEAMS_THREAD_LIMIT(void) {
#ifdef KMP_STUB
return 1;

View file

@ -0,0 +1,71 @@
// RUN: %libomp-compile-and-run 2>&1 | FileCheck %s
// Verify that omp_set_num_teams() and omp_set_teams_thread_limit() are
// ignored when called from within a parallel or teams region.
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc, char **argv) {
int err = 0;
// Set initial values outside any region.
omp_set_num_teams(5);
omp_set_teams_thread_limit(7);
if (omp_get_max_teams() != 5) {
fprintf(stderr, "error: nteams-var not set correctly\n");
exit(1);
}
if (omp_get_teams_thread_limit() != 7) {
fprintf(stderr, "error: teams-thread-limit-var not set correctly\n");
exit(1);
}
// Call from inside a teams region -- should be ignored.
// Use num_teams(1) to ensure exactly one team and deterministic warning
// count.
#pragma omp teams num_teams(1)
{
omp_set_num_teams(99);
omp_set_teams_thread_limit(99);
}
if (omp_get_max_teams() != 5) {
fprintf(stderr, "error: nteams-var modified inside teams region\n");
err++;
}
if (omp_get_teams_thread_limit() != 7) {
fprintf(stderr, "error: teams-thread-limit-var modified inside teams "
"region\n");
err++;
}
// Call from inside a parallel region -- should be ignored.
#pragma omp parallel num_threads(1)
{
omp_set_num_teams(99);
omp_set_teams_thread_limit(99);
}
if (omp_get_max_teams() != 5) {
fprintf(stderr, "error: nteams-var modified inside parallel region\n");
err++;
}
if (omp_get_teams_thread_limit() != 7) {
fprintf(stderr, "error: teams-thread-limit-var modified inside parallel "
"region\n");
err++;
}
if (err == 0) {
printf("passed\n");
}
return err;
}
// CHECK: OMP: Warning{{.*}}omp_set_num_teams{{.*}}call ignored
// CHECK: OMP: Warning{{.*}}omp_set_teams_thread_limit{{.*}}call ignored
// CHECK: OMP: Warning{{.*}}omp_set_num_teams{{.*}}call ignored
// CHECK: OMP: Warning{{.*}}omp_set_teams_thread_limit{{.*}}call ignored
// CHECK: passed