File 0238-timer_bif_SUITE-Fix-flaky-test-cases.patch of Package erlang

From 6c5d04c442b7aec0293ae8e5f6689226e6106d8e Mon Sep 17 00:00:00 2001
From: Kjell Winblad <kjellwinblad@gmail.com>
Date: Thu, 8 Apr 2021 11:41:56 +0200
Subject: [PATCH 1/2] timer_bif_SUITE: Fix flaky test cases

The test cases `timer_bif_SUITE:same_time_yielding*` failed consistently
on a PowerPC machine with 64 cores. There are two reasons for
this:

* The number of timers started depended on the number of schedulers
  but the amount of time after the actual timeout the receiver could
  get the timeout message was not adjusted accordingly.
* The use of the undocumented function `erlang:process_flag(scheduler,
  SchedId)` caused long waiting times that will not happen in a real
  system as `erlang:process_flag(scheduler, SchedId)` is not indented
  for external use.
---
 erts/emulator/test/timer_bif_SUITE.erl | 67 +++++++++++++++++++++-----
 1 file changed, 54 insertions(+), 13 deletions(-)

diff --git a/erts/emulator/test/timer_bif_SUITE.erl b/erts/emulator/test/timer_bif_SUITE.erl
index 68048b9771..5316793fed 100644
--- a/erts/emulator/test/timer_bif_SUITE.erl
+++ b/erts/emulator/test/timer_bif_SUITE.erl
@@ -493,19 +493,36 @@ registered_process(Config) when is_list(Config) ->
 same_time_yielding(Config) when is_list(Config) ->
     Mem = mem(),
     Ref = make_ref(),
-    SchdlrsOnln = erlang:system_info(schedulers_online),
-    Tmo = erlang:monotonic_time(millisecond) + 6000,
+    SchdlrsOnline = erlang:system_info(schedulers_online),
+    SchdlrsToUse = erlang:max(1, erlang:min(8, SchdlrsOnline) - 1),
+    StartTime = erlang:monotonic_time(millisecond),
+    Tmo = StartTime + 20000,
+    NrOfTimeouts = (?TIMEOUT_YIELD_LIMIT*3+1) * SchdlrsToUse,
+    NrOfTimeoutsPerScheduler = NrOfTimeouts div SchdlrsToUse,
     Tmrs = lists:map(fun (I) ->
-                             process_flag(scheduler, (I rem SchdlrsOnln) + 1),
-                             erlang:start_timer(Tmo, self(), Ref, [{abs, true}])
+                             SchedulerId =
+                                 case SchdlrsOnline of
+                                     1 -> 1;
+                                     _ ->
+                                         ((I div NrOfTimeoutsPerScheduler) rem SchdlrsToUse)  + 2
+                                 end,
+                             process_flag(scheduler, SchedulerId),
+                             erlang:start_timer(Tmo, self(), Ref, [{abs, true}]),
+                             SchedulerId
                      end,
-                     lists:seq(1, (?TIMEOUT_YIELD_LIMIT*3+1)*SchdlrsOnln)),
+                     lists:seq(1, NrOfTimeouts)),
+    process_flag(scheduler, 1),
+    AllTimersStartedTime = erlang:monotonic_time(millisecond),
     true = mem_larger_than(Mem),
-    receive_all_timeouts(length(Tmrs), Ref),
+    {TimeToReceive, TimeUntilFirst} = receive_all_timeouts(length(Tmrs), Ref),
     Done = erlang:monotonic_time(millisecond),
     true = Done >= Tmo,
     MsAfterTmo = Done - Tmo,
-    io:format("Done ~p ms after Tmo\n", [MsAfterTmo]),
+    io:format("Done ~p ms after Tmo\nInfo: ~p\n",
+              [MsAfterTmo,
+               {'TimeToStartAllTimers', AllTimersStartedTime - StartTime,
+                'TimeInReceiveUntilFirst',TimeUntilFirst,
+                'TimeToReceive', TimeToReceive}]),
     case erlang:system_info(build_type) of
         opt ->
             true = MsAfterTmo < 200;
@@ -518,12 +535,26 @@ same_time_yielding(Config) when is_list(Config) ->
 %% Read out all timeouts in receive queue order. This is efficient
 %% even if there are very many messages.
 
-receive_all_timeouts(0, _Ref) ->
-    ok;
 receive_all_timeouts(N, Ref) ->
+    receive_all_timeouts(N, Ref, not_set).
+
+receive_all_timeouts(0, _Ref, {FirstTime, TimeUntilFirst}) ->
+    {erlang:monotonic_time(millisecond) - FirstTime, TimeUntilFirst};
+receive_all_timeouts(N, Ref, Timings) ->
+    StartTime = case Timings of
+        not_set -> erlang:monotonic_time(millisecond);
+        _ -> ok
+    end,
     receive
         {timeout, _Tmr, Ref} ->
-            receive_all_timeouts(N-1, Ref)
+            NewTimings =
+                case Timings of
+                    not_set ->
+                        FirstMessageAtTime = erlang:monotonic_time(millisecond),
+                        {FirstMessageAtTime, FirstMessageAtTime - StartTime};
+                    _ -> Timings
+                end,
+            receive_all_timeouts(N-1, Ref, NewTimings)
     end.
 
 same_time_yielding_with_cancel(Config) when is_list(Config) ->
@@ -554,7 +585,10 @@ do_cancel_tmrs(Tmo, Tmrs, Tester) ->
 
 same_time_yielding_with_cancel_test(Other, Accessor) ->
     Mem = mem(),
-    SchdlrsOnln = erlang:system_info(schedulers_online),
+    SchdlrsOnline = erlang:system_info(schedulers_online),
+    SchdlrsToUse = erlang:max(1, erlang:min(8, SchdlrsOnline) - 1),
+    NrOfTimeouts = (?TIMEOUT_YIELD_LIMIT*3+1) * SchdlrsToUse,
+    NrOfTimeoutsPerScheduler = NrOfTimeouts div SchdlrsToUse,
     Tmo = erlang:monotonic_time(millisecond) + 6000,
     Tester = self(),
     Cancelor = case Other of
@@ -573,10 +607,17 @@ same_time_yielding_with_cancel_test(Other, Accessor) ->
                true -> [{accessor, Cancelor}, {abs, true}]
            end,
     Tmrs = lists:map(fun (I) ->
-                             process_flag(scheduler, (I rem SchdlrsOnln) + 1),
+                             SchedulerId =
+                                 case SchdlrsOnline of
+                                     1 -> 1;
+                                     _ ->
+                                         ((I div NrOfTimeoutsPerScheduler) rem SchdlrsToUse)  + 2
+                                 end,
+                             process_flag(scheduler, SchedulerId),
                              erlang:start_timer(Tmo, self(), hej, Opts)
                      end,
-                     lists:seq(1, (?TIMEOUT_YIELD_LIMIT*3+1)*SchdlrsOnln)),
+                     lists:seq(1, NrOfTimeouts)),
+    process_flag(scheduler, 1),
     true = mem_larger_than(Mem),
     case Other of
         false ->
-- 
2.26.2

openSUSE Build Service is sponsored by