aboutsummaryrefslogtreecommitdiffstats
path: root/erts/doc/src
diff options
context:
space:
mode:
Diffstat (limited to 'erts/doc/src')
-rw-r--r--erts/doc/src/Makefile2
-rw-r--r--erts/doc/src/absform.xml42
-rw-r--r--erts/doc/src/alt_dist.xml736
-rw-r--r--erts/doc/src/driver_entry.xml5
-rw-r--r--erts/doc/src/erl.xml116
-rw-r--r--erts/doc/src/erl_dist_protocol.xml70
-rw-r--r--erts/doc/src/erl_driver.xml20
-rw-r--r--erts/doc/src/erl_nif.xml20
-rw-r--r--erts/doc/src/erlang.xml477
-rw-r--r--erts/doc/src/erlc.xml8
-rw-r--r--erts/doc/src/erts_alloc.xml6
-rw-r--r--erts/doc/src/notes.xml6
12 files changed, 1251 insertions, 257 deletions
diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile
index 18c5490d7b..c4f1baf89e 100644
--- a/erts/doc/src/Makefile
+++ b/erts/doc/src/Makefile
@@ -171,6 +171,8 @@ release_docs_spec: docs
"$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(ERL_TOP)/erts/example/time_compat.erl \
"$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(ERL_TOP)/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl \
+ "$(RELSYSDIR)/doc/html"
$(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)"
$(INSTALL_DIR) "$(RELEASE_PATH)/man/man3"
$(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3"
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml
index e49c8c32e9..2ada903edb 100644
--- a/erts/doc/src/absform.xml
+++ b/erts/doc/src/absform.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>2001</year><year>2017</year>
+ <year>2001</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -614,26 +614,58 @@
<item>
<p>If C is a catch clause <c>P -> B</c>,
where <c>P</c> is a pattern and <c>B</c> is a body, then
- Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],[],Rep(B)}</c>.</p>
+ Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],[],Rep(B)}</c>,
+ that is, a catch clause with an explicit exception class
+ <c>throw</c> and with or without an explicit stacktrace
+ variable <c>_</c> cannot be distinguished from a catch clause
+ without an explicit exception class and without an explicit
+ stacktrace variable.</p>
</item>
<item>
<p>If C is a catch clause <c>X : P -> B</c>,
where <c>X</c> is an atomic literal or a variable pattern,
<c>P</c> is a pattern, and <c>B</c> is a body, then
- Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],[],Rep(B)}</c>.</p>
+ Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],[],Rep(B)}</c>,
+ that is, a catch clause with an explicit exception class and
+ with an explicit stacktrace variable <c>_</c> cannot be
+ distinguished from a catch clause with an explicit exception
+ class and without an explicit stacktrace variable.</p>
+ </item>
+ <item>
+ <p>If C is a catch clause <c>X : P : S -> B</c>,
+ where <c>X</c> is an atomic literal or a variable pattern,
+ <c>P</c> is a pattern, <c>S</c> is a variable, and <c>B</c>
+ is a body, then
+ Rep(C) = <c>{clause,LINE,[Rep({X,P,S})],[],Rep(B)}</c>.</p>
</item>
<item>
<p>If C is a catch clause <c>P when Gs -> B</c>,
where <c>P</c> is a pattern, <c>Gs</c> is a guard sequence,
and <c>B</c> is a body, then
- Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}</c>.</p>
+ Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}</c>,
+ that is, a catch clause with an explicit exception class
+ <c>throw</c> and with or without an explicit stacktrace
+ variable <c>_</c> cannot be distinguished from a catch clause
+ without an explicit exception class and without an explicit
+ stacktrace variable.</p>
</item>
<item>
<p>If C is a catch clause <c>X : P when Gs -> B</c>,
where <c>X</c> is an atomic literal or a variable pattern,
<c>P</c> is a pattern, <c>Gs</c> is a guard sequence,
and <c>B</c> is a body, then
- Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}</c>.</p>
+ Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}</c>,
+ that is, a catch clause with an explicit exception class and
+ with an explicit stacktrace variable <c>_</c> cannot be
+ distinguished from a catch clause with an explicit exception
+ class and without an explicit stacktrace variable.</p>
+ </item>
+ <item>
+ <p>If C is a catch clause <c>X : P : S when Gs -> B</c>,
+ where <c>X</c> is an atomic literal or a variable pattern,
+ <c>P</c> is a pattern, <c>Gs</c> is a guard sequence,
+ <c>S</c> is a variable, and <c>B</c> is a body, then
+ Rep(C) = <c>{clause,LINE,[Rep({X,P,S})],Rep(Gs),Rep(B)}</c>.</p>
</item>
<item>
<p>If C is a function clause <c>( Ps ) -> B</c>,
diff --git a/erts/doc/src/alt_dist.xml b/erts/doc/src/alt_dist.xml
index be969a8267..d3731a5391 100644
--- a/erts/doc/src/alt_dist.xml
+++ b/erts/doc/src/alt_dist.xml
@@ -47,23 +47,30 @@
runs on. The reason the C code is not made portable, is simply
readability.</p>
- <note>
- <p>This section was written a long time ago. Most of it is still
- valid, but some things have changed since then.
- Most notably is the driver interface. Some updates have been made
- to the documentation of the driver presented here,
- but more can be done and is planned for the future.
- The reader is encouraged to read the
- <seealso marker="erl_driver"><c>erl_driver</c></seealso> and
- <seealso marker="driver_entry"><c>driver_entry</c></seealso>
- documentation also.</p>
- </note>
-
<section>
<title>Introduction</title>
<p>To implement a new carrier for the Erlang distribution, the main
steps are as follows.</p>
+ <note><p>
+ As of ERTS version 10.0 support for distribution controller
+ processes has been introduced. That is, the traffic over a
+ distribution channel can be managed by a process instead of
+ only by a port. This makes it possible to implement large
+ parts of the logic in Erlang code, and you perhaps do not
+ even need a new driver for the protocol. One example could
+ be Erlang distribution over UDP using <c>gen_udp</c> (your
+ Erlang code will of course have to take care of retranspissions,
+ etc in this example). That is, depending on what you want
+ to do you perhaps do not need to implement a driver at all
+ and can then skip the driver related sections below.
+ The <c>gen_tcp_dist</c> example described in the
+ <seealso marker="#distribution_module">Distribution
+ Module</seealso> section utilize distribution controller
+ processes and can be worth having a look at if you want to
+ use distribution controller processes.
+ </p></note>
+
<section>
<title>Writing an Erlang Driver</title>
<p>First, the protocol must be available to the Erlang machine, which
@@ -152,7 +159,712 @@
</section>
<section>
+ <marker id="distribution_module"/>
+ <title>Distribution Module</title>
+ <p>
+ The distribution module expose an API that <c>net_kernel</c> call
+ in order to manage connections to other nodes. The module name
+ should have the suffix <c>_dist</c>.
+ </p>
+ <p>
+ The module needs to create some kind of listening entity (process
+ or port) and an acceptor process that accepts incoming connections
+ using the listening entity. For each connection, the module at least
+ needs to create one connection supervisor process, which also is
+ responsible for the handshake when setting up the connection, and
+ a distribution controller (process or port) responsible for
+ transport of data over the connection. The distribution controller
+ and the connection supervisor process should be linked together
+ so both of them are cleaned up when the connection is taken down.
+ </p>
+ <p>
+ Note that there need to be exactly one distribution controller
+ per connection. A process or port can only be distribution
+ controller for one connection. The registration as distribution
+ controller cannot be undone. It will stick until the distribution
+ controller terminates. The distribution controller should not
+ ignore exit signals. It is allowed to trap exits, but it should
+ then voluntarily terminate when an exit signal is received.
+ </p>
+ <p>
+ An example implementation of a distribution module can be found
+ in
+ <url href="gen_tcp_dist.erl">$ERL_TOP/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl</url>.
+ It implements the distribution over TCP/IP using the <c>gen_tcp</c>
+ API with distribution controllers implemented by processes. This
+ instead of using port distribution controllers as the ordinary TCP/IP
+ distribution uses.
+ </p>
+
+ <section>
+ <marker id="distribution_module_exported_callback_functions"/>
+ <title>Exported Callback Functions</title>
+
+ <p>
+ The following functions are mandatory:
+ </p>
+ <taglist>
+ <tag><marker id="listen"/><c>listen(Name) -></c><br/>&nbsp;&nbsp;<c>{ok, {Listen, Address, Creation}} | {error, Error} </c></tag>
+ <item>
+ <p>
+ <c>listen/1</c> is called once in order to listen for incoming
+ connection requests. The call is made when the distribution is brought
+ up. The argument <c>Name</c> is the part of the node name before
+ the <c>@</c> sign in the full node name. It can be either an atom or a
+ string.
+ </p>
+ <p>
+ The return value consists of a <c>Listen</c> handle (which is
+ later passed to the <seealso marker="#accept"><c>accept/1</c></seealso>
+ callback), <c>Address</c> which is a <c>#net_address{}</c> record
+ with information about the address for the node (the
+ <c>#net_address{}</c> record is defined in
+ <c>kernel/include/net_address.hrl</c>), and <c>Creation</c> which
+ (currently) is an integer <c>1</c>, <c>2</c>, or <c>3</c>.
+ </p>
+ <p>
+ If <seealso marker="erts:epmd"><c>epmd</c></seealso> is to be used
+ for node discovery, you typically want to use the (unfortunately
+ undocumented) <c>erl_epmd</c> module (part of the <c>kernel</c>
+ application) in order to register the listen port with <c>epmd</c>
+ and retrieve <c>Creation</c> to use.
+ </p>
+ </item>
+
+ <tag><marker id="accept"/><c>accept(Listen) -></c><br/>&nbsp;&nbsp;<c>AcceptorPid</c></tag>
+ <item>
+ <p>
+ <c>accept/1</c> should spawn a process that accepts connections. This
+ process should preferably execute on <c>max</c> priority. The process
+ identifier of this process should be returned.
+ </p>
+ <p>
+ The <c>Listen</c> argument will be the same as the <c>Listen</c> handle
+ part of the return value of the
+ <seealso marker="#listen"><c>listen/1</c></seealso> callback above.
+ <c>accept/1</c> is called only once when the distribution protocol is
+ started.
+ </p>
+ <p>
+ The caller of this function is a representative for <c>net_kernel</c>
+ (this may or may not be the process registered as <c>net_kernel</c>)
+ and is in this document identified as <c>Kernel</c>.
+ When a connection has been accepted by the acceptor process, it needs
+ to inform <c>Kernel</c> about the accepted connection. This is done by
+ passing a message on the form:
+ </p>
+ <code type="none"><![CDATA[Kernel ! {accept, AcceptorPid, DistController, Family, Proto}]]></code>
+ <p>
+ <c>DistController</c> is either the process or port identifier
+ of the distribution controller for the connection. The
+ distribution controller should be created by the acceptor
+ processes when a new connection is accepted. Its job is to
+ dispatch traffic on the connection.
+ </p>
+ <c>Kernel</c> responds with one of the following messages:
+ <taglist>
+ <tag><c>{Kernel, controller, SupervisorPid}</c></tag>
+ <item>
+ <p>
+ The request was accepted and <c>SupervisorPid</c> is the
+ process identifier of the connection supervisor process
+ (which is created in the
+ <seealso marker="#accept_connection"><c>accept_connection/5</c></seealso>
+ callback).
+ </p>
+ </item>
+ <tag><c>{Kernel, unsupported_protocol}</c></tag>
+ <item>
+ <p>
+ The request was rejected. This is a fatal error. The acceptor
+ process should terminate.
+ </p>
+ </item>
+ </taglist>
+ <p>
+ When an accept sequence has been completed the acceptor process
+ is expected to continue accepting further requests.
+ </p>
+ </item>
+
+ <tag><marker id="accept_connection"/><c>accept_connection(AcceptorPid, DistCtrl, MyNode, Allowed, SetupTime) -></c><br/>&nbsp;&nbsp;<c>ConnectionSupervisorPid</c></tag>
+ <item>
+ <p>
+ <c>accept_connection/5</c> should spawn a process that will
+ perform the Erlang distribution handshake for the connection.
+ If the handshake successfully completes it should continue to
+ function as a connection supervisor. This process
+ should preferably execute on <c>max</c> priority.
+ </p>
+ <p>The arguments:</p>
+ <taglist>
+ <tag><c>AcceptorPid</c></tag>
+ <item>
+ <p>
+ Process identifier of the process created by the
+ <seealso marker="#accept"><c>accept/1</c></seealso>
+ callback.
+ </p>
+ </item>
+ <tag><c>DistCtrl</c></tag>
+ <item>
+ <p>The identifier of the distribution controller identifier
+ created by the acceptor process. To be passed along to
+ <c>dist_util:handshake_other_started(HsData)</c>.
+ </p>
+ </item>
+ <tag><c>MyNode</c></tag>
+ <item>
+ <p>
+ Node name of this node. To be passed along to
+ <c>dist_util:handshake_other_started(HsData)</c>.
+ </p>
+ </item>
+ <tag><c>Allowed</c></tag>
+ <item>
+ <p>
+ To be passed along to
+ <c>dist_util:handshake_other_started(HsData)</c>.
+ </p>
+ </item>
+ <tag><c>SetupTime</c></tag>
+ <item>
+ <p>
+ Time used for creating a setup timer by a
+ call to <c>dist_util:start_timer(SetupTime)</c>.
+ The timer should be passed along to
+ <c>dist_util:handshake_other_started(HsData)</c>.
+ </p>
+ </item>
+ </taglist>
+ <p>
+ The created process should provide callbacks and other
+ information needed for the handshake in a
+ <seealso marker="#hs_data_record"><c>#hs_data{}</c></seealso>
+ record and call <c>dist_util:handshake_other_started(HsData)</c>
+ with this record.
+ </p>
+ <p>
+ <c>dist_util:handshake_other_started(HsData)</c> will perform
+ the handshake and if the handshake successfully completes this
+ process will then continue in a connection supervisor loop
+ as long as the connection is up.
+ </p>
+ </item>
+
+ <tag><marker id="setup"/><c>setup(Node, Type, MyNode, LongOrShortNames, SetupTime) -></c><br/>&nbsp;&nbsp;<c>ConnectionSupervisorPid</c></tag>
+ <item>
+ <p>
+ <c>setup/5</c> should spawn a process that connects to
+ <c>Node</c>. When connection has been established it should
+ perform the Erlang distribution handshake for the connection.
+ If the handshake successfully completes it should continue to
+ function as a connection supervisor. This process
+ should preferably execute on <c>max</c> priority.
+ </p>
+ <p>The arguments:</p>
+ <taglist>
+ <tag><c>Node</c></tag>
+ <item>
+ <p>
+ Node name of remote node. To be passed along to
+ <c>dist_util:handshake_we_started(HsData)</c>.
+ </p>
+ </item>
+ <tag><c>Type</c></tag>
+ <item>
+ <p>
+ Connection type. To be passed along to
+ <c>dist_util:handshake_we_started(HsData)</c>.
+ </p>
+ </item>
+ <tag><c>MyNode</c></tag>
+ <item>
+ <p>
+ Node name of this node. To be passed along to
+ <c>dist_util:handshake_we_started(HsData)</c>.
+ </p>
+ </item>
+ <tag><c>LongOrShortNames</c></tag>
+ <item>
+ <p>
+ Either the atom <c>longnames</c> or
+ the atom <c>shortnames</c> indicating
+ whether long or short names is used.
+ </p>
+ </item>
+ <tag><c>SetupTime</c></tag>
+ <item>
+ <p>
+ Time used for creating a setup timer by a
+ call to <c>dist_util:start_timer(SetupTime)</c>.
+ The timer should be passed along to
+ <c>dist_util:handshake_we_started(HsData)</c>.
+ </p>
+ </item>
+ </taglist>
+ <p>
+ The caller of this function is a representative for <c>net_kernel</c>
+ (this may or may not be the process registered as <c>net_kernel</c>)
+ and is in this document identified as <c>Kernel</c>.
+ </p>
+ <p>
+ This function should, besides spawning the connection supervisor,
+ also create a distribution controller. The distribution
+ controller is either a process or a port which is responsible
+ for dispatching traffic.
+ </p>
+ <p>
+ The created process should provide callbacks and other
+ information needed for the handshake in a
+ <seealso marker="#hs_data_record"><c>#hs_data{}</c></seealso>
+ record and call <c>dist_util:handshake_we_started(HsData)</c>
+ with this record.
+ </p>
+ <p>
+ <c>dist_util:handshake_we_started(HsData)</c> will perform
+ the handshake and the handshake successfully completes this
+ process will then continue in a connection supervisor loop
+ as long as the connection is up.
+ </p>
+ </item>
+
+ <tag><marker id="close"/><c>close(Listen) -></c><br/>&nbsp;&nbsp;<c>void()</c></tag>
+
+ <item><p>
+ Called in order to close the <c>Listen</c> handle
+ that originally was passed from the
+ <seealso marker="#listen"><c>listen/1</c></seealso> callback.
+ </p></item>
+
+ <tag><marker id="select"/><c>select(NodeName) -></c><br/>&nbsp;&nbsp;<c>boolean()</c></tag>
+ <item>
+ <p>Return <c>true</c> if the host name part
+ of the <c>NodeName</c> is valid for use
+ with this protocol; otherwise, <c>false</c>.
+ </p>
+ </item>
+
+ </taglist>
+
+ <p>
+ There are also two optional functions that may be
+ exported:
+ </p>
+ <taglist>
+ <tag><marker id="select"/><c>setopts(Listen, Opts) -></c><br/>&nbsp;&nbsp;<c>ok | {error, Error}</c></tag>
+ <item>
+ <p>
+ The argument <c>Listen</c> is the handle originally passed
+ from the
+ <seealso marker="#listen"><c>listen/1</c></seealso> callback.
+ The argument <c>Opts</c> is a list of options to set on future
+ connections.
+ </p>
+ </item>
+
+ <tag><marker id="select"/><c>getopts(Listen, Opts) -></c><br/>&nbsp;&nbsp;<c>{ok, OptionValues} | {error, Error}</c></tag>
+ <item>
+ <p>
+ The argument <c>Listen</c> is the handle originally passed
+ from the
+ <seealso marker="#listen"><c>listen/1</c></seealso> callback.
+ The argument <c>Opts</c> is a list of options to read for future
+ connections.
+ </p>
+ </item>
+ </taglist>
+
+ </section>
+ <section>
+ <marker id="hs_data_record"/>
+ <title>The #hs_data{} Record</title>
+ <p>
+ The <c>dist_util:handshake_we_started/1</c> and
+ <c>dist_util:handshake_other_started/1</c> functions
+ takes a <c>#hs_data{}</c> record as argument. There
+ are quite a lot of fields in this record that you
+ need to set. The record is defined in
+ <c>kernel/include/dist_util.hrl</c>. Not documented
+ fields should not be set, i.e., should be left as
+ <c>undefined</c>.
+ </p>
+ <p>
+ The following <c>#hs_data{}</c> record fields need
+ to be set unless otherwise stated:</p>
+ <taglist>
+ <tag><marker id="hs_data_kernel_pid"/><c>kernel_pid</c></tag>
+ <item>
+ <p>
+ Process identifier of the <c>Kernel</c> process. That is,
+ the process that called either
+ <seealso marker="#setup"><c>setup/5</c></seealso> or
+ <seealso marker="#accept_connection"><c>accept_connection/5</c></seealso>.
+ </p>
+ </item>
+
+ <tag><marker id="hs_data_other_node"/><c>other_node</c></tag>
+ <item>
+ <p>Name of the other node. This field is only
+ mandatory when this node initiates the connection.
+ That is, when connection is set up via
+ <seealso marker="#setup"><c>setup/5</c></seealso>.
+ </p>
+ </item>
+
+ <tag><marker id="hs_data_this_node"/><c>this_node</c></tag>
+ <item>
+ <p>
+ The node name of this node.
+ </p>
+ </item>
+
+ <tag><marker id="hs_data_socket"/><c>socket</c></tag>
+ <item>
+ <p>
+ The identifier of the distribution controller.
+ </p>
+ </item>
+
+ <tag><marker id="hs_data_timer"/><c>timer</c></tag>
+ <item>
+ <p>
+ The timer created using <c>dist_util:start_timer/1</c>.
+ </p>
+ </item>
+
+ <tag><marker id="hs_data_allowed"/><c>allowed</c></tag>
+ <item>
+ <p>Information passed as <c>Allowed</c> to
+ <c>accept_connection/5</c>. This field is only
+ mandatory when the remote node initiated the
+ connection. That is, when the connection is set
+ up via
+ <seealso marker="#accept_connection"><c>accept_connection/5</c></seealso>.
+ </p>
+ </item>
+
+ <tag><marker id="hs_data_f_send"/><c>f_send</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrlr, Data) -> ok | {error, Error}]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier of
+ the distribution controller and <c>Data</c>
+ is io data to pass to the other side.
+ </p>
+ <p>Only used during handshake phase.</p>
+ </item>
+
+ <tag><marker id="hs_data_f_recv"/><c>f_recv</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrlr, Length) -> {ok, Packet} | {error, Reason}]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier of the distribution
+ controller.
+ If <c>Length</c> is <c>0</c>, all available bytes should be
+ returned. If <c>Length > 0</c>, exactly <c>Length</c> bytes
+ should be returned, or an error; possibly discarding less
+ than <c>Length</c> bytes of data when the connection is
+ closed from the other side.
+ It is used for passive receive of data from the
+ other end.
+ </p>
+ <p>Only used during handshake phase.</p>
+ </item>
+
+ <tag><marker id="hs_data_f_setopts_pre_nodeup"/><c>f_setopts_pre_nodeup</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrlr) -> ok | {error, Error}]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier of
+ the distribution controller. Called just
+ before the distribution channel is taken up
+ for normal traffic.
+ </p>
+ <p>Only used during handshake phase.</p>
+ </item>
+
+ <tag><marker id="hs_data_f_setopts_post_nodeup"/><c>f_setopts_post_nodeup</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrlr) -> ok | {error, Error}]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier of
+ the distribution controller. Called just
+ after distribution channel has been taken
+ up for normal traffic.
+ </p>
+ <p>Only used during handshake phase.</p>
+ </item>
+
+ <tag><marker id="hs_data_f_getll"/><c>f_getll</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrlr) -> ID]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier of
+ the distribution controller and <c>ID</c> is
+ the identifier of the low level entity that
+ handles the connection (often <c>DistCtrlr</c>
+ itself).
+ </p>
+ <p>Only used during handshake phase.</p>
+ </item>
+
+ <tag><marker id="hs_data_f_address"/><c>f_address</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrlr, Node) -> NetAddress]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier of
+ the distribution controller, <c>Node</c>
+ is the node name of the node on the other end,
+ and <c>NetAddress</c> is a <c>#net_address{}</c>
+ record with information about the address
+ for the <c>Node</c> on the other end of the
+ connection. The <c>#net_address{}</c> record
+ is defined in
+ <c>kernel/include/net_address.hrl</c>.
+ </p>
+ <p>Only used during handshake phase.</p>
+ </item>
+
+ <tag><marker id="hs_data_mf_tick"/><c>mf_tick</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrlr) -> void()]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier
+ of the distribution controller. This
+ function should send information over
+ the connection that is not interpreted
+ by the other end while increasing the
+ statistics of received packets on the
+ other end. This is usually implemented by
+ sending an empty packet.
+ </p>
+ <note><p>
+ It is of vital importance that this operation
+ does not block the caller for a long time.
+ This since it is called from the connection
+ supervisor.
+ </p></note>
+ <p>Used when connection is up.</p>
+ </item>
+
+ <tag><marker id="hs_data_mf_getstat"/><c>mf_getstat</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrlr) -> {ok, Received, Sent, PendSend}]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier
+ of the distribution controller, <c>Received</c>
+ is received packets, <c>Sent</c> is
+ sent packets, and <c>PendSend</c> is
+ amount of packets in queue to be sent
+ or a <c>boolean()</c> indicating whether
+ there are packets in queue to be sent.
+ </p>
+ <note><p>
+ It is of vital importance that this operation
+ does not block the caller for a long time.
+ This since it is called from the connection
+ supervisor.
+ </p></note>
+ <p>Used when connection is up.</p>
+ </item>
+
+ <tag><marker id="hs_data_request_type"/><c>request_type</c></tag>
+ <item>
+ <p>
+ The request <c>Type</c> as passed to
+ <seealso marker="#setup"><c>setup/5</c></seealso>.
+ This is only mandatory when the connection has
+ been initiated by this node. That is, the connection
+ is set up via <c>setup/5</c>.
+ </p>
+ </item>
+
+ <tag><marker id="hs_data_mf_setopts"/><c>mf_setopts</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrl, Opts) -> ok | {error, Error}]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier
+ of the distribution controller and <c>Opts</c>
+ is a list of options to set on the connection.
+ </p>
+ <p>This function is optional. Used when connection is up.</p>
+ </item>
+
+ <tag><marker id="hs_data_mf_getopts"/><c>mf_getopts</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrl, Opts) -> {ok, OptionValues} | {error, Error}]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier
+ of the distribution controller and <c>Opts</c>
+ is a list of options to read for the connection.
+ </p>
+ <p>This function is optional. Used when connection is up.</p>
+ </item>
+
+ <tag><marker id="hs_data_f_handshake_complete"/><c>f_handshake_complete</c></tag>
+ <item>
+ <p>
+ A fun with the following signature:
+ </p>
+ <code type="none"><![CDATA[fun (DistCtrlr, Node, DHandle) -> void()]]></code>
+ <p>
+ where <c>DistCtrlr</c> is the identifier
+ of the distribution controller, <c>Node</c> is
+ the node name of the node connected at the other
+ end, and <c>DHandle</c> is a distribution handle
+ needed by a distribution controller process when
+ calling the following BIFs:
+ </p>
+ <list>
+ <item><p><seealso marker="erts:erlang#dist_ctrl_get_data/1"><c>erlang:dist_ctrl_get_data/1</c></seealso></p></item>
+ <item><p><seealso marker="erts:erlang#dist_ctrl_get_data_notification/1"><c>erlang:dist_ctrl_get_data_notification/1</c></seealso></p></item>
+ <item><p><seealso marker="erts:erlang#dist_ctrl_input_handler/2"><c>erlang:dist_ctrl_input_handler/2</c></seealso></p></item>
+ <item><p><seealso marker="erts:erlang#dist_ctrl_put_data/2"><c>erlang:dist_ctrl_put_data/2</c></seealso></p></item>
+ </list>
+ <p>
+ This function is called when the handshake has
+ completed and the distribution channel is up.
+ The distribution controller can begin dispatching
+ traffic over the channel. This function is optional.
+ </p>
+ <p>Only used during handshake phase.</p>
+ </item>
+
+ <tag><marker id="hs_data_add_flags"/><c>add_flags</c></tag>
+ <item>
+ <p>
+ <seealso marker="erl_dist_protocol#dflags">Distribution flags</seealso>
+ to add to the connection. Currently all (non obsolete) flags will
+ automatically be enabled.
+ </p>
+ <p>
+ This flag field is optional.
+ </p>
+ </item>
+
+ <tag><marker id="hs_data_reject_flags"/><c>reject_flags</c></tag>
+ <item>
+ <p>
+ <seealso marker="erl_dist_protocol#dflags">Distribution flags</seealso>
+ to reject. Currently the following distribution flags can be rejected:
+ </p>
+ <taglist>
+ <tag><c>DFLAG_DIST_HDR_ATOM_CACHE</c></tag>
+ <item>Do not use atom cache over this connection.</item>
+ <tag><c>DFLAGS_STRICT_ORDER_DELIVERY</c></tag>
+ <item>Do not use any features that require strict
+ order delivery.</item>
+ </taglist>
+ <p>
+ This flag field is optional.
+ </p>
+ </item>
+
+ <tag><marker id="hs_data_require_flags"/><c>require_flags</c></tag>
+ <item>
+ <p>
+ Require these <seealso marker="erl_dist_protocol#dflags">distribution
+ flags</seealso> to be used. The connection will be aborted during the
+ handshake if the other end does not use them.
+ </p>
+ <p>
+ This flag field is optional.
+ </p>
+ </item>
+
+ </taglist>
+ </section>
+
+ <section>
+ <marker id="distribution_data_delivery"/>
+ <title>Distribution Data Delivery</title>
+ <p>
+ When using the default configuration, the data to pass
+ over a connection needs to be delivered as is
+ to the node on the receiving end in the <em>exact same
+ order</em>, with no loss of data what so ever, as sent
+ from the sending node.
+ </p>
+ <p>
+ The data delivery order can be relaxed by disabling
+ features that require strict ordering. This is done by
+ passing the <c>?DFLAGS_STRICT_ORDER_DELIVERY</c>
+ <seealso marker="erl_dist_protocol#dflags">distribution
+ flags</seealso> in the
+ <seealso marker="alt_dist#hs_data_reject_flags"><c>reject_flags</c></seealso>
+ field of the <seealso marker="#hs_data_record"><c>#hs_data{}</c></seealso>
+ record used when setting up the connection. When relaxed
+ ordering is used, only the order of signals with the same
+ sender/receiver pair has to be preserved.
+ However, note that disabling the features that require
+ strict ordering may have a negative impact on performance,
+ throughput, and/or latency.
+ </p>
+ </section>
+
+ <section>
+ <marker id="enable_your_distribution_module"/>
+ <title>Enable Your Distribution Module</title>
+
+ <p>For <c>net_kernel</c> to find out which distribution module to use,
+ the <c>erl</c> command-line argument <c>-proto_dist</c> is used. It
+ is followed by one or more distribution module names, with suffix
+ "_dist" removed. That is, <c>gen_tcp_dist</c> as a distribution module
+ is specified as <c>-proto_dist gen_tcp</c>.</p>
+
+ <p>If no <c>epmd</c> (TCP port mapper daemon) is used, also command-line
+ option <c>-no_epmd</c> is to be specified, which makes
+ Erlang skip the <c>epmd</c> startup, both as an OS process and as an
+ Erlang ditto.</p>
+ </section>
+
+ </section>
+
+ <section>
<title>The Driver</title>
+
+ <note>
+ <p>This section was written a long time ago. Most of it is still
+ valid, but some things have changed since then. Some updates have
+ been made to the documentation of the driver presented here,
+ but more can be done and is planned for the future.
+ The reader is encouraged to read the
+ <seealso marker="erl_driver"><c>erl_driver</c></seealso> and
+ <seealso marker="driver_entry"><c>driver_entry</c></seealso>
+ documentation also.</p>
+ </note>
+
<p>Although Erlang drivers in general can be beyond the scope of this
section, a brief introduction seems to be in place.</p>
diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml
index 2421e0a8d9..e8c7e26457 100644
--- a/erts/doc/src/driver_entry.xml
+++ b/erts/doc/src/driver_entry.xml
@@ -196,10 +196,7 @@ typedef struct erl_drv_entry {
char **rbuf, ErlDrvSizeT rlen, unsigned int *flags);
/* Works mostly like 'control', a synchronous
call into the driver */
- void (*event)(ErlDrvData drv_data, ErlDrvEvent event,
- ErlDrvEventData event_data);
- /* Called when an event selected by
- driver_event() has occurred */
+ void* unused_event_callback;
int extended_marker; /* ERL_DRV_EXTENDED_MARKER */
int major_version; /* ERL_DRV_EXTENDED_MAJOR_VERSION */
int minor_version; /* ERL_DRV_EXTENDED_MINOR_VERSION */
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 638e88ca31..99f0421080 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -360,11 +360,12 @@
</item>
<tag><c><![CDATA[-mode interactive | embedded]]></c></tag>
<item>
- <p>Indicates if the system is to load code dynamically
- (<c><![CDATA[interactive]]></c>), or if all code is to be loaded
- during system initialization (<c><![CDATA[embedded]]></c>); see
- <seealso marker="kernel:code"><c>code(3)</c></seealso>.
- Defaults to <c><![CDATA[interactive]]></c>.</p>
+ <p>Modules are auto loaded when they are first referenced if the
+ runtime system runs in <c><![CDATA[interactive]]></c> mode, which is
+ the default. In <c><![CDATA[embedded]]></c> mode modules are not auto
+ loaded. The latter is recommended when the boot script preloads all
+ modules, as conventionally happens in OTP releases. See
+ <seealso marker="kernel:code"><c>code(3)</c></seealso></p>.
</item>
<tag><c><![CDATA[-name Name]]></c></tag>
<item>
@@ -538,20 +539,6 @@
<p>Note that a distributed node will fail to start if epmd is
not running.</p>
</item>
- <tag><marker id="smp"/><c><![CDATA[-smp [enable|auto|disable]]]></c></tag>
- <item>
- <p><c>-smp enable</c> and <c>-smp</c> start the Erlang runtime
- system with SMP support enabled. This can fail if no runtime
- system with SMP support is available. <c>-smp auto</c> starts
- the Erlang runtime system with SMP support enabled if it is
- available and more than one logical processor is detected.
- <c>-smp disable</c> starts a runtime system without SMP support.
- The runtime system without SMP support is deprecated and will
- be removed in a future major release.</p>
- <note>
- <p>See also flag<seealso marker="#+S"><c>+S</c></seealso>.</p>
- </note>
- </item>
<tag><c><![CDATA[-version]]></c> (emulator flag)</tag>
<item>
<p>Makes the emulator print its version number. The same
@@ -776,13 +763,40 @@
<seealso marker="erlang#process_flag_message_queue_data">
<c>process_flag(message_queue_data, MQD)</c></seealso>.</p>
</item>
- <tag><c><![CDATA[+K true | false]]></c></tag>
+ <tag><marker id="+IOp"/><c>+IOp PollSets</c></tag>
<item>
- <p>Enables or disables the kernel poll functionality if supported by
- the emulator. Defaults to <c><![CDATA[false]]></c> (disabled).
- If the emulator does not support kernel poll, and flag
- <c><![CDATA[+K]]></c> is passed to the emulator, a warning is
- issued at startup.</p>
+ <p>Sets the number of IO pollsets to use when polling for I/O.
+ This option is only used on platforms that support concurrent
+ updates of a pollset, otherwise the same number of pollsets
+ are used as IO poll threads.
+ The default is 1.
+ </p>
+ </item>
+ <tag><marker id="+IOt"/><c>+IOt PollThreads</c></tag>
+ <item>
+ <p>Sets the number of IO poll threads to use when polling for I/O.
+ The maximum number of poll threads allowed is 1024. The default is 1.
+ </p>
+ <p>A good way to check if more IO poll threads are needed is to use
+ <seealso marker="runtime_tools:msacc">microstate accounting</seealso>
+ and see what the load of the IO poll thread is. If it is high it could
+ be a good idea to add more threads.</p>
+ </item>
+ <tag><marker id="+IOPp"/><c>+IOPp PollSetsPercentage</c></tag>
+ <item>
+ <p>Similar to <seealso marker="#+IOp"><c>+IOp</c></seealso> but uses
+ percentages to set the number of IO pollsets to create, based on the
+ number of poll threads configured. If both <c>+IOPp</c> and <c>+IOp</c>
+ are used, <c>+IOPp</c> is ignored.
+ </p>
+ </item>
+ <tag><marker id="+IOPt"/><c>+IOPt PollThreadsPercentage</c></tag>
+ <item>
+ <p>Similar to <seealso marker="#+IOt"><c>+IOt</c></seealso> but uses
+ percentages to set the number of IO poll threads to create, based on
+ the number of schedulers configured. If both <c>+IOPt</c> and
+ <c>+IOt</c> are used, <c>+IOPt</c> is ignored.
+ </p>
</item>
<tag><c><![CDATA[+l]]></c></tag>
<item>
@@ -902,7 +916,7 @@
<c><![CDATA[+S Schedulers:SchedulerOnline]]></c></tag>
<item>
<p>Sets the number of scheduler threads to create and scheduler threads
- to set online when SMP support has been enabled. The maximum for both
+ to set online. The maximum for both
values is 1024. If the Erlang runtime system is able to determine the
number of logical processors configured and logical processors
available, <c>Schedulers</c> defaults to logical processors
@@ -920,8 +934,6 @@
<p>Specifying value <c>0</c> for <c>Schedulers</c> or
<c>SchedulersOnline</c> resets the number of scheduler threads or
scheduler threads online, respectively, to its default value.</p>
- <p>This option is ignored if the emulator does not have SMP support
- enabled (see flag <seealso marker="#smp"><c>-smp</c></seealso>).</p>
</item>
<tag><marker id="+SP"/><c><![CDATA[+SP
SchedulersPercentage:SchedulersOnlinePercentage]]></c></tag>
@@ -929,8 +941,8 @@
<p>Similar to <seealso marker="#+S"><c>+S</c></seealso> but uses
percentages to set the number of scheduler threads to create, based
on logical processors configured, and scheduler threads to set online,
- based on logical processors available, when SMP support has been
- enabled. Specified values must be &gt; 0. For example,
+ based on logical processors available.
+ Specified values must be &gt; 0. For example,
<c>+SP 50:25</c> sets the number of scheduler threads to 50% of the
logical processors configured, and the number of scheduler threads
online to 25% of the logical processors available.
@@ -945,15 +957,13 @@
and 8 logical cores available, the combination of the options
<c>+S 4:4 +SP 50:25</c> (in either order) results in 2 scheduler
threads (50% of 4) and 1 scheduler thread online (25% of 4).</p>
- <p>This option is ignored if the emulator does not have SMP support
- enabled (see flag <seealso marker="#smp"><c>-smp</c></seealso>).</p>
</item>
<tag><marker id="+SDcpu"/><c><![CDATA[+SDcpu
DirtyCPUSchedulers:DirtyCPUSchedulersOnline]]></c></tag>
<item>
<p>Sets the number of dirty CPU scheduler threads to create and dirty
- CPU scheduler threads to set online when threading support has been
- enabled. The maximum for both values is 1024, and each value is
+ CPU scheduler threads to set online.
+ The maximum for both values is 1024, and each value is
further limited by the settings for normal schedulers:</p>
<list type="bulleted">
<item>The number of dirty CPU scheduler threads created cannot exceed
@@ -977,16 +987,14 @@
executing on ordinary schedulers. If the amount of dirty CPU
schedulers was allowed to be unlimited, dirty CPU bound jobs would
potentially starve normal jobs.</p>
- <p>This option is ignored if the emulator does not have threading
- support enabled.</p>
</item>
<tag><marker id="+SDPcpu"/><c><![CDATA[+SDPcpu
DirtyCPUSchedulersPercentage:DirtyCPUSchedulersOnlinePercentage]]></c></tag>
<item>
<p>Similar to <seealso marker="#+SDcpu"><c>+SDcpu</c></seealso> but
uses percentages to set the number of dirty CPU scheduler threads to
- create and the number of dirty CPU scheduler threads to set online
- when threading support has been enabled. Specified values must be
+ create and the number of dirty CPU scheduler threads to set online.
+ Specified values must be
&gt; 0. For example, <c>+SDPcpu 50:25</c> sets the number of dirty
CPU scheduler threads to 50% of the logical processors configured
and the number of dirty CPU scheduler threads online to 25% of the
@@ -1003,13 +1011,11 @@
the combination of the options <c>+SDcpu 4:4 +SDPcpu 50:25</c> (in
either order) results in 2 dirty CPU scheduler threads (50% of 4) and
1 dirty CPU scheduler thread online (25% of 4).</p>
- <p>This option is ignored if the emulator does not have threading
- support enabled.</p>
</item>
<tag><marker id="+SDio"/><c><![CDATA[+SDio DirtyIOSchedulers]]></c></tag>
<item>
- <p>Sets the number of dirty I/O scheduler threads to create when
- threading support has been enabled. Valid range is 0-1024. By
+ <p>Sets the number of dirty I/O scheduler threads to create.
+ Valid range is 0-1024. By
default, the number of dirty I/O scheduler threads created is 10,
same as the default number of threads in the <seealso
marker="#async_thread_pool_size">async thread pool</seealso>.</p>
@@ -1019,8 +1025,6 @@
expected to execute on dirty I/O schedulers. If the user should schedule CPU
bound jobs on dirty I/O schedulers, these jobs might starve ordinary
jobs executing on ordinary schedulers.</p>
- <p>This option is ignored if the emulator does not have threading
- support enabled.</p>
</item>
<tag><c><![CDATA[+sFlag Value]]></c></tag>
<item>
@@ -1297,25 +1301,6 @@
<seealso marker="erlang#system_info_cpu_topology">
<c>erlang:system_info(cpu_topology)</c></seealso>.</p>
</item>
- <tag><marker id="+secio"/><c>+secio true|false</c></tag>
- <item>
- <p>Enables or disables eager check I/O scheduling. Defaults
- to <c>true</c>. The default was changed from <c>false</c>
- as from ERTS 7.0. The behavior before this
- flag was introduced corresponds to <c>+secio false</c>.</p>
- <p>The flag effects when schedulers will check for I/O
- operations possible to execute, and when such I/O operations
- will execute. As the parameter name implies,
- schedulers are more eager to check for I/O when
- <c>true</c> is passed. This, however, also implies that
- execution of outstanding I/O operation is not
- prioritized to the same extent as when <c>false</c> is
- passed.</p>
- <p><seealso marker="erlang#system_info_eager_check_io">
- <c>erlang:system_info(eager_check_io)</c></seealso>
- returns the value of this parameter used when starting
- the virtual machine.</p>
- </item>
<tag><marker id="+sfwi"/><c>+sfwi Interval</c></tag>
<item>
<p>Sets scheduler-forced wakeup interval. All run queues are
@@ -1657,9 +1642,7 @@
<tag>The <c>.erlang</c> startup file</tag>
<item>
<p>When Erlang/OTP is started, the system searches for a file named
- <c>.erlang</c> in the directory where Erlang/OTP is started. If not
- found, the user's home directory is searched for an <c>.erlang</c>
- file.</p>
+ <c>.erlang</c> in the user's home directory.</p>
<p>If an <c>.erlang</c> file is found, it is assumed to contain valid
Erlang expressions. These expressions are evaluated as if they were
input to the shell.</p>
@@ -1711,4 +1694,3 @@ code:load_abs("..../user_default"). ]]></code>
<seealso marker="tools:make"><c>make(3)</c></seealso></p>
</section>
</comref>
-
diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml
index 610351db6c..a78b13aaa4 100644
--- a/erts/doc/src/erl_dist_protocol.xml
+++ b/erts/doc/src/erl_dist_protocol.xml
@@ -829,7 +829,31 @@ DiB == gen_digest(ChA, ICA)?
<item>
<p>The node understand UTF-8 encoded atoms.</p>
</item>
+ <tag><c>-define(DFLAG_MAP_TAG, 16#20000).</c></tag>
+ <item>
+ <p>The node understand the map tag.</p>
+ </item>
+ <tag><c>-define(DFLAG_BIG_CREATION, 16#40000).</c></tag>
+ <item>
+ <p>The node understand big node creation.</p>
+ </item>
+ <tag><c>-define(DFLAG_SEND_SENDER, 16#80000).</c></tag>
+ <item>
+ <p>
+ Use the <c>SEND_SENDER</c>
+ <seealso marker="#control_message">control message</seealso>
+ instead of the <c>SEND</c> control message and use the
+ <c>SEND_SENDER_TT</c> control message instead
+ of the <c>SEND_TT</c> control message.
+ </p>
+ </item>
</taglist>
+ <p>
+ There are also a collection of <c>DFLAG</c>s bitwise or:ed
+ together in the <c>DFLAGS_STRICT_ORDER_DELIVERY</c> macro.
+ These flags corresponds to features that require strict
+ ordering of data over distribution channels.
+ </p>
</section>
</section>
@@ -922,6 +946,7 @@ DiB == gen_digest(ChA, ICA)?
</item>
</taglist>
+ <marker id="control_message"/>
<p>The <c>ControlMessage</c> is a tuple, where the first element indicates
which distributed operation it encodes:</p>
@@ -1028,4 +1053,49 @@ DiB == gen_digest(ChA, ICA)?
</item>
</taglist>
</section>
+
+ <section>
+ <title>New Ctrlmessages for Erlang/OTP 21</title>
+ <taglist>
+ <tag><c>SEND_SENDER</c></tag>
+ <item>
+ <p><c>{22, FromPid, ToPid}</c></p>
+ <p>Followed by <c>Message</c>.</p>
+ <p>
+ This control messages replace the <c>SEND</c> control
+ message and will be sent when the distribution flag
+ <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_SEND_SENDER</c></seealso>
+ has been negotiated in the connection setup handshake.
+ </p>
+ <note><p>
+ Messages encoded before the connection has
+ been set up may still use the <c>SEND</c> control
+ message. However, once a <c>SEND_SENDER</c> or <c>SEND_SENDER_TT</c>
+ control message has been sent, no more <c>SEND</c>
+ control messages will be sent in the same direction
+ on the connection.
+ </p></note>
+ </item>
+ <tag><c>SEND_SENDER_TT</c></tag>
+ <item>
+ <p><c>{23, FromPid, ToPid, TraceToken}</c></p>
+ <p>Followed by <c>Message</c>.</p>
+ <p>
+ This control messages replace the <c>SEND_TT</c> control
+ message and will be sent when the distribution flag
+ <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_SEND_SENDER</c></seealso>
+ has been negotiated in the connection setup handshake.
+ </p>
+ <note><p>
+ Messages encoded before the connection has
+ been set up may still use the <c>SEND_TT</c> control
+ message. However, once a <c>SEND_SENDER</c> or <c>SEND_SENDER_TT</c>
+ control message has been sent, no more <c>SEND_TT</c>
+ control messages will be sent in the same direction
+ on the connection.
+ </p></note>
+ </item>
+ </taglist>
+ </section>
+
</chapter>
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index 5705100ab2..c790872fe4 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -157,7 +157,7 @@
</note>
<p>Most functions in this API are <em>not</em> thread-safe, that is,
- they <em>cannot</em> be called from any thread. Functions
+ they <em>cannot</em> be called from arbitrary threads. Functions
that are not documented as thread-safe can only be called from
driver callbacks or function calls descending from a driver
callback call. Notice that driver callbacks can be called from
@@ -2304,8 +2304,13 @@ r = driver_async(myPort, &myKey, myData, myFunc); ]]></code>
buffer is too small, a value &gt; <c>0</c> is returned and
<c>*value_size</c> has been set to the buffer size needed.</p>
<warning>
- <p>Do <em>not</em> use libc's <c>getenv</c> or similar C library
- interfaces from a driver.</p>
+ <p>This function reads the emulated environment used by
+ <seealso marker="os:getenv/1"><c>os:getenv/1</c></seealso> and not
+ the environment used by libc's <c>getenv(3)</c> or similar. Drivers
+ that <em>require</em> that these are in sync will need to do so
+ themselves, but keep in mind that they are segregated for a reason;
+ <c>getenv(3)</c> and its friends are <em>not thread-safe</em> and
+ may cause unrelated code to misbehave or crash the emulator.</p>
</warning>
<p>This function is thread-safe.</p>
</desc>
@@ -2650,8 +2655,13 @@ erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0]
environment variable is removed.</p>
</note>
<warning>
- <p>Do <em>not</em> use libc's <c>putenv</c> or similar C library
- interfaces from a driver.</p>
+ <p>This function modifies the emulated environment used by
+ <seealso marker="os:putenv/2"><c>os:putenv/2</c></seealso> and not
+ the environment used by libc's <c>putenv(3)</c> or similar. Drivers
+ that <em>require</em> that these are in sync will need to do so
+ themselves, but keep in mind that they are segregated for a reason;
+ <c>putenv(3)</c> and its friends are <em>not thread-safe</em> and
+ may cause unrelated code to misbehave or crash the emulator.</p>
</warning>
<p>This function is thread-safe.</p>
</desc>
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index ef3cdb89e9..23f0c66429 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -367,6 +367,8 @@ return term;</code>
<c>enif_ioq_deq()</c></seealso></item>
<item><seealso marker="#enif_ioq_peek">
<c>enif_ioq_peek()</c></seealso></item>
+ <item><seealso marker="#enif_ioq_peek_head">
+ <c>enif_ioq_peek_head()</c></seealso></item>
<item><seealso marker="#enif_inspect_iovec">
<c>enif_inspect_iovec()</c></seealso></item>
<item><seealso marker="#enif_free_iovec">
@@ -1683,8 +1685,7 @@ enif_inspect_iovec(env, max_elements, term, &amp;tail, &amp;iovec);
<fsummary>Peek inside the IO Queue</fsummary>
<desc>
<p>Get the I/O queue as a pointer to an array of <c>SysIOVec</c>s.
- It also returns the number of elements in <c>iovlen</c>.
- This is the only way to get data out of the queue.</p>
+ It also returns the number of elements in <c>iovlen</c>.</p>
<p>Nothing is removed from the queue by this function, that must be done
with <seealso marker="#enif_ioq_deq"><c>enif_ioq_deq</c></seealso>.</p>
<p>The returned array is suitable to use with the Unix system
@@ -1693,6 +1694,21 @@ enif_inspect_iovec(env, max_elements, term, &amp;tail, &amp;iovec);
</func>
<func>
+ <name><ret>int</ret>
+ <nametext>enif_ioq_peek_head(ErlNifEnv *env, ErlNifIOQueue *q, size_t *size, ERL_NIF_TERM *bin_term)</nametext></name>
+ <fsummary>Peek the head of the IO Queue.</fsummary>
+ <desc>
+ <p>Get the head of the IO Queue as a binary term.</p>
+ <p>If <c>size</c> is not <c>NULL</c>, the size of the head is placed
+ there.</p>
+ <p>Nothing is removed from the queue by this function, that must be done
+ with <seealso marker="#enif_ioq_deq"><c>enif_ioq_deq</c></seealso>.</p>
+ <p>Returns <c>true</c> on success, or <c>false</c> if the queue is
+ empty.</p>
+ </desc>
+ </func>
+
+ <func>
<name><ret>size_t</ret>
<nametext>enif_ioq_size(ErlNifIOQueue *q)</nametext></name>
<fsummary>Get the current size of the IO Queue</fsummary>
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 3ed0f59b7d..771897ba94 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -189,6 +189,14 @@
</taglist>
</desc>
</datatype>
+
+ <datatype>
+ <name name="dist_handle"></name>
+ <desc>
+ <p>An opaque handle identifing a distribution channel.</p>
+ </desc>
+ </datatype>
+
</datatypes>
<funcs>
@@ -549,9 +557,7 @@ hello
<name name="binary_to_term" arity="2"/>
<fsummary>Decode an Erlang external term format binary.</fsummary>
<desc>
- <p>As <c>binary_to_term/1</c>, but takes options that affect decoding
- of the binary.</p>
- <p>Option:</p>
+ <p>As <c>binary_to_term/1</c>, but takes these options:</p>
<taglist>
<tag><c>safe</c></tag>
<item>
@@ -567,18 +573,31 @@ hello
creation of new external function references.
None of those resources are garbage collected, so unchecked
creation of them can exhaust available memory.</p>
- </item>
- </taglist>
- <p>Failure: <c>badarg</c> if <c>safe</c> is specified and unsafe
- data is decoded.</p>
<pre>
-> <input>binary_to_term(&lt;&lt;131,100,0,5,104,101,108,108,111>>, [safe]).</input>
+> <input>binary_to_term(&lt;&lt;131,100,0,5,"hello">>, [safe]).</input>
** exception error: bad argument
> <input>hello.</input>
hello
-> <input>binary_to_term(&lt;&lt;131,100,0,5,104,101,108,108,111>>, [safe]).</input>
+> <input>binary_to_term(&lt;&lt;131,100,0,5,"hello">>, [safe]).</input>
hello
</pre>
+ </item>
+ <tag><c>used</c></tag>
+ <item>
+ <p>Changes the return value to <c>{Term, Used}</c> where <c>Used</c>
+ is the number of bytes actually read from <c>Binary</c>.</p>
+ <pre>
+> <input>Input = &lt;&lt;131,100,0,5,"hello","world">>.</input>
+&lt;&lt;131,100,0,5,104,101,108,108,111,119,111,114,108,100>>
+> <input>{Term, Used} = binary_to_term(Input, [used]).</input>
+{hello, 9}
+> <input>split_binary(Input, Used).</input>
+{&lt;&lt;131,100,0,5,104,101,108,108,111>>, &lt;&lt;"world">>}
+</pre>
+ </item>
+ </taglist>
+ <p>Failure: <c>badarg</c> if <c>safe</c> is specified and unsafe
+ data is decoded.</p>
<p>See also
<seealso marker="#term_to_binary/1"><c>term_to_binary/1</c></seealso>,
<seealso marker="#binary_to_term/1">
@@ -1233,6 +1252,141 @@ end</code>
</func>
<func>
+ <name name="dist_ctrl_get_data" arity="1"/>
+ <fsummary>Get distribution channel data to pass to another node.</fsummary>
+ <desc>
+ <p>
+ Get distribution channel data from the local node that is
+ to be passed to the remote node. The distribution channel
+ is identified by <c><anno>DHandle</anno></c>. If no data
+ is available, the atom <c>none</c> is returned. One
+ can request to be informed by a message when more
+ data is available by calling
+ <seealso marker="erlang#dist_ctrl_get_data_notification/1"><c>erlang:dist_ctrl_get_data_notification(DHandle)</c></seealso>.
+ </p>
+ <note><p>
+ Only the process registered as distribution
+ controller for the distribution channel identified by
+ <c><anno>DHandle</anno></c> is allowed to call this
+ function.
+ </p></note>
+ <p>
+ This function is used when implementing an alternative
+ distribution carrier using processes as distribution
+ controllers. <c><anno>DHandle</anno></c> is retrived
+ via the callback
+ <seealso marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seealso>.
+ More information can be found in the documentation of
+ <seealso marker="erts:alt_dist#distribution_module">ERTS
+ User's Guide ➜ How to implement an Alternative Carrier
+ for the Erlang Distribution ➜ Distribution Module</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="dist_ctrl_get_data_notification" arity="1"/>
+ <fsummary>Request notification about available outgoing distribution channel data.</fsummary>
+ <desc>
+ <p>
+ Request notification when more data is available to
+ fetch using
+ <seealso marker="erlang#dist_ctrl_get_data/1"><c>erlang:dist_ctrl_get_data(DHandle)</c></seealso>
+ for the distribution channel identified by
+ <c><anno>DHandle</anno></c>. When more data is present,
+ the caller will be sent the message <c>dist_data</c>.
+ Once a <c>dist_data</c> messages has been sent, no
+ more <c>dist_data</c> messages will be sent until
+ the <c>dist_ctrl_get_data_notification/1</c> function has been called
+ again.
+ </p>
+ <note><p>
+ Only the process registered as distribution
+ controller for the distribution channel identified by
+ <c><anno>DHandle</anno></c> is allowed to call this
+ function.
+ </p></note>
+ <p>
+ This function is used when implementing an alternative
+ distribution carrier using processes as distribution
+ controllers. <c><anno>DHandle</anno></c> is retrived
+ via the callback
+ <seealso marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seealso>.
+ More information can be found in the documentation of
+ <seealso marker="erts:alt_dist#distribution_module">ERTS
+ User's Guide ➜ How to implement an Alternative Carrier
+ for the Erlang Distribution ➜ Distribution Module</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="dist_ctrl_input_handler" arity="2"/>
+ <fsummary>Register distribution channel input handler process.</fsummary>
+ <desc>
+ <p>
+ Register an alternate input handler process for the
+ distribution channel identified by <c><anno>DHandle</anno></c>.
+ Once this function has been called, <c><anno>InputHandler</anno></c>
+ is the only process allowed to call
+ <seealso marker="erlang#dist_ctrl_put_data/2"><c>erlang:dist_ctrl_put_data(DHandle, Data)</c></seealso>
+ with the <c><anno>DHandle</anno></c> identifing this distribution
+ channel.
+ </p>
+ <note><p>
+ Only the process registered as distribution
+ controller for the distribution channel identified by
+ <c><anno>DHandle</anno></c> is allowed to call this
+ function.
+ </p></note>
+ <p>
+ This function is used when implementing an alternative
+ distribution carrier using processes as distribution
+ controllers. <c><anno>DHandle</anno></c> is retrived
+ via the callback
+ <seealso marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seealso>.
+ More information can be found in the documentation of
+ <seealso marker="erts:alt_dist#distribution_module">ERTS
+ User's Guide ➜ How to implement an Alternative Carrier
+ for the Erlang Distribution ➜ Distribution Module</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="dist_ctrl_put_data" arity="2"/>
+ <fsummary>Pass data into the VM from a distribution channel.</fsummary>
+ <desc>
+ <p>
+ Deliver distribution channel data from a remote node to the
+ local node.
+ </p>
+ <note><p>
+ Only the process registered as distribution
+ controller for the distribution channel identified by
+ <c><anno>DHandle</anno></c> is allowed to call this
+ function unless an alternate input handler process
+ has been registered using
+ <seealso marker="erlang#dist_ctrl_input_handler/2"><c>erlang:dist_ctrl_input_handler(DHandle, InputHandler)</c></seealso>.
+ If an alternate input handler has been registered, only
+ the registered input handler process is allowed to call
+ this function.
+ </p></note>
+ <p>
+ This function is used when implementing an alternative
+ distribution carrier using processes as distribution
+ controllers. <c><anno>DHandle</anno></c> is retrived
+ via the callback
+ <seealso marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seealso>.
+ More information can be found in the documentation of
+ <seealso marker="erts:alt_dist#distribution_module">ERTS
+ User's Guide ➜ How to implement an Alternative Carrier
+ for the Erlang Distribution ➜ Distribution Module</seealso>.
+ </p>
+ </desc>
+ </func>
+
+ <func>
<name name="element" arity="2"/>
<fsummary>Return the Nth element of a tuple.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
@@ -1290,11 +1444,14 @@ b</pre>
the process to terminate, it has no return value. Example:</p>
<pre>
> <input>catch error(foobar).</input>
-{'EXIT',{foobar,[{erl_eval,do_apply,5},
- {erl_eval,expr,5},
- {shell,exprs,6},
- {shell,eval_exprs,6},
- {shell,eval_loop,3}]}}</pre>
+{'EXIT',{foobar,[{shell,apply_fun,3,
+ [{file,"shell.erl"},{line,906}]},
+ {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,677}]},
+ {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,430}]},
+ {shell,exprs,7,[{file,"shell.erl"},{line,687}]},
+ {shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]},
+ {shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}}
+</pre>
</desc>
</func>
@@ -1831,39 +1988,26 @@ true</pre>
<fsummary>Get the call stack back-trace of the last exception.</fsummary>
<type name="stack_item"/>
<desc>
- <p>Gets the call stack back-trace (<em>stacktrace</em>) for an
- exception that has just been caught
- in the calling process as a list of
- <c>{<anno>Module</anno>,<anno>Function</anno>,<anno>Arity</anno>,<anno>Location</anno>}</c>
- tuples. Field <c><anno>Arity</anno></c> in the first tuple can be the
- argument list of that function call instead of an arity integer,
- depending on the exception.</p>
- <p>If there has not been any exceptions in a process, the
- stacktrace is <c>[]</c>. After a code change for the process,
- the stacktrace can also be reset to <c>[]</c>.</p>
- <p><c>erlang:get_stacktrace/0</c> is only guaranteed to return
- a stacktrace if called (directly or indirectly) from within the
- scope of a <c>try</c> expression. That is, the following call works:</p>
+ <warning><p><c>erlang:get_stacktrace/0</c> is deprecated and will stop working
+ in a future release.</p></warning>
+ <p>Instead of using <c>erlang:get_stacktrace/0</c> to retrieve
+ the call stack back-trace, use the following syntax:</p>
<pre>
try Expr
catch
- C:R ->
- {C,R,erlang:get_stacktrace()}
+ Class:Reason:Stacktrace ->
+ {Class,Reason,Stacktrace}
end</pre>
- <p>As does this call:</p>
-<pre>
-try Expr
-catch
- C:R ->
- {C,R,helper()}
-end
-
-helper() ->
- erlang:get_stacktrace().</pre>
-
- <warning><p>In a future release,
- <c>erlang:get_stacktrace/0</c> will return <c>[]</c> if called
- from outside a <c>try</c> expression.</p></warning>
+ <p><c>erlang:get_stacktrace/0</c> retrieves the call stack back-trace
+ (<em>stacktrace</em>) for an exception that has just been
+ caught in the calling process as a list of
+ <c>{<anno>Module</anno>,<anno>Function</anno>,<anno>Arity</anno>,<anno>Location</anno>}</c>
+ tuples. Field <c><anno>Arity</anno></c> in the first tuple can
+ be the argument list of that function call instead of an arity
+ integer, depending on the exception.</p>
+ <p>If there has not been any exceptions in a process, the
+ stacktrace is <c>[]</c>. After a code change for the process,
+ the stacktrace can also be reset to <c>[]</c>.</p>
<p>The stacktrace is the same data as operator <c>catch</c>
returns, for example:</p>
<pre>
@@ -1886,6 +2030,18 @@ helper() ->
where the exception occurred or the function was called.
</item>
</taglist>
+ <warning><p>Developers should rely on stacktrace entries only for
+ debugging purposes.</p>
+ <p>The VM performs tail call optimization, which
+ does not add new entries to the stacktrace, and also limits stacktraces
+ to a certain depth. Furthermore, compiler options, optimizations and
+ future changes may add or remove stacktrace entries, causing any code
+ that expects the stacktrace to be in a certain order or contain specific
+ items to fail.</p>
+ <p>The only exception to this rule is <c>error:undef</c> which
+ guarantees to include the <anno>Module</anno>, <anno>Function</anno> and <anno>Arity</anno>
+ of the attempted function as the first stacktrace entry.</p>
+ </warning>
<p>See also
<seealso marker="#error/1"><c>error/1</c></seealso> and
<seealso marker="#error/2"><c>error/2</c></seealso>.</p>
@@ -3195,25 +3351,6 @@ RealSystem = system + MissedSystem</code>
monitored process resides). </p></item>
</taglist>
- <p>If an attempt is made to monitor a process on an older node
- (where remote process monitoring is not implemented or
- where remote process monitoring by registered name is not
- implemented), the call fails with <c>badarg</c>.</p>
- <note>
- <p>The format of the <c>'DOWN'</c> message changed in ERTS
- 5.2 (Erlang/OTP R9B) for monitoring
- <em>by registered name</em>. Element <c>Object</c> of
- the <c>'DOWN'</c> message could in earlier versions
- sometimes be the process identifier of the monitored process and sometimes
- be the registered name. Now element <c>Object</c> is
- always a tuple consisting of the registered name and
- the node name. Processes on new nodes (ERTS 5.2
- or higher versions) always get <c>'DOWN'</c> messages on
- the new format even if they are monitoring processes on old
- nodes. Processes on old nodes always get <c>'DOWN'</c>
- messages on the old format.</p>
- </note>
-
<taglist>
<tag>Monitoring a <marker id="monitor_process"/><c>process</c></tag>
<item>
@@ -3221,7 +3358,19 @@ RealSystem = system + MissedSystem</code>
process identified by <c><anno>Item</anno></c>, which can be a
<c>pid()</c> (local or remote), an atom <c>RegisteredName</c> or
a tuple <c>{RegisteredName, Node}</c> for a registered process,
- located elsewhere.</p>
+ located elsewhere.</p>
+
+ <note><p>Before ERTS 10.0 (OTP 21.0), monitoring a process could fail with
+ <c>badarg</c> if the monitored process resided on a primitive node
+ (such as erl_interface or jinterface), where remote process monitoring
+ is not implemented.</p>
+ <p>Now, such a call to <c>monitor</c> will instead succeed and a
+ monitor is created. But the monitor will only supervise the
+ connection. That is, a <c>{'DOWN', _, process, _, noconnection}</c> is
+ the only message that may be received, as the primitive node have no
+ way of reporting the status of the monitored process.</p>
+ </note>
+
</item>
<tag>Monitoring a <marker id="monitor_port"/><c>port</c></tag>
@@ -3686,6 +3835,12 @@ RealSystem = system + MissedSystem</code>
</item>
<tag><c>{env, <anno>Env</anno>}</c></tag>
<item>
+ <p>
+ Types:<br/>
+ &nbsp;&nbsp;<c><anno>Name</anno> = </c><seealso marker="kernel:os#type-env_var_name"><c>os:env_var_name()</c></seealso><br/>
+ &nbsp;&nbsp;<c><anno>Val</anno> = </c><seealso marker="kernel:os#type-env_var_value"><c>os:env_var_value()</c></seealso><c> | false</c><br/>
+ &nbsp;&nbsp;<c>Env = [{<anno>Name</anno>, <anno>Val</anno>}]</c>
+ </p>
<p>Only valid for <c>{spawn, <anno>Command</anno>}</c>, and
<c>{spawn_executable, <anno>FileName</anno>}</c>.
The environment of the started process is extended using
@@ -3700,7 +3855,13 @@ RealSystem = system + MissedSystem</code>
exception is <c><anno>Val</anno></c> being the atom
<c>false</c> (in analogy with
<seealso marker="kernel:os#getenv/1"><c>os:getenv/1</c></seealso>,
- which removes the environment variable.</p>
+ which removes the environment variable.
+ </p>
+ <p>
+ For information about encoding requirements, see documentation
+ of the types for <c><anno>Name</anno></c> and
+ <c><anno>Val</anno></c>.
+ </p>
</item>
<tag><c>{args, [ string() | binary() ]}</c></tag>
<item>
@@ -4326,7 +4487,6 @@ RealSystem = system + MissedSystem</code>
<desc>
<p><c><anno>Locking</anno></c> is one of the following:</p>
<list type="bulleted">
- <item><c>false</c> (emulator without SMP support)</item>
<item><c>port_level</c> (port-specific locking)</item>
<item><c>driver_level</c> (driver-specific locking)</item>
</list>
@@ -4567,11 +4727,11 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="process_flag" arity="2" clause_i="3"/>
+ <name name="process_flag" arity="2" clause_i="3"
+ anchor="process_flag_min_heap_size"/>
<fsummary>Set process flag min_heap_size for the calling process.
</fsummary>
<desc>
- <marker id="process_flag_min_heap_size"/>
<p>Changes the minimum heap size for the calling process.</p>
<p>Returns the old value of the flag.</p>
</desc>
@@ -4589,12 +4749,12 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="process_flag" arity="2" clause_i="5"/>
+ <name name="process_flag" arity="2" clause_i="5"
+ anchor="process_flag_max_heap_size"/>
<fsummary>Set process flag max_heap_size for the calling process.
</fsummary>
<type name="max_heap_size"/>
<desc>
- <marker id="process_flag_max_heap_size"/>
<p>This flag sets the maximum heap size for the calling process.
If <c><anno>MaxHeapSize</anno></c> is an integer, the system default
values for <c>kill</c> and <c>error_logger</c> are used.
@@ -4663,12 +4823,12 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="process_flag" arity="2" clause_i="6"/>
+ <name name="process_flag" arity="2" clause_i="6"
+ anchor="process_flag_message_queue_data"/>
<fsummary>Set process flag message_queue_data for the calling process.
</fsummary>
<type name="message_queue_data"/>
<desc>
- <marker id="process_flag_message_queue_data"/>
<p>This flag determines how messages in the message queue
are stored, as follows:</p>
<taglist>
@@ -4705,11 +4865,12 @@ RealSystem = system + MissedSystem</code>
</func>
<func>
- <name name="process_flag" arity="2" clause_i="7"/>
+ <name name="process_flag" arity="2" clause_i="7"
+ anchor="process_flag_priority"/>
<fsummary>Set process flag priority for the calling process.</fsummary>
<type name="priority_level"/>
<desc>
- <p><marker id="process_flag_priority"></marker>
+ <p>
Sets the process priority. <c><anno>Level</anno></c> is an atom.
Four priority levels exist: <c>low</c>,
<c>normal</c>, <c>high</c>, and <c>max</c>. Default
@@ -4730,8 +4891,8 @@ RealSystem = system + MissedSystem</code>
selected for execution. Notice however that this does
<em>not</em> mean that no processes on priority <c>low</c>
or <c>normal</c> can run when processes
- are running on priority <c>high</c>. On the runtime
- system with SMP support, more processes can be running
+ are running on priority <c>high</c>. When using multiple
+ schedulers, more processes can be running
in parallel than processes on priority <c>high</c>. That is,
a <c>low</c> and a <c>high</c> priority process can
execute at the same time.</p>
@@ -4746,10 +4907,8 @@ RealSystem = system + MissedSystem</code>
execution.</p>
<note>
<p>Do not depend on the scheduling
- to remain exactly as it is today. Scheduling, at least on
- the runtime system with SMP support, is likely to be
- changed in a future release to use available
- processor cores better.</p>
+ to remain exactly as it is today. Scheduling is likely to be
+ changed in a future release to use available processor cores better.</p>
</note>
<p>There is <em>no</em> automatic mechanism for
avoiding priority inversion, such as priority inheritance
@@ -6190,10 +6349,10 @@ true</pre>
</func>
<func>
- <name name="statistics" arity="1" clause_i="1"/>
+ <name name="statistics" arity="1" clause_i="1"
+ anchor="statistics_active_tasks"/>
<fsummary>Information about active processes and ports.</fsummary>
<desc>
- <marker id="statistics_active_tasks"></marker>
<p>Returns the same as
<seealso marker="#statistics_active_tasks_all">
<c>statistics(active_tasks_all)</c></seealso>
@@ -6205,10 +6364,10 @@ true</pre>
</func>
<func>
- <name name="statistics" arity="1" clause_i="2"/>
+ <name name="statistics" arity="1" clause_i="2"
+ anchor="statistics_active_tasks_all"/>
<fsummary>Information about active processes and ports.</fsummary>
<desc>
- <marker id="statistics_active_tasks_all"></marker>
<p>Returns a list where each element represents the amount
of active processes and ports on each run queue and its
associated schedulers. That is, the number of processes and
@@ -6256,17 +6415,16 @@ true</pre>
</func>
<func>
- <name name="statistics" arity="1" clause_i="4"/>
+ <name name="statistics" arity="1" clause_i="4"
+ anchor="statistics_exact_reductions"/>
<fsummary>Information about exact reductions.</fsummary>
<desc>
- <marker id="statistics_exact_reductions"></marker>
<p>Returns the number of exact reductions.</p>
<note>
<p><c>statistics(exact_reductions)</c> is
a more expensive operation than
<seealso marker="#statistics_reductions">
- statistics(reductions)</seealso>,
- especially on an Erlang machine with SMP support.</p>
+ statistics(reductions)</seealso>.</p>
</note>
</desc>
</func>
@@ -6295,10 +6453,10 @@ true</pre>
</func>
<func>
- <name name="statistics" arity="1" clause_i="7"/>
+ <name name="statistics" arity="1" clause_i="7"
+ anchor="statistics_microstate_accounting"/>
<fsummary>Information about microstate accounting.</fsummary>
<desc>
- <marker id="statistics_microstate_accounting"></marker>
<p>Microstate accounting can be used to measure how much time the Erlang
runtime system spends doing various tasks. It is designed to be as
lightweight as possible, but some overhead exists when this
@@ -6343,17 +6501,24 @@ lists:map(
<p><c><anno>MSAcc_Thread_Type</anno></c>s:</p>
<taglist>
<tag><c>scheduler</c></tag>
- <item>The main execution threads that do most of the work.</item>
+ <item>The main execution threads that do most of the work. See
+ <seealso marker="erts:erl#+S">erl +S</seealso> for more details.</item>
<tag><c>dirty_cpu_scheduler</c></tag>
- <item>The threads for long running cpu intensive work.</item>
+ <item>The threads for long running cpu intensive work. See
+ <seealso marker="erts:erl#+SDcpu">erl +SDcpu</seealso> for more details.</item>
<tag><c>dirty_io_scheduler</c></tag>
- <item>The threads for long running I/O work.</item>
+ <item>The threads for long running I/O work. See
+ <seealso marker="erts:erl#+SDio">erl +SDio</seealso> for more details.</item>
<tag><c>async</c></tag>
<item>Async threads are used by various linked-in drivers (mainly the
- file drivers) do offload non-CPU intensive work.</item>
+ file drivers) do offload non-CPU intensive work. See
+ <seealso marker="erts:erl#+async_thread_pool_size">erl +A</seealso> for more details.</item>
<tag><c>aux</c></tag>
<item>Takes care of any work that is not
specifically assigned to a scheduler.</item>
+ <tag><c>poll</c></tag>
+ <item>Does the IO polling for the emulator. See
+ <seealso marker="erts:erl#+IOt">erl +IOt</seealso> for more details.</item>
</taglist>
<p>The following <c><anno>MSAcc_Thread_State</anno></c>s are available.
All states are exclusive, meaning that a thread cannot be in two
@@ -6431,10 +6596,10 @@ lists:map(
</func>
<func>
- <name name="statistics" arity="1" clause_i="8"/>
+ <name name="statistics" arity="1" clause_i="8"
+ anchor="statistics_reductions"/>
<fsummary>Information about reductions.</fsummary>
<desc>
- <marker id="statistics_reductions"></marker>
<p>Returns information about reductions, for example:</p>
<pre>
> <input>statistics(reductions).</input>
@@ -6450,9 +6615,10 @@ lists:map(
</func>
<func>
- <name name="statistics" arity="1" clause_i="9"/>
+ <name name="statistics" arity="1" clause_i="9"
+ anchor="statistics_run_queue"/>
<fsummary>Information about the run-queues.</fsummary>
- <desc><marker id="statistics_run_queue"></marker>
+ <desc>
<p>Returns the total length of all normal run-queues. That is, the number
of processes and ports that are ready to run on all available
normal run-queues. Dirty run queues are not part of the
@@ -6466,9 +6632,10 @@ lists:map(
</func>
<func>
- <name name="statistics" arity="1" clause_i="10"/>
+ <name name="statistics" arity="1" clause_i="10"
+ anchor="statistics_run_queue_lengths"/>
<fsummary>Information about the run-queue lengths.</fsummary>
- <desc><marker id="statistics_run_queue_lengths"></marker>
+ <desc>
<p>Returns the same as
<seealso marker="#statistics_run_queue_lengths_all">
<c>statistics(run_queue_lengths_all)</c></seealso>
@@ -6480,9 +6647,10 @@ lists:map(
</func>
<func>
- <name name="statistics" arity="1" clause_i="11"/>
+ <name name="statistics" arity="1" clause_i="11"
+ anchor="statistics_run_queue_lengths_all"/>
<fsummary>Information about the run-queue lengths.</fsummary>
- <desc><marker id="statistics_run_queue_lengths_all"></marker>
+ <desc>
<p>Returns a list where each element represents the amount
of processes and ports ready to run for each run queue.
Values for normal run queues are located first in the
@@ -6540,10 +6708,10 @@ lists:map(
</func>
<func>
- <name name="statistics" arity="1" clause_i="13"/>
+ <name name="statistics" arity="1" clause_i="13"
+ anchor="statistics_scheduler_wall_time"/>
<fsummary>Information about each schedulers work time.</fsummary>
<desc>
- <marker id="statistics_scheduler_wall_time"></marker>
<p>Returns a list of tuples with
<c>{<anno>SchedulerId</anno>, <anno>ActiveTime</anno>,
<anno>TotalTime</anno>}</c>, where
@@ -6650,8 +6818,8 @@ ok
than available logical processors, this value may
be greater than <c>1.0</c>.</p>
<p>As of ERTS version 9.0, the Erlang runtime system
- with SMP support will as default have more schedulers
- than logical processors. This due to the dirty schedulers.</p>
+ will as default have more schedulers than logical processors.
+ This due to the dirty schedulers.</p>
<note>
<p><c>scheduler_wall_time</c> is by default disabled. To
enable it, use
@@ -6661,10 +6829,10 @@ ok
</func>
<func>
- <name name="statistics" arity="1" clause_i="14"/>
+ <name name="statistics" arity="1" clause_i="14"
+ anchor="statistics_scheduler_wall_time_all"/>
<fsummary>Information about each schedulers work time.</fsummary>
<desc>
- <marker id="statistics_scheduler_wall_time_all"></marker>
<p>The same as
<seealso marker="#statistics_scheduler_wall_time"><c>statistics(scheduler_wall_time)</c></seealso>,
except that it also include information about all dirty I/O
@@ -6686,9 +6854,10 @@ ok
</desc>
</func>
<func>
- <name name="statistics" arity="1" clause_i="15"/>
+ <name name="statistics" arity="1" clause_i="15"
+ anchor="statistics_total_active_tasks"/>
<fsummary>Information about active processes and ports.</fsummary>
- <desc><marker id="statistics_total_active_tasks"></marker>
+ <desc>
<p>The same as calling
<c>lists:sum(</c><seealso marker="#statistics_active_tasks"><c>statistics(active_tasks)</c></seealso><c>)</c>,
but more efficient.</p>
@@ -6696,9 +6865,10 @@ ok
</func>
<func>
- <name name="statistics" arity="1" clause_i="16"/>
+ <name name="statistics" arity="1" clause_i="16"
+ anchor="statistics_total_active_tasks_all"/>
<fsummary>Information about active processes and ports.</fsummary>
- <desc><marker id="statistics_total_active_tasks_all"></marker>
+ <desc>
<p>The same as calling
<c>lists:sum(</c><seealso marker="#statistics_active_tasks_all"><c>statistics(active_tasks_all)</c></seealso><c>)</c>,
but more efficient.</p>
@@ -6706,9 +6876,10 @@ ok
</func>
<func>
- <name name="statistics" arity="1" clause_i="17"/>
+ <name name="statistics" arity="1" clause_i="17"
+ anchor="statistics_total_run_queue_lengths"/>
<fsummary>Information about the run-queue lengths.</fsummary>
- <desc><marker id="statistics_total_run_queue_lengths"></marker>
+ <desc>
<p>The same as calling
<c>lists:sum(</c><seealso marker="#statistics_run_queue_lengths"><c>statistics(run_queue_lengths)</c></seealso><c>)</c>,
but more efficient.</p>
@@ -6716,9 +6887,10 @@ ok
</func>
<func>
- <name name="statistics" arity="1" clause_i="18"/>
+ <name name="statistics" arity="1" clause_i="18"
+ anchor="statistics_total_run_queue_lengths_all"/>
<fsummary>Information about the run-queue lengths.</fsummary>
- <desc><marker id="statistics_total_run_queue_lengths_all"></marker>
+ <desc>
<p>The same as calling
<c>lists:sum(</c><seealso marker="#statistics_run_queue_lengths_all"><c>statistics(run_queue_lengths_all)</c></seealso><c>)</c>,
but more efficient.</p>
@@ -6866,7 +7038,8 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="2"/>
+ <name name="system_flag" arity="2" clause_i="2"
+ anchor="system_flag_cpu_topology"/>
<fsummary>Set system flag <c>cpu_topology</c>.</fsummary>
<type name="cpu_topology"/>
<type name="level_entry"/>
@@ -6875,7 +7048,7 @@ ok
<type name="info_list"/>
<desc>
<warning>
- <p><marker id="system_flag_cpu_topology"></marker>
+ <p>
<em>This argument is deprecated.</em>
Instead of using this argument, use command-line argument
<seealso marker="erts:erl#+sct"><c>+sct</c></seealso> in
@@ -6913,10 +7086,11 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="3"/>
+ <name name="system_flag" arity="2" clause_i="3"
+ anchor="system_flag_dirty_cpu_schedulers_online"/>
<fsummary>Set system_flag_dirty_cpu_schedulers_online.</fsummary>
<desc>
- <p><marker id="system_flag_dirty_cpu_schedulers_online"></marker>
+ <p>
Sets the number of dirty CPU schedulers online. Range is
<c><![CDATA[1 <= DirtyCPUSchedulersOnline <= N]]></c>, where <c>N</c>
is the smallest of the return values of
@@ -6977,10 +7151,11 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="6"/>
+ <name name="system_flag" arity="2" clause_i="6"
+ anchor="system_flag_microstate_accounting"/>
<fsummary>Set system flag microstate_accounting.</fsummary>
<desc>
- <p><marker id="system_flag_microstate_accounting"></marker>
+ <p>
Turns on/off microstate accounting measurements. When passing reset,
all counters are reset to 0.</p>
<p>For more information see
@@ -7022,28 +7197,29 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="9"/>
+ <name name="system_flag" arity="2" clause_i="9"
+ anchor="system_flag_max_heap_size"/>
<fsummary>Set system flag max_heap_size.</fsummary>
<type name="max_heap_size"/>
<desc>
- <marker id="system_flag_max_heap_size"></marker>
<p>
Sets the default maximum heap size settings for processes.
The size is specified in words. The new <c>max_heap_size</c>
effects only processes spawned efter the change has been made.
<c>max_heap_size</c> can be set for individual processes using
<seealso marker="#spawn_opt/4"><c>spawn_opt/2,3,4</c></seealso> or
- <seealso marker="#process_flag_message_queue_data">
+ <seealso marker="#process_flag_max_heap_size">
<c>process_flag/2</c></seealso>.</p>
<p>Returns the old value of the flag.</p>
</desc>
</func>
<func>
- <name name="system_flag" arity="2" clause_i="10"/>
+ <name name="system_flag" arity="2" clause_i="10"
+ anchor="system_flag_multi_scheduling"/>
<fsummary>Set system flag multi_scheduling.</fsummary>
<desc>
- <p><marker id="system_flag_multi_scheduling"></marker>
+ <p>
If multi-scheduling is enabled, more than one scheduler
thread is used by the emulator. Multi-scheduling can be
blocked in two different ways. Either all schedulers but
@@ -7095,12 +7271,13 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="11"/>
+ <name name="system_flag" arity="2" clause_i="11"
+ anchor="system_flag_scheduler_bind_type"/>
<fsummary>Set system flag scheduler_bind_type.</fsummary>
<type name="scheduler_bind_type"/>
<desc>
<warning>
- <p><marker id="system_flag_scheduler_bind_type"></marker>
+ <p>
<em>This argument is deprecated.</em>
Instead of using this argument, use command-line argument
<seealso marker="erts:erl#+sbt"><c>+sbt</c></seealso> in
@@ -7221,10 +7398,11 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="12"/>
+ <name name="system_flag" arity="2" clause_i="12"
+ anchor="system_flag_scheduler_wall_time"/>
<fsummary>Set system flag scheduler_wall_time.</fsummary>
<desc>
- <p><marker id="system_flag_scheduler_wall_time"></marker>
+ <p>
Turns on or off scheduler wall time measurements.</p>
<p>For more information, see
<seealso marker="#statistics_scheduler_wall_time">
@@ -7233,10 +7411,11 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="13"/>
+ <name name="system_flag" arity="2" clause_i="13"
+ anchor="system_flag_schedulers_online"/>
<fsummary>Set system flag schedulers_online.</fsummary>
<desc>
- <p><marker id="system_flag_schedulers_online"></marker>
+ <p>
Sets the number of schedulers online. Range is
<c><![CDATA[1 <= SchedulersOnline <=
erlang:system_info(schedulers)]]></c>.</p>
@@ -7275,10 +7454,11 @@ ok
</func>
<func>
- <name name="system_flag" arity="2" clause_i="15"/>
+ <name name="system_flag" arity="2" clause_i="15"
+ anchor="system_flag_time_offset"/>
<fsummary>Finalize the time offset.</fsummary>
<desc>
- <p><marker id="system_flag_time_offset"></marker>
+ <p>
Finalizes the <seealso marker="#time_offset/0">time offset</seealso>
when <seealso marker="time_correction#Single_Time_Warp_Mode">single
time warp mode</seealso> is used. If another time warp mode
@@ -7451,7 +7631,8 @@ ok
</func>
<func>
- <name name="system_info" arity="1" clause_i="12"/>
+ <name name="system_info" arity="1" clause_i="12"
+ anchor="system_info_cpu_topology"/>
<name name="system_info" arity="1" clause_i="13"/>
<fsummary>Information about the CPU topology of the system.</fsummary>
<type name="cpu_topology"/>
@@ -7479,7 +7660,6 @@ ok
</type_desc>
<desc>
<marker id="system_info_cpu_topology_tags"></marker>
- <marker id="system_info_cpu_topology"></marker>
<p>Returns various information about the CPU topology of
the current system (emulator) as specified by
<c><anno>Item</anno></c>:</p>
@@ -7927,15 +8107,6 @@ ok
The return value will always be <c>false</c>, as the
<c>elib_malloc</c> allocator has been removed.</p>
</item>
- <tag><marker id="system_info_eager_check_io"/>
- <c>eager_check_io</c></tag>
- <item>
- <p>Returns the value of command-line flag
- <seealso marker="erl#+secio"><c>+secio</c></seealso> in
- <c>erl(1)</c>, which is either <c>true</c> or <c>false</c>.
- For information about the different values, see the
- documentation of the command-line flag.</p>
- </item>
<tag><c>ets_limit</c></tag>
<item>
<p>Returns the maximum number of ETS tables allowed. This
@@ -8038,9 +8209,7 @@ ok
<taglist>
<tag><c>disabled</c></tag>
<item>
- <p>The emulator has only one scheduler thread. The
- emulator does not have SMP support, or have been
- started with only one scheduler thread.</p>
+ <p>The emulator has been started with only one scheduler thread.</p>
</item>
<tag><c>blocked</c></tag>
<item>
@@ -8403,8 +8572,7 @@ ok
</item>
<tag><c>smp_support</c></tag>
<item>
- <p>Returns <c>true</c> if the emulator has been compiled
- with SMP support, otherwise <c>false</c> is returned.</p>
+ <p>Returns <c>true</c>.</p>
</item>
<tag><marker id="system_info_start_time"/><c>start_time</c></tag>
<item>
@@ -8427,8 +8595,7 @@ ok
</item>
<tag><c>threads</c></tag>
<item>
- <p>Returns <c>true</c> if the emulator has been compiled
- with thread support, otherwise <c>false</c> is returned.</p>
+ <p>Returns <c>true</c>.</p>
</item>
<tag><c>thread_pool_size</c></tag>
<item>
@@ -10551,9 +10718,9 @@ true</pre>
<c>receive after 1 -> ok end</c>, except that <c>yield()</c>
is faster.</p>
<warning>
- <p>There is seldom or never any need to use this BIF,
- especially in the SMP emulator, as other processes have a
- chance to run in another scheduler thread anyway.
+ <p>There is seldom or never any need to use this BIF
+ as other processes have a chance to run in another scheduler
+ thread anyway.
Using this BIF without a thorough grasp of how the scheduler
works can cause performance degradation.</p>
</warning>
diff --git a/erts/doc/src/erlc.xml b/erts/doc/src/erlc.xml
index 7355be488b..2214b76a51 100644
--- a/erts/doc/src/erlc.xml
+++ b/erts/doc/src/erlc.xml
@@ -143,6 +143,14 @@
<p>Produces a Makefile rule to track header dependencies. The
rule is sent to <c>stdout</c>. No object file is produced.</p>
</item>
+
+ <tag><c>-MMD</c></tag>
+ <item>
+ <p>Generate dependencies as a side-effect. The object file
+ will be produced as normal. This option overrides the
+ option <c><![CDATA[-M]]></c>.</p>
+ </item>
+
<tag><c>-MF &lt;Makefile&gt;</c></tag>
<item>
<p>As option <c><![CDATA[-M]]></c>, except that the
diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml
index ce8d75f350..049ffe560a 100644
--- a/erts/doc/src/erts_alloc.xml
+++ b/erts/doc/src/erts_alloc.xml
@@ -87,9 +87,9 @@
the number of system calls made.</item>
</taglist>
- <p><c>sys_alloc</c> and <c>literal_alloc</c> are always enabled and
- cannot be disabled. <c>exec_alloc</c> is only available if it is needed
- and cannot be disabled. <c>mseg_alloc</c> is always enabled if it is
+ <p><c>sys_alloc</c>, <c>literal_alloc</c> and <c>temp_alloc</c> are always
+ enabled and cannot be disabled. <c>exec_alloc</c> is only available if it
+ is needed and cannot be disabled. <c>mseg_alloc</c> is always enabled if it is
available and an allocator that uses it is enabled. All other
allocators can be <seealso marker="#M_e">enabled or disabled</seealso>.
By default all allocators are enabled.
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index f62788d2d8..3109da6738 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -4189,8 +4189,7 @@
<p>The previously introduced "eager check I/O" feature is
now enabled by default.</p>
<p>Eager check I/O can be disabled using the <c>erl</c>
- command line argument: <seealso
- marker="erl#+secio"><c>+secio false</c></seealso></p>
+ command line argument: <c>+secio false</c></p>
<p>Characteristics impact compared to previous
default:</p> <list> <item>Lower latency and smoother
management of externally triggered I/O operations.</item>
@@ -4971,8 +4970,7 @@
prioritized to the same extent as when eager check I/O is
disabled.</p>
<p>Eager check I/O can be enabled using the <c>erl</c>
- command line argument: <seealso
- marker="erl#+secio"><c>+secio true</c></seealso></p>
+ command line argument: <c>+secio true</c></p>
<p>Characteristics impact when enabled:</p> <list>
<item>Lower latency and smoother management of externally
triggered I/O operations.</item> <item>A slightly reduced