aboutsummaryrefslogtreecommitdiffstats
path: root/erts/doc
diff options
context:
space:
mode:
Diffstat (limited to 'erts/doc')
-rw-r--r--erts/doc/src/Makefile46
-rw-r--r--erts/doc/src/alt_disco.xml2
-rw-r--r--erts/doc/src/alt_dist.xml2
-rw-r--r--erts/doc/src/book.xml3
-rw-r--r--erts/doc/src/communication.xml2
-rw-r--r--erts/doc/src/crash_dump.xml2
-rw-r--r--erts/doc/src/erl.xml39
-rw-r--r--erts/doc/src/erl_dist_protocol.xml121
-rw-r--r--erts/doc/src/erl_driver.xml24
-rw-r--r--erts/doc/src/erl_ext_dist.xml510
-rw-r--r--erts/doc/src/erl_nif.xml192
-rw-r--r--erts/doc/src/erlang.xml101
-rw-r--r--erts/doc/src/erts_alloc.xml11
-rw-r--r--erts/doc/src/internal.xml44
-rw-r--r--erts/doc/src/net.xml129
-rw-r--r--erts/doc/src/notes.xml12
-rw-r--r--erts/doc/src/part.xml1
-rw-r--r--erts/doc/src/persistent_term.xml13
-rw-r--r--erts/doc/src/ref_man.xml34
-rw-r--r--erts/doc/src/socket.xml650
-rw-r--r--erts/doc/src/socket_usage.xml773
-rw-r--r--erts/doc/src/specs.xml2
-rw-r--r--erts/doc/src/tty.xml4
23 files changed, 2457 insertions, 260 deletions
diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile
index 40f74b78ff..bc01919da1 100644
--- a/erts/doc/src/Makefile
+++ b/erts/doc/src/Makefile
@@ -55,7 +55,9 @@ XML_REF3_EFILES = \
persistent_term.xml \
atomics.xml \
counters.xml \
- zlib.xml
+ zlib.xml \
+ socket.xml \
+ net.xml
XML_REF3_FILES = \
$(XML_REF3_EFILES) \
@@ -65,7 +67,22 @@ XML_REF3_FILES = \
erts_alloc.xml
XML_PART_FILES = \
- part.xml
+ part.xml internal.xml
+
+XML_INTERNAL_FILES = \
+ CarrierMigration.xml \
+ ThreadProgress.xml \
+ CodeLoading.xml \
+ Tracing.xml \
+ DelayedDealloc.xml \
+ beam_makeops.xml \
+ GarbageCollection.xml \
+ PTables.xml \
+ PortSignals.xml \
+ ProcessManagementOptimizations.xml \
+ SuperCarrier.xml \
+ CountingInstructions.xml
+
XML_CHAPTER_FILES = \
introduction.xml \
@@ -77,6 +94,7 @@ XML_CHAPTER_FILES = \
driver.xml \
absform.xml \
inet_cfg.xml \
+ socket_usage.xml \
erl_ext_dist.xml \
erl_dist_protocol.xml \
communication.xml \
@@ -94,6 +112,8 @@ XML_FILES = \
$(BOOK_FILES) $(XML_CHAPTER_FILES) \
$(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF1_FILES) $(XML_APPLICATION_FILES)
+XML_GEN_FILES = $(XML_INTERNAL_FILES:%=$(XMLDIR)/%)
+
# ----------------------------------------------------
HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \
@@ -113,6 +133,12 @@ SPECS_FILES = $(XML_REF3_EFILES:%.xml=$(SPECDIR)/specs_%.xml)
TOP_SPECS_FILE = specs.xml
+XML_FIGURE_DIR = $(XMLDIR)/figures
+
+INTERNAL_DOC_PNG_FILES = $(wildcard ../../emulator/internal_doc/figures/*.png)
+PNG_FILES = $(notdir $(INTERNAL_DOC_PNG_FILES))
+XMLDIR_PNG_FILES = $(PNG_FILES:%=$(XML_FIGURE_DIR)/%)
+
# ----------------------------------------------------
# FLAGS
# ----------------------------------------------------
@@ -125,10 +151,15 @@ SPECS_FLAGS = -I$(KERNEL_SRC) -I$(KERNEL_INCLUDE)
# ----------------------------------------------------
# Targets
# ----------------------------------------------------
+_create_dirs := $(shell mkdir -p $(XML_FIGURE_DIR))
+
$(HTMLDIR)/%.gif: %.gif
$(INSTALL_DATA) $< $@
-docs: man pdf html $(INFO_FILE)
+$(XML_FIGURE_DIR)/%.png: ../../emulator/internal_doc/figures/%.png
+ $(INSTALL_DATA) $< $@
+
+docs: figures man pdf html $(INFO_FILE)
$(TOP_PDF_FILE): $(XML_FILES)
@@ -143,9 +174,12 @@ gifs: $(GIF_FILES:%=$(HTMLDIR)/%)
$(INFO_FILE): $(INFO_FILE_SRC) $(ERL_TOP)/make/$(TARGET)/otp.mk
sed -e 's;%RELEASE%;$(SYSTEM_VSN);' $(INFO_FILE_SRC) > $(INFO_FILE)
+figures: $(XMLDIR_PNG_FILES)
debug opt:
+ldocs: xmllint local_docs
+
clean:
rm -rf $(HTMLDIR)/*
rm -rf $(XMLDIR)
@@ -159,6 +193,9 @@ $(SPECDIR)/specs_%.xml:
$(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \
-o$(dir $@) -module $(patsubst $(SPECDIR)/specs_%.xml,%,$@)
+$(XMLDIR)/%.xml: ../../emulator/internal_doc/%.md $(ERL_TOP)/make/emd2exml
+ $(ERL_TOP)/make/emd2exml $< $@
+
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
@@ -168,8 +205,11 @@ release_docs_spec: docs
$(INSTALL_DIR) "$(RELSYSDIR)/doc/pdf"
$(INSTALL_DATA) $(TOP_PDF_FILE) "$(RELSYSDIR)/doc/pdf"
$(INSTALL_DIR) "$(RELSYSDIR)/doc/html"
+ $(INSTALL_DIR) "$(RELSYSDIR)/doc/html/figures"
$(INSTALL_DATA) $(HTMLDIR)/* \
"$(RELSYSDIR)/doc/html"
+ $(INSTALL_DATA) $(XMLDIR)/figures/* \
+ "$(RELSYSDIR)/doc/html/figures"
$(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 \
diff --git a/erts/doc/src/alt_disco.xml b/erts/doc/src/alt_disco.xml
index d04221b9b3..148d6f549e 100644
--- a/erts/doc/src/alt_disco.xml
+++ b/erts/doc/src/alt_disco.xml
@@ -63,7 +63,7 @@
<seealso marker="kernel:erl_epmd">EPMD module</seealso>. However, instead of
communicating with EPMD you can connect to any service to find out
connection details of other nodes. A discovery module is enabled
- by setting <seealso marker="erts:erl#epmd_module">-epmd_module</seealso>
+ by setting <seealso marker="erts:erl">-epmd_module</seealso>
when starting erlang. The discovery module must implement the following
callbacks:</p>
diff --git a/erts/doc/src/alt_dist.xml b/erts/doc/src/alt_dist.xml
index e6245130fc..7c997cae20 100644
--- a/erts/doc/src/alt_dist.xml
+++ b/erts/doc/src/alt_dist.xml
@@ -60,7 +60,7 @@
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,
+ Erlang code will of course have to take care of retransmissions,
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.
diff --git a/erts/doc/src/book.xml b/erts/doc/src/book.xml
index a0780c91d9..d79da1e4f7 100644
--- a/erts/doc/src/book.xml
+++ b/erts/doc/src/book.xml
@@ -41,6 +41,9 @@
<applications>
<xi:include href="ref_man.xml"/>
</applications>
+ <internals>
+ <xi:include href="internal.xml"/>
+ </internals>
<releasenotes>
<xi:include href="notes.xml"/>
</releasenotes>
diff --git a/erts/doc/src/communication.xml b/erts/doc/src/communication.xml
index 7e18a73aa8..251b52dc65 100644
--- a/erts/doc/src/communication.xml
+++ b/erts/doc/src/communication.xml
@@ -64,7 +64,7 @@
a synchronous communication operation consists of two asynchronous
signals; one request signal and one reply signal. An example of
such a synchronous communication is a call to
- <seealso marker="erlang:process_info/2">
+ <seealso marker="erlang#process_info/2">
<c>erlang:process_info/2</c></seealso>
when the first argument is not <c>self()</c>. The caller sends
an asynchronous signal requesting information, and then
diff --git a/erts/doc/src/crash_dump.xml b/erts/doc/src/crash_dump.xml
index a9aeb1888c..33d0903622 100644
--- a/erts/doc/src/crash_dump.xml
+++ b/erts/doc/src/crash_dump.xml
@@ -290,7 +290,7 @@ Slogan: &lt;reason&gt;</pre>
<title>Memory Information</title>
<p>Under the tag <em>=memory</em> is shown information similar
to what can be obtainted on a living node with
- <seealso marker="erts:erlang#erlang:memory/0">
+ <seealso marker="erts:erlang#memory/0">
<c>erlang:memory()</c></seealso>.</p>
</section>
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml
index 133f160dc9..ed1b0880b4 100644
--- a/erts/doc/src/erl.xml
+++ b/erts/doc/src/erl.xml
@@ -460,11 +460,14 @@
<tag><c><![CDATA[-remsh Node]]></c></tag>
<item>
<p>Starts Erlang with a remote shell connected to
- <c><![CDATA[Node]]></c>.</p>
+ <c><![CDATA[Node]]></c>. Requires either <c><![CDATA[-name]]></c>
+ or <c><![CDATA[-sname]]></c> to be given. If <c><![CDATA[Node]]></c>
+ does not contain a hostname, one is automatically taken from
+ <c><![CDATA[-name]]></c> or <c><![CDATA[-sname]]></c></p>
</item>
<tag><c><![CDATA[-rsh Program]]></c></tag>
<item>
- <p>Specifies an alternative to <c><![CDATA[rsh]]></c> for starting a
+ <p>Specifies an alternative to <c><![CDATA[ssh]]></c> for starting a
slave node on a remote host; see
<seealso marker="stdlib:slave"><c>slave(3)</c></seealso>.</p>
</item>
@@ -636,6 +639,29 @@
produces a crash dump. On Unix systems, sending an emulator process
a <c>SIGUSR1</c> signal also forces a crash dump.</p>
</item>
+ <tag><marker id="+dcg"/><c><![CDATA[+rg DecentralizedCounterGroupsLimit]]></c></tag>
+ <item>
+ <p>Limits the number of decentralized counter groups used by
+ decentralized counters optimized for update operations in the
+ Erlang runtime system. By default, the limit is 256.</p>
+ <p>When the number of schedulers is less than or equal to the
+ limit, each scheduler has its own group. When the
+ number of schedulers is larger than the groups limit,
+ schedulers share groups. Shared groups degrade
+ the performance for updating counters while many reader groups
+ degrade the performance for reading counters. So, the limit is a tradeoff
+ between performance for update operations and performance for
+ read operations. Each group consumes 64 bytes in each
+ counter.</p>
+ <p>Notice that a runtime system using decentralized
+ counter groups benefits from <seealso marker="#+sbt">binding
+ schedulers to logical processors</seealso>, as the groups are
+ distributed better between schedulers with this option.</p>
+ <p>This option only affects decentralized counters used for
+ the counters that are keeping track of the memory consumption
+ and the number of terms in ETS tables of type ordered_set with
+ the write_concurrency option activated.</p>
+ </item>
<tag><marker id="+e"/><c><![CDATA[+e Number]]></c></tag>
<item>
<p>Sets the maximum number of ETS tables. This limit is
@@ -1552,15 +1578,6 @@
parameter determines. The lingering prevents repeated
deletions and insertions in the tables from occurring.</p>
</item>
- <tag><marker id="+ztma"/><c>+ztma true | false</c></tag>
- <item>
- <p>Enables or disables support for tuple module apply in
- the emulator. This is a transitional flag for running code
- that uses parameterized modules and was compiled under OTP 20
- or earlier. For future compatibility, the modules will need
- to be recompiled with the +tuple_calls compiler option.
- Defaults to false.</p>
- </item>
</taglist>
</item>
</taglist>
diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml
index c90c8f9521..f924c8a70b 100644
--- a/erts/doc/src/erl_dist_protocol.xml
+++ b/erts/doc/src/erl_dist_protocol.xml
@@ -532,11 +532,7 @@ io:format("old/unused name ~ts at port ~p, fd = ~p ~n",
<marker id="distribution_handshake"/>
<title>Distribution Handshake</title>
<p>This section describes the distribution handshake protocol introduced
- in Erlang/OTP R6. This description was previously located in
- <c>$ERL_TOP/lib/kernel/internal_doc/distribution_handshake.txt</c> and
- has more or less been copied and "formatted" here. It has been almost
- unchanged since 1999, but the handshake has not changed much since then
- either.</p>
+ in Erlang/OTP R6. The handshake has remained almost the same since then.</p>
<section>
<title>General</title>
@@ -847,6 +843,23 @@ DiB == gen_digest(ChA, ICA)?
of the <c>SEND_TT</c> control message.
</p>
</item>
+ <tag><c>-define(DFLAG_BIG_SEQTRACE_LABELS, 16#100000).</c></tag>
+ <item>
+ <p>The node understands any term as the seqtrace label.</p>
+ </item>
+ <tag><c>-define(DFLAG_EXIT_PAYLOAD, 16#400000).</c></tag>
+ <item>
+ <p>Use the <c>PAYLOAD_EXIT</c>, <c>PAYLOAD_EXIT_TT</c>,
+ <c>PAYLOAD_EXIT2</c>, <c>PAYLOAD_EXIT2_TT</c>
+ and <c>PAYLOAD_MONITOR_P_EXIT</c>
+ <seealso marker="#control_message">control message</seealso>s
+ instead of the non-PAYLOAD variants.</p>
+ </item>
+ <tag><c>-define(DFLAG_FRAGMENTS, 16#800000).</c></tag>
+ <item>
+ <p>Use <seealso marker="erl_ext_dist#fragments">fragmented</seealso>
+ distribution messages to send large messages.</p>
+ </item>
</taglist>
<p>
There is also function <c>dist_util:strict_order_flags/0</c>
@@ -859,7 +872,7 @@ DiB == gen_digest(ChA, ICA)?
<section>
<marker id="connected_nodes"/>
<title>Protocol between Connected Nodes</title>
- <p>As from ERTS 5.7.2 the runtime system passes a distribution flag
+ <p>Since ERTS 5.7.2 (OTP R13B) the runtime system passes a distribution flag
in the handshake stage that enables the use of a
<seealso marker="erl_ext_dist#distribution_header">distribution header
</seealso> on all messages passed. Messages passed between nodes have in
@@ -878,7 +891,7 @@ DiB == gen_digest(ChA, ICA)?
<cell align="center"><c>ControlMessage</c></cell>
<cell align="center"><c>Message</c></cell>
</row>
- <tcaption>Format of Messages Passed between Nodes (as from ERTS 5.7.2)
+ <tcaption>Format of Messages Passed between Nodes (as from ERTS 5.7.2 (OTP R13B))
</tcaption>
</table>
@@ -887,15 +900,23 @@ DiB == gen_digest(ChA, ICA)?
<item>
<p>Equal to d + n + m.</p>
</item>
+ <tag><c>DistributionHeader</c></tag>
+ <item>
+ <p>
+ <seealso marker="erl_ext_dist#distribution_header">Distribution header
+ describing the atom cache and fragmented distribution messages.
+ </seealso>
+ </p>
+ </item>
<tag><c>ControlMessage</c></tag>
<item>
<p>A tuple passed using the external format of Erlang.</p>
</item>
<tag><c>Message</c></tag>
<item>
- <p>The message sent to another node using the '!' (in external format).
- Notice that <c>Message</c> is only passed in combination with a
- <c>ControlMessage</c> encoding a send ('!').</p>
+ <p>The message sent to another node using the '!'
+ or the reason for a EXIT, EXIT2 or DOWN signal using
+ the external term format.</p>
</item>
</taglist>
@@ -903,7 +924,7 @@ DiB == gen_digest(ChA, ICA)?
number is omitted from the terms that follow a distribution header
</seealso>.</p>
- <p>Nodes with an ERTS version earlier than 5.7.2 does not pass the
+ <p>Nodes with an ERTS version earlier than 5.7.2 (OTP R13B) does not pass the
distribution flag that enables the distribution header. Messages passed
between nodes have in this case the following format:</p>
@@ -920,7 +941,7 @@ DiB == gen_digest(ChA, ICA)?
<cell align="center"><c>ControlMessage</c></cell>
<cell align="center"><c>Message</c></cell>
</row>
- <tcaption>Format of Messages Passed between Nodes (before ERTS 5.7.2)
+ <tcaption>Format of Messages Passed between Nodes (before ERTS 5.7.2 (OTP R13B))
</tcaption>
</table>
@@ -963,6 +984,7 @@ DiB == gen_digest(ChA, ICA)?
<tag><c>EXIT</c></tag>
<item>
<p><c>{3, FromPid, ToPid, Reason}</c></p>
+ <p>This signal is sent when a link has been broken</p>
</item>
<tag><c>UNLINK</c></tag>
<item>
@@ -985,6 +1007,7 @@ DiB == gen_digest(ChA, ICA)?
<tag><c>EXIT2</c></tag>
<item>
<p><c>{8, FromPid, ToPid, Reason}</c></p>
+ <p>This signal is sent by a call to the erlang:exit/2 bif</p>
</item>
</taglist>
</section>
@@ -1007,7 +1030,7 @@ DiB == gen_digest(ChA, ICA)?
<p><c>{16, FromPid, Unused, ToName, TraceToken}</c></p>
<p>Followed by <c>Message</c>.</p>
<p><c>Unused</c> is kept for backward compatibility.</p>
- </item>
+ </item>
<tag><c>EXIT2_TT</c></tag>
<item>
<p><c>{18, FromPid, ToPid, TraceToken, Reason}</c></p>
@@ -1061,7 +1084,7 @@ DiB == gen_digest(ChA, ICA)?
<p><c>{22, FromPid, ToPid}</c></p>
<p>Followed by <c>Message</c>.</p>
<p>
- This control messages replace the <c>SEND</c> control
+ This control message replaces 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.
@@ -1080,7 +1103,7 @@ DiB == gen_digest(ChA, ICA)?
<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
+ This control message replaces 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.
@@ -1097,4 +1120,72 @@ DiB == gen_digest(ChA, ICA)?
</taglist>
</section>
+ <section>
+ <title>New Ctrlmessages for Erlang/OTP 22</title>
+ <note><p>
+ Messages encoded before the connection has
+ been set up may still use the non-PAYLOAD variant.
+ However, once a PAYLOAD control message has been sent,
+ no more non-PAYLOAD control messages will be sent in
+ the same direction on the connection.
+ </p></note>
+ <taglist>
+ <tag><c>PAYLOAD_EXIT</c></tag>
+ <item>
+ <p><c>{24, FromPid, ToPid}</c></p>
+ <p>Followed by <c>Reason</c>.</p>
+ <p>
+ This control message replaces the <c>EXIT</c> control
+ message and will be sent when the distribution flag
+ <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_EXIT_PAYLOAD</c></seealso>
+ has been negotiated in the connection setup handshake.
+ </p>
+ </item>
+ <tag><c>PAYLOAD_EXIT_TT</c></tag>
+ <item>
+ <p><c>{25, FromPid, ToPid}</c></p>
+ <p>Followed by <c>Reason</c>.</p>
+ <p>
+ This control message replaces the <c>EXIT_TT</c> control
+ message and will be sent when the distribution flag
+ <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_EXIT_PAYLOAD</c></seealso>
+ has been negotiated in the connection setup handshake.
+ </p>
+ </item>
+ <tag><c>PAYLOAD_EXIT2</c></tag>
+ <item>
+ <p><c>{26, FromPid, ToPid}</c></p>
+ <p>Followed by <c>Reason</c>.</p>
+ <p>
+ This control message replaces the <c>EXIT2</c> control
+ message and will be sent when the distribution flag
+ <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_EXIT_PAYLOAD</c></seealso>
+ has been negotiated in the connection setup handshake.
+ </p>
+ </item>
+ <tag><c>PAYLOAD_EXIT2_TT</c></tag>
+ <item>
+ <p><c>{27, FromPid, ToPid}</c></p>
+ <p>Followed by <c>Reason</c>.</p>
+ <p>
+ This control message replaces the <c>EXIT2_TT</c> control
+ message and will be sent when the distribution flag
+ <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_EXIT_PAYLOAD</c></seealso>
+ has been negotiated in the connection setup handshake.
+ </p>
+ </item>
+ <tag><c>PAYLOAD_MONITOR_P_EXIT</c></tag>
+ <item>
+ <p><c>{28, FromPid, ToPid, Ref}</c></p>
+ <p>Followed by <c>Reason</c>.</p>
+ <p>
+ This control message replaces the <c>MONITOR_P_EXIT</c> control
+ message and will be sent when the distribution flag
+ <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_EXIT_PAYLOAD</c></seealso>
+ has been negotiated in the connection setup handshake.
+ </p>
+ </item>
+ </taglist>
+ </section>
+
</chapter>
diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml
index 58678f2393..3e2d3bb447 100644
--- a/erts/doc/src/erl_driver.xml
+++ b/erts/doc/src/erl_driver.xml
@@ -230,7 +230,7 @@
<item>
<p>With these functions, the driver sends data back to the emulator.
The data is received as messages by the port owner process, see
- <seealso marker="erlang:open_port/2">
+ <seealso marker="erlang#open_port/2">
<c>erlang:open_port/2</c></seealso>. The vector function and the
function taking a driver binary are faster, as they avoid
copying the data buffer. There is also a fast way of sending
@@ -1154,27 +1154,27 @@ r = driver_async(myPort, &myKey, myData, myFunc); ]]></code>
<taglist>
<tag><seealso marker="driver_entry#start">
<c>start</c></seealso></tag>
- <item>Called from <seealso marker="erlang:open_port/2">
+ <item>Called from <seealso marker="erlang#open_port/2">
<c>erlang:open_port/2</c></seealso>.</item>
<tag><seealso marker="driver_entry#output">
<c>output</c></seealso></tag>
- <item>Called from <seealso marker="erlang:send/2">
+ <item>Called from <seealso marker="erlang#send/2">
<c>erlang:send/2</c></seealso> and
- <seealso marker="erlang:port_command/2">
+ <seealso marker="erlang#port_command/2">
<c>erlang:port_command/2</c></seealso>.</item>
<tag><seealso marker="driver_entry#outputv">
<c>outputv</c></seealso></tag>
- <item>Called from <seealso marker="erlang:send/2">
+ <item>Called from <seealso marker="erlang#send/2">
<c>erlang:send/2</c></seealso> and
- <seealso marker="erlang:port_command/2">
+ <seealso marker="erlang#port_command/2">
<c>erlang:port_command/2</c></seealso>.</item>
<tag><seealso marker="driver_entry#control">
<c>control</c></seealso></tag>
- <item>Called from <seealso marker="erlang:port_control/3">
+ <item>Called from <seealso marker="erlang#port_control/3">
<c>erlang:port_control/3</c></seealso>.</item>
<tag><seealso marker="driver_entry#call">
<c>call</c></seealso></tag>
- <item>Called from <seealso marker="erlang:port_call/3">
+ <item>Called from <seealso marker="erlang#port_call/3">
<c>erlang:port_call/3</c></seealso>.</item>
</taglist>
<p>Notice that this function is <em>not</em> thread-safe, not
@@ -2305,7 +2305,7 @@ r = driver_async(myPort, &myKey, myData, myFunc); ]]></code>
<c>*value_size</c> has been set to the buffer size needed.</p>
<warning>
<p>This function reads the emulated environment used by
- <seealso marker="os:getenv/1"><c>os:getenv/1</c></seealso> and not
+ <seealso marker="kernel: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;
@@ -2656,7 +2656,7 @@ erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0]
</note>
<warning>
<p>This function modifies the emulated environment used by
- <seealso marker="os:putenv/2"><c>os:putenv/2</c></seealso> and not
+ <seealso marker="kernel: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;
@@ -2849,7 +2849,7 @@ erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0]
<desc>
<marker id="erl_drv_set_os_pid"></marker>
<p>Sets the <c>os_pid</c> seen when doing
- <seealso marker="erlang:port_info/2">
+ <seealso marker="erlang#port_info/2">
<c>erlang:port_info/2</c></seealso> on this port.</p>
<p><c>port</c> is the port handle of the port (driver instance) to set
the pid on. <c>pid</c>is the pid to set.</p>
@@ -3204,7 +3204,7 @@ erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0]
<c>control</c></seealso> driver entry
function will return data to the port owner process.
(The <c>control</c> function is called from
- <seealso marker="erlang:port_control/3">
+ <seealso marker="erlang#port_control/3">
<c>erlang:port_control/3</c></seealso>.)</p>
<p>Currently there are only two meaningful values for
<c>flags</c>: <c>0</c> means that data is returned in a list,
diff --git a/erts/doc/src/erl_ext_dist.xml b/erts/doc/src/erl_ext_dist.xml
index 5813af1d57..3730f0e8ac 100644
--- a/erts/doc/src/erl_ext_dist.xml
+++ b/erts/doc/src/erl_ext_dist.xml
@@ -136,172 +136,370 @@
</note>
</section>
- <section>
+ <section>
+ <marker id="distribution_header"/>
<title>Distribution Header</title>
<p>
- <marker id="distribution_header"/>
- As from ERTS 5.7.2 the old atom cache protocol was
- dropped and a new one was introduced. This protocol
- introduced the distribution header. Nodes with an ERTS version
- earlier than 5.7.2 can still communicate with new nodes,
- but no distribution header and no atom cache are used.</p>
- <p>
- The distribution header only contains an atom cache
- reference section, but can in the future contain more
- information. The distribution header precedes one or more Erlang
- terms on the external format. For more information, see the
- documentation of the
+ The distribution header is sent by the erlang distribution to
+ carry metadata about the coming
+ <seealso marker="erl_dist_protocol#control_message">control message</seealso>
+ and potential payload. It is primarily used to handle the atom cache
+ in the Erlang distribution. Since OTP-22 it is also used to fragment
+ large distribution messages into multiple smaller fragments.
+ For more information about how the distribution uses the distribution header,
+ see the documentation of the
<seealso marker="erl_dist_protocol#connected_nodes">protocol between
connected nodes</seealso> in the
<seealso marker="erl_dist_protocol">distribution protocol</seealso>
documentation.
</p>
<p>
- <seealso marker="#ATOM_CACHE_REF">ATOM_CACHE_REF</seealso>
+ Any <seealso marker="#ATOM_CACHE_REF">ATOM_CACHE_REF</seealso>
entries with corresponding <c>AtomCacheReferenceIndex</c> in terms
encoded on the external format following a distribution header refer
to the atom cache references made in the distribution header. The range
is 0 &lt;= <c>AtomCacheReferenceIndex</c> &lt; 255, that is, at most 255
different atom cache references from the following terms can be made.
</p>
- <p>
- The distribution header format is as follows:
- </p>
- <table align="left">
- <row>
- <cell align="center">1</cell>
- <cell align="center">1</cell>
- <cell align="center">1</cell>
- <cell align="center">NumberOfAtomCacheRefs/2+1 | 0</cell>
- <cell align="center">N | 0</cell>
- </row>
- <row>
- <cell align="center"><c>131</c></cell>
- <cell align="center"><c>68</c></cell>
- <cell align="center"><c>NumberOfAtomCacheRefs</c></cell>
- <cell align="center"><c>Flags</c></cell>
- <cell align="center"><c>AtomCacheRefs</c></cell>
- </row>
- <tcaption>Distribution Header Format</tcaption></table>
- <p>
- <c>Flags</c> consist of <c>NumberOfAtomCacheRefs/2+1</c> bytes,
- unless <c>NumberOfAtomCacheRefs</c> is <c>0</c>. If
- <c>NumberOfAtomCacheRefs</c> is <c>0</c>, <c>Flags</c> and
- <c>AtomCacheRefs</c> are omitted. Each atom cache reference has
- a half byte flag field. Flags corresponding to a specific
- <c>AtomCacheReferenceIndex</c> are located in flag byte number
- <c>AtomCacheReferenceIndex/2</c>. Flag byte 0 is the first byte
- after the <c>NumberOfAtomCacheRefs</c> byte. Flags for an even
- <c>AtomCacheReferenceIndex</c> are located in the least significant
- half byte and flags for an odd <c>AtomCacheReferenceIndex</c> are
- located in the most significant half byte.
- </p>
- <p>
- The flag field of an atom cache reference has the following
- format:
- </p>
- <table align="left">
- <row>
- <cell align="center">1 bit</cell>
- <cell align="center">3 bits</cell>
- </row>
- <row>
- <cell align="center"><c>NewCacheEntryFlag</c></cell>
- <cell align="center"><c>SegmentIndex</c></cell>
- </row>
- <tcaption></tcaption></table>
- <p>
- The most significant bit is the <c>NewCacheEntryFlag</c>. If set,
- the corresponding cache reference is new. The three least
- significant bits are the <c>SegmentIndex</c> of the corresponding
- atom cache entry. An atom cache consists of 8 segments, each of size
- 256, that is, an atom cache can contain 2048 entries.
- </p>
- <p>
- After flag fields for atom cache references, another half byte flag
- field is located with the following format:
- </p>
- <table align="left">
- <row>
- <cell align="center">3 bits</cell>
- <cell align="center">1 bit</cell>
- </row>
- <row>
- <cell align="center"><c>CurrentlyUnused</c></cell>
- <cell align="center"><c>LongAtoms</c></cell>
- </row>
- <tcaption></tcaption></table>
- <p>
- The least significant bit in that half byte is flag <c>LongAtoms</c>.
- If it is set, 2 bytes are used for atom lengths instead of
- 1 byte in the distribution header.
- </p>
- <p>
- After the <c>Flags</c> field follow the <c>AtomCacheRefs</c>. The
- first <c>AtomCacheRef</c> is the one corresponding to
- <c>AtomCacheReferenceIndex</c> 0. Higher indices follow
- in sequence up to index <c>NumberOfAtomCacheRefs - 1</c>.
- </p>
- <p>
- If the <c>NewCacheEntryFlag</c> for the next <c>AtomCacheRef</c> has
- been set, a <c>NewAtomCacheRef</c> on the following format follows:
- </p>
- <table align="left">
- <row>
- <cell align="center">1</cell>
- <cell align="center">1 | 2</cell>
- <cell align="center">Length</cell>
- </row>
- <row>
- <cell align="center"><c>InternalSegmentIndex</c></cell>
- <cell align="center"><c>Length</c></cell>
- <cell align="center"><c>AtomText</c></cell>
- </row>
- <tcaption></tcaption></table>
- <p>
- <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c>
- completely identify the location of an atom cache entry in the
- atom cache. <c>Length</c> is the number of bytes that <c>AtomText</c>
- consists of. Length is a 2 byte big-endian integer
- if flag <c>LongAtoms</c> has been set, otherwise a 1 byte
- integer. When distribution flag
- <seealso marker="erl_dist_protocol#dflags">
- <c>DFLAG_UTF8_ATOMS</c></seealso>
- has been exchanged between both nodes in the
- <seealso marker="erl_dist_protocol#distribution_handshake">
- distribution handshake</seealso>,
- characters in <c>AtomText</c> are encoded in UTF-8, otherwise
- in Latin-1. The following <c>CachedAtomRef</c>s with the same
- <c>SegmentIndex</c> and <c>InternalSegmentIndex</c> as this
- <c>NewAtomCacheRef</c> refer to this atom until a new
- <c>NewAtomCacheRef</c> with the same <c>SegmentIndex</c>
- and <c>InternalSegmentIndex</c> appear.
- </p>
- <p>
- For more information on encoding of atoms, see the
- <seealso marker="#utf8_atoms">note on UTF-8 encoded atoms</seealso>
- in the beginning of this section.
- </p>
- <p>
- If the <c>NewCacheEntryFlag</c> for the next <c>AtomCacheRef</c>
- has not been set, a <c>CachedAtomRef</c> on the following format
- follows:
- </p>
- <table align="left">
- <row>
- <cell align="center">1</cell>
- </row>
- <row>
- <cell align="center"><c>InternalSegmentIndex</c></cell>
- </row>
- <tcaption></tcaption></table>
- <p>
- <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c>
- identify the location of the atom cache entry in the atom cache.
- The atom corresponding to this <c>CachedAtomRef</c> is the
- latest <c>NewAtomCacheRef</c> preceding this <c>CachedAtomRef</c>
- in another previously passed distribution header.
- </p>
+ <section>
+ <title>Normal Distribution Header</title>
+ <p>
+ The non-fragmented distribution header format is as follows:
+ </p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ <cell align="center">1</cell>
+ <cell align="center">1</cell>
+ <cell align="center">NumberOfAtomCacheRefs/2+1 | 0</cell>
+ <cell align="center">N | 0</cell>
+ </row>
+ <row>
+ <cell align="center"><c>131</c></cell>
+ <cell align="center"><c>68</c></cell>
+ <cell align="center"><c>NumberOfAtomCacheRefs</c></cell>
+ <cell align="center"><c>Flags</c></cell>
+ <cell align="center"><c>AtomCacheRefs</c></cell>
+ </row>
+ <tcaption>Normal Distribution Header Format</tcaption></table>
+ <p>
+ <c>Flags</c> consist of <c>NumberOfAtomCacheRefs/2+1</c> bytes,
+ unless <c>NumberOfAtomCacheRefs</c> is <c>0</c>. If
+ <c>NumberOfAtomCacheRefs</c> is <c>0</c>, <c>Flags</c> and
+ <c>AtomCacheRefs</c> are omitted. Each atom cache reference has
+ a half byte flag field. Flags corresponding to a specific
+ <c>AtomCacheReferenceIndex</c> are located in flag byte number
+ <c>AtomCacheReferenceIndex/2</c>. Flag byte 0 is the first byte
+ after the <c>NumberOfAtomCacheRefs</c> byte. Flags for an even
+ <c>AtomCacheReferenceIndex</c> are located in the least significant
+ half byte and flags for an odd <c>AtomCacheReferenceIndex</c> are
+ located in the most significant half byte.
+ </p>
+ <p>
+ The flag field of an atom cache reference has the following
+ format:
+ </p>
+ <table align="left">
+ <row>
+ <cell align="center">1 bit</cell>
+ <cell align="center">3 bits</cell>
+ </row>
+ <row>
+ <cell align="center"><c>NewCacheEntryFlag</c></cell>
+ <cell align="center"><c>SegmentIndex</c></cell>
+ </row>
+ <tcaption></tcaption></table>
+ <p>
+ The most significant bit is the <c>NewCacheEntryFlag</c>. If set,
+ the corresponding cache reference is new. The three least
+ significant bits are the <c>SegmentIndex</c> of the corresponding
+ atom cache entry. An atom cache consists of 8 segments, each of size
+ 256, that is, an atom cache can contain 2048 entries.
+ </p>
+ <p>
+ After flag fields for atom cache references, another half byte flag
+ field is located with the following format:
+ </p>
+ <table align="left">
+ <row>
+ <cell align="center">3 bits</cell>
+ <cell align="center">1 bit</cell>
+ </row>
+ <row>
+ <cell align="center"><c>CurrentlyUnused</c></cell>
+ <cell align="center"><c>LongAtoms</c></cell>
+ </row>
+ <tcaption></tcaption></table>
+ <p>
+ The least significant bit in that half byte is flag <c>LongAtoms</c>.
+ If it is set, 2 bytes are used for atom lengths instead of
+ 1 byte in the distribution header.
+ </p>
+ <p>
+ After the <c>Flags</c> field follow the <c>AtomCacheRefs</c>. The
+ first <c>AtomCacheRef</c> is the one corresponding to
+ <c>AtomCacheReferenceIndex</c> 0. Higher indices follow
+ in sequence up to index <c>NumberOfAtomCacheRefs - 1</c>.
+ </p>
+ <p>
+ If the <c>NewCacheEntryFlag</c> for the next <c>AtomCacheRef</c> has
+ been set, a <c>NewAtomCacheRef</c> on the following format follows:
+ </p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ <cell align="center">1 | 2</cell>
+ <cell align="center">Length</cell>
+ </row>
+ <row>
+ <cell align="center"><c>InternalSegmentIndex</c></cell>
+ <cell align="center"><c>Length</c></cell>
+ <cell align="center"><c>AtomText</c></cell>
+ </row>
+ <tcaption></tcaption></table>
+ <p>
+ <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c>
+ completely identify the location of an atom cache entry in the
+ atom cache. <c>Length</c> is the number of bytes that <c>AtomText</c>
+ consists of. Length is a 2 byte big-endian integer
+ if flag <c>LongAtoms</c> has been set, otherwise a 1 byte
+ integer. When distribution flag
+ <seealso marker="erl_dist_protocol#dflags">
+ <c>DFLAG_UTF8_ATOMS</c></seealso>
+ has been exchanged between both nodes in the
+ <seealso marker="erl_dist_protocol#distribution_handshake">
+ distribution handshake</seealso>,
+ characters in <c>AtomText</c> are encoded in UTF-8, otherwise
+ in Latin-1. The following <c>CachedAtomRef</c>s with the same
+ <c>SegmentIndex</c> and <c>InternalSegmentIndex</c> as this
+ <c>NewAtomCacheRef</c> refer to this atom until a new
+ <c>NewAtomCacheRef</c> with the same <c>SegmentIndex</c>
+ and <c>InternalSegmentIndex</c> appear.
+ </p>
+ <p>
+ For more information on encoding of atoms, see the
+ <seealso marker="#utf8_atoms">note on UTF-8 encoded atoms</seealso>
+ in the beginning of this section.
+ </p>
+ <p>
+ If the <c>NewCacheEntryFlag</c> for the next <c>AtomCacheRef</c>
+ has not been set, a <c>CachedAtomRef</c> on the following format
+ follows:
+ </p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ </row>
+ <row>
+ <cell align="center"><c>InternalSegmentIndex</c></cell>
+ </row>
+ <tcaption></tcaption></table>
+ <p>
+ <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c>
+ identify the location of the atom cache entry in the atom cache.
+ The atom corresponding to this <c>CachedAtomRef</c> is the
+ latest <c>NewAtomCacheRef</c> preceding this <c>CachedAtomRef</c>
+ in another previously passed distribution header.
+ </p>
+ </section>
+ <section>
+ <marker id="fragments"/>
+ <title>Distribution Header for fragmented messages</title>
+ <p>Messages sent between Erlang nodes can sometimes be
+ quite large. Since OTP-22 it is possible to split large messages
+ into smaller fragments in order to allow smaller messages to be interleaved
+ between larges messages. It is only the <c>message</c> part of each
+ <seealso marker="erl_dist_protocol#connected_nodes">distributed message</seealso>
+ that may be split using fragmentation. Therefore it is recommended to use the
+ <seealso marker="erl_dist_protocol#new-ctrlmessages-for-erlang-otp-22">
+ PAYLOAD control messages</seealso> introduced in OTP-22.
+ </p>
+ <p>Fragmented distribution messages are only used if the receiving node
+ signals that it supports them via the
+ <seealso marker="erl_dist_protocol#dflags">DFLAG_FRAGMENTS</seealso> distribution
+ flag.</p>
+ <p>A process must complete the sending of a fragmented message before it
+ can start sending any other message on the same distribution channel.</p>
+
+ <p>The start of a sequence of fragmented messages looks like this:</p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ <cell align="center">1</cell>
+ <cell align="center">8</cell>
+ <cell align="center">8</cell>
+ <cell align="center">1</cell>
+ <cell align="center">NumberOfAtomCacheRefs/2+1 | 0</cell>
+ <cell align="center">N | 0</cell>
+ </row>
+ <row>
+ <cell align="center"><c>131</c></cell>
+ <cell align="center"><c>69</c></cell>
+ <cell align="center"><c>SequenceId</c></cell>
+ <cell align="center"><c>FragmentId</c></cell>
+ <cell align="center"><c>NumberOfAtomCacheRefs</c></cell>
+ <cell align="center"><c>Flags</c></cell>
+ <cell align="center"><c>AtomCacheRefs</c></cell>
+ </row>
+ <tcaption>Starting Fragmented Distribution Header Format</tcaption>
+ </table>
+
+ <p>The continuation of a sequence of fragmented messages looks like this:</p>
+ <table align="left">
+ <row>
+ <cell align="center">1</cell>
+ <cell align="center">1</cell>
+ <cell align="center">8</cell>
+ <cell align="center">8</cell>
+ </row>
+ <row>
+ <cell align="center"><c>131</c></cell>
+ <cell align="center"><c>70</c></cell>
+ <cell align="center"><c>SequenceId</c></cell>
+ <cell align="center"><c>FragmentId</c></cell>
+ </row>
+ <tcaption>Continuing Fragmented Distribution Header Format</tcaption>
+ </table>
+
+ <p>
+ The starting distribution header is very similar to a non-fragmented distribution
+ header. The atom cache works the same as for normal distribution header and
+ is the same for the entire sequence. The additional fields added are the
+ sequence id and fragment id.
+ </p>
+
+ <taglist>
+ <tag>Sequence ID</tag>
+ <item>
+ <p>
+ The sequence id is used to uniquely identify a fragmented message sent
+ from one process to another on the same distributed connection. This is used
+ to identify which sequence a fragment is a part of as the same process can
+ be in the process of receiving multiple sequences at the same time.
+ </p>
+ <p>
+ As one process can only be sending one fragmented message at once,
+ it can be convenient to use the local PID as the sequence id.
+ </p>
+ </item>
+ <tag>Fragments ID</tag>
+ <item>
+ <p>
+ The Fragment ID is used to number the fragments in a sequence.
+ The id starts at the total number of fragments and then decrements to 1
+ (which is the final fragment). So if a sequence consists of 3 fragments
+ the fragment id in the starting header will be 3, and then fragments 2 and 1
+ are sent.
+ </p>
+ <p>
+ The fragments must be delivered in the correct order, so if an unordered
+ distribution carrier is used, they must be ordered before delivered to the
+ Erlang run-time.
+ </p>
+ </item>
+ </taglist>
+
+ <section>
+ <title>Example:</title>
+ <p>
+ As an example, let say that we want to send
+ <c>{call, &lt;0.245.2>, {set_get_state, &lt;&lt;0:1024>>}}</c> to
+ registered process <c>reg</c> using a fragment size of 128. To send
+ this message we need a distribution header, atom cache updates,
+ the control message (which would be <c>{6, &lt;0.245.2>, [], reg}</c> in this case)
+ and finally the actual message. This would all be encoded into:
+ </p>
+
+ <code>
+131,69,0,0,2,168,0,0,5,83,0,0,0,0,0,0,0,2, %% Header with seq and frag id
+5,4,137,9,10,5,236,3,114,101,103,9,4,99,97,108,108, %% Atom cache updates
+238,13,115,101,116,95,103,101,116,95,115,116,97,116,101,
+104,4,97,6,103,82,0,0,0,0,85,0,0,0,0,2,82,1,82,2, %% Control message
+104,3,82,3,103,82,0,0,0,0,245,0,0,0,2,2, %% Actual message using cached atoms
+104,2,82,4,109,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+131,70,0,0,2,168,0,0,5,83,0,0,0,0,0,0,0,1, %% Cont Header with seq and frag id
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, %% Rest of payload
+0,0,0,0</code>
+
+ <p>
+ Let us break that apart into its components. First we have the
+ distribution header tags together with the sequence id and
+ a fragment id of 2.
+ </p>
+ <code>
+131,69, %% Start fragment header
+0,0,2,168,0,0,5,83, %% The sequence ID
+0,0,0,0,0,0,0,2, %% The fragment ID
+</code>
+ <p>Then we have the updates to the atom cache:</p>
+ <code>
+5,4,137,9, %% 5 atoms and their flags
+10,5, %% The already cached atom ids
+236,3,114,101,103, %% The atom 'reg'
+9,4,99,97,108,108, %% The atom 'call'
+238,13,115,101,116,95,103,101,116,95,115,116,97,116,101, %% The atom 'set_get_state'
+ </code>
+ <p>
+ The first byte says that we have 5 atoms that are part
+ of the cache. Then follows three bytes that are the
+ atom cache ref flags. Each of the flags uses 4 bits so
+ they are a bit hard to read in decimal byte form. In
+ binary half-byte form they look like this:
+ </p>
+ <code>0000, 0100, 1000, 1001, 1001</code>
+ <p>
+ As the high bit of the first two atoms in the
+ cache are not set we know that they are already in the cache,
+ so they do not have to be sent again (this is the node name of the
+ receiving and sending node). Then follows the atoms that have to be sent,
+ together with their segment ids.
+ </p>
+ <p>
+ Then the listing of the atoms comes, starting with 10 and 5
+ which are the atom refs of the already cached atoms. Then the
+ new atoms are sent.
+ </p>
+ <p>
+ When the atom cache is setup correctly the control message is sent.
+ </p>
+ <code>104,4,97,6,103,82,0,0,0,0,85,0,0,0,0,2,82,1,82,2,</code>
+ <p>
+ Note that up until here it is not allowed to fragments the message.
+ The entire atom cache and control message has to be part of the
+ starting fragment. After the control message the payload of the message
+ is sent using 128 bytes:
+ </p>
+ <code>
+104,3,82,3,103,82,0,0,0,0,245,0,0,0,2,2,
+104,2,82,4,109,0,0,0,128,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ </code>
+ <p>
+ Since the payload is larger than 128-bytes it is split into two
+ fragments. The second fragment does not have any atom cache update
+ instructions so it is a lot simpler:
+ </p>
+ <code>
+131,70,0,0,2,168,0,0,5,83,0,0,0,0,0,0,0,1, %% Continuation dist header 70 with seq and frag id
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, %% remaining payload
+0,0,0,0
+ </code>
+ <note>
+ <p>
+ The fragment size of 128 is only used as an example.
+ Any fragments size may be used when sending fragmented messages.
+ </p>
+ </note>
+ </section>
+ </section>
</section>
<section>
@@ -373,8 +571,9 @@
</row>
<tcaption>FLOAT_EXT</tcaption></table>
<p>
- A float is stored in string format. The format used in sprintf to
- format the float is "%.20e"
+ A finite float (i.e. not inf, -inf or NaN) is stored in
+ string format. The format used in sprintf to format the
+ float is "%.20e"
(there are more bytes allocated than necessary).
To unpack the float, use sscanf with format "%lf".
</p>
@@ -1100,7 +1299,8 @@
</row>
<tcaption>NEW_FLOAT_EXT</tcaption></table>
<p>
- A float is stored as 8 bytes in big-endian IEEE format.
+ A finite float (i.e. not inf, -inf or NaN) is stored as 8 bytes
+ in big-endian IEEE format.
</p>
<p>
This term is used in minor version 1 of the external format.
diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml
index 5cbeddabd9..c0be715678 100644
--- a/erts/doc/src/erl_nif.xml
+++ b/erts/doc/src/erl_nif.xml
@@ -546,8 +546,8 @@ int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail,
<p>Many operations communicating with a process executing a
dirty NIF can, however, complete while it executes the
dirty NIF. For example, retrieving information about it through
- <seealso marker="erlang:process_info/1">
- <c>erlang:process_info</c></seealso>, setting its group leader,
+ <seealso marker="erlang#process_info/1">
+ <c>process_info</c></seealso>, setting its group leader,
register/unregister its name, and so on.</p>
<p>Termination of a process executing a dirty NIF can only be
completed up to a certain point while it executes the dirty NIF.
@@ -783,14 +783,16 @@ typedef struct {
<p>A process identifier (pid). In contrast to pid terms (instances of
<c>ERL_NIF_TERM</c>), <c>ErlNifPid</c>s are self-contained and not
bound to any <seealso marker="#ErlNifEnv">environment</seealso>.
- <c>ErlNifPid</c> is an opaque type.</p>
+ <c>ErlNifPid</c> is an opaque type. It can be copied, moved
+ in memory, forgotten, and so on.</p>
</item>
<tag><marker id="ErlNifPort"/><c>ErlNifPort</c></tag>
<item>
<p>A port identifier. In contrast to port ID terms (instances of
<c>ERL_NIF_TERM</c>), <c>ErlNifPort</c>s are self-contained and not
bound to any <seealso marker="#ErlNifEnv">environment</seealso>.
- <c>ErlNifPort</c> is an opaque type.</p>
+ <c>ErlNifPort</c> is an opaque type. It can be copied, moved
+ in memory, forgotten, and so on.</p>
</item>
<tag><marker id="ErlNifResourceType"/><c>ErlNifResourceType</c></tag>
<item>
@@ -1088,6 +1090,20 @@ typedef struct {
</func>
<func>
+ <name since="OTP @OTP-15011@"><ret>int</ret>
+ <nametext>enif_compare_pids(const ErlNifPid *pid1, const ErlNifPid *pid2)
+ </nametext></name>
+ <fsummary>Compare two pids.</fsummary>
+ <desc>
+ <p>Compares two <seealso marker="#ErlNifPid"><c>ErlNifPid</c>
+ </seealso>s according to term order.</p>
+ <p>Returns <c>0</c> if <c>pid1</c> and <c>pid2</c> are equal,
+ &lt; <c>0</c> if <c>pid1</c> &lt; <c>pid2</c>, and
+ &gt; <c>0</c> if <c>pid1</c> &gt; <c>pid2</c>.</p>
+ </desc>
+ </func>
+
+ <func>
<name since="OTP R13B04"><ret>void</ret>
<nametext>enif_cond_broadcast(ErlNifCond *cnd)</nametext></name>
<fsummary></fsummary>
@@ -1392,6 +1408,9 @@ enif_free_iovec(iovec);]]></code>
initializes the pid variable <c>*pid</c> from it and returns
<c>true</c>. Otherwise returns <c>false</c>. No check is done to see
if the process is alive.</p>
+ <note><p><c>enif_get_local_pid</c> will return false if argument
+ <c>term</c> is the atom <seealso marker="#enif_make_pid">
+ <c>undefined</c></seealso>.</p></note>
</desc>
</func>
@@ -1871,6 +1890,17 @@ enif_inspect_iovec(env, max_elements, term, &amp;tail, &amp;iovec);
</func>
<func>
+ <name since="OTP @OTP-15011@"><ret>int</ret>
+ <nametext>enif_is_pid_undefined(const ErlNifPid* pid)</nametext></name>
+ <fsummary>Determine if pid is undefined.</fsummary>
+ <desc>
+ <p>Returns <c>true</c> if <c>pid</c> has been set as undefined by
+ <seealso marker="#enif_set_pid_undefined"><c>enif_set_pid_undefined</c>
+ </seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
<name since="OTP R13B04"><ret>int</ret>
<nametext>enif_is_port(ErlNifEnv* env, ERL_NIF_TERM term)</nametext>
</name>
@@ -2217,6 +2247,18 @@ enif_inspect_iovec(env, max_elements, term, &amp;tail, &amp;iovec);
</func>
<func>
+ <name since="OTP @OTP-15362@"><ret>ERL_NIF_TERM</ret>
+ <nametext>enif_make_monitor_term(ErlNifEnv* env, const ErlNifMonitor* mon)</nametext></name>
+ <fsummary>Make monitor term from the given monitor identifier.</fsummary>
+ <desc>
+ <p>Creates a term identifying the given monitor received from
+ <seealso marker="#enif_monitor_process"><c>enif_monitor_process</c>
+ </seealso>.</p>
+ <p>This function is primarily intended for debugging purpose.</p>
+ </desc>
+ </func>
+
+ <func>
<name since="OTP R14B"><ret>unsigned char *</ret><nametext>enif_make_new_binary(ErlNifEnv*
env, size_t size, ERL_NIF_TERM* termp)</nametext></name>
<fsummary>Allocate and create a new binary term.</fsummary>
@@ -2247,7 +2289,8 @@ enif_inspect_iovec(env, max_elements, term, &amp;tail, &amp;iovec);
</name>
<fsummary>Make a pid term.</fsummary>
<desc>
- <p>Makes a pid term from <c>*pid</c>.</p>
+ <p>Makes a pid term or the atom <seealso marker="#enif_set_pid_undefined">
+ <c>undefined</c></seealso> from <c>*pid</c>.</p>
</desc>
</func>
@@ -2613,7 +2656,9 @@ enif_map_iterator_destroy(env, &amp;iter);</code>
<p>Argument <c>caller_env</c> is the environment of the calling process
or callback. Must only be NULL if calling from a custom thread.</p>
<p>Returns <c>0</c> on success, &lt; 0 if no <c>down</c> callback is
- provided, and &gt; 0 if the process is no longer alive.</p>
+ provided, and &gt; 0 if the process is no longer alive or if
+ <c>target_pid</c> is <seealso marker="#enif_set_pid_undefined">
+ undefined</seealso>.</p>
<p>This function is only thread-safe when the emulator with SMP support
is used. It can only be used in a non-SMP emulator from a NIF-calling
thread.</p>
@@ -3056,13 +3101,21 @@ enif_map_iterator_destroy(env, &amp;iter);</code>
<p>Argument <c>mode</c> describes the type of events to wait for. It can be
<c>ERL_NIF_SELECT_READ</c>, <c>ERL_NIF_SELECT_WRITE</c> or a bitwise
OR combination to wait for both. It can also be <c>ERL_NIF_SELECT_STOP</c>
- which is described further below. When a read or write event is triggered,
+ or <c>ERL_NIF_SELECT_CANCEL</c> which are described further
+ below. When a read or write event is triggered,
a notification message like this is sent to the process identified by
<c>pid</c>:</p>
<code type="none">{select, Obj, Ref, ready_input | ready_output}</code>
<p><c>ready_input</c> or <c>ready_output</c> indicates if the event object
is ready for reading or writing.</p>
- <p>Argument <c>pid</c> may be <c>NULL</c> to indicate the calling process.</p>
+ <note><p>For complete control over the message format use the newer functions
+ <seealso marker="#enif_select_read"><c>enif_select_read</c></seealso> or
+ <seealso marker="#enif_select_write"><c>enif_select_write</c></seealso>
+ introduced in erts-11.0 (OTP-22.0).</p>
+ </note>
+ <p>Argument <c>pid</c> may be <c>NULL</c> to indicate the calling
+ process. It must not be set as <seealso marker="#enif_set_pid_undefined">
+ undefined</seealso>.</p>
<p>Argument <c>obj</c> is a resource object obtained from
<seealso marker="#enif_alloc_resource"><c>enif_alloc_resource</c></seealso>.
The purpose of the resource objects is as a container of the event object
@@ -3073,17 +3126,29 @@ enif_map_iterator_destroy(env, &amp;iter);</code>
or the atom <c>undefined</c>. It will be passed as <c>Ref</c> in the notifications.
If a selective <c>receive</c> statement is used to wait for the notification
then a reference created just before the <c>receive</c> will exploit a runtime
- optimization that bypasses all earlier received messages in the queue.</p>
+ optimization that bypasses all earlier received messages in the
+ queue.</p>
<p>The notifications are one-shot only. To receive further notifications of the same
type (read or write), repeated calls to <c>enif_select</c> must be made
after receiving each notification.</p>
+ <p><c>ERL_NIF_SELECT_CANCEL</c> can be used to cancel previously
+ selected events. It must be used in a bitwise OR combination with
+ <c>ERL_NIF_SELECT_READ</c> and/or <c>ERL_NIF_SELECT_WRITE</c> to
+ indicate which type of event to cancel. Arguments <c>pid</c> and
+ <c>ref</c> are ignored when <c>ERL_NIF_SELECT_CANCEL</c> is specified.
+ The return value will tell if the event was actualy cancelled or if a
+ notification may already have been sent.</p>
<p>Use <c>ERL_NIF_SELECT_STOP</c> as <c>mode</c> in order to safely
close an event object that has been passed to <c>enif_select</c>. The
<seealso marker="#ErlNifResourceStop"><c>stop</c></seealso> callback
of the resource <c>obj</c> will be called when it is safe to close
the event object. This safe way of closing event objects must be used
- even if all notifications have been received and no further calls to
- <c>enif_select</c> have been made.</p>
+ even if all notifications have been received (or cancelled) and no
+ further calls to <c>enif_select</c> have been made.
+ <c>ERL_NIF_SELECT_STOP</c> will first cancel any selected events
+ before it calls or schedules the <c>stop</c> callback. Arguments
+ <c>pid</c> and <c>ref</c> are ignored when <c>ERL_NIF_SELECT_STOP</c>
+ is specified.</p>
<p>The first call to <c>enif_select</c> for a specific OS <c>event</c> will establish
a relation between the event object and the containing resource. All subsequent calls
for an <c>event</c> must pass its containing resource as argument
@@ -3105,7 +3170,15 @@ enif_map_iterator_destroy(env, &amp;iter);</code>
<item>The stop callback was called directly by <c>enif_select</c>.</item>
<tag><c>ERL_NIF_SELECT_STOP_SCHEDULED</c></tag>
<item>The stop callback was scheduled to run on some other thread
- or later by this thread.</item>
+ or later by this thread.</item>
+ <tag><c>ERL_NIF_SELECT_READ_CANCELLED</c></tag>
+ <item>A read event was cancelled by <c>ERL_NIF_SELECT_CANCEL</c> or
+ <c>ERL_NIF_SELECT_STOP</c> and is guaranteed not to generate a
+ <c>ready_input</c> notification message.</item>
+ <tag><c>ERL_NIF_SELECT_WRITE_CANCELLED</c></tag>
+ <item>A write event was cancelled by <c>ERL_NIF_SELECT_CANCEL</c> or
+ <c>ERL_NIF_SELECT_STOP</c> and is guaranteed not to generate a
+ <c>ready_output</c> notification message.</item>
</taglist>
<p>Returns a negative value if the call failed where the following bits can be set:</p>
<taglist>
@@ -3131,6 +3204,43 @@ if (retval &amp; ERL_NIF_SELECT_STOP_CALLED) {
}
</code>
</note>
+ <note><p>The mode flag <c>ERL_NIF_SELECT_CANCEL</c> and the return flags
+ <c>ERL_NIF_SELECT_READ_CANCELLED</c> and
+ <c>ERL_NIF_SELECT_WRITE_CANCELLED</c> were introduced in erts-11.0
+ (OTP-22.0).</p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name since="OTP 22.0"><ret>int</ret>
+ <nametext>enif_select_read(ErlNifEnv* env, ErlNifEvent event, void* obj,
+ const ErlNifPid* pid, ERL_NIF_TERM msg, ErlNifEnv* msg_env)</nametext>
+ </name>
+ <name since="OTP 22.0"><ret>int</ret>
+ <nametext>enif_select_write(ErlNifEnv* env, ErlNifEvent event, void* obj,
+ const ErlNifPid* pid, ERL_NIF_TERM msg, ErlNifEnv* msg_env)</nametext>
+ </name>
+ <fsummary>Manage subscription on IO event.</fsummary>
+ <desc>
+ <p>These are variants of <seealso marker="#enif_select">enif_select</seealso>
+ where you can supply your own message term <c>msg</c> that will be sent to
+ the process instead of the predefined tuple <c>{select,_,_,_}.</c></p>
+ <p>Argument <c>msg_env</c> must either be <c>NULL</c> or the environment of
+ <c>msg</c> allocated with <seealso marker="#enif_alloc_env">
+ <c>enif_alloc_env</c></seealso>. If argument <c>msg_env</c> is
+ <c>NULL</c> the term <c>msg</c> will be copied, otherwise both
+ <c>msg</c> and <c>msg_env</c> will be invalidated by a successful call
+ to <c>enif_select_read</c> or <c>enif_select_write</c>. The environment
+ is then to either be freed with <seealso marker="#enif_free_env">
+ <c>enif_free_env</c></seealso> or cleared for reuse with
+ <seealso marker="#enif_clear_env"><c>enif_clear_env</c></seealso>. An
+ unsuccessful call will leave <c>msg</c> and <c>msg_env</c> still valid.</p>
+ <p>Apart from the message format <c>enif_select_read</c> and
+ <c>enif_select_write</c> behaves exactly the same as <seealso
+ marker="#enif_select">enif_select</seealso> with argument <c>mode</c> as
+ either <c>ERL_NIF_SELECT_READ</c> or <c>ERL_NIF_SELECT_WRITE</c>. To
+ cancel or close events use <seealso marker="#enif_select">enif_select</seealso>.</p>
</desc>
</func>
@@ -3179,8 +3289,9 @@ if (retval &amp; ERL_NIF_SELECT_STOP_CALLED) {
<c>msg</c>) is invalidated by a successful call to <c>enif_send</c>.
The environment is to either be freed with
<seealso marker="#enif_free_env">
- <c>enif_free_env</c></seealso> of cleared for reuse with
- <seealso marker="#enif_clear_env"><c>enif_clear_env</c></seealso>.</p>
+ <c>enif_free_env</c></seealso> or cleared for reuse with
+ <seealso marker="#enif_clear_env"><c>enif_clear_env</c></seealso>. An
+ unsuccessful call will leave <c>msg</c> and <c>msg_env</c> still valid.</p>
<p>If <c>msg_env</c> is set to <c>NULL</c>, the <c>msg</c> term is
copied and the original term and its environment is still valid after
the call.</p>
@@ -3195,6 +3306,17 @@ if (retval &amp; ERL_NIF_SELECT_STOP_CALLED) {
</func>
<func>
+ <name since="OTP @OTP-15011@"><ret>void</ret>
+ <nametext>enif_set_pid_undefined(ErlNifPid* pid)</nametext></name>
+ <fsummary>Set pid as undefined.</fsummary>
+ <desc>
+ <p>Sets an <seealso marker="#ErlNifPid"><c>ErlNifPid</c></seealso>
+ variable as undefined. See <seealso marker="#enif_is_pid_undefined">
+ <c>enif_is_pid_undefined</c></seealso>.</p>
+ </desc>
+ </func>
+
+ <func>
<name since="OTP R13B04"><ret>unsigned</ret>
<nametext>enif_sizeof_resource(void* obj)</nametext></name>
<fsummary>Get the byte size of a resource object.</fsummary>
@@ -3247,6 +3369,48 @@ if (retval &amp; ERL_NIF_SELECT_STOP_CALLED) {
</func>
<func>
+ <name since="OTP @OTP-15640@"><ret>ErlNifTermType</ret>
+ <nametext>enif_term_type(ErlNifEnv *env, ERL_NIF_TERM term)</nametext>
+ </name>
+ <fsummary>Determine the type of a term.</fsummary>
+ <desc>
+ <p>Determines the type of the given term. The term must be an ordinary
+ Erlang term and not one of the special terms returned by
+ <seealso marker="#enif_raise_exception">
+ <c>enif_raise_exception</c></seealso>,
+ <seealso marker="#enif_schedule_nif">
+ <c>enif_schedule_nif</c></seealso>, or similar.</p>
+ <p>The following types are defined at the moment:</p>
+ <taglist>
+ <tag><c>ERL_NIF_TERM_TYPE_ATOM</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_BITSTRING</c></tag>
+ <item><p>A bitstring or binary</p></item>
+ <tag><c>ERL_NIF_TERM_TYPE_FLOAT</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_FUN</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_INTEGER</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_LIST</c></tag>
+ <item><p>A list, empty or not</p></item>
+ <tag><c>ERL_NIF_TERM_TYPE_MAP</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_PID</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_PORT</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_REFERENCE</c></tag>
+ <item/>
+ <tag><c>ERL_NIF_TERM_TYPE_TUPLE</c></tag>
+ <item/>
+ </taglist>
+ <p>Note that new types may be added in the future, so the caller must
+ be prepared to handle unknown types.</p>
+ </desc>
+ </func>
+
+ <func>
<name since="OTP R13B04"><ret>int</ret>
<nametext>enif_thread_create(char *name,ErlNifTid
*tid,void * (*func)(void *),void *args,ErlNifThreadOpts
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 6932b18571..2b444ccf01 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -126,7 +126,7 @@
instance.</p>
<p>One can get an approximation of the <c>native</c>
time unit by calling
- <seealso marker="erlang:convert_time_unit/3">
+ <seealso marker="#convert_time_unit/3">
<c>erlang:convert_time_unit(1, second, native)</c></seealso>.
The result equals the number
of whole <c>native</c> time units per second. If
@@ -1269,6 +1269,42 @@ end</code>
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>
+ <p>The returned value when there are data available depends
+ on the value of the <c>get_size</c> option configured on the
+ distribution channel identified by <c><anno>DHandle</anno></c>.
+ For more information see the documentation of the <c>get_size</c>
+ option for the
+ <seealso marker="#dist_ctrl_set_opt/3"><c>erlang:dist_ctrl_set_opt/3</c></seealso>
+ function.</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_opt" arity="2" clause_i="1" since="OTP @OTP-15617@"/>
+ <fsummary>Get value of the get_size option on a distribution channel</fsummary>
+ <desc>
+ <p>Returns the value of the <c>get_size</c> option on the distribution channel
+ identified by <c><anno>DHandle</anno></c>. For more information see the
+ documentation of the <c>get_size</c> option for the
+ <seealso marker="#dist_ctrl_set_opt/3"><c>erlang:dist_ctrl_set_opt/3</c></seealso>
+ function.</p>
<note><p>
Only the process registered as distribution
controller for the distribution channel identified by
@@ -1392,6 +1428,55 @@ end</code>
</func>
<func>
+ <name name="dist_ctrl_set_opt" arity="3" clause_i="1" since="OTP @OTP-15617@"/>
+ <fsummary>Set value of the get_size option on a distribution channel</fsummary>
+ <desc>
+ <p>Sets the value of the <c>get_size</c> option on the distribution channel
+ identified by <c><anno>DHandle</anno></c>. This option controls the return
+ value of calls to
+ <seealso marker="#dist_ctrl_get_data/1">erlang:dist_ctrl_get_data(<anno>DHandle</anno>)</seealso>
+ where <c><anno>DHandle</anno></c> equals <c><anno>DHandle</anno></c> used
+ when setting this option.
+ When the <c>get_size</c> option is:</p>
+ <taglist>
+ <tag><c>false</c></tag>
+ <item>
+ and there are distribution data available, a call to
+ <c>erlang:dist_ctrl_get_data(<anno>DHandle</anno>)</c>
+ will just return <c>Data</c> to pass over the channel.
+ This is the default value of the <c>get_size</c> option.
+ </item>
+ <tag><c>true</c></tag>
+ <item>
+ and there are distribution data available, a call to
+ <c>erlang:dist_ctrl_get_data(<anno>DHandle</anno>)</c>
+ will return <c>Data</c> to pass over the channel as well as
+ the <c>Size</c> of <c>Data</c> in bytes. This is returned as
+ a tuple on the form <c>{Size, Data}</c>.
+ </item>
+ </taglist>
+ <p>All options are set to default when a channel is closed.</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="element" arity="2" since=""/>
<fsummary>Return the Nth element of a tuple.</fsummary>
<type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc>
@@ -1751,6 +1836,10 @@ true</pre>
<item>
<p><c>Pid</c> is the process identifier of the process
that originally created the fun.</p>
+ <p>It might point to the <c>init</c> process if the
+ <c>Fun</c> was statically allocated when module was
+ loaded (this optimisation is performed for local
+ functions that do not capture the enviornment).</p>
</item>
<tag><c>{index, Index}</c></tag>
<item>
@@ -4574,6 +4663,7 @@ RealSystem = system + MissedSystem</code>
<name name="port_info" arity="2" clause_i="6" since="OTP R16B"/>
<fsummary>Information about the memory size of a port.</fsummary>
<desc>
+ <marker id="port_info_memory"/>
<p><c><anno>Bytes</anno></c> is the total number of
bytes allocated for this port by the runtime system. The
port itself can have allocated memory that is not
@@ -5206,11 +5296,13 @@ RealSystem = system + MissedSystem</code>
changed or removed without prior notice.</p>
</item>
<tag><c>{current_function, {<anno>Module</anno>,
- <anno>Function</anno>, Arity}}</c></tag>
+ <anno>Function</anno>, Arity} | undefined}</c></tag>
<item>
<p><c><anno>Module</anno></c>, <c><anno>Function</anno></c>,
<c><anno>Arity</anno></c> is
- the current function call of the process.</p>
+ the current function call of the process. The value
+ <c>undefined</c> can be returned if the process is
+ currently executing native compiled code.</p>
</item>
<tag><c>{current_location, {<anno>Module</anno>,
<anno>Function</anno>, <anno>Arity</anno>,
@@ -5296,6 +5388,7 @@ RealSystem = system + MissedSystem</code>
</item>
<tag><c>{memory, <anno>Size</anno>}</c></tag>
<item>
+ <marker id="process_info_memory"/>
<p><c><anno>Size</anno></c> is the size in bytes of the process.
This includes call stack, heap, and internal structures.</p>
</item>
@@ -6585,7 +6678,7 @@ lists:map(
<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. See
- <seealso marker="erts:erl#+async_thread_pool_size">erl +A</seealso> for more details.</item>
+ <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>
diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml
index a094217959..962bc9a244 100644
--- a/erts/doc/src/erts_alloc.xml
+++ b/erts/doc/src/erts_alloc.xml
@@ -487,11 +487,10 @@
utilization value used. Once a carrier is abandoned, no new
allocations are made in it. When an allocator instance gets an
increased multiblock carrier need, it first tries to fetch an
- abandoned carrier from an allocator instance of the same
- allocator type. If no abandoned carrier can be fetched, it
- creates a new empty carrier. When an abandoned carrier has been
- fetched, it will function as an ordinary carrier. This feature has
- special requirements on the
+ abandoned carrier from another allocator instance. If no abandoned
+ carrier can be fetched, it creates a new empty carrier. When an
+ abandoned carrier has been fetched, it will function as an ordinary
+ carrier. This feature has special requirements on the
<seealso marker="#M_as">allocation strategy</seealso> used. Only
the strategies <c>aoff</c>, <c>aoffcbf</c>, <c>aoffcaobf</c>,
<c>ageffcaoff</c>m, <c>ageffcbf</c> and <c>ageffcaobf</c>
@@ -584,7 +583,7 @@
carriers are decided in section
<seealso marker="#mseg_mbc_sizes">
The alloc_util Framework</seealso>. On
- 32-bit Unix style OS this limit cannot be set &gt; 128 MB.</p>
+ 32-bit Unix style OS this limit cannot be set &gt; 64 MB.</p>
</item>
<tag><marker id="M_mbcgs"/><c><![CDATA[+M<S>mbcgs <ratio>]]></c></tag>
<item>
diff --git a/erts/doc/src/internal.xml b/erts/doc/src/internal.xml
new file mode 100644
index 0000000000..88609d492a
--- /dev/null
+++ b/erts/doc/src/internal.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE part SYSTEM "part.dtd">
+
+<internal xmlns:xi="http://www.w3.org/2001/XInclude">
+ <header>
+ <copyright>
+ <year>2018</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>ERTS Internal Documentation</title>
+ <prepared>Lukas Larsson</prepared>
+ <docno></docno>
+ <date>2018-07-07</date>
+ <rev>4.5.2</rev>
+ <file>internal.xml</file>
+ </header>
+ <xi:include href="CarrierMigration.xml"/>
+ <xi:include href="ThreadProgress.xml"/>
+ <xi:include href="CodeLoading.xml"/>
+ <xi:include href="Tracing.xml"/>
+ <xi:include href="DelayedDealloc.xml"/>
+ <xi:include href="beam_makeops.xml"/>
+ <xi:include href="CountingInstructions.xml"/>
+ <xi:include href="GarbageCollection.xml"/>
+ <xi:include href="PTables.xml"/>
+ <xi:include href="PortSignals.xml"/>
+ <xi:include href="ProcessManagementOptimizations.xml"/>
+ <xi:include href="SuperCarrier.xml"/>
+</internal>
diff --git a/erts/doc/src/net.xml b/erts/doc/src/net.xml
new file mode 100644
index 0000000000..b9e2cffce9
--- /dev/null
+++ b/erts/doc/src/net.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2018</year><year>2018</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>net</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>net.xml</file>
+ </header>
+ <module since="OTP @OTP-14831@">net</module>
+ <modulesummary>Network interface.</modulesummary>
+ <description>
+ <p>This module provides an API for the network interface.</p>
+ <note>
+ <p>There is currently <em>no</em> support for Windows. </p>
+ </note>
+ </description>
+
+ <datatypes>
+ <datatype>
+ <name name="address_info"/>
+ </datatype>
+ <datatype>
+ <name name="name_info"/>
+ </datatype>
+ <datatype>
+ <name name="name_info_flags"/>
+ </datatype>
+ <datatype>
+ <name name="name_info_flag"/>
+ </datatype>
+ <datatype>
+ <name name="name_info_flag_ext"/>
+ </datatype>
+ <datatype>
+ <name name="network_interface_name"/>
+ </datatype>
+ <datatype>
+ <name name="network_interface_index"/>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+ <func>
+ <name name="gethostname" arity="0"/>
+ <fsummary>Get hostname.</fsummary>
+ <desc>
+ <p>Returns the name of the current host.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="getnameinfo" arity="1" since="OTP @OTP-14831@"/>
+ <name name="getnameinfo" arity="2" since="OTP @OTP-14831@"/>
+ <fsummary>Address-to-name transaltion.</fsummary>
+ <desc>
+ <p>Address-to-name translation in a protocol-independant manner.</p>
+ <p>This function is the inverse of
+ <seealso marker="#getaddrinfo/1"><c>getaddrinfo</c></seealso>.
+ It converts a socket address to a corresponding host and service.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="getaddrinfo" arity="1" since="OTP @OTP-14831@"/>
+ <name name="getaddrinfo" arity="2" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="getaddrinfo" arity="2" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="getaddrinfo" arity="2" clause_i="3" since="OTP @OTP-14831@"/>
+ <fsummary>Network address and service transation.</fsummary>
+ <desc>
+ <p>Network address and service translation.</p>
+ <p>This function is the inverse of
+ <seealso marker="#getnameinfo/1"><c>getnameinfo</c></seealso>.
+ It converts host and service to a corresponding socket address.</p>
+ <p>One of the <c>Host</c> and <c>Service</c> may be <c>undefined</c>
+ but <em>not</em> both.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="if_name2index" arity="1" since="OTP @OTP-14831@"/>
+ <fsummary>Mappings between network interface names and indexes.</fsummary>
+ <desc>
+ <p>Mappings between network interface names and indexes.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="if_index2name" arity="1" since="OTP @OTP-14831@"/>
+ <fsummary>Mappings between network interface index and names.</fsummary>
+ <desc>
+ <p>Mappings between network interface index and names.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="if_names" arity="0" since="OTP @OTP-14831@"/>
+ <fsummary>Get network interface names and indexes.</fsummary>
+ <desc>
+ <p>Get network interface names and indexes.</p>
+ </desc>
+ </func>
+
+ </funcs>
+
+</erlref>
+
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index cc44b2f4cc..f0f97a6775 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -8477,8 +8477,7 @@
Erlang/OTP has been ported to the realtime operating
system OSE. The port supports both smp and non-smp
emulator. For details around the port and how to started
- see the User's Guide in the <seealso
- marker="ose:ose_intro">ose</seealso> application. </p>
+ see the User's Guide in the <em>ose</em> application.</p>
<p>
Note that not all parts of Erlang/OTP has been ported. </p>
<p>
@@ -9584,9 +9583,9 @@
<c>fix_alloc</c> allocator, a different strategy for
management of fix blocks will be used.</item> <item>The
information returned from <seealso
- marker="erlang:system_info_allocator_tuple"><c>erlang:system_info({allocator,
+ marker="erlang#system_info_allocator_tuple"><c>erlang:system_info({allocator,
A})</c></seealso>, and <seealso
- marker="erlang:system_info_allocator_sizes"><c>erlang:system_info({allocator_sizes,
+ marker="erlang#system_info_allocator_sizes"><c>erlang:system_info({allocator_sizes,
A})</c></seealso> will be slightly different when this
feature has been enabled. An <c>mbcs_pool</c> tuple will
be present giving information about abandoned carriers,
@@ -10395,8 +10394,7 @@
information about signal ordering guarantees, see the
chapter on <seealso
marker="erts:communication">communication</seealso> in
- the ERTS user's guide. The <seealso
- marker="erts:erl#+n">+n</seealso> command line flag of
+ the ERTS user's guide. The <c>+n</c> command line flag of
<seealso marker="erts:erl">erl(1)</seealso> can be
helpful when trying to find signaling order bugs in
Erlang code that have been exposed by these
@@ -11375,7 +11373,7 @@
you use erlang:halt/2 with an integer first argument and
an option list containing {flush,false} as the second
argument. Note that now is flushing not dependant of the
- exit code, and you can not only flush async threads
+ exit code, and you cannot only flush async threads
operations which we deemed as a strange behaviour anyway.
</p>
<p>Also, erlang:halt/1,2 has gotten a new feature: If the
diff --git a/erts/doc/src/part.xml b/erts/doc/src/part.xml
index 05e9a24af8..f0b8a00b90 100644
--- a/erts/doc/src/part.xml
+++ b/erts/doc/src/part.xml
@@ -42,6 +42,7 @@
<xi:include href="tty.xml"/>
<xi:include href="driver.xml"/>
<xi:include href="inet_cfg.xml"/>
+ <xi:include href="socket_usage.xml"/>
<xi:include href="erl_ext_dist.xml"/>
<xi:include href="erl_dist_protocol.xml"/>
</part>
diff --git a/erts/doc/src/persistent_term.xml b/erts/doc/src/persistent_term.xml
index 9d3c9afd80..672b00a83a 100644
--- a/erts/doc/src/persistent_term.xml
+++ b/erts/doc/src/persistent_term.xml
@@ -121,19 +121,6 @@
</section>
<section>
- <title>Warning For Many Persistent Terms</title>
- <p>The runtime system will send a warning report to the
- error logger if more than 20000 persistent terms have been
- created. It will look like this:</p>
-
-<pre>
-More than 20000 persistent terms have been created.
-It is recommended to avoid creating an excessive number of
-persistent terms, as creation and deletion of persistent terms
-will be slower as the number of persistent terms increases.</pre>
- </section>
-
- <section>
<title>Best Practices for Using Persistent Terms</title>
<p>It is recommended to use keys like <c>?MODULE</c> or
diff --git a/erts/doc/src/ref_man.xml b/erts/doc/src/ref_man.xml
index a78aaa449e..80cdcf9145 100644
--- a/erts/doc/src/ref_man.xml
+++ b/erts/doc/src/ref_man.xml
@@ -4,7 +4,7 @@
<application xmlns:xi="http://www.w3.org/2001/XInclude">
<header>
<copyright>
- <year>1996</year><year>2016</year>
+ <year>1996</year><year>2018</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -31,26 +31,28 @@
</header>
<description>
</description>
- <xi:include href="erl_prim_loader.xml"/>
- <xi:include href="erlang.xml"/>
- <xi:include href="init.xml"/>
- <xi:include href="persistent_term.xml"/>
- <xi:include href="zlib.xml"/>
+ <xi:include href="atomics.xml"/>
+ <xi:include href="counters.xml"/>
+ <xi:include href="driver_entry.xml"/>
<xi:include href="epmd.xml"/>
<xi:include href="erl.xml"/>
+ <xi:include href="erlang.xml"/>
<xi:include href="erlc.xml"/>
- <xi:include href="werl.xml"/>
- <xi:include href="escript.xml"/>
- <xi:include href="erlsrv.xml"/>
- <xi:include href="start_erl.xml"/>
- <xi:include href="run_erl.xml"/>
- <xi:include href="start.xml"/>
<xi:include href="erl_driver.xml"/>
- <xi:include href="driver_entry.xml"/>
- <xi:include href="erts_alloc.xml"/>
<xi:include href="erl_nif.xml"/>
+ <xi:include href="erl_prim_loader.xml"/>
+ <xi:include href="erlsrv.xml"/>
<xi:include href="erl_tracer.xml"/>
- <xi:include href="atomics.xml"/>
- <xi:include href="counters.xml"/>
+ <xi:include href="erts_alloc.xml"/>
+ <xi:include href="escript.xml"/>
+ <xi:include href="init.xml"/>
+ <xi:include href="net.xml"/>
+ <xi:include href="persistent_term.xml"/>
+ <xi:include href="run_erl.xml"/>
+ <xi:include href="socket.xml"/>
+ <xi:include href="start.xml"/>
+ <xi:include href="start_erl.xml"/>
+ <xi:include href="werl.xml"/>
+ <xi:include href="zlib.xml"/>
</application>
diff --git a/erts/doc/src/socket.xml b/erts/doc/src/socket.xml
new file mode 100644
index 0000000000..f6195a65b2
--- /dev/null
+++ b/erts/doc/src/socket.xml
@@ -0,0 +1,650 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE erlref SYSTEM "erlref.dtd">
+
+<erlref>
+ <header>
+ <copyright>
+ <year>2018</year><year>2019</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>socket</title>
+ <prepared></prepared>
+ <docno></docno>
+ <date></date>
+ <rev></rev>
+ <file>socket.xml</file>
+ </header>
+ <module since="OTP @OTP-14831@">socket</module>
+ <modulesummary>Socket interface.</modulesummary>
+ <description>
+ <p>This module provides an API for the socket interface.
+ It is used to create, delete and manipulate sockets,
+ send and receive data.</p>
+ <p>The idea is that it shall be as "close as possible" to the OS
+ level socket interface. The only significant addition is that some of
+ the functions,
+ e.g. <seealso marker="#recv/3"><c>recv/3</c></seealso>,
+ has a timeout argument. </p>
+ <note>
+ <p>There is currently <em>no</em> support for Windows. </p>
+ <p>Support for IPv6 has been implemented but <em>not</em> tested. </p>
+ <p>SCTP has only been partly implemented (and not tested). </p>
+ </note>
+ </description>
+
+ <datatypes>
+ <datatype>
+ <name name="domain"/>
+ </datatype>
+ <datatype>
+ <name name="type"/>
+ </datatype>
+ <datatype>
+ <name name="protocol"/>
+ </datatype>
+ <datatype>
+ <name>socket()</name>
+ <desc><p>As returned by
+ <seealso marker="#open/2"><c>open/2,3,4</c></seealso> and
+ <seealso marker="#accept/1"><c>accept/1,2</c></seealso>.</p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="ip4_address"/>
+ </datatype>
+ <datatype>
+ <name name="ip6_address"/>
+ </datatype>
+ <datatype>
+ <name name="ip_address"/>
+ </datatype>
+ <datatype>
+ <name name="sockaddr"/>
+ </datatype>
+ <datatype>
+ <name name="sockaddr_in4"/>
+ </datatype>
+ <datatype>
+ <name name="sockaddr_in6"/>
+ </datatype>
+ <datatype>
+ <name name="sockaddr_un"/>
+ </datatype>
+ <datatype>
+ <name name="port_number"/>
+ </datatype>
+ <datatype>
+ <name name="in6_flow_info"/>
+ </datatype>
+ <datatype>
+ <name name="in6_scope_id"/>
+ </datatype>
+ <datatype>
+ <name name="accept_flags"/>
+ </datatype>
+ <datatype>
+ <name name="accept_flag"/>
+ </datatype>
+ <datatype>
+ <name name="send_flags"/>
+ </datatype>
+ <datatype>
+ <name name="send_flag"/>
+ </datatype>
+ <datatype>
+ <name name="recv_flags"/>
+ </datatype>
+ <datatype>
+ <name name="recv_flag"/>
+ </datatype>
+ <datatype>
+ <name name="shutdown_how"/>
+ </datatype>
+ <datatype>
+ <name name="sockopt_level"/>
+ </datatype>
+ <datatype>
+ <name name="otp_socket_option"/>
+ </datatype>
+ <datatype>
+ <name name="socket_option"/>
+ </datatype>
+ <datatype>
+ <name name="ip_socket_option"/>
+ </datatype>
+ <datatype>
+ <name name="ipv6_socket_option"/>
+ </datatype>
+ <datatype>
+ <name name="tcp_socket_option"/>
+ </datatype>
+ <datatype>
+ <name name="udp_socket_option"/>
+ </datatype>
+ <datatype>
+ <name name="sctp_socket_option"/>
+ </datatype>
+ <datatype>
+ <name name="timeval"/>
+ </datatype>
+ <datatype>
+ <name name="ip_tos"/>
+ </datatype>
+ <datatype>
+ <name name="ip_mreq"/>
+ </datatype>
+ <datatype>
+ <name name="ip_mreq_source"/>
+ </datatype>
+ <datatype>
+ <name name="ip_pmtudisc"/>
+ </datatype>
+ <datatype>
+ <name name="ip_msfilter_mode"/>
+ </datatype>
+ <datatype>
+ <name name="ip_msfilter"/>
+ </datatype>
+ <datatype>
+ <name name="ip_pktinfo"/>
+ </datatype>
+ <datatype>
+ <name name="ipv6_mreq"/>
+ </datatype>
+ <datatype>
+ <name name="ipv6_pmtudisc"/>
+ </datatype>
+ <datatype>
+ <name name="ipv6_pktinfo"/>
+ </datatype>
+ <datatype>
+ <name name="sctp_assoc_id"/>
+ </datatype>
+ <datatype>
+ <name name="sctp_sndrcvinfo"/>
+ </datatype>
+ <datatype>
+ <name name="sctp_event_subscribe"/>
+ </datatype>
+ <datatype>
+ <name name="sctp_assocparams"/>
+ </datatype>
+ <datatype>
+ <name name="sctp_initmsg"/>
+ </datatype>
+ <datatype>
+ <name name="sctp_rtoinfo"/>
+ </datatype>
+ <datatype>
+ <name name="msghdr_flag"/>
+ </datatype>
+ <datatype>
+ <name name="msghdr_flags"/>
+ </datatype>
+ <datatype>
+ <name name="msghdr"/>
+ </datatype>
+ <datatype>
+ <name name="cmsghdr_level"/>
+ </datatype>
+ <datatype>
+ <name name="cmsghdr_type"/>
+ </datatype>
+ <!--
+ <datatype>
+ <name name="cmsghdr_data"/>
+ </datatype>
+ -->
+ <datatype>
+ <name name="cmsghdr_recv"/>
+ </datatype>
+ <datatype>
+ <name name="cmsghdr_send"/>
+ </datatype>
+ <datatype>
+ <name name="uint8"/>
+ </datatype>
+ <datatype>
+ <name name="uint16"/>
+ </datatype>
+ <datatype>
+ <name name="uint20"/>
+ </datatype>
+ <datatype>
+ <name name="uint32"/>
+ </datatype>
+ <datatype>
+ <name name="int32"/>
+ </datatype>
+ <datatype>
+ <name name="supports_options_socket"/>
+ </datatype>
+ <datatype>
+ <name name="supports_options_ip"/>
+ </datatype>
+ <datatype>
+ <name name="supports_options_ipv6"/>
+ </datatype>
+ <datatype>
+ <name name="supports_options_tcp"/>
+ </datatype>
+ <datatype>
+ <name name="supports_options_udp"/>
+ </datatype>
+ <datatype>
+ <name name="supports_options_sctp"/>
+ </datatype>
+ <datatype>
+ <name name="supports_options"/>
+ </datatype>
+ </datatypes>
+
+ <funcs>
+ <func>
+ <name name="accept" arity="1" since="OTP @OTP-14831@"/>
+ <name name="accept" arity="2" since="OTP @OTP-14831@"/>
+ <fsummary>Accept a connection on a socket.</fsummary>
+ <desc>
+ <p>Accept a connection on a socket.</p>
+ <p>This call is used with connection-based socket types
+ (<c>stream</c> or <c>seqpacket</c>). It extracs the first pending
+ connection request for the listen socket and returns the (newly)
+ connected socket.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="bind" arity="2" since="OTP @OTP-14831@"/>
+ <fsummary>Bind a name to a socket.</fsummary>
+ <desc>
+ <p>Bind a name to a socket.</p>
+ <p>When a socket is created
+ (with <seealso marker="#open/2"><c>open</c></seealso>),
+ it has no address assigned to it. <c>bind</c> assigns the
+ address specified by the <c>Addr</c> argument.</p>
+ <p>The rules used for name binding vary between domains.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="close" arity="1" since="OTP @OTP-14831@"/>
+ <fsummary>Close a socket.</fsummary>
+ <desc>
+ <p>Closes the socket.</p>
+
+ <note>
+ <p>Note that for e.g. <c>protocol</c> = <c>tcp</c>, most implementations
+ doing a close does not guarantee that any data sent is delivered to
+ the recipient before the close is detected at the remote side. </p>
+ <p>One way to handle this is to use the
+ <seealso marker="#shutdown/2"><c>shutdown</c></seealso>
+ function
+ (<c>socket:shutdown(Socket, write)</c>) to signal that no more data is
+ to be sent and then wait for the read side of the socket to be closed.</p>
+ </note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="connect" arity="2" since="OTP @OTP-14831@"/>
+ <name name="connect" arity="3" since="OTP @OTP-14831@"/>
+ <fsummary>Initiate a connection on a socket.</fsummary>
+ <desc>
+ <p>This function connects the socket to the address
+ specied by the <c>SockAddr</c> argument.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="getopt" arity="3" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="getopt" arity="3" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="getopt" arity="3" clause_i="3" since="OTP @OTP-14831@"/>
+ <name name="getopt" arity="3" clause_i="4" since="OTP @OTP-14831@"/>
+ <name name="getopt" arity="3" clause_i="5" since="OTP @OTP-14831@"/>
+ <name name="getopt" arity="3" clause_i="6" since="OTP @OTP-14831@"/>
+ <name name="getopt" arity="3" clause_i="7" since="OTP @OTP-14831@"/>
+ <fsummary>Get an option on a socket.</fsummary>
+ <desc>
+ <p>Get an option on a socket.</p>
+ <p>What properties are valid depend both on <c>Level</c> and
+ on what kind of socket it is (<c>domain</c>, <c>type</c> and
+ <c>protocol</c>).</p>
+
+ <p>See the
+ <seealso marker="socket_usage#socket_options">socket options</seealso>
+ chapter of the users guide for more info. </p>
+
+ <note><p>Not all options are valid on all platforms. That is,
+ even if "we" support an option, that does not mean that the
+ underlying OS does.</p></note>
+
+ </desc>
+ </func>
+
+ <func>
+ <name name="getopt" arity="3" clause_i="8" since="OTP @OTP-14831@"/>
+ <fsummary>Get an option on a socket.</fsummary>
+ <desc>
+ <p>Get an option on a socket.</p>
+ <p>What properties are valid depend both on <c>Level</c> and
+ on what kind of socket it is (<c>domain</c>, <c>type</c> and
+ <c>protocol</c>).</p>
+ <p>When specifying <c>Level</c> as an integer, and therefor
+ using "native mode", it is *currently* up to the caller to
+ know how to interpret the result.</p>
+
+ <p>See the
+ <seealso marker="socket_usage#socket_options">socket options</seealso>
+ chapter of the users guide for more info. </p>
+
+ <note><p>Not all options are valid on all platforms. That is,
+ even if "we" support an option, that does not mean that the
+ underlying OS does.</p></note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="listen" arity="1" since="OTP @OTP-14831@"/>
+ <name name="listen" arity="2" since="OTP @OTP-14831@"/>
+ <fsummary>Listen for connections on a socket.</fsummary>
+ <desc>
+ <p>Listen for connections on a socket.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="open" arity="2" since="OTP @OTP-14831@"/>
+ <name name="open" arity="3" since="OTP @OTP-14831@"/>
+ <name name="open" arity="4" since="OTP @OTP-14831@"/>
+ <fsummary>Create an endpoint for communication.</fsummary>
+ <desc>
+ <p>Creates an endpoint (socket) for communication.</p>
+ <p>For some <c>types</c> there is a default protocol, which will
+ be used if no protocol is specified: </p>
+
+ <list>
+ <item><p><c>stream</c>: <c>tcp</c></p></item>
+ <item><p><c>dgram</c>: <c>udp</c></p></item>
+ <item><p><c>seqpacket</c>: <c>sctp</c></p></item>
+ </list>
+
+ <p>The <c>Extra</c> argument is intended for "obscure" options.
+ Currently the only supported option is <c>netns</c>, which
+ is only supported on the linux platform.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="peername" arity="1" since="OTP @OTP-14831@"/>
+ <fsummary>Get name of connected socket peer.</fsummary>
+ <desc>
+ <p>Returns the address of the peer connected to the socket.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="recv" arity="1" since="OTP @OTP-14831@"/>
+ <name name="recv" arity="2" since="OTP @OTP-14831@"/>
+ <name name="recv" arity="3" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="recv" arity="3" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="recv" arity="4" since="OTP @OTP-14831@"/>
+ <fsummary>Receive a message from a socket.</fsummary>
+ <desc>
+ <p>Receive a message from a socket.</p>
+ <p>There is a special case for the argument <c>Length</c>.
+ If it is set to zero (0), it means "give me everything you
+ currently have".</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="recvfrom" arity="1" since="OTP @OTP-14831@"/>
+ <name name="recvfrom" arity="2" since="OTP @OTP-14831@"/>
+ <name name="recvfrom" arity="3" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="recvfrom" arity="3" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="recvfrom" arity="3" clause_i="3" since="OTP @OTP-14831@"/>
+ <name name="recvfrom" arity="4" since="OTP @OTP-14831@"/>
+ <fsummary>Receive a message from a socket.</fsummary>
+ <desc>
+ <p>Receive a message from a socket.</p>
+ <p>This function reads "messages", which means that regardless of
+ how much we want to read, it returns when we get a message.</p>
+ <p>The <c>BufSz</c> argument basically defines the size of the
+ receive buffer. By setting the value to zero (0), the configured
+ size (setopt with <c>Level</c> = <c>otp</c> and <c>Key</c> = <c>rcvbuf</c>)
+ is used.</p>
+ <p>It may be impossible to know what (buffer) size is appropriate
+ "in advance", and in those cases it may be convenient to use the
+ (recv) 'peek' flag. When this flag is provided, the message is *not*
+ "consumed" from the underlying buffers, so another recvfrom call
+ is needed, possibly with a then adjusted buffer size.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="recvmsg" arity="1" since="OTP @OTP-14831@"/>
+ <name name="recvmsg" arity="2" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="recvmsg" arity="2" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="recvmsg" arity="3" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="recvmsg" arity="3" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="recvmsg" arity="5" since="OTP @OTP-14831@"/>
+ <fsummary>Receive a message from a socket.</fsummary>
+ <desc>
+ <p>Receive a message from a socket.</p>
+ <p>This function reads "messages", which means that regardless of
+ how much we want to read, it returns when we get a message.</p>
+ <p>The message will be delivered in the form of a <c>msghdr()</c>,
+ which may contain the source address (if socket not connected),
+ a list of <c>cmsghdr_recv()</c> (depends on what socket options have
+ been set and what the protocol and platform supports) and
+ also a set of flags, providing further info about the read. </p>
+
+ <p>The <c>BufSz</c> argument basically defines the size of the
+ receive buffer. By setting the value to zero (0), the configured
+ size (setopt with <c>Level</c> = <c>otp</c> and <c>Key</c> = <c>rcvbuf</c>)
+ is used.</p>
+
+ <p>The <c>CtrlSz</c> argument basically defines the size of the
+ receive buffer for the control messages.
+ By setting the value to zero (0), the configured size (setopt
+ with <c>Level</c> = <c>otp</c>) is used.</p>
+
+ <p>It may be impossible to know what (buffer) size is appropriate
+ "in advance", and in those cases it may be convenient to use the
+ (recv) 'peek' flag. When this flag is provided, the message is *not*
+ "consumed" from the underlying buffers, so another recvmsg call
+ is needed, possibly with a then adjusted buffer size.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="send" arity="2" since="OTP @OTP-14831@"/>
+ <name name="send" arity="3" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="send" arity="3" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="send" arity="4" since="OTP @OTP-14831@"/>
+ <fsummary>Send a message on a socket.</fsummary>
+ <desc>
+ <p>Send a message on a connected socket.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="sendmsg" arity="2" since="OTP @OTP-14831@"/>
+ <name name="sendmsg" arity="3" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="sendmsg" arity="3" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="sendmsg" arity="4" since="OTP @OTP-14831@"/>
+ <fsummary>Send a message on a socket.</fsummary>
+ <desc>
+ <p>Send a message on a socket. The destination, if needed
+ (socket <em>not</em> connected) is provided in the <c>MsgHdr</c>,
+ which also contains the message to send,
+ The <c>MsgHdr</c> may also contain an list of optional <c>cmsghdr_send()</c>
+ (depends on what the protocol and platform supports).</p>
+
+ <p>Unlike the <seealso marker="#send/2"><c>send</c></seealso> function,
+ this one sends <em>one message</em>.
+ This means that if, for whatever reason, its not possible to send the
+ message in one go, the function will instead return with the
+ <em>remaining</em> data (<c>{ok, Remaining}</c>). Thereby leaving it
+ up to the caller to decide what to do (retry with the remaining data
+ of give up). </p>
+
+ </desc>
+ </func>
+
+ <func>
+ <name name="sendto" arity="3" since="OTP @OTP-14831@"/>
+ <name name="sendto" arity="4" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="sendto" arity="4" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="sendto" arity="5" since="OTP @OTP-14831@"/>
+ <fsummary>Send a message on a socket.</fsummary>
+ <desc>
+ <p>Send a message on a socket, to the specified destination.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="setopt" arity="4" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="setopt" arity="4" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="setopt" arity="4" clause_i="3" since="OTP @OTP-14831@"/>
+ <name name="setopt" arity="4" clause_i="4" since="OTP @OTP-14831@"/>
+ <name name="setopt" arity="4" clause_i="5" since="OTP @OTP-14831@"/>
+ <name name="setopt" arity="4" clause_i="6" since="OTP @OTP-14831@"/>
+ <name name="setopt" arity="4" clause_i="7" since="OTP @OTP-14831@"/>
+ <fsummary>Set options on a socket.</fsummary>
+ <desc>
+ <p>Set options on a socket.</p>
+ <p>What properties are valid depend both on <c>Level</c> and on
+ what kind of socket it is (<c>domain</c>, <c>type</c> and
+ <c>protocol</c>).</p>
+
+ <p>See the
+ <seealso marker="socket_usage#socket_options">socket options</seealso>
+ chapter of the users guide for more info. </p>
+
+ <note><p>Not all options are valid on all platforms. That is,
+ even if "we" support an option, that does not mean that the
+ underlying OS does.</p></note>
+
+ <note><p>Sockets are set 'non-blocking' when created, so this option
+ is *not* available (as it would adversely effect the Erlang VM
+ to set a socket 'blocking').</p></note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="setopt" arity="4" clause_i="8" since="OTP @OTP-14831@"/>
+ <fsummary>Set options on a socket.</fsummary>
+ <desc>
+ <p>Set options on a socket.</p>
+ <p>What properties are valid depend both on <c>Level</c> and on
+ what kind of socket it is (<c>domain</c>, <c>type</c> and
+ <c>protocol</c>).</p>
+
+ <p>See the
+ <seealso marker="socket_usage#socket_options">socket options</seealso>
+ chapter of the users guide for more info. </p>
+
+ <note><p>Not all options are valid on all platforms. That is,
+ even if "we" support an option, that does not mean that the
+ underlying OS does.</p></note>
+
+ <note><p>Sockets are set 'non-blocking' when created, so this option
+ is *not* available (as it would adversely effect the Erlang VM
+ to set a socket 'blocking').</p></note>
+ </desc>
+ </func>
+
+ <func>
+ <name name="shutdown" arity="2" since="OTP @OTP-14831@"/>
+ <fsummary>Shut down part of a full-duplex connection.</fsummary>
+ <desc>
+ <p>Shut down all or part of a full-duplex connection.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="sockname" arity="1" since="OTP @OTP-14831@"/>
+ <fsummary>Get socket name.</fsummary>
+ <desc>
+ <p>Returns the current address to which the socket is bound.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="supports" arity="0" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="1" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="1" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="1" clause_i="3" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="1" clause_i="4" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="2" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="2" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="2" clause_i="3" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="2" clause_i="4" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="2" clause_i="5" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="2" clause_i="6" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="2" clause_i="7" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="3" clause_i="1" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="3" clause_i="2" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="3" clause_i="3" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="3" clause_i="4" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="3" clause_i="5" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="3" clause_i="6" since="OTP @OTP-14831@"/>
+ <name name="supports" arity="3" clause_i="7" since="OTP @OTP-14831@"/>
+ <fsummary>Report info about what the platform supports.</fsummary>
+ <desc>
+ <p>This function intends to retreive information about what the
+ platform supports. Such as if SCTP is supported. Or which socket
+ options are supported. </p>
+ </desc>
+ </func>
+
+ </funcs>
+ <section>
+ <title>Examples</title>
+ <marker id="examples"></marker>
+ <code type="none">
+client(Addr, SAddr, SPort) ->
+ {ok, Sock} = socket:open(inet, stream, tcp),
+ {ok, _} = socket:bind(Sock, #{family => inet,
+ addr => Addr}),
+ ok = socket:connect(Sock, #{family => inet,
+ addr => SAddr,
+ port => SPort}),
+ Msg = list_to_binary("hello"),
+ ok = socket:send(Sock, Msg),
+ ok = socket:shutdown(Sock, write),
+ {ok, Msg} = socket:recv(Sock),
+ ok = socket:close(Sock).
+
+server(Addr, Port) ->
+ {ok, LSock} = socket:open(inet, stream, tcp),
+ {ok, _} = socket:bind(LSock, #{family => inet,
+ port => Port,
+ addr => Addr}),
+ ok = socket:listen(LSock),
+ {ok, Sock} = socket:accept(LSock),
+ {ok, Msg} = socket:recv(Sock),
+ ok = socket:send(Sock, Msg),
+ ok = socket:shutdown(Sock, write),
+ ok = socket:close(Sock),
+ ok = socket:close(LSock).
+ </code>
+ </section>
+</erlref>
+
diff --git a/erts/doc/src/socket_usage.xml b/erts/doc/src/socket_usage.xml
new file mode 100644
index 0000000000..e0f006e618
--- /dev/null
+++ b/erts/doc/src/socket_usage.xml
@@ -0,0 +1,773 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE chapter SYSTEM "chapter.dtd">
+
+<chapter>
+ <header>
+ <copyright>
+ <year>2018</year><year>2019</year>
+ <holder>Ericsson AB. All Rights Reserved.</holder>
+ </copyright>
+ <legalnotice>
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ </legalnotice>
+
+ <title>Socket Usage</title>
+ <prepared>Micael Karlberg</prepared>
+ <docno></docno>
+ <date>2018-07-17</date>
+ <rev>PA1</rev>
+ <file>socket_usage.xml</file>
+ </header>
+
+ <section>
+ <title>Introduction</title>
+ <p>The socket interface (module) is basically an "thin" layer on top of
+ the OS socket interface. It is assumed that, unless you have special needs,
+ gen_[tcp|udp|sctp] should be sufficent. </p>
+ <p>Note that just because we have a documented and described option,
+ it does <em>not</em> mean that the OS supports it. So its recommended
+ that the user reads the platform specific documentation for the
+ option used. </p>
+ </section>
+
+ <section>
+ <marker id="socket_options"></marker>
+ <title>Socket Options</title>
+
+ <p>Options for level <c>otp</c>: </p>
+ <table>
+ <row>
+ <cell><em>Option Name</em></cell>
+ <cell><em>Value Type</em></cell>
+ <cell><em>Set</em></cell>
+ <cell><em>Get</em></cell>
+ <cell><em>Other Requirements and comments</em></cell>
+ </row>
+ <row>
+ <cell>assoc_id</cell>
+ <cell>integer()</cell>
+ <cell>no</cell>
+ <cell>yes</cell>
+ <cell>type = seqpacket, protocol = sctp, is an association</cell>
+ </row>
+ <row>
+ <cell>debug</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>iow</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>controlling_process</cell>
+ <cell>pid()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>rcvbuf</cell>
+ <cell>default | pos_integer() | {pos_integer(), pos_ineteger()}</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>'default' only valid for set.
+ The tuple form is only valid for type 'stream' and protocol 'tcp'.</cell>
+ </row>
+ <row>
+ <cell>rcvctrlbuf</cell>
+ <cell>default | pos_integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>default only valid for set</cell>
+ </row>
+ <row>
+ <cell>sndctrlbuf</cell>
+ <cell>default | pos_integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>default only valid for set</cell>
+ </row>
+ <row>
+ <cell>fd</cell>
+ <cell>integer()</cell>
+ <cell>no</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <tcaption>option levels</tcaption>
+ </table>
+
+ <p>Options for level <c>socket</c>: </p>
+ <table>
+ <row>
+ <cell><em>Option Name</em></cell>
+ <cell><em>Value Type</em></cell>
+ <cell><em>Set</em></cell>
+ <cell><em>Get</em></cell>
+ <cell><em>Other Requirements and comments</em></cell>
+ </row>
+ <row>
+ <cell>acceptcon</cell>
+ <cell>boolean()</cell>
+ <cell>no</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>bindtodevice</cell>
+ <cell>string()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>broadcast</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram</cell>
+ </row>
+ <row>
+ <cell>debug</cell>
+ <cell>integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>requires admin capability</cell>
+ </row>
+ <row>
+ <cell>domain</cell>
+ <cell>domain()</cell>
+ <cell>no</cell>
+ <cell>yes</cell>
+ <cell><em>Not</em> on FreeBSD (for instance)</cell>
+ </row>
+ <row>
+ <cell>dontroute</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>keepalive</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>linger</cell>
+ <cell>abort | linger()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>oobinline</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>peek_off</cell>
+ <cell>integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>domain = local (unix)</cell>
+ </row>
+ <row>
+ <cell>priority</cell>
+ <cell>integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>protocol</cell>
+ <cell>protocol()</cell>
+ <cell>no</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>rcvbuf</cell>
+ <cell>non_neg_integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>rcvlowat</cell>
+ <cell>non_neg_integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>rcvtimeo</cell>
+ <cell>timeval()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>reuseaddr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>reuseport</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>domain = inet | inet6</cell>
+ </row>
+ <row>
+ <cell>sndbuf</cell>
+ <cell>non_neg_integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>sndlowat</cell>
+ <cell>non_neg_integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>not changeable on Linux</cell>
+ </row>
+ <row>
+ <cell>sndtimeo</cell>
+ <cell>timeval()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>timestamp</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>type</cell>
+ <cell>type()</cell>
+ <cell>no</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <tcaption>socket options</tcaption>
+ </table>
+
+ <p>Options for level <c>ip</c>: </p>
+ <table>
+ <row>
+ <cell><em>Option Name</em></cell>
+ <cell><em>Value Type</em></cell>
+ <cell><em>Set</em></cell>
+ <cell><em>Get</em></cell>
+ <cell><em>Other Requirements and comments</em></cell>
+ </row>
+ <row>
+ <cell>add_membership</cell>
+ <cell>ip_mreq()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>add_source_membership</cell>
+ <cell>ip_mreq_source()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>block_source</cell>
+ <cell>ip_mreq_source()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>drop_membership</cell>
+ <cell>ip_mreq()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>drop_source_membership</cell>
+ <cell>ip_mreq_source()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>freebind</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>hdrincl</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = raw</cell>
+ </row>
+ <row>
+ <cell>minttl</cell>
+ <cell>integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = raw</cell>
+ </row>
+ <row>
+ <cell>msfilter</cell>
+ <cell>null | ip_msfilter()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>mtu</cell>
+ <cell>integer()</cell>
+ <cell>no</cell>
+ <cell>yes</cell>
+ <cell>type = raw</cell>
+ </row>
+ <row>
+ <cell>mtu_discover</cell>
+ <cell>ip_pmtudisc()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>multicast_all</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>multicast_if</cell>
+ <cell>any | ip4_address()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>multicast_loop</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>multicast_ttl</cell>
+ <cell>uint8()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>nodefrag</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = raw</cell>
+ </row>
+ <row>
+ <cell>pktinfo</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram</cell>
+ </row>
+ <row>
+ <cell>recvdstaddr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram</cell>
+ </row>
+ <row>
+ <cell>recverr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>recvif</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw</cell>
+ </row>
+ <row>
+ <cell>recvopts</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type =/= stream</cell>
+ </row>
+ <row>
+ <cell>recvorigdstaddr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>recvttl</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type =/= stream</cell>
+ </row>
+ <row>
+ <cell>retopts</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type =/= stream</cell>
+ </row>
+ <row>
+ <cell>router_alert</cell>
+ <cell>integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = raw</cell>
+ </row>
+ <row>
+ <cell>sendsrcaddr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>tos</cell>
+ <cell>ip_tos()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>some high-priority levels may require superuser capability</cell>
+ </row>
+ <row>
+ <cell>transparent</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>requires admin capability</cell>
+ </row>
+ <row>
+ <cell>ttl</cell>
+ <cell>integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>unblock_source</cell>
+ <cell>ip_mreq_source()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <tcaption>ip options</tcaption>
+ </table>
+
+ <p>Options for level <c>ipv6</c>: </p>
+ <table>
+ <row>
+ <cell><em>Option Name</em></cell>
+ <cell><em>Value Type</em></cell>
+ <cell><em>Set</em></cell>
+ <cell><em>Get</em></cell>
+ <cell><em>Other Requirements and comments</em></cell>
+ </row>
+ <row>
+ <cell>addrform</cell>
+ <cell>inet</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>allowed only for IPv6 sockets that are connected and bound to a
+ v4-mapped-on-v6 address</cell>
+ </row>
+ <row>
+ <cell>add_membership</cell>
+ <cell>ipv6_mreq()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>authhdr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw, obsolete?</cell>
+ </row>
+ <row>
+ <cell>drop_membership</cell>
+ <cell>ipv6_mreq()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>dstopts</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw, requires superuser privileges to update</cell>
+ </row>
+ <row>
+ <cell>flowinfo</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw, requires superuser privileges to update</cell>
+ </row>
+ <row>
+ <cell>hoplimit</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw, requires superuser privileges to update</cell>
+ </row>
+ <row>
+ <cell>hopopts</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw, requires superuser privileges to update</cell>
+ </row>
+ <row>
+ <cell>mtu</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>Get: Only after the socket has been connected</cell>
+ </row>
+ <row>
+ <cell>mtu_discover</cell>
+ <cell>ipv6_pmtudisc()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>multicast_hops</cell>
+ <cell>default | uint8()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>multicast_if</cell>
+ <cell>integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw</cell>
+ </row>
+ <row>
+ <cell>multicast_loop</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>recverr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>recvpktinfo | pktinfo</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw</cell>
+ </row>
+ <row>
+ <cell>router_alert</cell>
+ <cell>integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = raw</cell>
+ </row>
+ <row>
+ <cell>rthdr</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>type = dgram | raw, requires superuser privileges to update</cell>
+ </row>
+ <row>
+ <cell>unicast_hops</cell>
+ <cell>default | uint8()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>v6only</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <tcaption>ipv6 options</tcaption>
+ </table>
+
+ <p>Options for level <c>tcp</c>: </p>
+ <table>
+ <row>
+ <cell><em>Option Name</em></cell>
+ <cell><em>Value Type</em></cell>
+ <cell><em>Set</em></cell>
+ <cell><em>Get</em></cell>
+ <cell><em>Other Requirements and comments</em></cell>
+ </row>
+ <row>
+ <cell>congestion</cell>
+ <cell>string()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>maxseg</cell>
+ <cell>integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>nodelay</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <tcaption>tcp options</tcaption>
+ </table>
+
+ <p>Options for level <c>udp</c>: </p>
+ <table>
+ <row>
+ <cell><em>Option Name</em></cell>
+ <cell><em>Value Type</em></cell>
+ <cell><em>Set</em></cell>
+ <cell><em>Get</em></cell>
+ <cell><em>Other Requirements and comments</em></cell>
+ </row>
+ <row>
+ <cell>cork</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <tcaption>udp options</tcaption>
+ </table>
+
+ <p>Options for level <c>sctp</c>: </p>
+ <table>
+ <row>
+ <cell><em>Option Name</em></cell>
+ <cell><em>Value Type</em></cell>
+ <cell><em>Set</em></cell>
+ <cell><em>Get</em></cell>
+ <cell><em>Other Requirements and comments</em></cell>
+ </row>
+ <row>
+ <cell>associnfo</cell>
+ <cell>sctp_assocparams()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>autoclose</cell>
+ <cell>non_neg_integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>disable_fragments</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>events</cell>
+ <cell>sctp_event_subscribe()</cell>
+ <cell>yes</cell>
+ <cell>no</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>initmsg</cell>
+ <cell>sctp_initmsg()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>maxseg</cell>
+ <cell>non_neg_integer()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>nodelay</cell>
+ <cell>boolean()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <row>
+ <cell>rtoinfo</cell>
+ <cell>sctp_rtoinfo()</cell>
+ <cell>yes</cell>
+ <cell>yes</cell>
+ <cell>none</cell>
+ </row>
+ <tcaption>sctp options</tcaption>
+ </table>
+
+ </section>
+</chapter>
+
diff --git a/erts/doc/src/specs.xml b/erts/doc/src/specs.xml
index 0b943e6295..68fab5edf1 100644
--- a/erts/doc/src/specs.xml
+++ b/erts/doc/src/specs.xml
@@ -5,6 +5,8 @@
<xi:include href="../specs/specs_erl_tracer.xml"/>
<xi:include href="../specs/specs_init.xml"/>
<xi:include href="../specs/specs_persistent_term.xml"/>
+ <xi:include href="../specs/specs_socket.xml"/>
+ <xi:include href="../specs/specs_net.xml"/>
<xi:include href="../specs/specs_zlib.xml"/>
<xi:include href="../specs/specs_atomics.xml"/>
<xi:include href="../specs/specs_counters.xml"/>
diff --git a/erts/doc/src/tty.xml b/erts/doc/src/tty.xml
index 51db1ba8e2..c33e082f4f 100644
--- a/erts/doc/src/tty.xml
+++ b/erts/doc/src/tty.xml
@@ -165,6 +165,10 @@ erl</pre>
<cell align="left" valign="middle">C-y</cell>
<cell align="left" valign="middle">Insert previously killed text</cell>
</row>
+ <row>
+ <cell align="left" valign="middle">C-]</cell>
+ <cell align="left" valign="middle">Insert matching closing bracket</cell>
+ </row>
<tcaption>tty Text Editing</tcaption>
</table>
</section>