aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test
diff options
context:
space:
mode:
Diffstat (limited to 'erts/emulator/test')
-rw-r--r--erts/emulator/test/alloc_SUITE.erl250
-rw-r--r--erts/emulator/test/alloc_SUITE_data/Makefile.src3
-rw-r--r--erts/emulator/test/alloc_SUITE_data/allocator_test.h20
-rw-r--r--erts/emulator/test/alloc_SUITE_data/basic.c3
-rw-r--r--erts/emulator/test/alloc_SUITE_data/basic.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_index.c2
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_index.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_mask.c4
-rw-r--r--erts/emulator/test/alloc_SUITE_data/bucket_mask.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/coalesce.c3
-rw-r--r--erts/emulator/test/alloc_SUITE_data/coalesce.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/cpool.c9
-rw-r--r--erts/emulator/test/alloc_SUITE_data/cpool.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/migration.c343
-rw-r--r--erts/emulator/test/alloc_SUITE_data/migration.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c3
-rw-r--r--erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/rbtree.c14
-rw-r--r--erts/emulator/test/alloc_SUITE_data/rbtree.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/realloc_copy.c2
-rw-r--r--erts/emulator/test/alloc_SUITE_data/realloc_copy.erl10
-rw-r--r--erts/emulator/test/alloc_SUITE_data/testcase_driver.c255
-rw-r--r--erts/emulator/test/alloc_SUITE_data/testcase_driver.h15
-rw-r--r--erts/emulator/test/alloc_SUITE_data/threads.c6
-rw-r--r--erts/emulator/test/alloc_SUITE_data/threads.erl10
-rw-r--r--erts/emulator/test/distribution_SUITE_data/run.erl47
-rw-r--r--erts/emulator/test/map_SUITE.erl206
-rw-r--r--erts/emulator/test/nif_SUITE_data/nif_mod.c2
-rw-r--r--erts/emulator/test/process_SUITE.erl10
29 files changed, 1085 insertions, 212 deletions
diff --git a/erts/emulator/test/alloc_SUITE.erl b/erts/emulator/test/alloc_SUITE.erl
index 7c7ddde5d4..aa6a1fbcdc 100644
--- a/erts/emulator/test/alloc_SUITE.erl
+++ b/erts/emulator/test/alloc_SUITE.erl
@@ -31,7 +31,8 @@
rbtree/1,
mseg_clear_cache/1,
erts_mmap/1,
- cpool/1]).
+ cpool/1,
+ migration/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
@@ -43,7 +44,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, coalesce, threads, realloc_copy, bucket_index,
- bucket_mask, rbtree, mseg_clear_cache, erts_mmap, cpool].
+ bucket_mask, rbtree, mseg_clear_cache, erts_mmap, cpool, migration].
groups() ->
[].
@@ -64,7 +65,7 @@ end_per_group(_GroupName, Config) ->
init_per_testcase(Case, Config) when is_list(Config) ->
Dog = ?t:timetrap(?t:seconds(?DEFAULT_TIMETRAP_SECS)),
- [{watchdog, Dog},{testcase, Case}|Config].
+ [{watchdog, Dog}, {testcase, Case}, {debug,false} | Config].
end_per_testcase(_Case, Config) when is_list(Config) ->
Dog = ?config(watchdog, Config),
@@ -112,6 +113,14 @@ cpool(suite) -> [];
cpool(doc) -> [];
cpool(Cfg) -> ?line drv_case(Cfg).
+migration(Cfg) ->
+ case erlang:system_info(smp_support) of
+ true ->
+ drv_case(Cfg, concurrent, "+MZe true");
+ false ->
+ {skipped, "No smp"}
+ end.
+
erts_mmap(Config) when is_list(Config) ->
case {?t:os_type(), is_halfword_vm()} of
{{unix, _}, false} ->
@@ -176,18 +185,17 @@ erts_mmap_do(Config, SCO, SCRPM, SCRFSD) ->
%% %%
drv_case(Config) ->
- drv_case(Config, "").
+ drv_case(Config, one_shot, "").
-drv_case(Config, Command) when is_list(Config),
- is_list(Command) ->
+drv_case(Config, Mode, NodeOpts) when is_list(Config) ->
case ?t:os_type() of
{Family, _} when Family == unix; Family == win32 ->
- ?line {ok, Node} = start_node(Config),
+ ?line {ok, Node} = start_node(Config, NodeOpts),
?line Self = self(),
?line Ref = make_ref(),
?line spawn_link(Node,
fun () ->
- Res = run_drv_case(Config, Command),
+ Res = run_drv_case(Config, Mode),
Self ! {Ref, Res}
end),
?line Result = receive {Ref, Rslt} -> Rslt end,
@@ -199,49 +207,172 @@ drv_case(Config, Command) when is_list(Config),
| io_lib:format("~p",[SkipOs])])}
end.
-run_drv_case(Config, Command) ->
- ?line DataDir = ?config(data_dir,Config),
- ?line CaseName = ?config(testcase,Config),
- case erl_ddll:load_driver(DataDir, CaseName) of
- ok -> ok;
- {error, Error} ->
- io:format("~s\n", [erl_ddll:format_error(Error)]),
- ?line ?t:fail()
+run_drv_case(Config, Mode) ->
+ DataDir = ?config(data_dir,Config),
+ CaseName = ?config(testcase,Config),
+ File = filename:join(DataDir, CaseName),
+ {ok,CaseName,Bin} = compile:file(File, [binary,return_errors]),
+ {module,CaseName} = erlang:load_module(CaseName,Bin),
+ print_stats(CaseName),
+ ok = CaseName:init(File),
+
+ SlaveState = slave_init(CaseName),
+ case Mode of
+ one_shot ->
+ Result = one_shot(CaseName);
+
+ concurrent ->
+ Result = concurrent(CaseName)
end,
- ?line Port = open_port({spawn, atom_to_list(CaseName)}, []),
- ?line true = is_port(Port),
- ?line Port ! {self(), {command, Command}},
- ?line Result = receive_drv_result(Port, CaseName),
- ?line Port ! {self(), close},
- ?line receive
- {Port, closed} ->
- ok
- end,
- ?line ok = erl_ddll:unload_driver(CaseName),
- ?line Result.
-
-receive_drv_result(Port, CaseName) ->
- ?line receive
- {print, Port, CaseName, Str} ->
- ?line ?t:format("~s", [Str]),
- ?line receive_drv_result(Port, CaseName);
- {'EXIT', Port, Error} ->
- ?line ?t:fail(Error);
- {'EXIT', error, Error} ->
- ?line ?t:fail(Error);
- {failed, Port, CaseName, Comment} ->
- ?line ?t:fail(Comment);
- {skipped, Port, CaseName, Comment} ->
- ?line {skipped, Comment};
- {succeeded, Port, CaseName, ""} ->
- ?line succeeded;
- {succeeded, Port, CaseName, Comment} ->
- ?line {comment, Comment}
- end.
-
-start_node(Config) ->
- start_node(Config, []).
+
+ wait_for_memory_deallocations(),
+ print_stats(CaseName),
+
+ true = erlang:delete_module(CaseName),
+ slave_end(SlaveState),
+ Result.
+
+slave_init(migration) ->
+ A0 = case application:start(sasl) of
+ ok -> [sasl];
+ _ -> []
+ end,
+ case application:start(os_mon) of
+ ok -> [os_mon|A0];
+ _ -> A0
+ end;
+slave_init(_) -> [].
+
+slave_end(Apps) ->
+ lists:foreach(fun (A) -> application:stop(A) end, Apps).
+
+wait_for_memory_deallocations() ->
+ try
+ erts_debug:set_internal_state(wait, deallocations)
+ catch
+ error:undef ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ wait_for_memory_deallocations()
+ end.
+
+print_stats(migration) ->
+ {Btot,Ctot} = lists:foldl(fun({instance,Inr,Istats}, {Bacc,Cacc}) ->
+ {mbcs,MBCS} = lists:keyfind(mbcs, 1, Istats),
+ Btup = lists:keyfind(blocks, 1, MBCS),
+ Ctup = lists:keyfind(carriers, 1, MBCS),
+ io:format("{instance,~p,~p,~p}\n", [Inr, Btup, Ctup]),
+ {tuple_add(Bacc,Btup),tuple_add(Cacc,Ctup)};
+ (_, Acc) -> Acc
+ end,
+ {{blocks,0,0,0},{carriers,0,0,0}},
+ erlang:system_info({allocator,test_alloc})),
+
+ io:format("Number of blocks : ~p\n", [Btot]),
+ io:format("Number of carriers: ~p\n", [Ctot]);
+
+print_stats(_) -> ok.
+
+tuple_add(T1, T2) ->
+ list_to_tuple(lists:zipwith(fun(E1,E2) when is_number(E1), is_number(E2) ->
+ E1 + E2;
+ (A,A) ->
+ A
+ end,
+ tuple_to_list(T1), tuple_to_list(T2))).
+
+
+one_shot(CaseName) ->
+ State = CaseName:start({1, 0, erlang:system_info(build_type)}),
+ Result0 = CaseName:run(State),
+ false = (Result0 =:= continue),
+ Result1 = handle_result(State, Result0),
+ CaseName:stop(State),
+ Result1.
+
+
+many_shot(CaseName, I, Mem) ->
+ State = CaseName:start({I, Mem, erlang:system_info(build_type)}),
+ Result1 = repeat_while(fun() ->
+ Result0 = CaseName:run(State),
+ handle_result(State, Result0)
+ end,
+ 10*1000, I),
+ CaseName:stop(State),
+ flush_log(),
+ Result1.
+
+concurrent(CaseName) ->
+ NSched = erlang:system_info(schedulers),
+ Mem = (free_memory() * 3) div 4,
+ PRs = lists:map(fun(I) -> spawn_opt(fun() ->
+ many_shot(CaseName, I,
+ Mem div NSched)
+ end,
+ [monitor, {scheduler,I}])
+ end,
+ lists:seq(1, NSched)),
+ lists:foreach(fun({Pid,Ref}) ->
+ receive {'DOWN', Ref, process, Pid, Reason} ->
+ Reason
+ end
+ end,
+ PRs),
+ ok.
+
+repeat_while(Fun, Timeout, I) ->
+ TRef = erlang:start_timer(Timeout, self(), timeout),
+ R = repeat_while_loop(Fun, TRef, I),
+ erlang:cancel_timer(TRef, [{async,true},{info,false}]),
+ R.
+
+repeat_while_loop(Fun, TRef, I) ->
+ receive
+ {timeout, TRef, timeout} ->
+ io:format("~p: Timeout, enough is enough.",[I]),
+ succeeded
+ after 0 ->
+ %%io:format("~p calls fun\n", [self()]),
+ case Fun() of
+ continue -> repeat_while_loop(Fun, TRef, I);
+ R -> R
+ end
+ end.
+
+flush_log() ->
+ receive
+ {print, Str} ->
+ ?t:format("~s", [Str]),
+ flush_log()
+ after 0 ->
+ ok
+ end.
+
+handle_result(_State, Result0) ->
+ flush_log(),
+ case Result0 of
+ {'EXIT', Error} ->
+ ?line ?t:fail(Error);
+ {'EXIT', error, Error} ->
+ ?line ?t:fail(Error);
+ {failed, Comment} ->
+ ?line ?t:fail(Comment);
+ {skipped, Comment} ->
+ ?line {skipped, Comment};
+ {succeeded, ""} ->
+ ?line succeeded;
+ {succeeded, Comment} ->
+ ?line {comment, Comment};
+ continue ->
+ continue
+ end.
+
start_node(Config, Opts) when is_list(Config), is_list(Opts) ->
+ case ?config(debug,Config) of
+ true -> {ok, node()};
+ _ -> start_node_1(Config, Opts)
+ end.
+
+start_node_1(Config, Opts) ->
Pa = filename:dirname(code:which(?MODULE)),
Name = list_to_atom(atom_to_list(?MODULE)
++ "-"
@@ -252,6 +383,7 @@ start_node(Config, Opts) when is_list(Config), is_list(Opts) ->
++ integer_to_list(erlang:unique_integer([positive]))),
?t:start_node(Name, slave, [{args, Opts++" -pa "++Pa}]).
+stop_node(Node) when Node =:= node() -> ok;
stop_node(Node) ->
?t:stop_node(Node).
@@ -261,3 +393,23 @@ is_halfword_vm() ->
{4, 8} -> true;
{WS, WS} -> false
end.
+
+free_memory() ->
+ %% Free memory in MB.
+ try
+ SMD = memsup:get_system_memory_data(),
+ {value, {free_memory, Free}} = lists:keysearch(free_memory, 1, SMD),
+ TotFree = (Free +
+ case lists:keysearch(cached_memory, 1, SMD) of
+ {value, {cached_memory, Cached}} -> Cached;
+ false -> 0
+ end +
+ case lists:keysearch(buffered_memory, 1, SMD) of
+ {value, {buffered_memory, Buffed}} -> Buffed;
+ false -> 0
+ end),
+ TotFree div (1024*1024)
+ catch
+ error : undef ->
+ ?t:fail({"os_mon not built"})
+ end.
diff --git a/erts/emulator/test/alloc_SUITE_data/Makefile.src b/erts/emulator/test/alloc_SUITE_data/Makefile.src
index a441fe946b..e31de54e1b 100644
--- a/erts/emulator/test/alloc_SUITE_data/Makefile.src
+++ b/erts/emulator/test/alloc_SUITE_data/Makefile.src
@@ -25,7 +25,8 @@ TEST_DRVS = basic@dll@ \
bucket_mask@dll@ \
rbtree@dll@ \
mseg_clear_cache@dll@ \
- cpool@dll@
+ cpool@dll@ \
+ migration@dll@
CC = @CC@
LD = @LD@
diff --git a/erts/emulator/test/alloc_SUITE_data/allocator_test.h b/erts/emulator/test/alloc_SUITE_data/allocator_test.h
index 1d6b2f4907..97ee58cdad 100644
--- a/erts/emulator/test/alloc_SUITE_data/allocator_test.h
+++ b/erts/emulator/test/alloc_SUITE_data/allocator_test.h
@@ -20,9 +20,20 @@
#ifndef ALLOCATOR_TEST_H__
#define ALLOCATOR_TEST_H__
-typedef ErlDrvUInt Ulong;
+#if SIZEOF_VOID_P == SIZEOF_INT
+typedef unsigned int Ulong;
+#elif SIZEOF_VOID_P == SIZEOF_LONG
+typedef unsigned long Ulong;
+#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
+typedef unsigned long long Ulong;
+#else
+# error No pointer sized integer type found ???
+#endif
-#ifndef __WIN32__
+#ifdef __WIN32__
+typedef Ulong erts_alc_test_Fn(Ulong, Ulong, Ulong, Ulong);
+# define erts_alc_test ((erts_alc_test_Fn*)WinDynNifCallbacks.erts_alc_test)
+#else
Ulong erts_alc_test(Ulong, Ulong, Ulong, Ulong);
#endif
@@ -85,6 +96,7 @@ typedef void* erts_cond;
#define CPOOL_DELETE(A,B) ((Carrier_t *) ALC_TEST2(0x022, (A), (B)))
#define CPOOL_IS_EMPTY(A) ((int) ALC_TEST1(0x023, (A)))
#define CPOOL_IS_IN_POOL(A,B) ((int) ALC_TEST2(0x024, (A), (B)))
+#define UMEM2BLK_TEST(P) ((Block_t*) ALC_TEST1(0x025, (P)))
/* From erl_goodfit_alloc.c */
#define BKT_IX(A, S) ((Ulong) ALC_TEST2(0x100, (A), (S)))
@@ -142,5 +154,9 @@ typedef void* erts_cond;
#define THR_JOIN(T) ((void) ALC_TEST1(0xf11, (T)))
#define THR_EXIT(R) ((void) ALC_TEST1(0xf12, (R)))
#define IS_SMP_ENABLED ((int) ALC_TEST0(0xf13))
+#define ALLOC_TEST(S) ((void*) ALC_TEST1(0xf14, (S)))
+#define FREE_TEST(P) ((void) ALC_TEST1(0xf15, (P)))
+#define SET_TEST_MBC_USER_HEADER(SZ,CMBC,DMBC) ((int)ALC_TEST3(0xf16, (SZ), (CMBC), (DMBC)))
+#define GET_TEST_MBC_SIZE() ((int) ALC_TEST0(0xf17))
#endif
diff --git a/erts/emulator/test/alloc_SUITE_data/basic.c b/erts/emulator/test/alloc_SUITE_data/basic.c
index 323a24a11f..debb3d7ebe 100644
--- a/erts/emulator/test/alloc_SUITE_data/basic.c
+++ b/erts/emulator/test/alloc_SUITE_data/basic.c
@@ -60,3 +60,6 @@ testcase_cleanup(TestCaseState_t *tcs)
if (tcs->extra)
STOP_ALC((Allctr_t *) tcs->extra);
}
+
+ERL_NIF_INIT(basic, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/basic.erl b/erts/emulator/test/alloc_SUITE_data/basic.erl
new file mode 100644
index 0000000000..a018fd5582
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/basic.erl
@@ -0,0 +1,10 @@
+-module(basic).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_index.c b/erts/emulator/test/alloc_SUITE_data/bucket_index.c
index c13f229049..45cb53fbf7 100644
--- a/erts/emulator/test/alloc_SUITE_data/bucket_index.c
+++ b/erts/emulator/test/alloc_SUITE_data/bucket_index.c
@@ -113,3 +113,5 @@ test_it(TestCaseState_t *tcs, unsigned sbct)
sbct ? sbct_buf : "default");
}
+ERL_NIF_INIT(bucket_index, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_index.erl b/erts/emulator/test/alloc_SUITE_data/bucket_index.erl
new file mode 100644
index 0000000000..c54f54e2f5
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/bucket_index.erl
@@ -0,0 +1,10 @@
+-module(bucket_index).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_mask.c b/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
index 8d6166771e..c94c265f4e 100644
--- a/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
+++ b/erts/emulator/test/alloc_SUITE_data/bucket_mask.c
@@ -52,7 +52,7 @@ testcase_run(TestCaseState_t *tcs)
typedef struct linked_block {
struct linked_block* next;
}Linked;
- Linked* link;
+ Linked* link = NULL;
Linked* fence_list;
Linked* pad_list;
void* tmp;
@@ -183,3 +183,5 @@ testcase_run(TestCaseState_t *tcs)
tcs->extra = NULL;
}
+ERL_NIF_INIT(bucket_mask, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/bucket_mask.erl b/erts/emulator/test/alloc_SUITE_data/bucket_mask.erl
new file mode 100644
index 0000000000..589a50e1fa
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/bucket_mask.erl
@@ -0,0 +1,10 @@
+-module(bucket_mask).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/coalesce.c b/erts/emulator/test/alloc_SUITE_data/coalesce.c
index 0a5e0c5b0e..7791409a34 100644
--- a/erts/emulator/test/alloc_SUITE_data/coalesce.c
+++ b/erts/emulator/test/alloc_SUITE_data/coalesce.c
@@ -317,3 +317,6 @@ testcase_cleanup(TestCaseState_t *tcs)
if (tcs->extra)
STOP_ALC((Allctr_t *) tcs->extra);
}
+
+ERL_NIF_INIT(coalesce, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/coalesce.erl b/erts/emulator/test/alloc_SUITE_data/coalesce.erl
new file mode 100644
index 0000000000..453c726c4e
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/coalesce.erl
@@ -0,0 +1,10 @@
+-module(coalesce).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/cpool.c b/erts/emulator/test/alloc_SUITE_data/cpool.c
index 75c2bc13ae..73026cc758 100644
--- a/erts/emulator/test/alloc_SUITE_data/cpool.c
+++ b/erts/emulator/test/alloc_SUITE_data/cpool.c
@@ -86,13 +86,13 @@ thread_func(void *arg)
for (i = 0; i < (TEST_NO_CARRIERS_PER_THREAD+TEST_CARRIERS_OFFSET); i++) {
int d;
if (i < TEST_NO_CARRIERS_PER_THREAD) {
- CPOOL_INSERT(alloc, crr[i]);
+ (void) CPOOL_INSERT(alloc, crr[i]);
if ((i & 0x7) == 0)
FATAL_ASSERT(CPOOL_IS_IN_POOL(alloc, crr[i]));
}
d = i-TEST_CARRIERS_OFFSET;
if (d >= 0) {
- CPOOL_DELETE(alloc, crr[d]);
+ (void) CPOOL_DELETE(alloc, crr[d]);
if ((d & 0x7) == 0)
FATAL_ASSERT(!CPOOL_IS_IN_POOL(alloc, crr[d]));
}
@@ -129,7 +129,7 @@ testcase_run(TestCaseState_t *tcs)
for (c = 0; c < TEST_NO_CARRIERS_PER_THREAD; c++) {
Carrier_t *crr = (Carrier_t *) p;
p += zcrr_sz;
- ZERO_CRR_INIT(alloc, crr);
+ (void) ZERO_CRR_INIT(alloc, crr);
threads[t].crr[c] = crr;
}
}
@@ -156,3 +156,6 @@ testcase_run(TestCaseState_t *tcs)
ASSERT(tcs, no_threads == TEST_NO_THREADS);
}
+
+ERL_NIF_INIT(cpool, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/cpool.erl b/erts/emulator/test/alloc_SUITE_data/cpool.erl
new file mode 100644
index 0000000000..89053471fa
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/cpool.erl
@@ -0,0 +1,10 @@
+-module(cpool).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/migration.c b/erts/emulator/test/alloc_SUITE_data/migration.c
new file mode 100644
index 0000000000..b006360043
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/migration.c
@@ -0,0 +1,343 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2014. 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/.
+ *
+ * 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.
+ *
+ * %CopyrightEnd%
+ */
+
+/*
+ * Test the carrier migration logic
+ */
+
+#ifndef __WIN32__
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include "testcase_driver.h"
+#include "allocator_test.h"
+
+#define FATAL_ASSERT(A) \
+ ((void) ((A) \
+ ? 1 \
+ : (fatal_assert_failed(#A, \
+ (char *) __FILE__, \
+ __LINE__), \
+ 0)))
+
+static void
+fatal_assert_failed(char* expr, char* file, int line)
+{
+ fflush(stdout);
+ fprintf(stderr, "%s:%d: Assertion failed: %s\n",
+ file, line, expr);
+ fflush(stderr);
+ abort();
+}
+
+
+char *
+testcase_name(void)
+{
+ return "migration";
+}
+
+/* Turns out random_r() is a nonstandard glibc extension.
+#define HAVE_RANDOM_R
+*/
+#ifdef HAVE_RANDOM_R
+
+typedef struct { struct random_data rnd; char rndbuf[32]; } MyRandState;
+
+static void myrand_init(MyRandState* mrs, unsigned int seed)
+{
+ int res;
+ memset(&mrs->rnd, 0, sizeof(mrs->rnd));
+ res = initstate_r(seed, mrs->rndbuf, sizeof(mrs->rndbuf), &mrs->rnd);
+ FATAL_ASSERT(res == 0);
+}
+
+static int myrand(MyRandState* mrs)
+{
+ int32_t x;
+ int res = random_r(&mrs->rnd, &x);
+ FATAL_ASSERT(res == 0);
+ return (int)x;
+}
+
+#else /* !HAVE_RANDOM_R */
+
+typedef unsigned int MyRandState;
+
+static void myrand_init(MyRandState* mrs, unsigned int seed)
+{
+ *mrs = seed;
+}
+
+static int myrand(MyRandState* mrs)
+{
+ /* Taken from rand(3) man page.
+ * Modified to return a full 31-bit value by using low half of *mrs as well.
+ */
+ *mrs = (*mrs) * 1103515245 + 12345;
+ return (int) (((*mrs >> 16) | (*mrs << 16)) & ~(1 << 31));
+}
+
+#endif /* !HAVE_RANDOM_R */
+
+#define MAX_BLOCK_PER_THR 200
+#define BLOCKS_PER_MBC 10
+#define MAX_ROUNDS 10000
+
+typedef struct MyBlock_ {
+ struct MyBlock_* next;
+ struct MyBlock_** prevp;
+} MyBlock;
+
+typedef struct {
+ MyBlock* blockv[MAX_BLOCK_PER_THR];
+ MyRandState rand_state;
+ enum { GROWING, SHRINKING, CLEANUP, DONE } phase;
+ int nblocks;
+ int goal_nblocks;
+ int round;
+ int nr_of_migrations;
+ int nr_of_carriers;
+ int max_blocks_in_mbc;
+ int block_size;
+ int max_nblocks;
+} MigrationState;
+
+typedef struct {
+ ErlNifMutex* mtx;
+ int nblocks;
+ MyBlock* first;
+ MigrationState* employer;
+} MyCrrInfo;
+
+
+static int crr_info_offset = -1;
+static void (*orig_create_mbc_fn)(Allctr_t *allctr, Carrier_t *carrier);
+static void (*orig_destroying_mbc_fn)(Allctr_t *allctr, Carrier_t *carrier);
+
+static void my_creating_mbc(Allctr_t *allctr, Carrier_t *carrier)
+{
+ MyCrrInfo* mci = (MyCrrInfo*) ((char*)carrier + crr_info_offset);
+ if (orig_create_mbc_fn)
+ orig_create_mbc_fn(allctr, carrier);
+
+ mci->mtx = enif_mutex_create("alloc_SUITE.migration");
+ mci->nblocks = 0;
+ mci->first = NULL;
+ mci->employer = NULL;
+}
+
+static void my_destroying_mbc(Allctr_t *allctr, Carrier_t *carrier)
+{
+ MyCrrInfo* mci = (MyCrrInfo*) ((char*)carrier + crr_info_offset);
+
+ FATAL_ASSERT(mci->nblocks == 0);
+ FATAL_ASSERT(mci->first == NULL);
+ enif_mutex_destroy(mci->mtx);
+
+ if (orig_destroying_mbc_fn)
+ orig_destroying_mbc_fn(allctr, carrier);
+}
+
+static int migration_init(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
+{
+ void* creating_mbc_arg = (void*)my_creating_mbc;
+ void* destroying_mbc_arg = (void*)my_destroying_mbc;
+
+ if (testcase_nif_init(env, priv_data, load_info))
+ return -1;
+
+ crr_info_offset = SET_TEST_MBC_USER_HEADER(sizeof(MyCrrInfo),
+ &creating_mbc_arg,
+ &destroying_mbc_arg);
+ FATAL_ASSERT(crr_info_offset >= 0);
+ orig_create_mbc_fn = creating_mbc_arg;
+ orig_destroying_mbc_fn = destroying_mbc_arg;
+
+ return 0;
+}
+
+static void add_block(MyBlock* p, MigrationState* state)
+{
+ MyCrrInfo* mci = (MyCrrInfo*)((char*)BLK_TO_MBC(UMEM2BLK_TEST(p)) + crr_info_offset);
+
+ enif_mutex_lock(mci->mtx);
+ if (++mci->nblocks > state->max_blocks_in_mbc)
+ state->max_blocks_in_mbc = mci->nblocks;
+ p->next = mci->first;
+ p->prevp = &mci->first;
+ mci->first = p;
+ if (p->next)
+ p->next->prevp = &p->next;
+ if (mci->employer != state) {
+ if (!mci->employer) {
+ FATAL_ASSERT(mci->nblocks == 1);
+ state->nr_of_carriers++;
+ }
+ else {
+ state->nr_of_migrations++;
+ }
+ mci->employer = state;
+ }
+ enif_mutex_unlock(mci->mtx);
+}
+
+static void remove_block(MyBlock* p)
+{
+ MyCrrInfo* mci = (MyCrrInfo*)((char*)BLK_TO_MBC(UMEM2BLK_TEST(p)) + crr_info_offset);
+
+ enif_mutex_lock(mci->mtx);
+ mci->nblocks--;
+ if (p->next)
+ p->next->prevp = p->prevp;
+ *p->prevp = p->next;
+ enif_mutex_unlock(mci->mtx);
+}
+
+static int rand_int(MigrationState* state, int low, int high)
+{
+ int x;
+ FATAL_ASSERT(high >= low);
+ x = myrand(&state->rand_state);
+ return low + (x % (high+1-low));
+}
+
+
+static void do_cleanup(TestCaseState_t *tcs, MigrationState* state)
+{
+ if (state->nblocks == 0) {
+ state->phase = DONE;
+ testcase_printf(tcs, "%d: Done %d rounds", tcs->thr_nr, state->round);
+ testcase_printf(tcs, "%d: Cleanup all blocks", tcs->thr_nr);
+ testcase_printf(tcs, "%d: Empty carriers detected = %d", tcs->thr_nr,
+ state->nr_of_carriers);
+ testcase_printf(tcs, "%d: Migrations detected = %d", tcs->thr_nr,
+ state->nr_of_migrations);
+ testcase_printf(tcs, "%d: Max blocks in carrier = %d", tcs->thr_nr,
+ state->max_blocks_in_mbc);
+ }
+ else {
+ state->nblocks--;
+ if (state->blockv[state->nblocks]) {
+ remove_block(state->blockv[state->nblocks]);
+ FREE_TEST(state->blockv[state->nblocks]);
+ }
+ }
+}
+
+
+void
+testcase_run(TestCaseState_t *tcs)
+{
+ MigrationState* state = (MigrationState*) tcs->extra;
+
+ if (!tcs->extra) {
+ if (!IS_SMP_ENABLED)
+ testcase_skipped(tcs, "No SMP support");
+
+ tcs->extra = enif_alloc(sizeof(MigrationState));
+ state = (MigrationState*) tcs->extra;
+ memset(state->blockv, 0, sizeof(state->blockv));
+ myrand_init(&state->rand_state, tcs->thr_nr);
+ state->phase = GROWING;
+ state->nblocks = 0;
+ state->round = 0;
+ state->nr_of_migrations = 0;
+ state->nr_of_carriers = 0;
+ state->max_blocks_in_mbc = 0;
+ state->block_size = GET_TEST_MBC_SIZE() / (BLOCKS_PER_MBC+1);
+ if (MAX_BLOCK_PER_THR * state->block_size < tcs->free_mem) {
+ state->max_nblocks = MAX_BLOCK_PER_THR;
+ } else {
+ state->max_nblocks = tcs->free_mem / state->block_size;
+ }
+ state->goal_nblocks = rand_int(state, 1, state->max_nblocks);
+ }
+
+ switch (state->phase) {
+ case GROWING: {
+ MyBlock* p;
+ FATAL_ASSERT(!state->blockv[state->nblocks]);
+ p = ALLOC_TEST(rand_int(state, state->block_size/2, state->block_size));
+ FATAL_ASSERT(p);
+ add_block(p, state);
+ state->blockv[state->nblocks] = p;
+ if (++state->nblocks >= state->goal_nblocks) {
+ /*testcase_printf(tcs, "%d: Grown to %d blocks", tcs->thr_nr, state->nblocks);*/
+ state->phase = SHRINKING;
+ state->goal_nblocks = rand_int(state, 0, state->goal_nblocks-1);
+ }
+ else
+ FATAL_ASSERT(!state->blockv[state->nblocks]);
+ break;
+ }
+ case SHRINKING: {
+ int ix = rand_int(state, 0, state->nblocks-1);
+ FATAL_ASSERT(state->blockv[ix]);
+ remove_block(state->blockv[ix]);
+ FREE_TEST(state->blockv[ix]);
+ state->blockv[ix] = state->blockv[--state->nblocks];
+ state->blockv[state->nblocks] = NULL;
+
+ if (state->nblocks <= state->goal_nblocks) {
+ /*testcase_printf(tcs, "%d: Shrunk to %d blocks", tcs->thr_nr, state->nblocks);*/
+ if (++state->round >= MAX_ROUNDS) {
+ state->phase = CLEANUP;
+ } else {
+ state->phase = GROWING;
+ state->goal_nblocks = rand_int(state, state->goal_nblocks+1, state->max_nblocks);
+ }
+ }
+ break;
+ }
+ case CLEANUP:
+ do_cleanup(tcs, state);
+ break;
+
+ default:
+ FATAL_ASSERT(!"Invalid phase");
+ }
+
+ if (state->phase == DONE) {
+ }
+ else {
+ testcase_continue(tcs);
+ }
+}
+
+void
+testcase_cleanup(TestCaseState_t *tcs)
+{
+ MigrationState* state = (MigrationState*) tcs->extra;
+
+ while (state->phase != DONE)
+ do_cleanup(tcs, state);
+
+ enif_free(tcs->extra);
+ tcs->extra = NULL;
+}
+
+
+ERL_NIF_INIT(migration, testcase_nif_funcs, migration_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/migration.erl b/erts/emulator/test/alloc_SUITE_data/migration.erl
new file mode 100644
index 0000000000..440a99becd
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/migration.erl
@@ -0,0 +1,10 @@
+-module(migration).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c b/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c
index 9c03f3a331..e5df3d647f 100644
--- a/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c
+++ b/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.c
@@ -101,3 +101,6 @@ testcase_cleanup(TestCaseState_t *tcs)
tcs->extra = NULL;
}
}
+
+ERL_NIF_INIT(mseg_clear_cache, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.erl b/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.erl
new file mode 100644
index 0000000000..befd6c2e8e
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/mseg_clear_cache.erl
@@ -0,0 +1,10 @@
+-module(mseg_clear_cache).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/rbtree.c b/erts/emulator/test/alloc_SUITE_data/rbtree.c
index 8d4d5535a8..38bbbdf90c 100644
--- a/erts/emulator/test/alloc_SUITE_data/rbtree.c
+++ b/erts/emulator/test/alloc_SUITE_data/rbtree.c
@@ -20,7 +20,7 @@
#include "testcase_driver.h"
#include "allocator_test.h"
-#define NO_BLOCKS 100000
+int NO_BLOCKS;
#define RIGHT_VISITED (1 << 0)
#define LEFT_VISITED (1 << 1)
@@ -265,9 +265,10 @@ check_tree(TestCaseState_t *tcs, Allctr_t *alc, Ulong size)
ASSERT(tcs, curr_blacks == 0);
ASSERT(tcs, i == -1);
+ /*
testcase_printf(tcs, "Red-Black Tree OK! Max depth = %d; "
"Black depth = %d\n", max_i+1, blacks < 0 ? 0 : blacks);
-
+ */
return res;
}
@@ -468,6 +469,12 @@ testcase_run(TestCaseState_t *tcs)
Allctr_t *a;
rbtree_test_data *td;
+ NO_BLOCKS = 100*1000;
+ if (enif_is_identical(tcs->build_type,
+ enif_make_atom(tcs->curr_env,"valgrind"))) {
+ NO_BLOCKS /= 10;
+ }
+
/* Best fit... */
testcase_printf(tcs, "Setup...\n");
@@ -577,3 +584,6 @@ testcase_run(TestCaseState_t *tcs)
testcase_printf(tcs, "aoffcaobf test succeeded!\n");
}
+
+ERL_NIF_INIT(rbtree, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/rbtree.erl b/erts/emulator/test/alloc_SUITE_data/rbtree.erl
new file mode 100644
index 0000000000..f5b7120ff2
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/rbtree.erl
@@ -0,0 +1,10 @@
+-module(rbtree).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/realloc_copy.c b/erts/emulator/test/alloc_SUITE_data/realloc_copy.c
index e405f06225..c4147eb00d 100644
--- a/erts/emulator/test/alloc_SUITE_data/realloc_copy.c
+++ b/erts/emulator/test/alloc_SUITE_data/realloc_copy.c
@@ -278,3 +278,5 @@ testcase_cleanup(TestCaseState_t *tcs)
STOP_ALC((Allctr_t *) tcs->extra);
}
+ERL_NIF_INIT(realloc_copy, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/realloc_copy.erl b/erts/emulator/test/alloc_SUITE_data/realloc_copy.erl
new file mode 100644
index 0000000000..cc6617bf64
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/realloc_copy.erl
@@ -0,0 +1,10 @@
+-module(realloc_copy).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
index bc674c56b7..7dcca544e5 100644
--- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
+++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.c
@@ -23,141 +23,147 @@
#include <stdarg.h>
#include <setjmp.h>
#include <string.h>
+#include <limits.h>
#ifdef __WIN32__
-#undef HAVE_VSNPRINTF
-#define HAVE_VSNPRINTF 1
-#define vsnprintf _vsnprintf
+static void my_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
+{
+ _vsnprintf(outBuf, size, format, ap);
+ outBuf[size-1] = 0; /* be sure string is terminated */
+}
+#elif defined(HAVE_VSNPRINTF)
+# define my_vsnprintf(B,S,F,A) (void)vsnprintf(B,S,F,A)
+#else
+# warning Using unsafe 'vsprintf' without buffer overflow protection
+# define my_vsnprintf(B,S,F,A) (void)vsprintf(B,F,A)
#endif
-#ifndef HAVE_VSNPRINTF
-#define HAVE_VSNPRINTF 0
-#endif
+static void my_snprintf(char *outBuf, size_t size, const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ my_vsnprintf(outBuf, size, format, ap);
+ va_end(ap);
+}
#define COMMENT_BUF_SZ 4096
#define TESTCASE_FAILED 0
#define TESTCASE_SKIPPED 1
#define TESTCASE_SUCCEEDED 2
+#define TESTCASE_CONTINUE 3
typedef struct {
TestCaseState_t visible;
- ErlDrvPort port;
- ErlDrvTermData port_id;
int result;
- jmp_buf done_jmp_buf;
+ jmp_buf* done_jmp_buf;
char *comment;
char comment_buf[COMMENT_BUF_SZ];
} InternalTestCaseState_t;
-ErlDrvData testcase_drv_start(ErlDrvPort port, char *command);
-void testcase_drv_stop(ErlDrvData drv_data);
-void testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
-
-static ErlDrvEntry testcase_drv_entry = {
- NULL,
- testcase_drv_start,
- testcase_drv_stop,
- testcase_drv_run,
- NULL,
- NULL,
- "testcase_drv",
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- ERL_DRV_EXTENDED_MARKER,
- ERL_DRV_EXTENDED_MAJOR_VERSION,
- ERL_DRV_EXTENDED_MINOR_VERSION,
- 0,
- NULL,
- NULL,
- NULL
+ERL_NIF_TERM testcase_nif_start(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM testcase_nif_stop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM testcase_nif_run(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+
+ErlNifFunc testcase_nif_funcs[] =
+{
+ {"start", 1, testcase_nif_start},
+ {"run", 1, testcase_nif_run},
+ {"stop", 1, testcase_nif_stop}
};
+static ErlNifResourceType* testcase_rt;
+static ERL_NIF_TERM print_atom;
-DRIVER_INIT(testcase_drv)
+int testcase_nif_init(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
- testcase_drv_entry.driver_name = testcase_name();
- return &testcase_drv_entry;
+ testcase_rt = enif_open_resource_type(env, NULL, "testcase_rt", NULL,
+ ERL_NIF_RT_CREATE, NULL);
+
+ print_atom = enif_make_atom(env, "print");
+ return 0;
}
-ErlDrvData
-testcase_drv_start(ErlDrvPort port, char *command)
-{
+ERL_NIF_TERM
+testcase_nif_start(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{ /* (ThrNr, FreeMeg, BuildType) */
+ ERL_NIF_TERM ret;
InternalTestCaseState_t *itcs = (InternalTestCaseState_t *)
- driver_alloc(sizeof(InternalTestCaseState_t));
- if (!itcs) {
- return ERL_DRV_ERROR_GENERAL;
+ enif_alloc_resource(testcase_rt, sizeof(InternalTestCaseState_t));
+ int free_megabyte;
+ const int max_megabyte = INT_MAX / (1024*1024);
+ const ERL_NIF_TERM* tpl;
+ int tpl_arity;
+
+ if (!itcs
+ || !enif_get_tuple(env, argv[0], &tpl_arity, &tpl)
+ || tpl_arity != 3
+ || !enif_get_int(env, tpl[0], &itcs->visible.thr_nr)
+ || !enif_get_int(env, tpl[1], &free_megabyte)) {
+ enif_make_badarg(env);
}
-
+ itcs->visible.free_mem = (free_megabyte < max_megabyte ?
+ free_megabyte : max_megabyte) * (1024*1024);
itcs->visible.testcase_name = testcase_name();
+ itcs->visible.build_type = tpl[2];
itcs->visible.extra = NULL;
- itcs->port = port;
- itcs->port_id = driver_mk_port(port);
itcs->result = TESTCASE_FAILED;
itcs->comment = "";
- return (ErlDrvData) itcs;
+ ret = enif_make_resource(env, itcs);
+ enif_release_resource(itcs);
+ return ret;
}
-void
-testcase_drv_stop(ErlDrvData drv_data)
+ERL_NIF_TERM
+testcase_nif_stop(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- testcase_cleanup((TestCaseState_t *) drv_data);
- driver_free((void *) drv_data);
+ InternalTestCaseState_t *itcs;
+ if (!enif_get_resource(env, argv[0], testcase_rt, (void**)&itcs))
+ return enif_make_badarg(env);
+ testcase_cleanup(&itcs->visible);
+ return enif_make_atom(env,"ok");
}
-void
-testcase_drv_run(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)
+ERL_NIF_TERM
+testcase_nif_run(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
- InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data;
- ErlDrvTermData result_atom;
- ErlDrvTermData msg[12];
+ InternalTestCaseState_t *itcs;
+ const char* result_atom;
+ jmp_buf the_jmp_buf;
+
+ if (!enif_get_resource(env, argv[0], testcase_rt, (void**)&itcs))
+ return enif_make_badarg(env);
- itcs->visible.command = buf;
- itcs->visible.command_len = len;
+ itcs->visible.curr_env = env;
- if (setjmp(itcs->done_jmp_buf) == 0) {
- testcase_run((TestCaseState_t *) itcs);
+ /* For some unknown reason, first call to setjmp crashes on win64
+ * when jmp_buf is allocated as part of the resource. But it works when
+ * allocated on stack. It used to work when this was a driver.
+ */
+ itcs->done_jmp_buf = &the_jmp_buf;
+
+ if (setjmp(the_jmp_buf) == 0) {
+ testcase_run(&itcs->visible);
itcs->result = TESTCASE_SUCCEEDED;
}
switch (itcs->result) {
- case TESTCASE_SUCCEEDED:
- result_atom = driver_mk_atom("succeeded");
- break;
- case TESTCASE_SKIPPED:
- result_atom = driver_mk_atom("skipped");
- break;
- case TESTCASE_FAILED:
+ case TESTCASE_CONTINUE:
+ return enif_make_atom(env, "continue");
+
+ case TESTCASE_SUCCEEDED: result_atom = "succeeded"; break;
+ case TESTCASE_SKIPPED: result_atom = "skipped"; break;
+ case TESTCASE_FAILED: result_atom = "failed"; break;
default:
- result_atom = driver_mk_atom("failed");
- break;
+ result_atom = "failed";
+ my_snprintf(itcs->comment_buf, sizeof(itcs->comment_buf),
+ "Unexpected test result code %d.", itcs->result);
+ itcs->comment = itcs->comment_buf;
}
- msg[0] = ERL_DRV_ATOM;
- msg[1] = (ErlDrvTermData) result_atom;
-
- msg[2] = ERL_DRV_PORT;
- msg[3] = itcs->port_id;
-
- msg[4] = ERL_DRV_ATOM;
- msg[5] = driver_mk_atom(itcs->visible.testcase_name);
-
- msg[6] = ERL_DRV_STRING;
- msg[7] = (ErlDrvTermData) itcs->comment;
- msg[8] = (ErlDrvTermData) strlen(itcs->comment);
-
- msg[9] = ERL_DRV_TUPLE;
- msg[10] = (ErlDrvTermData) 4;
-
- erl_drv_output_term(itcs->port_id, msg, 11);
+ return enif_make_tuple2(env, enif_make_atom(env, result_atom),
+ enif_make_string(env, itcs->comment, ERL_NIF_LATIN1));
}
int
@@ -172,34 +178,22 @@ testcase_assertion_failed(TestCaseState_t *tcs,
void
testcase_printf(TestCaseState_t *tcs, char *frmt, ...)
{
- InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
- ErlDrvTermData msg[12];
+ InternalTestCaseState_t* itcs = (InternalTestCaseState_t*)tcs;
+ ErlNifPid pid;
+ ErlNifEnv* msg_env = enif_alloc_env();
+ ERL_NIF_TERM msg;
va_list va;
va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
+ my_vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
va_end(va);
- msg[0] = ERL_DRV_ATOM;
- msg[1] = (ErlDrvTermData) driver_mk_atom("print");
+ msg = enif_make_tuple2(msg_env, print_atom,
+ enif_make_string(msg_env, itcs->comment_buf, ERL_NIF_LATIN1));
- msg[2] = ERL_DRV_PORT;
- msg[3] = itcs->port_id;
+ enif_send(itcs->visible.curr_env, enif_self(itcs->visible.curr_env, &pid),
+ msg_env, msg);
- msg[4] = ERL_DRV_ATOM;
- msg[5] = driver_mk_atom(itcs->visible.testcase_name);
-
- msg[6] = ERL_DRV_STRING;
- msg[7] = (ErlDrvTermData) itcs->comment_buf;
- msg[8] = (ErlDrvTermData) strlen(itcs->comment_buf);
-
- msg[9] = ERL_DRV_TUPLE;
- msg[10] = (ErlDrvTermData) 4;
-
- erl_drv_output_term(itcs->port_id, msg, 11);
+ enif_free_env(msg_env);
}
@@ -208,17 +202,13 @@ void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...)
InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
va_list va;
va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
+ my_vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
va_end(va);
itcs->result = TESTCASE_SUCCEEDED;
itcs->comment = itcs->comment_buf;
- longjmp(itcs->done_jmp_buf, 1);
+ longjmp(*itcs->done_jmp_buf, 1);
}
void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...)
@@ -226,17 +216,20 @@ void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...)
InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
va_list va;
va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
+ my_vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
va_end(va);
itcs->result = TESTCASE_SKIPPED;
itcs->comment = itcs->comment_buf;
- longjmp(itcs->done_jmp_buf, 1);
+ longjmp(*itcs->done_jmp_buf, 1);
+}
+
+void testcase_continue(TestCaseState_t *tcs)
+{
+ InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs;
+ itcs->result = TESTCASE_CONTINUE;
+ longjmp(*itcs->done_jmp_buf, 1);
}
void testcase_failed(TestCaseState_t *tcs, char *frmt, ...)
@@ -246,37 +239,33 @@ void testcase_failed(TestCaseState_t *tcs, char *frmt, ...)
size_t bufsz = sizeof(buf);
va_list va;
va_start(va, frmt);
-#if HAVE_VSNPRINTF
- vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
-#else
- vsprintf(itcs->comment_buf, frmt, va);
-#endif
+ my_vsnprintf(itcs->comment_buf, COMMENT_BUF_SZ, frmt, va);
va_end(va);
itcs->result = TESTCASE_FAILED;
itcs->comment = itcs->comment_buf;
- if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0
+ if (enif_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0
&& strcmp("true", buf) == 0) {
fprintf(stderr, "Testcase \"%s\" failed: %s\n",
itcs->visible.testcase_name, itcs->comment);
abort();
}
- longjmp(itcs->done_jmp_buf, 1);
+ longjmp(*itcs->done_jmp_buf, 1);
}
void *testcase_alloc(size_t size)
{
- return driver_alloc(size);
+ return enif_alloc(size);
}
void *testcase_realloc(void *ptr, size_t size)
{
- return driver_realloc(ptr, size);
+ return enif_realloc(ptr, size);
}
void testcase_free(void *ptr)
{
- driver_free(ptr);
+ enif_free(ptr);
}
diff --git a/erts/emulator/test/alloc_SUITE_data/testcase_driver.h b/erts/emulator/test/alloc_SUITE_data/testcase_driver.h
index 5d17eaec64..f0ca91bd06 100644
--- a/erts/emulator/test/alloc_SUITE_data/testcase_driver.h
+++ b/erts/emulator/test/alloc_SUITE_data/testcase_driver.h
@@ -20,13 +20,15 @@
#ifndef TESTCASE_DRIVER_H__
#define TESTCASE_DRIVER_H__
-#include "erl_driver.h"
+#include "erl_nif.h"
#include <stdlib.h>
typedef struct {
+ ErlNifEnv* curr_env;
char *testcase_name;
- char *command;
- int command_len;
+ int thr_nr;
+ int free_mem; /* in bytes */
+ ERL_NIF_TERM build_type; /* opt, debug, valgrind, ... */
void *extra;
} TestCaseState_t;
@@ -34,9 +36,11 @@ typedef struct {
((void) ((B) ? 1 : testcase_assertion_failed((TCS), __FILE__, __LINE__, #B)))
+int testcase_nif_init(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
void testcase_printf(TestCaseState_t *tcs, char *frmt, ...);
void testcase_succeeded(TestCaseState_t *tcs, char *frmt, ...);
void testcase_skipped(TestCaseState_t *tcs, char *frmt, ...);
+void testcase_continue(TestCaseState_t *tcs);
void testcase_failed(TestCaseState_t *tcs, char *frmt, ...);
int testcase_assertion_failed(TestCaseState_t *tcs, char *file, int line,
char *assertion);
@@ -45,8 +49,11 @@ void *testcase_realloc(void *ptr, size_t size);
void testcase_free(void *ptr);
+/* Implemented by testcase: */
char *testcase_name(void);
void testcase_run(TestCaseState_t *tcs);
void testcase_cleanup(TestCaseState_t *tcs);
-#endif
+extern ErlNifFunc testcase_nif_funcs[3];
+
+#endif /* TESTCASE_DRIVER_H__ */
diff --git a/erts/emulator/test/alloc_SUITE_data/threads.c b/erts/emulator/test/alloc_SUITE_data/threads.c
index edad24ee6b..a8a6a23695 100644
--- a/erts/emulator/test/alloc_SUITE_data/threads.c
+++ b/erts/emulator/test/alloc_SUITE_data/threads.c
@@ -86,7 +86,7 @@ static void fail(int t_no, char *frmt, ...)
tc_failed = 1;
- if (erl_drv_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0
+ if (enif_getenv("ERL_ABORT_ON_FAILURE", buf, &bufsz) == 0
&& strcmp("true", buf) == 0) {
fprintf(stderr, "Testcase \"%s\" failed: %s\n",
testcase_name(), err_buf);
@@ -187,7 +187,6 @@ testcase_run(TestCaseState_t *tcs)
for(i = 1; i <= NO_OF_THREADS; i++) {
char *alc;
- int res;
threads[i].arg.no_ops_per_bl = NO_OF_OPS_PER_BL;
@@ -446,3 +445,6 @@ thread_func(void *arg)
exit_thread(td->t_no, 1);
return NULL;
}
+
+ERL_NIF_INIT(threads, testcase_nif_funcs, testcase_nif_init,
+ NULL, NULL, NULL);
diff --git a/erts/emulator/test/alloc_SUITE_data/threads.erl b/erts/emulator/test/alloc_SUITE_data/threads.erl
new file mode 100644
index 0000000000..a7b4965f5e
--- /dev/null
+++ b/erts/emulator/test/alloc_SUITE_data/threads.erl
@@ -0,0 +1,10 @@
+-module(threads).
+
+-export([init/1, start/1, run/1, stop/1]).
+
+init(File) ->
+ ok = erlang:load_nif(File, 0).
+
+start(_) -> erlang:nif_error(not_loaded).
+run(_) -> erlang:nif_error(not_loaded).
+stop(_) -> erlang:nif_error(not_loaded).
diff --git a/erts/emulator/test/distribution_SUITE_data/run.erl b/erts/emulator/test/distribution_SUITE_data/run.erl
index f5169e160c..d5ed139369 100644
--- a/erts/emulator/test/distribution_SUITE_data/run.erl
+++ b/erts/emulator/test/distribution_SUITE_data/run.erl
@@ -30,16 +30,19 @@ from(H, [_ | T]) -> from(H, T);
from(H, []) -> [].
start() ->
- net_kernel:start([fideridum,shortnames]),
- {ok, Node} = slave:start(host(), heppel),
- P = spawn(Node, a, b, []),
- B1 = term_to_binary(P),
- N1 = node(P),
- ok = net_kernel:stop(),
- N2 = node(P),
- io:format("~w~n", [N1 == N2]),
+ Result = do_it(),
+
+ %% Do GCs and node_and_dist_references
+ %% in an attempt to crash the VM (without OTP-13076 fix)
+ lists:foreach(fun(P) -> erlang:garbage_collect(P) end,
+ processes()),
+ erts_debug:set_internal_state(available_internal_state, true),
+ erts_debug:get_internal_state(node_and_dist_references),
+
+ io:format("~w~n", [Result]),
+
if
- N1 == N2 ->
+ Result ->
init:stop();
true ->
%% Make sure that the io:format/2 output is really written
@@ -47,3 +50,29 @@ start() ->
erlang:yield(),
init:stop()
end.
+
+
+do_it() ->
+ {ok, _} = net_kernel:start([fideridum,shortnames]),
+ {ok, Node} = slave:start(host(), heppel),
+ P = spawn(Node, net_kernel, stop, []),
+ B1 = term_to_binary(P),
+ N1 = node(P),
+ ok = net_kernel:stop(),
+ N2 = node(P),
+
+ %% OTP-13076
+ %% Restart distribution with same node name as previous remote node
+ %% Repeat to wrap around creation
+ Result = lists:foldl(fun(_, Acc) ->
+ timer:sleep(2), % give net_kernel:stop() time to take effect :-(
+ {ok, _} = net_kernel:start([heppel,shortnames]),
+ N3 = node(P),
+ ok = net_kernel:stop(),
+ N4 = node(P),
+ Acc and (N3 =:= N1) and (N4 =:= N1)
+ end,
+ (N2 =:= N1),
+ lists:seq(1,3)),
+
+ Result.
diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl
index 886ae7d516..6890c42b7a 100644
--- a/erts/emulator/test/map_SUITE.erl
+++ b/erts/emulator/test/map_SUITE.erl
@@ -58,6 +58,7 @@
%% erlang
t_erlang_hash/1,
t_map_encode_decode/1,
+ t_gc_rare_map_overflow/1,
%% non specific BIF related
t_bif_build_and_check/1,
@@ -121,6 +122,7 @@ all() -> [
%% erlang
t_erlang_hash, t_map_encode_decode,
+ t_gc_rare_map_overflow,
t_map_size, t_is_map,
%% non specific BIF related
@@ -2181,7 +2183,9 @@ t_map_encode_decode(Config) when is_list(Config) ->
{<<>>, sc9}, {3.14158, sc10},
{[3.14158], sc11}, {more_atoms, sc12},
{{more_tuples}, sc13}, {self(), sc14},
- {{},{}},{[],[]}
+ {{},{}},{[],[]},
+ {map_s, #{a=>a, 2=>b, 3=>c}},
+ {map_l, maps:from_list([{I,I}||I <- lists:seq(1,74)])}
],
ok = map_encode_decode_and_match(Pairs,[],#{}),
@@ -2245,9 +2249,30 @@ t_map_encode_decode(Config) when is_list(Config) ->
%% bad size (too small) .. should fail just truncate it .. weird.
%% possibly change external format so truncated will be #{a:=1}
- #{ a:=b } =
- erlang:binary_to_term(<<131,116,0,0,0,1,100,0,1,97,100,0,1,98,97,1,97,1>>),
-
+ #{ a:=b } = erlang:binary_to_term(<<131,116,0,0,0,1,100,0,1,97,100,0,1,98,97,1,97,1>>),
+
+ %% specific fannerl (opensource app) binary_to_term error in 18.1
+
+ #{bias := {1,1,0},
+ bit_fail := 0,
+ connections := #{{2,9} := _,
+ {8,14} := _,
+ {2,12} := _,
+ {5,7} := _,
+ {11,16} := _,
+ {11,15} := _},
+ layers := {5,7,3},
+ network_type := fann_nettype_layer,
+ num_input := 5,
+ num_layers := 3,
+ num_output := 3,
+ rprop_delta_max := _,
+ rprop_delta_min := _,
+ total_connections := 66,
+ total_neurons := 17,
+ train_error_function := fann_errorfunc_tanh,
+ train_stop_function := fann_stopfunc_mse,
+ training_algorithm := fann_train_rprop} = erlang:binary_to_term(fannerl()),
ok.
map_encode_decode_and_match([{K,V}|Pairs], EncodedPairs, M0) ->
@@ -2966,3 +2991,176 @@ do_badmap_17(Config) ->
%% Use this function to avoid compile-time evaluation of an expression.
id(I) -> I.
+
+
+%% OTP-13146
+%% Provoke major GC with a lot of "fat" maps on external format in msg queue
+%% causing heap fragments to be allocated.
+t_gc_rare_map_overflow(Config) ->
+ Pa = filename:dirname(code:which(?MODULE)),
+ {ok, Node} = test_server:start_node(gc_rare_map_overflow, slave, [{args, "-pa \""++Pa++"\""}]),
+ Echo = spawn_link(Node, fun Loop() -> receive {From,Msg} -> From ! Msg
+ end,
+ Loop()
+ end),
+ FatMap = fatmap(34),
+ false = (flatmap =:= erts_internal:map_type(FatMap)),
+
+ t_gc_rare_map_overflow_do(Echo, FatMap, fun() -> erlang:garbage_collect() end),
+
+ % Repeat test for minor gc:
+ minor_collect(), % need this to make the next gc really be a minor
+ t_gc_rare_map_overflow_do(Echo, FatMap, fun() -> true = minor_collect() end),
+
+ unlink(Echo),
+ test_server:stop_node(Node).
+
+t_gc_rare_map_overflow_do(Echo, FatMap, GcFun) ->
+ Master = self(),
+ true = receive M -> false after 0 -> true end, % assert empty msg queue
+ Echo ! {Master, token},
+ repeat(1000, fun(_) -> Echo ! {Master, FatMap} end, void),
+
+ timer:sleep(100), % Wait for maps to arrive in our msg queue
+ token = receive Tok -> Tok end, % and provoke move from outer to inner msg queue
+
+ %% Do GC that will "overflow" and create heap frags due to all the fat maps
+ GcFun(),
+
+ %% Now check that all maps in msg queueu are intact
+ %% Will crash emulator in OTP-18.1
+ repeat(1000, fun(_) -> FatMap = receive FM -> FM end end, void),
+ ok.
+
+minor_collect() ->
+ minor_collect(minor_gcs()).
+
+minor_collect(Before) ->
+ After = minor_gcs(),
+ case After of
+ _ when After > Before -> true;
+ _ when After =:= Before -> minor_collect(Before);
+ 0 -> false
+ end.
+
+minor_gcs() ->
+ {garbage_collection, Info} = process_info(self(), garbage_collection),
+ {minor_gcs, GCS} = lists:keyfind(minor_gcs, 1, Info),
+ GCS.
+
+%% Generate a map with N (or N+1) keys that has an abnormal heap demand.
+%% Done by finding keys that collide in the first 32-bit hash.
+fatmap(N) ->
+ erts_debug:set_internal_state(available_internal_state, true),
+ Table = ets:new(void, [bag, private]),
+
+ Seed0 = rand:seed_s(exsplus, {4711, 3141592, 2718281}),
+ Seed1 = fatmap_populate(Table, Seed0, (1 bsl 16)),
+ Keys = fatmap_generate(Table, Seed1, N, []),
+ ets:delete(Table),
+ maps:from_list([{K,K} || K <- Keys]).
+
+fatmap_populate(_, Seed, 0) -> Seed;
+fatmap_populate(Table, Seed, N) ->
+ {I, NextSeed} = rand:uniform_s(1 bsl 48, Seed),
+ Hash = internal_hash(I),
+ ets:insert(Table, [{Hash, I}]),
+ fatmap_populate(Table, NextSeed, N-1).
+
+
+fatmap_generate(_, _, N, Acc) when N =< 0 ->
+ Acc;
+fatmap_generate(Table, Seed, N0, Acc0) ->
+ {I, NextSeed} = rand:uniform_s(1 bsl 48, Seed),
+ Hash = internal_hash(I),
+ case ets:member(Table, Hash) of
+ true ->
+ NewKeys = [I | ets:lookup_element(Table, Hash, 2)],
+ Acc1 = lists:usort(Acc0 ++ NewKeys),
+ N1 = N0 - (length(Acc1) - length(Acc0)),
+ fatmap_generate(Table, NextSeed, N1, Acc1);
+ false ->
+ fatmap_generate(Table, NextSeed, N0, Acc0)
+ end.
+
+internal_hash(Term) ->
+ erts_debug:get_internal_state({internal_hash, Term}).
+
+
+%% map external_format (fannerl).
+fannerl() ->
+ <<131,116,0,0,0,28,100,0,13,108,101,97,114,110,105,110,103,95,114,
+ 97,116,101,70,63,230,102,102,96,0,0,0,100,0,17,108,101,97,114,110,105,110,
+ 103,95,109,111,109,101,110,116,117,109,70,0,0,0,0,0,0,0,0,100,0,
+ 18,116,114,97,105,110,105,110,103,95,97,108,103,111,114,105,116,104,109,100,0,
+ 16,102,97,110,110,95,116,114,97,105,110,95,114,112,114,111,112,
+ 100,0,17,109,101,97,110,95,115,113,117,97,114,101,95,101,114,114,111,114,70,
+ 0,0,0,0,0,0,0,0,100,0,8,98,105,116,95,102,97,105,108,97,0,100,0,20,
+ 116,114,97,105,110,95,101,114,114,111,114,95,102,117,110,99,116,105,111,
+ 110,100,0,19,102,97,110,110,95,101,114,114,111,114,102,117,110,99,
+ 95,116,97,110,104,100,0,9,110,117,109,95,105,110,112,117,116,97,5,100,0,10,110,
+ 117,109,95,111,117,116,112,117,116,97,3,100,0,13,116,111,116,97,108,
+ 95,110,101,117,114,111,110,115,97,17,100,0,17,116,111,116,97,108,95,99,111,110,
+ 110,101,99,116,105,111,110,115,97,66,100,0,12,110,101,116,119,111,114,107,
+ 95,116,121,112,101,100,0,18,102,97,110,110,95,110,101,116,116,121,112,101,
+ 95,108,97,121,101,114,100,0,15,99,111,110,110,101,99,116,105,111,110,95,
+ 114,97,116,101,70,63,240,0,0,0,0,0,0,100,0,10,110,117,109,95,108,97,121,101,
+ 114,115,97,3,100,0,19,116,114,97,105,110,95,115,116,111,112,95,102,117,110,
+ 99,116,105,111,110,100,0,17,102,97,110,110,95,115,116,111,112,102,117,110,
+ 99,95,109,115,101,100,0,15,113,117,105,99,107,112,114,111,112,95,100,101,99,
+ 97,121,70,191,26,54,226,224,0,0,0,100,0,12,113,117,105,99,107,112,114,
+ 111,112,95,109,117,70,63,252,0,0,0,0,0,0,100,0,21,114,112,114,111,112,95,105,
+ 110,99,114,101,97,115,101,95,102,97,99,116,111,114,70,63,243,51,51,
+ 64,0,0,0,100,0,21,114,112,114,111,112,95,100,101,99,114,101,97,115,101,
+ 95,102,97,99,116,111,114,70,63,224,0,0,0,0,0,0,100,0,15,114,112,114,111,112,
+ 95,100,101,108,116,97,95,109,105,110,70,0,0,0,0,0,0,0,0,100,0,15,114,112,114,
+ 111,112,95,100,101,108,116,97,95,109,97,120,70,64,73,0,0,0,0,0,0,100,0,
+ 16,114,112,114,111,112,95,100,101,108,116,97,95,122,101,114,111,70,63,185,153,
+ 153,160,0,0,0,100,0,26,115,97,114,112,114,111,112,95,119,101,105,103,
+ 104,116,95,100,101,99,97,121,95,115,104,105,102,116,70,192,26,147,116,192,0,0,0,
+ 100,0,35,115,97,114,112,114,111,112,95,115,116,101,112,95,101,114,
+ 114,111,114,95,116,104,114,101,115,104,111,108,100,95,102,97,99,116,111,114,70,
+ 63,185,153,153,160,0,0,0,100,0,24,115,97,114,112,114,111,112,95,115,
+ 116,101,112,95,101,114,114,111,114,95,115,104,105,102,116,70,63,246,40,245,
+ 192,0,0,0,100,0,19,115,97,114,112,114,111,112,95,116,101,109,112,101,114,
+ 97,116,117,114,101,70,63,142,184,81,224,0,0,0,100,0,6,108,97,121,101,114,115,
+ 104,3,97,5,97,7,97,3,100,0,4,98,105,97,115,104,3,97,1,97,1,97,0,100,0,11,
+ 99,111,110,110,101,99,116,105,111,110,115,116,0,0,0,66,104,2,97,0,97,6,70,
+ 191,179,51,44,64,0,0,0,104,2,97,1,97,6,70,63,178,130,90,32,0,0,0,104,2,97,2,
+ 97,6,70,63,82,90,88,0,0,0,0,104,2,97,3,97,6,70,63,162,91,63,192,0,0,0,104,2,
+ 97,4,97,6,70,191,151,70,169,0,0,0,0,104,2,97,5,97,6,70,191,117,52,222,0,0,0,
+ 0,104,2,97,0,97,7,70,63,152,240,139,0,0,0,0,104,2,97,1,97,7,70,191,166,31,
+ 187,160,0,0,0,104,2,97,2,97,7,70,191,150,70,63,0,0,0,0,104,2,97,3,97,7,70,
+ 63,152,181,126,128,0,0,0,104,2,97,4,97,7,70,63,151,187,162,128,0,0,0,104,2,
+ 97,5,97,7,70,191,143,161,101,0,0,0,0,104,2,97,0,97,8,70,191,153,102,36,128,0,
+ 0,0,104,2,97,1,97,8,70,63,160,139,250,64,0,0,0,104,2,97,2,97,8,70,63,164,62,
+ 196,64,0,0,0,104,2,97,3,97,8,70,191,178,78,209,192,0,0,0,104,2,97,4,97,8,70,
+ 191,185,19,76,224,0,0,0,104,2,97,5,97,8,70,63,183,142,196,96,0,0,0,104,2,97,0,
+ 97,9,70,63,150,104,248,0,0,0,0,104,2,97,1,97,9,70,191,164,4,100,224,0,0,0,
+ 104,2,97,2,97,9,70,191,169,42,42,224,0,0,0,104,2,97,3,97,9,70,63,145,54,78,128,0,
+ 0,0,104,2,97,4,97,9,70,63,126,243,134,0,0,0,0,104,2,97,5,97,9,70,63,177,
+ 203,25,96,0,0,0,104,2,97,0,97,10,70,63,172,104,47,64,0,0,0,104,2,97,1,97,10,
+ 70,63,161,242,193,64,0,0,0,104,2,97,2,97,10,70,63,175,208,241,192,0,0,0,104,2,
+ 97,3,97,10,70,191,129,202,161,0,0,0,0,104,2,97,4,97,10,70,63,178,151,55,32,0,0,0,
+ 104,2,97,5,97,10,70,63,137,155,94,0,0,0,0,104,2,97,0,97,11,70,191,179,
+ 106,160,0,0,0,0,104,2,97,1,97,11,70,63,184,253,164,96,0,0,0,104,2,97,2,97,11,
+ 70,191,143,30,157,0,0,0,0,104,2,97,3,97,11,70,63,153,225,140,128,0,0,0,104,
+ 2,97,4,97,11,70,63,161,35,85,192,0,0,0,104,2,97,5,97,11,70,63,175,200,55,192,
+ 0,0,0,104,2,97,0,97,12,70,191,180,116,132,96,0,0,0,104,2,97,1,97,12,70,191,
+ 165,151,152,0,0,0,0,104,2,97,2,97,12,70,191,180,197,91,160,0,0,0,104,2,97,3,97,12,
+ 70,191,91,30,160,0,0,0,0,104,2,97,4,97,12,70,63,180,251,45,32,0,0,0,
+ 104,2,97,5,97,12,70,63,165,134,77,64,0,0,0,104,2,97,6,97,14,70,63,181,56,242,96,
+ 0,0,0,104,2,97,7,97,14,70,191,165,239,234,224,0,0,0,104,2,97,8,97,14,
+ 70,191,154,65,216,128,0,0,0,104,2,97,9,97,14,70,63,150,250,236,0,0,0,0,104,2,97,
+ 10,97,14,70,191,141,105,108,0,0,0,0,104,2,97,11,97,14,70,191,152,40,
+ 165,0,0,0,0,104,2,97,12,97,14,70,63,141,159,46,0,0,0,0,104,2,97,13,97,14,70,
+ 191,183,172,137,32,0,0,0,104,2,97,6,97,15,70,63,163,26,123,192,0,0,0,104,
+ 2,97,7,97,15,70,63,176,184,106,32,0,0,0,104,2,97,8,97,15,70,63,152,234,144,
+ 0,0,0,0,104,2,97,9,97,15,70,191,172,58,70,160,0,0,0,104,2,97,10,97,15,70,
+ 63,161,211,211,192,0,0,0,104,2,97,11,97,15,70,191,148,171,120,128,0,0,0,104,
+ 2,97,12,97,15,70,63,180,117,214,224,0,0,0,104,2,97,13,97,15,70,191,104,
+ 230,216,0,0,0,0,104,2,97,6,97,16,70,63,178,53,103,96,0,0,0,104,2,97,7,97,16,
+ 70,63,170,230,232,64,0,0,0,104,2,97,8,97,16,70,191,183,45,100,192,0,0,0,
+ 104,2,97,9,97,16,70,63,184,100,97,32,0,0,0,104,2,97,10,97,16,70,63,169,174,
+ 254,64,0,0,0,104,2,97,11,97,16,70,191,119,121,234,0,0,0,0,104,2,97,12,97,
+ 16,70,63,149,12,170,128,0,0,0,104,2,97,13,97,16,70,191,144,193,191,0,0,0,0>>.
diff --git a/erts/emulator/test/nif_SUITE_data/nif_mod.c b/erts/emulator/test/nif_SUITE_data/nif_mod.c
index 9c78c0e04d..f7e729e2b6 100644
--- a/erts/emulator/test/nif_SUITE_data/nif_mod.c
+++ b/erts/emulator/test/nif_SUITE_data/nif_mod.c
@@ -240,7 +240,7 @@ static ERL_NIF_TERM lib_version(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
static ERL_NIF_TERM get_priv_data_ptr(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
ADD_CALL("get_priv_data_ptr");
- return enif_make_ulong(env, (unsigned long)priv_data(env));
+ return enif_make_uint64(env, (ErlNifUInt64)priv_data(env));
}
static ERL_NIF_TERM make_new_resource(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl
index 4c311e1f06..97aa5e573e 100644
--- a/erts/emulator/test/process_SUITE.erl
+++ b/erts/emulator/test/process_SUITE.erl
@@ -1478,7 +1478,15 @@ processes_this_tab(doc) ->
processes_this_tab(suite) ->
[];
processes_this_tab(Config) when is_list(Config) ->
- sys_mem_cond_run(1024, fun () -> chk_processes_bif_test_res(processes_bif_test()) end).
+ Mem = case {erlang:system_info(build_type),
+ erlang:system_info(allocator)} of
+ {lcnt, {_, _Vsn, [sys_alloc], _Opts}} ->
+ %% When running +Mea min + lcnt we may need more memory
+ 1024 * 4;
+ _ ->
+ 1024
+ end,
+ sys_mem_cond_run(Mem, fun () -> chk_processes_bif_test_res(processes_bif_test()) end).
chk_processes_bif_test_res(ok) -> ok;
chk_processes_bif_test_res({comment, _} = Comment) -> Comment;