aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/Makefile1
-rw-r--r--erts/doc/src/absform.xml3
-rw-r--r--erts/doc/src/erl_nif.xml12
-rw-r--r--erts/doc/src/erlang.xml194
-rw-r--r--erts/doc/src/notes.xml132
-rw-r--r--erts/doc/src/time_correction.xml2
-rw-r--r--erts/emulator/beam/beam_bif_load.c5
-rw-r--r--erts/emulator/beam/beam_debug.c3
-rw-r--r--erts/emulator/beam/beam_ranges.c8
-rw-r--r--erts/emulator/beam/bif.c2
-rw-r--r--erts/emulator/beam/dist.c16
-rw-r--r--erts/emulator/beam/erl_alloc.c2
-rw-r--r--erts/emulator/beam/erl_bif_info.c28
-rw-r--r--erts/emulator/beam/erl_db.c1
-rw-r--r--erts/emulator/beam/erl_message.c18
-rw-r--r--erts/emulator/beam/erl_message.h6
-rw-r--r--erts/emulator/beam/erl_nif.c52
-rw-r--r--erts/emulator/beam/erl_proc_sig_queue.c38
-rw-r--r--erts/emulator/beam/erl_process.c1
-rw-r--r--erts/emulator/beam/erl_process.h2
-rw-r--r--erts/emulator/beam/io.c5
-rw-r--r--erts/emulator/drivers/common/inet_drv.c39
-rw-r--r--erts/emulator/sys/common/erl_check_io.c1
-rw-r--r--erts/emulator/sys/unix/sys.c4
-rw-r--r--erts/emulator/sys/unix/sys_drivers.c109
-rw-r--r--erts/emulator/sys/unix/sys_uds.c13
-rw-r--r--erts/emulator/sys/win32/erl_poll.c18
-rw-r--r--erts/emulator/test/nif_SUITE.erl58
-rw-r--r--erts/etc/unix/cerl.src26
-rw-r--r--erts/etc/unix/etp-commands.in26
-rw-r--r--erts/preloaded/src/erlang.erl11
31 files changed, 545 insertions, 291 deletions
diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile
index 3cc29e14b1..21aa3db864 100644
--- a/erts/doc/src/Makefile
+++ b/erts/doc/src/Makefile
@@ -149,6 +149,7 @@ debug opt:
clean:
rm -rf $(HTMLDIR)/*
+ rm -rf $(XMLDIR)
rm -f $(MAN1DIR)/*
rm -f $(MAN3DIR)/*
rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo)
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml
index 158f4dc4e8..f29bb7b8f9 100644
--- a/erts/doc/src/absform.xml
+++ b/erts/doc/src/absform.xml
@@ -801,7 +801,8 @@
<c>{ann_type,LINE,[Rep(A),Rep(T_0)]}</c>.</p>
</item>
<item>
- <p>If T is an atom or integer literal L, then Rep(T) = Rep(L).</p>
+ <p>If T is an atom, a character, or an integer literal L,
+ then Rep(T) = Rep(L).</p>
</item>
<item>
<p>If T is a bitstring type <c>&lt;&lt;_:M,_:_*N>></c>,
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index a8eff43623..a20b8ee884 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -194,7 +194,7 @@ ok
<p>Binaries are sequences of whole bytes. Bitstrings with an arbitrary
bit length have no support yet.</p>
</item>
- <tag>Resource objects</tag>
+ <tag><marker id="resource_objects"/>Resource objects</tag>
<item>
<p>The use of resource objects is a safe way to return pointers to
native data structures from a NIF. A resource object is
@@ -1250,8 +1250,9 @@ typedef struct {
<fsummary>Format strings and Erlang terms.</fsummary>
<desc>
<p>Similar to <c>fprintf</c> but this format string also accepts
- <c>"%T"</c>, which formats Erlang terms.</p>
- <p>This function was originally intenden for debugging purpose. It is not
+ <c>"%T"</c>, which formats Erlang terms of type
+ <seealso marker="#ERL_NIF_TERM"><c>ERL_NIF_TERM</c></seealso>.</p>
+ <p>This function is primarily intenden for debugging purpose. It is not
recommended to print very large terms with <c>%T</c>. The function may
change <c>errno</c>, even if successful.</p>
</desc>
@@ -3191,8 +3192,9 @@ if (retval &amp; ERL_NIF_SELECT_STOP_CALLED) {
<fsummary>Format strings and Erlang terms.</fsummary>
<desc>
<p>Similar to <c>snprintf</c> but this format string also accepts
- <c>"%T"</c>, which formats Erlang terms.</p>
- <p>This function was originally intenden for debugging purpose. It is not
+ <c>"%T"</c>, which formats Erlang terms of type
+ <seealso marker="#ERL_NIF_TERM"><c>ERL_NIF_TERM</c></seealso>.</p>
+ <p>This function is primarily intenden for debugging purpose. It is not
recommended to print very large terms with <c>%T</c>. The function may
change <c>errno</c>, even if successful.</p>
</desc>
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index b39d0e5e23..8e014c3010 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -197,6 +197,15 @@
</desc>
</datatype>
+ <datatype>
+ <name name="nif_resource"></name>
+ <desc>
+ <p>An opaque handle identifing a
+ <seealso marker="erl_nif#resource_objects">NIF resource object
+ </seealso>.</p>
+ </desc>
+ </datatype>
+
</datatypes>
<funcs>
@@ -3772,13 +3781,6 @@ RealSystem = system + MissedSystem</code>
If found, that driver is started. A driver runs in the Erlang
work space, which means that it is linked with the Erlang
runtime system.</p>
- <p>When starting external programs on Solaris, the system
- call <c>vfork</c> is used in preference to <c>fork</c>
- for performance reasons, although it has a history of
- being less robust. If there are problems using
- <c>vfork</c>, setting environment variable
- <c>ERL_NO_VFORK</c> to any value causes <c>fork</c>
- to be used instead.</p>
<p>For external programs, <c>PATH</c> is searched
(or an equivalent method is used to find programs,
depending on the OS). This is done by invoking
@@ -5295,10 +5297,10 @@ RealSystem = system + MissedSystem</code>
<p><c><anno>MinBinVHeapSize</anno></c> is the minimum binary virtual
heap size for the process.</p>
</item>
- <tag><c>{monitored_by, <anno>Pids</anno>}</c></tag>
+ <tag><c>{monitored_by, <anno>MonitoredBy</anno>}</c></tag>
<item>
- <p>A list of process identifiers monitoring the process (with
- <c>monitor/2</c>).</p>
+ <p>A list of identifiers for all the processes, ports and NIF
+ resources, that are monitoring the process.</p>
</item>
<tag><c>{monitors, <anno>Monitors</anno>}</c></tag>
<item>
@@ -6170,7 +6172,7 @@ true</pre>
<p>Monitors the new process (like
<seealso marker="#monitor/2"><c>monitor/2</c></seealso> does).</p>
</item>
- <tag><c>{priority, <anno>Level</anno></c></tag>
+ <tag><c>{priority, <anno>Level</anno>}</c></tag>
<item>
<p>Sets the priority of the new process. Equivalent to
executing <seealso marker="#process_flag_priority">
@@ -7581,7 +7583,7 @@ ok
</func>
<func>
- <name name="system_info" arity="1" clause_i="75"/>
+ <name name="system_info" arity="1" clause_i="76"/>
<fsummary>System info overview.</fsummary>
<desc>
<p>Returns information about the current system.
@@ -7629,6 +7631,7 @@ ok
<p>
<seealso marker="#system_info_atom_count"><c>atom_count</c></seealso>,
<seealso marker="#system_info_atom_limit"><c>atom_limit</c></seealso>,
+ <seealso marker="#system_info_ets_count"><c>ets_count</c></seealso>,
<seealso marker="#system_info_ets_limit"><c>ets_limit</c></seealso>,
<seealso marker="#system_info_port_count"><c>port_count</c></seealso>,
<seealso marker="#system_info_port_limit"><c>port_limit</c></seealso>,
@@ -7872,8 +7875,8 @@ ok
<name name="system_info" arity="1" clause_i="12"
anchor="system_info_cpu_topology"/> <!-- cpu_topology -->
<name name="system_info" arity="1" clause_i="13"/> <!-- {cpu_topology, _} -->
- <name name="system_info" arity="1" clause_i="37"/> <!-- logical_processors -->
- <name name="system_info" arity="1" clause_i="72"/> <!-- update_cpu_info -->
+ <name name="system_info" arity="1" clause_i="38"/> <!-- logical_processors -->
+ <name name="system_info" arity="1" clause_i="73"/> <!-- update_cpu_info -->
<fsummary>Information about the CPU topology of the system.</fsummary>
<type name="cpu_topology"/>
<type name="level_entry"/>
@@ -8024,16 +8027,16 @@ ok
</func>
<func>
- <name name="system_info" arity="1" clause_i="30"
+ <name name="system_info" arity="1" clause_i="31"
anchor="system_info_process"/> <!-- fullsweep_after -->
- <name name="system_info" arity="1" clause_i="31"/> <!-- garbage_collection -->
- <name name="system_info" arity="1" clause_i="32"/> <!-- heap_sizes -->
- <name name="system_info" arity="1" clause_i="33"/> <!-- heap_type -->
- <name name="system_info" arity="1" clause_i="39"/> <!-- max_heap_size -->
- <name name="system_info" arity="1" clause_i="40"/> <!-- message_queue_data -->
- <name name="system_info" arity="1" clause_i="41"/> <!-- min_heap_size -->
- <name name="system_info" arity="1" clause_i="42"/> <!-- min_bin_vheap_size -->
- <name name="system_info" arity="1" clause_i="56"/> <!-- procs -->
+ <name name="system_info" arity="1" clause_i="32"/> <!-- garbage_collection -->
+ <name name="system_info" arity="1" clause_i="33"/> <!-- heap_sizes -->
+ <name name="system_info" arity="1" clause_i="34"/> <!-- heap_type -->
+ <name name="system_info" arity="1" clause_i="40"/> <!-- max_heap_size -->
+ <name name="system_info" arity="1" clause_i="41"/> <!-- message_queue_data -->
+ <name name="system_info" arity="1" clause_i="42"/> <!-- min_heap_size -->
+ <name name="system_info" arity="1" clause_i="43"/> <!-- min_bin_vheap_size -->
+ <name name="system_info" arity="1" clause_i="57"/> <!-- procs -->
<fsummary>Information about the default process heap settings.</fsummary>
<type name="message_queue_data"/>
<type name="max_heap_size"/>
@@ -8143,14 +8146,14 @@ ok
</func>
<func>
- <name name="system_info" arity="1" clause_i="6"
- anchor="system_info_limits"/> <!-- atom_count -->
+ <name name="system_info" arity="1" clause_i="6" anchor="system_info_limits"/> <!-- atom_count -->
<name name="system_info" arity="1" clause_i="7"/> <!-- atom_limit -->
- <name name="system_info" arity="1" clause_i="29"/> <!-- ets_limit -->
- <name name="system_info" arity="1" clause_i="52"/> <!-- port_count -->
- <name name="system_info" arity="1" clause_i="53"/> <!-- port_limit -->
- <name name="system_info" arity="1" clause_i="54"/> <!-- process_count -->
- <name name="system_info" arity="1" clause_i="55"/> <!-- process_limit -->
+ <name name="system_info" arity="1" clause_i="29"/> <!-- ets_count -->
+ <name name="system_info" arity="1" clause_i="30"/> <!-- ets_limit -->
+ <name name="system_info" arity="1" clause_i="53"/> <!-- port_count -->
+ <name name="system_info" arity="1" clause_i="54"/> <!-- port_limit -->
+ <name name="system_info" arity="1" clause_i="55"/> <!-- process_count -->
+ <name name="system_info" arity="1" clause_i="56"/> <!-- process_limit -->
<fsummary>Information about various system limits.</fsummary>
<desc>
<marker id="system_info_limits"/>
@@ -8173,7 +8176,7 @@ ok
<c>erl(1)</c>.
</p>
</item>
- <tag><marker id="system_info_ets_count"/>
+ <tag><marker id="system_info_ets_count"/>
<c>ets_count</c></tag>
<item>
<p>Returns the number of ETS tables currently existing at the
@@ -8225,13 +8228,13 @@ ok
<func>
<name name="system_info" arity="1" clause_i="26"
anchor="system_info_time"/> <!-- end_time -->
- <name name="system_info" arity="1" clause_i="49"/> <!-- os_monotonic_time_source -->
- <name name="system_info" arity="1" clause_i="50"/> <!-- os_system_time_source -->
- <name name="system_info" arity="1" clause_i="62"/> <!-- start_time -->
- <name name="system_info" arity="1" clause_i="67"/> <!-- time_correction -->
- <name name="system_info" arity="1" clause_i="68"/> <!-- time_offset -->
- <name name="system_info" arity="1" clause_i="69"/> <!-- time_warp_mode -->
- <name name="system_info" arity="1" clause_i="70"/> <!-- tolerant_timeofday -->
+ <name name="system_info" arity="1" clause_i="50"/> <!-- os_monotonic_time_source -->
+ <name name="system_info" arity="1" clause_i="51"/> <!-- os_system_time_source -->
+ <name name="system_info" arity="1" clause_i="63"/> <!-- start_time -->
+ <name name="system_info" arity="1" clause_i="68"/> <!-- time_correction -->
+ <name name="system_info" arity="1" clause_i="69"/> <!-- time_offset -->
+ <name name="system_info" arity="1" clause_i="70"/> <!-- time_warp_mode -->
+ <name name="system_info" arity="1" clause_i="71"/> <!-- tolerant_timeofday -->
<fsummary>Information about system time.</fsummary>
<desc>
<marker id="system_info_time_tags"/>
@@ -8455,16 +8458,16 @@ ok
anchor="system_info_scheduler"/> <!-- dirty_cpu_schedulers -->
<name name="system_info" arity="1" clause_i="18"/> <!-- dirty_cpu_schedulers_online -->
<name name="system_info" arity="1" clause_i="19"/> <!-- dirty_io_schedulers -->
- <name name="system_info" arity="1" clause_i="44"/> <!-- multi_scheduling -->
- <name name="system_info" arity="1" clause_i="45"/> <!-- multi_scheduling_blockers -->
- <name name="system_info" arity="1" clause_i="47"/> <!-- normal_multi_scheduling_blockers -->
- <name name="system_info" arity="1" clause_i="57"/> <!-- scheduler_bind_type -->
- <name name="system_info" arity="1" clause_i="58"/> <!-- scheduler_bindings -->
- <name name="system_info" arity="1" clause_i="59"/> <!-- scheduler_id -->
- <name name="system_info" arity="1" clause_i="60"/> <!-- schedulers -->
- <name name="system_info" arity="1" clause_i="61"/> <!-- smp_support -->
- <name name="system_info" arity="1" clause_i="65"/> <!-- threads -->
- <name name="system_info" arity="1" clause_i="66"/> <!-- thread_pool_size -->
+ <name name="system_info" arity="1" clause_i="45"/> <!-- multi_scheduling -->
+ <name name="system_info" arity="1" clause_i="46"/> <!-- multi_scheduling_blockers -->
+ <name name="system_info" arity="1" clause_i="49"/> <!-- normal_multi_scheduling_blockers -->
+ <name name="system_info" arity="1" clause_i="58"/> <!-- scheduler_bind_type -->
+ <name name="system_info" arity="1" clause_i="59"/> <!-- scheduler_bindings -->
+ <name name="system_info" arity="1" clause_i="60"/> <!-- scheduler_id -->
+ <name name="system_info" arity="1" clause_i="61"/> <!-- schedulers -->
+ <name name="system_info" arity="1" clause_i="62"/> <!-- smp_support -->
+ <name name="system_info" arity="1" clause_i="66"/> <!-- threads -->
+ <name name="system_info" arity="1" clause_i="67"/> <!-- thread_pool_size -->
<fsummary>Information about system schedulers.</fsummary>
<desc>
<marker id="system_info_scheduler_tags"/>
@@ -8851,53 +8854,54 @@ ok
<!-- <name name="system_info" arity="1" clause_i="26"/> end_time -->
<!-- <name name="system_info" arity="1" clause_i="27"/> elib_malloc -->
<!-- <name name="system_info" arity="1" clause_i="28"/> eager_check_io, removed -->
- <!-- <name name="system_info" arity="1" clause_i="29"/> ets_limit -->
- <!-- <name name="system_info" arity="1" clause_i="30"/> fullsweep_after -->
- <!-- <name name="system_info" arity="1" clause_i="31"/> garbage_collection -->
- <!-- <name name="system_info" arity="1" clause_i="32"/> heap_sizes -->
- <!-- <name name="system_info" arity="1" clause_i="33"/> heap_type -->
- <name name="system_info" arity="1" clause_i="34"/> <!-- info -->
- <name name="system_info" arity="1" clause_i="35"/> <!-- kernel_poll -->
- <name name="system_info" arity="1" clause_i="36"/> <!-- loaded -->
- <!-- <name name="system_info" arity="1" clause_i="37"/> logical_processors -->
- <name name="system_info" arity="1" clause_i="38"/> <!-- machine -->
- <!-- <name name="system_info" arity="1" clause_i="39"/> max_heap_size -->
- <!-- <name name="system_info" arity="1" clause_i="40"/> message_queue_data -->
- <!-- <name name="system_info" arity="1" clause_i="41"/> min_heap_size -->
- <!-- <name name="system_info" arity="1" clause_i="42"/> min_bin_vheap_size -->
- <name name="system_info" arity="1" clause_i="43"/> <!-- modified_timing_level -->
- <!-- <name name="system_info" arity="1" clause_i="44"/> multi_scheduling -->
- <!-- <name name="system_info" arity="1" clause_i="45"/> multi_scheduling_blockers -->
- <name name="system_info" arity="1" clause_i="46"/> <!-- nif_version -->
- <!-- n<name name="system_info" arity="1" clause_i="47"/> ormal_multi_scheduling_blockers -->
- <name name="system_info" arity="1" clause_i="48"/> <!-- otp_release -->
- <!-- <name name="system_info" arity="1" clause_i="49"/> os_monotonic_time_source -->
- <!-- <name name="system_info" arity="1" clause_i="50"/> os_system_time_source -->
- <name name="system_info" arity="1" clause_i="51"/> <!-- port_parallelism -->
- <!-- <name name="system_info" arity="1" clause_i="52"/> port_count -->
- <!-- <name name="system_info" arity="1" clause_i="53"/> port_limit -->
- <!-- <name name="system_info" arity="1" clause_i="54"/> process_count -->
- <!-- <name name="system_info" arity="1" clause_i="55"/> process_limit -->
- <!-- <name name="system_info" arity="1" clause_i="56"/> procs -->
- <!-- <name name="system_info" arity="1" clause_i="57"/> scheduler_bind_type -->
- <!-- <name name="system_info" arity="1" clause_i="58"/> scheduler_bindings -->
- <!-- <name name="system_info" arity="1" clause_i="59"/> scheduler_id -->
- <!-- <name name="system_info" arity="1" clause_i="60"/> schedulers -->
- <!-- <name name="system_info" arity="1" clause_i="61"/> smp_support -->
- <!-- <name name="system_info" arity="1" clause_i="62"/> start_time -->
- <name name="system_info" arity="1" clause_i="63"/> <!-- system_version -->
- <name name="system_info" arity="1" clause_i="64"/> <!-- system_architecture -->
- <!-- <name name="system_info" arity="1" clause_i="65"/> threads -->
- <!-- <name name="system_info" arity="1" clause_i="66"/> thread_pool_size -->
- <!-- <name name="system_info" arity="1" clause_i="67"/> time_correction -->
- <!-- <name name="system_info" arity="1" clause_i="68"/> time_offset -->
- <!-- <name name="system_info" arity="1" clause_i="69"/> time_warp_mode -->
- <!-- <name name="system_info" arity="1" clause_i="70"/> tolerant_timeofday -->
- <name name="system_info" arity="1" clause_i="71"/> <!-- trace_control_word -->
- <!-- <name name="system_info" arity="1" clause_i="72"/> update_cpu_info -->
- <name name="system_info" arity="1" clause_i="73"/> <!-- version -->
- <name name="system_info" arity="1" clause_i="74"/> <!-- wordsize -->
- <!-- <name name="system_info" arity="1" clause_i="75"/> overview -->
+ <!-- <name name="system_info" arity="1" clause_i="29"/> ets_count -->
+ <!-- <name name="system_info" arity="1" clause_i="30"/> ets_limit -->
+ <!-- <name name="system_info" arity="1" clause_i="31"/> fullsweep_after -->
+ <!-- <name name="system_info" arity="1" clause_i="32"/> garbage_collection -->
+ <!-- <name name="system_info" arity="1" clause_i="33"/> heap_sizes -->
+ <!-- <name name="system_info" arity="1" clause_i="34"/> heap_type -->
+ <name name="system_info" arity="1" clause_i="35"/> <!-- info -->
+ <name name="system_info" arity="1" clause_i="36"/> <!-- kernel_poll -->
+ <name name="system_info" arity="1" clause_i="37"/> <!-- loaded -->
+ <!-- <name name="system_info" arity="1" clause_i="38"/> logical_processors -->
+ <name name="system_info" arity="1" clause_i="39"/> <!-- machine -->
+ <!-- <name name="system_info" arity="1" clause_i="40"/> max_heap_size -->
+ <!-- <name name="system_info" arity="1" clause_i="41"/> message_queue_data -->
+ <!-- <name name="system_info" arity="1" clause_i="42"/> min_heap_size -->
+ <!-- <name name="system_info" arity="1" clause_i="43"/> min_bin_vheap_size -->
+ <name name="system_info" arity="1" clause_i="44"/> <!-- modified_timing_level -->
+ <!-- <name name="system_info" arity="1" clause_i="45"/> multi_scheduling -->
+ <!-- <name name="system_info" arity="1" clause_i="46"/> multi_scheduling_blockers -->
+ <name name="system_info" arity="1" clause_i="47"/> <!-- nif_version -->
+ <!-- n<name name="system_info" arity="1" clause_i="48"/> ormal_multi_scheduling_blockers -->
+ <name name="system_info" arity="1" clause_i="49"/> <!-- otp_release -->
+ <!-- <name name="system_info" arity="1" clause_i="50"/> os_monotonic_time_source -->
+ <!-- <name name="system_info" arity="1" clause_i="51"/> os_system_time_source -->
+ <name name="system_info" arity="1" clause_i="52"/> <!-- port_parallelism -->
+ <!-- <name name="system_info" arity="1" clause_i="53"/> port_count -->
+ <!-- <name name="system_info" arity="1" clause_i="54"/> port_limit -->
+ <!-- <name name="system_info" arity="1" clause_i="55"/> process_count -->
+ <!-- <name name="system_info" arity="1" clause_i="56"/> process_limit -->
+ <!-- <name name="system_info" arity="1" clause_i="57"/> procs -->
+ <!-- <name name="system_info" arity="1" clause_i="58"/> scheduler_bind_type -->
+ <!-- <name name="system_info" arity="1" clause_i="59"/> scheduler_bindings -->
+ <!-- <name name="system_info" arity="1" clause_i="60"/> scheduler_id -->
+ <!-- <name name="system_info" arity="1" clause_i="61"/> schedulers -->
+ <!-- <name name="system_info" arity="1" clause_i="62"/> smp_support -->
+ <!-- <name name="system_info" arity="1" clause_i="63"/> start_time -->
+ <name name="system_info" arity="1" clause_i="64"/> <!-- system_version -->
+ <name name="system_info" arity="1" clause_i="65"/> <!-- system_architecture -->
+ <!-- <name name="system_info" arity="1" clause_i="66"/> threads -->
+ <!-- <name name="system_info" arity="1" clause_i="67"/> thread_pool_size -->
+ <!-- <name name="system_info" arity="1" clause_i="68"/> time_correction -->
+ <!-- <name name="system_info" arity="1" clause_i="69"/> time_offset -->
+ <!-- <name name="system_info" arity="1" clause_i="70"/> time_warp_mode -->
+ <!-- <name name="system_info" arity="1" clause_i="71"/> tolerant_timeofday -->
+ <name name="system_info" arity="1" clause_i="72"/> <!-- trace_control_word -->
+ <!-- <name name="system_info" arity="1" clause_i="73"/> update_cpu_info -->
+ <name name="system_info" arity="1" clause_i="74"/> <!-- version -->
+ <name name="system_info" arity="1" clause_i="75"/> <!-- wordsize -->
+ <!-- <name name="system_info" arity="1" clause_i="76"/> overview -->
<fsummary>Information about the system.</fsummary>
<desc>
<marker id="system_info_misc_tags"/>
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 446296571c..6b4db48f61 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -1090,6 +1090,81 @@
</section>
+<section><title>Erts 9.3.3.3</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed a bug which caused an emulator crash when
+ <c>enif_send()</c> was called by a NIF that executed on a
+ dirty scheduler. The bug was either triggered when the
+ NIF called <c>enif_send()</c> without a message
+ environment, or when the process executing the NIF was
+ <c>send</c> traced.</p>
+ <p>
+ Own Id: OTP-15223</p>
+ </item>
+ <item>
+ <p>
+ Fixed a bug causing some Erlang references to be
+ inconsistently ordered. This could for example cause
+ failure to look up certain elements with references as
+ keys in search data structures. This bug was introduced
+ in R13B02.</p>
+ <p>
+ Thanks to Simon Cornish for finding the bug and supplying
+ a fix.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15225</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 9.3.3.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a race condition in the inet driver that could
+ cause receive to hang when the emulator was compiled with
+ gcc 8.</p>
+ <p>
+ Own Id: OTP-15158 Aux Id: ERL-654 </p>
+ </item>
+ <item>
+ <p>
+ Fix bug in generation of erl_crash.dump, which could
+ cause VM to crash.</p>
+ <p>
+ Bug exist since erts-9.2 (OTP-20.2).</p>
+ <p>
+ Own Id: OTP-15181</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 9.3.3.1</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a rare bug that could cause processes to be
+ scheduled after they had been freed.</p>
+ <p>
+ Own Id: OTP-15067 Aux Id: ERL-573 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 9.3.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -2517,6 +2592,63 @@
</section>
+<section><title>Erts 8.3.5.5</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a race condition in the inet driver that could
+ cause receive to hang when the emulator was compiled with
+ gcc 8.</p>
+ <p>
+ Own Id: OTP-15158 Aux Id: ERL-654 </p>
+ </item>
+ <item>
+ <p>
+ Fixed a bug causing some Erlang references to be
+ inconsistently ordered. This could for example cause
+ failure to look up certain elements with references as
+ keys in search data structures. This bug was introduced
+ in R13B02.</p>
+ <p>
+ Thanks to Simon Cornish for finding the bug and supplying
+ a fix.</p>
+ <p>
+ *** POTENTIAL INCOMPATIBILITY ***</p>
+ <p>
+ Own Id: OTP-15225</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
+<section><title>Erts 8.3.5.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a bug in file closure on Unix; close(2) was
+ retried on EINTR which could cause a different (recently
+ opened) file to be closed as well.</p>
+ <p>
+ Own Id: OTP-14775</p>
+ </item>
+ <item>
+ <p>
+ A race-condition when tearing down a connection with
+ active node monitors could cause the runtime system to
+ crash.</p>
+ <p>
+ This bug was introduced in ERTS version 8.0 (OTP 19.0).</p>
+ <p>
+ Own Id: OTP-14781 Aux Id: OTP-13047 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 8.3.5.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/doc/src/time_correction.xml b/erts/doc/src/time_correction.xml
index 77e7a40529..53b555387c 100644
--- a/erts/doc/src/time_correction.xml
+++ b/erts/doc/src/time_correction.xml
@@ -940,7 +940,7 @@ EventTag = {Time, UMI}</code>
</item>
<item>
<seealso marker="erlang#system_info_os_system_time_source">
- <c>erlang:system_info(os_system_time_source)</c></seealso>)
+ <c>erlang:system_info(os_system_time_source)</c></seealso>
</item>
</list>
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index a0dbd9ec7b..d221e6aea6 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -1753,6 +1753,7 @@ BIF_RETTYPE erts_internal_purge_module_2(BIF_ALIST_2)
if (literals) {
ErtsLiteralAreaRef *ref;
+ ErtsMessage *mp;
ref = erts_alloc(ERTS_ALC_T_LITERAL_REF,
sizeof(ErtsLiteralAreaRef));
ref->literal_area = literals;
@@ -1767,10 +1768,12 @@ BIF_RETTYPE erts_internal_purge_module_2(BIF_ALIST_2)
release_literal_areas.last = ref;
}
erts_mtx_unlock(&release_literal_areas.mtx);
+ mp = erts_alloc_message(0, NULL);
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_proc_message(BIF_P,
erts_literal_area_collector,
0,
- erts_alloc_message(0, NULL),
+ mp,
am_copy_literals);
}
diff --git a/erts/emulator/beam/beam_debug.c b/erts/emulator/beam/beam_debug.c
index 6d3b99c43e..9633de2021 100644
--- a/erts/emulator/beam/beam_debug.c
+++ b/erts/emulator/beam/beam_debug.c
@@ -667,7 +667,7 @@ print_op(fmtfn_t to, void *to_arg, int op, int size, BeamInstr* addr)
ap++;
break;
case 'l': /* fr(N) */
- erts_print(to, to_arg, "fr(%d)", loader_reg_index(ap[0]));
+ erts_print(to, to_arg, "fr(%d)", ap[0] / sizeof(FloatDef));
ap++;
break;
default:
@@ -1191,6 +1191,7 @@ dirty_send_message(Process *c_p, Eterm to, Eterm tag)
mp = erts_alloc_message_heap(rp, &rp_locks, 3, &hp, &ohp);
msg = TUPLE2(hp, tag, c_p->common.id);
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_proc_message(c_p, rp, rp_locks, mp, msg);
if (rp == real_c_p)
diff --git a/erts/emulator/beam/beam_ranges.c b/erts/emulator/beam/beam_ranges.c
index f0c9496341..9f3153724a 100644
--- a/erts/emulator/beam/beam_ranges.c
+++ b/erts/emulator/beam/beam_ranges.c
@@ -35,10 +35,8 @@ typedef struct {
/*
* Used for crash dumping of literals. The size of erts_dump_lit_areas is
- * always twice the number of active ranges (to allow for literals in both
- * current and old code).
+ * always at least the number of active ranges.
*/
-
ErtsLiteralArea** erts_dump_lit_areas;
Uint erts_dump_num_lit_areas;
@@ -180,8 +178,8 @@ erts_end_staging_ranges(int commit)
(erts_aint_t) (r[dst].modules +
r[dst].n / 2));
- if (r[dst].allocated * 2 > erts_dump_num_lit_areas) {
- erts_dump_num_lit_areas *= 2;
+ if (r[dst].allocated > erts_dump_num_lit_areas) {
+ erts_dump_num_lit_areas = r[dst].allocated * 2;
erts_dump_lit_areas = (ErtsLiteralArea **)
erts_realloc(ERTS_ALC_T_CRASH_DUMP,
(void *) erts_dump_lit_areas,
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 97e1ee1286..f18af8bcd7 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -2063,7 +2063,7 @@ do_send(Process *p, Eterm to, Eterm msg, Eterm *refp, ErtsSendContext *ctx)
if (p == rp)
rp_locks |= ERTS_PROC_LOCK_MAIN;
/* send to local process */
- erts_send_message(p, rp, &rp_locks, msg, 0);
+ erts_send_message(p, rp, &rp_locks, msg);
erts_proc_unlock(rp,
p == rp
? (rp_locks & ~ERTS_PROC_LOCK_MAIN)
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 70474898b2..146c00b07d 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -1200,21 +1200,8 @@ erts_dsig_send_group_leader(ErtsDSigData *dsdp, Eterm leader, Eterm remote)
#include <valgrind/valgrind.h>
#include <valgrind/memcheck.h>
-#ifndef HAVE_VALGRIND_PRINTF_XML
-#define VALGRIND_PRINTF_XML VALGRIND_PRINTF
-#endif
-
# define PURIFY_MSG(msg) \
- do { \
- char buf__[1]; size_t bufsz__ = sizeof(buf__); \
- if (erts_sys_explicit_8bit_getenv("VALGRIND_LOG_XML", buf__, &bufsz__) >= 0) { \
- VALGRIND_PRINTF_XML("<erlang_error_log>" \
- "%s, line %d: %s</erlang_error_log>\n", \
- __FILE__, __LINE__, msg); \
- } else { \
- VALGRIND_PRINTF("%s, line %d: %s", __FILE__, __LINE__, msg); \
- } \
- } while (0)
+ VALGRIND_PRINTF("%s, line %d: %s", __FILE__, __LINE__, msg)
#else
# define PURIFY_MSG(msg)
#endif
@@ -3685,6 +3672,7 @@ int erts_auto_connect(DistEntry* dep, Process *proc, ErtsProcLocks proc_locks)
dhandle = erts_build_dhandle(&hp, ohp, dep);
msg = TUPLE4(hp, am_auto_connect, dep->sysname, make_small(conn_id),
dhandle);
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_proc_message(proc, net_kernel, nk_locks, mp, msg);
erts_proc_unlock(net_kernel, nk_locks);
}
diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c
index 575d6ca867..8fe1ccb758 100644
--- a/erts/emulator/beam/erl_alloc.c
+++ b/erts/emulator/beam/erl_alloc.c
@@ -114,7 +114,7 @@ typedef union {
char align_afa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AFAllctr_t))];
AOFFAllctr_t aoffa;
char align_aoffa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AOFFAllctr_t))];
-} ErtsAllocatorState_t;
+} ErtsAllocatorState_t erts_align_attribute(ERTS_CACHE_LINE_SIZE);
static ErtsAllocatorState_t std_alloc_state;
static ErtsAllocatorState_t ll_alloc_state;
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 5789fa8e71..7fada0d548 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -2093,17 +2093,6 @@ current_stacktrace(ErtsHeapFactory *hfact, Process* rp,
return res;
}
-#if defined(VALGRIND)
-static int check_if_xml(void)
-{
- char buf[1];
- size_t bufsz = sizeof(buf);
- return erts_sys_explicit_8bit_getenv("VALGRIND_LOG_XML", buf, &bufsz) >= 0;
-}
-#else
-#define check_if_xml() 0
-#endif
-
/*
* This function takes care of calls to erlang:system_info/1 when the argument
* is a tuple.
@@ -2200,15 +2189,9 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */
#endif
} else if (is_list(*tp)) {
#if defined(PURIFY)
-#define ERTS_ERROR_CHECKER_PRINTF purify_printf
-#define ERTS_ERROR_CHECKER_PRINTF_XML purify_printf
+# define ERTS_ERROR_CHECKER_PRINTF purify_printf
#elif defined(VALGRIND)
-#define ERTS_ERROR_CHECKER_PRINTF VALGRIND_PRINTF
-# ifndef HAVE_VALGRIND_PRINTF_XML
-# define ERTS_ERROR_CHECKER_PRINTF_XML VALGRIND_PRINTF
-# else
-# define ERTS_ERROR_CHECKER_PRINTF_XML VALGRIND_PRINTF_XML
-# endif
+# define ERTS_ERROR_CHECKER_PRINTF VALGRIND_PRINTF
#endif
ErlDrvSizeT buf_size = 8*1024; /* Try with 8KB first */
char *buf = erts_alloc(ERTS_ALC_T_TMP, buf_size);
@@ -2224,12 +2207,7 @@ info_1_tuple(Process* BIF_P, /* Pointer to current process. */
ASSERT(r == buf_size - 1);
}
buf[buf_size - 1 - r] = '\0';
- if (check_if_xml()) {
- ERTS_ERROR_CHECKER_PRINTF_XML("<erlang_info_log>"
- "%s</erlang_info_log>\n", buf);
- } else {
- ERTS_ERROR_CHECKER_PRINTF("%s\n", buf);
- }
+ ERTS_ERROR_CHECKER_PRINTF("%s\n", buf);
erts_free(ERTS_ALC_T_TMP, (void *) buf);
BIF_RET(am_true);
#undef ERTS_ERROR_CHECKER_PRINTF
diff --git a/erts/emulator/beam/erl_db.c b/erts/emulator/beam/erl_db.c
index 36d83d93f4..c009a3bde8 100644
--- a/erts/emulator/beam/erl_db.c
+++ b/erts/emulator/beam/erl_db.c
@@ -3647,6 +3647,7 @@ send_ets_transfer_message(Process *c_p, Process *proc,
hd_copy = copy_struct(heir_data, hd_sz, &hp, ohp);
sender = c_p->common.id;
msg = TUPLE4(hp, am_ETS_TRANSFER, tid, sender, hd_copy);
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_proc_message(c_p, proc, *locks, mp, msg);
}
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index 507cc989d2..a3274d7443 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -409,6 +409,11 @@ ErtsMessage* prepend_pending_sig_maybe(Process* sender, Process* receiver,
*
* @brief Send one message from *NOT* a local process.
*
+ * seq_trace does not work with this type of messages
+ * to it is set to am_undefined which means that the
+ * receiving process will not remove the seq_trace token
+ * when it gets this message.
+ *
*/
void
erts_queue_message(Process* receiver, ErtsProcLocks receiver_locks,
@@ -417,11 +422,19 @@ erts_queue_message(Process* receiver, ErtsProcLocks receiver_locks,
ASSERT(is_not_internal_pid(from));
ERL_MESSAGE_TERM(mp) = msg;
ERL_MESSAGE_FROM(mp) = from;
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
queue_messages(receiver, receiver_locks, mp, &mp->next, 1);
}
/**
* @brief Send one message from a local process.
+ *
+ * It is up to the caller of this function to set the
+ * correct seq_trace. The general rule of thumb is that
+ * it should be set to am_undefined if the message
+ * cannot be traced using seq_trace, if it can be
+ * traced it should be set to the trace token. It should
+ * very rarely be explicitly set to NIL!
*/
void
erts_queue_proc_message(Process* sender,
@@ -584,8 +597,7 @@ void
erts_send_message(Process* sender,
Process* receiver,
ErtsProcLocks *receiver_locks,
- Eterm message,
- unsigned flags)
+ Eterm message)
{
Uint msize;
ErtsMessage* mp;
@@ -619,7 +631,7 @@ erts_send_message(Process* sender,
receiver_state = erts_atomic32_read_nob(&receiver->state);
- if (SEQ_TRACE_TOKEN(sender) != NIL && !(flags & ERTS_SND_FLG_NO_SEQ_TRACE)) {
+ if (SEQ_TRACE_TOKEN(sender) != NIL) {
Eterm* hp;
Eterm stoken = SEQ_TRACE_TOKEN(sender);
Uint seq_trace_size = 0;
diff --git a/erts/emulator/beam/erl_message.h b/erts/emulator/beam/erl_message.h
index d120111634..b2550814fd 100644
--- a/erts/emulator/beam/erl_message.h
+++ b/erts/emulator/beam/erl_message.h
@@ -405,8 +405,6 @@ typedef struct erl_trace_message_queue__ {
#define SAVE_MESSAGE(p) \
(p)->sig_qs.save = &(*(p)->sig_qs.save)->next
-#define ERTS_SND_FLG_NO_SEQ_TRACE (((unsigned) 1) << 0)
-
#define ERTS_HEAP_FRAG_SIZE(DATA_WORDS) \
(sizeof(ErlHeapFragment) - sizeof(Eterm) + (DATA_WORDS)*sizeof(Eterm))
@@ -429,7 +427,7 @@ typedef struct erl_trace_message_queue__ {
do { \
(MP)->next = NULL; \
ERL_MESSAGE_TERM(MP) = THE_NON_VALUE; \
- ERL_MESSAGE_TOKEN(MP) = NIL; \
+ ERL_MESSAGE_TOKEN(MP) = THE_NON_VALUE; \
ERL_MESSAGE_FROM(MP) = NIL; \
ERL_MESSAGE_DT_UTAG_INIT(MP); \
MP->data.attached = NULL; \
@@ -446,7 +444,7 @@ void erts_queue_proc_message(Process* from,Process* to, ErtsProcLocks,ErtsMessag
void erts_queue_proc_messages(Process* from, Process* to, ErtsProcLocks,
ErtsMessage*, ErtsMessage**, Uint);
void erts_deliver_exit_message(Eterm, Process*, ErtsProcLocks *, Eterm, Eterm);
-void erts_send_message(Process*, Process*, ErtsProcLocks*, Eterm, unsigned);
+void erts_send_message(Process*, Process*, ErtsProcLocks*, Eterm);
void erts_link_mbuf_to_proc(Process *proc, ErlHeapFragment *bp);
Uint erts_msg_attached_data_size_aux(ErtsMessage *msg);
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index ef010ff476..ee6e6085b6 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -754,8 +754,58 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
rp_locks = ERTS_PROC_LOCK_MAIN;
if (menv) {
+ Eterm token = c_p ? SEQ_TRACE_TOKEN(c_p) : am_undefined;
+ if (token != NIL && token != am_undefined) {
+ /* This code is copied from erts_send_message */
+ Eterm stoken = SEQ_TRACE_TOKEN(c_p);
+#ifdef USE_VM_PROBES
+ DTRACE_CHARBUF(sender_name, 64);
+ DTRACE_CHARBUF(receiver_name, 64);
+ Sint tok_label = 0;
+ Sint tok_lastcnt = 0;
+ Sint tok_serial = 0;
+ Eterm utag = NIL;
+ *sender_name = *receiver_name = '\0';
+ if (DTRACE_ENABLED(message_send)) {
+ erts_snprintf(sender_name, sizeof(DTRACE_CHARBUF_NAME(sender_name)),
+ "%T", c_p->common.id);
+ erts_snprintf(receiver_name, sizeof(DTRACE_CHARBUF_NAME(receiver_name)),
+ "%T", rp->common.id);
+ }
+#endif
+ if (have_seqtrace(stoken)) {
+ seq_trace_update_send(c_p);
+ seq_trace_output(stoken, msg, SEQ_TRACE_SEND,
+ rp->common.id, c_p);
+ }
+#ifdef USE_VM_PROBES
+ if (!(DT_UTAG_FLAGS(c_p) & DT_UTAG_SPREADING)) {
+ stoken = NIL;
+ }
+#endif
+ token = enif_make_copy(msg_env, stoken);
+
+#ifdef USE_VM_PROBES
+ if (DT_UTAG_FLAGS(c_p) & DT_UTAG_SPREADING) {
+ if (is_immed(DT_UTAG(c_p)))
+ utag = DT_UTAG(c_p);
+ else
+ utag = enif_make_copy(msg_env, DT_UTAG(c_p));
+ }
+ if (DTRACE_ENABLED(message_send)) {
+ if (have_seqtrace(stoken)) {
+ tok_label = SEQ_TRACE_T_DTRACE_LABEL(stoken);
+ tok_lastcnt = signed_val(SEQ_TRACE_T_LASTCNT(stoken));
+ tok_serial = signed_val(SEQ_TRACE_T_SERIAL(stoken));
+ }
+ DTRACE6(message_send, sender_name, receiver_name,
+ size_object(msg), tok_label, tok_lastcnt, tok_serial);
+ }
+#endif
+ }
flush_env(msg_env);
mp = erts_alloc_message(0, NULL);
+ ERL_MESSAGE_TOKEN(mp) = token;
mp->data.heap_frag = menv->env.heap_frag;
ASSERT(mp->data.heap_frag == MBUF(&menv->phony_proc));
if (mp->data.heap_frag != NULL) {
@@ -793,6 +843,7 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
ohp = &bp->off_heap;
}
}
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
msg = copy_struct_litopt(msg, sz, &hp, ohp, &litarea);
}
@@ -836,6 +887,7 @@ int enif_send(ErlNifEnv* env, const ErlNifPid* to_pid,
ERL_MESSAGE_TERM(mp) = msg;
ERL_MESSAGE_FROM(mp) = from;
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
if (!msgq) {
msgq = erts_alloc(ERTS_ALC_T_TRACE_MSG_QUEUE,
diff --git a/erts/emulator/beam/erl_proc_sig_queue.c b/erts/emulator/beam/erl_proc_sig_queue.c
index 6af1236145..f343e984f7 100644
--- a/erts/emulator/beam/erl_proc_sig_queue.c
+++ b/erts/emulator/beam/erl_proc_sig_queue.c
@@ -52,8 +52,8 @@
#define ERTS_SIG_Q_OP_MAX 13
-#define ERTS_SIG_Q_OP_EXIT 0
-#define ERTS_SIG_Q_OP_EXIT_LINKED 1
+#define ERTS_SIG_Q_OP_EXIT 0 /* Exit signal due to bif call */
+#define ERTS_SIG_Q_OP_EXIT_LINKED 1 /* Exit signal due to link break*/
#define ERTS_SIG_Q_OP_MONITOR_DOWN 2
#define ERTS_SIG_Q_OP_MONITOR 3
#define ERTS_SIG_Q_OP_DEMONITOR 4
@@ -1167,10 +1167,7 @@ erts_proc_sig_send_persistent_monitor_msg(Uint16 type, Eterm key,
ERL_MESSAGE_TERM(mp) = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_PERSISTENT_MON_MSG,
type, 0);
ERL_MESSAGE_FROM(mp) = from;
- ERL_MESSAGE_TOKEN(mp) = NIL;
-#ifdef USE_VM_PROBES
- ERL_MESSAGE_DT_UTAG(mp) = NIL;
-#endif
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
if (!proc_queue_signal(NULL, to, (ErtsSignal *) mp,
ERTS_SIG_Q_OP_PERSISTENT_MON_MSG)) {
@@ -1564,11 +1561,6 @@ erts_proc_sig_send_is_alive_request(Process *c_p, Eterm to, Eterm ref)
ERL_MESSAGE_TERM(mp) = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_IS_ALIVE,
ERTS_SIG_Q_TYPE_UNDEFINED,
0);
- ERL_MESSAGE_TOKEN(mp) = NIL;
- ERL_MESSAGE_FROM(mp) = am_system;
-#ifdef USE_VM_PROBES
- ERL_MESSAGE_DT_UTAG(mp) = NIL;
-#endif
if (proc_queue_signal(c_p, to, (ErtsSignal *) mp, ERTS_SIG_Q_OP_IS_ALIVE))
(void) maybe_elevate_sig_handling_prio(c_p, to);
@@ -1672,11 +1664,6 @@ erts_proc_sig_send_sync_suspend(Process *c_p, Eterm to, Eterm tag, Eterm reply)
ERL_MESSAGE_TERM(mp) = ERTS_PROC_SIG_MAKE_TAG(ERTS_SIG_Q_OP_SYNC_SUSPEND,
ERTS_SIG_Q_TYPE_UNDEFINED,
0);
- ERL_MESSAGE_TOKEN(mp) = NIL;
- ERL_MESSAGE_FROM(mp) = am_system;
-#ifdef USE_VM_PROBES
- ERL_MESSAGE_DT_UTAG(mp) = NIL;
-#endif
if (proc_queue_signal(c_p, to, (ErtsSignal *) mp, ERTS_SIG_Q_OP_SYNC_SUSPEND))
(void) maybe_elevate_sig_handling_prio(c_p, to);
@@ -1790,7 +1777,7 @@ handle_rpc(Process *c_p, ErtsProcSigRPC *rpc, int cnt, int limit, int *yieldp)
msg = TUPLE2(hp, ref, res);
mp->hfrag.next = bp;
-
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_proc_message(c_p, rp, 0, mp, msg);
}
@@ -2155,10 +2142,7 @@ handle_exit_signal(Process *c_p, ErtsSigRecvTracing *tracing,
pid = STORE_NC(&hp, ohp, from);
ERL_MESSAGE_TERM(mp) = TUPLE3(hp, am_EXIT, pid, reason);
- ERL_MESSAGE_TOKEN(mp) = NIL;
-#ifdef USE_VM_PROBES
- ERL_MESSAGE_DT_UTAG(mp) = NIL;
-#endif
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
if (is_immed(pid))
ERL_MESSAGE_FROM(mp) = pid;
else {
@@ -2346,10 +2330,7 @@ convert_to_down_message(Process *c_p,
type, from, reason);
hp += 6;
- ERL_MESSAGE_TOKEN(mp) = NIL;
-#ifdef USE_VM_PROBES
- ERL_MESSAGE_DT_UTAG(mp) = NIL;
-#endif
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
/* Replace original signal with the exit message... */
convert_to_msg(c_p, sig, mp, next_nm_sig);
@@ -2397,10 +2378,7 @@ convert_to_nodedown_messages(Process *c_p,
ERL_MESSAGE_TERM(mp) = TUPLE2(hp, am_nodedown, node);
ERL_MESSAGE_FROM(mp) = am_system;
- ERL_MESSAGE_TOKEN(mp) = NIL;
-#ifdef USE_VM_PROBES
- ERL_MESSAGE_DT_UTAG(mp) = NIL;
-#endif
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
mp->next = nd_first;
nd_first = mp;
if (!nd_last)
@@ -2830,6 +2808,7 @@ handle_process_info(Process *c_p, ErtsSigRecvTracing *tracing,
if (is_alive)
erts_factory_trim_and_close(&hfact, &msg, 1);
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_proc_message(c_p, rp, locks, mp, msg);
if (!is_alive && locks)
@@ -2931,6 +2910,7 @@ sync_suspend_reply(Process *c_p, ErtsMessage *mp, erts_aint32_t state)
tp[2] = ssusp->async ? am_not_suspended : am_internal_error;
}
}
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_proc_message(c_p, rp, 0, mp, ssusp->message);
}
}
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 8784eb5a63..9386f79b56 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -9874,6 +9874,7 @@ notify_sys_task_executed(Process *c_p, ErtsProcSysTask *st,
ASSERT(hp_start + hsz == hp);
#endif
+ ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_proc_message(c_p, rp, rp_locks, mp, msg);
if (c_p == rp)
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index a60e117bab..8d20ccdf90 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -293,7 +293,7 @@ typedef enum {
* highest index...
*
* Remember to update description in erts_pre_init_process()
- * when adding new flags...
+ * and etp-commands when adding new flags...
*/
typedef enum {
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 2446b3c074..133ab485d9 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -3287,7 +3287,6 @@ static void deliver_read_message(Port* prt, erts_aint32_t state, Eterm to,
if (trace_send)
trace_port_send(prt, to, tuple, 1);
- ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_message(rp, rp_locks, mp, tuple, prt->common.id);
if (rp_locks)
erts_proc_unlock(rp, rp_locks);
@@ -3459,7 +3458,6 @@ deliver_vec_message(Port* prt, /* Port */
if (IS_TRACED_FL(prt, F_TRACE_SEND))
trace_port_send(prt, to, tuple, 1);
- ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_message(rp, rp_locks, mp, tuple, prt->common.id);
erts_proc_unlock(rp, rp_locks);
if (!scheduler)
@@ -5382,7 +5380,6 @@ void driver_report_exit(ErlDrvPort ix, int status)
if (IS_TRACED_FL(prt, F_TRACE_SEND))
trace_port_send(prt, pid, tuple, 1);
- ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_message(rp, rp_locks, mp, tuple, prt->common.id);
erts_proc_unlock(rp, rp_locks);
@@ -5988,8 +5985,6 @@ driver_deliver_term(Port *prt, Eterm to, ErlDrvTermData* data, int len)
from = prt->common.id;
}
- /* send message */
- ERL_MESSAGE_TOKEN(factory.message) = am_undefined;
erts_queue_message(rp, rp_locks, factory.message, mess, from);
}
else if (res == -2) {
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index 5e9afdc5ca..2048d0f625 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -1549,6 +1549,8 @@ static void *realloc_wrapper(void *current, ErlDrvSizeT size){
# define LOAD_ASSOC_ID LOAD_UINT
# define LOAD_ASSOC_ID_CNT LOAD_UINT_CNT
# define SCTP_ANC_BUFF_SIZE INET_DEF_BUFFER/2 /* XXX: not very good... */
+#else
+# define IS_SCTP(desc) 0
#endif
#ifdef HAVE_UDP
@@ -1785,6 +1787,7 @@ static void release_buffer(ErlDrvBinary* buf)
#ifdef HAVE_UDP
static ErlDrvBinary* realloc_buffer(ErlDrvBinary* buf, ErlDrvSizeT newsz)
{
+ DEBUGF(("realloc_buffer: %ld -> %ld\r\n", (buf==NULL) ? 0 : buf->orig_size, newsz));
return driver_realloc_binary(buf, newsz);
}
#endif
@@ -6435,7 +6438,12 @@ static int inet_set_opts(inet_descriptor* desc, char* ptr, int len)
(long)desc->port, desc->s, res));
if (type == SO_RCVBUF) {
/* make sure we have desc->bufsz >= SO_RCVBUF */
- if (ival > desc->bufsz)
+ if (ival > (1 << 16) && desc->stype == SOCK_DGRAM && !IS_SCTP(desc))
+ /* For UDP we don't want to automatically
+ set the buffer size to be larger than
+ the theoretical max MTU */
+ desc->bufsz = 1 << 16;
+ else if (ival > desc->bufsz)
desc->bufsz = ival;
}
}
@@ -12042,15 +12050,11 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
sys_memzero((char *) &other, sizeof(other));
/* udesc->i_buf is only kept between SCTP fragments */
- if (udesc->i_buf == NULL) {
- udesc->i_bufsz = desc->bufsz + len;
- if ((udesc->i_buf = alloc_buffer(udesc->i_bufsz)) == NULL)
- return packet_error(udesc, ENOMEM);
- /* pointer to message start */
- udesc->i_ptr = udesc->i_buf->orig_bytes + len;
- } else {
- ErlDrvBinary* tmp;
+#ifdef HAVE_SCTP
+ if (udesc->i_buf != NULL) {
+ ErlDrvBinary* tmp;
int bufsz;
+ ASSERT(IS_SCTP(desc));
bufsz = desc->bufsz + (udesc->i_ptr - udesc->i_buf->orig_bytes);
if ((tmp = realloc_buffer(udesc->i_buf, bufsz)) == NULL) {
release_buffer(udesc->i_buf);
@@ -12062,6 +12066,15 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
udesc->i_buf = tmp;
udesc->i_bufsz = bufsz;
}
+ } else
+#endif
+ {
+ ASSERT(udesc->i_buf == NULL);
+ udesc->i_bufsz = desc->bufsz + len;
+ if ((udesc->i_buf = alloc_buffer(udesc->i_bufsz)) == NULL)
+ return packet_error(udesc, ENOMEM);
+ /* pointer to message start */
+ udesc->i_ptr = udesc->i_buf->orig_bytes + len;
}
/* Note: On Windows NT, recvfrom() fails if the socket is connected. */
@@ -12120,6 +12133,14 @@ static int packet_inet_input(udp_descriptor* udesc, HANDLE event)
) {
sock_select(desc,FD_READ,1);
}
+#ifdef HAVE_SCTP
+ if (!short_recv) {
+#endif
+ release_buffer(udesc->i_buf);
+ udesc->i_buf = NULL;
+#ifdef HAVE_SCTP
+ }
+#endif
return count; /* strange, not ready */
}
diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c
index 3e77dce1cd..9f115706dc 100644
--- a/erts/emulator/sys/common/erl_check_io.c
+++ b/erts/emulator/sys/common/erl_check_io.c
@@ -1493,7 +1493,6 @@ send_event_tuple(struct erts_nif_select_event* e, ErtsResource* resource,
}
tuple = TUPLE4(hp, am_select, resource_term, ref_term, event_atom);
- ERL_MESSAGE_TOKEN(mp) = am_undefined;
erts_queue_message(rp, rp_locks, mp, tuple, am_system);
if (rp_locks)
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 189ca083d7..36579ffdb4 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -452,9 +452,9 @@ prepare_crash_dump(int secs)
envsz = sizeof(env);
i = erts_sys_explicit_8bit_getenv("ERL_CRASH_DUMP_NICE", env, &envsz);
- if (i >= 0) {
+ if (i != 0) {
int nice_val;
- nice_val = i != 1 ? 0 : atoi(env);
+ nice_val = (i != 1) ? 0 : atoi(env);
if (nice_val > 39) {
nice_val = 39;
}
diff --git a/erts/emulator/sys/unix/sys_drivers.c b/erts/emulator/sys/unix/sys_drivers.c
index 872c3a80b1..816bdea9c5 100644
--- a/erts/emulator/sys/unix/sys_drivers.c
+++ b/erts/emulator/sys/unix/sys_drivers.c
@@ -685,7 +685,7 @@ static ErlDrvData spawn_start(ErlDrvPort port_num, char* name,
/* we send the request to do the fork */
if ((res = writev(ofd[1], io_vector, iov_len > MAXIOV ? MAXIOV : iov_len)) < 0) {
- if (errno == ERRNO_BLOCK) {
+ if (errno == ERRNO_BLOCK || errno == EINTR) {
res = 0;
} else {
int err = errno;
@@ -1000,7 +1000,7 @@ static void clear_fd_data(ErtsSysFdData *fdd)
static void nbio_stop_fd(ErlDrvPort prt, ErtsSysFdData *fdd)
{
- driver_select(prt, abs(fdd->fd), DO_READ|DO_WRITE, 0);
+ driver_select(prt, abs(fdd->fd), ERL_DRV_USE_NO_CALLBACK|DO_READ|DO_WRITE, 0);
clear_fd_data(fdd);
SET_BLOCKING(abs(fdd->fd));
@@ -1257,6 +1257,8 @@ static int port_inp_failure(ErtsSysDriverData *dd, int res)
}
driver_failure_eof(dd->port_num);
} else if (dd->ifd) {
+ if (dd->alive == -1)
+ errno = dd->status;
erl_drv_init_ack(dd->port_num, ERL_DRV_ERROR_ERRNO);
} else {
driver_failure_posix(dd->port_num, err);
@@ -1287,10 +1289,10 @@ static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd)
int res;
if((res = read(ready_fd, &proto, sizeof(proto))) <= 0) {
+ if (res < 0 && (errno == ERRNO_BLOCK || errno == EINTR))
+ return;
/* hmm, child setup seems to have closed the pipe too early...
we close the port as there is not much else we can do */
- if (res < 0 && errno == ERRNO_BLOCK)
- return;
driver_select(port_num, ready_fd, ERL_DRV_READ, 0);
if (res == 0)
errno = EPIPE;
@@ -1424,7 +1426,7 @@ static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd)
continue;
}
else { /* The last message we got was split */
- char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h);
+ char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h);
if (!buf) {
errno = ENOMEM;
port_inp_failure(dd, -1);
@@ -1670,15 +1672,37 @@ static void forker_stop(ErlDrvData e)
the port has been closed by the user. */
}
+static ErlDrvSizeT forker_deq(ErlDrvPort port_num, ErtsSysForkerProto *proto)
+{
+ close(proto->u.start.fds[0]);
+ close(proto->u.start.fds[1]);
+ if (proto->u.start.fds[1] != proto->u.start.fds[2])
+ close(proto->u.start.fds[2]);
+
+ return driver_deq(port_num, sizeof(*proto));
+}
+
+static void forker_sigchld(Eterm port_id, int error)
+{
+ ErtsSysForkerProto *proto = erts_alloc(ERTS_ALC_T_DRV_CTRL_DATA, sizeof(*proto));
+ proto->action = ErtsSysForkerProtoAction_SigChld;
+ proto->u.sigchld.error_number = error;
+ proto->u.sigchld.port_id = port_id;
+
+ /* ideally this would be a port_command call, but as command is
+ already used by the spawn_driver, we use control instead.
+ Note that when using erl_drv_port_control it is an asynchronous
+ control. */
+ erl_drv_port_control(port_id, 'S', (char*)proto, sizeof(*proto));
+}
+
static void forker_ready_input(ErlDrvData e, ErlDrvEvent fd)
{
int res;
- ErtsSysForkerProto *proto;
+ ErtsSysForkerProto proto;
- proto = erts_alloc(ERTS_ALC_T_DRV_CTRL_DATA, sizeof(*proto));
-
- if ((res = read(fd, proto, sizeof(*proto))) < 0) {
- if (errno == ERRNO_BLOCK)
+ if ((res = read(fd, &proto, sizeof(proto))) < 0) {
+ if (errno == ERRNO_BLOCK || errno == EINTR)
return;
erts_exit(ERTS_DUMP_EXIT, "Failed to read from erl_child_setup: %d\n", errno);
}
@@ -1686,10 +1710,10 @@ static void forker_ready_input(ErlDrvData e, ErlDrvEvent fd)
if (res == 0)
erts_exit(ERTS_DUMP_EXIT, "erl_child_setup closed\n");
- ASSERT(res == sizeof(*proto));
+ ASSERT(res == sizeof(proto));
#ifdef FORKER_PROTO_START_ACK
- if (proto->action == ErtsSysForkerProtoAction_StartAck) {
+ if (proto.action == ErtsSysForkerProtoAction_StartAck) {
/* Ideally we would like to not have to ack each Start
command being sent over the uds, but it would seem
that some operating systems (only observed on FreeBSD)
@@ -1699,28 +1723,15 @@ static void forker_ready_input(ErlDrvData e, ErlDrvEvent fd)
ErlDrvPort port_num = (ErlDrvPort)e;
int vlen;
SysIOVec *iov = driver_peekq(port_num, &vlen);
- ErtsSysForkerProto *proto = (ErtsSysForkerProto *)iov[0].iov_base;
-
- close(proto->u.start.fds[0]);
- close(proto->u.start.fds[1]);
- if (proto->u.start.fds[1] != proto->u.start.fds[2])
- close(proto->u.start.fds[2]);
+ ErtsSysForkerProto *qproto = (ErtsSysForkerProto *)iov[0].iov_base;
- driver_deq(port_num, sizeof(*proto));
-
- if (driver_sizeq(port_num) > 0)
+ if (forker_deq(port_num, qproto))
driver_select(port_num, forker_fd, ERL_DRV_WRITE|ERL_DRV_USE, 1);
} else
#endif
{
- ASSERT(proto->action == ErtsSysForkerProtoAction_SigChld);
-
- /* ideally this would be a port_command call, but as command is
- already used by the spawn_driver, we use control instead.
- Note that when using erl_drv_port_control it is an asynchronous
- control. */
- erl_drv_port_control(proto->u.sigchld.port_id, 'S',
- (char*)proto, sizeof(*proto));
+ ASSERT(proto.action == ErtsSysForkerProtoAction_SigChld);
+ forker_sigchld(proto.u.sigchld.port_id, proto.u.sigchld.error_number);
}
}
@@ -1730,7 +1741,8 @@ static void forker_ready_output(ErlDrvData e, ErlDrvEvent fd)
ErlDrvPort port_num = (ErlDrvPort)e;
#ifndef FORKER_PROTO_START_ACK
- while (driver_sizeq(port_num) > 0) {
+ int loops = 10;
+ while (driver_sizeq(port_num) > 0 && --loops) {
#endif
int vlen;
SysIOVec *iov = driver_peekq(port_num, &vlen);
@@ -1738,20 +1750,24 @@ static void forker_ready_output(ErlDrvData e, ErlDrvEvent fd)
ASSERT(iov[0].iov_len >= (sizeof(*proto)));
if (sys_uds_write(forker_fd, (char*)proto, sizeof(*proto),
proto->u.start.fds, 3, 0) < 0) {
- if (errno == ERRNO_BLOCK)
+ if (errno == ERRNO_BLOCK || errno == EINTR) {
return;
- erts_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno);
+ } else if (errno == EMFILE) {
+ forker_sigchld(proto->u.start.port_id, errno);
+ if (forker_deq(port_num, proto) == 0)
+ driver_select(port_num, forker_fd, ERL_DRV_WRITE, 0);
+ return;
+ } else {
+ erts_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno);
+ }
}
#ifndef FORKER_PROTO_START_ACK
- close(proto->u.start.fds[0]);
- close(proto->u.start.fds[1]);
- if (proto->u.start.fds[1] != proto->u.start.fds[2])
- close(proto->u.start.fds[2]);
- driver_deq(port_num, sizeof(*proto));
+ if (forker_deq(port_num, proto) == 0)
+ driver_select(port_num, forker_fd, ERL_DRV_WRITE, 0);
}
-#endif
-
+#else
driver_select(port_num, forker_fd, ERL_DRV_WRITE, 0);
+#endif
}
static ErlDrvSSizeT forker_control(ErlDrvData e, unsigned int cmd, char *buf,
@@ -1777,20 +1793,21 @@ static ErlDrvSSizeT forker_control(ErlDrvData e, unsigned int cmd, char *buf,
if ((res = sys_uds_write(forker_fd, (char*)proto, sizeof(*proto),
proto->u.start.fds, 3, 0)) < 0) {
- if (errno == ERRNO_BLOCK) {
+ if (errno == ERRNO_BLOCK || errno == EINTR) {
driver_select(port_num, forker_fd, ERL_DRV_WRITE|ERL_DRV_USE, 1);
return 0;
+ } else if (errno == EMFILE) {
+ forker_sigchld(proto->u.start.port_id, errno);
+ forker_deq(port_num, proto);
+ return 0;
+ } else {
+ erts_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno);
}
- erts_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno);
}
#ifndef FORKER_PROTO_START_ACK
ASSERT(res == sizeof(*proto));
- close(proto->u.start.fds[0]);
- close(proto->u.start.fds[1]);
- if (proto->u.start.fds[1] != proto->u.start.fds[2])
- close(proto->u.start.fds[2]);
- driver_deq(port_num, sizeof(*proto));
+ forker_deq(port_num, proto);
#endif
return 0;
diff --git a/erts/emulator/sys/unix/sys_uds.c b/erts/emulator/sys/unix/sys_uds.c
index c328fd00bb..39a4866065 100644
--- a/erts/emulator/sys/unix/sys_uds.c
+++ b/erts/emulator/sys/unix/sys_uds.c
@@ -132,7 +132,7 @@ sys_uds_writev(int fd, struct iovec *iov, size_t iov_len,
struct msghdr msg;
struct cmsghdr *cmsg = NULL;
- int res, i;
+ int res, i, error;
/* initialize socket message */
memset(&msg, 0, sizeof(struct msghdr));
@@ -173,11 +173,22 @@ sys_uds_writev(int fd, struct iovec *iov, size_t iov_len,
res = sendmsg(fd, &msg, flags);
+#ifdef ETOOMANYREFS
+ /* Linux may give ETOOMANYREFS when there are too many fds in transit.
+ We map this to EMFILE as bsd and other use this error code and we want
+ the behaviour to be the same on all OSs */
+ if (errno == ETOOMANYREFS)
+ errno = EMFILE;
+#endif
+ error = errno;
+
if (iov_len > MAXIOV)
free(iov[0].iov_base);
free(msg.msg_control);
+ errno = error;
+
return res;
}
diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c
index fd4c745c3b..fcf5a0d533 100644
--- a/erts/emulator/sys/win32/erl_poll.c
+++ b/erts/emulator/sys/win32/erl_poll.c
@@ -362,11 +362,11 @@ is_io_ready(ErtsPollSet *ps)
}
static ERTS_INLINE void
-woke_up(ErtsPollSet *ps)
+woke_up(ErtsPollSet *ps, int waketype)
{
if (erts_atomic32_read_nob(&ps->wakeup_state) == ERTS_POLL_NOT_WOKEN)
erts_atomic32_cmpxchg_nob(&ps->wakeup_state,
- ERTS_POLL_WOKEN_TIMEDOUT,
+ waketype,
ERTS_POLL_NOT_WOKEN);
#ifdef DEBUG
{
@@ -960,12 +960,12 @@ static int cancel_driver_select(ErtsPollSet *ps, HANDLE event)
void erts_poll_interrupt(ErtsPollSet *ps, int set /* bool */)
{
- HARDTRACEF(("In erts_poll_interrupt(%d)",set));
+ HARDTRACEF(("In erts_poll_interrupt(%p, %d)",ps,set));
if (!set)
reset_interrupt(ps);
else
set_interrupt(ps);
- HARDTRACEF(("Out erts_poll_interrupt(%d)",set));
+ HARDTRACEF(("Out erts_poll_interrupt(%p, %d)",ps,set));
}
@@ -1051,19 +1051,20 @@ int erts_poll_wait(ErtsPollSet *ps,
if (!erts_atomic32_read_nob(&break_waiter_state)) {
HANDLE harr[2] = {ps->event_io_ready, break_happened_event};
- int num_h = 2;
+ int num_h = 2, handle;
ERTS_MSACC_PUSH_STATE();
HARDDEBUGF(("Start waiting %d [%d]",num_h, (int) timeout));
ERTS_POLLSET_UNLOCK(ps);
erts_thr_progress_prepare_wait(NULL);
ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_SLEEP);
- WaitForMultipleObjects(num_h, harr, FALSE, timeout);
+ handle = WaitForMultipleObjects(num_h, harr, FALSE, timeout);
erts_thr_progress_finalize_wait(NULL);
ERTS_MSACC_POP_STATE();
ERTS_POLLSET_LOCK(ps);
HARDDEBUGF(("Stop waiting %d [%d]",num_h, (int) timeout));
- woke_up(ps);
+ if (handle == WAIT_OBJECT_0)
+ woke_up(ps, ERTS_POLL_WOKEN_TIMEDOUT);
}
ERTS_UNSET_BREAK_REQUESTED;
@@ -1075,7 +1076,10 @@ int erts_poll_wait(ErtsPollSet *ps,
erts_mtx_unlock(&break_waiter_lock);
switch (break_state) {
case BREAK_WAITER_GOT_BREAK:
+ woke_up(ps, ERTS_POLL_WOKEN_INTR);
ERTS_SET_BREAK_REQUESTED;
+ /* Wake aux thread to get handle break */
+ erts_aux_thread_poke();
break;
case BREAK_WAITER_GOT_HALT:
erts_exit(0,"");
diff --git a/erts/emulator/test/nif_SUITE.erl b/erts/emulator/test/nif_SUITE.erl
index 7c85cf2259..a2f3489943 100644
--- a/erts/emulator/test/nif_SUITE.erl
+++ b/erts/emulator/test/nif_SUITE.erl
@@ -45,8 +45,9 @@
api_macros/1,
from_array/1, iolist_as_binary/1, resource/1, resource_binary/1,
resource_takeover/1,
- threading/1, send/1, send2/1, send3/1, send_threaded/1, neg/1,
- is_checks/1,
+ threading/1, send/1, send2/1, send3/1, send_threaded/1,
+ send_trace/1, send_seq_trace/1,
+ neg/1, is_checks/1,
get_length/1, make_atom/1, make_string/1, reverse_list_test/1,
otp_9828/1,
otp_9668/1, consume_timeslice/1, nif_schedule/1,
@@ -1789,6 +1790,59 @@ send(Config) when is_list(Config) ->
{ok,0} = send_list_seq(7, DeadPid),
ok.
+
+%% Test tracing of enif_send
+send_trace(Config) when is_list(Config) ->
+ ensure_lib_loaded(Config),
+
+ Papa = self(),
+ N = 1500,
+ List = lists:seq(1,N),
+
+ Tracer = spawn_link(fun F() -> receive get -> Papa ! receive_any(), F() end end),
+
+ erlang:trace(self(), true, [send,'receive',{tracer,Tracer}]),
+ {ok,1} = send_list_seq(N, self()),
+ List = receive_any(),
+ timeout = receive_any(0),
+ Tracer ! get,
+ {trace,Papa,send,List,Papa} = receive_any(),
+ Tracer ! get,
+ {trace,Papa,'receive',List} = receive_any().
+
+%% Test that seq_trace works with nif trace
+send_seq_trace(Config) when is_list(Config) ->
+ ensure_lib_loaded(Config),
+
+ Papa = self(),
+ N = 1500,
+ List = lists:seq(1,N),
+ Label = make_ref(),
+
+ Tracer = spawn_link(fun F() -> receive get -> Papa ! receive_any(), F() end end),
+
+ seq_trace:set_system_tracer(Tracer),
+ seq_trace:set_token(label,Label),
+ seq_trace:set_token(send,true),
+ seq_trace:set_token('receive',true),
+
+ {ok,1} = send_list_seq(N, self()),
+ List = receive_any(),
+ timeout = receive_any(0),
+ {ok,1} = send_list_seq(N, self()),
+ List = receive_any(),
+ timeout = receive_any(0),
+
+ Tracer ! get,
+ {seq_trace,Label,{send,{0,1},Papa,Papa,List}} = receive_any(),
+ Tracer ! get,
+ {seq_trace,Label,{'receive',{0,1},Papa,Papa,List}} = receive_any(),
+ Tracer ! get,
+ {seq_trace,Label,{send,{1,2},Papa,Papa,List}} = receive_any(),
+ Tracer ! get,
+ {seq_trace,Label,{'receive',{1,2},Papa,Papa,List}} = receive_any().
+
+
%% More NIF message sending
send2(Config) when is_list(Config) ->
ensure_lib_loaded(Config),
diff --git a/erts/etc/unix/cerl.src b/erts/etc/unix/cerl.src
index 3572fdd954..2e034513b0 100644
--- a/erts/etc/unix/cerl.src
+++ b/erts/etc/unix/cerl.src
@@ -69,15 +69,6 @@ cxargs_add() {
done
}
-eeargs=
-eeargs_add() {
- while [ $# -gt 0 ]; do
- cargs="$cargs $1"
- eeargs="$eeargs $1"
- shift
- done
-}
-
core=
GDB=
@@ -97,8 +88,6 @@ TARGET=%TARGET%
PROGNAME=$ROOTDIR/bin/cerl
EMU=beam
-PRELOADED=$ROOTDIR/erts/preloaded/ebin
-
while [ $# -gt 0 ]; do
case "$1" in
@@ -255,7 +244,7 @@ EXEC=$BINDIR/erlexec
PROGNAME="$PROGNAME$cargs"
EMU="$EMU$TYPE"
-EMU_NAME=`$EXEC -emu_name_exit $eeargs`
+EMU_NAME=`$EXEC -emu_name_exit`
if [ $skip_erlexec = yes ]; then
emu_xargs=`echo $xargs | sed "s|+|-|g"`
@@ -269,21 +258,20 @@ if [ $skip_erlexec = yes ]; then
'
set -- $beam_args
IFS="$SAVE_IFS"
-else
- xargs="$xargs -pz $PRELOADED --"
fi
if [ "x$GDB" = "x" ]; then
if [ $run_valgrind = yes ]; then
valversion=`valgrind --version`
valmajor=`echo $valversion | sed 's,[a-z]*\-\([0-9]*\).*,\1,'`
valminor=`echo $valversion | sed 's,[a-z]*\-[0-9]*.\([0-9]*\).*,\1,'`
+ valint=`echo "$valmajor * 1000 + $valminor" | bc`
if [ "x$VALGRIND_LOG_XML" = "x" ]; then
valgrind_xml=
log_file_prefix="--log-file="
else
export VALGRIND_LOG_XML
valgrind_xml="--xml=yes"
- if [ $valmajor -gt 2 -a $valminor -gt 4 ]; then
+ if [ $valint -gt 3004 ]; then
log_file_prefix="--xml-file="
else
log_file_prefix="--log-file="
@@ -292,7 +280,7 @@ if [ "x$GDB" = "x" ]; then
if [ "x$VALGRIND_LOG_DIR" = "x" ]; then
valgrind_log=
else
- if [ $valmajor -gt 2 -a $valminor -gt 4 ]; then
+ if [ $valint -gt 3004 ]; then
valgrind_log="$log_file_prefix$VALGRIND_LOG_DIR/$VALGRIND_LOGFILE_PREFIX$VALGRIND_LOGFILE_INFIX$EMU_NAME.log.$$"
else
valgrind_log="$log_file_prefix$VALGRIND_LOG_DIR/$VALGRIND_LOGFILE_PREFIX$VALGRIND_LOGFILE_INFIX$EMU_NAME.log"
@@ -316,12 +304,12 @@ if [ "x$GDB" = "x" ]; then
sched_arg=
fi
- exec $taskset1 valgrind $valgrind_xml $valgrind_log $valgrind_misc_flags $BINDIR/$EMU_NAME $sched_arg $emu_xargs "$@" -pz $PRELOADED
+ exec $taskset1 valgrind $valgrind_xml $valgrind_log $valgrind_misc_flags $BINDIR/$EMU_NAME $sched_arg $emu_xargs "$@"
elif [ $run_rr = yes ]; then
- exec rr record --ignore-nested $BINDIR/$EMU_NAME $emu_xargs "$@" -pz $PRELOADED
+ exec rr record --ignore-nested $BINDIR/$EMU_NAME $emu_xargs "$@"
else
- exec $EXEC $eeargs $xargs ${1+"$@"}
+ exec $EXEC $xargs ${1+"$@"}
fi
elif [ "x$GDB" = "xgdb" ]; then
case "x$core" in
diff --git a/erts/etc/unix/etp-commands.in b/erts/etc/unix/etp-commands.in
index 5b89621733..b12a205ba7 100644
--- a/erts/etc/unix/etp-commands.in
+++ b/erts/etc/unix/etp-commands.in
@@ -2734,25 +2734,37 @@ define etp-aux-work-flags
printf " fix-alloc-lower-lim"
end
if ($arg0 & 0x10)
- printf " async-ready"
+ printf " later-op"
end
if ($arg0 & 0x20)
- printf " async-ready-clean"
+ printf " canceled-timers"
end
if ($arg0 & 0x40)
- printf " misc-work-thr-prgr"
+ printf " canceled-timers-thr-prgr"
end
if ($arg0 & 0x80)
- printf " misc-work"
+ printf " async-ready"
end
if ($arg0 & 0x100)
- printf " check-children"
+ printf " async-ready-clean"
end
if ($arg0 & 0x200)
- printf " set-tmo"
+ printf " misc-thr-prgr"
end
if ($arg0 & 0x400)
- printf " mseg-cached-check"
+ printf " misc"
+ end
+ if ($arg0 & 0x800)
+ printf " set-tmo"
+ end
+ if ($arg0 & 0x1000)
+ printf " mseg-cache-check"
+ end
+ if ($arg0 & 0x2000)
+ printf " yield"
+ end
+ if ($arg0 & 0x1000)
+ printf " reap-ports"
end
if ($arg0 & ~0x7ff)
printf " GARBAGE"
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index f4f31b1e4b..1ed6b6b284 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -86,15 +86,15 @@
| 'nano_seconds'.
-opaque prepared_code() :: reference().
-
-export_type([prepared_code/0]).
--opaque dist_handle() :: atom().
+-opaque nif_resource() :: reference().
+-export_type([nif_resource/0]).
+-opaque dist_handle() :: atom().
-export_type([dist_handle/0]).
-type iovec() :: [binary()].
-
-export_type([iovec/0]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -2316,7 +2316,7 @@ process_flag(_Flag, _Value) ->
{min_heap_size, MinHeapSize :: non_neg_integer()} |
{min_bin_vheap_size, MinBinVHeapSize :: non_neg_integer()} |
{max_heap_size, MaxHeapSize :: max_heap_size()} |
- {monitored_by, Pids :: [pid()]} |
+ {monitored_by, MonitoredBy :: [pid() | port() | nif_resource()]} |
{monitors,
Monitors :: [{process | port, Pid :: pid() | port() |
{RegName :: atom(), Node :: node()}}]} |
@@ -2681,11 +2681,12 @@ tuple_to_list(_Tuple) ->
(dist_ctrl) -> {Node :: node(),
ControllingEntity :: port() | pid()};
(driver_version) -> string();
- (dynamic_trace) -> none | dtrace | systemtap;
+ (dynamic_trace) -> none | dtrace | systemtap;
(dynamic_trace_probes) -> boolean();
(end_time) -> non_neg_integer();
(elib_malloc) -> false;
(eager_check_io) -> boolean();
+ (ets_count) -> pos_integer();
(ets_limit) -> pos_integer();
(fullsweep_after) -> {fullsweep_after, non_neg_integer()};
(garbage_collection) -> [{atom(), integer()}];