aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/erlang.xml112
-rw-r--r--erts/doc/src/notes.xml75
-rw-r--r--erts/emulator/beam/bif.c6
-rw-r--r--erts/emulator/beam/binary.c6
-rw-r--r--erts/emulator/beam/break.c41
-rw-r--r--erts/emulator/beam/erl_bif_info.c1
-rw-r--r--erts/emulator/beam/erl_db_util.c2
-rw-r--r--erts/emulator/beam/erl_process.c242
-rw-r--r--erts/emulator/beam/erl_process.h4
-rw-r--r--erts/emulator/beam/global.h2
-rw-r--r--erts/emulator/beam/utils.c55
-rw-r--r--erts/emulator/drivers/common/inet_drv.c40
-rw-r--r--erts/emulator/sys/common/erl_check_io.c4
-rw-r--r--erts/emulator/sys/common/erl_poll.c10
-rw-r--r--erts/emulator/sys/unix/sys_drivers.c12
-rw-r--r--erts/emulator/test/driver_SUITE.erl19
-rw-r--r--erts/emulator/test/process_SUITE.erl14
-rw-r--r--erts/emulator/test/scheduler_SUITE.erl27
-rw-r--r--erts/emulator/test/z_SUITE.erl2
-rw-r--r--erts/preloaded/ebin/erl_prim_loader.beambin54480 -> 54496 bytes
-rw-r--r--erts/preloaded/ebin/init.beambin51528 -> 51536 bytes
-rw-r--r--erts/preloaded/src/erl_prim_loader.erl2
-rw-r--r--erts/preloaded/src/init.erl2
-rw-r--r--erts/vsn.mk2
24 files changed, 397 insertions, 283 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 7699f64c25..fabca87e9f 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -3339,7 +3339,7 @@ RealSystem = system + MissedSystem</code>
<func>
<name name="monitor" arity="2" clause_i="1" since=""/>
- <name name="monitor" arity="2" clause_i="2" since="?"/>
+ <name name="monitor" arity="2" clause_i="2" since="OTP 19.0"/>
<name name="monitor" arity="2" clause_i="3" since="OTP 18.0"/>
<fsummary>Start monitoring.</fsummary>
<type name="registered_name"/>
@@ -4526,7 +4526,7 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="port_info" arity="2" clause_i="5" since="?"/>
+ <name name="port_info" arity="2" clause_i="5" since="OTP R16B"/>
<fsummary>Information about the locking of a port.</fsummary>
<desc>
<p><c><anno>Locking</anno></c> is one of the following:</p>
@@ -4547,7 +4547,7 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="port_info" arity="2" clause_i="6" since="?"/>
+ <name name="port_info" arity="2" clause_i="6" since="OTP R16B"/>
<fsummary>Information about the memory size of a port.</fsummary>
<desc>
<p><c><anno>Bytes</anno></c> is the total number of
@@ -4565,7 +4565,7 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="port_info" arity="2" clause_i="7" since="?"/>
+ <name name="port_info" arity="2" clause_i="7" since="OTP R16B"/>
<fsummary>Information about the monitors of a port.</fsummary>
<desc>
<p><c><anno>Monitors</anno></c> represent processes monitored by
@@ -4581,7 +4581,7 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="port_info" arity="2" clause_i="8" since="?"/>
+ <name name="port_info" arity="2" clause_i="8" since="OTP 19.0"/>
<fsummary>Which processes are monitoring this port.</fsummary>
<desc>
<p>Returns list of pids that are monitoring given port at the
@@ -4613,7 +4613,7 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="port_info" arity="2" clause_i="10" since="?"/>
+ <name name="port_info" arity="2" clause_i="10" since="OTP R16B"/>
<fsummary>Information about the OS pid of a port.</fsummary>
<desc>
<p><c><anno>OsPid</anno></c> is the process identifier (or equivalent)
@@ -4651,7 +4651,7 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="port_info" arity="2" clause_i="12" since="?"/>
+ <name name="port_info" arity="2" clause_i="12" since="OTP R16B"/>
<fsummary>Information about the parallelism hint of a port.</fsummary>
<desc>
<p><c><anno>Boolean</anno></c> corresponds to the port parallelism
@@ -4662,7 +4662,7 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="port_info" arity="2" clause_i="13" since="?"/>
+ <name name="port_info" arity="2" clause_i="13" since="OTP R16B"/>
<fsummary>Information about the queue size of a port.</fsummary>
<desc>
<p><c><anno>Bytes</anno></c> is the total number
@@ -4782,7 +4782,7 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="process_flag" arity="2" clause_i="4" since="?"/>
+ <name name="process_flag" arity="2" clause_i="4" since="OTP R13B04"/>
<fsummary>Set process flag min_bin_vheap_size for the calling process.
</fsummary>
<desc>
@@ -4794,7 +4794,7 @@ RealSystem = system + MissedSystem</code>
<func>
<name name="process_flag" arity="2" clause_i="5"
- anchor="process_flag_max_heap_size" since="?"/>
+ anchor="process_flag_max_heap_size" since="OTP 19.0"/>
<fsummary>Set process flag max_heap_size for the calling process.
</fsummary>
<type name="max_heap_size"/>
@@ -4868,7 +4868,7 @@ RealSystem = system + MissedSystem</code>
<func>
<name name="process_flag" arity="2" clause_i="6"
- anchor="process_flag_message_queue_data" since="?"/>
+ anchor="process_flag_message_queue_data" since="OTP 19.0"/>
<fsummary>Set process flag message_queue_data for the calling process.
</fsummary>
<type name="message_queue_data"/>
@@ -5047,7 +5047,7 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="process_flag" arity="3" since="?"/>
+ <name name="process_flag" arity="3" since=""/>
<fsummary>Set process flags for a process.</fsummary>
<desc>
<p>Sets certain flags for the process <c><anno>Pid</anno></c>,
@@ -6399,7 +6399,7 @@ true</pre>
<func>
<name name="statistics" arity="1" clause_i="1"
- anchor="statistics_active_tasks" since="?"/>
+ anchor="statistics_active_tasks" since="OTP 18.3"/>
<fsummary>Information about active processes and ports.</fsummary>
<desc>
<p>Returns the same as
@@ -6414,7 +6414,7 @@ true</pre>
<func>
<name name="statistics" arity="1" clause_i="2"
- anchor="statistics_active_tasks_all" since="?"/>
+ anchor="statistics_active_tasks_all" since="OTP 20.0"/>
<fsummary>Information about active processes and ports.</fsummary>
<desc>
<p>Returns a list where each element represents the amount
@@ -6503,7 +6503,7 @@ true</pre>
<func>
<name name="statistics" arity="1" clause_i="7"
- anchor="statistics_microstate_accounting" since="?"/>
+ anchor="statistics_microstate_accounting" since="OTP 19.0"/>
<fsummary>Information about microstate accounting.</fsummary>
<desc>
<p>Microstate accounting can be used to measure how much time the Erlang
@@ -6682,7 +6682,7 @@ lists:map(
<func>
<name name="statistics" arity="1" clause_i="10"
- anchor="statistics_run_queue_lengths" since="?"/>
+ anchor="statistics_run_queue_lengths" since="OTP 18.3"/>
<fsummary>Information about the run-queue lengths.</fsummary>
<desc>
<p>Returns the same as
@@ -6697,7 +6697,7 @@ lists:map(
<func>
<name name="statistics" arity="1" clause_i="11"
- anchor="statistics_run_queue_lengths_all" since="?"/>
+ anchor="statistics_run_queue_lengths_all" since="OTP 20.0"/>
<fsummary>Information about the run-queue lengths.</fsummary>
<desc>
<p>Returns a list where each element represents the amount
@@ -6758,7 +6758,7 @@ lists:map(
<func>
<name name="statistics" arity="1" clause_i="13"
- anchor="statistics_scheduler_wall_time" since="?"/>
+ anchor="statistics_scheduler_wall_time" since="OTP R15B01"/>
<fsummary>Information about each schedulers work time.</fsummary>
<desc>
<p>Returns a list of tuples with
@@ -6882,7 +6882,7 @@ ok
<func>
<name name="statistics" arity="1" clause_i="14"
- anchor="statistics_scheduler_wall_time_all" since="?"/>
+ anchor="statistics_scheduler_wall_time_all" since="OTP 20.0"/>
<fsummary>Information about each schedulers work time.</fsummary>
<desc>
<p>The same as
@@ -6910,7 +6910,7 @@ ok
</func>
<func>
<name name="statistics" arity="1" clause_i="15"
- anchor="statistics_total_active_tasks" since="?"/>
+ anchor="statistics_total_active_tasks" since="OTP 18.3"/>
<fsummary>Information about active processes and ports.</fsummary>
<desc>
<p>The same as calling
@@ -6921,7 +6921,7 @@ ok
<func>
<name name="statistics" arity="1" clause_i="16"
- anchor="statistics_total_active_tasks_all" since="?"/>
+ anchor="statistics_total_active_tasks_all" since="OTP 20.0"/>
<fsummary>Information about active processes and ports.</fsummary>
<desc>
<p>The same as calling
@@ -6932,7 +6932,7 @@ ok
<func>
<name name="statistics" arity="1" clause_i="17"
- anchor="statistics_total_run_queue_lengths" since="?"/>
+ anchor="statistics_total_run_queue_lengths" since="OTP 18.3"/>
<fsummary>Information about the run-queue lengths.</fsummary>
<desc>
<p>The same as calling
@@ -6943,7 +6943,7 @@ ok
<func>
<name name="statistics" arity="1" clause_i="18"
- anchor="statistics_total_run_queue_lengths_all" since="?"/>
+ anchor="statistics_total_run_queue_lengths_all" since="OTP 20.0"/>
<fsummary>Information about the run-queue lengths.</fsummary>
<desc>
<p>The same as calling
@@ -7186,7 +7186,7 @@ ok
<func>
<name name="system_flag" arity="2" clause_i="3"
- anchor="system_flag_dirty_cpu_schedulers_online" since="?"/>
+ anchor="system_flag_dirty_cpu_schedulers_online" since="OTP 17.0"/>
<fsummary>Set system_flag_dirty_cpu_schedulers_online.</fsummary>
<desc>
<p>
@@ -7214,7 +7214,7 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="4" since="?"/>
+ <name name="system_flag" arity="2" clause_i="4" since="OTP 20.2.3"/>
<fsummary>Set system flag for erts_alloc.</fsummary>
<desc>
<p>Sets system flags for
@@ -7251,7 +7251,7 @@ ok
<func>
<name name="system_flag" arity="2" clause_i="6"
- anchor="system_flag_microstate_accounting" since="?"/>
+ anchor="system_flag_microstate_accounting" since="OTP 19.0"/>
<fsummary>Set system flag microstate_accounting.</fsummary>
<desc>
<p>
@@ -7279,7 +7279,7 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="8" since="?"/>
+ <name name="system_flag" arity="2" clause_i="8" since="OTP R13B04"/>
<fsummary>Set system flag min_bin_vheap_size.</fsummary>
<desc>
<p>Sets the default minimum binary virtual heap size for
@@ -7297,7 +7297,7 @@ ok
<func>
<name name="system_flag" arity="2" clause_i="9"
- anchor="system_flag_max_heap_size" since="?"/>
+ anchor="system_flag_max_heap_size" since="OTP 19.0"/>
<fsummary>Set system flag max_heap_size.</fsummary>
<type name="max_heap_size"/>
<desc>
@@ -7498,7 +7498,7 @@ ok
<func>
<name name="system_flag" arity="2" clause_i="12"
- anchor="system_flag_scheduler_wall_time" since="?"/>
+ anchor="system_flag_scheduler_wall_time" since="OTP R15B01"/>
<fsummary>Set system flag scheduler_wall_time.</fsummary>
<desc>
<p>
@@ -7586,7 +7586,7 @@ Metadata = #{ pid => pid(),
<func>
<name name="system_flag" arity="2" clause_i="16"
- anchor="system_flag_time_offset" since="?"/>
+ anchor="system_flag_time_offset" since="OTP 18.0"/>
<fsummary>Finalize the time offset.</fsummary>
<desc>
<p>
@@ -7909,7 +7909,7 @@ Metadata = #{ pid => pid(),
anchor="system_info_cpu_topology" since=""/> <!-- cpu_topology -->
<name name="system_info" arity="1" clause_i="13" since=""/> <!-- {cpu_topology, _} -->
<name name="system_info" arity="1" clause_i="38" since=""/> <!-- logical_processors -->
- <name name="system_info" arity="1" clause_i="74" since="?"/> <!-- update_cpu_info -->
+ <name name="system_info" arity="1" clause_i="74" since="OTP R14B"/> <!-- update_cpu_info -->
<fsummary>Information about the CPU topology of the system.</fsummary>
<type name="cpu_topology"/>
<type name="level_entry"/>
@@ -8061,14 +8061,14 @@ Metadata = #{ pid => pid(),
<func>
<name name="system_info" arity="1" clause_i="31"
- anchor="system_info_process" since="?"/> <!-- fullsweep_after -->
+ anchor="system_info_process" since=""/> <!-- fullsweep_after -->
<name name="system_info" arity="1" clause_i="32" since=""/> <!-- garbage_collection -->
<name name="system_info" arity="1" clause_i="33" since=""/> <!-- heap_sizes -->
<name name="system_info" arity="1" clause_i="34" since=""/> <!-- heap_type -->
- <name name="system_info" arity="1" clause_i="40" since="?"/> <!-- max_heap_size -->
- <name name="system_info" arity="1" clause_i="41" since="?"/> <!-- message_queue_data -->
- <name name="system_info" arity="1" clause_i="42" since="?"/> <!-- min_heap_size -->
- <name name="system_info" arity="1" clause_i="43" since="?"/> <!-- min_bin_vheap_size -->
+ <name name="system_info" arity="1" clause_i="40" since="OTP 19.0"/> <!-- max_heap_size -->
+ <name name="system_info" arity="1" clause_i="41" since="OTP 19.0"/> <!-- message_queue_data -->
+ <name name="system_info" arity="1" clause_i="42" since="OTP R13B04"/> <!-- min_heap_size -->
+ <name name="system_info" arity="1" clause_i="43" since="OTP R13B04"/> <!-- min_bin_vheap_size -->
<name name="system_info" arity="1" clause_i="57" since=""/> <!-- procs -->
<fsummary>Information about the default process heap settings.</fsummary>
<type name="message_queue_data"/>
@@ -8179,12 +8179,12 @@ Metadata = #{ pid => pid(),
</func>
<func>
- <name name="system_info" arity="1" clause_i="6" anchor="system_info_limits" since="?"/> <!-- atom_count -->
- <name name="system_info" arity="1" clause_i="7" since="?"/> <!-- atom_limit -->
- <name name="system_info" arity="1" clause_i="29" since="?"/> <!-- ets_count -->
- <name name="system_info" arity="1" clause_i="30" since="?"/> <!-- ets_limit -->
- <name name="system_info" arity="1" clause_i="53" since="?"/> <!-- port_count -->
- <name name="system_info" arity="1" clause_i="54" since="?"/> <!-- port_limit -->
+ <name name="system_info" arity="1" clause_i="6" anchor="system_info_limits" since="OTP 20.0"/> <!-- atom_count -->
+ <name name="system_info" arity="1" clause_i="7" since="OTP 20.0"/> <!-- atom_limit -->
+ <name name="system_info" arity="1" clause_i="29" since="OTP 21.1"/> <!-- ets_count -->
+ <name name="system_info" arity="1" clause_i="30" since="OTP R16B03"/> <!-- ets_limit -->
+ <name name="system_info" arity="1" clause_i="53" since="OTP R16B"/> <!-- port_count -->
+ <name name="system_info" arity="1" clause_i="54" since="OTP R16B"/> <!-- port_limit -->
<name name="system_info" arity="1" clause_i="55" since=""/> <!-- process_count -->
<name name="system_info" arity="1" clause_i="56" since=""/> <!-- process_limit -->
<fsummary>Information about various system limits.</fsummary>
@@ -8267,7 +8267,7 @@ Metadata = #{ pid => pid(),
<name name="system_info" arity="1" clause_i="69" since="OTP 18.0"/> <!-- time_correction -->
<name name="system_info" arity="1" clause_i="70" since="OTP 18.0"/> <!-- time_offset -->
<name name="system_info" arity="1" clause_i="71" since="OTP 18.0"/> <!-- time_warp_mode -->
- <name name="system_info" arity="1" clause_i="72" since="?"/> <!-- tolerant_timeofday -->
+ <name name="system_info" arity="1" clause_i="72" since="OTP 17.1"/> <!-- tolerant_timeofday -->
<fsummary>Information about system time.</fsummary>
<desc>
<marker id="system_info_time_tags"/>
@@ -8488,12 +8488,12 @@ Metadata = #{ pid => pid(),
<func>
<name name="system_info" arity="1" clause_i="17"
- anchor="system_info_scheduler" since="?"/> <!-- dirty_cpu_schedulers -->
- <name name="system_info" arity="1" clause_i="18" since="?"/> <!-- dirty_cpu_schedulers_online -->
- <name name="system_info" arity="1" clause_i="19" since="?"/> <!-- dirty_io_schedulers -->
+ anchor="system_info_scheduler" since="OTP 17.0"/> <!-- dirty_cpu_schedulers -->
+ <name name="system_info" arity="1" clause_i="18" since="OTP 17.0"/> <!-- dirty_cpu_schedulers_online -->
+ <name name="system_info" arity="1" clause_i="19" since="OTP 17.0"/> <!-- dirty_io_schedulers -->
<name name="system_info" arity="1" clause_i="45" since=""/> <!-- multi_scheduling -->
<name name="system_info" arity="1" clause_i="46" since=""/> <!-- multi_scheduling_blockers -->
- <name name="system_info" arity="1" clause_i="49" since="?"/> <!-- normal_multi_scheduling_blockers -->
+ <name name="system_info" arity="1" clause_i="49" since="OTP 19.0"/> <!-- normal_multi_scheduling_blockers -->
<name name="system_info" arity="1" clause_i="58" since=""/> <!-- scheduler_bind_type -->
<name name="system_info" arity="1" clause_i="59" since=""/> <!-- scheduler_bindings -->
<name name="system_info" arity="1" clause_i="60" since=""/> <!-- scheduler_id -->
@@ -8789,9 +8789,9 @@ Metadata = #{ pid => pid(),
<func>
<name name="system_info" arity="1" clause_i="14"
anchor="system_info_dist" since=""/> <!-- creation -->
- <name name="system_info" arity="1" clause_i="16" since="?"/> <!-- delayed_node_table_gc -->
+ <name name="system_info" arity="1" clause_i="16" since="OTP 18.0"/> <!-- delayed_node_table_gc -->
<name name="system_info" arity="1" clause_i="20" since=""/> <!-- dist -->
- <name name="system_info" arity="1" clause_i="21" since="?"/> <!-- dist_buf_busy_limit -->
+ <name name="system_info" arity="1" clause_i="21" since="OTP R14B01"/> <!-- dist_buf_busy_limit -->
<name name="system_info" arity="1" clause_i="22" since=""/> <!-- dist_ctrl -->
<fsummary>Information about erlang distribution.</fsummary>
<desc>
@@ -8866,7 +8866,7 @@ Metadata = #{ pid => pid(),
<!-- <name name="system_info" arity="1" clause_i="6"/> atom_count -->
<!-- <name name="system_info" arity="1" clause_i="7"/> atom_limit -->
<name name="system_info" arity="1" clause_i="8"
- anchor="system_info_misc" since="?"/> <!-- build_type -->
+ anchor="system_info_misc" since="OTP R14B"/> <!-- build_type -->
<name name="system_info" arity="1" clause_i="9" since=""/> <!-- c_compiler_used -->
<name name="system_info" arity="1" clause_i="10" since=""/> <!-- check_io -->
<name name="system_info" arity="1" clause_i="11" since=""/> <!-- compat_rel -->
@@ -8882,8 +8882,8 @@ Metadata = #{ pid => pid(),
<!-- <name name="system_info" arity="1" clause_i="21"/> dist_buf_busy_limit -->
<!-- <name name="system_info" arity="1" clause_i="22"/> dist_ctrl -->
<name name="system_info" arity="1" clause_i="23" since=""/> <!-- driver_version -->
- <name name="system_info" arity="1" clause_i="24" since="?"/> <!-- dynamic_trace -->
- <name name="system_info" arity="1" clause_i="25" since="?"/> <!-- dynamic_trace_probes -->
+ <name name="system_info" arity="1" clause_i="24" since="OTP R15B01"/> <!-- dynamic_trace -->
+ <name name="system_info" arity="1" clause_i="25" since="OTP R15B01"/> <!-- dynamic_trace_probes -->
<!-- <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 -->
@@ -8905,12 +8905,12 @@ Metadata = #{ pid => pid(),
<name name="system_info" arity="1" clause_i="44" since=""/> <!-- 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" since="?"/> <!-- nif_version -->
+ <name name="system_info" arity="1" clause_i="47" since="OTP 17.4"/> <!-- 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" since=""/> <!-- 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" since="?"/> <!-- port_parallelism -->
+ <name name="system_info" arity="1" clause_i="52" since="OTP R16B"/> <!-- 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 -->
@@ -10537,7 +10537,7 @@ timestamp() ->
</func>
<func>
- <name name="trace_pattern" arity="3" clause_i="1" since="?"/>
+ <name name="trace_pattern" arity="3" clause_i="1" since="OTP 19.0"/>
<fsummary>Set trace pattern for message sending.</fsummary>
<type name="trace_match_spec"/>
<type name="match_variable"/>
@@ -10608,7 +10608,7 @@ timestamp() ->
</func>
<func>
- <name name="trace_pattern" arity="3" clause_i="2" since="?"/>
+ <name name="trace_pattern" arity="3" clause_i="2" since="OTP 19.0"/>
<fsummary>Set trace pattern for tracing of message receiving.</fsummary>
<type name="trace_match_spec"/>
<type name="match_variable"/>
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 537d8a9821..82e4e898e5 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -31,6 +31,28 @@
</header>
<p>This document describes the changes made to the ERTS application.</p>
+<section><title>Erts 10.2.2</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fixed a crash when dangling files were closed after
+ <c>init:restart/0</c>.</p>
+ <p>
+ Own Id: OTP-15495 Aux Id: ERL-821 </p>
+ </item>
+ <item>
+ <p>
+ A bug that could cause dirty schedulers to become
+ unresponsive has been fixed.</p>
+ <p>
+ Own Id: OTP-15509 Aux Id: PR-2027, PR-2093 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 10.2.1</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -1625,6 +1647,22 @@
</section>
+<section><title>Erts 9.3.3.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ A bug that could cause dirty schedulers to become
+ unresponsive has been fixed.</p>
+ <p>
+ Own Id: OTP-15509 Aux Id: PR-2027, PR-2093 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 9.3.3.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
@@ -3220,6 +3258,43 @@
</section>
+<section><title>Erts 8.3.5.7</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ Fixed bug in operator <c>band</c> of two negative
+ operands causing erroneous result if the absolute value
+ of one of the operands have the lowest <c>N*W</c> bits as
+ zero and the other absolute value is not larger than
+ <c>N*W</c> bits. <c>N</c> is an integer of 1 or larger
+ and <c>W</c> is 32 or 64 depending on word size.</p>
+ <p>
+ Own Id: OTP-15487 Aux Id: ERL-804 </p>
+ </item>
+ </list>
+ </section>
+
+
+ <section><title>Improvements and New Features</title>
+ <list>
+ <item>
+ <p>Added an optional <c>./configure</c> flag to compile
+ the emulator with spectre mitigation:
+ <c>--with-spectre-mitigation</c></p>
+ <p>Note that this requires a recent version of GCC with
+ support for spectre mitigation and the
+ <c>--mindirect-branch=thunk</c> flag, such as
+ <c>8.1</c>.</p>
+ <p>
+ Own Id: OTP-15430 Aux Id: ERIERL-237 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 8.3.5.6</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index b13c6c90c6..000397e790 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -2886,13 +2886,13 @@ BIF_RETTYPE integer_to_list_1(BIF_ALIST_1)
BIF_RETTYPE integer_to_list_2(BIF_ALIST_2)
{
Eterm res;
- int base;
+ SWord base;
- if (is_not_integer(BIF_ARG_1) || is_not_integer(BIF_ARG_2)) {
+ if (is_not_integer(BIF_ARG_1) || is_not_small(BIF_ARG_2)) {
BIF_ERROR(BIF_P, BADARG);
}
- base = unsigned_val(BIF_ARG_2);
+ base = signed_val(BIF_ARG_2);
if (base < 2 || base > 36) {
BIF_ERROR(BIF_P, BADARG);
}
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index 5f090e89d7..a18228b84a 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -390,13 +390,13 @@ BIF_RETTYPE integer_to_binary_1(BIF_ALIST_1)
BIF_RETTYPE integer_to_binary_2(BIF_ALIST_2)
{
Eterm res;
- int base;
+ SWord base;
- if (is_not_integer(BIF_ARG_1) || is_not_integer(BIF_ARG_2)) {
+ if (is_not_integer(BIF_ARG_1) || is_not_small(BIF_ARG_2)) {
BIF_ERROR(BIF_P, BADARG);
}
- base = unsigned_val(BIF_ARG_2);
+ base = signed_val(BIF_ARG_2);
if (base < 2 || base > 36) {
BIF_ERROR(BIF_P, BADARG);
}
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 9ff52c92b8..92009c2345 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -82,7 +82,7 @@ process_info(fmtfn_t to, void *to_arg)
* they are most likely just created and has invalid data
*/
if (!ERTS_PROC_IS_EXITING(p) && p->heap != NULL)
- print_process_info(to, to_arg, p);
+ print_process_info(to, to_arg, p, 0);
}
}
@@ -101,7 +101,7 @@ process_killer(void)
rp = erts_pix2proc(i);
if (rp && rp->i != ENULL) {
int br;
- print_process_info(ERTS_PRINT_STDOUT, NULL, rp);
+ print_process_info(ERTS_PRINT_STDOUT, NULL, rp, 0);
erts_printf("(k)ill (n)ext (r)eturn:\n");
while(1) {
if ((j = sys_get_key(0)) <= 0)
@@ -199,13 +199,14 @@ static void doit_print_monitor(ErtsMonitor *mon, void *vpcontext)
/* Display info about an individual Erlang process */
void
-print_process_info(fmtfn_t to, void *to_arg, Process *p)
+print_process_info(fmtfn_t to, void *to_arg, Process *p, ErtsProcLocks orig_locks)
{
int garbing = 0;
int running = 0;
Sint len;
struct saved_calls *scb;
erts_aint32_t state;
+ ErtsProcLocks locks = orig_locks;
/* display the PID */
erts_print(to, to_arg, "=proc:%T\n", p->common.id);
@@ -222,6 +223,22 @@ print_process_info(fmtfn_t to, void *to_arg, Process *p)
| ERTS_PSFLG_DIRTY_RUNNING))
running = 1;
+ if (!(locks & ERTS_PROC_LOCK_MAIN)) {
+ locks |= ERTS_PROC_LOCK_MAIN;
+ if (ERTS_IS_CRASH_DUMPING && running) {
+ if (erts_proc_trylock(p, locks)) {
+ /* crash dumping and main lock taken, this probably means that
+ the process is doing a GC on a dirty-scheduler... so we cannot
+ do erts_proc_sig_fetch as that would potentially cause a segfault */
+ locks = 0;
+ }
+ } else {
+ erts_proc_lock(p, locks);
+ }
+ } else {
+ ERTS_ASSERT(locks == ERTS_PROC_LOCK_MAIN && "Only main lock should be held");
+ }
+
/*
* If the process is registered as a global process, display the
* registered name
@@ -251,13 +268,19 @@ print_process_info(fmtfn_t to, void *to_arg, Process *p)
erts_print(to, to_arg, "Spawned by: %T\n", p->parent);
- erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ);
- len = erts_proc_sig_fetch(p);
- erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ);
+ if (locks & ERTS_PROC_LOCK_MAIN) {
+ erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ);
+ len = erts_proc_sig_fetch(p);
+ erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ);
+ } else {
+ len = p->sig_qs.len;
+ }
erts_print(to, to_arg, "Message queue length: %d\n", len);
- /* display the message queue only if there is anything in it */
- if (!ERTS_IS_CRASH_DUMPING && p->sig_qs.first != NULL && !garbing) {
+ /* display the message queue only if there is anything in it
+ and we can do it safely */
+ if (!ERTS_IS_CRASH_DUMPING && p->sig_qs.first != NULL && !garbing
+ && (locks & ERTS_PROC_LOCK_MAIN)) {
erts_print(to, to_arg, "Message queue: [");
ERTS_FOREACH_SIG_PRIVQS(
p, mp,
@@ -357,6 +380,8 @@ print_process_info(fmtfn_t to, void *to_arg, Process *p)
/* Display all states */
erts_print(to, to_arg, "Internal State: ");
erts_dump_extended_process_state(to, to_arg, state);
+
+ erts_proc_unlock(p, locks & ~orig_locks);
}
static void
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 9cc95a5c09..6137edef1b 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -4610,6 +4610,7 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2)
}
}
else if (ERTS_IS_ATOM_STR("broken_halt", BIF_ARG_1)) {
+ erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
broken_halt_test(BIF_ARG_2);
}
else if (ERTS_IS_ATOM_STR("unique_monotonic_integer_state", BIF_ARG_1)) {
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index f1d47326b4..e2c029c244 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -2470,7 +2470,7 @@ restart:
case matchProcessDump: {
erts_dsprintf_buf_t *dsbufp = erts_create_tmp_dsbuf(0);
ASSERT(c_p == self);
- print_process_info(ERTS_PRINT_DSBUF, (void *) dsbufp, c_p);
+ print_process_info(ERTS_PRINT_DSBUF, (void *) dsbufp, c_p, ERTS_PROC_LOCK_MAIN);
*esp++ = new_binary(build_proc, (byte *)dsbufp->str,
dsbufp->str_len);
erts_destroy_tmp_dsbuf(dsbufp);
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 2427d87f66..dca502c939 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -92,10 +92,6 @@
#undef HARDDEBUG
#endif
-#ifdef HARDDEBUG
-#define HARDDEBUG_RUNQS
-#endif
-
#ifdef HIPE
#include "hipe_mode_switch.h" /* for hipe_init_process() */
#include "hipe_signal.h" /* for hipe_thread_signal_init() */
@@ -344,6 +340,7 @@ erts_sched_stat_t erts_sched_stat;
static erts_tsd_key_t ERTS_WRITE_UNLIKELY(sched_data_key);
#if ERTS_POLL_USE_SCHEDULER_POLLING
+static erts_atomic32_t function_calls;
static erts_atomic32_t doing_sys_schedule;
#endif
static erts_atomic32_t no_empty_run_queues;
@@ -3251,6 +3248,7 @@ poll_thread(void *arg)
static ERTS_INLINE void
clear_sys_scheduling(void)
{
+ erts_atomic32_set_relb(&function_calls, 0);
erts_atomic32_set_mb(&doing_sys_schedule, 0);
}
@@ -3273,31 +3271,49 @@ prepare_for_sys_schedule(void)
return 0;
}
-static void
-check_io_timer(void *null)
+#else
+#define clear_sys_scheduling()
+#define prepare_for_sys_schedule() 0
+#endif
+
+#ifdef HARDDEBUG
+#define ERTS_HDBG_CHK_SLEEP_LIST(SL, L, F, FN) \
+ check_sleepers_list((SL), (L), (F), (FN))
+static void check_sleepers_list(ErtsSchedulerSleepList *sl,
+ int lock,
+ ErtsSchedulerSleepInfo *find,
+ ErtsSchedulerSleepInfo *find_not)
{
- ErtsSchedulerData *esdp = erts_get_scheduler_data();
- if (prepare_for_sys_schedule()) {
- erts_check_io(esdp->ssi->psi, ERTS_POLL_NO_TIMEOUT);
- clear_sys_scheduling();
- }
+ ErtsSchedulerSleepInfo *last_out;
+ int found = 0;
- /* The timer is cleared if this schedulers run-queue became empty
- or if the CHECKIO flag was cleared. The CHECKIO flags is cleared
- when a check_balance assigns another scheduler to be the poller in
- the overload scenario. */
- if ((ERTS_RUNQ_FLGS_GET_NOB(esdp->run_queue) & (ERTS_RUNQ_FLG_OUT_OF_WORK|ERTS_RUNQ_FLG_CHECKIO))
- == ERTS_RUNQ_FLG_CHECKIO) {
- erts_start_timer_callback(ERTS_POLL_SCHEDULER_POLLING_TIMEOUT,
- check_io_timer, NULL);
- } else {
- ERTS_RUNQ_FLGS_UNSET(esdp->run_queue, ERTS_RUNQ_FLG_CHECKIO);
- }
-}
+ if (lock)
+ erts_spin_lock(&sl->lock);
+ ERTS_ASSERT(!find_not || (!find_not->next && !find_not->prev));
+
+ last_out = sl->list;
+ if (last_out) {
+ ErtsSchedulerSleepInfo *tmp = last_out;
+ do {
+ ERTS_ASSERT(tmp->next);
+ ERTS_ASSERT(tmp->prev);
+ ERTS_ASSERT(tmp->next->prev == tmp);
+ ERTS_ASSERT(tmp->prev->next == tmp);
+ ERTS_ASSERT(tmp != find_not);
+ if (tmp == find)
+ found = !0;
+ tmp = tmp->next;
+
+ } while (tmp != last_out);
+ }
+ ERTS_ASSERT(!find || found);
+
+ if (lock)
+ erts_spin_unlock(&sl->lock);
+}
#else
-#define clear_sys_scheduling()
-#define prepare_for_sys_schedule() 0
+#define ERTS_HDBG_CHK_SLEEP_LIST(SL, L, F, FN) ((void) 0)
#endif
static void
@@ -3313,23 +3329,29 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
ERTS_LC_ASSERT(erts_lc_runq_is_locked(rq));
- if (ERTS_RUNQ_IX_IS_DIRTY(rq->ix))
- erts_spin_lock(&rq->sleepers.lock);
flgs = sched_prep_spin_wait(ssi);
if (flgs & ERTS_SSI_FLG_SUSPENDED) {
/* Go suspend instead... */
- if (ERTS_RUNQ_IX_IS_DIRTY(rq->ix))
- erts_spin_unlock(&rq->sleepers.lock);
return;
}
if (ERTS_RUNQ_IX_IS_DIRTY(rq->ix)) {
- ssi->prev = NULL;
- ssi->next = rq->sleepers.list;
- if (rq->sleepers.list)
- rq->sleepers.list->prev = ssi;
- rq->sleepers.list = ssi;
- erts_spin_unlock(&rq->sleepers.lock);
+ erts_spin_lock(&rq->sleepers.lock);
+ ERTS_HDBG_CHK_SLEEP_LIST(&rq->sleepers, 0, NULL, ssi);
+ ASSERT(!ssi->next); /* Not in sleepers list */
+ ASSERT(!ssi->prev);
+ if (!rq->sleepers.list) {
+ ssi->next = ssi->prev = ssi;
+ rq->sleepers.list = ssi;
+ }
+ else {
+ ssi->prev = rq->sleepers.list;
+ ssi->next = rq->sleepers.list->next;
+ ssi->prev->next = ssi;
+ ssi->next->prev = ssi;
+ }
+ ERTS_HDBG_CHK_SLEEP_LIST(&rq->sleepers, 0, ssi, NULL);
+ erts_spin_unlock(&rq->sleepers.lock);
dirty_active(esdp, -1);
}
@@ -3406,6 +3428,7 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
current_time = erts_get_monotonic_time(esdp);
}
}
+ *fcalls = 0;
clear_sys_scheduling();
} else {
if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) {
@@ -3470,8 +3493,28 @@ scheduler_wait(int *fcalls, ErtsSchedulerData *esdp, ErtsRunQueue *rq)
(ERTS_SSI_FLG_SUSPENDED
| ERTS_SSI_FLG_MSB_EXEC));
- if (ERTS_SCHEDULER_IS_DIRTY(esdp))
+ if (ERTS_SCHEDULER_IS_DIRTY(esdp)) {
dirty_sched_wall_time_change(esdp, working = 1);
+ erts_spin_lock(&rq->sleepers.lock);
+ ERTS_HDBG_CHK_SLEEP_LIST(&rq->sleepers, 0, ssi->next ? ssi : NULL, NULL);
+ if (ssi->next) { /* Still in list... */
+ if (ssi->next == ssi) {
+ ASSERT(rq->sleepers.list == ssi);
+ ASSERT(ssi->prev == ssi);
+ rq->sleepers.list = NULL;
+ }
+ else {
+ ASSERT(ssi->prev != ssi);
+ if (rq->sleepers.list == ssi)
+ rq->sleepers.list = ssi->next;
+ ssi->prev->next = ssi->next;
+ ssi->next->prev = ssi->prev;
+ }
+ ssi->next = ssi->prev = NULL;
+ }
+ ERTS_HDBG_CHK_SLEEP_LIST(&rq->sleepers, 0, NULL, ssi);
+ erts_spin_unlock(&rq->sleepers.lock);
+ }
else if (!thr_prgr_active) {
erts_thr_progress_active(erts_thr_prgr_data(esdp), thr_prgr_active = 1);
sched_wall_time_change(esdp, 1);
@@ -3559,56 +3602,44 @@ wake_scheduler(ErtsRunQueue *rq)
}
static void
-wake_dirty_schedulers(ErtsRunQueue *rq, int one)
+wake_dirty_scheduler(ErtsRunQueue *rq)
{
- ErtsSchedulerSleepInfo *ssi;
+ ErtsSchedulerSleepInfo *lo_ssi, *fo_ssi;
ErtsSchedulerSleepList *sl;
ASSERT(ERTS_RUNQ_IX_IS_DIRTY(rq->ix));
sl = &rq->sleepers;
erts_spin_lock(&sl->lock);
- ssi = sl->list;
- if (!ssi) {
+ ERTS_HDBG_CHK_SLEEP_LIST(&rq->sleepers, 0, NULL, NULL);
+ lo_ssi = sl->list;
+ if (!lo_ssi) {
erts_spin_unlock(&sl->lock);
- if (one)
- wake_scheduler(rq);
- } else if (one) {
+ wake_scheduler(rq);
+ }
+ else {
erts_aint32_t flgs;
- if (ssi->prev)
- ssi->prev->next = ssi->next;
- else {
- ASSERT(sl->list == ssi);
- sl->list = ssi->next;
+ fo_ssi = lo_ssi->next;
+ ASSERT(fo_ssi->prev == lo_ssi);
+ if (fo_ssi == lo_ssi) {
+ ASSERT(lo_ssi->prev == lo_ssi);
+ sl->list = NULL;
+ }
+ else {
+ ASSERT(lo_ssi->prev != lo_ssi);
+ lo_ssi->next = fo_ssi->next;
+ fo_ssi->next->prev = fo_ssi->prev;
}
- if (ssi->next)
- ssi->next->prev = ssi->prev;
-
+ fo_ssi->next = fo_ssi->prev = NULL;
+ ERTS_HDBG_CHK_SLEEP_LIST(&rq->sleepers, 0, NULL, fo_ssi);
erts_spin_unlock(&sl->lock);
ERTS_THR_MEMORY_BARRIER;
- flgs = ssi_flags_set_wake(ssi);
- erts_sched_finish_poke(ssi, flgs);
- } else {
- sl->list = NULL;
- erts_spin_unlock(&sl->lock);
-
- ERTS_THR_MEMORY_BARRIER;
- do {
- ErtsSchedulerSleepInfo *wake_ssi = ssi;
- ssi = ssi->next;
- erts_sched_finish_poke(wake_ssi, ssi_flags_set_wake(wake_ssi));
- } while (ssi);
+ flgs = ssi_flags_set_wake(fo_ssi);
+ erts_sched_finish_poke(fo_ssi, flgs);
}
}
-static void
-wake_dirty_scheduler(ErtsRunQueue *rq)
-{
- wake_dirty_schedulers(rq, 1);
-}
-
-
#define ERTS_NO_USED_RUNQS_SHIFT 16
#define ERTS_NO_RUNQS_MASK 0xffffU
@@ -4661,15 +4692,6 @@ check_balance(ErtsRunQueue *c_rq)
if (blnc_no_rqs == 1) {
c_rq->check_balance_reds = INT_MAX;
erts_atomic32_set_nob(&balance_info.checking_balance, 0);
-#if ERTS_POLL_USE_SCHEDULER_POLLING
- c_rq->check_balance_reds = ERTS_RUNQ_CALL_CHECK_BALANCE_REDS;
- if ((ERTS_RUNQ_FLGS_GET_NOB(c_rq) & (ERTS_RUNQ_FLG_OUT_OF_WORK|ERTS_RUNQ_FLG_CHECKIO))
- == 0) {
- ERTS_RUNQ_FLGS_SET(c_rq, ERTS_RUNQ_FLG_CHECKIO);
- erts_start_timer_callback(ERTS_POLL_SCHEDULER_POLLING_TIMEOUT, check_io_timer, NULL);
- }
- ERTS_RUNQ_FLGS_UNSET(c_rq, ERTS_RUNQ_FLGS_MIGRATION_INFO);
-#endif
return;
}
@@ -5189,19 +5211,6 @@ erts_fprintf(stderr, "--------------------------------\n");
/* Publish new migration paths... */
erts_atomic_set_wb(&erts_migration_paths, (erts_aint_t) new_mpaths);
-#if ERTS_POLL_USE_SCHEDULER_POLLING
- if (full_scheds == current_active) {
- ERTS_ASSERT(full_scheds <= current_active);
- /* All active schedulers ran for full, we need to do active polling,
- so we setup a timer that does active polling */
- if (!(ERTS_RUNQ_FLGS_GET_NOB(c_rq) & ERTS_RUNQ_FLG_CHECKIO)) {
- /* Active polling is not running, start it */
- erts_start_timer_callback(ERTS_POLL_SCHEDULER_POLLING_TIMEOUT, check_io_timer, NULL);
- }
- run_queue_info[c_rq->ix].flags |= ERTS_RUNQ_FLG_CHECKIO;
- }
-#endif
-
/* Reset balance statistics in all online queues */
for (qix = 0; qix < blnc_no_rqs; qix++) {
Uint32 flags = run_queue_info[qix].flags;
@@ -5211,8 +5220,6 @@ erts_fprintf(stderr, "--------------------------------\n");
ASSERT(!(flags & ERTS_RUNQ_FLG_OUT_OF_WORK));
if (rq->waiting)
flags |= ERTS_RUNQ_FLG_OUT_OF_WORK;
- if (rq != c_rq)
- flags &= ~ERTS_RUNQ_FLG_CHECKIO;
rq->full_reds_history_sum
= run_queue_info[qix].full_reds_history_sum;
@@ -5222,7 +5229,7 @@ erts_fprintf(stderr, "--------------------------------\n");
ERTS_DBG_CHK_FULL_REDS_HISTORY(rq);
rq->out_of_work_count = 0;
- (void) ERTS_RUNQ_FLGS_READ_BSET(rq, ERTS_RUNQ_FLGS_MIGRATION_INFO|ERTS_RUNQ_FLG_CHECKIO, flags);
+ (void) ERTS_RUNQ_FLGS_READ_BSET(rq, ERTS_RUNQ_FLGS_MIGRATION_INFO, flags);
rq->max_len = erts_atomic32_read_dirty(&rq->len);
for (pix = 0; pix < ERTS_NO_PRIO_LEVELS; pix++) {
ErtsRunQueueInfo *rqi;
@@ -5873,6 +5880,7 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online, int no_poll_th
erts_alloc_permanent_cache_aligned(ERTS_ALC_T_RUNQS, size_runqs);
#if ERTS_POLL_USE_SCHEDULER_POLLING
erts_atomic32_init_nob(&doing_sys_schedule, 0);
+ erts_atomic32_init_nob(&function_calls, 0);
#endif
erts_atomic32_init_nob(&no_empty_run_queues, 0);
@@ -5988,6 +5996,8 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online, int no_poll_th
for (ix = 0; ix < no_dirty_cpu_schedulers; ix++) {
ErtsSchedulerSleepInfo *ssi = &aligned_dirty_cpu_sched_sleep_info[ix].ssi;
erts_atomic32_init_nob(&ssi->flags, 0);
+ ssi->next = NULL;
+ ssi->prev = NULL;
ssi->event = NULL; /* initialized in sched_dirty_cpu_thread_func */
erts_atomic32_init_nob(&ssi->aux_work, 0);
}
@@ -5998,6 +6008,8 @@ erts_init_scheduling(int no_schedulers, int no_schedulers_online, int no_poll_th
for (ix = 0; ix < no_dirty_io_schedulers; ix++) {
ErtsSchedulerSleepInfo *ssi = &aligned_dirty_io_sched_sleep_info[ix].ssi;
erts_atomic32_init_nob(&ssi->flags, 0);
+ ssi->next = NULL;
+ ssi->prev = NULL;
ssi->event = NULL; /* initialized in sched_dirty_io_thread_func */
erts_atomic32_init_nob(&ssi->aux_work, 0);
}
@@ -7517,7 +7529,13 @@ suspend_scheduler(ErtsSchedulerData *esdp)
return;
}
+#ifdef HARDDEBUG
+ if (sched_type != ERTS_SCHED_NORMAL)
+ ERTS_HDBG_CHK_SLEEP_LIST(&esdp->run_queue->sleepers, !0, NULL, ssi);
+#endif
+
if (erts_atomic32_read_nob(&ssi->flags) & ERTS_SSI_FLG_MSB_EXEC) {
+
ASSERT(no == 1);
if (!msb_scheduler_type_switch(sched_type, esdp, no))
return;
@@ -9217,7 +9235,7 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
Process *proxy_p = NULL;
ErtsRunQueue *rq;
int context_reds;
- int fcalls;
+ int fcalls = 0;
int actual_reds;
int reds;
Uint32 flags;
@@ -9291,6 +9309,10 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
reds = ERTS_PROC_MIN_CONTEXT_SWITCH_REDS_COST;
esdp->virtual_reds = 0;
+#if ERTS_POLL_USE_SCHEDULER_POLLING
+ fcalls = (int) erts_atomic32_add_read_acqb(&function_calls, reds);
+#endif
+
ASSERT(esdp && esdp == erts_get_scheduler_data());
rq = erts_get_runq_current(esdp);
@@ -9507,7 +9529,33 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls)
non_empty_runq(rq);
goto check_activities_to_run;
- }
+ } else if (is_normal_sched &&
+ fcalls > (2 * context_reds) &&
+ prepare_for_sys_schedule()) {
+ ErtsMonotonicTime current_time;
+ /*
+ * Schedule system-level activities.
+ */
+
+ ERTS_MSACC_PUSH_STATE_CACHED_M();
+
+ erts_runq_unlock(rq);
+
+ ERTS_MSACC_SET_STATE_CACHED_M(ERTS_MSACC_STATE_CHECK_IO);
+ LTTNG2(scheduler_poll, esdp->no, 1);
+
+ erts_check_io(esdp->ssi->psi, ERTS_POLL_NO_TIMEOUT);
+ ERTS_MSACC_POP_STATE_M();
+
+ current_time = erts_get_monotonic_time(esdp);
+ if (current_time >= erts_next_timeout_time(esdp->next_tmo_ref))
+ erts_bump_timers(esdp->timer_wheel, current_time);
+
+ erts_runq_lock(rq);
+ fcalls = 0;
+ clear_sys_scheduling();
+ goto continue_check_activities_to_run;
+ }
if (flags & ERTS_RUNQ_FLG_MISC_OP)
exec_misc_ops(rq);
diff --git a/erts/emulator/beam/erl_process.h b/erts/emulator/beam/erl_process.h
index a1b029adbe..43937f216c 100644
--- a/erts/emulator/beam/erl_process.h
+++ b/erts/emulator/beam/erl_process.h
@@ -173,8 +173,6 @@ extern int erts_dio_sched_thread_suggested_stack_size;
(((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 9))
#define ERTS_RUNQ_FLG_HALTING \
(((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 10))
-#define ERTS_RUNQ_FLG_CHECKIO \
- (((Uint32) 1) << (ERTS_RUNQ_FLG_BASE2 + 11))
#define ERTS_RUNQ_FLG_MAX (ERTS_RUNQ_FLG_BASE2 + 12)
@@ -359,7 +357,7 @@ typedef struct ErtsSchedulerSleepInfo_ ErtsSchedulerSleepInfo;
typedef struct {
erts_spinlock_t lock;
- ErtsSchedulerSleepInfo *list;
+ ErtsSchedulerSleepInfo *list; /* circular lifo list; points to last out */
} ErtsSchedulerSleepList;
struct ErtsSchedulerSleepInfo_ {
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index f1c6adeedd..36b753ca9c 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -962,7 +962,7 @@ void init_break_handler(void);
void erts_set_ignore_break(void);
void erts_replace_intr(void);
void process_info(fmtfn_t, void *);
-void print_process_info(fmtfn_t, void *, Process*);
+void print_process_info(fmtfn_t, void *, Process*, ErtsProcLocks);
void info(fmtfn_t, void *);
void loaded(fmtfn_t, void *);
void erts_print_base64(fmtfn_t to, void *to_arg, byte* src, Uint size);
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 1a6bcbb66e..a231638b50 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -4788,58 +4788,3 @@ erts_ptr_id(void *ptr)
return ptr;
}
-#ifdef DEBUG
-/*
- * Handy functions when using a debugger - don't use in the code!
- */
-
-void upp(byte *buf, size_t sz)
-{
- bin_write(ERTS_PRINT_STDERR, NULL, buf, sz);
-}
-
-void pat(Eterm atom)
-{
- upp(atom_tab(atom_val(atom))->name,
- atom_tab(atom_val(atom))->len);
-}
-
-
-void pinfo()
-{
- process_info(ERTS_PRINT_STDOUT, NULL);
-}
-
-
-void pp(p)
-Process *p;
-{
- if(p)
- print_process_info(ERTS_PRINT_STDERR, NULL, p);
-}
-
-void ppi(Eterm pid)
-{
- pp(erts_proc_lookup(pid));
-}
-
-void td(Eterm x)
-{
- erts_fprintf(stderr, "%T\n", x);
-}
-
-void
-ps(Process* p, Eterm* stop)
-{
- Eterm* sp = STACK_START(p) - 1;
-
- if (stop <= STACK_END(p)) {
- stop = STACK_END(p) + 1;
- }
-
- while(sp >= stop) {
- erts_printf("%p: %.75T\n", sp, *sp);
- sp--;
- }
-}
-#endif
diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c
index b44464d6da..ed687b8d70 100644
--- a/erts/emulator/drivers/common/inet_drv.c
+++ b/erts/emulator/drivers/common/inet_drv.c
@@ -12960,38 +12960,40 @@ make_noninheritable_handle(SOCKET s)
static void fire_multi_timers(tcp_descriptor *desc, ErlDrvPort port,
ErlDrvData data)
{
- ErlDrvTime next_timeout;
- MultiTimerData *curr = desc->mtd;
- if (!curr) {
- ASSERT(0);
- return;
+ ErlDrvTime next_timeout = 0;
+ if (!desc->mtd) {
+ ASSERT(0);
+ return;
}
#ifdef DEBUG
{
ErlDrvTime chk = erl_drv_monotonic_time(ERL_DRV_MSEC);
- ASSERT(chk >= curr->when);
+ ASSERT(chk >= desc->mtd->when);
}
#endif
do {
- MultiTimerData *save = curr;
+ MultiTimerData save = *desc->mtd;
- (*(save->timeout_function))(data,save->caller);
+ /* We first remove the timer so that the timeout_functions has
+ can call clean_multi_timers without breaking anything */
+ if (desc->mtd_cache == NULL) {
+ desc->mtd_cache = desc->mtd;
+ } else {
+ FREE(desc->mtd);
+ }
- curr = curr->next;
+ desc->mtd = save.next;
+ if (desc->mtd != NULL)
+ desc->mtd->prev = NULL;
- if (desc->mtd_cache == NULL)
- desc->mtd_cache = save;
- else
- FREE(save);
+ (*(save.timeout_function))(data,save.caller);
- if (curr == NULL) {
- desc->mtd = NULL;
+ if (desc->mtd == NULL)
return;
- }
- curr->prev = NULL;
- next_timeout = curr->when - erl_drv_monotonic_time(ERL_DRV_MSEC);
+
+ next_timeout = desc->mtd->when - erl_drv_monotonic_time(ERL_DRV_MSEC);
} while (next_timeout <= 0);
- desc->mtd = curr;
+
driver_set_timer(port, (unsigned long) next_timeout);
}
diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c
index c681fa481f..ac9a070bce 100644
--- a/erts/emulator/sys/common/erl_check_io.c
+++ b/erts/emulator/sys/common/erl_check_io.c
@@ -2262,14 +2262,14 @@ erts_check_io_info(void *proc)
#if ERTS_POLL_USE_FALLBACK
erts_poll_info_flbk(get_fallback_pollset(), &piv[0]);
- piv[0].poll_threads = 1;
+ piv[0].poll_threads = 0;
piv[0].active_fds = 0;
piv++;
#endif
#if ERTS_POLL_USE_SCHEDULER_POLLING
erts_poll_info(get_scheduler_pollset(0), &piv[0]);
- piv[0].poll_threads = 1;
+ piv[0].poll_threads = 0;
piv[0].active_fds = 0;
piv++;
#endif
diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c
index 51d50933ff..27ffba58bd 100644
--- a/erts/emulator/sys/common/erl_poll.c
+++ b/erts/emulator/sys/common/erl_poll.c
@@ -2326,6 +2326,7 @@ uint32_t epoll_events(int kp_fd, int fd)
{
/* For epoll we read the information about what is selected upon from the proc fs.*/
char fname[30];
+ char s[256];
FILE *f;
unsigned int pos, flags, mnt_id;
int line = 0;
@@ -2343,12 +2344,12 @@ uint32_t epoll_events(int kp_fd, int fd)
}
if (fscanf(f,"\nmnt_id:\t%x\n", &mnt_id));
line += 3;
- while (!feof(f)) {
+ while (fgets(s, sizeof(s) / sizeof(*s), f)) {
/* tfd: 10 events: 40000019 data: 180000000a */
int ev_fd;
uint32_t events;
uint64_t data;
- if (fscanf(f,"tfd:%d events:%x data:%llx\n", &ev_fd, &events,
+ if (sscanf(s,"tfd:%d events:%x data:%llx", &ev_fd, &events,
(unsigned long long*)&data) != 3) {
fprintf(stderr,"failed to parse file %s on line %d, errno = %d\n", fname,
line,
@@ -2392,6 +2393,7 @@ ERTS_POLL_EXPORT(erts_poll_get_selected_events)(ErtsPollSet *ps,
/* For epoll we read the information about what is selected upon from the proc fs.*/
char fname[30];
+ char s[256];
FILE *f;
unsigned int pos, flags, mnt_id;
int line = 0;
@@ -2410,12 +2412,12 @@ ERTS_POLL_EXPORT(erts_poll_get_selected_events)(ErtsPollSet *ps,
}
if (fscanf(f,"\nmnt_id:\t%x\n", &mnt_id));
line += 3;
- while (!feof(f)) {
+ while (fgets(s, sizeof(s) / sizeof(*s), f)) {
/* tfd: 10 events: 40000019 data: 180000000a */
int fd;
uint32_t events;
uint64_t data;
- if (fscanf(f,"tfd:%d events:%x data:%llx\n", &fd, &events,
+ if (sscanf(s,"tfd:%d events:%x data:%llx", &fd, &events,
(unsigned long long*)&data) != 3) {
fprintf(stderr,"failed to parse file %s on line %d, errno = %d\n",
fname, line, errno);
diff --git a/erts/emulator/sys/unix/sys_drivers.c b/erts/emulator/sys/unix/sys_drivers.c
index 816bdea9c5..2f5459bee5 100644
--- a/erts/emulator/sys/unix/sys_drivers.c
+++ b/erts/emulator/sys/unix/sys_drivers.c
@@ -998,9 +998,9 @@ static void clear_fd_data(ErtsSysFdData *fdd)
fdd->psz = 0;
}
-static void nbio_stop_fd(ErlDrvPort prt, ErtsSysFdData *fdd)
+static void nbio_stop_fd(ErlDrvPort prt, ErtsSysFdData *fdd, int use)
{
- driver_select(prt, abs(fdd->fd), ERL_DRV_USE_NO_CALLBACK|DO_READ|DO_WRITE, 0);
+ driver_select(prt, abs(fdd->fd), use ? ERL_DRV_USE_NO_CALLBACK : 0|DO_READ|DO_WRITE, 0);
clear_fd_data(fdd);
SET_BLOCKING(abs(fdd->fd));
@@ -1020,11 +1020,11 @@ static void fd_stop(ErlDrvData ev) /* Does not close the fds */
if (dd->ifd) {
sz += sizeof(ErtsSysFdData);
- nbio_stop_fd(prt, dd->ifd);
+ nbio_stop_fd(prt, dd->ifd, 1);
}
if (dd->ofd && dd->ofd != dd->ifd) {
sz += sizeof(ErtsSysFdData);
- nbio_stop_fd(prt, dd->ofd);
+ nbio_stop_fd(prt, dd->ofd, 1);
}
erts_free(ERTS_ALC_T_DRV_TAB, dd);
@@ -1070,12 +1070,12 @@ static void stop(ErlDrvData ev)
ErlDrvPort prt = dd->port_num;
if (dd->ifd) {
- nbio_stop_fd(prt, dd->ifd);
+ nbio_stop_fd(prt, dd->ifd, 0);
driver_select(prt, abs(dd->ifd->fd), ERL_DRV_USE, 0); /* close(ifd); */
}
if (dd->ofd && dd->ofd != dd->ifd) {
- nbio_stop_fd(prt, dd->ofd);
+ nbio_stop_fd(prt, dd->ofd, 0);
driver_select(prt, abs(dd->ofd->fd), ERL_DRV_USE, 0); /* close(ofd); */
}
diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl
index bd62708aa7..1d2ae4fb51 100644
--- a/erts/emulator/test/driver_SUITE.erl
+++ b/erts/emulator/test/driver_SUITE.erl
@@ -1069,14 +1069,19 @@ get_stable_check_io_info(N) ->
get_check_io_total(ChkIo) ->
ct:log("ChkIo = ~p~n",[ChkIo]),
{Fallback, Rest} = get_fallback(ChkIo),
+ OnlyPollThreads = [PS || PS <- Rest, not is_scheduler_pollset(PS)],
add_fallback_infos(Fallback,
- lists:foldl(fun(Pollset, Acc) ->
- lists:zipwith(fun(A, B) ->
- add_pollset_infos(A,B)
- end,
- Pollset, Acc)
- end,
- hd(Rest), tl(Rest))).
+ lists:foldl(
+ fun(Pollset, Acc) ->
+ lists:zipwith(fun(A, B) ->
+ add_pollset_infos(A,B)
+ end,
+ Pollset, Acc)
+ end,
+ hd(OnlyPollThreads), tl(OnlyPollThreads))).
+
+is_scheduler_pollset(Pollset) ->
+ proplists:get_value(poll_threads, Pollset) == 0.
add_pollset_infos({Tag, A}=TA , {Tag, B}=TB) ->
case tag_type(Tag) of
diff --git a/erts/emulator/test/process_SUITE.erl b/erts/emulator/test/process_SUITE.erl
index 57eb082d64..b23f77a0b2 100644
--- a/erts/emulator/test/process_SUITE.erl
+++ b/erts/emulator/test/process_SUITE.erl
@@ -2104,6 +2104,13 @@ spawn_opt_max_heap_size(_Config) ->
error_logger:add_report_handler(?MODULE, self()),
+ %% flush any prior messages in error_logger
+ Pid = spawn(fun() -> ok = nok end),
+ receive
+ {error, _, {emulator, _, [Pid|_]}} ->
+ flush()
+ end,
+
%% Test that numerical limit works
max_heap_size_test(1024, 1024, true, true),
@@ -2208,6 +2215,13 @@ receive_unexpected() ->
ok
end.
+flush() ->
+ receive
+ _M -> flush()
+ after 0 ->
+ ok
+ end.
+
%% error_logger report handler proxy
init(Pid) ->
{ok, Pid}.
diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl
index 2e0dfa42f3..f61949c75b 100644
--- a/erts/emulator/test/scheduler_SUITE.erl
+++ b/erts/emulator/test/scheduler_SUITE.erl
@@ -1450,28 +1450,26 @@ poll_threads(Config) when is_list(Config) ->
{Conc, PollType, KP} = get_ioconfig(Config),
{Sched, SchedOnln, _} = get_sstate(Config, ""),
+ [1, 1] = get_ionum(Config,"+IOt 2 +IOp 2"),
+ [1, 1, 1, 1, 1] = get_ionum(Config,"+IOt 5 +IOp 5"),
+ [1, 1] = get_ionum(Config, "+S 2 +IOPt 100 +IOPp 100"),
+
if
Conc ->
- [1, 1, 1] = get_ionum(Config,"+IOt 2 +IOp 2"),
- [1, 1, 1, 1, 1, 1] = get_ionum(Config,"+IOt 5 +IOp 5"),
- [1, 1, 1] = get_ionum(Config, "+S 2 +IOPt 100 +IOPp 100"),
- [5, 1] = get_ionum(Config,"+IOt 5 +IOp 1"),
- [3, 2, 1] = get_ionum(Config,"+IOt 5 +IOp 2"),
- [2, 2, 2, 2, 2, 1] = get_ionum(Config,"+IOt 10 +IOPp 50"),
+ [5] = get_ionum(Config,"+IOt 5 +IOp 1"),
+ [3, 2] = get_ionum(Config,"+IOt 5 +IOp 2"),
+ [2, 2, 2, 2, 2] = get_ionum(Config,"+IOt 10 +IOPp 50"),
- [2, 1] = get_ionum(Config, "+S 2 +IOPt 100"),
- [4, 1] = get_ionum(Config, "+S 4 +IOPt 100"),
- [4, 1] = get_ionum(Config, "+S 4:2 +IOPt 100"),
- [4, 4, 1] = get_ionum(Config, "+S 8 +IOPt 100 +IOPp 25"),
+ [2] = get_ionum(Config, "+S 2 +IOPt 100"),
+ [4] = get_ionum(Config, "+S 4 +IOPt 100"),
+ [4] = get_ionum(Config, "+S 4:2 +IOPt 100"),
+ [4, 4] = get_ionum(Config, "+S 8 +IOPt 100 +IOPp 25"),
fail = get_ionum(Config, "+IOt 1 +IOp 2"),
ok;
not Conc ->
- [1, 1] = get_ionum(Config,"+IOt 2 +IOp 2"),
- [1, 1, 1, 1, 1] = get_ionum(Config,"+IOt 5 +IOp 5"),
- [1, 1] = get_ionum(Config, "+S 2 +IOPt 100 +IOPp 100"),
[1, 1, 1, 1, 1] = get_ionum(Config,"+IOt 5 +IOp 1"),
[1, 1, 1, 1, 1] = get_ionum(Config,"+IOt 5 +IOp 2"),
@@ -1515,7 +1513,8 @@ get_iostate(Config, Cmd)->
erlang:system_info(check_io)
end]),
IO = [IOState || IOState <- IOStates,
- proplists:get_value(fallback, IOState) == false],
+ proplists:get_value(fallback, IOState) == false,
+ proplists:get_value(poll_threads, IOState) /= 0],
stop_node(Node),
IO;
{error,timeout} ->
diff --git a/erts/emulator/test/z_SUITE.erl b/erts/emulator/test/z_SUITE.erl
index 1c52e1a934..6549108126 100644
--- a/erts/emulator/test/z_SUITE.erl
+++ b/erts/emulator/test/z_SUITE.erl
@@ -251,7 +251,7 @@ pollset_size(Config) when is_list(Config) ->
end.
check_io_debug(Config) when is_list(Config) ->
- case lists:keysearch(name, 1, erlang:system_info(check_io)) of
+ case lists:keysearch(name, 1, hd(erlang:system_info(check_io))) of
{value, {name, erts_poll}} -> check_io_debug_test();
_ -> {skipped, "Not implemented in this emulator"}
end.
diff --git a/erts/preloaded/ebin/erl_prim_loader.beam b/erts/preloaded/ebin/erl_prim_loader.beam
index eee9ad3ca8..7cb34c2d58 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/init.beam b/erts/preloaded/ebin/init.beam
index 3feed8a31a..7d848ba790 100644
--- a/erts/preloaded/ebin/init.beam
+++ b/erts/preloaded/ebin/init.beam
Binary files differ
diff --git a/erts/preloaded/src/erl_prim_loader.erl b/erts/preloaded/src/erl_prim_loader.erl
index ae5f86e017..fefdd34292 100644
--- a/erts/preloaded/src/erl_prim_loader.erl
+++ b/erts/preloaded/src/erl_prim_loader.erl
@@ -302,7 +302,7 @@ check_file_result(Func, Target, {error,Reason}) ->
logger ! {log,error,#{label=>{?MODULE,file_error},report=>Report},
#{pid=>self(),
gl=>group_leader(),
- time=>erlang:monotonic_time(microsecond),
+ time=>erlang:system_time(microsecond),
error_logger=>#{tag=>error_report,
type=>std_error}}},
error
diff --git a/erts/preloaded/src/init.erl b/erts/preloaded/src/init.erl
index b4b8b3bf9b..bdcdf72c2f 100644
--- a/erts/preloaded/src/init.erl
+++ b/erts/preloaded/src/init.erl
@@ -485,7 +485,7 @@ do_handle_msg(Msg,State) ->
X ->
case whereis(user) of
undefined ->
- Time = erlang:monotonic_time(microsecond),
+ Time = erlang:system_time(microsecond),
catch logger ! {log, info, "init got unexpected: ~p", [X],
#{pid=>self(),
gl=>self(),
diff --git a/erts/vsn.mk b/erts/vsn.mk
index 73199cc721..c579b6364a 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
#
-VSN = 10.2.1
+VSN = 10.2.2
# Port number 4365 in 4.2
# Port number 4366 in 4.3