diff options
Diffstat (limited to 'erts/emulator/test/scheduler_SUITE.erl')
-rw-r--r-- | erts/emulator/test/scheduler_SUITE.erl | 2057 |
1 files changed, 1176 insertions, 881 deletions
diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index 8931562828..f18d79d770 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2011. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. All Rights Reserved. %% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% @@ -30,12 +31,12 @@ %-define(line_trace, 1). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). %-compile(export_all). --export([all/0, suite/0,groups/0,init_per_suite/1, - init_per_group/2,end_per_group/2, - init_per_testcase/2, end_per_testcase/2, end_per_suite/1]). +-export([all/0, suite/0, groups/0, + init_per_suite/1, end_per_suite/1, + init_per_testcase/2, end_per_testcase/2]). -export([equal/1, few_low/1, @@ -52,21 +53,25 @@ update_cpu_info/1, sct_cmd/1, sbt_cmd/1, + scheduler_threads/1, + scheduler_suspend_basic/1, scheduler_suspend/1, + dirty_scheduler_threads/1, reader_groups/1]). --define(DEFAULT_TIMEOUT, ?t:minutes(15)). - --define(MIN_SCHEDULER_TEST_TIMEOUT, ?t:minutes(1)). - -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap, {minutes, 15}}]. all() -> [equal, few_low, many_low, equal_with_part_time_high, equal_with_part_time_max, equal_and_high_with_part_time_max, equal_with_high, - equal_with_high_max, bound_process, - {group, scheduler_bind}, scheduler_suspend, + equal_with_high_max, + bound_process, + {group, scheduler_bind}, scheduler_threads, + scheduler_suspend_basic, scheduler_suspend, + dirty_scheduler_threads, reader_groups]. groups() -> @@ -81,12 +86,6 @@ end_per_suite(Config) -> catch erts_debug:set_internal_state(available_internal_state, false), Config. -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - init_per_testcase(update_cpu_info, Config) -> case os:find_executable("taskset") of false -> @@ -98,15 +97,12 @@ init_per_testcase(Case, Config) when is_list(Config) -> init_per_tc(Case, Config). init_per_tc(Case, Config) -> - Dog = ?t:timetrap(?DEFAULT_TIMEOUT), process_flag(priority, max), erlang:display({'------------', ?MODULE, Case, '------------'}), OkRes = ok, - [{watchdog, Dog}, {testcase, Case}, {ok_res, OkRes} |Config]. + [{testcase, Case}, {ok_res, OkRes} |Config]. end_per_testcase(_Case, Config) when is_list(Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), ok. -define(ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED, (2000*2000)). @@ -126,130 +122,130 @@ many_low(Config) when is_list(Config) -> low_normal_test(Config, 2*active_schedulers(), 1000). low_normal_test(Config, NW, LW) -> - ?line Tracer = start_tracer(), - ?line Low = workers(LW, low), - ?line Normal = workers(NW, normal), - ?line Res = do_it(Tracer, Low, Normal, [], []), - ?line chk_result(Res, LW, NW, 0, 0, true, false, false), - ?line workers_exit([Low, Normal]), - ?line ok(Res, Config). + Tracer = start_tracer(), + Low = workers(LW, low), + Normal = workers(NW, normal), + Res = do_it(Tracer, Low, Normal, [], []), + chk_result(Res, LW, NW, 0, 0, true, false, false), + workers_exit([Low, Normal]), + ok(Res, Config). equal_with_part_time_high(Config) when is_list(Config) -> - ?line NW = 500, - ?line LW = 500, - ?line HW = 1, - ?line Tracer = start_tracer(), - ?line Normal = workers(NW, normal), - ?line Low = workers(LW, low), - ?line High = part_time_workers(HW, high), - ?line Res = do_it(Tracer, Low, Normal, High, []), - ?line chk_result(Res, LW, NW, HW, 0, true, true, false), - ?line workers_exit([Low, Normal, High]), - ?line ok(Res, Config). + NW = 500, + LW = 500, + HW = 1, + Tracer = start_tracer(), + Normal = workers(NW, normal), + Low = workers(LW, low), + High = part_time_workers(HW, high), + Res = do_it(Tracer, Low, Normal, High, []), + chk_result(Res, LW, NW, HW, 0, true, true, false), + workers_exit([Low, Normal, High]), + ok(Res, Config). equal_and_high_with_part_time_max(Config) when is_list(Config) -> - ?line NW = 500, - ?line LW = 500, - ?line HW = 500, - ?line MW = 1, - ?line Tracer = start_tracer(), - ?line Low = workers(LW, low), - ?line Normal = workers(NW, normal), - ?line High = workers(HW, high), - ?line Max = part_time_workers(MW, max), - ?line Res = do_it(Tracer, Low, Normal, High, Max), - ?line chk_result(Res, LW, NW, HW, MW, false, true, true), - ?line workers_exit([Low, Normal, Max]), - ?line ok(Res, Config). + NW = 500, + LW = 500, + HW = 500, + MW = 1, + Tracer = start_tracer(), + Low = workers(LW, low), + Normal = workers(NW, normal), + High = workers(HW, high), + Max = part_time_workers(MW, max), + Res = do_it(Tracer, Low, Normal, High, Max), + chk_result(Res, LW, NW, HW, MW, false, true, true), + workers_exit([Low, Normal, Max]), + ok(Res, Config). equal_with_part_time_max(Config) when is_list(Config) -> - ?line NW = 500, - ?line LW = 500, - ?line MW = 1, - ?line Tracer = start_tracer(), - ?line Low = workers(LW, low), - ?line Normal = workers(NW, normal), - ?line Max = part_time_workers(MW, max), - ?line Res = do_it(Tracer, Low, Normal, [], Max), - ?line chk_result(Res, LW, NW, 0, MW, true, false, true), - ?line workers_exit([Low, Normal, Max]), - ?line ok(Res, Config). + NW = 500, + LW = 500, + MW = 1, + Tracer = start_tracer(), + Low = workers(LW, low), + Normal = workers(NW, normal), + Max = part_time_workers(MW, max), + Res = do_it(Tracer, Low, Normal, [], Max), + chk_result(Res, LW, NW, 0, MW, true, false, true), + workers_exit([Low, Normal, Max]), + ok(Res, Config). equal_with_high(Config) when is_list(Config) -> - ?line NW = 500, - ?line LW = 500, - ?line HW = 1, - ?line Tracer = start_tracer(), - ?line Low = workers(LW, low), - ?line Normal = workers(NW, normal), - ?line High = workers(HW, high), - ?line Res = do_it(Tracer, Low, Normal, High, []), - ?line LNExe = case active_schedulers() of + NW = 500, + LW = 500, + HW = 1, + Tracer = start_tracer(), + Low = workers(LW, low), + Normal = workers(NW, normal), + High = workers(HW, high), + Res = do_it(Tracer, Low, Normal, High, []), + LNExe = case active_schedulers() of S when S =< HW -> false; _ -> true end, - ?line chk_result(Res, LW, NW, HW, 0, LNExe, true, false), - ?line workers_exit([Low, Normal, High]), - ?line ok(Res, Config). + chk_result(Res, LW, NW, HW, 0, LNExe, true, false), + workers_exit([Low, Normal, High]), + ok(Res, Config). equal_with_high_max(Config) when is_list(Config) -> - ?line NW = 500, - ?line LW = 500, - ?line HW = 1, - ?line MW = 1, - ?line Tracer = start_tracer(), - ?line Normal = workers(NW, normal), - ?line Low = workers(LW, low), - ?line High = workers(HW, high), - ?line Max = workers(MW, max), - ?line Res = do_it(Tracer, Low, Normal, High, Max), - ?line {LNExe, HExe} = case active_schedulers() of + NW = 500, + LW = 500, + HW = 1, + MW = 1, + Tracer = start_tracer(), + Normal = workers(NW, normal), + Low = workers(LW, low), + High = workers(HW, high), + Max = workers(MW, max), + Res = do_it(Tracer, Low, Normal, High, Max), + {LNExe, HExe} = case active_schedulers() of S when S =< MW -> {false, false}; S when S =< (MW + HW) -> {false, true}; _ -> {true, true} end, - ?line chk_result(Res, LW, NW, HW, MW, LNExe, HExe, true), - ?line workers_exit([Low, Normal, Max]), - ?line ok(Res, Config). + chk_result(Res, LW, NW, HW, MW, LNExe, HExe, true), + workers_exit([Low, Normal, Max]), + ok(Res, Config). bound_process(Config) when is_list(Config) -> case erlang:system_info(run_queues) == erlang:system_info(schedulers) of - true -> - ?line NStartBase = 20000, - ?line NStart = case {erlang:system_info(debug_compiled), - erlang:system_info(lock_checking)} of - {true, true} -> NStartBase div 100; - {_, true} -> NStartBase div 10; - _ -> NStartBase - end, - ?line MStart = 100, - ?line Seq = lists:seq(1, 100), - ?line Tester = self(), - ?line Procs = lists:map( - fun (N) when N rem 2 == 0 -> - spawn_opt(fun () -> - bound_loop(NStart, - NStart, - MStart, - 1), - Tester ! {self(), done} - end, - [{scheduler, 1}, link]); - (_N) -> - spawn_link(fun () -> - bound_loop(NStart, - NStart, - MStart, - false), - Tester ! {self(), done} - end) - end, - Seq), - ?line lists:foreach(fun (P) -> receive {P, done} -> ok end end, - Procs), - ?line ok; - false -> - {skipped, "Functionality not supported"} + true -> + NStartBase = 20000, + NStart = case {erlang:system_info(debug_compiled), + erlang:system_info(lock_checking)} of + {true, true} -> NStartBase div 100; + {_, true} -> NStartBase div 10; + _ -> NStartBase + end, + MStart = 100, + Seq = lists:seq(1, 100), + Tester = self(), + Procs = lists:map( + fun (N) when N rem 2 == 0 -> + spawn_opt(fun () -> + bound_loop(NStart, + NStart, + MStart, + 1), + Tester ! {self(), done} + end, + [{scheduler, 1}, link]); + (_N) -> + spawn_link(fun () -> + bound_loop(NStart, + NStart, + MStart, + false), + Tester ! {self(), done} + end) + end, + Seq), + lists:foreach(fun (P) -> receive {P, done} -> ok end end, + Procs), + ok; + false -> + {skipped, "Functionality not supported"} end. bound_loop(_, 0, 0, _) -> @@ -483,59 +479,59 @@ bound_loop(NS, N, M, Sched) -> ":L30-31t0-1c15n3p0"). -define(TOPOLOGY_F_TERM, - [{processor,[{node,[{core,[{thread,{logical,0}}, - {thread,{logical,1}}]}, - {core,[{thread,{logical,2}}, - {thread,{logical,3}}]}, - {core,[{thread,{logical,4}}, - {thread,{logical,5}}]}, - {core,[{thread,{logical,6}}, - {thread,{logical,7}}]}]}, - {node,[{core,[{thread,{logical,8}}, - {thread,{logical,9}}]}, - {core,[{thread,{logical,10}}, - {thread,{logical,11}}]}, - {core,[{thread,{logical,12}}, - {thread,{logical,13}}]}, - {core,[{thread,{logical,14}}, - {thread,{logical,15}}]}]}, - {node,[{core,[{thread,{logical,16}}, - {thread,{logical,17}}]}, - {core,[{thread,{logical,18}}, - {thread,{logical,19}}]}, - {core,[{thread,{logical,20}}, - {thread,{logical,21}}]}, - {core,[{thread,{logical,22}}, - {thread,{logical,23}}]}]}, - {node,[{core,[{thread,{logical,24}}, - {thread,{logical,25}}]}, - {core,[{thread,{logical,26}}, - {thread,{logical,27}}]}, - {core,[{thread,{logical,28}}, - {thread,{logical,29}}]}, - {core,[{thread,{logical,30}}, - {thread,{logical,31}}]}]}]}]). + [{processor,[{node,[{core,[{thread,{logical,0}}, + {thread,{logical,1}}]}, + {core,[{thread,{logical,2}}, + {thread,{logical,3}}]}, + {core,[{thread,{logical,4}}, + {thread,{logical,5}}]}, + {core,[{thread,{logical,6}}, + {thread,{logical,7}}]}]}, + {node,[{core,[{thread,{logical,8}}, + {thread,{logical,9}}]}, + {core,[{thread,{logical,10}}, + {thread,{logical,11}}]}, + {core,[{thread,{logical,12}}, + {thread,{logical,13}}]}, + {core,[{thread,{logical,14}}, + {thread,{logical,15}}]}]}, + {node,[{core,[{thread,{logical,16}}, + {thread,{logical,17}}]}, + {core,[{thread,{logical,18}}, + {thread,{logical,19}}]}, + {core,[{thread,{logical,20}}, + {thread,{logical,21}}]}, + {core,[{thread,{logical,22}}, + {thread,{logical,23}}]}]}, + {node,[{core,[{thread,{logical,24}}, + {thread,{logical,25}}]}, + {core,[{thread,{logical,26}}, + {thread,{logical,27}}]}, + {core,[{thread,{logical,28}}, + {thread,{logical,29}}]}, + {core,[{thread,{logical,30}}, + {thread,{logical,31}}]}]}]}]). bindings(Node, BindType) -> Parent = self(), Ref = make_ref(), Pid = spawn_link(Node, - fun () -> - enable_internal_state(), - Res = (catch erts_debug:get_internal_state( - {fake_scheduler_bindings, - BindType})), - Parent ! {Ref, Res} - end), + fun () -> + enable_internal_state(), + Res = (catch erts_debug:get_internal_state( + {fake_scheduler_bindings, + BindType})), + Parent ! {Ref, Res} + end), receive - {Ref, Res} -> - ?t:format("~p: ~p~n", [BindType, Res]), - unlink(Pid), - Res + {Ref, Res} -> + io:format("~p: ~p~n", [BindType, Res]), + unlink(Pid), + Res end. scheduler_bind_types(Config) when is_list(Config) -> - ?line OldRelFlags = clear_erl_rel_flags(), + OldRelFlags = clear_erl_rel_flags(), try scheduler_bind_types_test(Config, ?TOPOLOGY_A_TERM, @@ -564,267 +560,267 @@ scheduler_bind_types(Config) when is_list(Config) -> after restore_erl_rel_flags(OldRelFlags) end, - ?line ok. + ok. scheduler_bind_types_test(Config, Topology, CmdLine, TermLetter) -> - ?line ?t:format("Testing (~p): ~p~n", [TermLetter, Topology]), - ?line {ok, Node0} = start_node(Config), - ?line _ = rpc:call(Node0, erlang, system_flag, [cpu_topology, Topology]), - ?line cmp(Topology, rpc:call(Node0, erlang, system_info, [cpu_topology])), - ?line check_bind_types(Node0, TermLetter), - ?line stop_node(Node0), - ?line {ok, Node1} = start_node(Config, CmdLine), - ?line cmp(Topology, rpc:call(Node1, erlang, system_info, [cpu_topology])), - ?line check_bind_types(Node1, TermLetter), - ?line stop_node(Node1). + io:format("Testing (~p): ~p~n", [TermLetter, Topology]), + {ok, Node0} = start_node(Config), + _ = rpc:call(Node0, erlang, system_flag, [cpu_topology, Topology]), + cmp(Topology, rpc:call(Node0, erlang, system_info, [cpu_topology])), + check_bind_types(Node0, TermLetter), + stop_node(Node0), + {ok, Node1} = start_node(Config, CmdLine), + cmp(Topology, rpc:call(Node1, erlang, system_info, [cpu_topology])), + check_bind_types(Node1, TermLetter), + stop_node(Node1). check_bind_types(Node, a) -> - ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} - = bindings(Node, no_spread), - ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} - = bindings(Node, thread_spread), - ?line {0,4,8,12,2,6,10,14,1,5,9,13,3,7,11,15} - = bindings(Node, processor_spread), - ?line {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15} - = bindings(Node, spread), - ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15} - = bindings(Node, no_node_thread_spread), - ?line {0,4,2,6,1,5,3,7,8,12,10,14,9,13,11,15} - = bindings(Node, no_node_processor_spread), - ?line {0,4,2,6,8,12,10,14,1,5,3,7,9,13,11,15} - = bindings(Node, thread_no_node_processor_spread), - ?line {0,4,2,6,8,12,10,14,1,5,3,7,9,13,11,15} - = bindings(Node, default_bind), - ?line ok; + {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} + = bindings(Node, no_spread), + {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, thread_spread), + {0,4,8,12,2,6,10,14,1,5,9,13,3,7,11,15} + = bindings(Node, processor_spread), + {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15} + = bindings(Node, spread), + {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15} + = bindings(Node, no_node_thread_spread), + {0,4,2,6,1,5,3,7,8,12,10,14,9,13,11,15} + = bindings(Node, no_node_processor_spread), + {0,4,2,6,8,12,10,14,1,5,3,7,9,13,11,15} + = bindings(Node, thread_no_node_processor_spread), + {0,4,2,6,8,12,10,14,1,5,3,7,9,13,11,15} + = bindings(Node, default_bind), + ok; check_bind_types(Node, b) -> - ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} - = bindings(Node, no_spread), - ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} - = bindings(Node, thread_spread), - ?line {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15} - = bindings(Node, processor_spread), - ?line {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15} - = bindings(Node, spread), - ?line {0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15} - = bindings(Node, no_node_thread_spread), - ?line {0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15} - = bindings(Node, no_node_processor_spread), - ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} - = bindings(Node, thread_no_node_processor_spread), - ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} - = bindings(Node, default_bind), - ?line ok; + {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} + = bindings(Node, no_spread), + {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, thread_spread), + {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15} + = bindings(Node, processor_spread), + {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15} + = bindings(Node, spread), + {0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15} + = bindings(Node, no_node_thread_spread), + {0,2,1,3,4,6,5,7,8,10,9,11,12,14,13,15} + = bindings(Node, no_node_processor_spread), + {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, thread_no_node_processor_spread), + {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, default_bind), + ok; check_bind_types(Node, c) -> - ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, - 25,26,27,28,29,30,31} = bindings(Node, no_spread), - ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15, - 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread), - ?line {0,4,8,16,20,24,2,6,10,18,22,26,12,28,14,30,1,5,9,17,21,25, - 3,7,11,19,23,27,13,29,15,31} = bindings(Node, processor_spread), - ?line {0,8,16,24,4,20,12,28,2,10,18,26,6,22,14,30,1,9,17,25,5,21,13,29,3,11, - 19,27,7,23,15,31} = bindings(Node, spread), - ?line {0,2,4,6,1,3,5,7,8,10,9,11,12,14,13,15,16,18,20,22,17,19,21,23,24,26, - 25,27,28,30,29,31} = bindings(Node, no_node_thread_spread), - ?line {0,4,2,6,1,5,3,7,8,10,9,11,12,14,13,15,16,20,18,22,17,21,19,23,24,26, - 25,27,28,30,29,31} = bindings(Node, no_node_processor_spread), - ?line {0,4,2,6,8,10,12,14,16,20,18,22,24,26,28,30,1,5,3,7,9,11,13,15,17,21, - 19,23,25,27,29,31} = bindings(Node, thread_no_node_processor_spread), - ?line {0,4,2,6,8,10,12,14,16,20,18,22,24,26,28,30,1,5,3,7,9,11,13,15,17,21, - 19,23,25,27,29,31} = bindings(Node, default_bind), - ?line ok; + {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, + 25,26,27,28,29,30,31} = bindings(Node, no_spread), + {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15, + 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread), + {0,4,8,16,20,24,2,6,10,18,22,26,12,28,14,30,1,5,9,17,21,25, + 3,7,11,19,23,27,13,29,15,31} = bindings(Node, processor_spread), + {0,8,16,24,4,20,12,28,2,10,18,26,6,22,14,30,1,9,17,25,5,21,13,29,3,11, + 19,27,7,23,15,31} = bindings(Node, spread), + {0,2,4,6,1,3,5,7,8,10,9,11,12,14,13,15,16,18,20,22,17,19,21,23,24,26, + 25,27,28,30,29,31} = bindings(Node, no_node_thread_spread), + {0,4,2,6,1,5,3,7,8,10,9,11,12,14,13,15,16,20,18,22,17,21,19,23,24,26, + 25,27,28,30,29,31} = bindings(Node, no_node_processor_spread), + {0,4,2,6,8,10,12,14,16,20,18,22,24,26,28,30,1,5,3,7,9,11,13,15,17,21, + 19,23,25,27,29,31} = bindings(Node, thread_no_node_processor_spread), + {0,4,2,6,8,10,12,14,16,20,18,22,24,26,28,30,1,5,3,7,9,11,13,15,17,21, + 19,23,25,27,29,31} = bindings(Node, default_bind), + ok; check_bind_types(Node, d) -> - ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, - 25,26,27,28,29,30,31} = bindings(Node, no_spread), - ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15, - 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread), - ?line {0,8,12,16,24,28,2,10,14,18,26,30,4,20,6,22,1,9,13,17,25,29,3,11,15, - 19,27,31,5,21,7,23} = bindings(Node, processor_spread), - ?line {0,8,16,24,12,28,4,20,2,10,18,26,14,30,6,22,1,9,17,25,13,29,5,21,3,11, - 19,27,15,31,7,23} = bindings(Node, spread), - ?line {0,2,1,3,4,6,5,7,8,10,12,14,9,11,13,15,16,18,17,19,20,22,21,23,24,26, - 28,30,25,27,29,31} = bindings(Node, no_node_thread_spread), - ?line {0,2,1,3,4,6,5,7,8,12,10,14,9,13,11,15,16,18,17,19,20,22,21,23,24,28, - 26,30,25,29,27,31} = bindings(Node, no_node_processor_spread), - ?line {0,2,4,6,8,12,10,14,16,18,20,22,24,28,26,30,1,3,5,7,9,13,11,15,17,19, - 21,23,25,29,27,31} = bindings(Node, thread_no_node_processor_spread), - ?line {0,2,4,6,8,12,10,14,16,18,20,22,24,28,26,30,1,3,5,7,9,13,11,15,17,19, - 21,23,25,29,27,31} = bindings(Node, default_bind), - ?line ok; + {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, + 25,26,27,28,29,30,31} = bindings(Node, no_spread), + {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15, + 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread), + {0,8,12,16,24,28,2,10,14,18,26,30,4,20,6,22,1,9,13,17,25,29,3,11,15, + 19,27,31,5,21,7,23} = bindings(Node, processor_spread), + {0,8,16,24,12,28,4,20,2,10,18,26,14,30,6,22,1,9,17,25,13,29,5,21,3,11, + 19,27,15,31,7,23} = bindings(Node, spread), + {0,2,1,3,4,6,5,7,8,10,12,14,9,11,13,15,16,18,17,19,20,22,21,23,24,26, + 28,30,25,27,29,31} = bindings(Node, no_node_thread_spread), + {0,2,1,3,4,6,5,7,8,12,10,14,9,13,11,15,16,18,17,19,20,22,21,23,24,28, + 26,30,25,29,27,31} = bindings(Node, no_node_processor_spread), + {0,2,4,6,8,12,10,14,16,18,20,22,24,28,26,30,1,3,5,7,9,13,11,15,17,19, + 21,23,25,29,27,31} = bindings(Node, thread_no_node_processor_spread), + {0,2,4,6,8,12,10,14,16,18,20,22,24,28,26,30,1,3,5,7,9,13,11,15,17,19, + 21,23,25,29,27,31} = bindings(Node, default_bind), + ok; check_bind_types(Node, e) -> - ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} - = bindings(Node, no_spread), - ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} - = bindings(Node, thread_spread), - ?line {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15} - = bindings(Node, processor_spread), - ?line {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15} - = bindings(Node, spread), - ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15} - = bindings(Node, no_node_thread_spread), - ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15} - = bindings(Node, no_node_processor_spread), - ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} - = bindings(Node, thread_no_node_processor_spread), - ?line {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} - = bindings(Node, default_bind), - ?line ok; + {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} + = bindings(Node, no_spread), + {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, thread_spread), + {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15} + = bindings(Node, processor_spread), + {0,8,2,10,4,12,6,14,1,9,3,11,5,13,7,15} + = bindings(Node, spread), + {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15} + = bindings(Node, no_node_thread_spread), + {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15} + = bindings(Node, no_node_processor_spread), + {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, thread_no_node_processor_spread), + {0,2,4,6,8,10,12,14,1,3,5,7,9,11,13,15} + = bindings(Node, default_bind), + ok; check_bind_types(Node, f) -> - ?line {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, - 25,26,27,28,29,30,31} = bindings(Node, no_spread), - ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15, - 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread), - ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13, - 15,17,19,21,23,25,27,29,31} = bindings(Node, processor_spread), - ?line {0,8,16,24,2,10,18,26,4,12,20,28,6,14,22,30,1,9,17,25,3,11,19,27,5,13, - 21,29,7,15,23,31} = bindings(Node, spread), - ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15,16,18,20,22,17,19,21,23,24,26, - 28,30,25,27,29,31} = bindings(Node, no_node_thread_spread), - ?line {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15,16,18,20,22,17,19,21,23,24,26, - 28,30,25,27,29,31} = bindings(Node, no_node_processor_spread), - ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,17,19, - 21,23,25,27,29,31} = bindings(Node, thread_no_node_processor_spread), - ?line {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,17,19, - 21,23,25,27,29,31} = bindings(Node, default_bind), - ?line ok; + {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, + 25,26,27,28,29,30,31} = bindings(Node, no_spread), + {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15, + 17,19,21,23,25,27,29,31} = bindings(Node, thread_spread), + {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13, + 15,17,19,21,23,25,27,29,31} = bindings(Node, processor_spread), + {0,8,16,24,2,10,18,26,4,12,20,28,6,14,22,30,1,9,17,25,3,11,19,27,5,13, + 21,29,7,15,23,31} = bindings(Node, spread), + {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15,16,18,20,22,17,19,21,23,24,26, + 28,30,25,27,29,31} = bindings(Node, no_node_thread_spread), + {0,2,4,6,1,3,5,7,8,10,12,14,9,11,13,15,16,18,20,22,17,19,21,23,24,26, + 28,30,25,27,29,31} = bindings(Node, no_node_processor_spread), + {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,17,19, + 21,23,25,27,29,31} = bindings(Node, thread_no_node_processor_spread), + {0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,1,3,5,7,9,11,13,15,17,19, + 21,23,25,27,29,31} = bindings(Node, default_bind), + ok; check_bind_types(Node, _) -> - ?line bindings(Node, no_spread), - ?line bindings(Node, thread_spread), - ?line bindings(Node, processor_spread), - ?line bindings(Node, spread), - ?line bindings(Node, no_node_thread_spread), - ?line bindings(Node, no_node_processor_spread), - ?line bindings(Node, thread_no_node_processor_spread), - ?line bindings(Node, default_bind), - ?line ok. + bindings(Node, no_spread), + bindings(Node, thread_spread), + bindings(Node, processor_spread), + bindings(Node, spread), + bindings(Node, no_node_thread_spread), + bindings(Node, no_node_processor_spread), + bindings(Node, thread_no_node_processor_spread), + bindings(Node, default_bind), + ok. cpu_topology(Config) when is_list(Config) -> - ?line OldRelFlags = clear_erl_rel_flags(), + OldRelFlags = clear_erl_rel_flags(), try - ?line cpu_topology_test( - Config, - [{node,[{processor,[{core,{logical,0}}, - {core,{logical,1}}]}]}, - {processor,[{node,[{core,{logical,2}}, - {core,{logical,3}}]}]}, - {node,[{processor,[{core,{logical,4}}, - {core,{logical,5}}]}]}, - {processor,[{node,[{core,{logical,6}}, - {core,{logical,7}}]}]}], - "+sct " - "L0-1c0-1p0n0" - ":L2-3c0-1n1p1" - ":L4-5c0-1p2n2" - ":L6-7c0-1n3p3"), - ?line cpu_topology_test( - Config, - [{node,[{processor,[{core,{logical,0}}, - {core,{logical,1}}]}, - {processor,[{core,{logical,2}}, - {core,{logical,3}}]}]}, - {processor,[{node,[{core,{logical,4}}, - {core,{logical,5}}]}, - {node,[{core,{logical,6}}, - {core,{logical,7}}]}]}, - {node,[{processor,[{core,{logical,8}}, - {core,{logical,9}}]}, - {processor,[{core,{logical,10}}, - {core,{logical,11}}]}]}, - {processor,[{node,[{core,{logical,12}}, - {core,{logical,13}}]}, - {node,[{core,{logical,14}}, - {core,{logical,15}}]}]}], - "+sct " - "L0-1c0-1p0n0" - ":L2-3c0-1p1n0" - ":L4-5c0-1n1p2" - ":L6-7c2-3n2p2" - ":L8-9c0-1p3n3" - ":L10-11c0-1p4n3" - ":L12-13c0-1n4p5" - ":L14-15c2-3n5p5"), - ?line cpu_topology_test( - Config, - [{node,[{processor,[{core,{logical,0}}, - {core,{logical,1}}]}]}, - {processor,[{node,[{core,{logical,2}}, - {core,{logical,3}}]}]}, - {processor,[{node,[{core,{logical,4}}, - {core,{logical,5}}]}]}, - {node,[{processor,[{core,{logical,6}}, - {core,{logical,7}}]}]}, - {node,[{processor,[{core,{logical,8}}, - {core,{logical,9}}]}]}, - {processor,[{node,[{core,{logical,10}}, - {core,{logical,11}}]}]}], - "+sct " - "L0-1c0-1p0n0" - ":L2-3c0-1n1p1" - ":L4-5c0-1n2p2" - ":L6-7c0-1p3n3" - ":L8-9c0-1p4n4" - ":L10-11c0-1n5p5") + cpu_topology_test( + Config, + [{node,[{processor,[{core,{logical,0}}, + {core,{logical,1}}]}]}, + {processor,[{node,[{core,{logical,2}}, + {core,{logical,3}}]}]}, + {node,[{processor,[{core,{logical,4}}, + {core,{logical,5}}]}]}, + {processor,[{node,[{core,{logical,6}}, + {core,{logical,7}}]}]}], + "+sct " + "L0-1c0-1p0n0" + ":L2-3c0-1n1p1" + ":L4-5c0-1p2n2" + ":L6-7c0-1n3p3"), + cpu_topology_test( + Config, + [{node,[{processor,[{core,{logical,0}}, + {core,{logical,1}}]}, + {processor,[{core,{logical,2}}, + {core,{logical,3}}]}]}, + {processor,[{node,[{core,{logical,4}}, + {core,{logical,5}}]}, + {node,[{core,{logical,6}}, + {core,{logical,7}}]}]}, + {node,[{processor,[{core,{logical,8}}, + {core,{logical,9}}]}, + {processor,[{core,{logical,10}}, + {core,{logical,11}}]}]}, + {processor,[{node,[{core,{logical,12}}, + {core,{logical,13}}]}, + {node,[{core,{logical,14}}, + {core,{logical,15}}]}]}], + "+sct " + "L0-1c0-1p0n0" + ":L2-3c0-1p1n0" + ":L4-5c0-1n1p2" + ":L6-7c2-3n2p2" + ":L8-9c0-1p3n3" + ":L10-11c0-1p4n3" + ":L12-13c0-1n4p5" + ":L14-15c2-3n5p5"), + cpu_topology_test( + Config, + [{node,[{processor,[{core,{logical,0}}, + {core,{logical,1}}]}]}, + {processor,[{node,[{core,{logical,2}}, + {core,{logical,3}}]}]}, + {processor,[{node,[{core,{logical,4}}, + {core,{logical,5}}]}]}, + {node,[{processor,[{core,{logical,6}}, + {core,{logical,7}}]}]}, + {node,[{processor,[{core,{logical,8}}, + {core,{logical,9}}]}]}, + {processor,[{node,[{core,{logical,10}}, + {core,{logical,11}}]}]}], + "+sct " + "L0-1c0-1p0n0" + ":L2-3c0-1n1p1" + ":L4-5c0-1n2p2" + ":L6-7c0-1p3n3" + ":L8-9c0-1p4n4" + ":L10-11c0-1n5p5") after - restore_erl_rel_flags(OldRelFlags) + restore_erl_rel_flags(OldRelFlags) end, - ?line ok. + ok. cpu_topology_test(Config, Topology, Cmd) -> - ?line ?t:format("Testing~n ~p~n ~p~n", [Topology, Cmd]), - ?line cpu_topology_bif_test(Config, Topology), - ?line cpu_topology_cmdline_test(Config, Topology, Cmd), - ?line ok. + io:format("Testing~n ~p~n ~p~n", [Topology, Cmd]), + cpu_topology_bif_test(Config, Topology), + cpu_topology_cmdline_test(Config, Topology, Cmd), + ok. cpu_topology_bif_test(_Config, false) -> - ?line ok; + ok; cpu_topology_bif_test(Config, Topology) -> - ?line {ok, Node} = start_node(Config), - ?line _ = rpc:call(Node, erlang, system_flag, [cpu_topology, Topology]), - ?line cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])), - ?line stop_node(Node), - ?line ok. + {ok, Node} = start_node(Config), + _ = rpc:call(Node, erlang, system_flag, [cpu_topology, Topology]), + cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])), + stop_node(Node), + ok. cpu_topology_cmdline_test(_Config, _Topology, false) -> - ?line ok; + ok; cpu_topology_cmdline_test(Config, Topology, Cmd) -> - ?line {ok, Node} = start_node(Config, Cmd), - ?line cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])), - ?line stop_node(Node), - ?line ok. + {ok, Node} = start_node(Config, Cmd), + cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])), + stop_node(Node), + ok. update_cpu_info(Config) when is_list(Config) -> - ?line OldOnline = erlang:system_info(schedulers_online), - ?line OldAff = get_affinity_mask(), - ?line ?t:format("START - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", + OldOnline = erlang:system_info(schedulers_online), + OldAff = get_affinity_mask(), + io:format("START - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", [OldAff, OldOnline, erlang:system_info(scheduler_bindings)]), - ?line case {erlang:system_info(logical_processors_available), OldAff} of + case {erlang:system_info(logical_processors_available), OldAff} of {Avail, _} when Avail == unknown; OldAff == unknown -> %% Nothing much to test; just a smoke test case erlang:system_info(update_cpu_info) of - unchanged -> ?line ok; - changed -> ?line ok + unchanged -> ok; + changed -> ok end; _ -> try - ?line adjust_schedulers_online(), + adjust_schedulers_online(), case erlang:system_info(schedulers_online) of 1 -> %% Nothing much to test; just a smoke test - ?line ok; + ok; Onln0 -> %% unset least significant bit - ?line Aff = (OldAff band (OldAff - 1)), - ?line set_affinity_mask(Aff), - ?line Onln1 = Onln0 - 1, - ?line case adjust_schedulers_online() of + Aff = (OldAff band (OldAff - 1)), + set_affinity_mask(Aff), + Onln1 = Onln0 - 1, + case adjust_schedulers_online() of {Onln0, Onln1} -> - ?line Onln1 = erlang:system_info(schedulers_online), - ?line receive after 500 -> ok end, - ?line ?t:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", + Onln1 = erlang:system_info(schedulers_online), + receive after 500 -> ok end, + io:format("TEST - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", [Aff, Onln1, erlang:system_info(scheduler_bindings)]), - ?line unchanged = adjust_schedulers_online(), - ?line ok; + unchanged = adjust_schedulers_online(), + ok; Fail -> - ?line ?t:fail(Fail) + ct:fail(Fail) end end after @@ -832,7 +828,7 @@ update_cpu_info(Config) when is_list(Config) -> adjust_schedulers_online(), erlang:system_flag(schedulers_online, OldOnline), receive after 500 -> ok end, - ?t:format("END - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", + io:format("END - Affinity mask: ~p - Schedulers online: ~p - Scheduler bindings: ~p~n", [get_affinity_mask(), erlang:system_info(schedulers_online), erlang:system_info(scheduler_bindings)]) @@ -879,7 +875,7 @@ get_affinity_mask(_Port, _Status, Affinity) -> Affinity. get_affinity_mask() -> - case ?t:os_type() of + case os:type() of {unix, linux} -> case catch open_port({spawn, "taskset -p " ++ os:getpid()}, [exit_status]) of @@ -923,21 +919,21 @@ set_affinity_mask(Mask) -> end. sct_cmd(Config) when is_list(Config) -> - ?line Topology = ?TOPOLOGY_A_TERM, - ?line OldRelFlags = clear_erl_rel_flags(), + Topology = ?TOPOLOGY_A_TERM, + OldRelFlags = clear_erl_rel_flags(), try - ?line {ok, Node} = start_node(Config, ?TOPOLOGY_A_CMD), - ?line cmp(Topology, + {ok, Node} = start_node(Config, ?TOPOLOGY_A_CMD), + cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])), - ?line cmp(Topology, + cmp(Topology, rpc:call(Node, erlang, system_flag, [cpu_topology, Topology])), - ?line cmp(Topology, + cmp(Topology, rpc:call(Node, erlang, system_info, [cpu_topology])), - ?line stop_node(Node) + stop_node(Node) after restore_erl_rel_flags(OldRelFlags) end, - ?line ok. + ok. -define(BIND_TYPES, [{"u", unbound}, @@ -961,7 +957,7 @@ sbt_cmd(Config) when is_list(Config) -> end, case Bind of notsup -> - ?line {skipped, "Binding of schedulers not supported"}; + {skipped, "Binding of schedulers not supported"}; go_for_it -> CpuTCmd = case erlang:system_info({cpu_topology,detected}) of undefined -> @@ -984,14 +980,14 @@ sbt_cmd(Config) when is_list(Config) -> end, case CpuTCmd of false -> - ?line {skipped, "Don't know how to create cpu topology"}; + {skipped, "Don't know how to create cpu topology"}; _ -> case erlang:system_info(logical_processors) of LP when is_integer(LP) -> OldRelFlags = clear_erl_rel_flags(), try lists:foreach(fun ({ClBt, Bt}) -> - ?line sbt_test(Config, + sbt_test(Config, CpuTCmd, ClBt, Bt, @@ -1001,88 +997,325 @@ sbt_cmd(Config) when is_list(Config) -> after restore_erl_rel_flags(OldRelFlags) end, - ?line ok; + ok; _ -> - ?line {skipped, + {skipped, "Don't know the amount of logical processors"} end end end. sbt_test(Config, CpuTCmd, ClBt, Bt, LP) -> - ?line ?t:format("Testing +sbt ~s (~p)~n", [ClBt, Bt]), - ?line LPS = integer_to_list(LP), - ?line Cmd = CpuTCmd++" +sbt "++ClBt++" +S"++LPS++":"++LPS, - ?line {ok, Node} = start_node(Config, Cmd), - ?line Bt = rpc:call(Node, + io:format("Testing +sbt ~s (~p)~n", [ClBt, Bt]), + LPS = integer_to_list(LP), + Cmd = CpuTCmd++" +sbt "++ClBt++" +S"++LPS++":"++LPS, + {ok, Node} = start_node(Config, Cmd), + Bt = rpc:call(Node, erlang, system_info, [scheduler_bind_type]), - ?line SB = rpc:call(Node, + SB = rpc:call(Node, erlang, system_info, [scheduler_bindings]), - ?line ?t:format("scheduler bindings: ~p~n", [SB]), - ?line BS = case {Bt, erlang:system_info(logical_processors_available)} of + io:format("scheduler bindings: ~p~n", [SB]), + BS = case {Bt, erlang:system_info(logical_processors_available)} of {unbound, _} -> 0; {_, Int} when is_integer(Int) -> Int; {_, _} -> LP end, - ?line lists:foldl(fun (S, 0) -> - ?line unbound = S, + lists:foldl(fun (S, 0) -> + unbound = S, 0; (S, N) -> - ?line true = is_integer(S), + true = is_integer(S), N-1 end, BS, tuple_to_list(SB)), - ?line stop_node(Node), - ?line ok. + stop_node(Node), + ok. + +scheduler_threads(Config) when is_list(Config) -> + SmpSupport = erlang:system_info(smp_support), + {Sched, SchedOnln, _} = get_sstate(Config, ""), + %% Configure half the number of both the scheduler threads and + %% the scheduler threads online. + {HalfSched, HalfSchedOnln} = case SmpSupport of + false -> {1,1}; + true -> + {Sched div 2, + SchedOnln div 2} + end, + {HalfSched, HalfSchedOnln, _} = get_sstate(Config, "+SP 50:50"), + %% Use +S to configure 4x the number of scheduler threads and + %% 4x the number of scheduler threads online, but alter that + %% setting using +SP to 50% scheduler threads and 25% scheduler + %% threads online. The result should be 2x scheduler threads and + %% 1x scheduler threads online. + TwiceSched = case SmpSupport of + false -> 1; + true -> Sched*2 + end, + FourSched = integer_to_list(Sched*4), + FourSchedOnln = integer_to_list(SchedOnln*4), + CombinedCmd1 = "+S "++FourSched++":"++FourSchedOnln++" +SP50:25", + {TwiceSched, SchedOnln, _} = get_sstate(Config, CombinedCmd1), + %% Now do the same test but with the +S and +SP options in the + %% opposite order, since order shouldn't matter. + CombinedCmd2 = "+SP50:25 +S "++FourSched++":"++FourSchedOnln, + {TwiceSched, SchedOnln, _} = get_sstate(Config, CombinedCmd2), + %% Apply two +SP options to make sure the second overrides the first + TwoCmd = "+SP 25:25 +SP 100:100", + {Sched, SchedOnln, _} = get_sstate(Config, TwoCmd), + %% Configure 50% of scheduler threads online only + {Sched, HalfSchedOnln, _} = get_sstate(Config, "+SP:50"), + %% Configure 2x scheduler threads only + {TwiceSched, SchedOnln, _} = get_sstate(Config, "+SP 200"), + %% Test resetting the scheduler counts + ResetCmd = "+S "++FourSched++":"++FourSchedOnln++" +S 0:0", + {Sched, SchedOnln, _} = get_sstate(Config, ResetCmd), + %% Test negative +S settings, but only for SMP-enabled emulators + case SmpSupport of + false -> ok; + true -> + SchedMinus1 = Sched-1, + SchedOnlnMinus1 = SchedOnln-1, + {SchedMinus1, SchedOnlnMinus1, _} = get_sstate(Config, "+S -1"), + {Sched, SchedOnlnMinus1, _} = get_sstate(Config, "+S :-1"), + {SchedMinus1, SchedOnlnMinus1, _} = get_sstate(Config, "+S -1:-1") + end, + ok. + +dirty_scheduler_threads(Config) when is_list(Config) -> + SmpSupport = erlang:system_info(smp_support), + try + erlang:system_info(dirty_cpu_schedulers), + dirty_scheduler_threads_test(Config, SmpSupport) + catch + error:badarg -> + {skipped, "No dirty scheduler support"} + end. + +dirty_scheduler_threads_test(Config, SmpSupport) -> + {Sched, SchedOnln, _} = get_dsstate(Config, ""), + {HalfSched, HalfSchedOnln} = case SmpSupport of + false -> {1,1}; + true -> + {Sched div 2, + SchedOnln div 2} + end, + Cmd1 = "+SDcpu "++integer_to_list(HalfSched)++":"++ + integer_to_list(HalfSchedOnln), + {HalfSched, HalfSchedOnln, _} = get_dsstate(Config, Cmd1), + {HalfSched, HalfSchedOnln, _} = get_dsstate(Config, "+SDPcpu 50:50"), + IOSched = 20, + {_, _, IOSched} = get_dsstate(Config, "+SDio "++integer_to_list(IOSched)), + {ok, Node} = start_node(Config, ""), + [ok] = mcall(Node, [fun() -> dirty_schedulers_online_test() end]), + ok. + +dirty_schedulers_online_test() -> + dirty_schedulers_online_test(erlang:system_info(smp_support)). +dirty_schedulers_online_test(false) -> ok; +dirty_schedulers_online_test(true) -> + dirty_schedulers_online_smp_test(erlang:system_info(schedulers_online)). +dirty_schedulers_online_smp_test(SchedOnln) when SchedOnln < 4 -> ok; +dirty_schedulers_online_smp_test(SchedOnln) -> + receive after 500 -> ok end, + DirtyCPUSchedOnln = erlang:system_info(dirty_cpu_schedulers_online), + SchedOnln = DirtyCPUSchedOnln, + HalfSchedOnln = SchedOnln div 2, + SchedOnln = erlang:system_flag(schedulers_online, HalfSchedOnln), + HalfDirtyCPUSchedOnln = DirtyCPUSchedOnln div 2, + HalfDirtyCPUSchedOnln = erlang:system_flag(schedulers_online, SchedOnln), + DirtyCPUSchedOnln = erlang:system_flag(dirty_cpu_schedulers_online, + HalfDirtyCPUSchedOnln), + receive after 500 -> ok end, + HalfDirtyCPUSchedOnln = erlang:system_info(dirty_cpu_schedulers_online), + QrtrDirtyCPUSchedOnln = HalfDirtyCPUSchedOnln div 2, + SchedOnln = erlang:system_flag(schedulers_online, HalfSchedOnln), + receive after 500 -> ok end, + QrtrDirtyCPUSchedOnln = erlang:system_info(dirty_cpu_schedulers_online), + ok. + +get_sstate(Config, Cmd) -> + {ok, Node} = start_node(Config, Cmd), + [SState] = mcall(Node, [fun () -> + erlang:system_info(schedulers_state) + end]), + stop_node(Node), + SState. + +get_dsstate(Config, Cmd) -> + {ok, Node} = start_node(Config, Cmd), + [DSCPU] = mcall(Node, [fun () -> + erlang:system_info(dirty_cpu_schedulers) + end]), + [DSCPUOnln] = mcall(Node, [fun () -> + erlang:system_info(dirty_cpu_schedulers_online) + end]), + [DSIO] = mcall(Node, [fun () -> + erlang:system_info(dirty_io_schedulers) + end]), + stop_node(Node), + {DSCPU, DSCPUOnln, DSIO}. + +scheduler_suspend_basic(Config) when is_list(Config) -> + case erlang:system_info(multi_scheduling) of + disabled -> + {skip, "Nothing to test"}; + _ -> + Onln = erlang:system_info(schedulers_online), + try + scheduler_suspend_basic_test() + after + erlang:system_flag(schedulers_online, Onln) + end + end. + +scheduler_suspend_basic_test() -> + %% The receives after setting scheduler states are there + %% since the operation is not fully synchronous. For example, + %% we do not wait for dirty cpu schedulers online to complete + %% before returning from erlang:system_flag(schedulers_online, _). + + erlang:system_flag(schedulers_online, + erlang:system_info(schedulers)), + try + erlang:system_flag(dirty_cpu_schedulers_online, + erlang:system_info(dirty_cpu_schedulers)), + receive after 500 -> ok end + catch + _ : _ -> + ok + end, + + S0 = sched_state(), + io:format("~p~n", [S0]), + {{normal,NTot0,NOnln0,NAct0}, + {dirty_cpu,DCTot0,DCOnln0,DCAct0}, + {dirty_io,DITot0,DIOnln0,DIAct0}} = S0, + enabled = erlang:system_info(multi_scheduling), + + DCOne = case DCTot0 of + 0 -> 0; + _ -> 1 + end, + + blocked_normal = erlang:system_flag(multi_scheduling, block_normal), + blocked_normal = erlang:system_info(multi_scheduling), + {{normal,NTot0,NOnln0,1}, + {dirty_cpu,DCTot0,DCOnln0,DCAct0}, + {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(), + + NOnln0 = erlang:system_flag(schedulers_online, 1), + receive after 500 -> ok end, + {{normal,NTot0,1,1}, + {dirty_cpu,DCTot0,DCOne,DCOne}, + {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(), + + 1 = erlang:system_flag(schedulers_online, NOnln0), + receive after 500 -> ok end, + {{normal,NTot0,NOnln0,1}, + {dirty_cpu,DCTot0,DCOnln0,DCAct0}, + {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(), + + blocked = erlang:system_flag(multi_scheduling, block), + blocked = erlang:system_info(multi_scheduling), + receive after 500 -> ok end, + {{normal,NTot0,NOnln0,1}, + {dirty_cpu,DCTot0,DCOnln0,0}, + {dirty_io,DITot0,DIOnln0,0}} = sched_state(), + + NOnln0 = erlang:system_flag(schedulers_online, 1), + receive after 500 -> ok end, + {{normal,NTot0,1,1}, + {dirty_cpu,DCTot0,DCOne,0}, + {dirty_io,DITot0,DIOnln0,0}} = sched_state(), + + 1 = erlang:system_flag(schedulers_online, NOnln0), + receive after 500 -> ok end, + {{normal,NTot0,NOnln0,1}, + {dirty_cpu,DCTot0,DCOnln0,0}, + {dirty_io,DITot0,DIOnln0,0}} = sched_state(), + + blocked = erlang:system_flag(multi_scheduling, unblock_normal), + blocked = erlang:system_info(multi_scheduling), + {{normal,NTot0,NOnln0,1}, + {dirty_cpu,DCTot0,DCOnln0,0}, + {dirty_io,DITot0,DIOnln0,0}} = sched_state(), + + enabled = erlang:system_flag(multi_scheduling, unblock), + enabled = erlang:system_info(multi_scheduling), + receive after 500 -> ok end, + {{normal,NTot0,NOnln0,NAct0}, + {dirty_cpu,DCTot0,DCOnln0,DCAct0}, + {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(), + + NOnln0 = erlang:system_flag(schedulers_online, 1), + receive after 500 -> ok end, + {{normal,NTot0,1,1}, + {dirty_cpu,DCTot0,DCOne,DCOne}, + {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(), + + 1 = erlang:system_flag(schedulers_online, NOnln0), + receive after 500 -> ok end, + {{normal,NTot0,NOnln0,NAct0}, + {dirty_cpu,DCTot0,DCOnln0,DCAct0}, + {dirty_io,DITot0,DIOnln0,DIAct0}} = sched_state(), + + ok. + scheduler_suspend(Config) when is_list(Config) -> - ?line Dog = ?t:timetrap(?t:minutes(5)), - ?line lists:foreach(fun (S) -> scheduler_suspend_test(Config, S) end, + ct:timetrap({minutes, 5}), + lists:foreach(fun (S) -> scheduler_suspend_test(Config, S) end, [64, 32, 16, default]), - ?line ?t:timetrap_cancel(Dog), - ?line ok. + ok. scheduler_suspend_test(Config, Schedulers) -> - ?line Cmd = case Schedulers of + Cmd = case Schedulers of default -> ""; _ -> S = integer_to_list(Schedulers), "+S"++S++":"++S end, - ?line {ok, Node} = start_node(Config, Cmd), - ?line [SState] = mcall(Node, [fun () -> - erlang:system_info(schedulers_state) - end]), - ?line ?t:format("SState=~p~n", [SState]), - ?line {Sched, SchedOnln, _SchedAvail} = SState, - ?line true = is_integer(Sched), - ?line [ok] = mcall(Node, [fun () -> sst0_loop(300) end]), - ?line [ok] = mcall(Node, [fun () -> sst1_loop(300) end]), - ?line [ok] = mcall(Node, [fun () -> sst2_loop(300) end]), - ?line [ok, ok, ok, ok, ok] = mcall(Node, - [fun () -> sst0_loop(200) end, - fun () -> sst1_loop(200) end, - fun () -> sst2_loop(200) end, - fun () -> sst2_loop(200) end, - fun () -> sst3_loop(Sched, 200) end]), - ?line [SState] = mcall(Node, [fun () -> - case Sched == SchedOnln of - false -> - Sched = erlang:system_flag( - schedulers_online, - SchedOnln); - true -> - ok - end, - erlang:system_info(schedulers_state) - end]), - ?line stop_node(Node), - ?line ok. + {ok, Node} = start_node(Config, Cmd), + [SState] = mcall(Node, [fun () -> + erlang:system_info(schedulers_state) + end]), + + io:format("SState=~p~n", [SState]), + {Sched, SchedOnln, _SchedAvail} = SState, + true = is_integer(Sched), + [ok] = mcall(Node, [fun () -> sst0_loop(300) end]), + [ok] = mcall(Node, [fun () -> sst1_loop(300) end]), + [ok] = mcall(Node, [fun () -> sst2_loop(300) end]), + [ok] = mcall(Node, [fun () -> sst4_loop(300) end]), + [ok] = mcall(Node, [fun () -> sst5_loop(300) end]), + [ok, ok, ok, ok, + ok, ok, ok] = mcall(Node, + [fun () -> sst0_loop(200) end, + fun () -> sst1_loop(200) end, + fun () -> sst2_loop(200) end, + fun () -> sst2_loop(200) end, + fun () -> sst3_loop(Sched, 200) end, + fun () -> sst4_loop(200) end, + fun () -> sst5_loop(200) end]), + [SState] = mcall(Node, [fun () -> + case Sched == SchedOnln of + false -> + Sched = erlang:system_flag( + schedulers_online, + SchedOnln); + true -> + ok + end, + erlang:system_info(schedulers_state) + end]), + stop_node(Node), + ok. sst0_loop(0) -> @@ -1111,16 +1344,54 @@ sst2_loop(N) -> erlang:system_flag(multi_scheduling, unblock), sst2_loop(N-1). -sst3_loop(_S, 0) -> - ok; sst3_loop(S, N) -> + try erlang:system_info(dirty_cpu_schedulers) of + DS -> + sst3_loop_with_dirty_schedulers(S, DS, N) + catch + error:badarg -> + sst3_loop_normal_schedulers_only(S, N) + end. + +sst3_loop_normal_schedulers_only(_S, 0) -> + ok; +sst3_loop_normal_schedulers_only(S, N) -> + erlang:system_flag(schedulers_online, (S div 2)+1), + erlang:system_flag(schedulers_online, 1), erlang:system_flag(schedulers_online, (S div 2)+1), + erlang:system_flag(schedulers_online, S), erlang:system_flag(schedulers_online, 1), + erlang:system_flag(schedulers_online, S), + sst3_loop_normal_schedulers_only(S, N-1). + +sst3_loop_with_dirty_schedulers(_S, _DS, 0) -> + ok; +sst3_loop_with_dirty_schedulers(S, DS, N) -> erlang:system_flag(schedulers_online, (S div 2)+1), + erlang:system_flag(dirty_cpu_schedulers_online, (DS div 2)+1), + erlang:system_flag(schedulers_online, 1), + erlang:system_flag(schedulers_online, (S div 2)+1), + erlang:system_flag(dirty_cpu_schedulers_online, 1), erlang:system_flag(schedulers_online, S), + erlang:system_flag(dirty_cpu_schedulers_online, DS), erlang:system_flag(schedulers_online, 1), erlang:system_flag(schedulers_online, S), - sst3_loop(S, N-1). + erlang:system_flag(dirty_cpu_schedulers_online, DS), + sst3_loop_with_dirty_schedulers(S, DS, N-1). + +sst4_loop(0) -> + ok; +sst4_loop(N) -> + erlang:system_flag(multi_scheduling, block_normal), + erlang:system_flag(multi_scheduling, unblock_normal), + sst4_loop(N-1). + +sst5_loop(0) -> + ok; +sst5_loop(N) -> + erlang:system_flag(multi_scheduling, block_normal), + erlang:system_flag(multi_scheduling, unblock_normal), + sst5_loop(N-1). reader_groups(Config) when is_list(Config) -> %% White box testing. These results are correct, but other results @@ -1128,264 +1399,263 @@ reader_groups(Config) when is_list(Config) -> %% The actual tilepro64 topology CPUT0 = [{processor,[{node,[{core,{logical,0}}, - {core,{logical,1}}, - {core,{logical,2}}, - {core,{logical,8}}, - {core,{logical,9}}, - {core,{logical,10}}, - {core,{logical,11}}, - {core,{logical,16}}, - {core,{logical,17}}, - {core,{logical,18}}, - {core,{logical,19}}, - {core,{logical,24}}, - {core,{logical,25}}, - {core,{logical,27}}, - {core,{logical,29}}]}, - {node,[{core,{logical,3}}, - {core,{logical,4}}, - {core,{logical,5}}, - {core,{logical,6}}, - {core,{logical,7}}, - {core,{logical,12}}, - {core,{logical,13}}, - {core,{logical,14}}, - {core,{logical,15}}, - {core,{logical,20}}, - {core,{logical,21}}, - {core,{logical,22}}, - {core,{logical,23}}, - {core,{logical,28}}, - {core,{logical,30}}]}, - {node,[{core,{logical,31}}, - {core,{logical,36}}, - {core,{logical,37}}, - {core,{logical,38}}, - {core,{logical,44}}, - {core,{logical,45}}, - {core,{logical,46}}, - {core,{logical,47}}, - {core,{logical,51}}, - {core,{logical,52}}, - {core,{logical,53}}, - {core,{logical,54}}, - {core,{logical,55}}, - {core,{logical,60}}, - {core,{logical,61}}]}, - {node,[{core,{logical,26}}, - {core,{logical,32}}, - {core,{logical,33}}, - {core,{logical,34}}, - {core,{logical,35}}, - {core,{logical,39}}, - {core,{logical,40}}, - {core,{logical,41}}, - {core,{logical,42}}, - {core,{logical,43}}, - {core,{logical,48}}, - {core,{logical,49}}, - {core,{logical,50}}, - {core,{logical,58}}]}]}], - - ?line [{0,1},{1,1},{2,1},{3,3},{4,3},{5,3},{6,3},{7,3},{8,1},{9,1},{10,1}, - {11,1},{12,3},{13,3},{14,4},{15,4},{16,2},{17,2},{18,2},{19,2}, - {20,4},{21,4},{22,4},{23,4},{24,2},{25,2},{26,7},{27,2},{28,4}, - {29,2},{30,4},{31,5},{32,7},{33,7},{34,7},{35,7},{36,5},{37,5}, - {38,5},{39,7},{40,7},{41,8},{42,8},{43,8},{44,5},{45,5},{46,5}, - {47,6},{48,8},{49,8},{50,8},{51,6},{52,6},{53,6},{54,6},{55,6}, - {58,8},{60,6},{61,6}] - = reader_groups_map(CPUT0, 8), + {core,{logical,1}}, + {core,{logical,2}}, + {core,{logical,8}}, + {core,{logical,9}}, + {core,{logical,10}}, + {core,{logical,11}}, + {core,{logical,16}}, + {core,{logical,17}}, + {core,{logical,18}}, + {core,{logical,19}}, + {core,{logical,24}}, + {core,{logical,25}}, + {core,{logical,27}}, + {core,{logical,29}}]}, + {node,[{core,{logical,3}}, + {core,{logical,4}}, + {core,{logical,5}}, + {core,{logical,6}}, + {core,{logical,7}}, + {core,{logical,12}}, + {core,{logical,13}}, + {core,{logical,14}}, + {core,{logical,15}}, + {core,{logical,20}}, + {core,{logical,21}}, + {core,{logical,22}}, + {core,{logical,23}}, + {core,{logical,28}}, + {core,{logical,30}}]}, + {node,[{core,{logical,31}}, + {core,{logical,36}}, + {core,{logical,37}}, + {core,{logical,38}}, + {core,{logical,44}}, + {core,{logical,45}}, + {core,{logical,46}}, + {core,{logical,47}}, + {core,{logical,51}}, + {core,{logical,52}}, + {core,{logical,53}}, + {core,{logical,54}}, + {core,{logical,55}}, + {core,{logical,60}}, + {core,{logical,61}}]}, + {node,[{core,{logical,26}}, + {core,{logical,32}}, + {core,{logical,33}}, + {core,{logical,34}}, + {core,{logical,35}}, + {core,{logical,39}}, + {core,{logical,40}}, + {core,{logical,41}}, + {core,{logical,42}}, + {core,{logical,43}}, + {core,{logical,48}}, + {core,{logical,49}}, + {core,{logical,50}}, + {core,{logical,58}}]}]}], + + [{0,1},{1,1},{2,1},{3,3},{4,3},{5,3},{6,3},{7,3},{8,1},{9,1},{10,1}, + {11,1},{12,3},{13,3},{14,4},{15,4},{16,2},{17,2},{18,2},{19,2}, + {20,4},{21,4},{22,4},{23,4},{24,2},{25,2},{26,7},{27,2},{28,4}, + {29,2},{30,4},{31,5},{32,7},{33,7},{34,7},{35,7},{36,5},{37,5}, + {38,5},{39,7},{40,7},{41,8},{42,8},{43,8},{44,5},{45,5},{46,5}, + {47,6},{48,8},{49,8},{50,8},{51,6},{52,6},{53,6},{54,6},{55,6}, + {58,8},{60,6},{61,6}] + = reader_groups_map(CPUT0, 8), CPUT1 = [n([p([c([t(l(0)),t(l(1)),t(l(2)),t(l(3))]), - c([t(l(4)),t(l(5)),t(l(6)),t(l(7))]), - c([t(l(8)),t(l(9)),t(l(10)),t(l(11))]), - c([t(l(12)),t(l(13)),t(l(14)),t(l(15))])]), - p([c([t(l(16)),t(l(17)),t(l(18)),t(l(19))]), - c([t(l(20)),t(l(21)),t(l(22)),t(l(23))]), - c([t(l(24)),t(l(25)),t(l(26)),t(l(27))]), - c([t(l(28)),t(l(29)),t(l(30)),t(l(31))])])]), - n([p([c([t(l(32)),t(l(33)),t(l(34)),t(l(35))]), - c([t(l(36)),t(l(37)),t(l(38)),t(l(39))]), - c([t(l(40)),t(l(41)),t(l(42)),t(l(43))]), - c([t(l(44)),t(l(45)),t(l(46)),t(l(47))])]), - p([c([t(l(48)),t(l(49)),t(l(50)),t(l(51))]), - c([t(l(52)),t(l(53)),t(l(54)),t(l(55))]), - c([t(l(56)),t(l(57)),t(l(58)),t(l(59))]), - c([t(l(60)),t(l(61)),t(l(62)),t(l(63))])])]), - n([p([c([t(l(64)),t(l(65)),t(l(66)),t(l(67))]), - c([t(l(68)),t(l(69)),t(l(70)),t(l(71))]), - c([t(l(72)),t(l(73)),t(l(74)),t(l(75))]), - c([t(l(76)),t(l(77)),t(l(78)),t(l(79))])]), - p([c([t(l(80)),t(l(81)),t(l(82)),t(l(83))]), - c([t(l(84)),t(l(85)),t(l(86)),t(l(87))]), - c([t(l(88)),t(l(89)),t(l(90)),t(l(91))]), - c([t(l(92)),t(l(93)),t(l(94)),t(l(95))])])]), - n([p([c([t(l(96)),t(l(97)),t(l(98)),t(l(99))]), - c([t(l(100)),t(l(101)),t(l(102)),t(l(103))]), - c([t(l(104)),t(l(105)),t(l(106)),t(l(107))]), - c([t(l(108)),t(l(109)),t(l(110)),t(l(111))])]), - p([c([t(l(112)),t(l(113)),t(l(114)),t(l(115))]), - c([t(l(116)),t(l(117)),t(l(118)),t(l(119))]), - c([t(l(120)),t(l(121)),t(l(122)),t(l(123))]), - c([t(l(124)),t(l(125)),t(l(126)),t(l(127))])])])], - - ?line [{0,1},{1,1},{2,1},{3,1},{4,2},{5,2},{6,2},{7,2},{8,3},{9,3}, - {10,3},{11,3},{12,4},{13,4},{14,4},{15,4},{16,5},{17,5},{18,5}, - {19,5},{20,6},{21,6},{22,6},{23,6},{24,7},{25,7},{26,7},{27,7}, - {28,8},{29,8},{30,8},{31,8},{32,9},{33,9},{34,9},{35,9},{36,10}, - {37,10},{38,10},{39,10},{40,11},{41,11},{42,11},{43,11},{44,12}, - {45,12},{46,12},{47,12},{48,13},{49,13},{50,13},{51,13},{52,14}, - {53,14},{54,14},{55,14},{56,15},{57,15},{58,15},{59,15},{60,16}, - {61,16},{62,16},{63,16},{64,17},{65,17},{66,17},{67,17},{68,18}, - {69,18},{70,18},{71,18},{72,19},{73,19},{74,19},{75,19},{76,20}, - {77,20},{78,20},{79,20},{80,21},{81,21},{82,21},{83,21},{84,22}, - {85,22},{86,22},{87,22},{88,23},{89,23},{90,23},{91,23},{92,24}, - {93,24},{94,24},{95,24},{96,25},{97,25},{98,25},{99,25},{100,26}, - {101,26},{102,26},{103,26},{104,27},{105,27},{106,27},{107,27}, - {108,28},{109,28},{110,28},{111,28},{112,29},{113,29},{114,29}, - {115,29},{116,30},{117,30},{118,30},{119,30},{120,31},{121,31}, - {122,31},{123,31},{124,32},{125,32},{126,32},{127,32}] - = reader_groups_map(CPUT1, 128), - - ?line [{0,1},{1,1},{2,1},{3,1},{4,1},{5,1},{6,1},{7,1},{8,1},{9,1},{10,1}, - {11,1},{12,1},{13,1},{14,1},{15,1},{16,1},{17,1},{18,1},{19,1}, - {20,1},{21,1},{22,1},{23,1},{24,1},{25,1},{26,1},{27,1},{28,1}, - {29,1},{30,1},{31,1},{32,1},{33,1},{34,1},{35,1},{36,1},{37,1}, - {38,1},{39,1},{40,1},{41,1},{42,1},{43,1},{44,1},{45,1},{46,1}, - {47,1},{48,1},{49,1},{50,1},{51,1},{52,1},{53,1},{54,1},{55,1}, - {56,1},{57,1},{58,1},{59,1},{60,1},{61,1},{62,1},{63,1},{64,2}, - {65,2},{66,2},{67,2},{68,2},{69,2},{70,2},{71,2},{72,2},{73,2}, - {74,2},{75,2},{76,2},{77,2},{78,2},{79,2},{80,2},{81,2},{82,2}, - {83,2},{84,2},{85,2},{86,2},{87,2},{88,2},{89,2},{90,2},{91,2}, - {92,2},{93,2},{94,2},{95,2},{96,2},{97,2},{98,2},{99,2},{100,2}, - {101,2},{102,2},{103,2},{104,2},{105,2},{106,2},{107,2},{108,2}, - {109,2},{110,2},{111,2},{112,2},{113,2},{114,2},{115,2},{116,2}, - {117,2},{118,2},{119,2},{120,2},{121,2},{122,2},{123,2},{124,2}, - {125,2},{126,2},{127,2}] - = reader_groups_map(CPUT1, 2), - - ?line [{0,1},{1,1},{2,1},{3,1},{4,2},{5,2},{6,2},{7,2},{8,3},{9,3},{10,3}, - {11,3},{12,3},{13,3},{14,3},{15,3},{16,4},{17,4},{18,4},{19,4}, - {20,4},{21,4},{22,4},{23,4},{24,5},{25,5},{26,5},{27,5},{28,5}, - {29,5},{30,5},{31,5},{32,6},{33,6},{34,6},{35,6},{36,6},{37,6}, - {38,6},{39,6},{40,7},{41,7},{42,7},{43,7},{44,7},{45,7},{46,7}, - {47,7},{48,8},{49,8},{50,8},{51,8},{52,8},{53,8},{54,8},{55,8}, - {56,9},{57,9},{58,9},{59,9},{60,9},{61,9},{62,9},{63,9},{64,10}, - {65,10},{66,10},{67,10},{68,10},{69,10},{70,10},{71,10},{72,11}, - {73,11},{74,11},{75,11},{76,11},{77,11},{78,11},{79,11},{80,12}, - {81,12},{82,12},{83,12},{84,12},{85,12},{86,12},{87,12},{88,13}, - {89,13},{90,13},{91,13},{92,13},{93,13},{94,13},{95,13},{96,14}, - {97,14},{98,14},{99,14},{100,14},{101,14},{102,14},{103,14}, - {104,15},{105,15},{106,15},{107,15},{108,15},{109,15},{110,15}, - {111,15},{112,16},{113,16},{114,16},{115,16},{116,16},{117,16}, - {118,16},{119,16},{120,17},{121,17},{122,17},{123,17},{124,17}, - {125,17},{126,17},{127,17}] - = reader_groups_map(CPUT1, 17), - - ?line [{0,1},{1,1},{2,1},{3,1},{4,1},{5,1},{6,1},{7,1},{8,1},{9,1},{10,1}, - {11,1},{12,1},{13,1},{14,1},{15,1},{16,2},{17,2},{18,2},{19,2}, - {20,2},{21,2},{22,2},{23,2},{24,2},{25,2},{26,2},{27,2},{28,2}, - {29,2},{30,2},{31,2},{32,3},{33,3},{34,3},{35,3},{36,3},{37,3}, - {38,3},{39,3},{40,3},{41,3},{42,3},{43,3},{44,3},{45,3},{46,3}, - {47,3},{48,4},{49,4},{50,4},{51,4},{52,4},{53,4},{54,4},{55,4}, - {56,4},{57,4},{58,4},{59,4},{60,4},{61,4},{62,4},{63,4},{64,5}, - {65,5},{66,5},{67,5},{68,5},{69,5},{70,5},{71,5},{72,5},{73,5}, - {74,5},{75,5},{76,5},{77,5},{78,5},{79,5},{80,6},{81,6},{82,6}, - {83,6},{84,6},{85,6},{86,6},{87,6},{88,6},{89,6},{90,6},{91,6}, - {92,6},{93,6},{94,6},{95,6},{96,7},{97,7},{98,7},{99,7},{100,7}, - {101,7},{102,7},{103,7},{104,7},{105,7},{106,7},{107,7},{108,7}, - {109,7},{110,7},{111,7},{112,7},{113,7},{114,7},{115,7},{116,7}, - {117,7},{118,7},{119,7},{120,7},{121,7},{122,7},{123,7},{124,7}, - {125,7},{126,7},{127,7}] - = reader_groups_map(CPUT1, 7), - - ?line CPUT2 = [p([c(l(0)),c(l(1)),c(l(2)),c(l(3)),c(l(4))]), - p([t(l(5)),t(l(6)),t(l(7)),t(l(8)),t(l(9))]), - p([t(l(10))]), - p([c(l(11)),c(l(12)),c(l(13))]), - p([c(l(14)),c(l(15))])], - - ?line [{0,1},{1,1},{2,1},{3,1},{4,1}, - {5,2},{6,2},{7,2},{8,2},{9,2}, - {10,3}, - {11,4},{12,4},{13,4}, - {14,5},{15,5}] = reader_groups_map(CPUT2, 5), - - - ?line [{0,1},{1,1},{2,2},{3,2},{4,2}, - {5,3},{6,3},{7,3},{8,3},{9,3}, - {10,4}, - {11,5},{12,5},{13,5}, - {14,6},{15,6}] = reader_groups_map(CPUT2, 6), - - ?line [{0,1},{1,1},{2,2},{3,2},{4,2}, - {5,3},{6,3},{7,3},{8,3},{9,3}, - {10,4}, - {11,5},{12,6},{13,6}, - {14,7},{15,7}] = reader_groups_map(CPUT2, 7), - - ?line [{0,1},{1,1},{2,2},{3,2},{4,2}, - {5,3},{6,3},{7,3},{8,3},{9,3}, - {10,4}, - {11,5},{12,6},{13,6}, - {14,7},{15,8}] = reader_groups_map(CPUT2, 8), - - ?line [{0,1},{1,2},{2,2},{3,3},{4,3}, - {5,4},{6,4},{7,4},{8,4},{9,4}, - {10,5}, - {11,6},{12,7},{13,7}, - {14,8},{15,9}] = reader_groups_map(CPUT2, 9), - - ?line [{0,1},{1,2},{2,2},{3,3},{4,3}, - {5,4},{6,4},{7,4},{8,4},{9,4}, - {10,5}, - {11,6},{12,7},{13,8}, - {14,9},{15,10}] = reader_groups_map(CPUT2, 10), - - ?line [{0,1},{1,2},{2,3},{3,4},{4,4}, - {5,5},{6,5},{7,5},{8,5},{9,5}, - {10,6}, - {11,7},{12,8},{13,9}, - {14,10},{15,11}] = reader_groups_map(CPUT2, 11), - - ?line [{0,1},{1,2},{2,3},{3,4},{4,5}, - {5,6},{6,6},{7,6},{8,6},{9,6}, - {10,7}, - {11,8},{12,9},{13,10}, - {14,11},{15,12}] = reader_groups_map(CPUT2, 100), + c([t(l(4)),t(l(5)),t(l(6)),t(l(7))]), + c([t(l(8)),t(l(9)),t(l(10)),t(l(11))]), + c([t(l(12)),t(l(13)),t(l(14)),t(l(15))])]), + p([c([t(l(16)),t(l(17)),t(l(18)),t(l(19))]), + c([t(l(20)),t(l(21)),t(l(22)),t(l(23))]), + c([t(l(24)),t(l(25)),t(l(26)),t(l(27))]), + c([t(l(28)),t(l(29)),t(l(30)),t(l(31))])])]), + n([p([c([t(l(32)),t(l(33)),t(l(34)),t(l(35))]), + c([t(l(36)),t(l(37)),t(l(38)),t(l(39))]), + c([t(l(40)),t(l(41)),t(l(42)),t(l(43))]), + c([t(l(44)),t(l(45)),t(l(46)),t(l(47))])]), + p([c([t(l(48)),t(l(49)),t(l(50)),t(l(51))]), + c([t(l(52)),t(l(53)),t(l(54)),t(l(55))]), + c([t(l(56)),t(l(57)),t(l(58)),t(l(59))]), + c([t(l(60)),t(l(61)),t(l(62)),t(l(63))])])]), + n([p([c([t(l(64)),t(l(65)),t(l(66)),t(l(67))]), + c([t(l(68)),t(l(69)),t(l(70)),t(l(71))]), + c([t(l(72)),t(l(73)),t(l(74)),t(l(75))]), + c([t(l(76)),t(l(77)),t(l(78)),t(l(79))])]), + p([c([t(l(80)),t(l(81)),t(l(82)),t(l(83))]), + c([t(l(84)),t(l(85)),t(l(86)),t(l(87))]), + c([t(l(88)),t(l(89)),t(l(90)),t(l(91))]), + c([t(l(92)),t(l(93)),t(l(94)),t(l(95))])])]), + n([p([c([t(l(96)),t(l(97)),t(l(98)),t(l(99))]), + c([t(l(100)),t(l(101)),t(l(102)),t(l(103))]), + c([t(l(104)),t(l(105)),t(l(106)),t(l(107))]), + c([t(l(108)),t(l(109)),t(l(110)),t(l(111))])]), + p([c([t(l(112)),t(l(113)),t(l(114)),t(l(115))]), + c([t(l(116)),t(l(117)),t(l(118)),t(l(119))]), + c([t(l(120)),t(l(121)),t(l(122)),t(l(123))]), + c([t(l(124)),t(l(125)),t(l(126)),t(l(127))])])])], + + [{0,1},{1,1},{2,1},{3,1},{4,2},{5,2},{6,2},{7,2},{8,3},{9,3}, + {10,3},{11,3},{12,4},{13,4},{14,4},{15,4},{16,5},{17,5},{18,5}, + {19,5},{20,6},{21,6},{22,6},{23,6},{24,7},{25,7},{26,7},{27,7}, + {28,8},{29,8},{30,8},{31,8},{32,9},{33,9},{34,9},{35,9},{36,10}, + {37,10},{38,10},{39,10},{40,11},{41,11},{42,11},{43,11},{44,12}, + {45,12},{46,12},{47,12},{48,13},{49,13},{50,13},{51,13},{52,14}, + {53,14},{54,14},{55,14},{56,15},{57,15},{58,15},{59,15},{60,16}, + {61,16},{62,16},{63,16},{64,17},{65,17},{66,17},{67,17},{68,18}, + {69,18},{70,18},{71,18},{72,19},{73,19},{74,19},{75,19},{76,20}, + {77,20},{78,20},{79,20},{80,21},{81,21},{82,21},{83,21},{84,22}, + {85,22},{86,22},{87,22},{88,23},{89,23},{90,23},{91,23},{92,24}, + {93,24},{94,24},{95,24},{96,25},{97,25},{98,25},{99,25},{100,26}, + {101,26},{102,26},{103,26},{104,27},{105,27},{106,27},{107,27}, + {108,28},{109,28},{110,28},{111,28},{112,29},{113,29},{114,29}, + {115,29},{116,30},{117,30},{118,30},{119,30},{120,31},{121,31}, + {122,31},{123,31},{124,32},{125,32},{126,32},{127,32}] + = reader_groups_map(CPUT1, 128), + + [{0,1},{1,1},{2,1},{3,1},{4,1},{5,1},{6,1},{7,1},{8,1},{9,1},{10,1}, + {11,1},{12,1},{13,1},{14,1},{15,1},{16,1},{17,1},{18,1},{19,1}, + {20,1},{21,1},{22,1},{23,1},{24,1},{25,1},{26,1},{27,1},{28,1}, + {29,1},{30,1},{31,1},{32,1},{33,1},{34,1},{35,1},{36,1},{37,1}, + {38,1},{39,1},{40,1},{41,1},{42,1},{43,1},{44,1},{45,1},{46,1}, + {47,1},{48,1},{49,1},{50,1},{51,1},{52,1},{53,1},{54,1},{55,1}, + {56,1},{57,1},{58,1},{59,1},{60,1},{61,1},{62,1},{63,1},{64,2}, + {65,2},{66,2},{67,2},{68,2},{69,2},{70,2},{71,2},{72,2},{73,2}, + {74,2},{75,2},{76,2},{77,2},{78,2},{79,2},{80,2},{81,2},{82,2}, + {83,2},{84,2},{85,2},{86,2},{87,2},{88,2},{89,2},{90,2},{91,2}, + {92,2},{93,2},{94,2},{95,2},{96,2},{97,2},{98,2},{99,2},{100,2}, + {101,2},{102,2},{103,2},{104,2},{105,2},{106,2},{107,2},{108,2}, + {109,2},{110,2},{111,2},{112,2},{113,2},{114,2},{115,2},{116,2}, + {117,2},{118,2},{119,2},{120,2},{121,2},{122,2},{123,2},{124,2}, + {125,2},{126,2},{127,2}] + = reader_groups_map(CPUT1, 2), + + [{0,1},{1,1},{2,1},{3,1},{4,2},{5,2},{6,2},{7,2},{8,3},{9,3},{10,3}, + {11,3},{12,3},{13,3},{14,3},{15,3},{16,4},{17,4},{18,4},{19,4}, + {20,4},{21,4},{22,4},{23,4},{24,5},{25,5},{26,5},{27,5},{28,5}, + {29,5},{30,5},{31,5},{32,6},{33,6},{34,6},{35,6},{36,6},{37,6}, + {38,6},{39,6},{40,7},{41,7},{42,7},{43,7},{44,7},{45,7},{46,7}, + {47,7},{48,8},{49,8},{50,8},{51,8},{52,8},{53,8},{54,8},{55,8}, + {56,9},{57,9},{58,9},{59,9},{60,9},{61,9},{62,9},{63,9},{64,10}, + {65,10},{66,10},{67,10},{68,10},{69,10},{70,10},{71,10},{72,11}, + {73,11},{74,11},{75,11},{76,11},{77,11},{78,11},{79,11},{80,12}, + {81,12},{82,12},{83,12},{84,12},{85,12},{86,12},{87,12},{88,13}, + {89,13},{90,13},{91,13},{92,13},{93,13},{94,13},{95,13},{96,14}, + {97,14},{98,14},{99,14},{100,14},{101,14},{102,14},{103,14}, + {104,15},{105,15},{106,15},{107,15},{108,15},{109,15},{110,15}, + {111,15},{112,16},{113,16},{114,16},{115,16},{116,16},{117,16}, + {118,16},{119,16},{120,17},{121,17},{122,17},{123,17},{124,17}, + {125,17},{126,17},{127,17}] + = reader_groups_map(CPUT1, 17), + + [{0,1},{1,1},{2,1},{3,1},{4,1},{5,1},{6,1},{7,1},{8,1},{9,1},{10,1}, + {11,1},{12,1},{13,1},{14,1},{15,1},{16,2},{17,2},{18,2},{19,2}, + {20,2},{21,2},{22,2},{23,2},{24,2},{25,2},{26,2},{27,2},{28,2}, + {29,2},{30,2},{31,2},{32,3},{33,3},{34,3},{35,3},{36,3},{37,3}, + {38,3},{39,3},{40,3},{41,3},{42,3},{43,3},{44,3},{45,3},{46,3}, + {47,3},{48,4},{49,4},{50,4},{51,4},{52,4},{53,4},{54,4},{55,4}, + {56,4},{57,4},{58,4},{59,4},{60,4},{61,4},{62,4},{63,4},{64,5}, + {65,5},{66,5},{67,5},{68,5},{69,5},{70,5},{71,5},{72,5},{73,5}, + {74,5},{75,5},{76,5},{77,5},{78,5},{79,5},{80,6},{81,6},{82,6}, + {83,6},{84,6},{85,6},{86,6},{87,6},{88,6},{89,6},{90,6},{91,6}, + {92,6},{93,6},{94,6},{95,6},{96,7},{97,7},{98,7},{99,7},{100,7}, + {101,7},{102,7},{103,7},{104,7},{105,7},{106,7},{107,7},{108,7}, + {109,7},{110,7},{111,7},{112,7},{113,7},{114,7},{115,7},{116,7}, + {117,7},{118,7},{119,7},{120,7},{121,7},{122,7},{123,7},{124,7}, + {125,7},{126,7},{127,7}] + = reader_groups_map(CPUT1, 7), + + CPUT2 = [p([c(l(0)),c(l(1)),c(l(2)),c(l(3)),c(l(4))]), + p([t(l(5)),t(l(6)),t(l(7)),t(l(8)),t(l(9))]), + p([t(l(10))]), + p([c(l(11)),c(l(12)),c(l(13))]), + p([c(l(14)),c(l(15))])], + + [{0,1},{1,1},{2,1},{3,1},{4,1}, + {5,2},{6,2},{7,2},{8,2},{9,2}, + {10,3}, + {11,4},{12,4},{13,4}, + {14,5},{15,5}] = reader_groups_map(CPUT2, 5), + + + [{0,1},{1,1},{2,2},{3,2},{4,2}, + {5,3},{6,3},{7,3},{8,3},{9,3}, + {10,4}, + {11,5},{12,5},{13,5}, + {14,6},{15,6}] = reader_groups_map(CPUT2, 6), + + [{0,1},{1,1},{2,2},{3,2},{4,2}, + {5,3},{6,3},{7,3},{8,3},{9,3}, + {10,4}, + {11,5},{12,6},{13,6}, + {14,7},{15,7}] = reader_groups_map(CPUT2, 7), + + [{0,1},{1,1},{2,2},{3,2},{4,2}, + {5,3},{6,3},{7,3},{8,3},{9,3}, + {10,4}, + {11,5},{12,6},{13,6}, + {14,7},{15,8}] = reader_groups_map(CPUT2, 8), + + [{0,1},{1,2},{2,2},{3,3},{4,3}, + {5,4},{6,4},{7,4},{8,4},{9,4}, + {10,5}, + {11,6},{12,7},{13,7}, + {14,8},{15,9}] = reader_groups_map(CPUT2, 9), + + [{0,1},{1,2},{2,2},{3,3},{4,3}, + {5,4},{6,4},{7,4},{8,4},{9,4}, + {10,5}, + {11,6},{12,7},{13,8}, + {14,9},{15,10}] = reader_groups_map(CPUT2, 10), + + [{0,1},{1,2},{2,3},{3,4},{4,4}, + {5,5},{6,5},{7,5},{8,5},{9,5}, + {10,6}, + {11,7},{12,8},{13,9}, + {14,10},{15,11}] = reader_groups_map(CPUT2, 11), + + [{0,1},{1,2},{2,3},{3,4},{4,5}, + {5,6},{6,6},{7,6},{8,6},{9,6}, + {10,7}, + {11,8},{12,9},{13,10}, + {14,11},{15,12}] = reader_groups_map(CPUT2, 100), CPUT3 = [p([t(l(5)),t(l(6)),t(l(7)),t(l(8)),t(l(9))]), - p([t(l(10))]), - p([c(l(11)),c(l(12)),c(l(13))]), - p([c(l(14)),c(l(15))]), - p([c(l(0)),c(l(1)),c(l(2)),c(l(3)),c(l(4))])], + p([t(l(10))]), + p([c(l(11)),c(l(12)),c(l(13))]), + p([c(l(14)),c(l(15))]), + p([c(l(0)),c(l(1)),c(l(2)),c(l(3)),c(l(4))])], - ?line [{0,5},{1,5},{2,6},{3,6},{4,6}, - {5,1},{6,1},{7,1},{8,1},{9,1}, - {10,2},{11,3},{12,3},{13,3}, - {14,4},{15,4}] = reader_groups_map(CPUT3, 6), + [{0,5},{1,5},{2,6},{3,6},{4,6}, + {5,1},{6,1},{7,1},{8,1},{9,1}, + {10,2},{11,3},{12,3},{13,3}, + {14,4},{15,4}] = reader_groups_map(CPUT3, 6), CPUT4 = [p([t(l(0)),t(l(1)),t(l(2)),t(l(3)),t(l(4))]), - p([t(l(5))]), - p([c(l(6)),c(l(7)),c(l(8))]), - p([c(l(9)),c(l(10))]), - p([c(l(11)),c(l(12)),c(l(13)),c(l(14)),c(l(15))])], - - ?line [{0,1},{1,1},{2,1},{3,1},{4,1}, - {5,2}, - {6,3},{7,3},{8,3}, - {9,4},{10,4}, - {11,5},{12,5},{13,6},{14,6},{15,6}] = reader_groups_map(CPUT4, 6), - - ?line [{0,1},{1,1},{2,1},{3,1},{4,1}, - {5,2}, - {6,3},{7,4},{8,4}, - {9,5},{10,5}, - {11,6},{12,6},{13,7},{14,7},{15,7}] = reader_groups_map(CPUT4, 7), - - ?line [{0,1},{65535,2}] = reader_groups_map([c(l(0)),c(l(65535))], 10), - - ?line ok. + p([t(l(5))]), + p([c(l(6)),c(l(7)),c(l(8))]), + p([c(l(9)),c(l(10))]), + p([c(l(11)),c(l(12)),c(l(13)),c(l(14)),c(l(15))])], + + [{0,1},{1,1},{2,1},{3,1},{4,1}, + {5,2}, + {6,3},{7,3},{8,3}, + {9,4},{10,4}, + {11,5},{12,5},{13,6},{14,6},{15,6}] = reader_groups_map(CPUT4, 6), + + [{0,1},{1,1},{2,1},{3,1},{4,1}, + {5,2}, + {6,3},{7,4},{8,4}, + {9,5},{10,5}, + {11,6},{12,6},{13,7},{14,7},{15,7}] = reader_groups_map(CPUT4, 7), + + [{0,1},{65535,2}] = reader_groups_map([c(l(0)),c(l(65535))], 10), + ok. reader_groups_map(CPUT, Groups) -> @@ -1400,6 +1670,34 @@ reader_groups_map(CPUT, Groups) -> %% Utils %% +sched_state() -> + sched_state(erlang:system_info(all_schedulers_state), + undefined, + {dirty_cpu,0,0,0}, + {dirty_io,0,0,0}). + + +sched_state([], N, DC, DI) -> + try + chk_basic(N), + chk_basic(DC), + chk_basic(DI), + {N, DC, DI} + catch + _ : _ -> + ct:fail({inconsisten_scheduler_state, {N, DC, DI}}) + end; +sched_state([{normal, _, _, _} = S | Rest], _S, DC, DI) -> + sched_state(Rest, S, DC, DI); +sched_state([{dirty_cpu, _, _, _} = DC | Rest], S, _DC, DI) -> + sched_state(Rest, S, DC, DI); +sched_state([{dirty_io, _, _, _} = DI | Rest], S, DC, _DI) -> + sched_state(Rest, S, DC, DI). + +chk_basic({_Type, Tot, Onln, Act}) -> + true = Tot >= Onln, + true = Onln >= Act. + l(Id) -> {logical, Id}. @@ -1418,24 +1716,24 @@ n(X) -> mcall(Node, Funs) -> Parent = self(), Refs = lists:map(fun (Fun) -> - Ref = make_ref(), - spawn_link(Node, - fun () -> - Res = Fun(), - unlink(Parent), - Parent ! {Ref, Res} - end), - Ref - end, Funs), + Ref = make_ref(), + spawn_link(Node, + fun () -> + Res = Fun(), + unlink(Parent), + Parent ! {Ref, Res} + end), + Ref + end, Funs), lists:map(fun (Ref) -> - receive - {Ref, Res} -> - Res - end - end, Refs). + receive + {Ref, Res} -> + Res + end + end, Refs). erl_rel_flag_var() -> - "ERL_"++erlang:system_info(otp_release)++"_FLAGS". + "ERL_OTP"++erlang:system_info(otp_release)++"_FLAGS". clear_erl_rel_flags() -> EnvVar = erl_rel_flag_var(), @@ -1456,101 +1754,101 @@ restore_erl_rel_flags(OldValue) -> ok(too_slow, _Config) -> {comment, "Too slow system to do any actual testing..."}; ok(_Res, Config) -> - ?config(ok_res, Config). + proplists:get_value(ok_res, Config). chk_result(too_slow, - _LWorkers, - _NWorkers, - _HWorkers, - _MWorkers, - _LNShouldWork, - _HShouldWork, - _MShouldWork) -> - ?line ok; + _LWorkers, + _NWorkers, + _HWorkers, + _MWorkers, + _LNShouldWork, + _HShouldWork, + _MShouldWork) -> + ok; chk_result([{low, L, Lmin, _Lmax}, - {normal, N, Nmin, _Nmax}, - {high, H, Hmin, _Hmax}, - {max, M, Mmin, _Mmax}] = Res, - LWorkers, - NWorkers, - HWorkers, - MWorkers, - LNShouldWork, - HShouldWork, - MShouldWork) -> - ?line ?t:format("~p~n", [Res]), - ?line Relax = relax_limits(), + {normal, N, Nmin, _Nmax}, + {high, H, Hmin, _Hmax}, + {max, M, Mmin, _Mmax}] = Res, + LWorkers, + NWorkers, + HWorkers, + MWorkers, + LNShouldWork, + HShouldWork, + MShouldWork) -> + io:format("~p~n", [Res]), + Relax = relax_limits(), case {L, N} of - {0, 0} -> - ?line false = LNShouldWork; - _ -> - ?line {LminRatioLim, - NminRatioLim, - LNRatioLimMin, - LNRatioLimMax} = case Relax of - false -> {0.5, 0.5, 0.05, 0.25}; - true -> {0.05, 0.05, 0.01, 0.4} - end, - ?line Lavg = L/LWorkers, - ?line Navg = N/NWorkers, - ?line Ratio = Lavg/Navg, - ?line LminRatio = Lmin/Lavg, - ?line NminRatio = Nmin/Navg, - ?line ?t:format("low min ratio=~p~n" - "normal min ratio=~p~n" - "low avg=~p~n" - "normal avg=~p~n" - "low/normal ratio=~p~n", - [LminRatio, NminRatio, Lavg, Navg, Ratio]), - erlang:display({low_min_ratio, LminRatio}), - erlang:display({normal_min_ratio, NminRatio}), - erlang:display({low_avg, Lavg}), - erlang:display({normal_avg, Navg}), - erlang:display({low_normal_ratio, Ratio}), - ?line chk_lim(LminRatioLim, LminRatio, 1.0, low_min_ratio), - ?line chk_lim(NminRatioLim, NminRatio, 1.0, normal_min_ratio), - ?line chk_lim(LNRatioLimMin, Ratio, LNRatioLimMax, low_normal_ratio), - ?line true = LNShouldWork, - ?line ok + {0, 0} -> + false = LNShouldWork; + _ -> + {LminRatioLim, + NminRatioLim, + LNRatioLimMin, + LNRatioLimMax} = case Relax of + false -> {0.5, 0.5, 0.05, 0.25}; + true -> {0.05, 0.05, 0.01, 0.4} + end, + Lavg = L/LWorkers, + Navg = N/NWorkers, + Ratio = Lavg/Navg, + LminRatio = Lmin/Lavg, + NminRatio = Nmin/Navg, + io:format("low min ratio=~p~n" + "normal min ratio=~p~n" + "low avg=~p~n" + "normal avg=~p~n" + "low/normal ratio=~p~n", + [LminRatio, NminRatio, Lavg, Navg, Ratio]), + erlang:display({low_min_ratio, LminRatio}), + erlang:display({normal_min_ratio, NminRatio}), + erlang:display({low_avg, Lavg}), + erlang:display({normal_avg, Navg}), + erlang:display({low_normal_ratio, Ratio}), + chk_lim(LminRatioLim, LminRatio, 1.0, low_min_ratio), + chk_lim(NminRatioLim, NminRatio, 1.0, normal_min_ratio), + chk_lim(LNRatioLimMin, Ratio, LNRatioLimMax, low_normal_ratio), + true = LNShouldWork, + ok end, case H of - 0 -> - ?line false = HShouldWork; - _ -> - ?line HminRatioLim = case Relax of - false -> 0.5; - true -> 0.1 - end, - ?line Havg = H/HWorkers, - ?line HminRatio = Hmin/Havg, - erlang:display({high_min_ratio, HminRatio}), - ?line chk_lim(HminRatioLim, HminRatio, 1.0, high_min_ratio), - ?line true = HShouldWork, - ?line ok + 0 -> + false = HShouldWork; + _ -> + HminRatioLim = case Relax of + false -> 0.5; + true -> 0.1 + end, + Havg = H/HWorkers, + HminRatio = Hmin/Havg, + erlang:display({high_min_ratio, HminRatio}), + chk_lim(HminRatioLim, HminRatio, 1.0, high_min_ratio), + true = HShouldWork, + ok end, case M of - 0 -> - ?line false = MShouldWork; - _ -> - ?line MminRatioLim = case Relax of - false -> 0.5; - true -> 0.1 - end, - ?line Mavg = M/MWorkers, - ?line MminRatio = Mmin/Mavg, - erlang:display({max_min_ratio, MminRatio}), - ?line chk_lim(MminRatioLim, MminRatio, 1.0, max_min_ratio), - ?line true = MShouldWork, - ?line ok + 0 -> + false = MShouldWork; + _ -> + MminRatioLim = case Relax of + false -> 0.5; + true -> 0.1 + end, + Mavg = M/MWorkers, + MminRatio = Mmin/Mavg, + erlang:display({max_min_ratio, MminRatio}), + chk_lim(MminRatioLim, MminRatio, 1.0, max_min_ratio), + true = MShouldWork, + ok end, - ?line ok. + ok. chk_lim(Min, V, Max, _What) when Min =< V, V =< Max -> ok; chk_lim(_Min, V, _Max, What) -> - ?t:fail({bad, What, V}). + ct:fail({bad, What, V}). snd(_Msg, []) -> []; @@ -1561,7 +1859,7 @@ snd(Msg, [P|Ps]) -> relax_limits() -> case strange_system_scale() of Scale when Scale > 1 -> - ?t:format("Relaxing limits~n", []), + io:format("Relaxing limits~n", []), true; _ -> false @@ -1680,14 +1978,14 @@ do_it(Tracer, Low, Normal, High, Max) -> do_it(Tracer, Low, Normal, High, Max, RedsPerSchedLimit) -> OldPrio = process_flag(priority, max), go_work(Low, Normal, High, Max), - StartWait = now(), + StartWait = erlang:monotonic_time(milli_seconds), %% Give the emulator a chance to balance the load... wait_balance(5), - EndWait = now(), - BalanceWait = timer:now_diff(EndWait,StartWait) div 1000, + EndWait = erlang:monotonic_time(milli_seconds), + BalanceWait = EndWait-StartWait, erlang:display({balance_wait, BalanceWait}), - Timeout = ?DEFAULT_TIMEOUT - ?t:minutes(4) - BalanceWait, - Res = case Timeout < ?MIN_SCHEDULER_TEST_TIMEOUT of + Timeout = (15 - 4)*60*1000 - BalanceWait, + Res = case Timeout < 60*1000 of true -> stop_work(Low, Normal, High, Max), too_slow; @@ -1757,55 +2055,55 @@ part_time_workers(N, Prio) -> tracer(Low, Normal, High, Max) -> receive - {tracees, Prio, Tracees} -> - save_tracees(Prio, Tracees), - case Prio of - low -> tracer(Tracees++Low, Normal, High, Max); - normal -> tracer(Low, Tracees++Normal, High, Max); - high -> tracer(Low, Normal, Tracees++High, Max); - max -> tracer(Low, Normal, High, Tracees++Max) - end; - {get_result, Ref, Who} -> - Delivered = erlang:trace_delivered(all), - receive - {trace_delivered, all, Delivered} -> - ok - end, - {Lc, Nc, Hc, Mc} = read_trace(), - GetMinMax - = fun (Prio, Procs) -> - LargeNum = 1 bsl 64, - case lists:foldl(fun (P, {Mn, Mx} = MnMx) -> - {Prio, C} = get(P), - case C < Mn of - true -> - case C > Mx of - true -> - {C, C}; - false -> - {C, Mx} - end; - false -> - case C > Mx of - true -> {Mn, C}; - false -> MnMx - end - end - end, - {LargeNum, 0}, - Procs) of - {LargeNum, 0} -> {0, 0}; - Res -> Res - end - end, - {Lmin, Lmax} = GetMinMax(low, Low), - {Nmin, Nmax} = GetMinMax(normal, Normal), - {Hmin, Hmax} = GetMinMax(high, High), - {Mmin, Mmax} = GetMinMax(max, Max), - Who ! {trace_result, Ref, [{low, Lc, Lmin, Lmax}, - {normal, Nc, Nmin, Nmax}, - {high, Hc, Hmin, Hmax}, - {max, Mc, Mmin, Mmax}]} + {tracees, Prio, Tracees} -> + save_tracees(Prio, Tracees), + case Prio of + low -> tracer(Tracees++Low, Normal, High, Max); + normal -> tracer(Low, Tracees++Normal, High, Max); + high -> tracer(Low, Normal, Tracees++High, Max); + max -> tracer(Low, Normal, High, Tracees++Max) + end; + {get_result, Ref, Who} -> + Delivered = erlang:trace_delivered(all), + receive + {trace_delivered, all, Delivered} -> + ok + end, + {Lc, Nc, Hc, Mc} = read_trace(), + GetMinMax + = fun (Prio, Procs) -> + LargeNum = 1 bsl 64, + case lists:foldl(fun (P, {Mn, Mx} = MnMx) -> + {Prio, C} = get(P), + case C < Mn of + true -> + case C > Mx of + true -> + {C, C}; + false -> + {C, Mx} + end; + false -> + case C > Mx of + true -> {Mn, C}; + false -> MnMx + end + end + end, + {LargeNum, 0}, + Procs) of + {LargeNum, 0} -> {0, 0}; + Res -> Res + end + end, + {Lmin, Lmax} = GetMinMax(low, Low), + {Nmin, Nmax} = GetMinMax(normal, Normal), + {Hmin, Hmax} = GetMinMax(high, High), + {Mmin, Mmax} = GetMinMax(max, Max), + Who ! {trace_result, Ref, [{low, Lc, Lmin, Lmax}, + {normal, Nc, Nmin, Nmax}, + {high, Hc, Hmin, Hmax}, + {max, Mc, Mmin, Mmax}]} end. read_trace() -> @@ -1878,21 +2176,18 @@ start_node(Config) -> start_node(Config, ""). start_node(Config, Args) when is_list(Config) -> - ?line Pa = filename:dirname(code:which(?MODULE)), - ?line {A, B, C} = now(), - ?line Name = list_to_atom(atom_to_list(?MODULE) - ++ "-" - ++ atom_to_list(?config(testcase, Config)) - ++ "-" - ++ integer_to_list(A) - ++ "-" - ++ integer_to_list(B) - ++ "-" - ++ integer_to_list(C)), - ?line ?t:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]). + Pa = filename:dirname(code:which(?MODULE)), + Name = list_to_atom(atom_to_list(?MODULE) + ++ "-" + ++ atom_to_list(proplists:get_value(testcase, Config)) + ++ "-" + ++ integer_to_list(erlang:system_time(seconds)) + ++ "-" + ++ integer_to_list(erlang:unique_integer([positive]))), + test_server:start_node(Name, slave, [{args, "-pa "++Pa++" "++Args}]). stop_node(Node) -> - ?t:stop_node(Node). + test_server:stop_node(Node). enable_internal_state() -> @@ -1904,7 +2199,7 @@ enable_internal_state() -> cmp(X, X) -> ok; cmp(X, Y) -> - ?t:format("cmp failed:~n X=~p~n Y=~p~n", [X,Y]), + io:format("cmp failed:~n X=~p~n Y=~p~n", [X,Y]), cmp_aux(X, Y). @@ -1916,7 +2211,7 @@ cmp_aux(T0, T1) when is_tuple(T0), is_tuple(T1), size(T0) == size(T1) -> cmp_aux(X, X) -> ok; cmp_aux(F0, F1) -> - ?t:fail({no_match, F0, F1}). + ct:fail({no_match, F0, F1}). cmp_tuple(_T0, _T1, N, Sz) when N > Sz -> ok; |