aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/erl.xml5
-rw-r--r--erts/doc/src/erl_driver.xml4
-rw-r--r--erts/doc/src/erlang.xml24
-rw-r--r--erts/doc/src/notes.xml44
-rw-r--r--erts/emulator/beam/beam_bif_load.c4
-rw-r--r--erts/emulator/beam/beam_emu.c2
-rw-r--r--erts/emulator/beam/beam_load.c2
-rw-r--r--erts/emulator/beam/beam_load.h3
-rw-r--r--erts/emulator/beam/bif.tab1
-rw-r--r--erts/emulator/beam/dist.c1
-rw-r--r--erts/emulator/beam/erl_fun.c24
-rw-r--r--erts/emulator/beam/erl_fun.h3
-rw-r--r--erts/emulator/beam/erl_math.c5
-rw-r--r--erts/emulator/beam/erl_nif.c6
-rw-r--r--erts/emulator/beam/external.c2
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.c7
-rw-r--r--erts/emulator/hipe/hipe_mode_switch.h2
-rw-r--r--erts/emulator/sys/unix/sys.c2
-rw-r--r--erts/emulator/test/code_SUITE.erl168
-rw-r--r--erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl167
-rw-r--r--erts/emulator/test/nif_SUITE.erl18
-rw-r--r--erts/emulator/test/nif_SUITE_data/hipe_compiled.erl6
-rw-r--r--erts/emulator/test/port_SUITE.erl25
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin55752 -> 55804 bytes
-rw-r--r--erts/preloaded/ebin/erlang.beambin105884 -> 105940 bytes
-rw-r--r--erts/preloaded/ebin/erts_internal.beambin10872 -> 10896 bytes
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl23
-rw-r--r--erts/preloaded/src/erlang.erl3
-rw-r--r--erts/preloaded/src/erts_internal.erl3
-rw-r--r--erts/vsn.mk2
30 files changed, 361 insertions, 195 deletions
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index eb1d24cf12..f39b640c7e 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -250,6 +250,11 @@
environment variable <c><![CDATA[DISPLAY]]></c> set to
<c><![CDATA[gin:0]]></c>.</p>
</item>
+ <tag><c><![CDATA[-epmd_module Module]]></c> (init flag)</tag>
+ <item>
+ <p>Configures the module responsible to communicate to
+ <seealso marker="epmd">epmd</seealso>. Defaults to <c>erl_epmd</c>.</p>
+ </item>
<tag><c><![CDATA[-eval Expr]]></c> (init flag)</tag>
<item>
<p>Makes <c><![CDATA[init]]></c> evaluate the expression
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index 5191742bc9..d8bf45c523 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -2039,7 +2039,7 @@ r = driver_async(myPort, &myKey, myData, myFunc); ]]></code>
<fsummary>Set and get limits for busy port message queue.</fsummary>
<desc>
<marker id="erl_drv_busy_msgq_limits"></marker>
- <p>Sets and gets limits that will be used for controling the
+ <p>Sets and gets limits that will be used for controlling the
busy state of the port message queue.</p>
<p>The port message queue is set into a busy
state when the amount of command data queued on the
@@ -2112,7 +2112,7 @@ r = driver_async(myPort, &myKey, myData, myFunc); ]]></code>
It is used to identify the condition variable in planned
future debug functionality.</p>
<p>Returns <c>NULL</c> on failure. The driver
- creating the condition variable is responsibile for
+ creating the condition variable is responsible for
destroying it before the driver is unloaded.</p>
<p>This function is thread-safe.</p>
</desc>
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 3d1775e973..3dad09365e 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -2618,6 +2618,10 @@ os_prompt%</pre>
code of a module that has been upgraded; this is not
allowed.
</item>
+ <tag><c>notsup</c></tag>
+ <item>Lack of support. Such as loading NIF library for a
+ HiPE compiled module.
+ </item>
</taglist>
</desc>
</func>
@@ -9564,6 +9568,10 @@ timestamp() ->
<type name="trace_info_item_result"/>
<type name="trace_info_flag"/>
<type name="trace_match_spec"/>
+ <type name="match_variable"/>
+ <type_desc name="match_variable">
+ Approximation of '$1' | '$2' | '$3' | ...
+ </type_desc>
<desc>
<p>Returns trace information about a port, process, function, or
event.</p>
@@ -9695,6 +9703,10 @@ timestamp() ->
</fsummary>
<type name="trace_pattern_mfa"/>
<type name="trace_match_spec"/>
+ <type_desc name="match_variable">
+ Approximation of '$1' | '$2' | '$3' | ...
+ </type_desc>
+ <type name="match_variable"/>
<desc>
<p>The same as
<seealso marker="#trace_pattern/3">
@@ -9707,6 +9719,10 @@ timestamp() ->
<name name="trace_pattern" arity="3" clause_i="1"/>
<fsummary>Set trace pattern for message sending.</fsummary>
<type name="trace_match_spec"/>
+ <type name="match_variable"/>
+ <type_desc name="match_variable">
+ Approximation of '$1' | '$2' | '$3' | ...
+ </type_desc>
<desc>
<p>Sets trace pattern for <em>message sending</em>.
Must be combined with
@@ -9774,6 +9790,10 @@ timestamp() ->
<name name="trace_pattern" arity="3" clause_i="2"/>
<fsummary>Set trace pattern for tracing of message receiving.</fsummary>
<type name="trace_match_spec"/>
+ <type name="match_variable"/>
+ <type_desc name="match_variable">
+ Approximation of '$1' | '$2' | '$3' | ...
+ </type_desc>
<desc>
<p>Sets trace pattern for <em>message receiving</em>.
Must be combined with
@@ -9844,6 +9864,10 @@ timestamp() ->
<type name="trace_pattern_mfa"/>
<type name="trace_match_spec"/>
<type name="trace_pattern_flag"/>
+ <type name="match_variable"/>
+ <type_desc name="match_variable">
+ Approximation of '$1' | '$2' | '$3' | ...
+ </type_desc>
<desc>
<p>Enables or disables <em>call tracing</em> for one or more functions.
Must be combined with
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/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 099abad4e1..e7301b1b4b 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -1397,10 +1397,10 @@ erts_purge_state_add_fun(ErlFunEntry *fe)
}
Export *
-erts_suspend_process_on_pending_purge_lambda(Process *c_p)
+erts_suspend_process_on_pending_purge_lambda(Process *c_p, ErlFunEntry* fe)
{
erts_smp_mtx_lock(&purge_state.mtx);
- if (is_value(purge_state.module)) {
+ if (purge_state.module == fe->module) {
/*
* The process c_p is about to call a fun in the code
* that we are trying to purge. Suspend it and call
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 84e2d42af6..7eaa7a0d8b 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -6547,7 +6547,7 @@ call_fun(Process* p, /* Current process. */
* and let it try again when the purge operation is
* done (may succeed or not).
*/
- ep = erts_suspend_process_on_pending_purge_lambda(p);
+ ep = erts_suspend_process_on_pending_purge_lambda(p, fe);
ASSERT(ep);
}
else {
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 36cf64e08d..3cd395c2c1 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -4848,7 +4848,7 @@ final_touch(LoaderState* stp, struct erl_module_instance* inst_p)
}
fe->address = code_ptr;
#ifdef HIPE
- hipe_set_closure_stub(fe, stp->lambdas[i].num_free);
+ hipe_set_closure_stub(fe);
#endif
}
}
diff --git a/erts/emulator/beam/beam_load.h b/erts/emulator/beam/beam_load.h
index 6a3110d0f5..d420a4346c 100644
--- a/erts/emulator/beam/beam_load.h
+++ b/erts/emulator/beam/beam_load.h
@@ -116,7 +116,8 @@ int erts_is_module_native(BeamCodeHeader* code);
void erts_beam_bif_load_init(void);
struct erl_fun_entry;
void erts_purge_state_add_fun(struct erl_fun_entry *fe);
-Export *erts_suspend_process_on_pending_purge_lambda(Process *c_p);
+Export *erts_suspend_process_on_pending_purge_lambda(Process *c_p,
+ struct erl_fun_entry*);
/*
* Layout of the line table.
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index 852b1135fe..32600f4338 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -667,6 +667,7 @@ gcbif erlang:floor/1
gcbif erlang:ceil/1
bif math:floor/1
bif math:ceil/1
+bif math:fmod/2
#
# Obsolete
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 09c83f1117..9bfeaa3379 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -25,6 +25,7 @@
/* define this to get a lot of debug output */
/* #define ERTS_DIST_MSG_DBG */
+/* #define ERTS_RAW_DIST_MSG_DBG */
#ifdef HAVE_CONFIG_H
# include "config.h"
diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c
index 9deec946d5..d9118d2549 100644
--- a/erts/emulator/beam/erl_fun.c
+++ b/erts/emulator/beam/erl_fun.c
@@ -31,6 +31,9 @@
static Hash erts_fun_table;
#include "erl_smp.h"
+#ifdef HIPE
+# include "hipe_mode_switch.h"
+#endif
static erts_smp_rwmtx_t erts_fun_table_lock;
@@ -219,6 +222,10 @@ erts_fun_purge_prepare(BeamInstr* start, BeamInstr* end)
fe->pend_purge_address = addr;
ERTS_SMP_WRITE_MEMORY_BARRIER;
fe->address = unloaded_fun;
+#ifdef HIPE
+ fe->pend_purge_native_address = fe->native_address;
+ hipe_set_closure_stub(fe);
+#endif
erts_purge_state_add_fun(fe);
}
b = b->next;
@@ -234,9 +241,12 @@ erts_fun_purge_abort_prepare(ErlFunEntry **funs, Uint no)
for (ix = 0; ix < no; ix++) {
ErlFunEntry *fe = funs[ix];
- if (fe->address == unloaded_fun)
+ if (fe->address == unloaded_fun) {
fe->address = fe->pend_purge_address;
- fe->pend_purge_address = NULL;
+#ifdef HIPE
+ fe->native_address = fe->pend_purge_native_address;
+#endif
+ }
}
}
@@ -245,8 +255,12 @@ erts_fun_purge_abort_finalize(ErlFunEntry **funs, Uint no)
{
Uint ix;
- for (ix = 0; ix < no; ix++)
+ for (ix = 0; ix < no; ix++) {
funs[ix]->pend_purge_address = NULL;
+#ifdef HIPE
+ funs[ix]->pend_purge_native_address = NULL;
+#endif
+ }
}
void
@@ -257,6 +271,9 @@ erts_fun_purge_complete(ErlFunEntry **funs, Uint no)
for (ix = 0; ix < no; ix++) {
ErlFunEntry *fe = funs[ix];
fe->pend_purge_address = NULL;
+#ifdef HIPE
+ fe->pend_purge_native_address = NULL;
+#endif
if (erts_refc_dectest(&fe->refc, 0) == 0)
erts_erase_fun_entry(fe);
}
@@ -325,6 +342,7 @@ fun_alloc(ErlFunEntry* template)
obj->pend_purge_address = NULL;
#ifdef HIPE
obj->native_address = NULL;
+ obj->pend_purge_native_address = NULL;
#endif
return obj;
}
diff --git a/erts/emulator/beam/erl_fun.h b/erts/emulator/beam/erl_fun.h
index 6ba055d92c..717bfee0fb 100644
--- a/erts/emulator/beam/erl_fun.h
+++ b/erts/emulator/beam/erl_fun.h
@@ -45,6 +45,9 @@ typedef struct erl_fun_entry {
erts_refc_t refc; /* Reference count: One for code + one for each
fun object in each process. */
BeamInstr *pend_purge_address; /* address stored during a pending purge */
+#ifdef HIPE
+ UWord* pend_purge_native_address;
+#endif
} ErlFunEntry;
/*
diff --git a/erts/emulator/beam/erl_math.c b/erts/emulator/beam/erl_math.c
index 990fa63bd4..1f270eb55f 100644
--- a/erts/emulator/beam/erl_math.c
+++ b/erts/emulator/beam/erl_math.c
@@ -256,3 +256,8 @@ BIF_RETTYPE math_floor_1(BIF_ALIST_1)
{
return math_call_1(BIF_P, floor, BIF_ARG_1);
}
+
+BIF_RETTYPE math_fmod_2(BIF_ALIST_2)
+{
+ return math_call_2(BIF_P, fmod, BIF_ARG_1, BIF_ARG_2);
+}
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index c5606f72a1..9872a3ab81 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -3166,6 +3166,12 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
struct erl_module_instance* this_mi;
struct erl_module_instance* prev_mi;
+ if (BIF_P->flags & F_HIPE_MODE) {
+ ret = load_nif_error(BIF_P, "notsup", "Calling load_nif from HiPE compiled "
+ "modules not supported");
+ BIF_RET(ret);
+ }
+
encoding = erts_get_native_filename_encoding();
if (encoding == ERL_FILENAME_WIN_WCHAR) {
/* Do not convert the lib name to utf-16le yet, do that in win32 specific code */
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 98df8a0726..a49b242d7c 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -3748,7 +3748,7 @@ dec_term_atom_common:
funp->arity = arity;
#ifdef HIPE
if (funp->fe->native_address == NULL) {
- hipe_set_closure_stub(funp->fe, num_free);
+ hipe_set_closure_stub(funp->fe);
}
#endif
hp = factory->hp;
diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c
index ed95045292..0706f8d2c9 100644
--- a/erts/emulator/hipe/hipe_mode_switch.c
+++ b/erts/emulator/hipe/hipe_mode_switch.c
@@ -718,12 +718,9 @@ void hipe_empty_nstack(Process *p)
p->hipe.nstend = NULL;
}
-void hipe_set_closure_stub(ErlFunEntry *fe, unsigned num_free)
+void hipe_set_closure_stub(ErlFunEntry *fe)
{
- unsigned arity;
-
- arity = fe->arity;
- fe->native_address = (Eterm*) hipe_closure_stub_address(arity);
+ fe->native_address = (Eterm*) hipe_closure_stub_address(fe->arity);
}
Eterm hipe_build_stacktrace(Process *p, struct StackTrace *s)
diff --git a/erts/emulator/hipe/hipe_mode_switch.h b/erts/emulator/hipe/hipe_mode_switch.h
index c40077d558..334e978307 100644
--- a/erts/emulator/hipe/hipe_mode_switch.h
+++ b/erts/emulator/hipe/hipe_mode_switch.h
@@ -59,7 +59,7 @@ void hipe_set_call_trap(Uint *bfun, void *nfun, int is_closure);
Process *hipe_mode_switch(Process*, unsigned, Eterm*);
void hipe_inc_nstack(Process *p);
void hipe_empty_nstack(Process *p);
-void hipe_set_closure_stub(ErlFunEntry *fe, unsigned num_free);
+void hipe_set_closure_stub(ErlFunEntry *fe);
Eterm hipe_build_stacktrace(Process *p, struct StackTrace *s);
ERTS_GLB_INLINE void hipe_reserve_beam_trap_frame(Process*, Eterm reg[], unsigned arity);
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/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl
index 465ddfa7a8..774461c525 100644
--- a/erts/emulator/test/code_SUITE.erl
+++ b/erts/emulator/test/code_SUITE.erl
@@ -153,127 +153,23 @@ call_purged_fun_code_there(Config) when is_list(Config) ->
ok.
call_purged_fun_test(Priv, Data, Type) ->
- File = filename:join(Data, "my_code_test2"),
- Code = filename:join(Priv, "my_code_test2"),
-
- catch erlang:purge_module(my_code_test2),
- catch erlang:delete_module(my_code_test2),
- catch erlang:purge_module(my_code_test2),
-
- {ok,my_code_test2} = c:c(File, [{outdir,Priv}]),
-
- T = ets:new(my_code_test2_fun_table, []),
- ets:insert(T, {my_fun,my_code_test2:make_fun(4711)}),
- ets:insert(T, {my_fun2,my_code_test2:make_fun2()}),
-
- spawn(fun () ->
- [{my_fun2,F2}] = ets:lookup(T, my_fun2),
- F2(fun () ->
- receive after infinity -> ok end
- end,
- fun () -> ok end),
- exit(completed)
- end),
-
- PurgeType = case Type of
- code_gone ->
- ok = file:delete(Code++".beam"),
- true;
- code_reload ->
- true;
- code_there ->
- false
- end,
-
- true = erlang:delete_module(my_code_test2),
-
- Purge = start_purge(my_code_test2, PurgeType),
-
- {P0, M0} = spawn_monitor(fun () ->
- [{my_fun,F}] = ets:lookup(T, my_fun),
- 4712 = F(1),
- exit(completed)
- end),
-
- wait_until(fun () ->
- {status, suspended}
- == process_info(P0, status)
- end),
-
- ok = continue_purge(Purge),
-
- {P1, M1} = spawn_monitor(fun () ->
- [{my_fun,F}] = ets:lookup(T, my_fun),
- 4713 = F(2),
- exit(completed)
- end),
- {P2, M2} = spawn_monitor(fun () ->
- [{my_fun,F}] = ets:lookup(T, my_fun),
- 4714 = F(3),
- exit(completed)
- end),
-
- wait_until(fun () ->
- {status, suspended}
- == process_info(P1, status)
- end),
- wait_until(fun () ->
- {status, suspended}
- == process_info(P2, status)
- end),
-
- {current_function,
- {erts_code_purger,
- pending_purge_lambda,
- 3}} = process_info(P0, current_function),
- {current_function,
- {erts_code_purger,
- pending_purge_lambda,
- 3}} = process_info(P1, current_function),
- {current_function,
- {erts_code_purger,
- pending_purge_lambda,
- 3}} = process_info(P2, current_function),
-
- case Type of
- code_there ->
- false = complete_purge(Purge);
- _ ->
- {true, true} = complete_purge(Purge)
- end,
+ OptsList = case erlang:system_info(hipe_architecture) of
+ undefined -> [[]];
+ _ -> [[], [native]]
+ end,
+ [call_purged_fun_test_do(Priv, Data, Type, CO, FO)
+ || CO <- OptsList, FO <- OptsList].
+
+
+call_purged_fun_test_do(Priv, Data, Type, CallerOpts, FunOpts) ->
+ io:format("Compile caller as ~p and funs as ~p\n", [CallerOpts, FunOpts]),
+ SrcFile = filename:join(Data, "call_purged_fun_tester.erl"),
+ ObjFile = filename:join(Priv, "call_purged_fun_tester.beam"),
+ {ok,Mod,Code} = compile:file(SrcFile, [binary, report | CallerOpts]),
+ {module,Mod} = code:load_binary(Mod, ObjFile, Code),
+
+ call_purged_fun_tester:do(Priv, Data, Type, FunOpts).
- case Type of
- code_gone ->
- receive
- {'DOWN', M0, process, P0, Reason0} ->
- {undef, _} = Reason0
- end,
- receive
- {'DOWN', M1, process, P1, Reason1} ->
- {undef, _} = Reason1
- end,
- receive
- {'DOWN', M2, process, P2, Reason2} ->
- {undef, _} = Reason2
- end;
- _ ->
- receive
- {'DOWN', M0, process, P0, Reason0} ->
- completed = Reason0
- end,
- receive
- {'DOWN', M1, process, P1, Reason1} ->
- completed = Reason1
- end,
- receive
- {'DOWN', M2, process, P2, Reason2} ->
- completed = Reason2
- end,
- catch erlang:purge_module(my_code_test2),
- catch erlang:delete_module(my_code_test2),
- catch erlang:purge_module(my_code_test2)
- end,
- ok.
multi_proc_purge(Config) when is_list(Config) ->
%%
@@ -975,35 +871,3 @@ flush() ->
id(I) -> I.
-wait_until(Fun) ->
- case Fun() of
- true ->
- ok;
- false ->
- receive after 100 -> ok end,
- wait_until(Fun)
- end.
-
-start_purge(Mod, Type) when is_atom(Mod)
- andalso ((Type == true)
- orelse (Type == false)) ->
- Ref = make_ref(),
- erts_code_purger ! {test_purge, Mod, self(), Type, Ref},
- receive
- {started, Ref} ->
- Ref
- end.
-
-continue_purge(Ref) when is_reference(Ref) ->
- erts_code_purger ! {continue, Ref},
- receive
- {continued, Ref} ->
- ok
- end.
-
-complete_purge(Ref) when is_reference(Ref) ->
- erts_code_purger ! {complete, Ref},
- receive
- {test_purge, Res, Ref} ->
- Res
- end.
diff --git a/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl
new file mode 100644
index 0000000000..5e031abca8
--- /dev/null
+++ b/erts/emulator/test/code_SUITE_data/call_purged_fun_tester.erl
@@ -0,0 +1,167 @@
+-module(call_purged_fun_tester).
+
+-export([do/4]).
+
+do(Priv, Data, Type, Opts) ->
+ File = filename:join(Data, "my_code_test2"),
+ Code = filename:join(Priv, "my_code_test2"),
+
+ catch erlang:purge_module(my_code_test2),
+ catch erlang:delete_module(my_code_test2),
+ catch erlang:purge_module(my_code_test2),
+
+ {ok,my_code_test2} = c:c(File, [{outdir,Priv} | Opts]),
+
+ IsNative = lists:member(native,Opts),
+ IsNative = code:is_module_native(my_code_test2),
+
+ T = ets:new(my_code_test2_fun_table, []),
+ ets:insert(T, {my_fun,my_code_test2:make_fun(4711)}),
+ ets:insert(T, {my_fun2,my_code_test2:make_fun2()}),
+
+ spawn(fun () ->
+ [{my_fun2,F2}] = ets:lookup(T, my_fun2),
+ F2(fun () ->
+ receive after infinity -> ok end
+ end,
+ fun () -> ok end),
+ exit(completed)
+ end),
+
+ PurgeType = case Type of
+ code_gone ->
+ ok = file:delete(Code++".beam"),
+ true;
+ code_reload ->
+ true;
+ code_there ->
+ false
+ end,
+
+ true = erlang:delete_module(my_code_test2),
+
+ Purge = start_purge(my_code_test2, PurgeType),
+
+ {P0, M0} = spawn_monitor(fun () ->
+ [{my_fun,F}] = ets:lookup(T, my_fun),
+ 4712 = F(1),
+ exit(completed)
+ end),
+
+ wait_until(fun () ->
+ {status, suspended}
+ == process_info(P0, status)
+ end),
+
+ ok = continue_purge(Purge),
+
+ {P1, M1} = spawn_monitor(fun () ->
+ [{my_fun,F}] = ets:lookup(T, my_fun),
+ 4713 = F(2),
+ exit(completed)
+ end),
+ {P2, M2} = spawn_monitor(fun () ->
+ [{my_fun,F}] = ets:lookup(T, my_fun),
+ 4714 = F(3),
+ exit(completed)
+ end),
+
+ wait_until(fun () ->
+ {status, suspended}
+ == process_info(P1, status)
+ end),
+ wait_until(fun () ->
+ {status, suspended}
+ == process_info(P2, status)
+ end),
+
+ {current_function,
+ {erts_code_purger,
+ pending_purge_lambda,
+ 3}} = process_info(P0, current_function),
+ {current_function,
+ {erts_code_purger,
+ pending_purge_lambda,
+ 3}} = process_info(P1, current_function),
+ {current_function,
+ {erts_code_purger,
+ pending_purge_lambda,
+ 3}} = process_info(P2, current_function),
+
+ case Type of
+ code_there ->
+ false = complete_purge(Purge);
+ _ ->
+ {true, true} = complete_purge(Purge)
+ end,
+
+ case Type of
+ code_gone ->
+ receive
+ {'DOWN', M0, process, P0, Reason0} ->
+ {undef, _} = Reason0
+ end,
+ receive
+ {'DOWN', M1, process, P1, Reason1} ->
+ {undef, _} = Reason1
+ end,
+ receive
+ {'DOWN', M2, process, P2, Reason2} ->
+ {undef, _} = Reason2
+ end;
+ _ ->
+ receive
+ {'DOWN', M0, process, P0, Reason0} ->
+ completed = Reason0
+ end,
+ receive
+ {'DOWN', M1, process, P1, Reason1} ->
+ completed = Reason1
+ end,
+ receive
+ {'DOWN', M2, process, P2, Reason2} ->
+ completed = Reason2
+ end,
+ catch erlang:purge_module(my_code_test2),
+ catch erlang:delete_module(my_code_test2),
+ catch erlang:purge_module(my_code_test2)
+ end,
+ ok.
+
+wait_until(Fun) ->
+ ok = wait_until(Fun, 20).
+
+wait_until(Fun, N) ->
+ case {Fun(),N} of
+ {true, _} ->
+ ok;
+ {false, 0} ->
+ timeout;
+ {false, _} ->
+ receive after 100 -> ok end,
+ wait_until(Fun, N-1)
+ end.
+
+start_purge(Mod, Type) when is_atom(Mod)
+ andalso ((Type == true)
+ orelse (Type == false)) ->
+ Ref = make_ref(),
+ erts_code_purger ! {test_purge, Mod, self(), Type, Ref},
+ receive
+ {started, Ref} ->
+ Ref
+ end.
+
+continue_purge(Ref) when is_reference(Ref) ->
+ erts_code_purger ! {continue, Ref},
+ receive
+ {continued, Ref} ->
+ ok
+ end.
+
+complete_purge(Ref) when is_reference(Ref) ->
+ erts_code_purger ! {complete, Ref},
+ receive
+ {test_purge, Res, Ref} ->
+ Res
+ end.
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index 306f2091a1..3a76ee6aee 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -30,6 +30,7 @@
init_per_testcase/2, end_per_testcase/2,
basic/1, reload_error/1, upgrade/1, heap_frag/1,
t_on_load/1,
+ hipe/1,
types/1, many_args/1, binaries/1, get_string/1, get_atom/1,
maps/1,
api_macros/1,
@@ -70,6 +71,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[basic, reload_error, upgrade, heap_frag, types, many_args,
t_on_load,
+ hipe,
binaries, get_string, get_atom, maps, api_macros, from_array,
iolist_as_binary, resource, resource_binary,
resource_takeover, threading, send, send2, send3,
@@ -88,6 +90,11 @@ all() ->
init_per_testcase(t_on_load, Config) ->
ets:new(nif_SUITE, [named_table]),
Config;
+init_per_testcase(hipe, Config) ->
+ case erlang:system_info(hipe_architecture) of
+ undefined -> {skip, "HiPE is disabled"};
+ _ -> Config
+ end;
init_per_testcase(_Case, Config) ->
Config.
@@ -411,6 +418,17 @@ t_on_load(Config) when is_list(Config) ->
verify_tmpmem(TmpMem),
ok.
+hipe(Config) when is_list(Config) ->
+ Data = proplists:get_value(data_dir, Config),
+ Priv = proplists:get_value(priv_dir, Config),
+ Src = filename:join(Data, "hipe_compiled"),
+ {ok,hipe_compiled} = c:c(Src, [{outdir,Priv},native]),
+ true = code:is_module_native(hipe_compiled),
+ {error, {notsup,_}} = hipe_compiled:try_load_nif(),
+ true = code:delete(hipe_compiled),
+ false = code:purge(hipe_compiled),
+ ok.
+
%% Test NIF building heap fragments
heap_frag(Config) when is_list(Config) ->
diff --git a/erts/emulator/test/nif_SUITE_data/hipe_compiled.erl b/erts/emulator/test/nif_SUITE_data/hipe_compiled.erl
new file mode 100644
index 0000000000..84ddbc8d63
--- /dev/null
+++ b/erts/emulator/test/nif_SUITE_data/hipe_compiled.erl
@@ -0,0 +1,6 @@
+-module(hipe_compiled).
+
+-export([try_load_nif/0]).
+
+try_load_nif() ->
+ erlang:load_nif("doesn't matter", 0).
diff --git a/erts/emulator/test/port_SUITE.erl b/erts/emulator/test/port_SUITE.erl
index 4323849465..d4e77d634a 100644
--- a/erts/emulator/test/port_SUITE.erl
+++ b/erts/emulator/test/port_SUITE.erl
@@ -976,21 +976,21 @@ try_bad_env(Env) ->
%% Test that we can handle a very very large environment gracefully.
huge_env(Config) when is_list(Config) ->
ct:timetrap({minutes, 2}),
- Vars = case os:type() of
- {win32,_} -> 500;
- _ ->
- %% We create a huge environment,
- %% 20000 variables is about 25MB
- %% which seems to be the limit on Linux.
- 20000
- end,
+ {Vars, Cmd} = case os:type() of
+ {win32,_} -> {500, "cmd /q /c ls"};
+ _ ->
+ %% We create a huge environment,
+ %% 20000 variables is about 25MB
+ %% which seems to be the limit on Linux.
+ {20000, "ls"}
+ end,
Env = [{[$a + I div (25*25*25*25) rem 25,
$a + I div (25*25*25) rem 25,
$a + I div (25*25) rem 25,
$a+I div 25 rem 25, $a+I rem 25],
lists:duplicate(100,$a+I rem 25)}
|| I <- lists:seq(1,Vars)],
- try erlang:open_port({spawn,"ls"},[exit_status, {env, Env}]) of
+ try erlang:open_port({spawn,Cmd},[exit_status, {env, Env}]) of
P ->
receive
{P, {exit_status,N}} = M ->
@@ -1009,7 +1009,10 @@ huge_env(Config) when is_list(Config) ->
%% Test to spawn program with command payload buffer
%% just around pipe capacity (9f779819f6bda734c5953468f7798)
pipe_limit_env(Config) when is_list(Config) ->
- Cmd = "true",
+ Cmd = case os:type() of
+ {win32,_} -> "cmd /q /c true";
+ _ -> "true"
+ end,
CmdSize = command_payload_size(Cmd),
Limits = [4096, 16384, 65536], % Try a couple of common pipe buffer sizes
@@ -1026,7 +1029,7 @@ pipe_limit_env_do(Bytes, Cmd, CmdSize) ->
try erlang:open_port({spawn,Cmd},[exit_status, {env, Env}]) of
P ->
receive
- {P, {exit_status,N}} = M ->
+ {P, {exit_status,N}} ->
%% Bug caused exit_status 150 (EINVAL+128)
0 = N
end
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/ebin/erlang.beam b/erts/preloaded/ebin/erlang.beam
index fa5960dffd..6159228bff 100644
--- a/erts/preloaded/ebin/erlang.beam
+++ b/erts/preloaded/ebin/erlang.beam
Binary files differ
diff --git a/erts/preloaded/ebin/erts_internal.beam b/erts/preloaded/ebin/erts_internal.beam
index 0a78c5b6c3..aae3976298 100644
--- a/erts/preloaded/ebin/erts_internal.beam
+++ b/erts/preloaded/ebin/erts_internal.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/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index da08ab383b..f502a7cd36 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -2428,10 +2428,11 @@ term_to_binary(_Term, _Options) ->
tl(_List) ->
erlang:nif_error(undefined).
+-type match_variable() :: atom(). % Approximation of '$1' | '$2' | ...
-type trace_pattern_mfa() ::
{atom(),atom(),arity() | '_'} | on_load.
-type trace_match_spec() ::
- [{[term()] | '_' ,[term()],[term()]}].
+ [{[term()] | '_' | match_variable() ,[term()],[term()]}].
-spec erlang:trace_pattern(MFA, MatchSpec) -> non_neg_integer() when
MFA :: trace_pattern_mfa() | send | 'receive',
diff --git a/erts/preloaded/src/erts_internal.erl b/erts/preloaded/src/erts_internal.erl
index fecdfc348c..a27cb2ba38 100644
--- a/erts/preloaded/src/erts_internal.erl
+++ b/erts/preloaded/src/erts_internal.erl
@@ -436,10 +436,11 @@ microstate_accounting(Ref, Threads) ->
trace(_PidSpec, _How, _FlagList) ->
erlang:nif_error(undefined).
+-type match_variable() :: atom(). % Approximation of '$1' | '$2' | ...
-type trace_pattern_mfa() ::
{atom(),atom(),arity() | '_'} | on_load.
-type trace_match_spec() ::
- [{[term()] | '_' ,[term()],[term()]}].
+ [{[term()] | '_' | match_variable() ,[term()],[term()]}].
-spec trace_pattern(MFA, MatchSpec, FlagList) -> non_neg_integer() when
MFA :: trace_pattern_mfa(),
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