See attached patch. _gfortran_caf_end_team synchronized the team with
sync_team, whose barrier wait threw away the count of images that had
stopped or failed, and then left STAT= at 0. A stopped or failed image
in the team being ended was therefore never reported. The barrier
round already records how many images had left when it ended, and
counter_barrier_wait_abortable already passes that out; this patch
lets counter_barrier_wait pass it out too. END TEAM keeps the
non-abortable wait, so the remaining images still synchronize with
each other, and then calls TEAM_HEALTH_CHECK on the ended team when
the count is nonzero.
Start with _gfortran_caf_end_team in shmem.c: the barrier wait that
returns the count, the coarray deallocation that no longer takes
STAT=/ERRMSG= (so a deallocation status cannot overwrite the team
status), and TEAM_HEALTH_CHECK at the end, after the team is back on
caf_teams_formed. Then counter_barrier_wait in counter_barrier.c and
counter_barrier.h, which forwards TERMINATED to wait_round; the
comment on TERMINATED moves to it from the abortable variant.
sync_team in sync.c passes NULL. Of the tests, end_team_stat_1 and
end_team_stat_2 are new. signal_team_1, stop_end_team_1 and
stop_sync_team_1 end a team that contains a stopped or failed image,
which now means error termination without STAT=, so they get
END TEAM (STAT=).
Regression tested on x86_64.
OK for mainline?
Regards,
Jerry
---
libgfortran: [PR127837] Set END TEAM STAT= for stopped and failed images
With caf_shmem, END TEAM always returned STAT=0 because
_gfortran_caf_end_team synchronized with sync_team, which does not
report stopped or failed images. Without STAT= such an image did not
cause error termination either, as F2023 11.7.11 requires. END TEAM
now takes the number of terminated images from the barrier round and
runs TEAM_HEALTH_CHECK on the ended team after deallocating its
coarrays; counter_barrier_wait gains a TERMINATED argument for this.
Existing tests that end a team containing a stopped or failed image
now give END TEAM a STAT= variable.
Assisted-by: Claude Opus 5.5
PR libfortran/127837
libgfortran/ChangeLog:
* caf/shmem.c (_gfortran_caf_end_team): Wait with
counter_barrier_wait and set STAT= with TEAM_HEALTH_CHECK when
an image of the team stopped or failed. Do not pass STAT= to
_gfortran_caf_deregister.
* caf/shmem/counter_barrier.c (counter_barrier_wait): Add
TERMINATED argument.
* caf/shmem/counter_barrier.h (counter_barrier_wait): Likewise.
* caf/shmem/sync.c (sync_team): Update call.
gcc/testsuite/ChangeLog:
* gfortran.dg/coarray/signal_team_1.f90: Add STAT= to END TEAM.
* gfortran.dg/coarray/stop_end_team_1.f90: Likewise and check it.
* gfortran.dg/coarray/stop_sync_team_1.f90: Likewise.
* gfortran.dg/coarray/end_team_stat_1.f90: New test.
* gfortran.dg/coarray/end_team_stat_2.f90: New test.
>From 87475204c580c4fff745a3c1d146760d32418466 Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Mon, 5 Oct 2026 18:13:33 -0700
Subject: [PATCH] libgfortran: [PR127837] Set END TEAM STAT= for stopped and
failed images
With caf_shmem, END TEAM always returned STAT=0 because
_gfortran_caf_end_team synchronized with sync_team, which does not
report stopped or failed images. Without STAT= such an image did not
cause error termination either, as F2023 11.7.11 requires. END TEAM
now takes the number of terminated images from the barrier round and
runs TEAM_HEALTH_CHECK on the ended team after deallocating its
coarrays; counter_barrier_wait gains a TERMINATED argument for this.
Existing tests that end a team containing a stopped or failed image
now give END TEAM a STAT= variable.
Assisted-by: Claude Opus 5.5
PR libfortran/127837
libgfortran/ChangeLog:
* caf/shmem.c (_gfortran_caf_end_team): Wait with
counter_barrier_wait and set STAT= with TEAM_HEALTH_CHECK when
an image of the team stopped or failed. Do not pass STAT= to
_gfortran_caf_deregister.
* caf/shmem/counter_barrier.c (counter_barrier_wait): Add
TERMINATED argument.
* caf/shmem/counter_barrier.h (counter_barrier_wait): Likewise.
* caf/shmem/sync.c (sync_team): Update call.
gcc/testsuite/ChangeLog:
* gfortran.dg/coarray/signal_team_1.f90: Add STAT= to END TEAM.
* gfortran.dg/coarray/stop_end_team_1.f90: Likewise and check it.
* gfortran.dg/coarray/stop_sync_team_1.f90: Likewise.
* gfortran.dg/coarray/end_team_stat_1.f90: New test.
* gfortran.dg/coarray/end_team_stat_2.f90: New test.
---
.../gfortran.dg/coarray/end_team_stat_1.f90 | 42 +++++++++++++++++++
.../gfortran.dg/coarray/end_team_stat_2.f90 | 18 ++++++++
.../gfortran.dg/coarray/signal_team_1.f90 | 2 +-
.../gfortran.dg/coarray/stop_end_team_1.f90 | 3 +-
.../gfortran.dg/coarray/stop_sync_team_1.f90 | 4 +-
libgfortran/caf/shmem.c | 17 +++++---
libgfortran/caf/shmem/counter_barrier.c | 4 +-
libgfortran/caf/shmem/counter_barrier.h | 10 ++---
libgfortran/caf/shmem/sync.c | 2 +-
9 files changed, 85 insertions(+), 17 deletions(-)
create mode 100644 gcc/testsuite/gfortran.dg/coarray/end_team_stat_1.f90
create mode 100644 gcc/testsuite/gfortran.dg/coarray/end_team_stat_2.f90
diff --git a/gcc/testsuite/gfortran.dg/coarray/end_team_stat_1.f90 b/gcc/testsuite/gfortran.dg/coarray/end_team_stat_1.f90
new file mode 100644
index 00000000000..1a3fdafefe2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/end_team_stat_1.f90
@@ -0,0 +1,42 @@
+! { dg-do run }
+! { dg-skip-if "CHANGE TEAM needs a coarray library" { *-*-* } { "-fcoarray=single" } { "" } }
+!
+! END TEAM (STAT=) reports a stopped or failed image of the team it ends,
+! not one of a sibling team, and still deallocates the team's coarrays.
+
+program end_team_stat_1
+ use iso_fortran_env, only : team_type, stat_stopped_image, stat_failed_image
+ implicit none
+ type(team_type) :: t
+ integer, allocatable :: a[:]
+ integer :: me, st
+ character(len=40) :: msg
+
+ if (num_images () < 6) stop
+ me = mod (this_image () - 1, 3) + 1
+ form team (me, t)
+
+ change team (t)
+ msg = "unchanged"
+ end team (stat=st, errmsg=msg)
+ if (st /= 0 .or. msg /= "unchanged") error stop 1
+
+ change team (t)
+ allocate (a[*])
+ if (this_image () == num_images ()) then
+ if (me == 1) stop
+ if (me == 2) fail image
+ end if
+ st = -1
+ msg = "unchanged"
+ end team (stat=st, errmsg=msg)
+ if (allocated (a)) error stop 2
+ select case (me)
+ case (1)
+ if (st /= stat_stopped_image .or. msg == "unchanged") error stop 3
+ case (2)
+ if (st /= stat_failed_image .or. msg == "unchanged") error stop 4
+ case (3)
+ if (st /= 0 .or. msg /= "unchanged") error stop 5
+ end select
+end program end_team_stat_1
diff --git a/gcc/testsuite/gfortran.dg/coarray/end_team_stat_2.f90 b/gcc/testsuite/gfortran.dg/coarray/end_team_stat_2.f90
new file mode 100644
index 00000000000..600d4058448
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/coarray/end_team_stat_2.f90
@@ -0,0 +1,18 @@
+! { dg-do run }
+! { dg-skip-if "CHANGE TEAM needs a coarray library" { *-*-* } { "-fcoarray=single" } { "" } }
+! { dg-shouldfail "END TEAM without STAT= in a team with a stopped image" }
+!
+! END TEAM without STAT= in a team with a stopped image is error
+! termination.
+
+program end_team_stat_2
+ use iso_fortran_env, only : team_type
+ implicit none
+ type(team_type) :: t
+
+ if (num_images () < 2) error stop
+ form team (1, t)
+ change team (t)
+ if (this_image () == num_images ()) stop
+ end team
+end program end_team_stat_2
diff --git a/gcc/testsuite/gfortran.dg/coarray/signal_team_1.f90 b/gcc/testsuite/gfortran.dg/coarray/signal_team_1.f90
index 958801a7fda..bcce79c939e 100644
--- a/gcc/testsuite/gfortran.dg/coarray/signal_team_1.f90
+++ b/gcc/testsuite/gfortran.dg/coarray/signal_team_1.f90
@@ -22,5 +22,5 @@ program signal_team_1
if (st == stat_failed_image) exit
end do
if (num_images () > 1 .and. st /= stat_failed_image) error stop "not reported"
- end team
+ end team (stat=st)
end program signal_team_1
diff --git a/gcc/testsuite/gfortran.dg/coarray/stop_end_team_1.f90 b/gcc/testsuite/gfortran.dg/coarray/stop_end_team_1.f90
index 79e7d246f57..3b5fe656ff5 100644
--- a/gcc/testsuite/gfortran.dg/coarray/stop_end_team_1.f90
+++ b/gcc/testsuite/gfortran.dg/coarray/stop_end_team_1.f90
@@ -21,7 +21,8 @@ program stop_end_team_1
if (st /= 0 .and. st /= stat_stopped_image) error stop 1
end do
end if
- end team
+ end team (stat=st)
+ if (me == 1 .and. num_images () > 2 .and. st /= stat_stopped_image) error stop 3
st = -1
sync all (stat=st)
if (num_images () > 2 .and. st /= stat_stopped_image) error stop 2
diff --git a/gcc/testsuite/gfortran.dg/coarray/stop_sync_team_1.f90 b/gcc/testsuite/gfortran.dg/coarray/stop_sync_team_1.f90
index 9eba00e7b10..a3c9106d35d 100644
--- a/gcc/testsuite/gfortran.dg/coarray/stop_sync_team_1.f90
+++ b/gcc/testsuite/gfortran.dg/coarray/stop_sync_team_1.f90
@@ -28,5 +28,7 @@ program stop_sync_team_1
sync team (get_team (), stat=st)
if (me == 2 .and. st /= 0) error stop 3
if (me == 1 .and. st /= stat_stopped_image) error stop 4
- end team
+ end team (stat=st)
+ if (me == 2 .and. st /= 0) error stop 5
+ if (me == 1 .and. st /= stat_stopped_image) error stop 6
end program stop_sync_team_1
diff --git a/libgfortran/caf/shmem.c b/libgfortran/caf/shmem.c
index 7fb23f05e6c..014a26e9c9e 100644
--- a/libgfortran/caf/shmem.c
+++ b/libgfortran/caf/shmem.c
@@ -1899,26 +1899,31 @@ void
_gfortran_caf_end_team (int *stat, char *errmsg, size_t errmsg_len)
{
caf_shmem_team_t t = caf_current_team;
-
- if (stat)
- *stat = 0;
+ int terminated;
caf_current_team = caf_current_team->parent;
next_memid = t->parent_teams_last_active_memid;
- sync_team (t);
+ /* The active images synchronize even with a stopped image, unlike in
+ SYNC ALL (F2023 11.7.11). */
+ counter_barrier_wait (&t->u.image_info->image_count, &terminated);
for (struct coarray_allocated *ca = t->allocated; ca;)
{
struct coarray_allocated *nca = ca->next;
_gfortran_caf_deregister ((caf_token_t *) &ca->token,
- CAF_DEREGTYPE_COARRAY_DEALLOCATE_ONLY, stat,
- errmsg, errmsg_len);
+ CAF_DEREGTYPE_COARRAY_DEALLOCATE_ONLY, NULL,
+ NULL, 0);
free (ca);
ca = nca;
}
t->allocated = NULL;
t->parent = caf_teams_formed;
caf_teams_formed = t;
+
+ if (terminated)
+ TEAM_HEALTH_CHECK (t, stat, errmsg, errmsg_len);
+ else if (stat)
+ *stat = 0;
}
void
diff --git a/libgfortran/caf/shmem/counter_barrier.c b/libgfortran/caf/shmem/counter_barrier.c
index 1a30e45dda7..bf3a5fbb9d9 100644
--- a/libgfortran/caf/shmem/counter_barrier.c
+++ b/libgfortran/caf/shmem/counter_barrier.c
@@ -108,10 +108,10 @@ wait_round (counter_barrier *b, bool abortable, int *terminated)
}
void
-counter_barrier_wait (counter_barrier *b)
+counter_barrier_wait (counter_barrier *b, int *terminated)
{
lock_counter_barrier (b);
- while (!wait_round (b, false, NULL))
+ while (!wait_round (b, false, terminated))
;
unlock_counter_barrier (b);
}
diff --git a/libgfortran/caf/shmem/counter_barrier.h b/libgfortran/caf/shmem/counter_barrier.h
index 2eb886545b1..110cd71d76b 100644
--- a/libgfortran/caf/shmem/counter_barrier.h
+++ b/libgfortran/caf/shmem/counter_barrier.h
@@ -88,14 +88,14 @@ void counter_barrier_init_add (counter_barrier *, int);
int counter_barrier_get_count (counter_barrier *);
/* Wait for the count in the barrier drop to or below 0. When the round is
- aborted, take part in the next one. */
+ aborted, take part in the next one. TERMINATED, when given, receives the
+ number of images that had been removed from the barrier when the round
+ ended; images removed later are not counted. */
-void counter_barrier_wait (counter_barrier *);
+void counter_barrier_wait (counter_barrier *, int *terminated);
/* Like counter_barrier_wait, but return false without waiting when the
- barrier is aborting, or when the round is aborted. TERMINATED, when
- given, receives the number of images that had been removed from the
- barrier when the round ended; images removed later are not counted. */
+ barrier is aborting, or when the round is aborted. */
bool counter_barrier_wait_abortable (counter_barrier *, int *terminated);
diff --git a/libgfortran/caf/shmem/sync.c b/libgfortran/caf/shmem/sync.c
index e3041a3c128..4245c155f14 100644
--- a/libgfortran/caf/shmem/sync.c
+++ b/libgfortran/caf/shmem/sync.c
@@ -175,7 +175,7 @@ sync_all (int *terminated)
void
sync_team (caf_shmem_team_t team)
{
- counter_barrier_wait (&team->u.image_info->image_count);
+ counter_barrier_wait (&team->u.image_info->image_count, NULL);
}
bool
--
2.56.0