Skip to content

Commit 1275e5f

Browse files
author
Andy Hanson
authored
Always fire join events for an rjoin (#651)
Previously, there was an additional check `if (!join_struct.wait_done)` at the beginning of an rjoin. This usually had no effect as the join isn't usually done yet. But if thread A is the first to enter the join and finishes before thread B starts, then B will never enter the `if`. The only effect this had was that B would not fire join events in these rare cases. (After that we check `join_struct.wait_done` again anyway.) As of this PR we will always fire the events, which makes them easier to analyze consistently. Before this PR, looking at the join events for a single thread would show no traces of the rjoin happening, except for an extra restart event from the other thread.
1 parent 7814f97 commit 1275e5f

File tree

1 file changed

+30
-36
lines changed

1 file changed

+30
-36
lines changed

src/coreclr/src/gc/gc.cpp

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,50 +1022,44 @@ class t_join
10221022

10231023
if (Interlocked::CompareExchange(&join_struct.r_join_lock, 0, join_struct.n_threads) == 0)
10241024
{
1025-
if (!join_struct.wait_done)
1026-
{
1027-
dprintf (JOIN_LOG, ("r_join() Waiting..."));
1025+
fire_event (gch->heap_number, time_start, type_join, join_id);
10281026

1029-
fire_event (gch->heap_number, time_start, type_join, join_id);
1027+
dprintf (JOIN_LOG, ("r_join() Waiting..."));
10301028

1031-
//busy wait around the color
1032-
if (!join_struct.wait_done)
1033-
{
1029+
//busy wait around the color
10341030
respin:
1035-
int spin_count = 256 * yp_spin_count_unit;
1036-
for (int j = 0; j < spin_count; j++)
1037-
{
1038-
if (join_struct.wait_done)
1039-
{
1040-
break;
1041-
}
1042-
YieldProcessor(); // indicate to the processor that we are spinning
1043-
}
1044-
1045-
// we've spun, and if color still hasn't changed, fall into hard wait
1046-
if (!join_struct.wait_done)
1047-
{
1048-
dprintf (JOIN_LOG, ("Join() hard wait on reset event %d", first_thread_arrived));
1049-
uint32_t dwJoinWait = join_struct.joined_event[first_thread_arrived].Wait(INFINITE, FALSE);
1050-
if (dwJoinWait != WAIT_OBJECT_0)
1051-
{
1052-
STRESS_LOG1 (LF_GC, LL_FATALERROR, "joined event wait failed with code: %Ix", dwJoinWait);
1053-
FATAL_GC_ERROR ();
1054-
}
1055-
}
1056-
1057-
// avoid race due to the thread about to reset the event (occasionally) being preempted before ResetEvent()
1058-
if (!join_struct.wait_done)
1059-
{
1060-
goto respin;
1061-
}
1031+
int spin_count = 256 * yp_spin_count_unit;
1032+
for (int j = 0; j < spin_count; j++)
1033+
{
1034+
if (join_struct.wait_done)
1035+
{
1036+
break;
1037+
}
1038+
YieldProcessor(); // indicate to the processor that we are spinning
1039+
}
10621040

1063-
dprintf (JOIN_LOG, ("r_join() done"));
1041+
// we've spun, and if color still hasn't changed, fall into hard wait
1042+
if (!join_struct.wait_done)
1043+
{
1044+
dprintf (JOIN_LOG, ("Join() hard wait on reset event %d", first_thread_arrived));
1045+
uint32_t dwJoinWait = join_struct.joined_event[first_thread_arrived].Wait(INFINITE, FALSE);
1046+
if (dwJoinWait != WAIT_OBJECT_0)
1047+
{
1048+
STRESS_LOG1 (LF_GC, LL_FATALERROR, "joined event wait failed with code: %Ix", dwJoinWait);
1049+
FATAL_GC_ERROR ();
10641050
}
1051+
}
10651052

1066-
fire_event (gch->heap_number, time_end, type_join, join_id);
1053+
// avoid race due to the thread about to reset the event (occasionally) being preempted before ResetEvent()
1054+
if (!join_struct.wait_done)
1055+
{
1056+
goto respin;
10671057
}
10681058

1059+
dprintf (JOIN_LOG, ("r_join() done"));
1060+
1061+
fire_event (gch->heap_number, time_end, type_join, join_id);
1062+
10691063
return FALSE;
10701064
}
10711065
else

0 commit comments

Comments
 (0)