Hi! When thinking about GOMP_teams3, I've realized that using global variables for the values returned by omp_get_num_teams()/omp_get_team_num() calls is incorrect even with our right now dumb way of implementing host teams. The problems are two, one is if host teams is used from multiple pthread_create created threads - the spec says that host teams can't be nested inside of explicit parallel or other teams constructs, but with pthread_create the standard says obviously nothing about it. Another more important thing is host fallback, right now we don't do anything for omp_get_num_teams() or omp_get_team_num() which was fine before host teams was introduced and the 5.1 requirement that num_teams clause specifies minimum of teams, but with the global vars it means inside of target teams num_teams (2) we happily return omp_get_num_teams() == 4 if the target teams is inside of host teams with num_teams(4). With target fallback being invoked from parallel regions global vars simply can't work right on the host. Both with nowait target and with synchronous target too, as while doing host fallback from one thread a different thread could see wrong values.
So, this patch moves them to struct gomp_thread and propagates those for parallel to child threads. For host fallback, the implicit zeroing of *thr results in us returning omp_get_num_teams () == 1 and omp_get_team_num () == 0 which is fine for target teams without num_teams clause, for target teams with num_teams clause something to work on and for target without teams nested in it I've asked on omp-lang what should be done. Regtested on x86_64-linux, committed to trunk. 2021-11-11 Jakub Jelinek <ja...@redhat.com> * libgomp.h (struct gomp_thread): Add num_teams and team_num members. * team.c (struct gomp_thread_start_data): Likewise. (gomp_thread_start): Initialize thr->num_teams and thr->team_num. (gomp_team_start): Initialize start_data->num_teams and start_data->team_num. Update nthr->num_teams and nthr->team_num. * teams.c (gomp_num_teams, gomp_team_num): Remove. (GOMP_teams_reg): Set and restore thr->num_teams and thr->team_num instead of gomp_num_teams and gomp_team_num. (omp_get_num_teams): Use thr->num_teams + 1 instead of gomp_num_teams. (omp_get_team_num): Use thr->team_num instead of gomp_team_num. * testsuite/libgomp.c/teams-4.c: New test. --- libgomp/libgomp.h.jj 2021-10-20 09:34:47.004331626 +0200 +++ libgomp/libgomp.h 2021-11-11 12:44:47.710092897 +0100 @@ -768,6 +768,14 @@ struct gomp_thread /* User pthread thread pool */ struct gomp_thread_pool *thread_pool; +#ifdef LIBGOMP_USE_PTHREADS + /* omp_get_num_teams () - 1. */ + unsigned int num_teams; + + /* omp_get_team_num (). */ + unsigned int team_num; +#endif + #if defined(LIBGOMP_USE_PTHREADS) \ && (!defined(HAVE_TLS) \ || !defined(__GLIBC__) \ --- libgomp/team.c.jj 2021-09-28 11:34:29.380146749 +0200 +++ libgomp/team.c 2021-11-11 12:55:22.524952564 +0100 @@ -56,6 +56,8 @@ struct gomp_thread_start_data struct gomp_task *task; struct gomp_thread_pool *thread_pool; unsigned int place; + unsigned int num_teams; + unsigned int team_num; bool nested; pthread_t handle; }; @@ -88,6 +90,8 @@ gomp_thread_start (void *xdata) thr->ts = data->ts; thr->task = data->task; thr->place = data->place; + thr->num_teams = data->num_teams; + thr->team_num = data->team_num; #ifdef GOMP_NEEDS_THREAD_HANDLE thr->handle = data->handle; #endif @@ -645,6 +649,8 @@ gomp_team_start (void (*fn) (void *), vo nthr->ts.single_count = 0; #endif nthr->ts.static_trip = 0; + nthr->num_teams = thr->num_teams; + nthr->team_num = thr->team_num; nthr->task = &team->implicit_task[i]; nthr->place = place; gomp_init_task (nthr->task, task, icv); @@ -833,6 +839,8 @@ gomp_team_start (void (*fn) (void *), vo start_data->ts.single_count = 0; #endif start_data->ts.static_trip = 0; + start_data->num_teams = thr->num_teams; + start_data->team_num = thr->team_num; start_data->task = &team->implicit_task[i]; gomp_init_task (start_data->task, task, icv); team->implicit_task[i].icv.nthreads_var = nthreads_var; --- libgomp/teams.c.jj 2021-10-11 12:20:21.927063104 +0200 +++ libgomp/teams.c 2021-11-11 12:43:58.769797557 +0100 @@ -28,14 +28,12 @@ #include "libgomp.h" #include <limits.h> -static unsigned gomp_num_teams = 1, gomp_team_num = 0; - void GOMP_teams_reg (void (*fn) (void *), void *data, unsigned int num_teams, unsigned int thread_limit, unsigned int flags) { + struct gomp_thread *thr = gomp_thread (); (void) flags; - (void) num_teams; unsigned old_thread_limit_var = 0; if (thread_limit == 0) thread_limit = gomp_teams_thread_limit_var; @@ -48,11 +46,11 @@ GOMP_teams_reg (void (*fn) (void *), voi } if (num_teams == 0) num_teams = gomp_nteams_var ? gomp_nteams_var : 3; - gomp_num_teams = num_teams; - for (gomp_team_num = 0; gomp_team_num < num_teams; gomp_team_num++) + thr->num_teams = num_teams - 1; + for (thr->team_num = 0; thr->team_num < num_teams; thr->team_num++) fn (data); - gomp_num_teams = 1; - gomp_team_num = 0; + thr->num_teams = 0; + thr->team_num = 0; if (thread_limit) { struct gomp_task_icv *icv = gomp_icv (true); @@ -63,13 +61,15 @@ GOMP_teams_reg (void (*fn) (void *), voi int omp_get_num_teams (void) { - return gomp_num_teams; + struct gomp_thread *thr = gomp_thread (); + return thr->num_teams + 1; } int omp_get_team_num (void) { - return gomp_team_num; + struct gomp_thread *thr = gomp_thread (); + return thr->team_num; } ialias (omp_get_num_teams) --- libgomp/testsuite/libgomp.c/teams-4.c.jj 2021-11-11 13:13:05.834638687 +0100 +++ libgomp/testsuite/libgomp.c/teams-4.c 2021-11-11 13:27:37.730085919 +0100 @@ -0,0 +1,30 @@ +#include <omp.h> +#include <stdlib.h> + +int +main () +{ + if (omp_get_num_teams () != 1 || omp_get_team_num () != 0) + abort (); + #pragma omp parallel num_threads (2) + if (omp_get_num_teams () != 1 || omp_get_team_num () != 0) + abort (); + #pragma omp teams num_teams (4) + { + int team = omp_get_team_num (); + if (omp_get_num_teams () != 4 || (unsigned) team >= 4U) + abort (); + #pragma omp parallel num_threads (3) + if (omp_get_num_teams () != 4 || omp_get_team_num () != team) + abort (); + #pragma omp parallel if (0) + #pragma omp target + #pragma omp teams num_teams (2) + if (omp_get_num_teams () > 2 + || (unsigned) omp_get_team_num () >= 2U) + abort (); + if (omp_get_num_teams () != 4 || (unsigned) team >= 4U) + abort (); + } + return 0; +} Jakub