diff options
Diffstat (limited to 'erts/doc')
-rw-r--r-- | erts/doc/src/absform.xml | 22 | ||||
-rw-r--r-- | erts/doc/src/erl.xml | 115 | ||||
-rw-r--r-- | erts/doc/src/erl_dist_protocol.xml | 11 | ||||
-rw-r--r-- | erts/doc/src/erl_ext_dist.xml | 163 | ||||
-rw-r--r-- | erts/doc/src/erl_nif.xml | 391 | ||||
-rw-r--r-- | erts/doc/src/erl_tracer.xml | 19 | ||||
-rw-r--r-- | erts/doc/src/erlang.xml | 532 | ||||
-rw-r--r-- | erts/doc/src/erts_alloc.xml | 6 | ||||
-rw-r--r-- | erts/doc/src/escript.xml | 24 | ||||
-rw-r--r-- | erts/doc/src/notes.xml | 14 | ||||
-rw-r--r-- | erts/doc/src/zlib.xml | 12 |
11 files changed, 912 insertions, 397 deletions
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml index ab00d47425..e49c8c32e9 100644 --- a/erts/doc/src/absform.xml +++ b/erts/doc/src/absform.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2001</year><year>2016</year> + <year>2001</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -182,10 +182,18 @@ can contain the following:</p> <list type="bulleted"> - <item>Tuples <c>{error,E}</c> and <c>{warning,W}</c>, denoting - syntactically incorrect forms and warnings</item> - <item><c>{eof,LINE}</c>, denoting an end-of-stream - encountered before a complete form had been parsed</item> + <item> + <p>Tuples <c>{error,E}</c> and <c>{warning,W}</c>, denoting + syntactically incorrect forms and warnings. + </p> + </item> + <item> + <p><c>{eof,LOCATION}</c>, denoting an end-of-stream + encountered before a complete form had been parsed. + The word <c>LOCATION</c> represents an integer, and denotes the + number of the last line in the source file. + </p> + </item> </list> </section> </section> @@ -357,7 +365,7 @@ <c>{cons,LINE,Rep(E_h),Rep(E_t)}</c>.</p> </item> <item> - <p>>If E is a fun expression <c>fun Name/Arity</c>, then Rep(E) = + <p>If E is a fun expression <c>fun Name/Arity</c>, then Rep(E) = <c>{'fun',LINE,{function,Name,Arity}}</c>.</p> </item> <item> @@ -886,7 +894,7 @@ Rep(Fc) = <c>[Rep(C_1), ..., Rep(C_k)]</c>.</p> <list type="bulleted"> - <item>If C is a constraint <c>is_subtype(V, T)</c> or <c>V :: T</c>, + <item>If C is a constraint <c>V :: T</c>, where <c>V</c> is a type variable and <c>T</c> is a type, then Rep(C) = <c>{type,LINE,constraint,[{atom,LINE,is_subtype},[Rep(V),Rep(T)]]}</c>. diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index 8da832ac37..638e88ca31 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -4,7 +4,7 @@ <comref> <header> <copyright> - <year>1996</year><year>2016</year> + <year>1996</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -239,6 +239,13 @@ <item> <p>Useful for debugging. Prints the arguments sent to the emulator.</p> </item> + <tag><c><![CDATA[-emu_type Type]]></c></tag> + <item> + <p>Start an emulator of a different type. For example, to start + the lock-counter emualator, use <c>-emu_type lcnt</c>. (The emulator + must already be built. Use the <c>configure</c> option + <c>--enable-lock-counter</c> to build the lock-counter emulator.)</p> + </item> <tag><c><![CDATA[-env Variable Value]]></c></tag> <item> <p>Sets the host OS environment variable <c><![CDATA[Variable]]></c> to @@ -372,6 +379,16 @@ <c><![CDATA[Host]]></c> is the fully qualified host name of the current host. For short names, use flag <c><![CDATA[-sname]]></c> instead.</p> + <warning> + <p> + Starting a distributed node without also specifying + <seealso marker="#proto_dist"><c>-proto_dist inet_tls</c></seealso> + will expose the node to attacks that may give the attacker + complete access to the node and in extension the cluster. + When using un-secure distributed nodes, make sure that the + network is configured to keep potential attackers out. + </p> + </warning> </item> <tag><c><![CDATA[-noinput]]></c></tag> <item> @@ -421,12 +438,17 @@ </item> <tag><c><![CDATA[-proto_dist Proto]]></c></tag> <item> + <marker id="proto_dist"/> <p>Specifies a protocol for Erlang distribution:</p> <taglist> <tag><c>inet_tcp</c></tag> <item>TCP over IPv4 (the default)</item> <tag><c>inet_tls</c></tag> - <item>Distribution over TLS/SSL</item> + <item>Distribution over TLS/SSL, See the + <seealso marker="ssl:ssl_distribution"> + Using SSL for Erlang Distribution</seealso> User's Guide + for details on how to setup a secure distributed node. + </item> <tag><c>inet6_tcp</c></tag> <item>TCP over IPv6</item> </taglist> @@ -490,6 +512,16 @@ exist between nodes running with flag <c><![CDATA[-sname]]></c> and those running with flag <c><![CDATA[-name]]></c>, as node names must be unique in distributed Erlang systems.</p> + <warning> + <p> + Starting a distributed node without also specifying + <seealso marker="#proto_dist"><c>-proto_dist inet_tls</c></seealso> + will expose the node to attacks that may give the attacker + complete access to the node and in extension the cluster. + When using un-secure distributed nodes, make sure that the + network is configured to keep potential attackers out. + </p> + </warning> </item> <tag><marker id="start_epmd"/><c>-start_epmd true | false</c></tag> <item> @@ -513,11 +545,11 @@ system with SMP support is available. <c>-smp auto</c> starts the Erlang runtime system with SMP support enabled if it is available and more than one logical processor is detected. - <c>-smp disable</c> starts a runtime system without SMP support.</p> + <c>-smp disable</c> starts a runtime system without SMP support. + The runtime system without SMP support is deprecated and will + be removed in a future major release.</p> <note> - <p>The runtime system with SMP support is not available on all - supported platforms. See also flag - <seealso marker="#+S"><c>+S</c></seealso>.</p> + <p>See also flag<seealso marker="#+S"><c>+S</c></seealso>.</p> </note> </item> <tag><c><![CDATA[-version]]></c> (emulator flag)</tag> @@ -638,7 +670,7 @@ this value also applies to command-line parameters and environment variables (see section <seealso marker="stdlib:unicode_usage#unicode_in_environment_and_parameters"> - Unicode in Enviroment and Parameters</seealso> in the STDLIB + Unicode in Environment and Parameters</seealso> in the STDLIB User's Guide).</p> </item> <tag><c><![CDATA[+fnu[{w|i|e}]]]></c></tag> @@ -674,7 +706,7 @@ this value also applies to command-line parameters and environment variables (see section <seealso marker="stdlib:unicode_usage#unicode_in_environment_and_parameters"> - Unicode in Enviroment and Parameters</seealso> in the STDLIB + Unicode in Environment and Parameters</seealso> in the STDLIB User's Guide).</p> </item> <tag><c><![CDATA[+fna[{w|i|e}]]]></c></tag> @@ -695,7 +727,7 @@ this value also applies to command-line parameters and environment variables (see section <seealso marker="stdlib:unicode_usage#unicode_in_environment_and_parameters"> - Unicode in Enviroment and Parameters</seealso> in the STDLIB + Unicode in Environment and Parameters</seealso> in the STDLIB User's Guide).</p> </item> <tag><c><![CDATA[+hms Size]]></c></tag> @@ -946,9 +978,7 @@ schedulers was allowed to be unlimited, dirty CPU bound jobs would potentially starve normal jobs.</p> <p>This option is ignored if the emulator does not have threading - support enabled. <em>This option is experimental</em> and - is supported only if the emulator was configured and built with - support for dirty schedulers enabled (it is disabled by default).</p> + support enabled.</p> </item> <tag><marker id="+SDPcpu"/><c><![CDATA[+SDPcpu DirtyCPUSchedulersPercentage:DirtyCPUSchedulersOnlinePercentage]]></c></tag> @@ -974,9 +1004,7 @@ either order) results in 2 dirty CPU scheduler threads (50% of 4) and 1 dirty CPU scheduler thread online (25% of 4).</p> <p>This option is ignored if the emulator does not have threading - support enabled. <em>This option is experimental</em> and - is supported only if the emulator was configured and built with - support for dirty schedulers enabled (it is disabled by default).</p> + support enabled.</p> </item> <tag><marker id="+SDio"/><c><![CDATA[+SDio DirtyIOSchedulers]]></c></tag> <item> @@ -992,9 +1020,7 @@ bound jobs on dirty I/O schedulers, these jobs might starve ordinary jobs executing on ordinary schedulers.</p> <p>This option is ignored if the emulator does not have threading - support enabled. <em>This option is experimental</em> and - is supported only if the emulator was configured and built with - support for dirty schedulers enabled (it is disabled by default).</p> + support enabled.</p> </item> <tag><c><![CDATA[+sFlag Value]]></c></tag> <item> @@ -1324,8 +1350,22 @@ <c><![CDATA[+sss size]]></c></tag> <item> <p>Suggested stack size, in kilowords, for scheduler threads. - Valid range is 4-8192 kilowords. The default stack size is - OS-dependent.</p> + Valid range is 20-8192 kilowords. The default suggested + stack size is 128 kilowords.</p> + </item> + <tag><marker id="dcpu_sched_thread_stack_size"/> + <c><![CDATA[+sssdcpu size]]></c></tag> + <item> + <p>Suggested stack size, in kilowords, for dirty CPU scheduler + threads. Valid range is 20-8192 kilowords. The default + suggested stack size is 40 kilowords.</p> + </item> + <tag><marker id="dio_sched_thread_stack_size"/> + <c><![CDATA[+sssdio size]]></c></tag> + <item> + <p>Suggested stack size, in kilowords, for dirty IO scheduler + threads. Valid range is 20-8192 kilowords. The default + suggested stack size is 40 kilowords.</p> </item> <tag><marker id="+stbt"/><c>+stbt BindType</c></tag> <item> @@ -1513,32 +1553,27 @@ <item> <p><em>Unix systems</em>: This variable gives the number of seconds that the emulator is allowed to spend writing a crash dump. When the - given number of seconds have elapsed, the emulator is terminated by a - <c>SIGALRM</c> signal.</p> - <p>If the variable is <em>not</em> set or set to <c>0</c> seconds - (<c><![CDATA[ERL_CRASH_DUMP_SECONDS=0]]></c>), the runtime system does - not even attempt to write the crash dump file. It only terminates.</p> - <p>If the variable is set to negative value, such as - <c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c>, the runtime system - waits indefinitely for the crash dump file to be written.</p> - <p>This variable is used with <seealso marker="kernel:heart"> - <c>heart(3)</c></seealso> if <c>heart</c> is running:</p> + given number of seconds have elapsed, the emulator is terminated.</p> <taglist> <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=0]]></c></tag> - <item>Suppresses the writing a crash dump file entirely, thus - rebooting the runtime system immediately. This is the same as not - setting the environment variable. + <item>If the variable is set to <c>0</c> seconds, the runtime system does + not even attempt to write the crash dump file. It only terminates. + This is the default if option <c>-heart</c> is passed to <c>erl</c> + and <c>ERL_CRASH_DUMP_SECONDS</c> is not set. + </item> + <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=S]]></c></tag> + <item>If the variable is set to a positive value <c>S</c>, + wait for <c>S</c> seconds to complete the crash dump file and + then terminates the runtime system with a <c>SIGALRM</c> signal. </item> <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c></tag> - <item>Setting the environment variable to a negative value causes the - termination of the runtime system to wait until the crash dump file - has been completly written. - </item> - <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=S]]></c></tag> - <item>Waits for <c>S</c> seconds to complete the crash dump file and - then terminates the runtime system. + <item>A negative value causes the termination of the runtime system + to wait indefinitely until the crash dump file has been completly + written. This is the default if option <c>-heart</c> is <em>not</em> + passed to <c>erl</c> and <c>ERL_CRASH_DUMP_SECONDS</c> is not set. </item> </taglist> + <p>See also <seealso marker="kernel:heart"><c>heart(3)</c></seealso>.</p> </item> <tag><c><![CDATA[ERL_CRASH_DUMP_BYTES]]></c></tag> <item> diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml index ee74983730..8391408a2e 100644 --- a/erts/doc/src/erl_dist_protocol.xml +++ b/erts/doc/src/erl_dist_protocol.xml @@ -70,6 +70,17 @@ <p>The integers in all multibyte fields are in big-endian order.</p> + <warning> + <p> + The Erlang Distribution protocol is not by itself secure and does not + aim to be so. In order to get secure distribution the distributed nodes + should be configured to use distribution over tls. + See the <seealso marker="ssl:ssl_distribution"> + Using SSL for Erlang Distribution</seealso> User's Guide + for details on how to setup a secure distributed node. + </p> + </warning> + <section> <title>EPMD Protocol</title> <p>The requests served by the EPMD are summarized in the following diff --git a/erts/doc/src/erl_ext_dist.xml b/erts/doc/src/erl_ext_dist.xml index 4f799f8f34..b7090d0472 100644 --- a/erts/doc/src/erl_ext_dist.xml +++ b/erts/doc/src/erl_ext_dist.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2007</year> - <year>2016</year> + <year>2017</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -51,7 +51,7 @@ term into the external format. To convert binary data encoding to a term, the BIF <seealso marker="erts:erlang#binary_to_term/1"> - <c>erlang:binary_to_term/1</c>c></seealso> is used. + <c>erlang:binary_to_term/1</c></seealso> is used. </p> <p> The distribution does this implicitly when sending messages across @@ -119,27 +119,18 @@ <tcaption>Compressed Data Format when Expanded</tcaption></table> <marker id="utf8_atoms"/> <note> - <p>As from ERTS 5.10 (OTP R16) support - for UTF-8 encoded atoms has been introduced in the external format. - However, only characters that can be encoded using Latin-1 (ISO-8859-1) - are currently supported in atoms. The support for UTF-8 encoded atoms - in the external format has been implemented to be able to support - all Unicode characters in atoms in <em>some future release</em>. - Until full Unicode support for atoms has been introduced, - it is an <em>error</em> to pass atoms containing - characters that cannot be encoded in Latin-1, and <em>the behavior is - undefined</em>.</p> - <p>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>, all atoms in the distribution header - are encoded in UTF-8, otherwise in Latin-1. The two - new tags <seealso marker="#ATOM_UTF8_EXT"><c>ATOM_UTF8_EXT</c></seealso> - and <seealso marker="#SMALL_ATOM_UTF8_EXT"> - <c>SMALL_ATOM_UTF8_EXT</c></seealso> - are only used if the distribution flag <c>DFLAG_UTF8_ATOMS</c> has - been exchanged between nodes, or if an atom containing characters - that cannot be encoded in Latin-1 is encountered.</p> + <p>As from ERTS 9.0 (OTP 20), atoms may contain any Unicode + characters and are always encoded using the UTF-8 external formats + <seealso marker="#ATOM_UTF8_EXT"><c>ATOM_UTF8_EXT</c></seealso> + or <seealso marker="#SMALL_ATOM_UTF8_EXT"><c>SMALL_ATOM_UTF8_EXT</c></seealso>. + The old Latin-1 formats <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso> + and <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_EXT</c></seealso> + are deprecated and are only kept for backward + compatibility when decoding terms encoded by older nodes.</p> + <p>Support for UTF-8 encoded atoms in the external format has been + available since ERTS 5.10 (OTP R16). This abillity allows such old nodes + to decode, store and encode any Unicode atoms received from a new OTP 20 + node.</p> <p>The maximum number of allowed characters in an atom is 255. In the UTF-8 case, each character can need 4 bytes to be encoded.</p> </note> @@ -395,28 +386,6 @@ </section> <section> - <marker id="ATOM_EXT"/> - <title>ATOM_EXT</title> - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">2</cell> - <cell align="center">Len</cell> - </row> - <row> - <cell align="center"><c>100</c></cell> - <cell align="center"><c>Len</c></cell> - <cell align="center"><c>AtomName</c></cell> - </row> - <tcaption>ATOM_EXT</tcaption></table> - <p> - An atom is stored with a 2 byte unsigned length in big-endian order, - followed by <c>Len</c> numbers of 8-bit Latin-1 characters that forms - the <c>AtomName</c>. The maximum allowed value for <c>Len</c> is 255. - </p> - </section> - - <section> <marker id="REFERENCE_EXT"/> <title>REFERENCE_EXT</title> <table align="left"> @@ -437,8 +406,8 @@ Encodes a reference object (an object generated with <seealso marker="erlang:make_ref/0">erlang:make_ref/0</seealso>). The <c>Node</c> term is an encoded atom, that is, - <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso>, - <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_EXT</c></seealso>, or + <seealso marker="#ATOM_UTF8_EXT"><c>ATOM_UTF8_EXT</c></seealso>, + <seealso marker="#SMALL_ATOM_UTF8_EXT"><c>SMALL_ATOM_UTF8_EXT</c></seealso>, or <seealso marker="#ATOM_CACHE_REF"><c>ATOM_CACHE_REF</c></seealso>. The <c>ID</c> field contains a big-endian unsigned integer, but <em>is to be regarded as uninterpreted data</em>, @@ -777,39 +746,6 @@ </section> <section> - <marker id="SMALL_ATOM_EXT"/> - <title>SMALL_ATOM_EXT</title> - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">1</cell> - <cell align="center">Len</cell> - </row> - <row> - <cell align="center"><c>115</c></cell> - <cell align="center"><c>Len</c></cell> - <cell align="center"><c>AtomName</c></cell> - </row> - <tcaption>SMALL_ATOM_EXT</tcaption></table> - <p> - An atom is stored with a 1 byte unsigned length, - followed by <c>Len</c> numbers of 8-bit Latin-1 characters that - forms the <c>AtomName</c>. Longer atoms can be represented - by <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso>. - </p> - <note> - <p> - <c>SMALL_ATOM_EXT</c> was introduced in ERTS 5.7.2 and - require an exchange of distribution flag - <seealso marker="erl_dist_protocol#dflags"> - <c>DFLAG_SMALL_ATOM_TAGS</c></seealso> in the - <seealso marker="erl_dist_protocol#distribution_handshake"> - distribution handshake</seealso>. - </p> - </note> - </section> - - <section> <marker id="FUN_EXT"/> <title>FUN_EXT</title> <table align="left"> @@ -843,8 +779,8 @@ <tag><c>Module</c></tag> <item> <p>Encoded as an atom, using - <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso>, - <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_EXT</c></seealso>, + <seealso marker="#ATOM_UTF8_EXT"><c>ATOM_UTF8_EXT</c></seealso>, + <seealso marker="#SMALL_ATOM_UTF8_EXT"><c>SMALL_ATOM_UTF8_EXT</c></seealso>, or <seealso marker="#ATOM_CACHE_REF"> <c>ATOM_CACHE_REF</c></seealso>. This is the module that the fun is implemented in. @@ -938,8 +874,8 @@ <tag><c>Module</c></tag> <item> <p>Encoded as an atom, using - <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso>, - <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_EXT</c></seealso>, + <seealso marker="#ATOM_EXT"><c>ATOM_UTF8_EXT</c></seealso>, + <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_UTF8_EXT</c></seealso>, or <seealso marker="#ATOM_CACHE_REF"> <c>ATOM_CACHE_REF</c></seealso>. Is the module that the fun is implemented in. @@ -1001,8 +937,8 @@ </p> <p> <c>Module</c> and <c>Function</c> are atoms - (encoded using <seealso marker="#ATOM_EXT"><c>ATOM_EXT</c></seealso>, - <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_EXT</c></seealso>, or + (encoded using <seealso marker="#ATOM_EXT"><c>ATOM_UTF8_EXT</c></seealso>, + <seealso marker="#SMALL_ATOM_EXT"><c>SMALL_ATOM_UTF8_EXT</c></seealso>, or <seealso marker="#ATOM_CACHE_REF"><c>ATOM_CACHE_REF</c></seealso>). </p> <p> @@ -1114,6 +1050,61 @@ in the beginning of this section. </p> </section> + + <section> + <marker id="ATOM_EXT"/> + <title>ATOM_EXT (deprecated)</title> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">2</cell> + <cell align="center">Len</cell> + </row> + <row> + <cell align="center"><c>100</c></cell> + <cell align="center"><c>Len</c></cell> + <cell align="center"><c>AtomName</c></cell> + </row> + <tcaption>ATOM_EXT</tcaption></table> + <p> + An atom is stored with a 2 byte unsigned length in big-endian order, + followed by <c>Len</c> numbers of 8-bit Latin-1 characters that forms + the <c>AtomName</c>. The maximum allowed value for <c>Len</c> is 255. + </p> + </section> + + <section> + <marker id="SMALL_ATOM_EXT"/> + <title>SMALL_ATOM_EXT (deprecated)</title> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">Len</cell> + </row> + <row> + <cell align="center"><c>115</c></cell> + <cell align="center"><c>Len</c></cell> + <cell align="center"><c>AtomName</c></cell> + </row> + <tcaption>SMALL_ATOM_EXT</tcaption></table> + <p> + An atom is stored with a 1 byte unsigned length, + followed by <c>Len</c> numbers of 8-bit Latin-1 characters that + forms the <c>AtomName</c>. + </p> + <note> + <p> + <c>SMALL_ATOM_EXT</c> was introduced in ERTS 5.7.2 and + require an exchange of distribution flag + <seealso marker="erl_dist_protocol#dflags"> + <c>DFLAG_SMALL_ATOM_TAGS</c></seealso> in the + <seealso marker="erl_dist_protocol#distribution_handshake"> + distribution handshake</seealso>. + </p> + </note> + </section> + </chapter> diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index b5dc9037c4..3eb3e04f33 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -4,7 +4,7 @@ <cref> <header> <copyright> - <year>2001</year><year>2016</year> + <year>2001</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -80,7 +80,7 @@ <code type="none"> /* niftest.c */ -#include "erl_nif.h" +#include <erl_nif.h> static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { @@ -123,7 +123,7 @@ ok "Hello world!"</code> <p>A better solution for a real module is to take advantage of the new - directive <c>on load</c> (see section + directive <c>on_load</c> (see section <seealso marker="doc/reference_manual:code_loading#on_load">Running a Function When a Module is Loaded</seealso> in the Erlang Reference Manual) to load the NIF library automatically when the module is @@ -135,27 +135,14 @@ ok away by the compiler, causing loading of the NIF library to fail.</p> </note> - <p>A loaded NIF library is tied to the Erlang module code version - that loaded it. If the module is upgraded with a new version, the - new Erlang code need to load its own NIF library (or maybe choose not - to). The new code version can, however, choose to load the - same NIF library as the old code if it wants to. Sharing the - dynamic library means that static data defined by the library - is shared as well. To avoid unintentionally shared static - data, each Erlang module code can keep its own private data. This - private data can be set when the NIF library is loaded and - then retrieved by calling <seealso marker="#enif_priv_data"> - <c>enif_priv_data</c></seealso>.</p> - - <p>A NIF library cannot be loaded explicitly. A library is - automatically unloaded when the module code that it belongs to is purged - by the code server.</p> + <p>Once loaded, a NIF library is persistent. It will not be unloaded + until the module code version that it belongs to is purged.</p> </description> <section> <title>Functionality</title> - <p>All functions that a NIF library needs to do with Erlang are - performed through the NIF API functions. Functions exist + <p>All interaction between NIF code and the Erlang runtime system is + performed by calling NIF API functions. Functions exist for the following functionality:</p> <taglist> @@ -286,6 +273,19 @@ return term;</code> library is postponed as long as there exist resource objects with a destructor function in the library.</p> </item> + <tag>Module upgrade and static data</tag> + <item> + <p>A loaded NIF library is tied to the Erlang module instance + that loaded it. If the module is upgraded, the new module instance + needs to load its own NIF library (or maybe choose not to). The new + module instance can, however, choose to load the exact same NIF library + as the old code if it wants to. Sharing the dynamic library means that + static data defined by the library is shared as well. To avoid + unintentionally shared static data between module instances, each Erlang + module version can keep its own private data. This private data can be + set when the NIF library is loaded and later retrieved by calling + <seealso marker="#enif_priv_data"><c>enif_priv_data</c></seealso>.</p> + </item> <tag>Threads and concurrency</tag> <item> <p>A NIF is thread-safe without any explicit synchronization as @@ -296,8 +296,8 @@ return term;</code> synchronization. This includes terms in process-independent environments that are shared between threads. Resource objects also require synchronization if you treat them as mutable.</p> - <p>The library initialization callbacks <c>load</c>, <c>reload</c>, and - <c>upgrade</c> are all thread-safe even for shared state data.</p> + <p>The library initialization callbacks <c>load</c> and + <c>upgrade</c> are thread-safe even for shared state data.</p> </item> <tag><marker id="version_management"/>Version Management</tag> <item> @@ -402,14 +402,14 @@ return term;</code> <tag><marker id="dirty_nifs"/>Dirty NIF</tag> <item> <note> - <p><em>The dirty NIF functionality described here - is experimental</em>. Dirty NIF support is available only when - the emulator is configured with dirty schedulers enabled. This - feature is disabled by default. The Erlang runtime - without SMP support does not support dirty schedulers even when - the dirty scheduler support is enabled. To check at runtime for - the presence of dirty scheduler threads, code can use the - <seealso marker="#enif_system_info"> + <p>Dirty NIF support is available only when the emulator is + configured with dirty scheduler support. As of ERTS version + 9.0, dirty scheduler support is enabled by default on the + runtime system with SMP support. The Erlang runtime without + SMP support does <em>not</em> support dirty schedulers even + when the dirty scheduler support is explicitly enabled. To + check at runtime for the presence of dirty scheduler threads, + code can use the <seealso marker="#enif_system_info"> <c>enif_system_info()</c></seealso> API function.</p> </note> <p>A NIF that cannot be split and cannot execute in a millisecond @@ -498,7 +498,7 @@ return term;</code> <title>Initialization</title> <taglist> <tag><marker id="ERL_NIF_INIT"/><c>ERL_NIF_INIT(MODULE, - ErlNifFunc funcs[], load, reload, upgrade, unload)</c></tag> + ErlNifFunc funcs[], load, NULL, upgrade, unload)</c></tag> <item> <p>This is the magic macro to initialize a NIF library. It is to be evaluated in global file scope.</p> @@ -507,11 +507,14 @@ return term;</code> the macro.</p> <p><c>funcs</c> is a static array of function descriptors for all the implemented NIFs in this library.</p> - <p><c>load</c>, <c>reload</c>, <c>upgrade</c> and <c>unload</c> - are pointers to functions. One of <c>load</c>, <c>reload</c>, or + <p><c>load</c>, <c>upgrade</c> and <c>unload</c> + are pointers to functions. One of <c>load</c> or <c>upgrade</c> is called to initialize the library. <c>unload</c> is called to release the library. All are described individually below.</p> + <p>The fourth argument <c>NULL</c> is ignored. It + was earlier used for the deprectated <c>reload</c> callback + which is no longer supported since OTP 20.</p> <p>If compiling a NIF for static inclusion through <c>--enable-static-nifs</c>, you must define <c>STATIC_ERLANG_NIF</c> before the <c>ERL_NIF_INIT</c> declaration.</p> @@ -522,7 +525,7 @@ return term;</code> <p><c>load</c> is called when the NIF library is loaded and no previously loaded library exists for this module.</p> <p><c>*priv_data</c> can be set to point to some private data - that the library needs to keep a state between NIF + if the library needs to keep a state between NIF calls. <c>enif_priv_data</c> returns this pointer. <c>*priv_data</c> is initialized to <c>NULL</c> when <c>load</c> is called.</p> @@ -539,7 +542,7 @@ return term;</code> and there is old code of this module with a loaded NIF library.</p> <p>Works as <c>load</c>, except that <c>*old_priv_data</c> already contains the value set by the last call to <c>load</c> or - <c>reload</c> for the old module code. <c>*priv_data</c> is + <c>upgrade</c> for the old module code. <c>*priv_data</c> is initialized to <c>NULL</c> when <c>upgrade</c> is called. It is allowed to write to both <c>*priv_data</c> and <c>*old_priv_data.</c></p> @@ -551,27 +554,7 @@ return term;</code> <item> <p><c>unload</c> is called when the module code that the NIF library belongs to is purged as old. New code of the same - module may or may not exist. Notice that <c>unload</c> is not - called for a replaced library as a consequence of <c>reload</c>.</p> - </item> - <tag><marker id="reload"/><c>int (*reload)(ErlNifEnv* env, void** - priv_data, ERL_NIF_TERM load_info)</c></tag> - <item> - <note> - <p><em>The reload mechanism is deprecated.</em> It was only intended - as a development feature. Do not use it as an upgrade method for - live production systems. It can be removed in future releases. - Ensure to pass <c>reload</c> as <c>NULL</c> to - <seealso marker="#ERL_NIF_INIT"><c>ERL_NIF_INIT</c></seealso> - to disable it when not used.</p> - </note> - <p><c>reload</c> is called when the NIF library is loaded and a - previously loaded library already exists for this module code.</p> - <p>Works as <c>load</c>, except that - <c>*priv_data</c> already contains the value set by the - previous call to <c>load</c> or <c>reload</c>.</p> - <p>The library fails to load if <c>reload</c> returns - anything other than <c>0</c> or if <c>reload</c> is <c>NULL</c>.</p> + module may or may not exist.</p> </item> </taglist> </section> @@ -659,9 +642,6 @@ typedef struct { <p><c>flags</c> can be used to indicate that the NIF is a <seealso marker="#dirty_nifs">dirty NIF</seealso> that is to be executed on a dirty scheduler thread.</p> - <p><em>The dirty NIF functionality described here is - experimental.</em> You have to enable support for dirty - schedulers when building OTP to try out the functionality.</p> <p>If the dirty NIF is expected to be CPU-bound, its <c>flags</c> field is to be set to <c>ERL_NIF_DIRTY_JOB_CPU_BOUND</c> or <c>ERL_NIF_DIRTY_JOB_IO_BOUND</c>.</p> @@ -695,6 +675,18 @@ typedef struct { <p>When receiving data from untrusted sources, use option <c>ERL_NIF_BIN2TERM_SAFE</c>.</p> </item> + <tag><marker id="ErlNifMonitor"/><c>ErlNifMonitor</c></tag> + <item> + <p>This is an opaque data type that identifies a monitor.</p> + <p>The nif writer is to provide the memory for storing the + monitor when calling <seealso marker="#enif_monitor_process"> + <c>enif_monitor_process</c></seealso>. The + address of the data is not stored by the runtime system, so + <c>ErlNifMonitor</c> can be used as any other data, it + can be copied, moved in memory, forgotten, and so on. + To compare two monitors, <seealso marker="#enif_compare_monitors"> + <c>enif_compare_monitors</c></seealso> must be used.</p> + </item> <tag><marker id="ErlNifPid"/><c>ErlNifPid</c></tag> <item> <p>A process identifier (pid). In contrast to pid terms (instances of @@ -716,11 +708,47 @@ typedef struct { Each resource type has a unique name and a destructor function that is called when objects of its type are released.</p> </item> + <tag><marker id="ErlNifResourceTypeInit"/><c>ErlNifResourceTypeInit</c></tag> + <item> + <code type="none"> +typedef struct { + ErlNifResourceDtor* dtor; + ErlNifResourceStop* stop; + ErlNifResourceDown* down; +} ErlNifResourceTypeInit;</code> + <p>Initialization structure read by <seealso marker="#enif_open_resource_type_x"> + enif_open_resource_type_x</seealso>.</p> + </item> <tag><marker id="ErlNifResourceDtor"/><c>ErlNifResourceDtor</c></tag> <item> <code type="none"> typedef void ErlNifResourceDtor(ErlNifEnv* env, void* obj);</code> <p>The function prototype of a resource destructor function.</p> + <p>The <c>obj</c> argument is a pointer to the resource. The only + allowed use for the resource in the destructor is to access its + user data one final time. The destructor is guaranteed to be the + last callback before the resource is deallocated.</p> + </item> + <tag><marker id="ErlNifResourceDown"/><c>ErlNifResourceDown</c></tag> + <item> + <code type="none"> +typedef void ErlNifResourceDown(ErlNifEnv* env, void* obj, const ErlNifPid* pid, const ErlNifMonitor* mon);</code> + <p>The function prototype of a resource down function, + called on the behalf of <seealso marker="#enif_monitor_process"> + enif_monitor_process</seealso>. <c>obj</c> is the resource, <c>pid</c> + is the identity of the monitored process that is exiting, and <c>mon</c> + is the identity of the monitor. + </p> + </item> + <tag><marker id="ErlNifResourceStop"/><c>ErlNifResourceStop</c></tag> + <item> + <code type="none"> +typedef void ErlNifResourceStop(ErlNifEnv* env, void* obj, ErlNifEvent event, int is_direct_call);</code> + <p>The function prototype of a resource stop function, + called on the behalf of <seealso marker="#enif_select"> + enif_select</seealso>. <c>obj</c> is the resource, <c>event</c> is OS event, + <c>is_direct_call</c> is true if the call is made directly from <c>enif_select</c> + or false if it is a scheduled call (potentially from another thread).</p> </item> <tag><marker id="ErlNifCharEncoding"/><c>ErlNifCharEncoding</c></tag> <item> @@ -786,6 +814,29 @@ typedef enum { </item> </taglist> </item> + <tag><marker id="ErlNifHash"/><c>ErlNifHash</c></tag> + <item> + <p>An enumeration of the supported hash types that can be generated + using <seealso marker="#enif_hash"><c>enif_hash</c></seealso>. + </p> + <taglist> + <tag><c>ERL_NIF_INTERNAL_HASH</c></tag> + <item> + <p>Non-portable hash function that only guarantees the same hash + for the same term within one Erlang VM instance.</p> + <p>It takes 32-bit salt values and generates hashes within <c>0..2^32-1</c>.</p> + </item> + <tag><c>ERL_NIF_PHASH2</c></tag> + <item> + <p>Portable hash function that gives the same hash for the + same Erlang term regardless of machine architecture and ERTS version.</p> + <p><em>It ignores salt values</em> and generates hashes within <c>0..2^27-1</c>.</p> + <p>Slower than <c>ERL_NIF_INTERNAL_HASH.</c> + It corresponds to <seealso marker="erlang#phash2-1"><c>erlang:phash2/1</c></seealso>. + </p> + </item> + </taglist> + </item> </taglist> </section> @@ -895,6 +946,21 @@ typedef enum { </func> <func> + <name><ret>int</ret><nametext>enif_compare_monitors(const ErlNifMonitor + *monitor1, const ErlNifMonitor *monitor2)</nametext></name> + <fsummary>Compare two monitors.</fsummary> + <desc> + <marker id="enif_compare_monitors"></marker> + <p>Compares two <seealso marker="#ErlNifMonitor"><c>ErlNifMonitor</c></seealso>s. + Can also be used to imply some artificial order on monitors, + for whatever reason.</p> + <p>Returns <c>0</c> if <c>monitor1</c> and <c>monitor2</c> are equal, + < <c>0</c> if <c>monitor1</c> < <c>monitor2</c>, and + > <c>0</c> if <c>monitor1</c> > <c>monitor2</c>.</p> + </desc> + </func> + + <func> <name><ret>void</ret> <nametext>enif_cond_broadcast(ErlNifCond *cnd)</nametext></name> <fsummary></fsummary> @@ -1022,6 +1088,30 @@ typedef enum { </func> <func> + <name><ret>int</ret><nametext>enif_demonitor_process(ErlNifEnv* env, void* obj, + const ErlNifMonitor* mon)</nametext></name> + <fsummary>Cancel a process monitor.</fsummary> + <desc> + <marker id="enif_demonitor_process"></marker> + <p>Cancels a monitor created earlier with <seealso marker="#enif_monitor_process"> + <c>enif_monitor_process</c></seealso>. Argument <c>obj</c> is a pointer + to the resource holding the monitor and <c>*mon</c> identifies the monitor.</p> + <p>Returns <c>0</c> if the monitor was successfully identified and removed. + Returns a non-zero value if the monitor could not be identified, which means + it was either</p> + <list type="bulleted"> + <item>never created for this resource</item> + <item>already cancelled</item> + <item>already triggered</item> + <item>just about to be triggered by a concurrent thread</item> + </list> + <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> + </desc> + </func> + + <func> <name><ret>int</ret> <nametext>enif_equal_tids(ErlNifTid tid1, ErlNifTid tid2)</nametext> </name> @@ -1306,13 +1396,12 @@ typedef enum { <p>Returns <c>true</c> if a pending exception is associated with the environment <c>env</c>. If <c>reason</c> is a <c>NULL</c> pointer, ignore it. Otherwise, if a pending exception associated with - <c>env</c> exists, set <c>ERL_NIF_TERM</c> to which <c>reason</c> - points to the value of the exception's term. For example, if - <seealso marker="#enif_make_badarg"> + <c>env</c> exists, set <c>*reason</c> to the value of the exception + term. For example, if <seealso marker="#enif_make_badarg"> <c>enif_make_badarg</c></seealso> is called to set a pending <c>badarg</c> exception, a later call to <c>enif_has_pending_exception(env, &reason)</c> sets - <c>reason</c> to the atom <c>badarg</c>, then return <c>true</c>.</p> + <c>*reason</c> to the atom <c>badarg</c>, then return <c>true</c>.</p> <p>See also <seealso marker="#enif_make_badarg"> <c>enif_make_badarg</c></seealso> and <seealso marker="#enif_raise_exception"> @@ -1321,6 +1410,19 @@ typedef enum { </func> <func> + <name> + <ret>ErlNifUInt64</ret> + <nametext>enif_hash(ErlNifHash type, ERL_NIF_TERM term, ErlNifUInt64 salt)</nametext> + </name> + <fsummary>Hash terms.</fsummary> + <desc> + <p>Hashes <c>term</c> according to the specified + <seealso marker="#ErlNifHash"><c>ErlNifHash</c></seealso> <c>type</c>.</p> + <p>Ranges of taken salt (if any) and returned value depend on the hash type.</p> + </desc> + </func> + + <func> <name><ret>int</ret><nametext>enif_inspect_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, ErlNifBinary* bin)</nametext></name> <fsummary>Inspect the content of a binary.</fsummary> @@ -2137,6 +2239,36 @@ enif_map_iterator_destroy(env, &iter);</code> </func> <func> + <name><ret>int</ret><nametext>enif_monitor_process(ErlNifEnv* env, void* obj, + const ErlNifPid* target_pid, ErlNifMonitor* mon)</nametext></name> + <fsummary>Monitor a process from a resource.</fsummary> + <desc> + <marker id="enif_monitor_process"></marker> + <p>Starts monitoring a process from a resource. When a process is + monitored, a process exit results in a call to the provided + <seealso marker="#ErlNifResourceDown"> + <c>down</c></seealso> callback associated with the resource type.</p> + <p>Argument <c>obj</c> is pointer to the resource to hold the monitor and + <c>*target_pid</c> identifies the local process to be monitored.</p> + <p>If <c>mon</c> is not <c>NULL</c>, a successful call stores the + identity of the monitor in the + <seealso marker="#ErlNifMonitor"><c>ErlNifMonitor</c></seealso> + struct pointed to by <c>mon</c>. This identifier is used to refer to the + monitor for later removal with + <seealso marker="#enif_demonitor_process"><c>enif_demonitor_process</c></seealso> + or compare with + <seealso marker="#enif_compare_monitors"><c>enif_compare_monitors</c></seealso>. + A monitor is automatically removed when it triggers or when + the resource is deallocated.</p> + <p>Returns <c>0</c> on success, < 0 if no <c>down</c> callback is + provided, and > 0 if the process is no longer alive.</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> + </desc> + </func> + + <func> <name><ret>ErlNifTime</ret> <nametext>enif_monotonic_time(ErlNifTimeUnit time_unit)</nametext> </name> @@ -2249,10 +2381,30 @@ enif_map_iterator_destroy(env, &iter);</code> returns <c>NULL</c> and sets <c>*tried</c> to <c>flags</c>. It is allowed to set <c>tried</c> to <c>NULL</c>.</p> <p>Notice that <c>enif_open_resource_type</c> is only allowed to be - called in the three callbacks - <seealso marker="#load"><c>load</c></seealso>, - <seealso marker="#reload"><c>reload</c></seealso>, and + called in the two callbacks + <seealso marker="#load"><c>load</c></seealso> and <seealso marker="#upgrade"><c>upgrade</c></seealso>.</p> + <p>See also <seealso marker="#enif_open_resource_type_x"> + <c>enif_open_resource_type_x</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifResourceType *</ret> + <nametext>enif_open_resource_type_x(ErlNifEnv* env, const char* name, + const ErlNifResourceTypeInit* init, + ErlNifResourceFlags flags, ErlNifResourceFlags* tried)</nametext> + </name> + <fsummary>Create or takeover a resource type.</fsummary> + <desc> + <p>Same as <seealso marker="#enif_open_resource_type"><c>enif_open_resource_type</c></seealso> + except it accepts additional callback functions for resource types that are + used together with <seealso marker="#enif_select"><c>enif_select</c></seealso> + and <seealso marker="#enif_monitor_process"><c>enif_monitor_process</c></seealso>.</p> + <p>Argument <c>init</c> is a pointer to an + <seealso marker="#ErlNifResourceTypeInit"><c>ErlNifResourceTypeInit</c></seealso> + structure that contains the function pointers for destructor, down and stop callbacks + for the resource type.</p> </desc> </func> @@ -2305,10 +2457,8 @@ enif_map_iterator_destroy(env, &iter);</code> <fsummary>Get the private data of a NIF library.</fsummary> <desc> <p>Returns the pointer to the private data that was set by - <seealso marker="#load"><c>load</c></seealso>, - <seealso marker="#reload"><c>reload</c></seealso>, or + <seealso marker="#load"><c>load</c></seealso> or <seealso marker="#upgrade"><c>upgrade</c></seealso>.</p> - <p>Was previously named <c>enif_get_data</c>.</p> </desc> </func> @@ -2365,7 +2515,7 @@ enif_map_iterator_destroy(env, &iter);</code> <nametext>enif_release_resource(void* obj)</nametext></name> <fsummary>Release a resource object.</fsummary> <desc> - <p>Removes a reference to resource object <c>obj</c>obtained from + <p>Removes a reference to resource object <c>obj</c> obtained from <seealso marker="#enif_alloc_resource"> <c>enif_alloc_resource</c></seealso>. The resource object is destructed when the last reference is removed. @@ -2470,9 +2620,6 @@ enif_map_iterator_destroy(env, &iter);</code> application to break up long-running work into multiple regular NIF calls or to schedule a <seealso marker="#dirty_nifs"> dirty NIF</seealso> to execute on a dirty scheduler thread.</p> - <p><em>The dirty NIF functionality described here is - experimental.</em> You have to enable support for dirty - schedulers when building OTP to try out the functionality.</p> <taglist> <tag><c>fun_name</c></tag> <item> @@ -2483,13 +2630,13 @@ enif_map_iterator_destroy(env, &iter);</code> <tag><c>flags</c></tag> <item> <p>Must be set to <c>0</c> for a regular NIF. If the emulator was - built with the experimental dirty scheduler support enabled, + built with dirty scheduler support enabled, <c>flags</c> can be set to either <c>ERL_NIF_DIRTY_JOB_CPU_BOUND</c> if the job is expected to be CPU-bound, or <c>ERL_NIF_DIRTY_JOB_IO_BOUND</c> for jobs that will be I/O-bound. If dirty scheduler threads are not available in the emulator, an attempt to schedule such a job - results in a <c>badarg</c> exception.</p> + results in a <c>notsup</c> exception.</p> </item> <tag><c>argc</c> and <c>argv</c></tag> <item> @@ -2508,6 +2655,100 @@ enif_map_iterator_destroy(env, &iter);</code> </func> <func> + <name><ret>int</ret> + <nametext>enif_select(ErlNifEnv* env, ErlNifEvent event, enum ErlNifSelectFlags mode, + void* obj, const ErlNifPid* pid, ERL_NIF_TERM ref)</nametext> + </name> + <fsummary>Manage subscription on IO event.</fsummary> + <desc> + <p>This function can be used to receive asynchronous notifications + when OS-specific event objects become ready for either read or write operations.</p> + <p>Argument <c>event</c> identifies the event object. On Unix + systems, the functions <c>select</c>/<c>poll</c> are used. The event + object must be a socket, pipe or other file descriptor object that + <c>select</c>/<c>poll</c> can use.</p> + <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 triggerred, + 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> + <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 + to manage its state and lifetime. A handle to the resource is received + in the notification message as <c>Obj</c>.</p> + <p>Argument <c>ref</c> must be either a reference obtained from + <seealso marker="erlang#make_ref-0"><c>erlang:make_ref/0</c></seealso> + 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> + <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>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> + <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 + <c>obj</c>. The relation is dissolved when <c>enif_select</c> has + been called with <c>mode</c> as <c>ERL_NIF_SELECT_STOP</c> and the + corresponding <c>stop</c> callback has returned. A resource can contain + several event objects but one event object can only be contained within + one resource. A resource will not be destructed until all its contained relations + have been dissolved.</p> + <note> + <p>Use <seealso marker="#enif_monitor_process"><c>enif_monitor_process</c></seealso> + together with <c>enif_select</c> to detect failing Erlang + processes and prevent them from causing permanent leakage of resources + and their contained OS event objects.</p> + </note> + <p>Returns a non-negative value on success where the following bits can be set:</p> + <taglist> + <tag><c>ERL_NIF_SELECT_STOP_CALLED</c></tag> + <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> + </taglist> + <p>Returns a negative value if the call failed where the follwing bits can be set:</p> + <taglist> + <tag><c>ERL_NIF_SELECT_INVALID_EVENT</c></tag> + <item>Argument <c>event</c> is not a valid OS event object.</item> + <tag><c>ERL_NIF_SELECT_FAILED</c></tag> + <item>The system call failed to add the event object to the poll set.</item> + </taglist> + <note> + <p>Use bitwise AND to test for specific bits in the return vaue. + New significant bits may be added in future releases to give more detailed + information for both failed and successful calls. Do NOT use equallity tests + like <c>==</c>, as that may cause your application to stop working.</p> + <p>Example:</p> + <code type="none"> +retval = enif_select(env, fd, ERL_NIF_SELECT_STOP, resource, ref); +if (retval < 0) { + /* handle error */ +} +/* Success! */ +if (retval & ERL_NIF_SELECT_STOP_CALLED) { + /* ... */ +} +</code> + </note> + </desc> + </func> + + <func> <name><ret>ErlNifPid *</ret> <nametext>enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)</nametext> </name> diff --git a/erts/doc/src/erl_tracer.xml b/erts/doc/src/erl_tracer.xml index 83eef374ca..fd3c17f337 100644 --- a/erts/doc/src/erl_tracer.xml +++ b/erts/doc/src/erl_tracer.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2016</year><year>2016</year> + <year>2016</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -103,7 +103,7 @@ <item>If set the tracer has been requested to include a time stamp.</item> <tag><c>extra</c></tag> - <item>If set the tracepoint has included additonal data about + <item>If set the tracepoint has included additional data about the trace event. What the additional data is depends on which <c>TraceTag</c> has been triggered. The <c>extra</c> trace data corresponds to the fifth element in the trace tuples described in @@ -653,7 +653,7 @@ ok <0.37.0> 3> erlang:trace(new, true, [send,{tracer, erl_msg_tracer, Tracer}]). 0 -{<0.39.0>,<0.27.0>} +{trace,<0.39.0>,<0.27.0>} 4> {ok, D} = file:open("/tmp/tmp.data",[write]). {trace,#Port<0.486>,<0.40.0>} {trace,<0.40.0>,<0.21.0>} @@ -684,7 +684,7 @@ trace(_, _, _, _, _) -> <p><c>erl_msg_tracer.c</c>:</p> <pre> -#include "erl_nif.h" +#include <erl_nif.h> /* NIF interface declarations */ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); @@ -758,18 +758,21 @@ static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) /* * argv[0]: TraceTag, should only be 'send' - * argv[1]: TracerState, process to send {argv[2], argv[4]} to + * argv[1]: TracerState, process to send {Tracee, Recipient} to * argv[2]: Tracee - * argv[3]: Recipient - * argv[4]: Options, ignored + * argv[3]: Message + * argv[4]: Options, map containing Recipient */ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { ErlNifPid to_pid; + ERL_NIF_TERM recipient, msg; if (enif_get_local_pid(env, argv[1], &to_pid)) { - ERL_NIF_TERM msg = enif_make_tuple3(env, enif_make_atom(env, "trace"), argv[2], argv[4]); + if (enif_get_map_value(env, argv[4], enif_make_atom(env, "extra"), &recipient)) { + msg = enif_make_tuple3(env, enif_make_atom(env, "trace"), argv[2], recipient); enif_send(env, &to_pid, NULL, msg); + } } return enif_make_atom(env, "ok"); diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index c3b0bc0d74..d9cc5ef936 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -325,16 +325,11 @@ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code> is <c>latin1</c>, one byte exists for each character in the text representation. If <c><anno>Encoding</anno></c> is <c>utf8</c> or - <c>unicode</c>, the characters are encoded using UTF-8 - (that is, characters from 128 through 255 are - encoded in two bytes).</p> + <c>unicode</c>, the characters are encoded using UTF-8 where + characters may require multiple bytes.</p> <note> - <p><c>atom_to_binary(<anno>Atom</anno>, latin1)</c> never - fails, as the text representation of an atom can only - contain characters from 0 through 255. In a future release, - the text representation - of atoms can be allowed to contain any Unicode character and - <c>atom_to_binary(<anno>Atom</anno>, latin1)</c> then fails if the + <p>As from Erlang/OTP 20, atoms can contain any Unicode character + and <c>atom_to_binary(<anno>Atom</anno>, latin1)</c> may fail if the text representation for <c><anno>Atom</anno></c> contains a Unicode character > 255.</p> </note> @@ -402,13 +397,11 @@ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code> translation of bytes in the binary is done. If <c><anno>Encoding</anno></c> is <c>utf8</c> or <c>unicode</c>, the binary must contain - valid UTF-8 sequences. Only Unicode characters up - to 255 are allowed.</p> + valid UTF-8 sequences.</p> <note> - <p><c>binary_to_atom(<anno>Binary</anno>, utf8)</c> fails if - the binary contains Unicode characters > 255. - In a future release, such Unicode characters can be allowed and - <c>binary_to_atom(<anno>Binary</anno>, utf8)</c> does then not fail. + <p>As from Erlang/OTP 20, <c>binary_to_atom(<anno>Binary</anno>, utf8)</c> + is capable of encoding any Unicode character. Earlier versions would + fail if the binary contained Unicode characters > 255. For more information about Unicode support in atoms, see the <seealso marker="erl_ext_dist#utf8_atoms">note on UTF-8 encoded atoms</seealso> @@ -419,9 +412,7 @@ Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code> > <input>binary_to_atom(<<"Erlang">>, latin1).</input> 'Erlang' > <input>binary_to_atom(<<1024/utf8>>, utf8).</input> -** exception error: bad argument - in function binary_to_atom/2 - called as binary_to_atom(<<208,128>>,utf8)</pre> +'Ѐ'</pre> </desc> </func> @@ -733,6 +724,19 @@ hello </func> <func> + <name name="ceil" arity="1"/> + <fsummary>Returns the smallest integer not less than the argument</fsummary> + <desc> + <p>Returns the smallest integer not less than + <c><anno>Number</anno></c>. + For example:</p> + <pre> +> <input>ceil(5.5).</input> +6</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> <name name="check_old_code" arity="1"/> <fsummary>Check if a module has old code.</fsummary> <desc> @@ -1480,6 +1484,20 @@ true</pre> </func> <func> + <name name="floor" arity="1"/> + <fsummary>Returns the largest integer not greater than the argument</fsummary> + <desc> + <p>Returns the largest integer not greater than + <c><anno>Number</anno></c>. + For example:</p> + <pre> +> <input>floor(-10.5).</input> +-11</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + + <func> <name name="fun_info" arity="1"/> <fsummary>Information about a fun.</fsummary> <desc> @@ -1667,6 +1685,12 @@ true</pre> the form <c>{garbage_collect, <anno>RequestId</anno>, <anno>GCResult</anno>}</c>. </item> + + <tag><c>{type, 'major' | 'minor'}</c></tag> + <item>Triggers garbage collection of requested type. Default value is + <c>'major'</c>, which would trigger a fullsweep GC. + The option <c>'minor'</c> is considered a hint and may lead to + either minor or major GC run.</item> </taglist> <p>If <c><anno>Pid</anno></c> equals <c>self()</c>, and no <c>async</c> option has been passed, the garbage @@ -1789,8 +1813,9 @@ true</pre> <fsummary>Get the call stack back-trace of the last exception.</fsummary> <type name="stack_item"/> <desc> - <p>Gets the call stack back-trace (<em>stacktrace</em>) of the - last exception in the calling process as a list of + <p>Gets the call stack back-trace (<em>stacktrace</em>) for an + exception that has just been caught + in the calling process as a list of <c>{<anno>Module</anno>,<anno>Function</anno>,<anno>Arity</anno>,<anno>Location</anno>}</c> tuples. Field <c><anno>Arity</anno></c> in the first tuple can be the argument list of that function call instead of an arity integer, @@ -1798,6 +1823,29 @@ true</pre> <p>If there has not been any exceptions in a process, the stacktrace is <c>[]</c>. After a code change for the process, the stacktrace can also be reset to <c>[]</c>.</p> + <p><c>erlang:get_stacktrace/0</c> is only guaranteed to return + a stacktrace if called (directly or indirectly) from within the + scope of a <c>try</c> expression. That is, the following call works:</p> +<pre> +try Expr +catch + C:R -> + {C,R,erlang:get_stacktrace()} +end</pre> + <p>As does this call:</p> +<pre> +try Expr +catch + C:R -> + {C,R,helper()} +end + +helper() -> + erlang:get_stacktrace().</pre> + + <warning><p>In a future release, + <c>erlang:get_stacktrace/0</c> will return <c>[]</c> if called + from outside a <c>try</c> expression.</p></warning> <p>The stacktrace is the same data as operator <c>catch</c> returns, for example:</p> <pre> @@ -1922,26 +1970,6 @@ os_prompt%</pre> </func> <func> - <name name="hash" arity="2"/> - <fsummary>Hash function (deprecated).</fsummary> - <desc> - <p>Returns a hash value for <c><anno>Term</anno></c> within the range - <c>1..<anno>Range</anno></c>. The maximum range is 1..2^27-1.</p> - <warning> - <p><em>This BIF is deprecated, as the hash value can differ on - different architectures.</em> The hash values for integer - terms > 2^27 and large binaries are - poor. The BIF is retained for backward compatibility - reasons (it can have been used to hash records into a file), - but all new code is to use one of the BIFs - <seealso marker="#phash/2"><c>erlang:phash/2</c></seealso> or - <seealso marker="#phash2/1"><c>erlang:phash2/1,2</c></seealso> - instead.</p> - </warning> - </desc> - </func> - - <func> <name name="hd" arity="1"/> <fsummary>Head of a list.</fsummary> <desc> @@ -2368,10 +2396,10 @@ os_prompt%</pre> <desc> <p>Returns the atom whose text representation is <c><anno>String</anno></c>.</p> - <p><c><anno>String</anno></c> can only contain ISO-latin-1 - characters (that is, numbers < 256) as the implementation does not - allow Unicode characters equal to or above 256 in atoms. - For more information on Unicode support in atoms, see + <p>As from Erlang/OTP 20, <c><anno>String</anno></c> may contain + any Unicode character. Earlier versions allowed only ISO-latin-1 + characters as the implementation did not allow Unicode characters + above 255. For more information on Unicode support in atoms, see <seealso marker="erl_ext_dist#utf8_atoms">note on UTF-8 encoded atoms</seealso> in section "External Term Format" in the User's Guide.</p> @@ -2495,6 +2523,42 @@ os_prompt%</pre> </func> <func> + <name name="list_to_port" arity="1"/> + <fsummary>Convert from text representation to a port.</fsummary> + <desc> + <p>Returns a port identifier whose text representation is a + <c><anno>String</anno></c>, for example:</p> + <pre> +> <input>list_to_port("#Port<0.4>").</input> +#Port<0.4></pre> + <p>Failure: <c>badarg</c> if <c><anno>String</anno></c> contains a bad + representation of a port identifier.</p> + <warning> + <p>This BIF is intended for debugging and is not to be used + in application programs.</p> + </warning> + </desc> + </func> + + <func> + <name name="list_to_ref" arity="1"/> + <fsummary>Convert from text representation to a ref.</fsummary> + <desc> + <p>Returns a reference whose text representation is a + <c><anno>String</anno></c>, for example:</p> + <pre> +> <input>list_to_ref("#Ref<0.4192537678.4073193475.71181>").</input> +#Ref<0.4192537678.4073193475.71181></pre> + <p>Failure: <c>badarg</c> if <c><anno>String</anno></c> contains a bad + representation of a reference.</p> + <warning> + <p>This BIF is intended for debugging and is not to be used + in application programs.</p> + </warning> + </desc> + </func> + + <func> <name name="list_to_tuple" arity="1"/> <fsummary>Convert a list to a tuple.</fsummary> <desc> @@ -2544,13 +2608,6 @@ os_prompt%</pre> <name name="load_nif" arity="2"/> <fsummary>Load NIF library.</fsummary> <desc> - <note> - <p>Before Erlang/OTP R14B, NIFs were an - experimental feature. Versions before Erlang/OTP R14B can - have different and possibly incompatible NIF semantics and - interfaces. For example, in Erlang/OTP R13B03 the return value on - failure was <c>{error,Reason,Text}</c>.</p> - </note> <p>Loads and links a dynamic library containing native implemented functions (NIFs) for a module. <c><anno>Path</anno></c> is a file path to the shareable object/dynamic library file minus @@ -2580,14 +2637,22 @@ os_prompt%</pre> <item>The library did not fulfill the requirements as a NIF library of the calling module. </item> - <tag><c>load | reload | upgrade</c></tag> + <tag><c>load | upgrade</c></tag> <item>The corresponding library callback was unsuccessful. </item> + <tag><c>reload</c></tag> + <item>A NIF library is already loaded for this module instance. + The previously deprecated <c>reload</c> feature was removed in OTP 20. + </item> <tag><c>old_code</c></tag> <item>The call to <c>load_nif/2</c> was made from the old code of a module that has been upgraded; this is not allowed. </item> + <tag><c>notsup</c></tag> + <item>Lack of support. Such as loading NIF library for a + HiPE compiled module. + </item> </taglist> </desc> </func> @@ -3784,9 +3849,6 @@ RealSystem = system + MissedSystem</code> <c><anno>Term</anno></c> within the range <c>1..<anno>Range</anno></c>. The maximum value for <c><anno>Range</anno></c> is 2^32.</p> - <p>This BIF can be used instead of the old deprecated BIF - <c>erlang:hash/2</c>, as it calculates better hashes for - all data types, but consider using <c>phash2/1,2</c> instead.</p> </desc> </func> @@ -3821,10 +3883,6 @@ RealSystem = system + MissedSystem</code> <desc> <p>Returns a string corresponding to the text representation of <c><anno>Pid</anno></c>.</p> - <warning> - <p>This BIF is intended for debugging and is not to be used - in application programs.</p> - </warning> </desc> </func> @@ -4397,10 +4455,6 @@ RealSystem = system + MissedSystem</code> <desc> <p>Returns a string corresponding to the text representation of the port identifier <c><anno>Port</anno></c>.</p> - <warning> - <p>This BIF is intended for debugging. It is not to be used - in application programs.</p> - </warning> </desc> </func> @@ -4597,7 +4651,7 @@ RealSystem = system + MissedSystem</code> <p>If the process potentially can get many messages, you are advised to set the flag to <c>off_heap</c>. This because a garbage collection with many messages placed on - the heap can become extremly expensive and the process can + the heap can become extremely expensive and the process can consume large amounts of memory. Performance of the actual message passing is however generally better when not using flag <c>off_heap</c>.</p> @@ -6094,28 +6148,60 @@ true</pre> <fsummary>Information about active processes and ports.</fsummary> <desc> <marker id="statistics_active_tasks"></marker> + <p>Returns the same as + <seealso marker="#statistics_active_tasks_all"> + <c>statistics(active_tasks_all)</c></seealso> + with the exception that no information about the dirty + IO run queue and its associated schedulers is part of + the result. That is, only tasks that are expected to be + CPU bound are part of the result.</p> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="2"/> + <fsummary>Information about active processes and ports.</fsummary> + <desc> + <marker id="statistics_active_tasks_all"></marker> <p>Returns a list where each element represents the amount of active processes and ports on each run queue and its - associated scheduler. That is, the number of processes and - ports that are ready to run, or are currently running. The - element location in the list corresponds to the scheduler - and its run queue. The first element corresponds to scheduler - number 1 and so on. The information is <em>not</em> gathered - atomically. That is, the result is not necessarily a - consistent snapshot of the state, but instead quite - efficiently gathered.</p> + associated schedulers. That is, the number of processes and + ports that are ready to run, or are currently running. + Values for normal run queues and their associated schedulers + are located first in the resulting list. The first element + corresponds to scheduler number 1 and so on. If support for + dirty schedulers exist, an element with the value for the + dirty CPU run queue and its associated dirty CPU schedulers + follow and then as last element the value for the the dirty + IO run queue and its associated dirty IO schedulers follow. + The information is <em>not</em> gathered atomically. That is, + the result is not necessarily a consistent snapshot of the + state, but instead quite efficiently gathered.</p> + <note><p>Each normal scheduler has one run queue that it + manages. If dirty schedulers schedulers are supported, all + dirty CPU schedulers share one run queue, and all dirty IO + schedulers share one run queue. That is, we have multiple + normal run queues, one dirty CPU run queue and one dirty + IO run queue. Work can <em>not</em> migrate between the + different types of run queues. Only work in normal run + queues can migrate to other normal run queues. This has + to be taken into account when evaluating the result.</p></note> <p>See also <seealso marker="#statistics_total_active_tasks"> <c>statistics(total_active_tasks)</c></seealso>, <seealso marker="#statistics_run_queue_lengths"> - <c>statistics(run_queue_lengths)</c></seealso>, and + <c>statistics(run_queue_lengths)</c></seealso>, + <seealso marker="#statistics_run_queue_lengths_all"> + <c>statistics(run_queue_lengths_all)</c></seealso>, <seealso marker="#statistics_total_run_queue_lengths"> - <c>statistics(total_run_queue_lengths)</c></seealso>.</p> + <c>statistics(total_run_queue_lengths)</c></seealso>, and + <seealso marker="#statistics_total_run_queue_lengths_all"> + <c>statistics(total_run_queue_lengths_all)</c></seealso>.</p> </desc> </func> <func> - <name name="statistics" arity="1" clause_i="2"/> + <name name="statistics" arity="1" clause_i="3"/> <fsummary>Information about context switches.</fsummary> <desc> <p>Returns the total number of context switches since the @@ -6124,7 +6210,7 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="3"/> + <name name="statistics" arity="1" clause_i="4"/> <fsummary>Information about exact reductions.</fsummary> <desc> <marker id="statistics_exact_reductions"></marker> @@ -6140,7 +6226,7 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="4"/> + <name name="statistics" arity="1" clause_i="5"/> <fsummary>Information about garbage collection.</fsummary> <desc> <p>Returns information about garbage collection, for example:</p> @@ -6152,7 +6238,7 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="5"/> + <name name="statistics" arity="1" clause_i="6"/> <fsummary>Information about I/O.</fsummary> <desc> <p>Returns <c><anno>Input</anno></c>, @@ -6163,7 +6249,7 @@ true</pre> </func> <func> - <name name="statistics" arity="1" clause_i="6"/> + <name name="statistics" arity="1" clause_i="7"/> <fsummary>Information about microstate accounting.</fsummary> <desc> <marker id="statistics_microstate_accounting"></marker> @@ -6299,7 +6385,7 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="7"/> + <name name="statistics" arity="1" clause_i="8"/> <fsummary>Information about reductions.</fsummary> <desc> <marker id="statistics_reductions"></marker> @@ -6318,12 +6404,13 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="8"/> + <name name="statistics" arity="1" clause_i="9"/> <fsummary>Information about the run-queues.</fsummary> <desc><marker id="statistics_run_queue"></marker> - <p>Returns the total length of the run-queues. That is, the number + <p>Returns the total length of all normal run-queues. That is, the number of processes and ports that are ready to run on all available - run-queues. The information is gathered atomically. That + normal run-queues. Dirty run queues are not part of the + result. The information is gathered atomically. That is, the result is a consistent snapshot of the state, but this operation is much more expensive compared to <seealso marker="#statistics_total_run_queue_lengths"> @@ -6333,29 +6420,63 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="9"/> + <name name="statistics" arity="1" clause_i="10"/> <fsummary>Information about the run-queue lengths.</fsummary> <desc><marker id="statistics_run_queue_lengths"></marker> + <p>Returns the same as + <seealso marker="#statistics_run_queue_lengths_all"> + <c>statistics(run_queue_lengths_all)</c></seealso> + with the exception that no information about the dirty + IO run queue is part of the result. That is, only + run queues with work that is expected to be CPU bound + is part of the result.</p> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="11"/> + <fsummary>Information about the run-queue lengths.</fsummary> + <desc><marker id="statistics_run_queue_lengths_all"></marker> <p>Returns a list where each element represents the amount - of processes and ports ready to run for each run queue. The - element location in the list corresponds to the run queue - of a scheduler. The first element corresponds to the run - queue of scheduler number 1 and so on. The information is - <em>not</em> gathered atomically. That is, the result is - not necessarily a consistent snapshot of the state, but - instead quite efficiently gathered.</p> + of processes and ports ready to run for each run queue. + Values for normal run queues are located first in the + resulting list. The first element corresponds to the + normal run queue of scheduler number 1 and so on. If + support for dirty schedulers exist, values for the dirty + CPU run queue and the dirty IO run queue follow (in that + order) at the end. The information is <em>not</em> + gathered atomically. That is, the result is not + necessarily a consistent snapshot of the state, but + instead quite efficiently gathered.</p> + <note><p>Each normal scheduler has one run queue that it + manages. If dirty schedulers schedulers are supported, all + dirty CPU schedulers share one run queue, and all dirty IO + schedulers share one run queue. That is, we have multiple + normal run queues, one dirty CPU run queue and one dirty + IO run queue. Work can <em>not</em> migrate between the + different types of run queues. Only work in normal run + queues can migrate to other normal run queues. This has + to be taken into account when evaluating the result.</p></note> <p>See also + <seealso marker="#statistics_run_queue_lengths"> + <c>statistics(run_queue_lengths)</c></seealso>, + <seealso marker="#statistics_total_run_queue_lengths_all"> + <c>statistics(total_run_queue_lengths_all)</c></seealso>, <seealso marker="#statistics_total_run_queue_lengths"> <c>statistics(total_run_queue_lengths)</c></seealso>, <seealso marker="#statistics_active_tasks"> - <c>statistics(active_tasks)</c></seealso>, and + <c>statistics(active_tasks)</c></seealso>, + <seealso marker="#statistics_active_tasks_all"> + <c>statistics(active_tasks_all)</c></seealso>, and <seealso marker="#statistics_total_active_tasks"> - <c>statistics(total_active_tasks)</c></seealso>.</p> + <c>statistics(total_active_tasks)</c></seealso>, + <seealso marker="#statistics_total_active_tasks_all"> + <c>statistics(total_active_tasks_all)</c></seealso>.</p> </desc> </func> <func> - <name name="statistics" arity="1" clause_i="10"/> + <name name="statistics" arity="1" clause_i="12"/> <fsummary>Information about runtime.</fsummary> <desc> <p>Returns information about runtime, in milliseconds.</p> @@ -6370,7 +6491,7 @@ lists:map( </func> <func> - <name name="statistics" arity="1" clause_i="11"/> + <name name="statistics" arity="1" clause_i="13"/> <fsummary>Information about each schedulers work time.</fsummary> <desc> <marker id="statistics_scheduler_wall_time"></marker> @@ -6383,12 +6504,17 @@ lists:map( <c><anno>TotalTime</anno></c> is the total time duration since <seealso marker="#system_flag_scheduler_wall_time"> <c>scheduler_wall_time</c></seealso> - activation. The time unit is undefined and can be subject - to change between releases, OSs, and system restarts. - <c>scheduler_wall_time</c> is only to be used to - calculate relative values for scheduler-utilization. - <c><anno>ActiveTime</anno></c> can never exceed - <c><anno>TotalTime</anno></c>.</p> + activation for the specific scheduler. Note that + activation time can differ significantly between + schedulers. Currently dirty schedulers are activated + at system start while normal schedulers are activated + some time after the <c>scheduler_wall_time</c> + functionality is enabled. The time unit is undefined + and can be subject to change between releases, OSs, + and system restarts. <c>scheduler_wall_time</c> is only + to be used to calculate relative values for scheduler + utilization. <c><anno>ActiveTime</anno></c> can never + exceed <c><anno>TotalTime</anno></c>.</p> <p>The definition of a busy scheduler is when it is not idle and is not scheduling (selecting) a process or port, that is:</p> @@ -6406,15 +6532,37 @@ lists:map( <c>scheduler_wall_time</c></seealso> is turned off.</p> <p>The list of scheduler information is unsorted and can appear in different order between calls.</p> + <p>As of ERTS version 9.0, also dirty CPU schedulers will + be included in the result. That is, all scheduler threads + that are expected to handle CPU bound work. If you also + want information about dirty I/O schedulers, use + <seealso marker="#statistics_scheduler_wall_time_all"><c>statistics(scheduler_wall_time_all)</c></seealso> + instead.</p> + + <p>Normal schedulers will have scheduler identifiers in + the range <c>1 =< <anno>SchedulerId</anno> =< + </c><seealso marker="#system_info_schedulers"><c>erlang:system_info(schedulers)</c></seealso>. + Dirty CPU schedulers will have scheduler identifiers in + the range <c>erlang:system_info(schedulers) < + <anno>SchedulerId</anno> =< erlang:system_info(schedulers) + + + </c><seealso marker="#system_info_dirty_cpu_schedulers"><c>erlang:system_info(dirty_cpu_schedulers)</c></seealso>. + </p> + <note><p>The different types of schedulers handle + specific types of jobs. Every job is assigned to a specific + scheduler type. Jobs can migrate between different schedulers + of the same type, but never between schedulers of different + types. This fact has to be taken under consideration when + evaluating the result returned.</p></note> <p>Using <c>scheduler_wall_time</c> to calculate - scheduler-utilization:</p> + scheduler utilization:</p> <pre> > <input>erlang:system_flag(scheduler_wall_time, true).</input> false > <input>Ts0 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.</input> ok</pre> <p>Some time later the user takes another snapshot and calculates - scheduler-utilization per scheduler, for example:</p> + scheduler utilization per scheduler, for example:</p> <pre> > <input>Ts1 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.</input> ok @@ -6429,11 +6577,32 @@ ok {7,0.973237033077876}, {8,0.9741297293248656}]</pre> <p>Using the same snapshots to calculate a total - scheduler-utilization:</p> + scheduler utilization:</p> <pre> > <input>{A, T} = lists:foldl(fun({{_, A0, T0}, {_, A1, T1}}, {Ai,Ti}) -> - {Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0,Ts1)), A/T.</input> + {Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0,Ts1)), + TotalSchedulerUtilization = A/T.</input> +0.9769136803764825</pre> + <p>Total scheduler utilization will equal <c>1.0</c> when + all schedulers have been active all the time between the + two measurements.</p> + <p>Another (probably more) useful value is to calculate + total scheduler utilization weighted against maximum amount + of available CPU time:</p> + <pre> +> <input>WeightedSchedulerUtilization = (TotalSchedulerUtilization + * (erlang:system_info(schedulers) + + erlang:system_info(dirty_cpu_schedulers))) + / erlang:system_info(logical_processors_available).</input> 0.9769136803764825</pre> + <p>This weighted scheduler utilization will reach <c>1.0</c> + when schedulers are active the same amount of time as + maximum available CPU time. If more schedulers exist + than available logical processors, this value may + be greater than <c>1.0</c>.</p> + <p>As of ERTS version 9.0, the Erlang runtime system + with SMP support will as default have more schedulers + than logical processors. This due to the dirty schedulers.</p> <note> <p><c>scheduler_wall_time</c> is by default disabled. To enable it, use @@ -6443,47 +6612,72 @@ ok </func> <func> - <name name="statistics" arity="1" clause_i="12"/> + <name name="statistics" arity="1" clause_i="14"/> + <fsummary>Information about each schedulers work time.</fsummary> + <desc> + <marker id="statistics_scheduler_wall_time_all"></marker> + <p>The same as + <seealso marker="#statistics_scheduler_wall_time"><c>statistics(scheduler_wall_time)</c></seealso>, + except that it also include information about all dirty I/O + schedulers.</p> + <p>Dirty IO schedulers will have scheduler identifiers in + the range + <seealso marker="#system_info_schedulers"><c>erlang:system_info(schedulers)</c></seealso><c> + + + </c><seealso marker="#system_info_dirty_cpu_schedulers"><c>erlang:system_info(dirty_cpu_schedulers)</c></seealso><c> < + <anno>SchedulerId</anno> =< erlang:system_info(schedulers) + + erlang:system_info(dirty_cpu_schedulers) + + + </c><seealso marker="#system_info_dirty_io_schedulers"><c>erlang:system_info(dirty_io_schedulers)</c></seealso>.</p> + <note><p>Note that work executing on dirty I/O schedulers + are expected to mainly wait for I/O. That is, when you + get high scheduler utilization on dirty I/O schedulers, + CPU utilization is <em>not</em> expected to be high due to + this work.</p></note> + </desc> + </func> + <func> + <name name="statistics" arity="1" clause_i="15"/> <fsummary>Information about active processes and ports.</fsummary> <desc><marker id="statistics_total_active_tasks"></marker> - <p>Returns the total amount of active processes and ports in - the system. That is, the number of processes and ports that - are ready to run, or are currently running. The information - is <em>not</em> gathered atomically. That is, the result - is not necessarily a consistent snapshot of the state, but - instead quite efficiently gathered.</p> - <p>See also - <seealso marker="#statistics_active_tasks"> - <c>statistics(active_tasks)</c></seealso>, - <seealso marker="#statistics_run_queue_lengths"> - <c>statistics(run_queue_lengths)</c></seealso>, and - <seealso marker="#statistics_total_run_queue_lengths"> - <c>statistics(total_run_queue_lengths)</c></seealso>.</p> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_active_tasks"><c>statistics(active_tasks)</c></seealso><c>)</c>, + but more efficient.</p> </desc> </func> <func> - <name name="statistics" arity="1" clause_i="13"/> + <name name="statistics" arity="1" clause_i="16"/> + <fsummary>Information about active processes and ports.</fsummary> + <desc><marker id="statistics_total_active_tasks_all"></marker> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_active_tasks_all"><c>statistics(active_tasks_all)</c></seealso><c>)</c>, + but more efficient.</p> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="17"/> <fsummary>Information about the run-queue lengths.</fsummary> <desc><marker id="statistics_total_run_queue_lengths"></marker> - <p>Returns the total length of the run queues. That is, the number - of processes and ports that are ready to run on all available - run queues. The information is <em>not</em> gathered atomically. - That is, the result is not necessarily a consistent snapshot of - the state, but much more efficiently gathered compared to - <seealso marker="#statistics_run_queue"> - <c>statistics(run_queue)</c></seealso>.</p> - <p>See also <seealso marker="#statistics_run_queue_lengths"> - <c>statistics(run_queue_lengths)</c></seealso>, - <seealso marker="#statistics_total_active_tasks"> - <c>statistics(total_active_tasks)</c></seealso>, and - <seealso marker="#statistics_active_tasks"> - <c>statistics(active_tasks)</c></seealso>.</p> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_run_queue_lengths"><c>statistics(run_queue_lengths)</c></seealso><c>)</c>, + but more efficient.</p> </desc> </func> <func> - <name name="statistics" arity="1" clause_i="14"/> + <name name="statistics" arity="1" clause_i="18"/> + <fsummary>Information about the run-queue lengths.</fsummary> + <desc><marker id="statistics_total_run_queue_lengths_all"></marker> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_run_queue_lengths_all"><c>statistics(run_queue_lengths_all)</c></seealso><c>)</c>, + but more efficient.</p> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="19"/> <fsummary>Information about wall clock.</fsummary> <desc> <p>Returns information about wall clock. <c>wall_clock</c> can @@ -6689,11 +6883,6 @@ ok down to 3. Similarly, the number of dirty CPU schedulers online increases proportionally to increases in the number of schedulers online.</p> - <note> - <p>The dirty schedulers functionality is experimental. - Enable support for dirty schedulers when building OTP to - try out the functionality.</p> - </note> <p>For more information, see <seealso marker="#system_info_dirty_cpu_schedulers"> <c>erlang:system_info(dirty_cpu_schedulers)</c></seealso> and @@ -7196,8 +7385,8 @@ ok </func> <func> - <name name="system_info" arity="1" clause_i="10"/> - <name name="system_info" arity="1" clause_i="11"/> + <name name="system_info" arity="1" clause_i="12"/> + <name name="system_info" arity="1" clause_i="13"/> <fsummary>Information about the CPU topology of the system.</fsummary> <type name="cpu_topology"/> <type name="level_entry"/> @@ -7297,12 +7486,12 @@ ok </func> <func> - <name name="system_info" arity="1" clause_i="27"/> - <name name="system_info" arity="1" clause_i="28"/> - <name name="system_info" arity="1" clause_i="36"/> - <name name="system_info" arity="1" clause_i="37"/> + <name name="system_info" arity="1" clause_i="29"/> + <name name="system_info" arity="1" clause_i="30"/> <name name="system_info" arity="1" clause_i="38"/> <name name="system_info" arity="1" clause_i="39"/> + <name name="system_info" arity="1" clause_i="40"/> + <name name="system_info" arity="1" clause_i="41"/> <fsummary>Information about the default process heap settings.</fsummary> <type name="message_queue_data"/> <type name="max_heap_size"/> @@ -7345,12 +7534,6 @@ ok see <seealso marker="#process_flag_max_heap_size"> <c>process_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> </item> - <tag><c>min_heap_size</c></tag> - <item> - <p>Returns <c>{min_heap_size, <anno>MinHeapSize</anno>}</c>, - where <c><anno>MinHeapSize</anno></c> is the current - system-wide minimum heap size for spawned processes.</p> - </item> <tag><marker id="system_info_message_queue_data"/> <c>message_queue_data</c></tag> <item> @@ -7363,6 +7546,12 @@ ok <seealso marker="#process_flag_message_queue_data"> <c>process_flag(message_queue_data, MQD)</c></seealso>.</p> </item> + <tag><c>min_heap_size</c></tag> + <item> + <p>Returns <c>{min_heap_size, <anno>MinHeapSize</anno>}</c>, + where <c><anno>MinHeapSize</anno></c> is the current + system-wide minimum heap size for spawned processes.</p> + </item> <tag><c>min_bin_vheap_size</c></tag> <item> <p>Returns <c>{min_bin_vheap_size, @@ -7379,8 +7568,8 @@ ok <name name="system_info" arity="1" clause_i="7"/> <name name="system_info" arity="1" clause_i="8"/> <name name="system_info" arity="1" clause_i="9"/> - <name name="system_info" arity="1" clause_i="12"/> - <name name="system_info" arity="1" clause_i="13"/> + <name name="system_info" arity="1" clause_i="10"/> + <name name="system_info" arity="1" clause_i="11"/> <name name="system_info" arity="1" clause_i="14"/> <name name="system_info" arity="1" clause_i="15"/> <name name="system_info" arity="1" clause_i="16"/> @@ -7394,15 +7583,15 @@ ok <name name="system_info" arity="1" clause_i="24"/> <name name="system_info" arity="1" clause_i="25"/> <name name="system_info" arity="1" clause_i="26"/> - <name name="system_info" arity="1" clause_i="29"/> - <name name="system_info" arity="1" clause_i="30"/> + <name name="system_info" arity="1" clause_i="27"/> + <name name="system_info" arity="1" clause_i="28"/> <name name="system_info" arity="1" clause_i="31"/> <name name="system_info" arity="1" clause_i="32"/> <name name="system_info" arity="1" clause_i="33"/> <name name="system_info" arity="1" clause_i="34"/> <name name="system_info" arity="1" clause_i="35"/> - <name name="system_info" arity="1" clause_i="40"/> - <name name="system_info" arity="1" clause_i="41"/> + <name name="system_info" arity="1" clause_i="36"/> + <name name="system_info" arity="1" clause_i="37"/> <name name="system_info" arity="1" clause_i="42"/> <name name="system_info" arity="1" clause_i="43"/> <name name="system_info" arity="1" clause_i="44"/> @@ -7431,16 +7620,28 @@ ok <name name="system_info" arity="1" clause_i="67"/> <name name="system_info" arity="1" clause_i="68"/> <name name="system_info" arity="1" clause_i="69"/> + <name name="system_info" arity="1" clause_i="70"/> + <name name="system_info" arity="1" clause_i="71"/> <fsummary>Information about the system.</fsummary> <desc> <p>Returns various information about the current system (emulator) as specified by <c><anno>Item</anno></c>:</p> <taglist> - <tag><c>allocated_areas</c>, <c>allocator</c>, - <c>alloc_util_allocators</c>, <c>allocator_sizes</c></tag> + <tag><c>atom_count</c></tag> + <item> + <marker id="system_info_atom_count"></marker> + <p>Returns the number of atoms currently existing at the + local node. The value is given as an integer.</p> + </item> + <tag><c>atom_limit</c></tag> <item> - <p>See <seealso marker="#system_info_allocator_tags"> - above</seealso>.</p> + <marker id="system_info_atom_limit"></marker> + <p>Returns the maximum number of atoms allowed. + This limit can be increased at startup by passing + command-line flag + <seealso marker="erts:erl#+t"><c>+t</c></seealso> to + <c>erl(1)</c>. + </p> </item> <tag><c>build_type</c></tag> <item> @@ -7526,9 +7727,6 @@ ok <seealso marker="erts:erl#+SDcpu"><c>+SDcpu</c></seealso> or <seealso marker="erts:erl#+SDPcpu"><c>+SDPcpu</c></seealso> in <c>erl(1)</c>.</p> - <p>Notice that the dirty schedulers functionality is - experimental. Enable support for dirty schedulers when - building OTP to try out the functionality.</p> <p>See also <seealso marker="#system_flag_dirty_cpu_schedulers_online"> <c>erlang:system_flag(dirty_cpu_schedulers_online, @@ -7558,9 +7756,6 @@ ok startup by passing command-line flag <seealso marker="erts:erl#+SDcpu"><c>+SDcpu</c></seealso> in <c>erl(1)</c>.</p> - <p>Notice that the dirty schedulers functionality is - experimental. Enable support for dirty schedulers when - building OTP to try out the functionality.</p> <p>For more information, see <seealso marker="#system_info_dirty_cpu_schedulers"> <c>erlang:system_info(dirty_cpu_schedulers)</c></seealso>, @@ -7582,9 +7777,6 @@ ok <p>This value can be set at startup by passing command-line argument <seealso marker="erts:erl#+SDio"><c>+SDio</c></seealso> in <c>erl(1)</c>.</p> - <p>Notice that the dirty schedulers functionality is - experimental. Enable support for dirty schedulers when - building OTP to try out the functionality.</p> <p>For more information, see <seealso marker="#system_info_dirty_cpu_schedulers"> <c>erlang:system_info(dirty_cpu_schedulers)</c></seealso>, diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml index 8ab35851c1..d3f725ef99 100644 --- a/erts/doc/src/erts_alloc.xml +++ b/erts/doc/src/erts_alloc.xml @@ -4,7 +4,7 @@ <cref> <header> <copyright> - <year>2002</year><year>2016</year> + <year>2002</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -452,7 +452,7 @@ utilization value > 0 is used, allocator instances are allowed to abandon multiblock carriers. If <c>de</c> (default enabled) is passed instead of a <c><![CDATA[<utilization>]]></c>, - a recomended non-zero utilization value is used. The value + a recommended non-zero utilization value is used. The value chosen depends on the allocator type and can be changed between ERTS versions. Defaults to <c>de</c>, but this can be changed in the future.</p> @@ -595,7 +595,7 @@ </item> <tag><marker id="M_sbct"/><c><![CDATA[+M<S>sbct <size>]]></c></tag> <item> - <p>Singleblock carrier threshold. Blocks larger than this + <p>Singleblock carrier threshold (in kilobytes). Blocks larger than this threshold are placed in singleblock carriers. Blocks smaller than this threshold are placed in multiblock carriers. On 32-bit Unix style OS this threshold cannot be set diff --git a/erts/doc/src/escript.xml b/erts/doc/src/escript.xml index 1d5d280338..9b0d42185e 100644 --- a/erts/doc/src/escript.xml +++ b/erts/doc/src/escript.xml @@ -4,7 +4,7 @@ <comref> <header> <copyright> - <year>2007</year><year>2016</year> + <year>2007</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -35,6 +35,28 @@ <p><c>escript</c> provides support for running short Erlang programs without having to compile them first, and an easy way to retrieve the command-line arguments.</p> + + <p>It is possible to bundle <c>escript</c>(s) with an Erlang + runtime system to make it self-sufficient and relocatable. In such + a standalone system, the <c>escript</c>(s) should be located in + the top <c>bin</c> directory of the standalone system and given + <c>.escript</c> as file extension. Further the (built-in) + <c>escript</c> program should be copied to the same directory and + given the scripts original name (without the <c>.escript</c> + extension). This will enable use of the bundled Erlang runtime + system.</p> + + <p>The (built-in) <c>escript</c> program first determines which + Erlang runtime system to use and then starts it to execute your + script. Usually the runtime system is located in the same Erlang + installation as the <c>escript</c> program itself. But for + standalone systems with one or more escripts it may be the case + that the <c>escript</c> program in your path actually starts the + runtime system bundled with the escript. This is intentional, and + typically happens when the standalone system <c>bin</c> directory is not + in the execution path (as it may cause its <c>erl</c> program to + override the desired one) and the <c>escript</c>(s) are referred to via + symbolic links from a <c>bin</c> directory in the path.</p> </description> <funcs> diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index d70b734809..e61114c504 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -909,7 +909,7 @@ <list> <item> <p> - Fixed a VM crash that occured in a garbage collection of + Fixed a VM crash that occurred in a garbage collection of a process when it had received binaries. This bug was introduced in ERTS version 8.0 (OTP 19.0).</p> <p> @@ -926,7 +926,7 @@ <list> <item> <p> - Fixed a VM crash that occured in garbage collection of a + Fixed a VM crash that occurred in garbage collection of a process when it had received maps over the distribution. This bug was introduced in ERTS version 8.0 (OTP 19.0).</p> <p> @@ -6142,7 +6142,7 @@ dependent, so applications aiming to be portable should consider using <c>{ipv6_v6only,true}</c> when creating an <c>inet6</c> listening/destination socket, and if - neccesary also create an <c>inet</c> socket on the same + necessary also create an <c>inet</c> socket on the same port for IPv4 traffic. See the documentation.</p> <p> Own Id: OTP-8928 Aux Id: kunagi-193 [104] </p> @@ -6523,7 +6523,7 @@ This change of default value will reduce lock contention on ETS tables using the <c>read_concurrency</c> option at the expense of memory consumption when the amount of - schedulers and logical processors are beween 8 and 64. + schedulers and logical processors are between 8 and 64. For more information, see documentation of the <c>+rg</c> command line argument of <c>erl(1)</c>.</p> <p> @@ -7500,7 +7500,7 @@ <p> For the subsection about process_flag(save_calls, N) there's an unrelated paragraph about process priorities - which was copied from the preceeding subsection regarding + which was copied from the preceding subsection regarding process_flag(priority, Level). (Thanks to Filipe David Manana)</p> <p> @@ -8715,7 +8715,7 @@ <item> <p> Wx on MacOS X generated complains on stderr about certain - cocoa functions not beeing called from the "Main thread". + cocoa functions not being called from the "Main thread". This is now corrected.</p> <p> Own Id: OTP-9081</p> @@ -9706,7 +9706,7 @@ </item> <item> <p>The <c>empd</c> program could loop and consume 100% - CPU time if an unexpected error ocurred in + CPU time if an unexpected error occurred in <c>listen()</c> or <c>accept()</c>. Now <c>epmd</c> will terminate if a non-recoverable error occurs. (Thanks to Michael Santos.)</p> diff --git a/erts/doc/src/zlib.xml b/erts/doc/src/zlib.xml index f8140544b7..1d272c4c18 100644 --- a/erts/doc/src/zlib.xml +++ b/erts/doc/src/zlib.xml @@ -585,6 +585,18 @@ unpack(Z, Compressed, Dict) -> </func> <func> + <name name="inflateGetDictionary" arity="1"/> + <fsummary>Return the decompression dictionary.</fsummary> + <desc> + <p>Returns the decompression dictionary currently in use + by the stream. This function must be called between + <seealso marker="#inflateInit/1"><c>inflateInit/1,2</c></seealso> + and <seealso marker="#inflateEnd/1"><c>inflateEnd</c></seealso>.</p> + <p>Only supported if ERTS was compiled with zlib >= 1.2.8.</p> + </desc> + </func> + + <func> <name name="open" arity="0"/> <fsummary>Open a stream and return a stream reference.</fsummary> <desc> |