aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/configure.in17
-rw-r--r--erts/doc/src/notes.xml44
-rw-r--r--erts/emulator/Makefile.in7
-rw-r--r--erts/emulator/sys/unix/sys.c2
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin55752 -> 55804 bytes
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl23
-rw-r--r--erts/vsn.mk2
-rw-r--r--lib/common_test/src/Makefile1
-rw-r--r--lib/common_test/src/ct_default_gl.erl83
-rw-r--r--lib/common_test/src/ct_framework.erl14
-rw-r--r--lib/common_test/src/ct_logs.erl13
-rw-r--r--lib/common_test/src/ct_run.erl15
-rw-r--r--lib/common_test/src/ct_util.erl18
-rw-r--r--lib/common_test/src/ct_util.hrl1
-rw-r--r--lib/compiler/test/compile_SUITE.erl30
-rw-r--r--lib/compiler/test/guard_SUITE.erl137
-rw-r--r--lib/hipe/llvm/hipe_llvm_main.erl14
-rw-r--r--lib/hipe/llvm/hipe_rtl_to_llvm.erl103
-rw-r--r--lib/kernel/src/kernel.appup.src6
-rw-r--r--lib/odbc/configure.in22
-rw-r--r--lib/sasl/src/sasl.appup.src6
-rw-r--r--lib/sasl/src/systools_make.erl4
-rw-r--r--lib/sasl/test/systools_SUITE.erl35
-rw-r--r--lib/sasl/test/test_lib.hrl4
-rw-r--r--lib/ssh/src/Makefile2
-rw-r--r--lib/ssh/src/ssh_connection_handler.erl25
-rw-r--r--lib/ssh/src/ssh_dbg.erl3
-rw-r--r--lib/ssh/src/ssh_dbg.hrl27
-rw-r--r--lib/ssh/test/ssh_connection_SUITE.erl97
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl22
-rw-r--r--lib/ssl/test/ssl_ECC_SUITE.erl13
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl18
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl3
-rw-r--r--lib/ssl/test/ssl_packet_SUITE.erl6
-rw-r--r--lib/ssl/test/ssl_test_lib.erl63
-rw-r--r--lib/ssl/test/ssl_to_openssl_SUITE.erl2
-rw-r--r--lib/stdlib/doc/src/rand.xml35
-rw-r--r--lib/stdlib/src/rand.erl146
-rw-r--r--lib/stdlib/src/sets.erl66
-rw-r--r--lib/stdlib/src/stdlib.appup.src6
-rw-r--r--lib/stdlib/test/rand_SUITE.erl182
-rw-r--r--otp_versions.table1
42 files changed, 1047 insertions, 271 deletions
diff --git a/erts/configure.in b/erts/configure.in
index 4bff2ebf3d..50f8c3b429 100644
--- a/erts/configure.in
+++ b/erts/configure.in
@@ -2783,6 +2783,23 @@ if test "$cross_compiling" != "yes" && test X${enable_hipe} != Xno; then
fi
fi
+dnl Check to disable -fPIE and friends for HiPE on amd64
+if test X${enable_hipe} = Xyes && test X$ARCH = Xamd64; then
+ AC_TRY_COMPILE(, [#if defined(__pie__) || defined(__PIE__)
+ #error -fPIE is enabled by default
+ #endif],
+ [AC_MSG_NOTICE([No -fPIE enabled by default])],
+ [AC_MSG_WARN([Security feature -fPIE will be disabled for HiPE])
+ STATIC_CFLAGS="-fno-PIE $STATIC_CFLAGS"
+ saved_LDFLAGS=$LDFLAGS
+ LDFLAGS="-no-pie $LDFLAGS"
+ AC_TRY_LINK(,, [],
+ [AC_MSG_WARN([Linked does not accept option -no-pie])
+ LDFLAGS=$saved_LDFLAGS])])
+
+fi
+
+
if test X${enable_fp_exceptions} = Xauto ; then
case $host_os in
*linux*)
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 412675fd2b..dd260f2d1f 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -32,6 +32,50 @@
<p>This document describes the changes made to the ERTS application.</p>
+<section><title>Erts 8.1.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ The emulator got a dynamic library dependency towards
+ libsctp, which on Linux was not intended since the
+ emulator there loads and resolves the needed sctp
+ functions in runtime. This has been fixed and a configure
+ switch --enable-sctp=lib has been added for those who
+ want such a library dependency.</p>
+ <p>
+ Own Id: OTP-13956 Aux Id: ERL-262, ERL-133 </p>
+ </item>
+ <item>
+ <p>
+ Fix SIGUSR1 crashdump generation</p>
+ <p>
+ Do not generate a core when a crashdump is asked for.</p>
+ <p>
+ Own Id: OTP-13997</p>
+ </item>
+ <item>
+ <p>The new functions in <c>code</c> that allows loading
+ of many modules at once had a performance problem. While
+ executing a helper function in the <c>erl_prim_loader</c>
+ process, garbage messages were produced. The garbages
+ messages were ignored and ultimately discarded, but there
+ would be a negative impact on performance and memory
+ usage. The number of garbage message depended on both the
+ number of modules to be loaded and the length of the code
+ path.</p>
+ <p>The functions affected of this problem were:
+ <c>atomic_load/1</c>, <c>ensure_modules_loaded/1</c>, and
+ <c>prepare_loading/1</c>.</p>
+ <p>
+ Own Id: OTP-14009</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 8.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in
index fa4de5805e..ce50022683 100644
--- a/erts/emulator/Makefile.in
+++ b/erts/emulator/Makefile.in
@@ -49,6 +49,7 @@ CREATE_DIRS=
LDFLAGS=@LDFLAGS@
ARFLAGS=rc
OMIT_OMIT_FP=no
+TYPE_LIBS=
DIRTY_SCHEDULER_SUPPORT=@DIRTY_SCHEDULER_SUPPORT@
@@ -89,7 +90,7 @@ PURIFY =
TYPEMARKER = .gcov
TYPE_FLAGS = $(DEBUG_CFLAGS) -DERTS_GCOV -DNO_JUMP_TABLE -fprofile-arcs -ftest-coverage -O0 -DERTS_CAN_INLINE=0 -DERTS_INLINE=
ifneq ($(findstring solaris,$(TARGET)),solaris)
-LIBS += -lgcov
+TYPE_LIBS = -lgcov
endif
ENABLE_ALLOC_TYPE_VARS += debug
else
@@ -145,6 +146,8 @@ endif
endif
endif
+LIBS += $(TYPE_LIBS)
+
comma:=,
space:=
space+=
@@ -932,7 +935,7 @@ $(OBJDIR)/%.o: hipe/%.c
$(V_CC) $(subst O2,O3, $(CFLAGS)) $(INCLUDES) -c $< -o $@
$(BINDIR)/hipe_mkliterals$(TF_MARKER): $(OBJDIR)/hipe_mkliterals.o
- $(ld_verbose)$(CC) $(CFLAGS) $(INCLUDES) -o $@ $<
+ $(ld_verbose)$(CC) $(LDFLAGS) -o $@ $< $(TYPE_LIBS)
$(OBJDIR)/hipe_mkliterals.o: $(HIPE_ASM) $(TTF_DIR)/erl_alloc_types.h $(DTRACE_HEADERS) \
$(TTF_DIR)/OPCODES-GENERATED $(TARGET)/TABLES-GENERATED
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index b0e623a5b9..99e0aea4b5 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -672,7 +672,7 @@ sigusr1_exit(void)
}
prepare_crash_dump(secs);
- erts_exit(ERTS_ERROR_EXIT, "Received SIGUSR1\n");
+ erts_exit(ERTS_DUMP_EXIT, "Received SIGUSR1\n");
}
#ifdef ETHR_UNUSABLE_SIGUSRX
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index 796cbd74c5..64d1a70e61 100644
--- a/erts/preloaded/ebin/erl_prim_loader.beam
+++ b/erts/preloaded/ebin/erl_prim_loader.beam
Binary files differ
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index b3ec73a60e..1d09aeded9 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -555,17 +555,18 @@ efile_gm_get(Paths, Mod, ParentRef, Process) ->
efile_gm_get_1([P|Ps], File0, Mod, {Parent,Ref}=PR, Process) ->
File = join(P, File0),
- Res = try prim_file:read_file(File) of
- {ok,Bin} ->
- gm_process(Mod, File, Bin, Process);
- Error ->
- _ = check_file_result(get_modules, File, Error),
- efile_gm_get_1(Ps, File0, Mod, PR, Process)
- catch
- _:Reason ->
- {error,{crash,Reason}}
- end,
- Parent ! {Ref,Mod,Res};
+ try prim_file:read_file(File) of
+ {ok,Bin} ->
+ Res = gm_process(Mod, File, Bin, Process),
+ Parent ! {Ref,Mod,Res};
+ Error ->
+ _ = check_file_result(get_modules, File, Error),
+ efile_gm_get_1(Ps, File0, Mod, PR, Process)
+ catch
+ _:Reason ->
+ Res = {error,{crash,Reason}},
+ Parent ! {Ref,Mod,Res}
+ end;
efile_gm_get_1([], _, Mod, {Parent,Ref}, _Process) ->
Parent ! {Ref,Mod,{error,enoent}}.
diff --git a/erts/vsn.mk b/erts/vsn.mk
index ad9148f61f..317d731cd7 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
#
-VSN = 8.1
+VSN = 8.1.1
# Port number 4365 in 4.2
# Port number 4366 in 4.3
diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile
index 0f9e044f9e..9d751996ad 100644
--- a/lib/common_test/src/Makefile
+++ b/lib/common_test/src/Makefile
@@ -80,6 +80,7 @@ MODULES= \
ct_groups \
ct_property_test \
ct_release_test \
+ ct_default_gl \
erl2html2 \
test_server_ctrl \
test_server_gl \
diff --git a/lib/common_test/src/ct_default_gl.erl b/lib/common_test/src/ct_default_gl.erl
new file mode 100644
index 0000000000..d1b52e5f4f
--- /dev/null
+++ b/lib/common_test/src/ct_default_gl.erl
@@ -0,0 +1,83 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2012-2016. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ct_default_gl).
+-export([start_link/1, stop/0]).
+
+-export([init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2]).
+
+%% start_link()
+%% Start a new group leader process.
+start_link(ParentGL) ->
+ do_start(ParentGL, 3).
+
+do_start(_ParentGL, 0) ->
+ exit({?MODULE,startup});
+do_start(ParentGL, Retries) ->
+ case whereis(?MODULE) of
+ undefined ->
+ case gen_server:start_link(?MODULE, [ParentGL], []) of
+ {ok,Pid} ->
+ {ok,Pid};
+ Other ->
+ Other
+ end;
+ Pid ->
+ exit(Pid, kill),
+ timer:sleep(1000),
+ do_start(ParentGL, Retries-1)
+ end.
+
+%% stop(Pid)
+%% Stop a group leader process.
+stop() ->
+ gen_server:cast(whereis(?MODULE), stop).
+
+
+%%% Internal functions.
+
+init([ParentGL]) ->
+ register(?MODULE, self()),
+ {ok,#{parent_gl_pid => ParentGL,
+ parent_gl_monitor => erlang:monitor(process,ParentGL)}}.
+
+handle_cast(stop, St) ->
+ {stop,normal,St}.
+
+%% If the parent group leader dies, fall back on using the local user process
+handle_info({'DOWN',Ref,process,_,_Reason}, #{parent_gl_monitor := Ref} = St) ->
+ User = whereis(user),
+ {noreply,St#{parent_gl_pid => User,
+ parent_gl_monitor => erlang:monitor(process,User)}};
+
+handle_info({io_request,_From,_ReplyAs,_Req} = IoReq,
+ #{parent_gl_pid := ParentGL} = St) ->
+ ParentGL ! IoReq,
+ {noreply,St};
+
+handle_info(Msg, St) ->
+ io:format(user, "Common Test Group Leader process got: ~tp~n", [Msg]),
+ {noreply,St}.
+
+handle_call(_Req, _From, St) ->
+ {reply,ok,St}.
+
+terminate(_, _) ->
+ ok.
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index 104515e57e..291a4d716c 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -307,7 +307,7 @@ add_defaults(Mod,Func, GroupPath) ->
"~w:suite/0 failed: ~p~n",
[Suite,Reason]),
io:format(ErrStr, []),
- io:format(user, ErrStr, []),
+ io:format(?def_gl, ErrStr, []),
{suite0_failed,{exited,Reason}};
SuiteInfo when is_list(SuiteInfo) ->
case lists:all(fun(E) when is_tuple(E) -> true;
@@ -330,7 +330,7 @@ add_defaults(Mod,Func, GroupPath) ->
"~w:suite/0: ~p~n",
[Suite,SuiteInfo]),
io:format(ErrStr, []),
- io:format(user, ErrStr, []),
+ io:format(?def_gl, ErrStr, []),
{suite0_failed,bad_return_value}
end;
SuiteInfo ->
@@ -338,7 +338,7 @@ add_defaults(Mod,Func, GroupPath) ->
"Invalid return value from "
"~w:suite/0: ~p~n", [Suite,SuiteInfo]),
io:format(ErrStr, []),
- io:format(user, ErrStr, []),
+ io:format(?def_gl, ErrStr, []),
{suite0_failed,bad_return_value}
end.
@@ -366,7 +366,7 @@ add_defaults1(Mod,Func, GroupPath, SuiteInfo) ->
"~w:group(~w): ~p~n",
[Mod,GrName,BadGr0Val]),
io:format(Gr0ErrStr, []),
- io:format(user, Gr0ErrStr, []),
+ io:format(?def_gl, Gr0ErrStr, []),
{group0_failed,bad_return_value};
_ ->
Args = if Func == init_per_group ; Func == end_per_group ->
@@ -388,7 +388,7 @@ add_defaults1(Mod,Func, GroupPath, SuiteInfo) ->
"~w:~w/0: ~p~n",
[Mod,Func,BadTC0Val]),
io:format(TC0ErrStr, []),
- io:format(user, TC0ErrStr, []),
+ io:format(?def_gl, TC0ErrStr, []),
{testcase0_failed,bad_return_value};
_ ->
%% let test case info (also for all config funcs) override
@@ -927,7 +927,7 @@ error_notification(Mod,Func,_Args,{Error,Loc}) ->
Div = "~n- - - - - - - - - - - - - - - - - - - "
"- - - - - - - - - - - - - - - - - - - - -~n",
ErrorStr2 = io_lib:format(ErrorFormat, ErrorArgs),
- io:format(user, lists:concat([Div,ErrorStr2,Div,"~n"]),
+ io:format(?def_gl, lists:concat([Div,ErrorStr2,Div,"~n"]),
[]),
Link =
"\n\n<a href=\"#end\">"
@@ -1133,7 +1133,7 @@ get_all(Mod, ConfTests) ->
ErrStr = io_lib:format("~n*** ERROR *** "
"~w:all/0 failed: ~p~n",
[Mod,ExitReason]),
- io:format(user, ErrStr, []),
+ io:format(?def_gl, ErrStr, []),
%% save the error info so it doesn't get printed twice
ct_util:set_testdata_async({{error_in_suite,Mod},
ExitReason});
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index 9282a9f81d..0daed60dba 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -531,8 +531,13 @@ tc_print(Category,Importance,Format,Args) ->
Val
end,
if Importance >= (100-VLvl) ->
- Head = get_heading(Category),
- io:format(user, lists:concat([Head,Format,"\n\n"]), Args),
+ Str = lists:concat([get_heading(Category),Format,"\n\n"]),
+ try
+ io:format(?def_gl, Str, Args)
+ catch
+ %% default group leader probably not started, or has stopped
+ _:_ -> io:format(user, Str, Args)
+ end,
ok;
true ->
ok
@@ -679,7 +684,7 @@ logger(Parent, Mode, Verbosity) ->
PrivFilesDestRun = [filename:join(AbsDir, F) || F <- PrivFiles],
case copy_priv_files(PrivFilesSrc, PrivFilesDestTop) of
{error,Src1,Dest1,Reason1} ->
- io:format(user, "ERROR! "++
+ io:format(?def_gl, "ERROR! "++
"Priv file ~p could not be copied to ~p. "++
"Reason: ~p~n",
[Src1,Dest1,Reason1]),
@@ -687,7 +692,7 @@ logger(Parent, Mode, Verbosity) ->
ok ->
case copy_priv_files(PrivFilesSrc, PrivFilesDestRun) of
{error,Src2,Dest2,Reason2} ->
- io:format(user,
+ io:format(?def_gl,
"ERROR! "++
"Priv file ~p could not be copied to ~p. "
++"Reason: ~p~n",
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index fbb9c7ab60..a049ef5695 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -2155,8 +2155,8 @@ continue(_MakeErrors, true) ->
false;
continue(_MakeErrors, _AbortIfMissingSuites) ->
io:nl(),
- OldGl = group_leader(),
- case set_group_leader_same_as_shell() of
+ OldGL = group_leader(),
+ case set_group_leader_same_as_shell(OldGL) of
true ->
S = self(),
io:format("Failed to compile or locate one "
@@ -2172,7 +2172,7 @@ continue(_MakeErrors, _AbortIfMissingSuites) ->
S ! false
end
end),
- group_leader(OldGl, self()),
+ group_leader(OldGL, self()),
receive R when R==true; R==false ->
R
after 15000 ->
@@ -2184,7 +2184,9 @@ continue(_MakeErrors, _AbortIfMissingSuites) ->
true
end.
-set_group_leader_same_as_shell() ->
+set_group_leader_same_as_shell(OldGL) ->
+ %% find the group leader process on the node in a dirty fashion
+ %% (check initial function call and look in the process dictionary)
GS2or3 = fun(P) ->
case process_info(P,initial_call) of
{initial_call,{group,server,X}} when X == 2 ; X == 3 ->
@@ -2197,7 +2199,10 @@ set_group_leader_same_as_shell() ->
true == lists:keymember(shell,1,
element(2,process_info(P,dictionary)))] of
[GL|_] ->
- group_leader(GL, self());
+ %% check if started from remote node (skip interaction)
+ if node(OldGL) /= node(GL) -> false;
+ true -> group_leader(GL, self())
+ end;
[] ->
false
end.
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index 82a8743cf0..4d3a2ae7e3 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -188,6 +188,8 @@ do_start(Parent, Mode, LogDir, Verbosity) ->
ok
end,
+ ct_default_gl:start_link(group_leader()),
+
{StartTime,TestLogDir} = ct_logs:init(Mode, Verbosity),
ct_event:notify(#event{name=test_start,
@@ -474,6 +476,7 @@ loop(Mode,TestData,StartDir) ->
ct_logs:close(Info, StartDir),
ct_event:stop(),
ct_config:stop(),
+ ct_default_gl:stop(),
ok = file:set_cwd(StartDir),
return(From, Info);
{Ref, _Msg} when is_reference(Ref) ->
@@ -926,7 +929,8 @@ warn_duplicates(Suites) ->
[] ->
ok;
_ ->
- io:format(user,"~nWARNING! Deprecated function: ~w:sequences/0.~n"
+ io:format(?def_gl,
+ "~nWARNING! Deprecated function: ~w:sequences/0.~n"
" Use group with sequence property instead.~n",[Mod])
end
end,
@@ -980,12 +984,12 @@ get_profile_data(Profile, Key, StartDir) ->
end,
case Result of
{error,enoent} when Profile /= default ->
- io:format(user, "~nERROR! Missing profile file ~p~n", [File]),
+ io:format(?def_gl, "~nERROR! Missing profile file ~p~n", [File]),
undefined;
{error,enoent} when Profile == default ->
undefined;
{error,Reason} ->
- io:format(user,"~nERROR! Error in profile file ~p: ~p~n",
+ io:format(?def_gl,"~nERROR! Error in profile file ~p: ~p~n",
[WhichFile,Reason]),
undefined;
{ok,Data} ->
@@ -995,7 +999,7 @@ get_profile_data(Profile, Key, StartDir) ->
_ when is_list(Data) ->
Data;
_ ->
- io:format(user,
+ io:format(?def_gl,
"~nERROR! Invalid profile data in ~p~n",
[WhichFile]),
[]
@@ -1082,10 +1086,10 @@ open_url(iexplore, Args, URL) ->
Path = proplists:get_value(default, Paths),
[Cmd | _] = string:tokens(Path, "%"),
Cmd1 = Cmd ++ " " ++ Args ++ " " ++ URL,
- io:format(user, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd1]),
+ io:format(?def_gl, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd1]),
open_port({spawn,Cmd1}, []);
_ ->
- io:format("~nNo path to iexplore.exe~n",[])
+ io:format(?def_gl, "~nNo path to iexplore.exe~n",[])
end,
win32reg:close(R),
ok;
@@ -1095,6 +1099,6 @@ open_url(Prog, Args, URL) ->
is_list(Prog) -> Prog
end,
Cmd = ProgStr ++ " " ++ Args ++ " " ++ URL,
- io:format(user, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd]),
+ io:format(?def_gl, "~nOpening ~ts with command:~n ~ts~n", [URL,Cmd]),
open_port({spawn,Cmd},[]),
ok.
diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl
index d7efa26863..039c8168ec 100644
--- a/lib/common_test/src/ct_util.hrl
+++ b/lib/common_test/src/ct_util.hrl
@@ -23,6 +23,7 @@
-define(board_table,ct_boards).
-define(suite_table,ct_suite_data).
-define(verbosity_table,ct_verbosity_table).
+-define(def_gl, ct_default_gl).
-record(conn, {handle,
targetref,
diff --git a/lib/compiler/test/compile_SUITE.erl b/lib/compiler/test/compile_SUITE.erl
index 28a353d27b..2953a901b5 100644
--- a/lib/compiler/test/compile_SUITE.erl
+++ b/lib/compiler/test/compile_SUITE.erl
@@ -29,7 +29,7 @@
app_test/1,appup_test/1,
file_1/1, forms_2/1, module_mismatch/1, big_file/1, outdir/1,
binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1,
- other_output/1, encrypted_abstr/1,
+ other_output/1, kernel_listing/1, encrypted_abstr/1,
strict_record/1,
cover/1, env/1, core/1,
core_roundtrip/1, asm/1,
@@ -47,7 +47,7 @@ all() ->
test_lib:recompile(?MODULE),
[app_test, appup_test, file_1, forms_2, module_mismatch, big_file, outdir,
binary, makedep, cond_and_ifdef, listings, listings_big,
- other_output, encrypted_abstr,
+ other_output, kernel_listing, encrypted_abstr,
strict_record,
cover, env, core, core_roundtrip, asm,
sys_pre_attributes, dialyzer, warnings, pre_load_check,
@@ -430,6 +430,32 @@ other_output(Config) when is_list(Config) ->
ok.
+%% Smoke test and cover of pretty-printing of Kernel code.
+kernel_listing(_Config) ->
+ TestBeams = get_unique_beam_files(),
+ Abstr = [begin {ok,{Mod,[{abstract_code,
+ {raw_abstract_v1,Abstr}}]}} =
+ beam_lib:chunks(Beam, [abstract_code]),
+ {Mod,Abstr} end || Beam <- TestBeams],
+ test_lib:p_run(fun(F) -> do_kernel_listing(F) end, Abstr).
+
+do_kernel_listing({M,A}) ->
+ try
+ {ok,M,Kern} = compile:forms(A, [to_kernel]),
+ IoList = v3_kernel_pp:format(Kern),
+ _ = iolist_size(IoList),
+ ok
+ catch
+ throw:{error,Error} ->
+ io:format("*** compilation failure '~p' for module ~s\n",
+ [Error,M]),
+ error;
+ Class:Error ->
+ io:format("~p: ~p ~p\n~p\n",
+ [M,Class,Error,erlang:get_stacktrace()]),
+ error
+ end.
+
encrypted_abstr(Config) when is_list(Config) ->
{Simple,Target} = get_files(Config, simple, "encrypted_abstr"),
diff --git a/lib/compiler/test/guard_SUITE.erl b/lib/compiler/test/guard_SUITE.erl
index 429d6b79e0..11d4038b06 100644
--- a/lib/compiler/test/guard_SUITE.erl
+++ b/lib/compiler/test/guard_SUITE.erl
@@ -88,8 +88,31 @@ misc(Config) when is_list(Config) ->
{ok,buf,<<>>} = get_data({o,false,0}, 0, buf),
error = get_data({o,false,0}, 42, buf),
+ relief = misc_2(0),
+ error = misc_2(1),
+ error = misc_2(true),
+
+ if
+ is_integer(Config) =/= true ->
+ ok
+ end,
+
+ true = misc_3(1, 0),
+ true = misc_3(0, 0),
+ false = misc_3(0, 2),
+
+ %% Abuse of boolean values.
+
+ Zero = id(0),
+ One = id(1),
+ ok = if (Zero == 0) > false -> ok end,
+ ok = if (Zero == 0) =:= (One == 1) -> ok end,
+ ok = if (Zero == 0) =:= (One == 1) -> ok end,
+ ok = if is_atom(Zero > One) -> ok end,
+ error = if abs(Zero > One) -> ok; true -> error end,
+ ok = if is_integer(Zero) >= is_integer(One) -> ok end,
+
ok.
-
misc_1([{W},{X},{Y},{Z}]) ->
if
@@ -99,6 +122,17 @@ misc_1([{W},{X},{Y},{Z}]) ->
none
end.
+misc_2(0) -> relief;
+misc_2(Adapter = 1) when Adapter -> franklin;
+misc_2(_) -> error.
+
+misc_3(LenUp, LenDw) ->
+ if
+ %% Cover handling of #k_alt{}.
+ LenUp >= 1 orelse ((LenDw >= 2) xor true) -> true;
+ true -> false
+ end.
+
get_data({o,Active,Raw}, BytesToRead, Buffer)
when Raw =:= raw; Raw =:= 0 ->
if
@@ -164,6 +198,12 @@ basic_not(Config) when is_list(Config) ->
check(fun() -> if not glurf -> ok; true -> error end end, error),
check(fun() -> if not Glurf -> ok; true -> error end end, error),
+ check(fun() -> if not (not true) -> broken end end, broken),
+
+ check(fun() -> if not (True xor True) -> ok end end, ok),
+ check(fun() -> if not (True xor False) -> ok;
+ true -> error end end, error),
+
ok.
complex_not(Config) when is_list(Config) ->
@@ -188,8 +228,60 @@ complex_not(Config) when is_list(Config) ->
check(fun() -> if not(element(1, ATuple) orelse element(3, ATuple)) -> ok;
true -> error end end, error),
+ %% complex_not_1/4
+ ok = complex_not_1(1, 1, 1, a),
+ error = complex_not_1(1, 1, 1, []),
+ error = complex_not_1(1, 1, 3, a),
+ error = complex_not_1(1, 1, 3, []),
+ error = complex_not_1(1, 2, 1, a),
+ error = complex_not_1(1, 2, 1, []),
+ error = complex_not_1(1, 2, 3, a),
+ error = complex_not_1(1, 2, 3, []),
+
+ %% complex_not_2/4
+ ok = complex_not_2(1, 2, 0, x),
+ error = complex_not_2(1, 2, 0, []),
+ error = complex_not_2(1, 2, 3, x),
+ error = complex_not_2(1, 2, 3, []),
+ error = complex_not_2(1, 1, 0, x),
+ error = complex_not_2(1, 1, 0, []),
+ error = complex_not_2(1, 1, 3, x),
+ error = complex_not_2(1, 1, 3, []),
+
ok.
+complex_not_1(A, B, C, D) ->
+ Res = complex_not_1a(A, B, C, D),
+ Res = complex_not_1b(A, B, C, D).
+
+complex_not_1a(A, B, C, D)
+ when (not (A < B)) andalso (not (B < C)) andalso (not is_list(D)) ->
+ ok;
+complex_not_1a(_, _, _, _) ->
+ error.
+
+complex_not_1b(A, B, C, D)
+ when (not (A < B)) and (not (B < C)) and (not is_list(D)) ->
+ ok;
+complex_not_1b(_, _, _, _) ->
+ error.
+
+complex_not_2(A, B, C, D) ->
+ Res = complex_not_2a(A, B, C, D),
+ Res = complex_not_2b(A, B, C, D).
+
+complex_not_2a(A, B, C, D)
+ when A < B andalso not (B < C) andalso not is_list(D) ->
+ ok;
+complex_not_2a(_, _, _, _) ->
+ error.
+
+complex_not_2b(A, B, C, D)
+ when A < B, not (B < C), not is_list(D) ->
+ ok;
+complex_not_2b(_, _, _, _) ->
+ error.
+
nested_nots(Config) when is_list(Config) ->
true = nested_not_1(0, 0),
true = nested_not_1(0, 1),
@@ -210,19 +302,36 @@ nested_nots(Config) when is_list(Config) ->
false = nested_not_2(true, true, atom),
ok.
-nested_not_1(X, Y) when not (((X>Y) or not(is_atom(X))) and
+nested_not_1(X, Y) ->
+ Res = nested_not_1a(X, Y),
+ Res = nested_not_1b(X, Y).
+
+nested_not_1a(X, Y) when not (((X>Y) or not(is_atom(X))) and
(is_atom(Y) or (X==3.4))) ->
true;
-nested_not_1(_, _) ->
+nested_not_1a(_, _) ->
+ false.
+
+nested_not_1b(X, Y) when not (((X>Y) orelse not(is_atom(X))) andalso
+ (is_atom(Y) orelse (X==3.4))) ->
+ true;
+nested_not_1b(_, _) ->
false.
nested_not_2(X, Y, Z) ->
- nested_not_2(X, Y, Z, true).
+ Res = nested_not_2a(X, Y, Z, true),
+ Res = nested_not_2b(X, Y, Z, true).
-nested_not_2(X, Y, Z, True)
+nested_not_2a(X, Y, Z, True)
when not(True and not((not(X) and not(Y)) or not(is_atom(Z)))) ->
true;
-nested_not_2(_, _, _, _) ->
+nested_not_2a(_, _, _, _) ->
+ false.
+
+nested_not_2b(X, Y, Z, True)
+ when not(True andalso not((not(X) andalso not(Y)) orelse not(is_atom(Z)))) ->
+ true;
+nested_not_2b(_, _, _, _) ->
false.
semicolon(Config) when is_list(Config) ->
@@ -1094,6 +1203,13 @@ tricky(Config) when is_list(Config) ->
false = rb(100000, [1], 42),
true = rb(100000, [], 42),
true = rb(555, [a,b,c], 19),
+
+ error = tricky_3(42),
+ error = tricky_3(42.0),
+ error = tricky_3(<<>>),
+ error = tricky_3(#{}),
+ error = tricky_3({a,b}),
+
ok.
tricky_1(X, Y) when abs((X == 1) or (Y == 2)) -> ok;
@@ -1102,6 +1218,15 @@ tricky_1(_, _) -> not_ok.
tricky_2(X) when float(X) or float(X) -> ok;
tricky_2(_) -> error.
+tricky_3(X)
+ when abs(X) or bit_size(X) or byte_size(X) or ceil(X) or
+ float(X) or floor(X) or length(X) or
+ map_size(X) or node() or node(X) or round(X) or
+ self() or size(X) or tl(X) or trunc(X) or tuple_size(X) ->
+ ok;
+tricky_3(_) ->
+ error.
+
%% From dets_v9:read_buckets/11, simplified.
rb(Size, ToRead, SoFar) when SoFar + Size < 81920; ToRead == [] -> true;
diff --git a/lib/hipe/llvm/hipe_llvm_main.erl b/lib/hipe/llvm/hipe_llvm_main.erl
index c8fc9cc856..0957dd4df2 100644
--- a/lib/hipe/llvm/hipe_llvm_main.erl
+++ b/lib/hipe/llvm/hipe_llvm_main.erl
@@ -84,7 +84,7 @@ compile_with_llvm(FunName, Arity, LLVMCode, Options, UseBuffer) ->
__ = file:close(File_llvm),
%% Invoke LLVM compiler tools to produce an object file
llvm_opt(Dir, Filename, Options),
- llvm_llc(Dir, Filename, Options),
+ llvm_llc(Dir, Filename, Ver, Options),
compile(Dir, Filename, "gcc"), %%FIXME: use llc -filetype=obj and skip this!
{ok, Dir, Dir ++ Filename ++ ".o"}.
@@ -103,12 +103,14 @@ llvm_opt(Dir, Filename, Options) ->
%% @doc Invoke llc tool to compile the bitcode to object file
%% (_name.bc -> _name.o).
-llvm_llc(Dir, Filename, Options) ->
+llvm_llc(Dir, Filename, Ver, Options) ->
Source = Dir ++ Filename ++ ".bc",
OptLevel = trans_optlev_flag(llc, Options),
+ VerFlags = llc_ver_flags(Ver),
Align = find_stack_alignment(),
LlcFlags = [OptLevel, "-code-model=medium", "-stack-alignment=" ++ Align
- , "-tailcallopt", "-filetype=asm"], %%FIXME
+ , "-tailcallopt", "-filetype=asm" %FIXME
+ | VerFlags],
Command = "llc " ++ fix_opts(LlcFlags) ++ " " ++ Source,
%% io:format("LLC: ~s~n", [Command]),
case os:cmd(Command) of
@@ -153,6 +155,12 @@ trans_optlev_flag(Tool, Options) ->
undefined -> "-O2"
end.
+llc_ver_flags(Ver = {_, _}) when Ver >= {3,9} ->
+ %% Works around a bug in the x86-call-frame-opt pass (as of LLVM 3.9) that
+ %% break the garbage collection stack descriptors.
+ ["-no-x86-call-frame-opt"];
+llc_ver_flags({_, _}) -> [].
+
%%------------------------------------------------------------------------------
%% Functions to manage Relocations
%%------------------------------------------------------------------------------
diff --git a/lib/hipe/llvm/hipe_rtl_to_llvm.erl b/lib/hipe/llvm/hipe_rtl_to_llvm.erl
index 53aa8c57b2..20813f8bd7 100644
--- a/lib/hipe/llvm/hipe_rtl_to_llvm.erl
+++ b/lib/hipe/llvm/hipe_rtl_to_llvm.erl
@@ -10,7 +10,8 @@
-include("../rtl/hipe_literals.hrl").
-include("hipe_llvm_arch.hrl").
--define(WORD_WIDTH, (?bytes_to_bits(hipe_rtl_arch:word_size()))).
+-define(BITS_IN_WORD, (?bytes_to_bits(hipe_rtl_arch:word_size()))).
+-define(BITS_IN_BYTE, (?bytes_to_bits(1))).
-define(BRANCH_META_TAKEN, "0").
-define(BRANCH_META_NOT_TAKEN, "1").
-define(FIRST_FREE_META_NO, 2).
@@ -95,9 +96,9 @@ do_alloca_stack([], _, _, Acc) ->
Acc;
do_alloca_stack([D|Ds], Params, Roots, Acc) ->
{Name, _I} = trans_dst(D),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
- ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)),
+ ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)),
case hipe_rtl:is_var(D) of
true ->
Num = hipe_rtl:var_index(D),
@@ -233,7 +234,7 @@ trans_alu(I, Relocs) ->
{Src1, I1} = trans_src(hipe_rtl:alu_src1(I)),
{Src2, I2} = trans_src(hipe_rtl:alu_src2(I)),
Op = trans_op(hipe_rtl:alu_op(I)),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
I3 = hipe_llvm:mk_operation(TmpDst, Op, WordTy, Src1, Src2, []),
I4 = store_stack_dst(TmpDst, RtlDst),
{[I4, I3, I2, I1], Relocs}.
@@ -258,7 +259,7 @@ trans_alub_overflow(I, Sign, Relocs) ->
TmpDst = mk_temp(),
Name = trans_alub_op(I, Sign),
NewRelocs = relocs_store(Name, {call, remote, {llvm, Name, 2}}, Relocs),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
ReturnType = hipe_llvm:mk_struct([WordTy, hipe_llvm:mk_int(1)]),
T1 = mk_temp(),
I3 = hipe_llvm:mk_call(T1, false, [], [], ReturnType, "@" ++ Name,
@@ -320,7 +321,7 @@ trans_alub_no_overflow(I, Relocs) ->
{Dst, I2} = trans_src(hipe_rtl:alub_dst(I)),
Cond = trans_rel_op(hipe_rtl:alub_cond(I)),
T3 = mk_temp(),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
I5 = hipe_llvm:mk_icmp(T3, Cond, WordTy, Dst, "0"),
%% br
Metadata = branch_metadata(hipe_rtl:alub_pred(I)),
@@ -338,7 +339,7 @@ trans_branch(I, Relocs) ->
Cond = trans_rel_op(hipe_rtl:branch_cond(I)),
%% icmp
T1 = mk_temp(),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
I3 = hipe_llvm:mk_icmp(T1, Cond, WordTy, Src1, Src2),
%% br
True_label = mk_jump_label(hipe_rtl:branch_true_label(I)),
@@ -366,7 +367,7 @@ trans_call(I, Relocs) ->
{Name, I3, Relocs2} =
trans_call_name(RtlCallName, hipe_rtl:call_type(I), Relocs1, CallArgs, FinalArgs),
T1 = mk_temp(),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)),
I4 =
case hipe_rtl:call_fail(I) of
@@ -450,7 +451,7 @@ trans_call_name(RtlCallName, RtlCallType, Relocs, CallArgs, FinalArgs) ->
%% order to make the call
TT1 = mk_temp(),
{RegName, II1} = trans_src(Reg),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
II2 =
hipe_llvm:mk_conversion(TT1, inttoptr, WordTy, RegName, WordTyPtr),
@@ -503,7 +504,7 @@ trans_enter(I, Relocs) ->
{Name, I2, NewRelocs} =
trans_call_name(hipe_rtl:enter_fun(I), hipe_rtl:enter_type(I), Relocs, CallArgs, FinalArgs),
T1 = mk_temp(),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)),
I3 = hipe_llvm:mk_call(T1, true, "cc 11", [], FunRetTy, Name, FinalArgs, []),
I4 = hipe_llvm:mk_ret([{FunRetTy, T1}]),
@@ -518,7 +519,7 @@ trans_fconv(I, Relocs) ->
TmpDst = mk_temp(),
{Src, I1} = trans_float_src(hipe_rtl:fconv_src(I)),
FloatTy = hipe_llvm:mk_double(),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
I2 = hipe_llvm:mk_conversion(TmpDst, sitofp, WordTy, Src, FloatTy),
I3 = store_float_stack(TmpDst, RtlDst),
{[I3, I2, I1], Relocs}.
@@ -538,7 +539,7 @@ trans_fload(I, Relocs) ->
{Src, I1} = trans_float_src(RtlSrc),
{Offset, I2} = trans_float_src(_Offset),
T1 = mk_temp(),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
FloatTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_double()),
I3 = hipe_llvm:mk_operation(T1, add, WordTy, Src, Offset, []),
T2 = mk_temp(),
@@ -619,7 +620,7 @@ trans_fstore(I, Relocs) ->
trans_fstore_reg(I, Relocs) ->
{Base, I0} = trans_reg(hipe_rtl:fstore_base(I), dst),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
FloatTy = hipe_llvm:mk_double(),
FloatTyPtr = hipe_llvm:mk_pointer(FloatTy),
@@ -659,7 +660,7 @@ trans_load(I, Relocs) ->
{Src, I1} = trans_src(hipe_rtl:load_src(I)),
{Offset, I2} = trans_src(hipe_rtl:load_offset(I)),
T1 = mk_temp(),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
I3 = hipe_llvm:mk_operation(T1, add, WordTy, Src, Offset, []),
%%----------------------------------------------------------------
@@ -737,7 +738,7 @@ trans_move(I, Relocs) ->
%% return
%%
trans_return(I, Relocs) ->
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
{VarRet, I1} =
case hipe_rtl:return_varlist(I) of
[] ->
@@ -777,7 +778,7 @@ trans_store(I, Relocs) ->
{Offset, I2} = trans_src(hipe_rtl:store_offset(I)),
{Value, I3} = trans_src(hipe_rtl:store_src(I)),
T1 = mk_temp(),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
I4 = hipe_llvm:mk_operation(T1, add, WordTy, Base, Offset, []),
I5 =
@@ -811,14 +812,14 @@ trans_switch(I, Relocs, Data) ->
JumpLabels = [mk_jump_label(L) || L <- Labels],
SortOrder = hipe_rtl:switch_sort_order(I),
NrLabels = length(Labels),
- ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)),
+ ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)),
TableType = hipe_llvm:mk_array(NrLabels, ByteTyPtr),
TableTypeP = hipe_llvm:mk_pointer(TableType),
TypedJumpLabels = [{hipe_llvm:mk_label_type(), X} || X <- JumpLabels],
T1 = mk_temp(),
{Src2, []} = trans_dst(RtlSrc),
TableName = "table_" ++ tl(Src2),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
I2 = hipe_llvm:mk_getelementptr(T1, TableTypeP, "@"++TableName,
[{WordTy, "0"}, {WordTy, Src}], false),
T2 = mk_temp(),
@@ -933,7 +934,7 @@ create_fail_blocks(Label, FailLabels, Acc) ->
false ->
Acc;
{value, {Label, FailLabel, SpAdj}, RestFailLabels} ->
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
I1 = hipe_llvm:mk_label(FailLabel),
LP = hipe_llvm:mk_landingpad(),
I2 =
@@ -962,7 +963,7 @@ create_fail_blocks(Label, FailLabels, Acc) ->
%% @doc Convert RTL argument list to LLVM argument list.
trans_args(ArgList) ->
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
MakeArg =
fun(A) ->
{Name, I1} = trans_src(A),
@@ -972,13 +973,13 @@ trans_args(ArgList) ->
%% @doc Convert a list of Precoloured registers to LLVM argument list.
fix_reg_args(ArgList) ->
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
[{WordTy, A} || A <- ArgList].
%% @doc Load Precoloured registers.
load_fixed_regs(RegList) ->
Names = [mk_temp_reg(R) || R <- RegList],
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
Fun1 =
fun (X, Y) ->
@@ -991,7 +992,7 @@ load_fixed_regs(RegList) ->
store_fixed_regs(RegList, Name) ->
Names = [mk_temp_reg(R) || R <- RegList],
Indexes = lists:seq(0, erlang:length(RegList) - 1),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)),
Fun1 =
@@ -1064,7 +1065,7 @@ mk_temp_reg(Name) ->
store_stack_dst(TempDst, Dst) ->
{Dst2, II1} = trans_dst(Dst),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
II2 = hipe_llvm:mk_store(WordTy, TempDst, WordTyPtr, Dst2, [], [], false),
[II2, II1].
@@ -1082,7 +1083,7 @@ trans_float_src(Src) ->
Name = "@DL" ++ integer_to_list(hipe_rtl:const_label_label(Src)),
T1 = mk_temp(),
%% XXX: Hardcoded offset
- ByteTy = hipe_llvm:mk_int(8),
+ ByteTy = hipe_llvm:mk_int(?BITS_IN_BYTE),
ByteTyPtr = hipe_llvm:mk_pointer(ByteTy),
I1 = hipe_llvm:mk_getelementptr(T1, ByteTyPtr, Name,
[{ByteTy, integer_to_list(?FLOAT_OFFSET)}], true),
@@ -1098,7 +1099,7 @@ trans_float_src(Src) ->
end.
trans_src(A) ->
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
case hipe_rtl:is_imm(A) of
true ->
@@ -1201,7 +1202,7 @@ map_precoloured_reg(Index) ->
fix_reg_dst(Register) ->
case Register of
{Name, Offset} -> %% Case of %fcalls, %hplim
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
pointer_from_reg(Name, WordTy, Offset);
Name -> %% Case of %p and %hp
{Name, []}
@@ -1209,7 +1210,7 @@ fix_reg_dst(Register) ->
%% @doc Load precoloured src register.
fix_reg_src(Register) ->
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
case Register of
{Name, Offset} -> %% Case of %fcalls, %hplim
@@ -1331,10 +1332,10 @@ insn_dst(I) ->
llvm_type_from_size(Size) ->
case Size of
- byte -> hipe_llvm:mk_int(8);
+ byte -> hipe_llvm:mk_int(?BITS_IN_BYTE);
int16 -> hipe_llvm:mk_int(16);
int32 -> hipe_llvm:mk_int(32);
- word -> hipe_llvm:mk_int(64)
+ word -> hipe_llvm:mk_int(?BITS_IN_WORD)
end.
%% @doc Create definition for the compiled function. The parameters that are
@@ -1364,13 +1365,13 @@ create_function_definition(Fun, Params, Code, LocalVars) ->
lists:flatten([EntryLabel, ExceptionSync, I2, LocalVars, StoredParams, I3]),
Final_Code = EntryBlock ++ Code,
FunctionOptions = [nounwind, noredzone, list_to_atom("gc \"erlang\"")],
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)),
hipe_llvm:mk_fun_def([], [], "cc 11", [], FunRetTy, FunctionName, Args,
FunctionOptions, [], Final_Code).
header_params(Params) ->
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
[{WordTy, "%v" ++ integer_to_list(hipe_rtl:var_index(P))} || P <- Params].
store_params(Params) ->
@@ -1379,7 +1380,7 @@ store_params(Params) ->
Index = hipe_rtl:var_index(X),
{Name, _} = trans_dst(X),
ParamName = "%v" ++ integer_to_list(Index),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
hipe_llvm:mk_store(WordTy, ParamName, WordTyPtr, Name, [], [], false)
end,
@@ -1396,11 +1397,11 @@ fixed_registers() ->
end.
header_regs(Registers) ->
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
[{WordTy, "%" ++ X ++ "_in"} || X <- Registers].
load_regs(Registers) ->
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
WordTyPtr = hipe_llvm:mk_pointer(WordTy),
Fun1 =
fun(X) ->
@@ -1501,28 +1502,30 @@ seperate_relocs([R|Rs], CallAcc, AtomAcc, ClosureAcc, LabelAcc, JmpTableAcc) ->
%% @doc External declaration of an atom.
declare_atom({AtomName, _}) ->
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
- hipe_llvm:mk_const_decl("@" ++ AtomName, "external constant", WordTy, "").
+ %% The type has to be byte, or a backend might assume the constant is aligned
+ %% and incorrectly optimise away type tests
+ ByteTy = hipe_llvm:mk_int(?BITS_IN_BYTE),
+ hipe_llvm:mk_const_decl("@" ++ AtomName, "external constant", ByteTy, "").
%% @doc Creation of local variable for an atom.
load_atom({AtomName, _}) ->
Dst = "%" ++ AtomName ++ "_var",
Name = "@" ++ AtomName,
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
- WordTyPtr = hipe_llvm:mk_pointer(WordTy),
- hipe_llvm:mk_conversion(Dst, ptrtoint, WordTyPtr, Name, WordTy).
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
+ ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)),
+ hipe_llvm:mk_conversion(Dst, ptrtoint, ByteTyPtr, Name, WordTy).
%% @doc External declaration of a closure.
declare_closure({ClosureName, _})->
- ByteTy = hipe_llvm:mk_int(8),
+ ByteTy = hipe_llvm:mk_int(?BITS_IN_BYTE),
hipe_llvm:mk_const_decl("@" ++ ClosureName, "external constant", ByteTy, "").
%% @doc Creation of local variable for a closure.
load_closure({ClosureName, _})->
Dst = "%" ++ ClosureName ++ "_var",
Name = "@" ++ ClosureName,
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
- ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
+ ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)),
hipe_llvm:mk_conversion(Dst, ptrtoint, ByteTyPtr, Name, WordTy).
%% @doc Declaration of a local variable for a switch jump table.
@@ -1553,7 +1556,7 @@ declare_closure_labels(ClosureLabels, Relocs, Fun) ->
List3 = string:join(List2, ",\n"),
List4 = "[\n" ++ List3 ++ "\n]\n",
NrLabels = length(LabelList),
- ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)),
+ ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)),
TableType = hipe_llvm:mk_array(NrLabels, ByteTyPtr),
ConstDecl =
hipe_llvm:mk_const_decl("@table_closures", "constant", TableType, List4),
@@ -1568,7 +1571,7 @@ is_external_call(_, _) -> true.
call_to_decl({Name, {call, _, MFA}}) ->
{M, _F, A} = MFA,
CConv = "cc 11",
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)),
{Type, Args} =
case M of
@@ -1583,14 +1586,14 @@ call_to_decl({Name, {call, _, MFA}}) ->
%% @doc These functions are always declared, even if not used.
fixed_fun_decl() ->
- ByteTy = hipe_llvm:mk_int(8),
+ ByteTy = hipe_llvm:mk_int(?BITS_IN_BYTE),
ByteTyPtr = hipe_llvm:mk_pointer(ByteTy),
LandPad = hipe_llvm:mk_fun_decl([], [], [], [], hipe_llvm:mk_int(32),
"@__gcc_personality_v0", [hipe_llvm:mk_int(32), hipe_llvm:mk_int(64),
ByteTyPtr, ByteTyPtr], []),
GCROOTDecl = hipe_llvm:mk_fun_decl([], [], [], [], hipe_llvm:mk_void(),
"@llvm.gcroot", [hipe_llvm:mk_pointer(ByteTyPtr), ByteTyPtr], []),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
FunRetTy = hipe_llvm:mk_struct(lists:duplicate(?NR_PINNED_REGS + 1, WordTy)),
FixPinnedRegs = hipe_llvm:mk_fun_decl([], [], [], [], FunRetTy,
"@hipe_bifs.llvm_fix_pinned_regs.0", [], []),
@@ -1604,7 +1607,7 @@ fixed_fun_decl() ->
%% values, add the offset and convert them again to pointers.
declare_constant(Label) ->
Name = "@DL" ++ integer_to_list(Label),
- ByteTy = hipe_llvm:mk_int(8),
+ ByteTy = hipe_llvm:mk_int(?BITS_IN_BYTE),
hipe_llvm:mk_const_decl(Name, "external constant", ByteTy, "").
%% @doc Load a constant is achieved by converting a pointer to an integer of
@@ -1612,8 +1615,8 @@ declare_constant(Label) ->
load_constant(Label) ->
Dst = "%DL" ++ integer_to_list(Label) ++ "_var",
Name = "@DL" ++ integer_to_list(Label),
- WordTy = hipe_llvm:mk_int(?WORD_WIDTH),
- ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(8)),
+ WordTy = hipe_llvm:mk_int(?BITS_IN_WORD),
+ ByteTyPtr = hipe_llvm:mk_pointer(hipe_llvm:mk_int(?BITS_IN_BYTE)),
hipe_llvm:mk_conversion(Dst, ptrtoint, ByteTyPtr, Name, WordTy).
%% @doc Store external constants and calls to dictionary.
diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src
index 82cf73cbda..b505524471 100644
--- a/lib/kernel/src/kernel.appup.src
+++ b/lib/kernel/src/kernel.appup.src
@@ -18,9 +18,7 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max one major revision back
- [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
- {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.*
+ [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.*
%% Down to - max one major revision back
- [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
- {<<"4\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.*
+ [{<<"5\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.*
}.
diff --git a/lib/odbc/configure.in b/lib/odbc/configure.in
index d26daa5eda..4deda13c8b 100644
--- a/lib/odbc/configure.in
+++ b/lib/odbc/configure.in
@@ -65,7 +65,7 @@ dnl ---------------------------------------------------------------------
dnl Special windows stuff regarding CFLAGS and details in the environment...
dnl ---------------------------------------------------------------------
LM_WINDOWS_ENVIRONMENT
-
+
AC_PROG_MAKE_SET
AC_CHECK_PROGS(LD, ld.sh)
@@ -136,8 +136,8 @@ AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_addr], [], [],
dnl Checks for library functions.
AC_CHECK_FUNCS([memset socket])
-
-# ODBC
+
+# ODBC
$RM -f "$ERL_TOP/lib/odbc/SKIP"
LM_CHECK_THR_LIB
@@ -147,23 +147,23 @@ AC_SUBST(THR_LIBS)
odbc_lib_link_success=no
AC_SUBST(TARGET_FLAGS)
case $host_os in
- darwin1[[0-5]].*|darwin[[0-9]].*)
+ darwin*)
TARGET_FLAGS="-DUNIX"
if test ! -d "$with_odbc" || test "$with_odbc" = "yes"; then
- ODBC_LIB= -L"/usr/lib"
- ODBC_INCLUDE="-I/usr/lib/include"
+ ODBC_LIB= -L"/usr/local/lib"
+ ODBC_INCLUDE="-I/usr/local/include"
else
ODBC_LIB=-L"$with_odbc/lib"
ODBC_INCLUDE="-I$with_odbc/include"
fi
-
- AC_CHECK_LIB(iodbc, SQLAllocHandle,[ODBC_LIB="$ODBC_LIB -liodbc"; odbc_lib_link_success=yes])
+
+ AC_CHECK_LIB(iodbc, SQLAllocHandle,[ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes])
;;
win32|cygwin)
TARGET_FLAGS="-DWIN32"
AC_CHECK_LIB(ws2_32, main)
if test ! -d "$with_odbc" || test "$with_odbc" = "yes"; then
- ODBC_LIB=""
+ ODBC_LIB=""
ODBC_INCLUDE=""
else
ODBC_LIB=-L"$with_odbc/lib"
@@ -196,7 +196,7 @@ AC_SUBST(TARGET_FLAGS)
elif test -d "${libdir}/64/."; then
libdir="${libdir}/64"
fi
- fi
+ fi
ODBC_LIB="-L$libdir"
ODBC_INCLUDE="-I$erl_xcomp_isysroot$rdir/include"
break
@@ -207,7 +207,7 @@ AC_SUBST(TARGET_FLAGS)
echo "No odbc library found" > "$ERL_TOP/lib/odbc/SKIP"
else
AC_MSG_RESULT($ODBC_LIB)
- AC_CHECK_LIB(odbc, SQLAllocHandle,[ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes])
+ AC_CHECK_LIB(odbc, SQLAllocHandle,[ODBC_LIB="$ODBC_LIB -lodbc"; odbc_lib_link_success=yes])
fi
;;
diff --git a/lib/sasl/src/sasl.appup.src b/lib/sasl/src/sasl.appup.src
index ecd320c1ea..7f866507a0 100644
--- a/lib/sasl/src/sasl.appup.src
+++ b/lib/sasl/src/sasl.appup.src
@@ -18,9 +18,7 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max one major revision back
- [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
- {<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.*
+ [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.*
%% Down to - max one major revision back
- [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
- {<<"2\\.[5-7](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.*
+ [{<<"3\\.0(\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.*
}.
diff --git a/lib/sasl/src/systools_make.erl b/lib/sasl/src/systools_make.erl
index efe6cc9eb4..6a16c8689e 100644
--- a/lib/sasl/src/systools_make.erl
+++ b/lib/sasl/src/systools_make.erl
@@ -643,6 +643,8 @@ get_items([], _Dict) ->
check_item({_,{mod,{M,A}}},_) when is_atom(M) ->
{M,A};
+check_item({_,{mod,[]}},_) -> % default mod is [], so accept as entry
+ [];
check_item({_,{vsn,Vsn}},I) ->
case string_p(Vsn) of
true -> Vsn;
@@ -678,6 +680,8 @@ check_item({_,{modules,Mods}},I) ->
true -> Mods;
_ -> throw({bad_param, I})
end;
+check_item({_,{start_phases,undefined}},_) -> % default start_phase is undefined,
+ undefined; % so accept as entry
check_item({_,{start_phases,Phase}},I) ->
case t_list_p(Phase) of
true -> Phase;
diff --git a/lib/sasl/test/systools_SUITE.erl b/lib/sasl/test/systools_SUITE.erl
index bf95ceb70c..dd5f277a77 100644
--- a/lib/sasl/test/systools_SUITE.erl
+++ b/lib/sasl/test/systools_SUITE.erl
@@ -59,7 +59,7 @@
no_appup_relup/1, bad_appup_relup/1, app_start_type_relup/1,
regexp_relup/1]).
-export([normal_hybrid/1,hybrid_no_old_sasl/1,hybrid_no_new_sasl/1]).
--export([otp_6226_outdir/1]).
+-export([otp_6226_outdir/1, app_file_defaults/1]).
-export([init_per_suite/1, end_per_suite/1,
init_per_testcase/2, end_per_testcase/2]).
-export([delete_tree/1]).
@@ -97,7 +97,7 @@ groups() ->
no_appup_relup, bad_appup_relup, app_start_type_relup, regexp_relup
]},
{hybrid, [], [normal_hybrid,hybrid_no_old_sasl,hybrid_no_new_sasl]},
- {options, [], [otp_6226_outdir]}].
+ {options, [], [otp_6226_outdir,app_file_defaults]}].
init_per_group(_GroupName, Config) ->
Config.
@@ -2014,6 +2014,37 @@ otp_6226_outdir(Config) when is_list(Config) ->
ok.
+%% Test that all default values can be used as values in the .app file
+app_file_defaults(Config) ->
+ PrivDir = ?config(priv_dir,Config),
+ Name = app1,
+ NameStr = atom_to_list(Name),
+ Vsn = "1.0",
+ AppSpec = app_spec(Name,#{vsn=>"1.0"}),
+ ok = file:write_file(filename:join(PrivDir,NameStr ++ ".app"),
+ io_lib:format("~p.~n",[AppSpec])),
+ {ok,_} = systools_make:read_application(NameStr,Vsn,[PrivDir],[]),
+ ok.
+
+app_spec(Name,New) ->
+ {application,Name,app_spec(New)}.
+
+app_spec(New) ->
+ Default = #{description => "",
+ id => "",
+ vsn => "",
+ modules => [],
+ maxP => infinity,
+ maxT => infinity,
+ registered => [],
+ included_applications => [],
+ applications => [],
+ env => [],
+ mod => [],
+ start_phases => undefined,
+ runtime_dependencies => []},
+ maps:to_list(maps:merge(Default,New)).
+
%%%%%%
%%%%%% Utilities
%%%%%%
diff --git a/lib/sasl/test/test_lib.hrl b/lib/sasl/test/test_lib.hrl
index 2d897e9903..9a54937f96 100644
--- a/lib/sasl/test/test_lib.hrl
+++ b/lib/sasl/test/test_lib.hrl
@@ -1,3 +1,3 @@
-define(ertsvsn,"4.4").
--define(kernelvsn,"4.0").
--define(stdlibvsn,"2.5").
+-define(kernelvsn,"5.0").
+-define(stdlibvsn,"3.0").
diff --git a/lib/ssh/src/Makefile b/lib/ssh/src/Makefile
index 69d5a47f83..7ab6f22424 100644
--- a/lib/ssh/src/Makefile
+++ b/lib/ssh/src/Makefile
@@ -96,7 +96,7 @@ APP_TARGET= $(EBIN)/$(APP_FILE)
APPUP_SRC= $(APPUP_FILE).src
APPUP_TARGET= $(EBIN)/$(APPUP_FILE)
-INTERNAL_HRL_FILES = ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl ssh.hrl ssh_userauth.hrl ssh_xfer.hrl
+INTERNAL_HRL_FILES = ssh_auth.hrl ssh_connect.hrl ssh_transport.hrl ssh.hrl ssh_userauth.hrl ssh_xfer.hrl ssh_dbg.hrl
# ----------------------------------------------------
# FLAGS
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index dd414894d4..7451c9e6d0 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -928,6 +928,7 @@ handle_event(internal, Msg=#ssh_msg_channel_request{}, StateName, D) -
handle_connection_msg(Msg, StateName, D);
handle_event(internal, Msg=#ssh_msg_channel_success{}, StateName, D) ->
+ update_inet_buffers(D#data.socket),
handle_connection_msg(Msg, StateName, D);
handle_event(internal, Msg=#ssh_msg_channel_failure{}, StateName, D) ->
@@ -1007,6 +1008,7 @@ handle_event(cast, {reply_request,success,ChannelId}, {connected,_}, D) ->
case ssh_channel:cache_lookup(cache(D), ChannelId) of
#channel{remote_id = RemoteId} ->
Msg = ssh_connection:channel_success_msg(RemoteId),
+ update_inet_buffers(D#data.socket),
{keep_state, send_msg(Msg,D)};
undefined ->
@@ -1194,12 +1196,12 @@ handle_event(info, {Proto, Sock, NewData}, StateName, D0 = #data{socket = Sock,
ssh_message:decode(set_kex_overload_prefix(DecryptedBytes,D))
of
Msg = #ssh_msg_kexinit{} ->
- {keep_state, D, [{next_event, internal, {Msg,DecryptedBytes}},
- {next_event, internal, prepare_next_packet}
+ {keep_state, D, [{next_event, internal, prepare_next_packet},
+ {next_event, internal, {Msg,DecryptedBytes}}
]};
Msg ->
- {keep_state, D, [{next_event, internal, Msg},
- {next_event, internal, prepare_next_packet}
+ {keep_state, D, [{next_event, internal, prepare_next_packet},
+ {next_event, internal, Msg}
]}
catch
_C:_E ->
@@ -1738,6 +1740,11 @@ send_replies(Repls, State) ->
Repls).
get_repl({connection_reply,Msg}, {CallRepls,S}) ->
+ if is_record(Msg, ssh_msg_channel_success) ->
+ update_inet_buffers(S#data.socket);
+ true ->
+ ok
+ end,
{CallRepls, send_msg(Msg,S)};
get_repl({channel_data,undefined,_Data}, Acc) ->
Acc;
@@ -1926,3 +1933,13 @@ handshake(Pid, Ref, Timeout) ->
{error, timeout}
end.
+update_inet_buffers(Socket) ->
+ {ok, BufSzs0} = inet:getopts(Socket, [sndbuf,recbuf]),
+ MinVal = 655360,
+ case
+ [{Tag,MinVal} || {Tag,Val} <- BufSzs0,
+ Val < MinVal]
+ of
+ [] -> ok;
+ NewOpts -> inet:setopts(Socket, NewOpts)
+ end.
diff --git a/lib/ssh/src/ssh_dbg.erl b/lib/ssh/src/ssh_dbg.erl
index ce5596e0f9..dff2bae9f2 100644
--- a/lib/ssh/src/ssh_dbg.erl
+++ b/lib/ssh/src/ssh_dbg.erl
@@ -28,6 +28,9 @@
stop/0
]).
+-export([shrink_bin/1,
+ wr_record/3]).
+
-include("ssh.hrl").
-include("ssh_transport.hrl").
-include("ssh_connect.hrl").
diff --git a/lib/ssh/src/ssh_dbg.hrl b/lib/ssh/src/ssh_dbg.hrl
new file mode 100644
index 0000000000..e94664737b
--- /dev/null
+++ b/lib/ssh/src/ssh_dbg.hrl
@@ -0,0 +1,27 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%% http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-ifndef(SSH_DBG_HRL).
+-define(SSH_DBG_HRL, 1).
+
+-define(formatrec(RecName,R),
+ ssh_dbg:wr_record(R, record_info(fields,RecName), [])).
+
+-endif. % SSH_DBG_HRL defined
diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl
index bcf3b01824..e898d55b6f 100644
--- a/lib/ssh/test/ssh_connection_SUITE.erl
+++ b/lib/ssh/test/ssh_connection_SUITE.erl
@@ -381,13 +381,13 @@ do_interrupted_send(Config, SendSize, EchoSize) ->
{password, "morot"},
{subsystems, [{"echo_n",EchoSS_spec}]}]),
- ct:log("connect", []),
+ ct:log("~p:~p connect", [?MODULE,?LINE]),
ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
{user, "foo"},
{password, "morot"},
{user_interaction, false},
{user_dir, UserDir}]),
- ct:log("connected", []),
+ ct:log("~p:~p connected", [?MODULE,?LINE]),
%% build big binary
Data = << <<X:32>> || X <- lists:seq(1,SendSize div 4)>>,
@@ -399,9 +399,9 @@ do_interrupted_send(Config, SendSize, EchoSize) ->
Parent = self(),
ResultPid = spawn(
fun() ->
- ct:log("open channel",[]),
+ ct:log("~p:~p open channel",[?MODULE,?LINE]),
{ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
- ct:log("start subsystem", []),
+ ct:log("~p:~p start subsystem", [?MODULE,?LINE]),
case ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity) of
success ->
Parent ! {self(), channelId, ChannelId},
@@ -410,47 +410,69 @@ do_interrupted_send(Config, SendSize, EchoSize) ->
try collect_data(ConnectionRef, ChannelId)
of
ExpectedData ->
+ ct:log("~p:~p got expected data",[?MODULE,?LINE]),
ok;
- _ ->
- {fail,"unexpected result"}
+ Other ->
+ ct:log("~p:~p unexpect: ~p", [?MODULE,?LINE,Other]),
+ {fail,"unexpected result in listener"}
catch
Class:Exception ->
- {fail, io_lib:format("Exception ~p:~p",[Class,Exception])}
+ {fail, io_lib:format("Listener exception ~p:~p",[Class,Exception])}
end,
- Parent ! {self(), Result};
+ Parent ! {self(), result, Result};
Other ->
Parent ! {self(), channelId, error, Other}
end
end),
receive
+ {ResultPid, channelId, error, Other} ->
+ ct:log("~p:~p channelId error ~p", [?MODULE,?LINE,Other]),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid),
+ {fail, "ssh_connection:subsystem"};
+
{ResultPid, channelId, ChannelId} ->
- %% pre-adjust receive window so the other end doesn't block
- ct:log("adjust window", []),
- ssh_connection:adjust_window(ConnectionRef, ChannelId, size(ExpectedData) + 1),
-
- ct:log("going to send ~p bytes", [size(Data)]),
- case ssh_connection:send(ConnectionRef, ChannelId, Data, 30000) of
- {error, closed} ->
- ct:log("{error,closed} - That's what we expect :)", []),
- ok;
- Msg ->
- ct:log("Got ~p - that's bad, very bad indeed",[Msg]),
- ct:fail({expected,{error,closed}, got, Msg})
- end,
- ct:log("going to check the result (if it is available)", []),
+ ct:log("~p:~p ~p going to send ~p bytes", [?MODULE,?LINE,self(),size(Data)]),
+ SenderPid = spawn(fun() ->
+ Parent ! {self(), ssh_connection:send(ConnectionRef, ChannelId, Data, 30000)}
+ end),
receive
- {ResultPid, Result} ->
- ct:log("Got result: ~p", [Result]),
+ {ResultPid, result, {fail, Fail}} ->
+ ct:log("~p:~p Listener failed: ~p", [?MODULE,?LINE,Fail]),
+ {fail, Fail};
+
+ {ResultPid, result, Result} ->
+ ct:log("~p:~p Got result: ~p", [?MODULE,?LINE,Result]),
ssh:close(ConnectionRef),
ssh:stop_daemon(Pid),
- Result
- end;
+ ct:log("~p:~p Check sender", [?MODULE,?LINE]),
+ receive
+ {SenderPid, {error, closed}} ->
+ ct:log("~p:~p {error,closed} - That's what we expect :)",[?MODULE,?LINE]),
+ ok;
+ Msg ->
+ ct:log("~p:~p Not expected send result: ~p",[?MODULE,?LINE,Msg]),
+ {fail, "Not expected msg"}
+ end;
+
+ {SenderPid, {error, closed}} ->
+ ct:log("~p:~p {error,closed} - That's what we expect, but client channel handler has not reported yet",[?MODULE,?LINE]),
+ receive
+ {ResultPid, result, Result} ->
+ ct:log("~p:~p Now got the result: ~p", [?MODULE,?LINE,Result]),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid),
+ ok;
+ Msg ->
+ ct:log("~p:~p Got an unexpected msg ~p",[?MODULE,?LINE,Msg]),
+ {fail, "Un-expected msg"}
+ end;
- {ResultPid, channelId, error, Other} ->
- ssh:close(ConnectionRef),
- ssh:stop_daemon(Pid),
- {fail, io_lib:format("ssh_connection:subsystem: ~p",[Other])}
+ Msg ->
+ ct:log("~p:~p Got unexpected ~p",[?MODULE,?LINE,Msg]),
+ {fail, "Unexpected msg"}
+ end
end.
%%--------------------------------------------------------------------
@@ -910,34 +932,35 @@ big_cat_rx(ConnectionRef, ChannelId, Acc) ->
end.
collect_data(ConnectionRef, ChannelId) ->
- ct:log("Listener ~p running! ConnectionRef=~p, ChannelId=~p",[self(),ConnectionRef,ChannelId]),
+ ct:log("~p:~p Listener ~p running! ConnectionRef=~p, ChannelId=~p",[?MODULE,?LINE,self(),ConnectionRef,ChannelId]),
collect_data(ConnectionRef, ChannelId, [], 0).
collect_data(ConnectionRef, ChannelId, Acc, Sum) ->
TO = 5000,
receive
{ssh_cm, ConnectionRef, {data, ChannelId, 0, Data}} when is_binary(Data) ->
- ct:log("collect_data: received ~p bytes. total ~p bytes",[size(Data),Sum+size(Data)]),
+ ct:log("~p:~p collect_data: received ~p bytes. total ~p bytes",[?MODULE,?LINE,size(Data),Sum+size(Data)]),
+ ssh_connection:adjust_window(ConnectionRef, ChannelId, size(Data)),
collect_data(ConnectionRef, ChannelId, [Data | Acc], Sum+size(Data));
{ssh_cm, ConnectionRef, {eof, ChannelId}} ->
try
iolist_to_binary(lists:reverse(Acc))
of
Bin ->
- ct:log("collect_data: received eof.~nGot in total ~p bytes",[size(Bin)]),
+ ct:log("~p:~p collect_data: received eof.~nGot in total ~p bytes",[?MODULE,?LINE,size(Bin)]),
Bin
catch
C:E ->
- ct:log("collect_data: received eof.~nAcc is strange...~nException=~p:~p~nAcc=~p",
- [C,E,Acc]),
+ ct:log("~p:~p collect_data: received eof.~nAcc is strange...~nException=~p:~p~nAcc=~p",
+ [?MODULE,?LINE,C,E,Acc]),
{error,{C,E}}
end;
Msg ->
- ct:log("collect_data: ***** unexpected message *****~n~p",[Msg]),
+ ct:log("~p:~p collect_data: ***** unexpected message *****~n~p",[?MODULE,?LINE,Msg]),
collect_data(ConnectionRef, ChannelId, Acc, Sum)
after TO ->
- ct:log("collect_data: ----- Nothing received for ~p seconds -----~n",[]),
+ ct:log("~p:~p collect_data: ----- Nothing received for ~p seconds -----~n",[?MODULE,?LINE,TO]),
collect_data(ConnectionRef, ChannelId, Acc, Sum)
end.
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index 2c7fe7898f..86c3d5de26 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -404,8 +404,6 @@ erlang_server_openssh_client_renegotiate(Config) ->
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SystemDir},
{public_key_alg, PubKeyAlg},
{failfun, fun ssh_test_lib:failfun/2}]),
-
-%% catch ssh_dbg:messages(fun(String,_D) -> ct:log(String) end),
ct:sleep(500),
RenegLimitK = 3,
@@ -431,13 +429,24 @@ erlang_server_openssh_client_renegotiate(Config) ->
catch
_:_ -> false
end;
+
+ ({exit_status,E}) when E=/=0 ->
+ ct:log("exit_status ~p",[E]),
+ throw({skip,"exit status"});
+
(_) ->
false
end,
-
- ssh_test_lib:rcv_expected(Expect, OpenSsh, ?TIMEOUT),
- %% Unfortunatly we can't check that there has been a renegotiation, just trust OpenSSH.
- ssh:stop_daemon(Pid).
+
+ try
+ ssh_test_lib:rcv_expected(Expect, OpenSsh, ?TIMEOUT)
+ of
+ _ ->
+ %% Unfortunatly we can't check that there has been a renegotiation, just trust OpenSSH.
+ ssh:stop_daemon(Pid)
+ catch
+ throw:{skip,R} -> {skip,R}
+ end.
%%--------------------------------------------------------------------
erlang_client_openssh_server_renegotiate(_Config) ->
@@ -447,7 +456,6 @@ erlang_client_openssh_server_renegotiate(_Config) ->
Ref = make_ref(),
Parent = self(),
- catch ssh_dbg:messages(fun(X,_) -> ct:log(X) end),
Shell =
spawn_link(
fun() ->
diff --git a/lib/ssl/test/ssl_ECC_SUITE.erl b/lib/ssl/test/ssl_ECC_SUITE.erl
index bd0c630d41..76999185b6 100644
--- a/lib/ssl/test/ssl_ECC_SUITE.erl
+++ b/lib/ssl/test/ssl_ECC_SUITE.erl
@@ -566,17 +566,8 @@ new_openssl_ca(FileName, CA, OwnCa) ->
E1 = public_key:pem_decode(P1),
{ok, P2} = file:read_file(OwnCa),
E2 = public_key:pem_decode(P2),
- case os:cmd("openssl version") of
- "OpenSSL 1.0.1p-freebsd" ++ _ ->
- Pem = public_key:pem_encode(E1 ++E2),
- file:write_file(FileName, Pem);
- "LibreSSL" ++ _ ->
- Pem = public_key:pem_encode(E1 ++E2),
- file:write_file(FileName, Pem);
- _ ->
- Pem = public_key:pem_encode(E2 ++E1),
- file:write_file(FileName, Pem)
- end,
+ Pem = public_key:pem_encode(E2 ++E1),
+ file:write_file(FileName, Pem),
FileName.
supported_eccs(Opts) ->
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index f8dea736ae..392da738ec 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -2193,7 +2193,7 @@ ciphers_dsa_signed_certs() ->
ciphers_dsa_signed_certs(Config) when is_list(Config) ->
Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:dsa_suites(),
+ Ciphers = ssl_test_lib:dsa_suites(tls_record:protocol_version(Version)),
ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
run_suites(Ciphers, Version, Config, dsa).
%%-------------------------------------------------------------------
@@ -2334,7 +2334,7 @@ ciphers_ecdsa_signed_certs() ->
ciphers_ecdsa_signed_certs(Config) when is_list(Config) ->
Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:ecdsa_suites(),
+ Ciphers = ssl_test_lib:ecdsa_suites(tls_record:protocol_version(Version)),
ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
run_suites(Ciphers, Version, Config, ecdsa).
%%--------------------------------------------------------------------
@@ -2352,7 +2352,7 @@ ciphers_ecdh_rsa_signed_certs() ->
ciphers_ecdh_rsa_signed_certs(Config) when is_list(Config) ->
Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:ecdh_rsa_suites(),
+ Ciphers = ssl_test_lib:ecdh_rsa_suites(tls_record:protocol_version(Version)),
ct:log("~p erlang cipher suites ~p~n", [Version, Ciphers]),
run_suites(Ciphers, Version, Config, ecdh_rsa).
%%--------------------------------------------------------------------
@@ -3663,9 +3663,10 @@ no_rizzo_rc4() ->
[{doc,"Test that there is no 1/n-1-split for RC4 as it is not vunrable to Rizzo/Dungon attack"}].
no_rizzo_rc4(Config) when is_list(Config) ->
- Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(),Y == rc4_128],
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
+ Ciphers = [ssl_cipher:erl_suite_definition(Suite) ||
+ Suite <- ssl_test_lib:rc4_suites(tls_record:protocol_version(Version))],
run_send_recv_rizzo(Ciphers, Config, Version,
{?MODULE, send_recv_result_active_no_rizzo, []}).
@@ -3673,9 +3674,10 @@ rizzo_one_n_minus_one() ->
[{doc,"Test that the 1/n-1-split mitigation of Rizzo/Dungon attack can be explicitly selected"}].
rizzo_one_n_minus_one(Config) when is_list(Config) ->
- Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128],
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
+ AllSuites = ssl_test_lib:available_suites(tls_record:protocol_version(Version)),
+ Ciphers = [X || X ={_,Y,_} <- AllSuites, Y =/= rc4_128],
run_send_recv_rizzo(Ciphers, Config, Version,
{?MODULE, send_recv_result_active_rizzo, []}).
@@ -3683,9 +3685,10 @@ rizzo_zero_n() ->
[{doc,"Test that the 0/n-split mitigation of Rizzo/Dungon attack can be explicitly selected"}].
rizzo_zero_n(Config) when is_list(Config) ->
- Ciphers = [X || X ={_,Y,_} <- ssl:cipher_suites(), Y =/= rc4_128],
Prop = proplists:get_value(tc_group_properties, Config),
Version = proplists:get_value(name, Prop),
+ AllSuites = ssl_test_lib:available_suites(tls_record:protocol_version(Version)),
+ Ciphers = [X || X ={_,Y,_} <- AllSuites, Y =/= rc4_128],
run_send_recv_rizzo(Ciphers, Config, Version,
{?MODULE, send_recv_result_active_no_rizzo, []}).
@@ -4436,7 +4439,7 @@ rizzo_test(Cipher, Config, Version, Mfa) ->
{host, Hostname},
{from, self()},
{mfa, Mfa},
- {options, [{active, true} | ClientOpts]}]),
+ {options, [{active, true}, {ciphers, [Cipher]}| ClientOpts]}]),
Result = ssl_test_lib:check_result(Server, ok, Client, ok),
ssl_test_lib:close(Server),
@@ -4727,3 +4730,4 @@ first_rsa_suite([_ | Rest]) ->
wait_for_send(Socket) ->
%% Make sure TLS process processed send message event
_ = ssl:connection_information(Socket).
+
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 4c6f1d7c01..5265c87e29 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -1097,7 +1097,8 @@ client_with_cert_cipher_suites_handshake(Config) when is_list(Config) ->
{mfa, {ssl_test_lib,
send_recv_result_active, []}},
{options, [{active, true},
- {ciphers, ssl_test_lib:rsa_non_signed_suites()}
+ {ciphers,
+ ssl_test_lib:rsa_non_signed_suites(tls_record:highest_protocol_version([]))}
| ServerOpts]}]),
Port = ssl_test_lib:inet_port(Server),
Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
diff --git a/lib/ssl/test/ssl_packet_SUITE.erl b/lib/ssl/test/ssl_packet_SUITE.erl
index 942e68967a..3446a566c4 100644
--- a/lib/ssl/test/ssl_packet_SUITE.erl
+++ b/lib/ssl/test/ssl_packet_SUITE.erl
@@ -41,9 +41,9 @@
-define(MANY, 1000).
-define(SOME, 50).
--define(BASE_TIMEOUT_SECONDS, 30).
--define(SOME_SCALE, 20).
--define(MANY_SCALE, 20).
+-define(BASE_TIMEOUT_SECONDS, 5).
+-define(SOME_SCALE, 2).
+-define(MANY_SCALE, 3).
%%--------------------------------------------------------------------
%% Common Test interface functions -----------------------------------
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index cab22a60a8..9632103696 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -462,9 +462,10 @@ cert_options(Config) ->
make_dsa_cert(Config) ->
-
- {ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_cert_files("server", Config, dsa, dsa, ""),
- {ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_cert_files("client", Config, dsa, dsa, ""),
+ {ServerCaCertFile, ServerCertFile, ServerKeyFile} =
+ make_cert_files("server", Config, dsa, dsa, "", []),
+ {ClientCaCertFile, ClientCertFile, ClientKeyFile} =
+ make_cert_files("client", Config, dsa, dsa, "", []),
[{server_dsa_opts, [{ssl_imp, new},{reuseaddr, true},
{cacertfile, ServerCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
@@ -490,8 +491,10 @@ make_ecdsa_cert(Config) ->
CryptoSupport = crypto:supports(),
case proplists:get_bool(ecdsa, proplists:get_value(public_keys, CryptoSupport)) of
true ->
- {ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_cert_files("server", Config, ec, ec, ""),
- {ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_cert_files("client", Config, ec, ec, ""),
+ {ServerCaCertFile, ServerCertFile, ServerKeyFile} =
+ make_cert_files("server", Config, ec, ec, "", [{digest, appropriate_sha(CryptoSupport)}]),
+ {ClientCaCertFile, ClientCertFile, ClientKeyFile} =
+ make_cert_files("client", Config, ec, ec, "", [{digest, appropriate_sha(CryptoSupport)}]),
[{server_ecdsa_opts, [{ssl_imp, new},{reuseaddr, true},
{cacertfile, ServerCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
@@ -507,6 +510,14 @@ make_ecdsa_cert(Config) ->
Config
end.
+appropriate_sha(CryptoSupport) ->
+ case proplists:get_bool(sha256, CryptoSupport) of
+ true ->
+ sha256;
+ false ->
+ sha1
+ end.
+
%% RFC 4492, Sect. 2.3. ECDH_RSA
%%
%% This key exchange algorithm is the same as ECDH_ECDSA except that the
@@ -515,8 +526,10 @@ make_ecdh_rsa_cert(Config) ->
CryptoSupport = crypto:supports(),
case proplists:get_bool(ecdh, proplists:get_value(public_keys, CryptoSupport)) of
true ->
- {ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_cert_files("server", Config, rsa, ec, "rsa_"),
- {ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_cert_files("client", Config, rsa, ec, "rsa_"),
+ {ServerCaCertFile, ServerCertFile, ServerKeyFile} =
+ make_cert_files("server", Config, rsa, ec, "rsa_", []),
+ {ClientCaCertFile, ClientCertFile, ClientKeyFile} =
+ make_cert_files("client", Config, rsa, ec, "rsa_",[]),
[{server_ecdh_rsa_opts, [{ssl_imp, new},{reuseaddr, true},
{cacertfile, ServerCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
@@ -534,9 +547,9 @@ make_ecdh_rsa_cert(Config) ->
make_mix_cert(Config) ->
{ServerCaCertFile, ServerCertFile, ServerKeyFile} = make_cert_files("server", Config, dsa,
- rsa, "mix"),
+ rsa, "mix", []),
{ClientCaCertFile, ClientCertFile, ClientKeyFile} = make_cert_files("client", Config, dsa,
- rsa, "mix"),
+ rsa, "mix", []),
[{server_mix_opts, [{ssl_imp, new},{reuseaddr, true},
{cacertfile, ServerCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
@@ -549,11 +562,11 @@ make_mix_cert(Config) ->
{certfile, ClientCertFile}, {keyfile, ClientKeyFile}]}
| Config].
-make_cert_files(RoleStr, Config, Alg1, Alg2, Prefix) ->
+make_cert_files(RoleStr, Config, Alg1, Alg2, Prefix, Opts) ->
Alg1Str = atom_to_list(Alg1),
Alg2Str = atom_to_list(Alg2),
- CaInfo = {CaCert, _} = erl_make_certs:make_cert([{key, Alg1}]),
- {Cert, CertKey} = erl_make_certs:make_cert([{key, Alg2}, {issuer, CaInfo}]),
+ CaInfo = {CaCert, _} = erl_make_certs:make_cert([{key, Alg1}| Opts]),
+ {Cert, CertKey} = erl_make_certs:make_cert([{key, Alg2}, {issuer, CaInfo} | Opts]),
CaCertFile = filename:join([proplists:get_value(priv_dir, Config),
RoleStr, Prefix ++ Alg1Str ++ "_cacerts.pem"]),
CertFile = filename:join([proplists:get_value(priv_dir, Config),
@@ -840,37 +853,42 @@ common_ciphers(openssl) ->
lists:member(ssl_cipher:openssl_suite_name(S), OpenSslSuites)
].
-rsa_non_signed_suites() ->
+available_suites(Version) ->
+ [ssl_cipher:erl_suite_definition(Suite) ||
+ Suite <- ssl_cipher:filter_suites(ssl_cipher:suites(Version))].
+
+
+rsa_non_signed_suites(Version) ->
lists:filter(fun({rsa, _, _}) ->
true;
(_) ->
false
end,
- ssl:cipher_suites()).
+ available_suites(Version)).
-dsa_suites() ->
+dsa_suites(Version) ->
lists:filter(fun({dhe_dss, _, _}) ->
true;
(_) ->
false
end,
- ssl:cipher_suites()).
+ available_suites(Version)).
-ecdsa_suites() ->
+ecdsa_suites(Version) ->
lists:filter(fun({ecdhe_ecdsa, _, _}) ->
true;
(_) ->
false
end,
- ssl:cipher_suites()).
+ available_suites(Version)).
-ecdh_rsa_suites() ->
+ecdh_rsa_suites(Version) ->
lists:filter(fun({ecdh_rsa, _, _}) ->
true;
(_) ->
false
end,
- ssl:cipher_suites()).
+ available_suites(Version)).
openssl_rsa_suites(CounterPart) ->
Ciphers = ssl:cipher_suites(openssl),
@@ -1174,14 +1192,15 @@ is_fips(_) ->
false.
cipher_restriction(Config0) ->
+ Version = tls_record:protocol_version(protocol_version(Config0)),
case is_sane_ecc(openssl) of
false ->
Opts = proplists:get_value(server_opts, Config0),
Config1 = proplists:delete(server_opts, Config0),
VerOpts = proplists:get_value(server_verification_opts, Config1),
Config = proplists:delete(server_verification_opts, Config1),
- Restricted0 = ssl:cipher_suites() -- ecdsa_suites(),
- Restricted = Restricted0 -- ecdh_rsa_suites(),
+ Restricted0 = ssl:cipher_suites() -- ecdsa_suites(Version),
+ Restricted = Restricted0 -- ecdh_rsa_suites(Version),
[{server_opts, [{ciphers, Restricted} | Opts]}, {server_verification_opts, [{ciphers, Restricted} | VerOpts] } | Config];
true ->
Config0
diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl
index 9ecfe5b0ea..e99340822d 100644
--- a/lib/ssl/test/ssl_to_openssl_SUITE.erl
+++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl
@@ -834,7 +834,7 @@ ciphers_dsa_signed_certs() ->
[{doc,"Test cipher suites that uses dsa certs"}].
ciphers_dsa_signed_certs(Config) when is_list(Config) ->
Version = ssl_test_lib:protocol_version(Config),
- Ciphers = ssl_test_lib:dsa_suites(),
+ Ciphers = ssl_test_lib:dsa_suites(tls_record:protocol_version(Version)),
run_suites(Ciphers, Version, Config, dsa).
%%--------------------------------------------------------------------
diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml
index 1dcc3de000..1364a3277b 100644
--- a/lib/stdlib/doc/src/rand.xml
+++ b/lib/stdlib/doc/src/rand.xml
@@ -41,6 +41,11 @@
Sebastiano Vigna</url>. The normal distribution algorithm uses the
<url href="http://www.jstatsoft.org/v05/i08">Ziggurat Method by Marsaglia
and Tsang</url>.</p>
+ <p>For some algorithms, jump functions are provided for generating
+ non-overlapping sequences for parallel computations.
+ The jump functions perform calculations
+ equivalent to perform a large number of repeated calls
+ for calculating new states. </p>
<p>The following algorithms are provided:</p>
@@ -48,14 +53,17 @@
<tag><c>exsplus</c></tag>
<item>
<p>Xorshift116+, 58 bits precision and period of 2^116-1</p>
+ <p>Jump function: equivalent to 2^64 calls</p>
</item>
<tag><c>exs64</c></tag>
<item>
<p>Xorshift64*, 64 bits precision and a period of 2^64-1</p>
+ <p>Jump function: not available</p>
</item>
<tag><c>exs1024</c></tag>
<item>
<p>Xorshift1024*, 64 bits precision and a period of 2^1024-1</p>
+ <p>Jump function: equivalent to 2^512 calls</p>
</item>
</taglist>
@@ -156,6 +164,33 @@ S0 = rand:seed_s(exsplus),
</func>
<func>
+ <name name="jump" arity="0"/>
+ <fsummary>Return the seed after performing jump calculation
+ to the state in the process dictionary.</fsummary>
+ <desc><marker id="jump-0" />
+ <p>Returns the state
+ after performing jump calculation
+ to the state in the process dictionary.</p>
+ <p>This function generates a <c>not_implemented</c> error exception
+ when the jump function is not implemented for
+ the algorithm specified in the state
+ in the process dictionary.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="jump" arity="1"/>
+ <fsummary>Return the seed after performing jump calculation.</fsummary>
+ <desc><marker id="jump-1" />
+ <p>Returns the state after performing jump calculation
+ to the given state. </p>
+ <p>This function generates a <c>not_implemented</c> error exception
+ when the jump function is not implemented for
+ the algorithm specified in the state.</p>
+ </desc>
+ </func>
+
+ <func>
<name name="normal" arity="0"/>
<fsummary>Return a standard normal distributed random float.</fsummary>
<desc>
diff --git a/lib/stdlib/src/rand.erl b/lib/stdlib/src/rand.erl
index 93409d95df..3b1767e731 100644
--- a/lib/stdlib/src/rand.erl
+++ b/lib/stdlib/src/rand.erl
@@ -19,7 +19,7 @@
%%
%% =====================================================================
%% Multiple PRNG module for Erlang/OTP
-%% Copyright (c) 2015 Kenji Rikitake
+%% Copyright (c) 2015-2016 Kenji Rikitake
%% =====================================================================
-module(rand).
@@ -27,11 +27,14 @@
-export([seed_s/1, seed_s/2, seed/1, seed/2,
export_seed/0, export_seed_s/1,
uniform/0, uniform/1, uniform_s/1, uniform_s/2,
+ jump/0, jump/1,
normal/0, normal_s/1
]).
-compile({inline, [exs64_next/1, exsplus_next/1,
+ exsplus_jump/1,
exs1024_next/1, exs1024_calc/2,
+ exs1024_jump/1,
get_52/1, normal_kiwi/1]}).
-define(DEFAULT_ALG_HANDLER, exsplus).
@@ -48,7 +51,8 @@
max := integer(),
next := fun(),
uniform := fun(),
- uniform_n := fun()}.
+ uniform_n := fun(),
+ jump := fun()}.
%% Internal state
-opaque state() :: {alg_handler(), alg_seed()}.
@@ -79,9 +83,7 @@ export_seed_s({#{type:=Alg}, Seed}) -> {Alg, Seed}.
-spec seed(AlgOrExpState::alg() | export_state()) -> state().
seed(Alg) ->
- R = seed_s(Alg),
- _ = seed_put(R),
- R.
+ seed_put(seed_s(Alg)).
-spec seed_s(AlgOrExpState::alg() | export_state()) -> state().
seed_s(Alg) when is_atom(Alg) ->
@@ -97,9 +99,7 @@ seed_s({Alg0, Seed}) ->
-spec seed(Alg :: alg(), {integer(), integer(), integer()}) -> state().
seed(Alg0, S0) ->
- State = seed_s(Alg0, S0),
- _ = seed_put(State),
- State.
+ seed_put(seed_s(Alg0, S0)).
-spec seed_s(Alg :: alg(), {integer(), integer(), integer()}) -> state().
seed_s(Alg0, S0 = {_, _, _}) ->
@@ -150,6 +150,25 @@ uniform_s(N, State0 = {#{uniform:=Uniform}, _})
{F, State} = Uniform(State0),
{trunc(F * N) + 1, State}.
+%% jump/1: given a state, jump/1
+%% returns a new state which is equivalent to that
+%% after a large number of call defined for each algorithm.
+%% The large number is algorithm dependent.
+
+-spec jump(state()) -> {NewS :: state()}.
+jump(State = {#{jump:=Jump}, _}) ->
+ Jump(State).
+
+%% jump/0: read the internal state and
+%% apply the jump function for the state as in jump/1
+%% and write back the new value to the internal state,
+%% then returns the new value.
+
+-spec jump() -> {NewS :: state()}.
+
+jump() ->
+ seed_put(jump(seed_get())).
+
%% normal/0: returns a random float with standard normal distribution
%% updating the state in the process dictionary.
@@ -192,9 +211,10 @@ normal_s(State0) ->
-type uint64() :: 0..16#ffffffffffffffff.
-type uint58() :: 0..16#03ffffffffffffff.
--spec seed_put(state()) -> undefined | state().
+-spec seed_put(state()) -> state().
seed_put(Seed) ->
- put(?SEED_DICT, Seed).
+ put(?SEED_DICT, Seed),
+ Seed.
seed_get() ->
case get(?SEED_DICT) of
@@ -205,15 +225,18 @@ seed_get() ->
%% Setup alg record
mk_alg(exs64) ->
{#{type=>exs64, max=>?UINT64MASK, next=>fun exs64_next/1,
- uniform=>fun exs64_uniform/1, uniform_n=>fun exs64_uniform/2},
+ uniform=>fun exs64_uniform/1, uniform_n=>fun exs64_uniform/2,
+ jump=>fun exs64_jump/1},
fun exs64_seed/1};
mk_alg(exsplus) ->
{#{type=>exsplus, max=>?UINT58MASK, next=>fun exsplus_next/1,
- uniform=>fun exsplus_uniform/1, uniform_n=>fun exsplus_uniform/2},
+ uniform=>fun exsplus_uniform/1, uniform_n=>fun exsplus_uniform/2,
+ jump=>fun exsplus_jump/1},
fun exsplus_seed/1};
mk_alg(exs1024) ->
{#{type=>exs1024, max=>?UINT64MASK, next=>fun exs1024_next/1,
- uniform=>fun exs1024_uniform/1, uniform_n=>fun exs1024_uniform/2},
+ uniform=>fun exs1024_uniform/1, uniform_n=>fun exs1024_uniform/2,
+ jump=>fun exs1024_jump/1},
fun exs1024_seed/1}.
%% =====================================================================
@@ -246,6 +269,9 @@ exs64_uniform(Max, {Alg, R}) ->
{V, R1} = exs64_next(R),
{(V rem Max) + 1, {Alg, R1}}.
+exs64_jump(_) ->
+ erlang:error(not_implemented).
+
%% =====================================================================
%% exsplus PRNG: Xorshift116+
%% Algorithm by Sebastiano Vigna
@@ -283,6 +309,42 @@ exsplus_uniform(Max, {Alg, R}) ->
{V, R1} = exsplus_next(R),
{(V rem Max) + 1, {Alg, R1}}.
+%% This is the jump function for the exsplus generator, equivalent
+%% to 2^64 calls to next/1; it can be used to generate 2^52
+%% non-overlapping subsequences for parallel computations.
+%% Note: the jump function takes 116 times of the execution time of
+%% next/1.
+
+%% -define(JUMPCONST, 16#000d174a83e17de2302f8ea6bc32c797).
+%% split into 58-bit chunks
+%% and two iterative executions
+
+-define(JUMPCONST1, 16#02f8ea6bc32c797).
+-define(JUMPCONST2, 16#345d2a0f85f788c).
+-define(JUMPELEMLEN, 58).
+
+-spec exsplus_jump(exsplus_state()) -> exsplus_state().
+
+exsplus_jump({Alg, S}) ->
+ {S1, AS1} = exsplus_jump(S, [0|0], ?JUMPCONST1, ?JUMPELEMLEN),
+ {_, AS2} = exsplus_jump(S1, AS1, ?JUMPCONST2, ?JUMPELEMLEN),
+ {Alg, AS2}.
+
+-spec exsplus_jump(state(), state(), pos_integer(), pos_integer()) ->
+ {state(), state()}.
+
+exsplus_jump(S, AS, _, 0) ->
+ {S, AS};
+exsplus_jump(S, [AS0|AS1], J, N) ->
+ {_, NS} = exsplus_next(S),
+ case (J band 1) of
+ 1 ->
+ [S0|S1] = S,
+ exsplus_jump(NS, [(AS0 bxor S0)|(AS1 bxor S1)], J bsr 1, N-1);
+ 0 ->
+ exsplus_jump(NS, [AS0|AS1], J bsr 1, N-1)
+ end.
+
%% =====================================================================
%% exs1024 PRNG: Xorshift1024*
%% Algorithm by Sebastiano Vigna
@@ -340,6 +402,64 @@ exs1024_uniform(Max, {Alg, R}) ->
{V, R1} = exs1024_next(R),
{(V rem Max) + 1, {Alg, R1}}.
+%% This is the jump function for the exs1024 generator, equivalent
+%% to 2^512 calls to next(); it can be used to generate 2^512
+%% non-overlapping subsequences for parallel computations.
+%% Note: the jump function takes ~2000 times of the execution time of
+%% next/1.
+
+%% Jump constant here split into 58 bits for speed
+-define(JUMPCONSTHEAD, 16#00242f96eca9c41d).
+-define(JUMPCONSTTAIL,
+ [16#0196e1ddbe5a1561,
+ 16#0239f070b5837a3c,
+ 16#03f393cc68796cd2,
+ 16#0248316f404489af,
+ 16#039a30088bffbac2,
+ 16#02fea70dc2d9891f,
+ 16#032ae0d9644caec4,
+ 16#0313aac17d8efa43,
+ 16#02f132e055642626,
+ 16#01ee975283d71c93,
+ 16#00552321b06f5501,
+ 16#00c41d10a1e6a569,
+ 16#019158ecf8aa1e44,
+ 16#004e9fc949d0b5fc,
+ 16#0363da172811fdda,
+ 16#030e38c3b99181f2,
+ 16#0000000a118038fc]).
+-define(JUMPTOTALLEN, 1024).
+-define(RINGLEN, 16).
+
+-spec exs1024_jump(state()) -> state().
+
+exs1024_jump({Alg, {L, RL}}) ->
+ P = length(RL),
+ AS = exs1024_jump({L, RL},
+ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ ?JUMPCONSTTAIL, ?JUMPCONSTHEAD, ?JUMPELEMLEN, ?JUMPTOTALLEN),
+ {ASL, ASR} = lists:split(?RINGLEN - P, AS),
+ {Alg, {ASL, lists:reverse(ASR)}}.
+
+-spec exs1024_jump(state(), list(non_neg_integer()),
+ list(non_neg_integer()), non_neg_integer(),
+ non_neg_integer(), non_neg_integer()) -> list(non_neg_integer()).
+
+exs1024_jump(_, AS, _, _, _, 0) ->
+ AS;
+exs1024_jump(S, AS, [H|T], _, 0, TN) ->
+ exs1024_jump(S, AS, T, H, ?JUMPELEMLEN, TN);
+exs1024_jump({L, RL}, AS, JL, J, N, TN) ->
+ {_, NS} = exs1024_next({L, RL}),
+ case (J band 1) of
+ 1 ->
+ AS2 = lists:zipwith(fun(X, Y) -> X bxor Y end,
+ AS, L ++ lists:reverse(RL)),
+ exs1024_jump(NS, AS2, JL, J bsr 1, N-1, TN-1);
+ 0 ->
+ exs1024_jump(NS, AS, JL, J bsr 1, N-1, TN-1)
+ end.
+
%% =====================================================================
%% Ziggurat cont
%% =====================================================================
diff --git a/lib/stdlib/src/sets.erl b/lib/stdlib/src/sets.erl
index 3e70450320..c65a13b22e 100644
--- a/lib/stdlib/src/sets.erl
+++ b/lib/stdlib/src/sets.erl
@@ -128,14 +128,14 @@ is_element(E, S) ->
Set2 :: set(Element).
add_element(E, S0) ->
Slot = get_slot(S0, E),
- {S1,Ic} = on_bucket(fun (B0) -> add_bkt_el(E, B0, B0) end, S0, Slot),
- maybe_expand(S1, Ic).
-
--spec add_bkt_el(T, [T], [T]) -> {[T], 0 | 1}.
-add_bkt_el(E, [E|_], Bkt) -> {Bkt,0};
-add_bkt_el(E, [_|B], Bkt) ->
- add_bkt_el(E, B, Bkt);
-add_bkt_el(E, [], Bkt) -> {[E|Bkt],1}.
+ Bkt = get_bucket(S0, Slot),
+ case lists:member(E, Bkt) of
+ true ->
+ S0;
+ false ->
+ S1 = update_bucket(S0, Slot, [E | Bkt]),
+ maybe_expand(S1)
+ end.
%% del_element(Element, Set) -> Set.
%% Return Set but with Element removed.
@@ -144,15 +144,28 @@ add_bkt_el(E, [], Bkt) -> {[E|Bkt],1}.
Set2 :: set(Element).
del_element(E, S0) ->
Slot = get_slot(S0, E),
- {S1,Dc} = on_bucket(fun (B0) -> del_bkt_el(E, B0) end, S0, Slot),
- maybe_contract(S1, Dc).
+ Bkt = get_bucket(S0, Slot),
+ case lists:member(E, Bkt) of
+ false ->
+ S0;
+ true ->
+ S1 = update_bucket(S0, Slot, lists:delete(E, Bkt)),
+ maybe_contract(S1, 1)
+ end.
--spec del_bkt_el(T, [T]) -> {[T], 0 | 1}.
-del_bkt_el(E, [E|Bkt]) -> {Bkt,1};
-del_bkt_el(E, [Other|Bkt0]) ->
- {Bkt1,Dc} = del_bkt_el(E, Bkt0),
- {[Other|Bkt1],Dc};
-del_bkt_el(_, []) -> {[],0}.
+%% update_bucket(Set, Slot, NewBucket) -> UpdatedSet.
+%% Replace bucket in Slot by NewBucket
+-spec update_bucket(Set1, Slot, Bkt) -> Set2 when
+ Set1 :: set(Element),
+ Set2 :: set(Element),
+ Slot :: non_neg_integer(),
+ Bkt :: [Element].
+update_bucket(Set, Slot, NewBucket) ->
+ SegI = ((Slot-1) div ?seg_size) + 1,
+ BktI = ((Slot-1) rem ?seg_size) + 1,
+ Segs = Set#set.segs,
+ Seg = element(SegI, Segs),
+ Set#set{segs = setelement(SegI, Segs, setelement(BktI, Seg, NewBucket))}.
%% union(Set1, Set2) -> Set
%% Return the union of Set1 and Set2.
@@ -272,19 +285,6 @@ get_slot(T, Key) ->
-spec get_bucket(set(), non_neg_integer()) -> term().
get_bucket(T, Slot) -> get_bucket_s(T#set.segs, Slot).
-%% on_bucket(Fun, Hashdb, Slot) -> {NewHashDb,Result}.
-%% Apply Fun to the bucket in Slot and replace the returned bucket.
--spec on_bucket(fun((_) -> {[_], 0 | 1}), set(E), non_neg_integer()) ->
- {set(E), 0 | 1}.
-on_bucket(F, T, Slot) ->
- SegI = ((Slot-1) div ?seg_size) + 1,
- BktI = ((Slot-1) rem ?seg_size) + 1,
- Segs = T#set.segs,
- Seg = element(SegI, Segs),
- B0 = element(BktI, Seg),
- {B1, Res} = F(B0), %Op on the bucket.
- {T#set{segs = setelement(SegI, Segs, setelement(BktI, Seg, B1))},Res}.
-
%% fold_set(Fun, Acc, Dictionary) -> Dictionary.
%% filter_set(Fun, Dictionary) -> Dictionary.
@@ -349,8 +349,8 @@ put_bucket_s(Segs, Slot, Bkt) ->
Seg = setelement(BktI, element(SegI, Segs), Bkt),
setelement(SegI, Segs, Seg).
--spec maybe_expand(set(E), 0 | 1) -> set(E).
-maybe_expand(T0, Ic) when T0#set.size + Ic > T0#set.exp_size ->
+-spec maybe_expand(set(E)) -> set(E).
+maybe_expand(T0) when T0#set.size + 1 > T0#set.exp_size ->
T = maybe_expand_segs(T0), %Do we need more segments.
N = T#set.n + 1, %Next slot to expand into
Segs0 = T#set.segs,
@@ -360,12 +360,12 @@ maybe_expand(T0, Ic) when T0#set.size + Ic > T0#set.exp_size ->
{B1,B2} = rehash(B, Slot1, Slot2, T#set.maxn),
Segs1 = put_bucket_s(Segs0, Slot1, B1),
Segs2 = put_bucket_s(Segs1, Slot2, B2),
- T#set{size = T#set.size + Ic,
+ T#set{size = T#set.size + 1,
n = N,
exp_size = N * ?expand_load,
con_size = N * ?contract_load,
segs = Segs2};
-maybe_expand(T, Ic) -> T#set{size = T#set.size + Ic}.
+maybe_expand(T) -> T#set{size = T#set.size + 1}.
-spec maybe_expand_segs(set(E)) -> set(E).
maybe_expand_segs(T) when T#set.n =:= T#set.maxn ->
diff --git a/lib/stdlib/src/stdlib.appup.src b/lib/stdlib/src/stdlib.appup.src
index e917b7ea1f..979161fef7 100644
--- a/lib/stdlib/src/stdlib.appup.src
+++ b/lib/stdlib/src/stdlib.appup.src
@@ -18,9 +18,7 @@
%% %CopyrightEnd%
{"%VSN%",
%% Up from - max one major revision back
- [{<<"3\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
- {<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-18.*
+ [{<<"3\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.*
%% Down to - max one major revision back
- [{<<"3\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}, % OTP-19.*
- {<<"2\\.[5-8](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-18.*
+ [{<<"3\\.[0-1](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.*
}.
diff --git a/lib/stdlib/test/rand_SUITE.erl b/lib/stdlib/test/rand_SUITE.erl
index 02b7cb10c2..8e7ac223a7 100644
--- a/lib/stdlib/test/rand_SUITE.erl
+++ b/lib/stdlib/test/rand_SUITE.erl
@@ -28,7 +28,8 @@
api_eq/1, reference/1,
basic_stats_uniform_1/1, basic_stats_uniform_2/1,
basic_stats_normal/1,
- plugin/1, measure/1]).
+ plugin/1, measure/1,
+ reference_jump_state/1, reference_jump_procdict/1]).
-export([test/0, gen/1]).
@@ -45,14 +46,21 @@ all() ->
api_eq,
reference,
{group, basic_stats},
- plugin, measure].
+ plugin, measure,
+ {group, reference_jump}
+ ].
groups() ->
[{basic_stats, [parallel],
- [basic_stats_uniform_1, basic_stats_uniform_2, basic_stats_normal]}].
+ [basic_stats_uniform_1, basic_stats_uniform_2, basic_stats_normal]},
+ {reference_jump, [parallel],
+ [reference_jump_state, reference_jump_procdict]}].
group(basic_stats) ->
%% valgrind needs a lot of time
+ [{timetrap,{minutes,10}}];
+group(reference_jump) ->
+ %% valgrind needs a lot of time
[{timetrap,{minutes,10}}].
%% A simple helper to test without test_server during dev
@@ -228,7 +236,7 @@ interval_float_1(N) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%% Check if exs64 algorithm generates the proper sequence.
+%% Check if each algorithm generates the proper sequence.
reference(Config) when is_list(Config) ->
[reference_1(Alg) || Alg <- algs()],
ok.
@@ -242,7 +250,7 @@ reference_1(Alg) ->
io:format("Failed: ~p~n",[Alg]),
io:format("Length ~p ~p~n",[length(Refval), length(Testval)]),
io:format("Head ~p ~p~n",[hd(Refval), hd(Testval)]),
- ok
+ exit(wrong_value)
end.
gen(Algo) ->
@@ -434,6 +442,112 @@ measure_2(N, State0, Fun) when N > 0 ->
measure_2(0, _, _) -> ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% The jump sequence tests has two parts
+%% for those with the functional API (jump/1)
+%% and for those with the internal state
+%% in process dictionary (jump/0).
+
+-define(LOOP_JUMP, (?LOOP div 1000)).
+
+%% Check if each algorithm generates the proper jump sequence
+%% with the functional API.
+reference_jump_state(Config) when is_list(Config) ->
+ [reference_jump_1(Alg) || Alg <- algs()],
+ ok.
+
+reference_jump_1(Alg) ->
+ Refval = reference_jump_val(Alg),
+ Testval = gen_jump_1(Alg),
+ case Refval =:= Testval of
+ true -> ok;
+ false ->
+ io:format("Failed: ~p~n",[Alg]),
+ io:format("Length ~p ~p~n",[length(Refval), length(Testval)]),
+ io:format("Head ~p ~p~n",[hd(Refval), hd(Testval)]),
+ exit(wrong_value)
+ end.
+
+gen_jump_1(Algo) ->
+ Seed = case Algo of
+ exsplus -> %% Printed with orig 'C' code and this seed
+ rand:seed_s({exsplus, [12345678|12345678]});
+ exs1024 -> %% Printed with orig 'C' code and this seed
+ rand:seed_s({exs1024, {lists:duplicate(16, 12345678), []}});
+ exs64 -> %% Test exception of not_implemented notice
+ try rand:jump(rand:seed_s(exs64))
+ catch
+ error:not_implemented -> not_implemented
+ end;
+ _ -> % unimplemented
+ not_implemented
+ end,
+ case Seed of
+ not_implemented -> [not_implemented];
+ S -> gen_jump_1(?LOOP_JUMP, S, [])
+ end.
+
+gen_jump_1(N, State0 = {#{max:=Max}, _}, Acc) when N > 0 ->
+ {_, State1} = rand:uniform_s(Max, State0),
+ {Random, State2} = rand:uniform_s(Max, rand:jump(State1)),
+ case N rem (?LOOP_JUMP div 100) of
+ 0 -> gen_jump_1(N-1, State2, [Random|Acc]);
+ _ -> gen_jump_1(N-1, State2, Acc)
+ end;
+gen_jump_1(_, _, Acc) -> lists:reverse(Acc).
+
+%% Check if each algorithm generates the proper jump sequence
+%% with the internal state in the process dictionary.
+reference_jump_procdict(Config) when is_list(Config) ->
+ [reference_jump_0(Alg) || Alg <- algs()],
+ ok.
+
+reference_jump_0(Alg) ->
+ Refval = reference_jump_val(Alg),
+ Testval = gen_jump_0(Alg),
+ case Refval =:= Testval of
+ true -> ok;
+ false ->
+ io:format("Failed: ~p~n",[Alg]),
+ io:format("Length ~p ~p~n",[length(Refval), length(Testval)]),
+ io:format("Head ~p ~p~n",[hd(Refval), hd(Testval)]),
+ exit(wrong_value)
+ end.
+
+gen_jump_0(Algo) ->
+ Seed = case Algo of
+ exsplus -> %% Printed with orig 'C' code and this seed
+ rand:seed({exsplus, [12345678|12345678]});
+ exs1024 -> %% Printed with orig 'C' code and this seed
+ rand:seed({exs1024, {lists:duplicate(16, 12345678), []}});
+ exs64 -> %% Test exception of not_implemented notice
+ try
+ _ = rand:seed(exs64),
+ rand:jump()
+ catch
+ error:not_implemented -> not_implemented
+ end;
+ _ -> % unimplemented
+ not_implemented
+ end,
+ case Seed of
+ not_implemented -> [not_implemented];
+ S ->
+ {Seedmap=#{}, _} = S,
+ Max = maps:get(max, Seedmap),
+ gen_jump_0(?LOOP_JUMP, Max, [])
+ end.
+
+gen_jump_0(N, Max, Acc) when N > 0 ->
+ _ = rand:uniform(Max),
+ _ = rand:jump(),
+ Random = rand:uniform(Max),
+ case N rem (?LOOP_JUMP div 100) of
+ 0 -> gen_jump_0(N-1, Max, [Random|Acc]);
+ _ -> gen_jump_0(N-1, Max, Acc)
+ end;
+gen_jump_0(_, _, Acc) -> lists:reverse(Acc).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Data
reference_val(exs64) ->
[16#3737ad0c703ff6c3,16#3868a78fe71adbbd,16#1f01b62b4338b605,16#50876a917437965f,
@@ -515,3 +629,61 @@ reference_val(exsplus) ->
16#36f715a249f4ec2,16#1c27629826c50d3,16#914d9a6648726a,16#27f5bf5ce2301e8,
16#3dd493b8012970f,16#be13bed1e00e5c,16#ceef033b74ae10,16#3da38c6a50abe03,
16#15cbd1a421c7a8c,16#22794e3ec6ef3b1,16#26154d26e7ea99f,16#3a66681359a6ab6].
+
+%%%
+
+reference_jump_val(exsplus) ->
+ [82445318862816932, 145810727464480743, 16514517716894509, 247642377064868650,
+ 162385642339156908, 251810707075252101, 82288275771998924, 234412731596926322,
+ 49960883129071044, 200690077681656596, 213743196668671647, 131182800982967108,
+ 144200072021941728, 263557425008503277, 194858522616874272, 185869394820993172,
+ 80384502675241453, 262654144824057588, 90033295011291362, 4494510449302659,
+ 226005372746479588, 116780561309220553, 47048528594475843, 39168929349768743,
+ 139615163424415552, 55330632656603925, 237575574720486569, 102381140288455025,
+ 18452933910354323, 150248612130579752, 269358096791922740, 61313433522002187,
+ 160327361842676597, 185187983548528938, 57378981505594193, 167510799293984067,
+ 105117045862954303, 176126685946302943, 123590876906828803, 69185336947273487,
+ 9098689247665808, 49906154674145057, 131575138412788650, 161843880211677185,
+ 30743946051071186, 187578920583823612, 45008401528636978, 122454158686456658,
+ 111195992644229524, 17962783958752862, 13579507636941108, 130137843317798663,
+ 144202635170576832, 132539563255093922, 159785575703967124, 187241848364816640,
+ 183044737781926478, 12921559769912263, 83553932242922001, 96698298841984688,
+ 281664320227537824, 224233030818578263, 77812932110318774, 169729351013291728,
+ 164475402723178734, 242780633011249051, 51095111179609125, 19249189591963554,
+ 221412426221439180, 265700202856282653, 265342254311932308, 241218503498385511,
+ 255400887248486575, 212083616929812076, 227947034485840579, 268261881651571692,
+ 104846262373404908, 49690734329496661, 213259196633566308, 186966479726202436,
+ 282157378232384574, 11272948584603747, 166540426999573480, 50628164001018755,
+ 65235580992800860, 230664399047956956, 64575592354687978, 40519393736078511,
+ 108341851194332747, 115426411532008961, 120656817002338193, 234537867870809797,
+ 12504080415362731, 45083100453836317, 270968267812126657, 93505647407734103,
+ 252852934678537969, 258758309277167202, 74250882143432077, 141629095984552833];
+
+reference_jump_val(exs1024) ->
+ [2655961906500790629, 17003395417078685063, 10466831598958356428, 7603399148503548021,
+ 1650550950190587188, 12294992315080723704, 15743995773860389219, 5492181000145247327,
+ 14118165228742583601, 1024386975263610703, 10124872895886669513, 6445624517813169301,
+ 6238575554686562601, 14108646153524288915, 11804141635807832816, 8421575378006186238,
+ 6354993374304550369, 838493020029548163, 14759355804308819469, 12212491527912522022,
+ 16943204735100571602, 198964074252287588, 7325922870779721649, 15853102065526570574,
+ 16294058349151823341, 6153379962047409781, 15874031679495957261, 17299265255608442340,
+ 984658421210027171, 17408042033939375278, 3326465916992232353, 5222817718770538733,
+ 13262385796795170510, 15648751121811336061, 6718721549566546451, 7353765235619801875,
+ 16110995049882478788, 14559143407227563441, 4189805181268804683, 10938587948346538224,
+ 1635025506014383478, 12619562911869525411, 17469465615861488695, 125252234176411528,
+ 2004192558503448853, 13175467866790974840, 17712272336167363518, 1710549840100880318,
+ 17486892343528340916, 5337910082227550967, 8333082060923612691, 6284787745504163856,
+ 8072221024586708290, 6077032673910717705, 11495200863352251610, 11722792537523099594,
+ 14642059504258647996, 8595733246938141113, 17223366528010341891, 17447739753327015776,
+ 6149800490736735996, 11155866914574313276, 7123864553063709909, 15982886296520662323,
+ 5775920250955521517, 8624640108274906072, 8652974210855988961, 8715770416136907275,
+ 11841689528820039868, 10991309078149220415, 11758038663970841716, 7308750055935299261,
+ 15939068400245256963, 6920341533033919644, 8017706063646646166, 15814376391419160498,
+ 13529376573221932937, 16749061963269842448, 14639730709921425830, 3265850480169354066,
+ 4569394597532719321, 16594515239012200038, 13372824240764466517, 16892840440503406128,
+ 11260004846380394643, 2441660009097834955, 10566922722880085440, 11463315545387550692,
+ 5252492021914937692, 10404636333478845345, 11109538423683960387, 5525267334484537655,
+ 17936751184378118743, 4224632875737239207, 15888641556987476199, 9586888813112229805,
+ 9476861567287505094, 14909536929239540332, 17996844556292992842, 2699310519182298856];
+
+reference_jump_val(exs64) -> [not_implemented].
diff --git a/otp_versions.table b/otp_versions.table
index 1378f6afea..793f7bcd28 100644
--- a/otp_versions.table
+++ b/otp_versions.table
@@ -1,3 +1,4 @@
+OTP-19.1.6 : erts-8.1.1 # asn1-4.0.4 common_test-1.12.3 compiler-7.0.2 cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.1 cosTime-1.2.2 cosTransactions-1.3.2 crypto-3.7.1 debugger-4.2.1 dialyzer-3.0.2 diameter-1.12.1 edoc-0.8 eldap-1.2.2 erl_docgen-0.6 erl_interface-3.9.1 et-1.6 eunit-2.3.1 gs-1.6.2 hipe-3.15.2 ic-4.4.2 inets-6.3.3 jinterface-1.7.1 kernel-5.1 megaco-3.18.1 mnesia-4.14.1 observer-2.2.2 odbc-2.11.3 orber-3.8.2 os_mon-2.4.1 otp_mibs-1.1.1 parsetools-2.1.3 percept-0.9 public_key-1.2 reltool-0.7.2 runtime_tools-1.10.1 sasl-3.0.1 snmp-5.2.4 ssh-4.3.6 ssl-8.0.3 stdlib-3.1 syntax_tools-2.1 tools-2.8.6 typer-0.9.11 wx-1.7.1 xmerl-1.3.12 :
OTP-19.1.5 : ssh-4.3.6 # asn1-4.0.4 common_test-1.12.3 compiler-7.0.2 cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.1 cosTime-1.2.2 cosTransactions-1.3.2 crypto-3.7.1 debugger-4.2.1 dialyzer-3.0.2 diameter-1.12.1 edoc-0.8 eldap-1.2.2 erl_docgen-0.6 erl_interface-3.9.1 erts-8.1 et-1.6 eunit-2.3.1 gs-1.6.2 hipe-3.15.2 ic-4.4.2 inets-6.3.3 jinterface-1.7.1 kernel-5.1 megaco-3.18.1 mnesia-4.14.1 observer-2.2.2 odbc-2.11.3 orber-3.8.2 os_mon-2.4.1 otp_mibs-1.1.1 parsetools-2.1.3 percept-0.9 public_key-1.2 reltool-0.7.2 runtime_tools-1.10.1 sasl-3.0.1 snmp-5.2.4 ssl-8.0.3 stdlib-3.1 syntax_tools-2.1 tools-2.8.6 typer-0.9.11 wx-1.7.1 xmerl-1.3.12 :
OTP-19.1.4 : ssh-4.3.5 # asn1-4.0.4 common_test-1.12.3 compiler-7.0.2 cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.1 cosTime-1.2.2 cosTransactions-1.3.2 crypto-3.7.1 debugger-4.2.1 dialyzer-3.0.2 diameter-1.12.1 edoc-0.8 eldap-1.2.2 erl_docgen-0.6 erl_interface-3.9.1 erts-8.1 et-1.6 eunit-2.3.1 gs-1.6.2 hipe-3.15.2 ic-4.4.2 inets-6.3.3 jinterface-1.7.1 kernel-5.1 megaco-3.18.1 mnesia-4.14.1 observer-2.2.2 odbc-2.11.3 orber-3.8.2 os_mon-2.4.1 otp_mibs-1.1.1 parsetools-2.1.3 percept-0.9 public_key-1.2 reltool-0.7.2 runtime_tools-1.10.1 sasl-3.0.1 snmp-5.2.4 ssl-8.0.3 stdlib-3.1 syntax_tools-2.1 tools-2.8.6 typer-0.9.11 wx-1.7.1 xmerl-1.3.12 :
OTP-19.1.3 : ssh-4.3.4 # asn1-4.0.4 common_test-1.12.3 compiler-7.0.2 cosEvent-2.2.1 cosEventDomain-1.2.1 cosFileTransfer-1.2.1 cosNotification-1.2.2 cosProperty-1.2.1 cosTime-1.2.2 cosTransactions-1.3.2 crypto-3.7.1 debugger-4.2.1 dialyzer-3.0.2 diameter-1.12.1 edoc-0.8 eldap-1.2.2 erl_docgen-0.6 erl_interface-3.9.1 erts-8.1 et-1.6 eunit-2.3.1 gs-1.6.2 hipe-3.15.2 ic-4.4.2 inets-6.3.3 jinterface-1.7.1 kernel-5.1 megaco-3.18.1 mnesia-4.14.1 observer-2.2.2 odbc-2.11.3 orber-3.8.2 os_mon-2.4.1 otp_mibs-1.1.1 parsetools-2.1.3 percept-0.9 public_key-1.2 reltool-0.7.2 runtime_tools-1.10.1 sasl-3.0.1 snmp-5.2.4 ssl-8.0.3 stdlib-3.1 syntax_tools-2.1 tools-2.8.6 typer-0.9.11 wx-1.7.1 xmerl-1.3.12 :