diff options
-rw-r--r-- | erts/emulator/test/dirty_nif_SUITE.erl | 62 | ||||
-rw-r--r-- | erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c | 16 |
2 files changed, 61 insertions, 17 deletions
diff --git a/erts/emulator/test/dirty_nif_SUITE.erl b/erts/emulator/test/dirty_nif_SUITE.erl index 71fbf17a2e..c3afbc0803 100644 --- a/erts/emulator/test/dirty_nif_SUITE.erl +++ b/erts/emulator/test/dirty_nif_SUITE.erl @@ -31,7 +31,8 @@ init_per_testcase/2, end_per_testcase/2, dirty_nif/1, dirty_nif_send/1, dirty_nif_exception/1, call_dirty_nif_exception/1, - dirty_scheduler_exit/1, dirty_call_while_terminated/1]). + dirty_scheduler_exit/1, dirty_call_while_terminated/1, + dirty_heap_access/1]). -define(nif_stub,nif_stub_error(?LINE)). @@ -42,7 +43,8 @@ all() -> dirty_nif_send, dirty_nif_exception, dirty_scheduler_exit, - dirty_call_while_terminated]. + dirty_call_while_terminated, + dirty_heap_access]. init_per_suite(Config) -> try erlang:system_info(dirty_cpu_schedulers) of @@ -133,15 +135,6 @@ nif_raise_exceptions(NifFunc) -> end, ok, ExcTerms). dirty_scheduler_exit(Config) when is_list(Config) -> - try - erlang:system_info(dirty_cpu_schedulers), - dirty_scheduler_exit_test(Config) - catch - error:badarg -> - {skipped, "No dirty scheduler support"} - end. - -dirty_scheduler_exit_test(Config) -> {ok, Node} = start_node(Config, "+SDio 1"), Path = proplists:get_value(data_dir, Config), NifLib = filename:join(Path, atom_to_list(?MODULE)), @@ -164,10 +157,7 @@ test_dse(0,Pids) -> timer:sleep(100), kill_dse(Pids,[]); test_dse(N,Pids) -> - Pid = spawn_link(fun () -> - F = fun dirty_sleeper/0, - F() - end), + Pid = spawn_link(fun dirty_sleeper/0), test_dse(N-1,[Pid|Pids]). kill_dse([],Killed) -> @@ -238,6 +228,47 @@ dirty_call_while_terminated(Config) when is_list(Config) -> process_flag(trap_exit, OT), ok. +dirty_heap_access(Config) when is_list(Config) -> + {ok, Node} = start_node(Config), + Me = self(), + RGL = rpc:call(Node,erlang,whereis,[init]), + Ref = rpc:call(Node,erlang,make_ref,[]), + Dirty = spawn_link(fun () -> + Res = dirty_heap_access_nif(Ref), + garbage_collect(), + Me ! {self(), Res}, + receive after infinity -> ok end + end), + {N, R} = access_dirty_heap(Dirty, RGL, 0, 0), + receive + {Pid, Res} -> + 1000 = length(Res), + lists:foreach(fun (X) -> Ref = X end, Res) + end, + unlink(Dirty), + exit(Dirty, kill), + stop_node(Node), + {comment, integer_to_list(N) ++ " GL change loops; " + ++ integer_to_list(R) ++ " while running dirty"}. + +access_dirty_heap(Dirty, RGL, N, R) -> + case process_info(Dirty, status) of + {status, waiting} -> + {N, R}; + {status, Status} -> + {group_leader, GL} = process_info(Dirty, group_leader), + true = group_leader(RGL, Dirty), + {group_leader, RGL} = process_info(Dirty, group_leader), + true = group_leader(GL, Dirty), + {group_leader, GL} = process_info(Dirty, group_leader), + access_dirty_heap(Dirty, RGL, N+1, case Status of + running -> + R+1; + _ -> + R + end) + end. + %% %% Internal... %% @@ -290,6 +321,7 @@ call_dirty_nif_exception(_) -> ?nif_stub. call_dirty_nif_zero_args() -> ?nif_stub. dirty_call_while_terminated_nif(_) -> ?nif_stub. dirty_sleeper() -> ?nif_stub. +dirty_heap_access_nif(_) -> ?nif_stub. nif_stub_error(Line) -> exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c index 8de60d1020..2013c88167 100644 --- a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c +++ b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c @@ -45,7 +45,6 @@ static ERL_NIF_TERM dirty_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ int n; char s[10]; ErlNifBinary b; - ERL_NIF_TERM result; if (have_dirty_schedulers()) { assert(enif_is_on_dirty_scheduler(env)); } @@ -197,6 +196,18 @@ static ERL_NIF_TERM dirty_call_while_terminated_nif(ErlNifEnv* env, int argc, co return enif_make_atom(env, "ok"); } +static ERL_NIF_TERM dirty_heap_access_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ERL_NIF_TERM res = enif_make_list(env, 0); + int i; + assert(enif_is_on_dirty_scheduler(env)); + for (i = 0; i < 1000; i++) + res = enif_make_list_cell(env, enif_make_copy(env, argv[0]), res); + + return res; +} + + static ErlNifFunc nif_funcs[] = { {"lib_loaded", 0, lib_loaded}, @@ -205,7 +216,8 @@ static ErlNifFunc nif_funcs[] = {"call_dirty_nif_exception", 1, call_dirty_nif_exception, ERL_NIF_DIRTY_JOB_IO_BOUND}, {"call_dirty_nif_zero_args", 0, call_dirty_nif_zero_args, ERL_NIF_DIRTY_JOB_CPU_BOUND}, {"dirty_sleeper", 0, dirty_sleeper, ERL_NIF_DIRTY_JOB_IO_BOUND}, - {"dirty_call_while_terminated_nif", 1, dirty_call_while_terminated_nif, ERL_NIF_DIRTY_JOB_CPU_BOUND} + {"dirty_call_while_terminated_nif", 1, dirty_call_while_terminated_nif, ERL_NIF_DIRTY_JOB_CPU_BOUND}, + {"dirty_heap_access_nif", 1, dirty_heap_access_nif, ERL_NIF_DIRTY_JOB_CPU_BOUND} }; ERL_NIF_INIT(dirty_nif_SUITE,nif_funcs,load,NULL,NULL,NULL) |