diff options
Diffstat (limited to 'erts/emulator/test')
-rw-r--r-- | erts/emulator/test/Makefile | 1 | ||||
-rw-r--r-- | erts/emulator/test/decode_packet_SUITE.erl | 4 | ||||
-rw-r--r-- | erts/emulator/test/float_SUITE.erl | 29 | ||||
-rw-r--r-- | erts/emulator/test/hash_SUITE.erl | 8 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE.erl | 168 | ||||
-rw-r--r-- | erts/emulator/test/nif_SUITE_data/nif_SUITE.c | 114 | ||||
-rw-r--r-- | erts/emulator/test/obsolete_SUITE.erl | 123 | ||||
-rw-r--r-- | erts/emulator/test/obsolete_SUITE_data/Makefile.src | 33 | ||||
-rw-r--r-- | erts/emulator/test/obsolete_SUITE_data/erl_threads.c | 302 | ||||
-rw-r--r-- | erts/emulator/test/obsolete_SUITE_data/testcase_driver.c | 262 | ||||
-rw-r--r-- | erts/emulator/test/obsolete_SUITE_data/testcase_driver.h | 57 | ||||
-rw-r--r-- | erts/emulator/test/scheduler_SUITE.erl | 361 | ||||
-rw-r--r-- | erts/emulator/test/send_term_SUITE.erl | 67 | ||||
-rw-r--r-- | erts/emulator/test/send_term_SUITE_data/send_term_drv.c | 218 |
14 files changed, 790 insertions, 957 deletions
diff --git a/erts/emulator/test/Makefile b/erts/emulator/test/Makefile index 5ec17a5e2a..a4c02da626 100644 --- a/erts/emulator/test/Makefile +++ b/erts/emulator/test/Makefile @@ -75,7 +75,6 @@ MODULES= \ node_container_SUITE \ nofrag_SUITE \ num_bif_SUITE \ - obsolete_SUITE \ op_SUITE \ port_SUITE \ port_bif_SUITE \ diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl index 6cde286871..d9e961be2f 100644 --- a/erts/emulator/test/decode_packet_SUITE.erl +++ b/erts/emulator/test/decode_packet_SUITE.erl @@ -304,6 +304,10 @@ http(Config) when is_list(Config) -> {ok, {http_request, 'GET', ResB, {1,1}}, Rest} = decode_pkt(http_bin,Bin) end, lists:foreach(UriF, http_uri_variants()), + + %% Response with empty phrase + ?line {ok,{http_response,{1,1},200,[]},<<>>} = decode_pkt(http, <<"HTTP/1.1 200\r\n">>, []), + ?line {ok,{http_response,{1,1},200,<<>>},<<>>} = decode_pkt(http_bin, <<"HTTP/1.1 200\r\n">>, []), ok. http_with_bin(http) -> diff --git a/erts/emulator/test/float_SUITE.erl b/erts/emulator/test/float_SUITE.erl index 102e472ea6..99e9457985 100644 --- a/erts/emulator/test/float_SUITE.erl +++ b/erts/emulator/test/float_SUITE.erl @@ -22,7 +22,10 @@ -include("test_server.hrl"). -export([all/1,init_per_testcase/2,fin_per_testcase/2, - fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1,bad_float_unpack/1]). + fpe/1,fp_drv/1,fp_drv_thread/1,denormalized/1,match/1, + bad_float_unpack/1]). +-export([otp_7178/1]). + init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> Dog = ?t:timetrap(?t:minutes(3)), @@ -33,7 +36,29 @@ fin_per_testcase(_Func, Config) -> ?t:timetrap_cancel(Dog). all(suite) -> - [fpe,fp_drv,fp_drv_thread,denormalized,match,bad_float_unpack]. + [fpe, + fp_drv, + fp_drv_thread, + otp_7178, + denormalized, + match, + bad_float_unpack]. + +%% +%% OTP-7178, list_to_float on very small numbers should give 0.0 +%% instead of exception, i.e. ignore underflow. +%% +otp_7178(suite) -> + []; +otp_7178(doc) -> + ["test that list_to_float on very small numbers give 0.0"]; +otp_7178(Config) when is_list(Config) -> + ?line X = list_to_float("1.0e-325"), + ?line true = (X < 0.00000001) and (X > -0.00000001), + ?line Y = list_to_float("1.0e-325325325"), + ?line true = (Y < 0.00000001) and (Y > -0.00000001), + ?line {'EXIT', {badarg,_}} = (catch list_to_float("1.0e83291083210")), + ok. %% Forces floating point exceptions and tests that subsequent, legal, %% operations are calculated correctly. Original version by Sebastian diff --git a/erts/emulator/test/hash_SUITE.erl b/erts/emulator/test/hash_SUITE.erl index 85bdb8bff8..f5d1871bfb 100644 --- a/erts/emulator/test/hash_SUITE.erl +++ b/erts/emulator/test/hash_SUITE.erl @@ -480,14 +480,14 @@ otp_5292_test() -> S2 = md5([md5(hash_int(S, E, PH)) || {Start, N, Sz} <- d(), {S, E} <- int(Start, N, Sz)]), ?line Comment = case S1 of - <<43,186,76,102,87,4,110,245,203,177,206,6,130,69,43,99>> -> + <<4,248,208,156,200,131,7,1,173,13,239,173,112,81,16,174>> -> ?line big = erlang:system_info(endian), "Big endian machine"; - <<21,206,139,15,149,28,167,81,98,225,132,254,49,125,174,195>> -> + <<180,28,33,231,239,184,71,125,76,47,227,241,78,184,176,233>> -> ?line little = erlang:system_info(endian), "Little endian machine" end, - ?line <<140,37,79,80,26,242,130,22,20,229,123,240,223,244,43,99>> = S2, + ?line <<124,81,198,121,174,233,19,137,10,83,33,80,226,111,238,99>> = S2, ?line 2 = erlang:hash(1, (1 bsl 27) -1), ?line {'EXIT', _} = (catch erlang:hash(1, (1 bsl 27))), {comment, Comment}. @@ -507,7 +507,7 @@ hash_int(Start, End, F) -> {Start, End, md5(HL)}. md5(T) -> - erlang:md5(term_to_binary(T)). + erlang:md5(term_to_binary(T)). bit_level_binaries() -> ?line [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] = diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl index 888bf582d8..f45cfa3e4a 100644 --- a/erts/emulator/test/nif_SUITE.erl +++ b/erts/emulator/test/nif_SUITE.erl @@ -30,7 +30,7 @@ fin_per_testcase/2, basic/1, reload/1, upgrade/1, heap_frag/1, types/1, many_args/1, binaries/1, get_string/1, get_atom/1, api_macros/1, from_array/1, iolist_as_binary/1, resource/1, resource_binary/1, resource_takeover/1, - threading/1, send/1, send2/1, send_threaded/1, neg/1, is_checks/1, + threading/1, send/1, send2/1, send3/1, send_threaded/1, neg/1, is_checks/1, get_length/1, make_atom/1, make_string/1]). -export([many_args_100/100]). @@ -51,7 +51,7 @@ all(suite) -> [basic, reload, upgrade, heap_frag, types, many_args, binaries, get_string, get_atom, api_macros, from_array, iolist_as_binary, resource, resource_binary, - resource_takeover, threading, send, send2, send_threaded, neg, is_checks, + resource_takeover, threading, send, send2, send3, send_threaded, neg, is_checks, get_length, make_atom, make_string]. %%init_per_testcase(_Case, Config) -> @@ -916,7 +916,164 @@ forwarder(To, N) -> other_term() -> {fun(X,Y) -> X*Y end, make_ref()}. - + +send3(doc) -> ["Message sending stress test"]; +send3(Config) when is_list(Config) -> + %% Let a number of processes send random message blobs between each other + %% using enif_send. Kill and spawn new ones randomly to keep a ~constant + %% number of workers running. + Seed = now(), + io:format("seed: ~p\n",[Seed]), + random:seed(Seed), + ets:new(nif_SUITE,[named_table,public]), + ?line true = ets:insert(nif_SUITE,{send3,0,0,0,0}), + timer:send_after(10000, timeout), % Run for 10 seconds + SpawnCnt = send3_controller(0, [], [], 20), + ?line [{_,Rcv,SndOk,SndFail,Balance}] = ets:lookup(nif_SUITE,send3), + io:format("spawns=~p received=~p, sent=~p send-failure=~p balance=~p\n", + [SpawnCnt,Rcv,SndOk,SndFail,Balance]), + ets:delete(nif_SUITE). + +send3_controller(SpawnCnt, [], _, infinity) -> + SpawnCnt; +send3_controller(SpawnCnt0, Mons0, Pids0, Tick) -> + receive + timeout -> + io:format("Timeout. Sending 'halt' to ~p\n",[Pids0]), + lists:foreach(fun(P) -> P ! {halt,self()} end, Pids0), + lists:foreach(fun(P) -> receive {halted,P} -> ok end end, Pids0), + QTot = lists:foldl(fun(P,QSum) -> + {message_queue_len,QLen} = + erlang:process_info(P,message_queue_len), + QSum + QLen + end, 0, Pids0), + io:format("Total queue length ~p\n",[QTot]), + lists:foreach(fun(P) -> P ! die end, Pids0), + send3_controller(SpawnCnt0, Mons0, [], infinity); + {'DOWN', MonRef, process, _Pid, _} -> + Mons1 = lists:delete(MonRef, Mons0), + %%io:format("Got DOWN from ~p. Monitors left: ~p\n",[Pid,Mons1]), + send3_controller(SpawnCnt0, Mons1, Pids0, Tick) + after Tick -> + Max = 20, + N = length(Pids0), + PidN = random:uniform(Max), + %%io:format("N=~p PidN=~p Pids0=~p\n", [N,PidN,Pids0]), + case PidN > N of + true -> + {NewPid,Mon} = spawn_opt(fun send3_proc/0, [link,monitor]), + lists:foreach(fun(P) -> P ! {is_born,NewPid} end, Pids0), + ?line Balance = ets:lookup_element(nif_SUITE,send3,5), + Inject = (Balance =< 0), + case Inject of + true -> ok; + false -> ets:update_element(nif_SUITE,send3,{5,-1}) + end, + NewPid ! {pids,Pids0,Inject}, + send3_controller(SpawnCnt0+1, [Mon|Mons0], [NewPid|Pids0], Tick); + false -> + KillPid = lists:nth(PidN,Pids0), + KillPid ! die, + Pids1 = lists:delete(KillPid, Pids0), + lists:foreach(fun(P) -> P ! {is_dead,KillPid} end, Pids1), + send3_controller(SpawnCnt0, Mons0, Pids1, Tick) + end + end. + +send3_proc() -> + %%io:format("Process ~p spawned\n",[self()]), + send3_proc([self()], {0,0,0}, {1,2,3,4,5}). +send3_proc(Pids0, Counters={Rcv,SndOk,SndFail}, State0) -> + %%io:format("~p: Pids0=~p", [self(), Pids0]), + %%timer:sleep(10), + receive + {pids, Pids1, Inject} -> + %%io:format("~p: got ~p Inject=~p\n", [self(), Pids1, Inject]), + ?line Pids0 = [self()], + Pids2 = [self() | Pids1], + case Inject of + true -> send3_proc_send(Pids2, Counters, State0); + false -> send3_proc(Pids2, Counters, State0) + end; + {is_born, Pid} -> + %%io:format("~p: is_born ~p, got ~p\n", [self(), Pid, Pids0]), + send3_proc([Pid | Pids0], Counters, State0); + {is_dead, Pid} -> + Pids1 = lists:delete(Pid,Pids0), + %%io:format("~p: is_dead ~p, got ~p\n", [self(), Pid, Pids1]), + send3_proc(Pids1, Counters, State0); + {blob, Blob0} -> + %%io:format("~p: blob ~p\n", [self(), Blob0]), + State1 = send3_new_state(State0, Blob0), + send3_proc_send(Pids0, {Rcv+1,SndOk,SndFail}, State1); + die -> + %%io:format("Process ~p terminating, stats = ~p\n",[self(),Counters]), + {message_queue_len,Dropped} = erlang:process_info(self(),message_queue_len), + _R = ets:update_counter(nif_SUITE,send3, + [{2,Rcv},{3,SndOk},{4,SndFail},{5,1-Dropped}]), + %%io:format("~p: dies R=~p\n", [self(), R]), + ok; + {halt,Papa} -> + Papa ! {halted,self()}, + io:format("~p halted\n",[self()]), + receive die -> ok end, + io:format("~p dying\n",[self()]) + end. + +send3_proc_send(Pids, {Rcv,SndOk,SndFail}, State0) -> + To = lists:nth(random:uniform(length(Pids)),Pids), + Blob = send3_make_blob(), + State1 = send3_new_state(State0,Blob), + case send3_send(To, Blob) of + true -> + send3_proc(Pids, {Rcv,SndOk+1,SndFail}, State1); + false -> + send3_proc(Pids, {Rcv,SndOk,SndFail+1}, State1) + end. + + +send3_make_blob() -> + case random:uniform(20)-1 of + 0 -> {term,[]}; + N -> + MsgEnv = alloc_msgenv(), + repeat(N bsr 1, + fun(_) -> grow_blob(MsgEnv,other_term(),random:uniform(1 bsl 20)) + end, void), + case (N band 1) of + 0 -> {term,copy_blob(MsgEnv)}; + 1 -> {msgenv,MsgEnv} + end + end. + +send3_send(Pid, Msg) -> + %% 90% enif_send and 10% normal bang + case random:uniform(10) of + 1 -> send3_send_bang(Pid,Msg); + _ -> send3_send_nif(Pid,Msg) + end. +send3_send_nif(Pid, {term,Blob}) -> + %%io:format("~p send term nif\n",[self()]), + send_term(Pid, {blob, Blob}) =:= 1; +send3_send_nif(Pid, {msgenv,MsgEnv}) -> + %%io:format("~p send blob nif\n",[self()]), + send3_blob(MsgEnv, Pid, blob) =:= 1. + +send3_send_bang(Pid, {term,Blob}) -> + %%io:format("~p send term bang\n",[self()]), + Pid ! {blob, Blob}, + true; +send3_send_bang(Pid, {msgenv,MsgEnv}) -> + %%io:format("~p send blob bang\n",[self()]), + Pid ! {blob, copy_blob(MsgEnv)}, + true. + +send3_new_state(State, Blob) -> + case random:uniform(5+2) of + N when N =< 5-> setelement(N, State, Blob); + _ -> State % Don't store blob + end. + neg(doc) -> ["Negative testing of load_nif"]; neg(Config) when is_list(Config) -> TmpMem = tmpmem(), @@ -1070,10 +1227,13 @@ send_new_blob(_,_) -> ?nif_stub. alloc_msgenv() -> ?nif_stub. clear_msgenv(_) -> ?nif_stub. grow_blob(_,_) -> ?nif_stub. +grow_blob(_,_,_) -> ?nif_stub. send_blob(_,_) -> ?nif_stub. +send3_blob(_,_,_) -> ?nif_stub. send_blob_thread(_,_,_) -> ?nif_stub. join_send_thread(_) -> ?nif_stub. - +copy_blob(_) -> ?nif_stub. +send_term(_,_) -> ?nif_stub. nif_stub_error(Line) -> exit({nif_not_loaded,module,?MODULE,line,Line}). diff --git a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c index c8cd323b7e..17f644829f 100644 --- a/erts/emulator/test/nif_SUITE_data/nif_SUITE.c +++ b/erts/emulator/test/nif_SUITE_data/nif_SUITE.c @@ -1038,36 +1038,41 @@ static ERL_NIF_TERM make_term_copy(struct make_term_info* mti, int n) { return enif_make_copy(mti->dst_env, mti->other_term); } + +typedef ERL_NIF_TERM Make_term_Func(struct make_term_info*, int); +static Make_term_Func* make_funcs[] = { + make_term_binary, + make_term_int, + make_term_ulong, + make_term_double, + make_term_atom, + make_term_existing_atom, + make_term_string, + //make_term_ref, + make_term_sub_binary, + make_term_uint, + make_term_long, + make_term_tuple0, + make_term_list0, + make_term_resource, + make_term_new_binary, + make_term_caller_pid, + make_term_tuple, + make_term_list, + make_term_list_cell, + make_term_tuple_from_array, + make_term_list_from_array, + make_term_garbage, + make_term_copy +}; +static unsigned num_of_make_funcs() +{ + return sizeof(make_funcs)/sizeof(*make_funcs); +} static int make_term_n(struct make_term_info* mti, int n, ERL_NIF_TERM* res) { - typedef ERL_NIF_TERM Make_term_Func(struct make_term_info*, int); - static Make_term_Func* funcs[] = { - make_term_binary, - make_term_int, - make_term_ulong, - make_term_double, - make_term_atom, - make_term_existing_atom, - make_term_string, - //make_term_ref, - make_term_sub_binary, - make_term_uint, - make_term_long, - make_term_tuple0, - make_term_list0, - make_term_resource, - make_term_new_binary, - make_term_caller_pid, - make_term_tuple, - make_term_list, - make_term_list_cell, - make_term_tuple_from_array, - make_term_list_from_array, - make_term_garbage, - make_term_copy - }; - if (n < sizeof(funcs)/sizeof(*funcs)) { - *res = funcs[n](mti, n); + if (n < num_of_make_funcs()) { + *res = make_funcs[n](mti, n); push_term(mti, *res); return 1; } @@ -1167,14 +1172,14 @@ static ERL_NIF_TERM grow_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ { union { void* vp; struct make_term_info* p; }mti; ERL_NIF_TERM term; - if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)) { + if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp) + || (argc>2 && !enif_get_uint(env,argv[2], &mti.p->n))) { return enif_make_badarg(env); } mti.p->caller_env = env; mti.p->other_term = argv[1]; - while (!make_term_n(mti.p, mti.p->n++, &term)) { - mti.p->n = 0; - } + mti.p->n %= num_of_make_funcs(); + make_term_n(mti.p, mti.p->n++, &term); mti.p->blob = enif_make_list_cell(mti.p->dst_env, term, mti.p->blob); return atom_ok; } @@ -1194,6 +1199,23 @@ static ERL_NIF_TERM send_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ return enif_make_tuple3(env, atom_ok, enif_make_int(env,res), copy); } +static ERL_NIF_TERM send3_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + union { void* vp; struct make_term_info* p; }mti; + ErlNifPid to; + ERL_NIF_TERM copy; + int res; + if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp) + || !enif_get_local_pid(env, argv[1], &to)) { + return enif_make_badarg(env); + } + mti.p->blob = enif_make_tuple2(mti.p->dst_env, + enif_make_copy(mti.p->dst_env, argv[2]), + mti.p->blob); + res = enif_send(env, &to, mti.p->dst_env, mti.p->blob); + return enif_make_int(env,res); +} + void* threaded_sender(void *arg) { @@ -1253,6 +1275,28 @@ static ERL_NIF_TERM join_send_thread(ErlNifEnv* env, int argc, const ERL_NIF_TER return enif_make_tuple2(env, atom_ok, enif_make_int(env, mti.p->send_res)); } +static ERL_NIF_TERM copy_blob(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + union { void* vp; struct make_term_info* p; }mti; + if (!enif_get_resource(env, argv[0], msgenv_resource_type, &mti.vp)) { + return enif_make_badarg(env); + } + return enif_make_copy(env, mti.p->blob); +} + +static ERL_NIF_TERM send_term(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifEnv* menv; + ErlNifPid pid; + int ret; + if (!enif_get_local_pid(env, argv[0], &pid)) { + return enif_make_badarg(env); + } + menv = enif_alloc_env(); + ret = enif_send(env, &pid, menv, enif_make_copy(menv, argv[1])); + enif_free_env(menv); + return enif_make_int(env, ret); +} static ErlNifFunc nif_funcs[] = { @@ -1291,9 +1335,13 @@ static ErlNifFunc nif_funcs[] = {"alloc_msgenv", 0, alloc_msgenv}, {"clear_msgenv", 1, clear_msgenv}, {"grow_blob", 2, grow_blob}, + {"grow_blob", 3, grow_blob}, {"send_blob", 2, send_blob}, + {"send3_blob", 3, send3_blob}, {"send_blob_thread", 3, send_blob_thread}, - {"join_send_thread", 1, join_send_thread} + {"join_send_thread", 1, join_send_thread}, + {"copy_blob", 1, copy_blob}, + {"send_term", 2, send_term} }; ERL_NIF_INIT(nif_SUITE,nif_funcs,load,reload,upgrade,unload) diff --git a/erts/emulator/test/obsolete_SUITE.erl b/erts/emulator/test/obsolete_SUITE.erl deleted file mode 100644 index b191f84ee0..0000000000 --- a/erts/emulator/test/obsolete_SUITE.erl +++ /dev/null @@ -1,123 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2004-2010. 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% -%% - - --module(obsolete_SUITE). --author('[email protected]'). --compile(nowarn_obsolete_guard). - --export([all/1]). - --export([erl_threads/1]). - --include("test_server.hrl"). - --define(DEFAULT_TIMETRAP_SECS, 240). - -all(doc) -> []; -all(suite) -> - case catch erlang:system_info({wordsize,external}) of - 4 -> [erl_threads]; - _ -> {skip, "Only expected to work on true 32-bit architectures"} - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% Testcases %% -%% %% - -erl_threads(suite) -> []; -erl_threads(doc) -> []; -erl_threads(Cfg) -> - ?line case erlang:system_info(threads) of - true -> - ?line drv_case(Cfg, erl_threads); - false -> - ?line {skip, "Emulator not compiled with threads support"} - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% Internal functions %% -%% %% - -drv_case(Config, CaseName) -> - drv_case(Config, CaseName, ""). - -drv_case(Config, CaseName, TimeTrap) when integer(TimeTrap) -> - drv_case(Config, CaseName, "", TimeTrap); -drv_case(Config, CaseName, Command) when list(Command) -> - drv_case(Config, CaseName, Command, ?DEFAULT_TIMETRAP_SECS). - -drv_case(Config, CaseName, TimeTrap, Command) when list(Command), - integer(TimeTrap) -> - drv_case(Config, CaseName, Command, TimeTrap); -drv_case(Config, CaseName, Command, TimeTrap) when list(Config), - atom(CaseName), - list(Command), - integer(TimeTrap) -> - case ?t:os_type() of - {Family, _} when Family == unix; Family == win32 -> - ?line run_drv_case(Config, CaseName, Command, TimeTrap); - SkipOs -> - ?line {skipped, - lists:flatten(["Not run on " - | io_lib:format("~p",[SkipOs])])} - end. - -run_drv_case(Config, CaseName, Command, TimeTrap) -> - ?line Dog = test_server:timetrap(test_server:seconds(TimeTrap)), - ?line DataDir = ?config(data_dir,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() - 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 test_server:timetrap_cancel(Dog), - ?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. diff --git a/erts/emulator/test/obsolete_SUITE_data/Makefile.src b/erts/emulator/test/obsolete_SUITE_data/Makefile.src deleted file mode 100644 index d8e2b861c0..0000000000 --- a/erts/emulator/test/obsolete_SUITE_data/Makefile.src +++ /dev/null @@ -1,33 +0,0 @@ -# ``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 via the world wide web 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. -# -# The Initial Developer of the Original Code is Ericsson Utvecklings AB. -# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -# AB. All Rights Reserved.'' -# -# $Id$ -# - -TEST_DRVS = erl_threads@dll@ -CC = @CC@ -LD = @LD@ -CFLAGS = @SHLIB_CFLAGS@ -I@erl_include@ @DEFS@ -SHLIB_EXTRA_LDLIBS = testcase_driver@obj@ - -all: $(TEST_DRVS) - -@SHLIB_RULES@ - -testcase_driver@obj@: testcase_driver.c testcase_driver.h -$(TEST_DRVS): testcase_driver@obj@ - - - diff --git a/erts/emulator/test/obsolete_SUITE_data/erl_threads.c b/erts/emulator/test/obsolete_SUITE_data/erl_threads.c deleted file mode 100644 index 27a5163121..0000000000 --- a/erts/emulator/test/obsolete_SUITE_data/erl_threads.c +++ /dev/null @@ -1,302 +0,0 @@ -/* ``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 via the world wide web 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. - * - * The Initial Developer of the Original Code is Ericsson Utvecklings AB. - * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings - * AB. All Rights Reserved.'' - * - * $Id$ - */ - -#include "testcase_driver.h" - -#ifndef __WIN32__ - -#define NO_OF_THREADS 2 - -#include <unistd.h> -#include <errno.h> - -static int die; -static int cw_passed; -static int res_tf0; -static int res_tf1; -static erl_mutex_t mtx; -static erl_cond_t cnd; -static erl_thread_t tid[NO_OF_THREADS]; -static int need_join[NO_OF_THREADS]; - -typedef struct { - int n; -} thr_arg_t; - - -static void *tf0(void *vta) -{ - int r; - - if (((thr_arg_t *) vta)->n != 0) - goto fail; - - r = erts_mutex_lock(mtx); - if (r != 0) { - erts_mutex_unlock(mtx); - goto fail; - } - - r = erts_cond_wait(cnd, mtx); - if (r != 0 || die) { - erts_mutex_unlock(mtx); - goto fail; - } - - cw_passed++; - - r = erts_cond_wait(cnd, mtx); - if (r != 0 || die) { - erts_mutex_unlock(mtx); - goto fail; - } - - cw_passed++; - - r = erts_mutex_unlock(mtx); - if (r != 0) - goto fail; - - res_tf0 = 0; - - return (void *) &res_tf0; - - fail: - return NULL; -} - - -static void *tf1(void *vta) -{ - int r; - - if (((thr_arg_t *) vta)->n != 1) - goto fail; - - r = erts_mutex_lock(mtx); - if (r != 0) { - erts_mutex_unlock(mtx); - goto fail; - } - - r = erts_cond_wait(cnd, mtx); - if (r != 0 || die) { - erts_mutex_unlock(mtx); - goto fail; - } - - cw_passed++; - - r = erts_cond_wait(cnd, mtx); - if (r != 0 || die) { - erts_mutex_unlock(mtx); - goto fail; - } - - cw_passed++; - - r = erts_mutex_unlock(mtx); - if (r != 0) - goto fail; - - res_tf1 = 1; - - erts_thread_exit((void *) &res_tf1); - - res_tf1 = 4711; - - fail: - return NULL; -} - -#endif /* #ifndef __WIN32__ */ - -void -testcase_run(TestCaseState_t *tcs) -{ -#ifdef __WIN32__ - testcase_skipped(tcs, "Nothing to test; not supported on windows."); -#else - int i, r; - void *tres[NO_OF_THREADS]; - thr_arg_t ta[NO_OF_THREADS]; - erl_thread_t t1; - - die = 0; - cw_passed = 0; - - for (i = 0; i < NO_OF_THREADS; i++) - need_join[i] = 0; - - res_tf0 = 17; - res_tf1 = 17; - - cnd = mtx = NULL; - - /* Create mutex and cond */ - mtx = erts_mutex_create(); - ASSERT(tcs, mtx); - cnd = erts_cond_create(); - ASSERT(tcs, cnd); - - /* Create the threads */ - ta[0].n = 0; - r = erts_thread_create(&tid[0], tf0, (void *) &ta[0], 0); - ASSERT(tcs, r == 0); - need_join[0] = 1; - - ta[1].n = 1; - r = erts_thread_create(&tid[1], tf1, (void *) &ta[1], 0); - ASSERT(tcs, r == 0); - need_join[1] = 1; - - /* Make sure the threads waits on cond wait */ - sleep(1); - - r = erts_mutex_lock(mtx); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - - ASSERT_CLNUP(tcs, cw_passed == 0, (void) erts_mutex_unlock(mtx)); - - - /* Let one thread pass one cond wait */ - r = erts_cond_signal(cnd); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - - r = erts_mutex_unlock(mtx); - ASSERT(tcs, r == 0); - - sleep(1); - - r = erts_mutex_lock(mtx); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - - ASSERT_CLNUP(tcs, cw_passed == 1, (void) erts_mutex_unlock(mtx)); - - - /* Let both threads pass one cond wait */ - r = erts_cond_broadcast(cnd); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - - r = erts_mutex_unlock(mtx); - ASSERT(tcs, r == 0); - - sleep(1); - - r = erts_mutex_lock(mtx); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - - ASSERT_CLNUP(tcs, cw_passed == 3, (void) erts_mutex_unlock(mtx)); - - - /* Let the thread that only have passed one cond wait pass the other one */ - r = erts_cond_signal(cnd); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - - r = erts_mutex_unlock(mtx); - ASSERT(tcs, r == 0); - - sleep(1); - - r = erts_mutex_lock(mtx); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - - ASSERT_CLNUP(tcs, cw_passed == 4, (void) erts_mutex_unlock(mtx)); - - /* Both threads should have passed both cond waits and exited; - join them and check returned values */ - - r = erts_thread_join(tid[0], &tres[0]); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - need_join[0] = 0; - - ASSERT_CLNUP(tcs, tres[0] == &res_tf0, (void) erts_mutex_unlock(mtx)); - ASSERT_CLNUP(tcs, res_tf0 == 0, (void) erts_mutex_unlock(mtx)); - - r = erts_thread_join(tid[1], &tres[1]); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - need_join[1] = 0; - - ASSERT_CLNUP(tcs, tres[1] == &res_tf1, (void) erts_mutex_unlock(mtx)); - ASSERT_CLNUP(tcs, res_tf1 == 1, (void) erts_mutex_unlock(mtx)); - - /* Test signaling when noone waits */ - - r = erts_cond_signal(cnd); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - - /* Test broadcasting when noone waits */ - - r = erts_cond_broadcast(cnd); - ASSERT_CLNUP(tcs, r == 0, (void) erts_mutex_unlock(mtx)); - - /* erts_cond_timedwait() not supported anymore */ - r = erts_cond_timedwait(cnd, mtx, 1000); - ASSERT_CLNUP(tcs, r != 0, (void) erts_mutex_unlock(mtx)); - ASSERT_CLNUP(tcs, - strcmp(erl_errno_id(r), "enotsup") == 0, - (void) erts_mutex_unlock(mtx)); - - r = erts_mutex_unlock(mtx); - ASSERT(tcs, r == 0); - - r = erts_mutex_destroy(mtx); - ASSERT(tcs, r == 0); - mtx = NULL; - - r = erts_cond_destroy(cnd); - ASSERT(tcs, r == 0); - cnd = NULL; - - /* ... */ - t1 = erts_thread_self(); - - if (cw_passed == 4711) { - /* We don't want to execute this just check that the - symbol/symbols is/are defined */ - erts_thread_kill(t1); - } - -#endif /* #ifndef __WIN32__ */ -} - -char * -testcase_name(void) -{ - return "erl_threads"; -} - -void -testcase_cleanup(TestCaseState_t *tcs) -{ - int i; - for (i = 0; i < NO_OF_THREADS; i++) { - if (need_join[i]) { - erts_mutex_lock(mtx); - die = 1; - erts_cond_broadcast(cnd); - erts_mutex_unlock(mtx); - erts_thread_join(tid[1], NULL); - } - } - if (mtx) - erts_mutex_destroy(mtx); - if (cnd) - erts_cond_destroy(cnd); -} - diff --git a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c deleted file mode 100644 index 99d5adb041..0000000000 --- a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.c +++ /dev/null @@ -1,262 +0,0 @@ -/* ``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 via the world wide web 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. - * - * The Initial Developer of the Original Code is Ericsson Utvecklings AB. - * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings - * AB. All Rights Reserved.'' - * - * $Id$ - */ - -#include "testcase_driver.h" -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <setjmp.h> -#include <string.h> - -#ifdef __WIN32__ -#undef HAVE_VSNPRINTF -#define HAVE_VSNPRINTF 1 -#define vsnprintf _vsnprintf -#endif - -#ifndef HAVE_VSNPRINTF -#define HAVE_VSNPRINTF 0 -#endif - -#define COMMENT_BUF_SZ 4096 - -#define TESTCASE_FAILED 0 -#define TESTCASE_SKIPPED 1 -#define TESTCASE_SUCCEEDED 2 - -typedef struct { - TestCaseState_t visible; - int port; - int result; - jmp_buf done_jmp_buf; - char *comment; - char comment_buf[COMMENT_BUF_SZ]; -} InternalTestCaseState_t; - -long testcase_drv_start(int port, char *command); -int testcase_drv_stop(long drv_data); -int testcase_drv_run(long drv_data, char *buf, int len); - -static DriverEntry testcase_drv_entry = { - NULL, - testcase_drv_start, - testcase_drv_stop, - testcase_drv_run -}; - - -int DRIVER_INIT(testcase_drv)(void *arg) -{ - testcase_drv_entry.driver_name = testcase_name(); - return (int) &testcase_drv_entry; -} - -long -testcase_drv_start(int port, char *command) -{ - InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) - driver_alloc(sizeof(InternalTestCaseState_t)); - if (!itcs) { - return -1; - } - - itcs->visible.testcase_name = testcase_name(); - itcs->visible.extra = NULL; - itcs->port = port; - itcs->result = TESTCASE_FAILED; - itcs->comment = ""; - - return (long) itcs; -} - -int -testcase_drv_stop(long drv_data) -{ - testcase_cleanup((TestCaseState_t *) drv_data); - driver_free((void *) drv_data); - return 0; -} - -int -testcase_drv_run(long drv_data, char *buf, int len) -{ - InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) drv_data; - DriverTermData result_atom; - DriverTermData msg[12]; - - itcs->visible.command = buf; - itcs->visible.command_len = len; - - if (setjmp(itcs->done_jmp_buf) == 0) { - testcase_run((TestCaseState_t *) itcs); - 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: - default: - result_atom = driver_mk_atom("failed"); - break; - } - - msg[0] = ERL_DRV_ATOM; - msg[1] = (DriverTermData) result_atom; - - msg[2] = ERL_DRV_PORT; - msg[3] = driver_mk_port(itcs->port); - - msg[4] = ERL_DRV_ATOM; - msg[5] = driver_mk_atom(itcs->visible.testcase_name); - - msg[6] = ERL_DRV_STRING; - msg[7] = (DriverTermData) itcs->comment; - msg[8] = (DriverTermData) strlen(itcs->comment); - - msg[9] = ERL_DRV_TUPLE; - msg[10] = (DriverTermData) 4; - - driver_output_term(itcs->port, msg, 11); - return 0; -} - -int -testcase_assertion_failed(TestCaseState_t *tcs, - char *file, int line, char *assertion) -{ - testcase_failed(tcs, "%s:%d: Assertion failed: \"%s\"", - file, line, assertion); - return 0; -} - -void -testcase_printf(TestCaseState_t *tcs, char *frmt, ...) -{ - InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; - DriverTermData msg[12]; - 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 - va_end(va); - - msg[0] = ERL_DRV_ATOM; - msg[1] = (DriverTermData) driver_mk_atom("print"); - - msg[2] = ERL_DRV_PORT; - msg[3] = driver_mk_port(itcs->port); - - msg[4] = ERL_DRV_ATOM; - msg[5] = driver_mk_atom(itcs->visible.testcase_name); - - msg[6] = ERL_DRV_STRING; - msg[7] = (DriverTermData) itcs->comment_buf; - msg[8] = (DriverTermData) strlen(itcs->comment_buf); - - msg[9] = ERL_DRV_TUPLE; - msg[10] = (DriverTermData) 4; - - driver_output_term(itcs->port, msg, 11); -} - - -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 - va_end(va); - - itcs->result = TESTCASE_SUCCEEDED; - itcs->comment = itcs->comment_buf; - - longjmp(itcs->done_jmp_buf, 1); -} - -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 - va_end(va); - - itcs->result = TESTCASE_SKIPPED; - itcs->comment = itcs->comment_buf; - - longjmp(itcs->done_jmp_buf, 1); -} - -void testcase_failed(TestCaseState_t *tcs, char *frmt, ...) -{ - InternalTestCaseState_t *itcs = (InternalTestCaseState_t *) tcs; - char buf[10]; - 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 - va_end(va); - - itcs->result = TESTCASE_FAILED; - itcs->comment = itcs->comment_buf; - - if (erl_drv_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); -} - -void *testcase_alloc(size_t size) -{ - return driver_alloc(size); -} - -void *testcase_realloc(void *ptr, size_t size) -{ - return driver_realloc(ptr, size); -} - -void testcase_free(void *ptr) -{ - driver_free(ptr); -} diff --git a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h b/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h deleted file mode 100644 index 3d85ca6df0..0000000000 --- a/erts/emulator/test/obsolete_SUITE_data/testcase_driver.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ``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 via the world wide web 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. - * - * The Initial Developer of the Original Code is Ericsson Utvecklings AB. - * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings - * AB. All Rights Reserved.'' - * - * $Id$ - */ - -#ifndef TESTCASE_DRIVER_H__ -#define TESTCASE_DRIVER_H__ - -#include "obsolete/driver.h" -#include <stdlib.h> - -typedef struct { - char *testcase_name; - char *command; - int command_len; - void *extra; -} TestCaseState_t; - -#define ASSERT_CLNUP(TCS, B, CLN) \ -do { \ - if (!(B)) { \ - CLN; \ - testcase_assertion_failed((TCS), __FILE__, __LINE__, #B); \ - } \ -} while (0) - -#define ASSERT(TCS, B) ASSERT_CLNUP(TCS, B, (void) 0) - -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_failed(TestCaseState_t *tcs, char *frmt, ...); -int testcase_assertion_failed(TestCaseState_t *tcs, char *file, int line, - char *assertion); -void *testcase_alloc(size_t size); -void *testcase_realloc(void *ptr, size_t size); -void testcase_free(void *ptr); - - -char *testcase_name(void); -void testcase_run(TestCaseState_t *tcs); -void testcase_cleanup(TestCaseState_t *tcs); - -#endif diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index ab727b7cb1..4f4458802c 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -33,7 +33,7 @@ -include("test_server.hrl"). %-compile(export_all). --export([all/1, init_per_testcase/2, fin_per_testcase/2]). +-export([all/1, init_per_testcase/2, fin_per_testcase/2, end_per_suite/1]). -export([equal/1, few_low/1, @@ -49,7 +49,8 @@ cpu_topology/1, sct_cmd/1, sbt_cmd/1, - scheduler_suspend/1]). + scheduler_suspend/1, + reader_groups/1]). -define(DEFAULT_TIMEOUT, ?t:minutes(10)). @@ -67,7 +68,8 @@ all(suite) -> equal_with_high_max, bound_process, scheduler_bind, - scheduler_suspend]. + scheduler_suspend, + reader_groups]. init_per_testcase(Case, Config) when is_list(Config) -> Dog = ?t:timetrap(?DEFAULT_TIMEOUT), @@ -81,6 +83,10 @@ fin_per_testcase(_Case, Config) when is_list(Config) -> ?t:timetrap_cancel(Dog), ok. +end_per_suite(Config) -> + catch erts_debug:set_internal_state(available_internal_state, false), + Config. + -define(ERTS_RUNQ_CHECK_BALANCE_REDS_PER_SCHED, (2000*2000)). -define(DEFAULT_TEST_REDS_PER_SCHED, 200000000). @@ -965,12 +971,361 @@ sst3_loop(S, N) -> erlang:system_flag(schedulers_online, 1), erlang:system_flag(schedulers_online, S), sst3_loop(S, N-1). + +reader_groups(Config) when is_list(Config) -> + %% White box testing. These results are correct, but other results + %% could be too... + + %% 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), + + 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), + + 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))])], + + ?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), + + 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. +reader_groups_map(CPUT, Groups) -> + Old = erlang:system_info({cpu_topology, defined}), + erlang:system_flag(cpu_topology, CPUT), + enable_internal_state(), + Res = erts_debug:get_internal_state({reader_groups_map, Groups}), + erlang:system_flag(cpu_topology, Old), + lists:sort(Res). + %% %% Utils %% +tilera_cpu_topology() -> + [{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}}]}]}]. + +l(Id) -> + {logical, Id}. + +t(X) -> + {thread, X}. + +c(X) -> + {core, X}. + +p(X) -> + {processor, X}. + +n(X) -> + {node, X}. + mcall(Node, Funs) -> Parent = self(), Refs = lists:map(fun (Fun) -> diff --git a/erts/emulator/test/send_term_SUITE.erl b/erts/emulator/test/send_term_SUITE.erl index 489adbd660..5fd01a9ac5 100644 --- a/erts/emulator/test/send_term_SUITE.erl +++ b/erts/emulator/test/send_term_SUITE.erl @@ -76,40 +76,43 @@ basic(Config) when is_list(Config) -> ?line ExpectedBinTup = term(P, 7), %% single terms - ?line [] = term(P, 8), % ERL_DRV_NIL - ?line '' = term(P, 9), % ERL_DRV_ATOM - ?line an_atom = term(P, 10), % ERL_DRV_ATOM - ?line -4711 = term(P, 11), % ERL_DRV_INT - ?line 4711 = term(P, 12), % ERL_DRV_UINT - ?line P = term(P, 13), % ERL_DRV_PORT - ?line <<>> = term(P, 14), % ERL_DRV_BINARY - ?line <<"hejsan">> = term(P, 15), % ERL_DRV_BINARY - ?line <<>> = term(P, 16), % ERL_DRV_BUF2BINARY - ?line <<>> = term(P, 17), % ERL_DRV_BUF2BINARY - ?line <<"hoppsan">> = term(P, 18), % ERL_DRV_BUF2BINARY - ?line "" = term(P, 19), % ERL_DRV_STRING - ?line "" = term(P, 20), % ERL_DRV_STRING - ?line "hippsan" = term(P, 21), % ERL_DRV_STRING - ?line {} = term(P, 22), % ERL_DRV_TUPLE - ?line [] = term(P, 23), % ERL_DRV_LIST - ?line Self = term(P, 24), % ERL_DRV_PID - ?line [] = term(P, 25), % ERL_DRV_STRING_CONS - ?line AFloat = term(P, 26), % ERL_DRV_FLOAT + Singles = [{[], 8}, % ERL_DRV_NIL + {'', 9}, % ERL_DRV_ATOM + {an_atom, 10}, % ERL_DRV_ATOM + {-4711, 11}, % ERL_DRV_INT + {4711, 12}, % ERL_DRV_UINT + {P, 13}, % ERL_DRV_PORT + {<<>>, 14}, % ERL_DRV_BINARY + {<<"hejsan">>, 15}, % ERL_DRV_BINARY + {<<>>, 16}, % ERL_DRV_BUF2BINARY + {<<>>, 17}, % ERL_DRV_BUF2BINARY + {<<"hoppsan">>, 18}, % ERL_DRV_BUF2BINARY + {"", 19}, % ERL_DRV_STRING + {"", 20}, % ERL_DRV_STRING + {"hippsan", 21}, % ERL_DRV_STRING + {{}, 22}, % ERL_DRV_TUPLE + {[], 23}, % ERL_DRV_LIST + {Self, 24}, % ERL_DRV_PID + {[], 25}, % ERL_DRV_STRING_CONS + {[], 27}, % ERL_DRV_EXT2TERM + {18446744073709551615, 28}, % ERL_DRV_UINT64 + {20233590931456, 29}, % ERL_DRV_UINT64 + {4711, 30}, % ERL_DRV_UINT64 + {0, 31}, % ERL_DRV_UINT64 + {9223372036854775807, 32}, % ERL_DRV_INT64 + {20233590931456, 33}, % ERL_DRV_INT64 + {4711, 34}, % ERL_DRV_INT64 + {0, 35}, % ERL_DRV_INT64 + {-1, 36}, % ERL_DRV_INT64 + {-4711, 37}, % ERL_DRV_INT64 + {-20233590931456, 38}, % ERL_DRV_INT64 + {-9223372036854775808, 39}], % ERL_DRV_INT64 + ?line {Terms, Ops} = lists:unzip(Singles), + ?line Terms = term(P,Ops), + + AFloat = term(P, 26), % ERL_DRV_FLOAT ?line true = AFloat < 0.001, ?line true = AFloat > -0.001, - ?line [] = term(P, 27), % ERL_DRV_EXT2TERM - ?line 18446744073709551615 = term(P, 28), % ERL_DRV_UINT64 - ?line 20233590931456 = term(P, 29), % ERL_DRV_UINT64 - ?line 4711 = term(P, 30), % ERL_DRV_UINT64 - ?line 0 = term(P, 31), % ERL_DRV_UINT64 - ?line 9223372036854775807 = term(P, 32), % ERL_DRV_INT64 - ?line 20233590931456 = term(P, 33), % ERL_DRV_INT64 - ?line 4711 = term(P, 34), % ERL_DRV_INT64 - ?line 0 = term(P, 35), % ERL_DRV_INT64 - ?line -1 = term(P, 36), % ERL_DRV_INT64 - ?line -4711 = term(P, 37), % ERL_DRV_INT64 - ?line -20233590931456 = term(P, 38), % ERL_DRV_INT64 - ?line -9223372036854775808 = term(P, 39), % ERL_DRV_INT64 %% Failure cases. ?line [] = term(P, 127), diff --git a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c index 6638de0560..165cce2e9d 100644 --- a/erts/emulator/test/send_term_SUITE_data/send_term_drv.c +++ b/erts/emulator/test/send_term_SUITE_data/send_term_drv.c @@ -17,6 +17,7 @@ */ #include "erl_driver.h" +#include <stdio.h> #include <errno.h> #include <string.h> @@ -65,12 +66,21 @@ static void fail_term(ErlDrvTermData* msg, int len, int line); static void send_term_drv_run(ErlDrvData port, char *buf, int count) { - ErlDrvTermData msg[1024]; - - switch (*buf) { + char buf7[1024]; + ErlDrvTermData spec[1024]; + ErlDrvTermData* msg = spec; + ErlDrvBinary* bins[15]; + int bin_ix = 0; + ErlDrvSInt64 s64[15]; + int s64_ix = 0; + ErlDrvUInt64 u64[15]; + int u64_ix = 0; + int i = 0; + + for (i=0; i<count; i++) switch (buf[i]) { case 0: msg[0] = ERL_DRV_NIL; - output_term(msg, 1); + msg += 1; break; case 1: /* Most term types inside a tuple. */ @@ -102,7 +112,7 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) msg[22] = driver_connected(erlang_port); msg[23] = ERL_DRV_TUPLE; msg[24] = (ErlDrvTermData) 7; - output_term(msg, 25); + msg += 25; } break; @@ -117,7 +127,7 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) msg[i] = ERL_DRV_NIL; msg[i+1] = ERL_DRV_LIST; msg[i+2] = (ErlDrvTermData) 201; - output_term(msg, i+3); + msg += i+3; } break; @@ -126,7 +136,7 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) ErlDrvBinary* bin; int i; - bin = driver_alloc_binary(256); + bin = bins[bin_ix++] = driver_alloc_binary(256); for (i = 0; i < 256; i++) { bin->orig_bytes[i] = i; } @@ -140,8 +150,7 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) msg[7] = (ErlDrvTermData) 23; msg[8] = ERL_DRV_TUPLE; msg[9] = (ErlDrvTermData) 2; - output_term(msg, 10); - driver_free_binary(bin); + msg += 10; } break; @@ -152,11 +161,11 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) msg[3] = driver_caller(erlang_port); msg[4] = ERL_DRV_TUPLE; msg[5] = (ErlDrvTermData) 2; - output_term(msg, 6); + msg += 6; break; case 5: - output_term(msg, make_ext_term_list(msg, 0)); + msg += make_ext_term_list(msg, 0); break; case 6: @@ -166,94 +175,91 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) msg[3] = ~((ErlDrvTermData) 0); msg[4] = ERL_DRV_TUPLE; msg[5] = (ErlDrvTermData) 2; - output_term(msg, 6); + msg += 6; break; case 7: { int len = 0; - char buf[1024]; - memset(buf, 17, sizeof(buf)); + memset(buf7, 17, sizeof(buf7)); /* empty heap binary */ msg[len++] = ERL_DRV_BUF2BINARY; msg[len++] = (ErlDrvTermData) NULL; /* NULL is ok if size == 0 */ msg[len++] = (ErlDrvTermData) 0; /* empty heap binary again */ msg[len++] = ERL_DRV_BUF2BINARY; - msg[len++] = (ErlDrvTermData) &buf[0]; /* ptr is ok if size == 0 */ + msg[len++] = (ErlDrvTermData) buf7; /* ptr is ok if size == 0 */ msg[len++] = (ErlDrvTermData) 0; /* heap binary */ msg[len++] = ERL_DRV_BUF2BINARY; - msg[len++] = (ErlDrvTermData) &buf[0]; + msg[len++] = (ErlDrvTermData) buf7; msg[len++] = (ErlDrvTermData) 17; /* off heap binary */ msg[len++] = ERL_DRV_BUF2BINARY; - msg[len++] = (ErlDrvTermData) &buf[0]; - msg[len++] = (ErlDrvTermData) sizeof(buf); + msg[len++] = (ErlDrvTermData) buf7; + msg[len++] = (ErlDrvTermData) sizeof(buf7); msg[len++] = ERL_DRV_TUPLE; msg[len++] = (ErlDrvTermData) 4; - output_term(msg, len); + msg += len; break; } case 8: msg[0] = ERL_DRV_NIL; - output_term(msg, 1); + msg += 1; break; case 9: msg[0] = ERL_DRV_ATOM; msg[1] = (ErlDrvTermData) driver_mk_atom(""); - output_term(msg, 2); + msg += 2; break; case 10: msg[0] = ERL_DRV_ATOM; msg[1] = (ErlDrvTermData) driver_mk_atom("an_atom"); - output_term(msg, 2); + msg += 2; break; case 11: msg[0] = ERL_DRV_INT; msg[1] = (ErlDrvTermData) -4711; - output_term(msg, 2); + msg += 2; break; case 12: msg[0] = ERL_DRV_UINT; msg[1] = (ErlDrvTermData) 4711; - output_term(msg, 2); + msg += 2; break; case 13: msg[0] = ERL_DRV_PORT; msg[1] = driver_mk_port(erlang_port); - output_term(msg, 2); + msg += 2; break; case 14: { - ErlDrvBinary *dbin = driver_alloc_binary(0); + ErlDrvBinary *dbin = bins[bin_ix++] = driver_alloc_binary(0); msg[0] = ERL_DRV_BINARY; msg[1] = (ErlDrvTermData) dbin; msg[2] = (ErlDrvTermData) 0; msg[3] = (ErlDrvTermData) 0; - output_term(msg, 4); - driver_free_binary(dbin); + msg += 4; break; } case 15: { - char buf[] = "hejsan"; - ErlDrvBinary *dbin = driver_alloc_binary(sizeof(buf)-1); + static const char buf[] = "hejsan"; + ErlDrvBinary *dbin = bins[bin_ix++] = driver_alloc_binary(sizeof(buf)-1); if (dbin) memcpy((void *) dbin->orig_bytes, (void *) buf, sizeof(buf)-1); msg[0] = ERL_DRV_BINARY; msg[1] = (ErlDrvTermData) dbin; msg[2] = (ErlDrvTermData) (dbin ? sizeof(buf)-1 : 0); msg[3] = (ErlDrvTermData) 0; - output_term(msg, 4); - driver_free_binary(dbin); + msg += 4; break; } @@ -261,24 +267,24 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) msg[0] = ERL_DRV_BUF2BINARY; msg[1] = (ErlDrvTermData) NULL; msg[2] = (ErlDrvTermData) 0; - output_term(msg, 3); + msg += 3; break; case 17: { - char buf[] = ""; + static const char buf[] = ""; msg[0] = ERL_DRV_BUF2BINARY; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf)-1; - output_term(msg, 3); + msg += 3; break; } case 18: { - char buf[] = "hoppsan"; + static const char buf[] = "hoppsan"; msg[0] = ERL_DRV_BUF2BINARY; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf)-1; - output_term(msg, 3); + msg += 3; break; } @@ -286,44 +292,44 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) msg[0] = ERL_DRV_STRING; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) 0; - output_term(msg, 3); + msg += 3; break; case 20: { - char buf[] = ""; + static const char buf[] = ""; msg[0] = ERL_DRV_STRING; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf)-1; - output_term(msg, 3); + msg += 3; break; } case 21: { - char buf[] = "hippsan"; + static const char buf[] = "hippsan"; msg[0] = ERL_DRV_STRING; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf)-1; - output_term(msg, 3); + msg += 3; break; } case 22: msg[0] = ERL_DRV_TUPLE; msg[1] = (ErlDrvTermData) 0; - output_term(msg, 2); + msg += 2; break; case 23: msg[0] = ERL_DRV_NIL; msg[1] = ERL_DRV_LIST; msg[2] = (ErlDrvTermData) 1; - output_term(msg, 3); + msg += 3; break; case 24: msg[0] = ERL_DRV_PID; msg[1] = driver_connected(erlang_port); - output_term(msg, 2); + msg += 2; break; case 25: @@ -331,132 +337,131 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) msg[1] = ERL_DRV_STRING_CONS; msg[2] = (ErlDrvTermData) ""; msg[3] = (ErlDrvTermData) 0; - output_term(msg, 4); + msg += 4; break; case 26: { - double my_float = 0.0; + static double my_float = 0.0; msg[0] = ERL_DRV_FLOAT; msg[1] = (ErlDrvTermData) &my_float; - output_term(msg, 2); + msg += 2; break; } case 27: { - char buf[] = {131, 106}; /* [] */ + static char buf[] = {131, 106}; /* [] */ msg[0] = ERL_DRV_EXT2TERM; msg[1] = (ErlDrvTermData) buf; msg[2] = (ErlDrvTermData) sizeof(buf); - output_term(msg, 3); + msg += 3; break; } case 28: { - ErlDrvUInt64 x = ~((ErlDrvUInt64) 0); + ErlDrvUInt64* x = &u64[u64_ix++]; + *x = ~((ErlDrvUInt64) 0); msg[0] = ERL_DRV_UINT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 29: { - ErlDrvUInt64 x = ((ErlDrvUInt64) 4711) << 32; + ErlDrvUInt64* x = &u64[u64_ix++]; + *x = ((ErlDrvUInt64) 4711) << 32; msg[0] = ERL_DRV_UINT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 30: { - ErlDrvUInt64 x = 4711; + ErlDrvUInt64* x = &u64[u64_ix++]; + *x = 4711; msg[0] = ERL_DRV_UINT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 31: { - ErlDrvUInt64 x = 0; + ErlDrvUInt64* x = &u64[u64_ix++]; + *x = 0; msg[0] = ERL_DRV_UINT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 32: { - ErlDrvSInt64 x = ((((ErlDrvUInt64) 0x7fffffff) << 32) - | ((ErlDrvUInt64) 0xffffffff)); + ErlDrvSInt64* x = &s64[s64_ix++]; + *x = ((((ErlDrvUInt64) 0x7fffffff) << 32) | ((ErlDrvUInt64) 0xffffffff)); msg[0] = ERL_DRV_INT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 33: { - ErlDrvSInt64 x = (ErlDrvSInt64) (((ErlDrvUInt64) 4711) << 32); + ErlDrvSInt64* x = &s64[s64_ix++]; + *x = (ErlDrvSInt64) (((ErlDrvUInt64) 4711) << 32); msg[0] = ERL_DRV_INT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 34: { - ErlDrvSInt64 x = 4711; + ErlDrvSInt64* x = &s64[s64_ix++]; + *x = 4711; msg[0] = ERL_DRV_INT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 35: { - ErlDrvSInt64 x = 0; + ErlDrvSInt64* x = &s64[s64_ix++]; + *x = 0; msg[0] = ERL_DRV_INT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 36: { - ErlDrvSInt64 x = -1; + ErlDrvSInt64* x = &s64[s64_ix++]; + *x = -1; msg[0] = ERL_DRV_INT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 37: { - ErlDrvSInt64 x = -4711; + ErlDrvSInt64* x = &s64[s64_ix++]; + *x = -4711; msg[0] = ERL_DRV_INT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 38: { - ErlDrvSInt64 x = ((ErlDrvSInt64) ((ErlDrvUInt64) 4711) << 32)*-1; + ErlDrvSInt64* x = &s64[s64_ix++]; + *x = ((ErlDrvSInt64) ((ErlDrvUInt64) 4711) << 32)*-1; msg[0] = ERL_DRV_INT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } case 39: { - ErlDrvSInt64 x = ((ErlDrvSInt64) 1) << 63; + ErlDrvSInt64* x = &s64[s64_ix++]; + *x = ((ErlDrvSInt64) 1) << 63; msg[0] = ERL_DRV_INT64; - msg[1] = (ErlDrvTermData) &x; - output_term(msg, 2); - + msg[1] = (ErlDrvTermData) x; + msg += 2; break; } @@ -464,7 +469,7 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) case 127: /* Error cases */ { long refc; - ErlDrvBinary* bin = driver_alloc_binary(256); + ErlDrvBinary* bin = bins[bin_ix++] = driver_alloc_binary(256); FAIL_TERM(msg, 0); @@ -537,7 +542,7 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) refc = driver_binary_get_refc(bin); if (refc > 3) { char sbuf[128]; - sprintf(sbuf, "bad_refc:%d", refc); + sprintf(sbuf, "bad_refc:%ld", refc); driver_failure_atom(erlang_port, sbuf); } driver_free_binary(bin); @@ -644,6 +649,7 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) /* Signal end of test case */ msg[0] = ERL_DRV_NIL; driver_output_term(erlang_port, msg, 1); + return; } break; @@ -651,6 +657,16 @@ static void send_term_drv_run(ErlDrvData port, char *buf, int count) driver_failure_atom(erlang_port, "bad_request"); break; } + if (count > 1) { + *msg++ = ERL_DRV_NIL; + *msg++ = ERL_DRV_LIST; + *msg++ = count + 1; + } + output_term(spec, msg-spec); + if ((bin_ix|s64_ix|u64_ix) > 15) abort(); + while (bin_ix) { + driver_free_binary(bins[--bin_ix]); + } } static void output_term(ErlDrvTermData* msg, int len) |