aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/test/dirty_nif_SUITE.erl62
-rw-r--r--erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c16
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)