diff options
Diffstat (limited to 'erts/doc/src')
41 files changed, 32130 insertions, 15459 deletions
diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile index e8b856c3ff..21aa3db864 100644 --- a/erts/doc/src/Makefile +++ b/erts/doc/src/Makefile @@ -1,21 +1,22 @@ -# +# # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2012. All Rights Reserved. +# Copyright Ericsson AB 1997-2018. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# The contents of this file are subject to the Erlang Public License, -# Version 1.1, (the "License"); you may not use this file except in -# compliance with the License. You should have received a copy of the -# Erlang Public License along with this software. If not, it can be -# retrieved online at http://www.erlang.org/. +# http://www.apache.org/licenses/LICENSE-2.0 # -# Software distributed under the License is distributed on an "AS IS" -# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -# the License for the specific language governing rights and limitations -# under the License. +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. # # %CopyrightEnd% -# +# SPECS_ESRC = ../../preloaded/src/ @@ -49,12 +50,14 @@ XML_REF1_FILES = epmd.xml \ XML_REF3_EFILES = \ erl_prim_loader.xml \ erlang.xml \ + erl_tracer.xml \ init.xml \ zlib.xml XML_REF3_FILES = \ driver_entry.xml \ erl_nif.xml \ + erl_tracer.xml \ erl_driver.xml \ erl_prim_loader.xml \ erlang.xml \ @@ -63,15 +66,15 @@ XML_REF3_FILES = \ zlib.xml XML_PART_FILES = \ - part.xml \ - part_notes.xml \ - part_notes_history.xml + part.xml XML_CHAPTER_FILES = \ + introduction.xml \ tty.xml \ match_spec.xml \ crash_dump.xml \ alt_dist.xml \ + alt_disco.xml \ driver.xml \ absform.xml \ inet_cfg.xml \ @@ -79,8 +82,7 @@ XML_CHAPTER_FILES = \ erl_dist_protocol.xml \ communication.xml \ time_correction.xml \ - notes.xml \ - notes_history.xml + notes.xml TOPDOCDIR=../../../doc @@ -113,9 +115,9 @@ SPECS_FILES = $(XML_REF3_EFILES:%.xml=$(SPECDIR)/specs_%.xml) TOP_SPECS_FILE = specs.xml # ---------------------------------------------------- -# FLAGS +# FLAGS # ---------------------------------------------------- -XML_FLAGS += +XML_FLAGS += KERNEL_SRC=$(ERL_TOP)/lib/kernel/src KERNEL_INCLUDE=$(ERL_TOP)/lib/kernel/include @@ -143,32 +145,24 @@ $(INFO_FILE): $(INFO_FILE_SRC) $(ERL_TOP)/make/$(TARGET)/otp.mk sed -e 's;%RELEASE%;$(SYSTEM_VSN);' $(INFO_FILE_SRC) > $(INFO_FILE) -debug opt: +debug opt: clean: rm -rf $(HTMLDIR)/* + rm -rf $(XMLDIR) rm -f $(MAN1DIR)/* rm -f $(MAN3DIR)/* rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) rm -f $(SPECDIR)/* - rm -f errs core *~ - -$(SPECDIR)/specs_driver_entry.xml: - escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ - -o$(dir $@) -module driver_entry -$(SPECDIR)/specs_erl_nif.xml: - escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ - -o$(dir $@) -module erl_nif -$(SPECDIR)/specs_erl_driver.xml: - escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ - -o$(dir $@) -module erl_driver -$(SPECDIR)/specs_erts_alloc.xml: - escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ - -o$(dir $@) -module erts_alloc + rm -f errs core *~ + +$(SPECDIR)/specs_%.xml: + $(gen_verbose)escript $(SPECS_EXTRACTOR) $(SPECS_FLAGS) \ + -o$(dir $@) -module $(patsubst $(SPECDIR)/specs_%.xml,%,$@) # ---------------------------------------------------- # Release Target -# ---------------------------------------------------- +# ---------------------------------------------------- include $(ERL_TOP)/make/otp_release_targets.mk release_docs_spec: docs @@ -177,6 +171,10 @@ release_docs_spec: docs $(INSTALL_DIR) "$(RELSYSDIR)/doc/html" $(INSTALL_DATA) $(HTMLDIR)/* \ "$(RELSYSDIR)/doc/html" + $(INSTALL_DATA) $(ERL_TOP)/erts/example/time_compat.erl \ + "$(RELSYSDIR)/doc/html" + $(INSTALL_DATA) $(ERL_TOP)/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl \ + "$(RELSYSDIR)/doc/html" $(INSTALL_DATA) $(INFO_FILE) "$(RELSYSDIR)" $(INSTALL_DIR) "$(RELEASE_PATH)/man/man3" $(INSTALL_DATA) $(MAN3DIR)/* "$(RELEASE_PATH)/man/man3" diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml index 835a4fc692..d77d989057 100644 --- a/erts/doc/src/absform.xml +++ b/erts/doc/src/absform.xml @@ -4,470 +4,979 @@ <chapter> <header> <copyright> - <year>2001</year><year>2013</year> + <year>2001</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + </legalnotice> <title>The Abstract Format</title> <prepared>Arndt Jonasson</prepared> <responsible>Kenneth Lundin</responsible> <docno>1</docno> - <approved>Jultomten</approved> + <approved></approved> <checked></checked> - <date>00-12-01</date> + <date>2000-12-01</date> <rev>A</rev> <file>absform.xml</file> </header> - <p></p> - <p>This document describes the standard representation of parse trees for Erlang - programs as Erlang terms. This representation is known as the <em>abstract format</em>. - Functions dealing with such parse trees are <c><![CDATA[compile:forms/[1,2]]]></c> - and functions in the modules - <c><![CDATA[epp]]></c>, - <c><![CDATA[erl_eval]]></c>, - <c><![CDATA[erl_lint]]></c>, - <c><![CDATA[erl_pp]]></c>, - <c><![CDATA[erl_parse]]></c>, - and - <c><![CDATA[io]]></c>. - They are also used as input and output for parse transforms (see the module - <c><![CDATA[compile]]></c>).</p> - <p>We use the function <c><![CDATA[Rep]]></c> to denote the mapping from an Erlang source - construct <c><![CDATA[C]]></c> to its abstract format representation <c><![CDATA[R]]></c>, and write - <c><![CDATA[R = Rep(C)]]></c>. - </p> - <p>The word <c><![CDATA[LINE]]></c> below represents an integer, and denotes the + <p>This section describes the standard representation of parse trees for Erlang + programs as Erlang terms. This representation is known as the <em>abstract + format</em>. Functions dealing with such parse trees are + <seealso marker="compiler:compile#forms/1"> + <c>compile:forms/1,2</c></seealso> and functions in the following + modules:</p> + + <list type="bulleted"> + <item><seealso marker="stdlib:epp"> + <c>epp(3)</c></seealso></item> + <item><seealso marker="stdlib:erl_eval"> + <c>erl_eval(3)</c></seealso></item> + <item><seealso marker="stdlib:erl_lint"> + <c>erl_lint(3)</c></seealso></item> + <item><seealso marker="stdlib:erl_parse"> + <c>erl_parse(3)</c></seealso></item> + <item><seealso marker="stdlib:erl_pp"> + <c>erl_pp(3)</c></seealso></item> + <item><seealso marker="stdlib:io"> + <c>io(3)</c></seealso></item> + </list> + + <p>The functions are also used as input and output for parse transforms, see + the <seealso marker="compiler:compile"><c>compile(3)</c></seealso> + module.</p> + + <p>We use the function <c>Rep</c> to denote the mapping from an Erlang source + construct <c>C</c> to its abstract format representation <c>R</c>, and write + <c>R = Rep(C)</c>.</p> + + <p>The word <c>LINE</c> in this section represents an integer, and denotes the number of the line in the source file where the construction occurred. - Several instances of <c><![CDATA[LINE]]></c> in the same construction may denote + Several instances of <c>LINE</c> in the same construction can denote different lines.</p> - <p>Since operators are not terms in their own right, when operators are - mentioned below, the representation of an operator should be taken to + + <p>As operators are not terms in their own right, when operators are + mentioned below, the representation of an operator is to be taken to be the atom with a printname consisting of the same characters as the - operator. - </p> + operator.</p> <section> - <title>Module declarations and forms</title> - <p>A module declaration consists of a sequence of forms that are either + <title>Module Declarations and Forms</title> + <p>A module declaration consists of a sequence of forms, which are either function declarations or attributes.</p> + <list type="bulleted"> - <item>If D is a module declaration consisting of the forms - <c><![CDATA[F_1]]></c>, ..., <c><![CDATA[F_k]]></c>, then - Rep(D) = <c><![CDATA[[Rep(F_1), ..., Rep(F_k)]]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-module(Mod)]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,module,Mod}]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-export([Fun_1/A_1, ..., Fun_k/A_k])]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-import(Mod,[Fun_1/A_1, ..., Fun_k/A_k])]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}}]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-compile(Options)]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,compile,Options}]]></c>.</item> - <item>If F is an attribute <c><![CDATA[-file(File,Line)]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,file,{File,Line}}]]></c>.</item> - <item>If F is a record declaration <c><![CDATA[-record(Name,{V_1, ..., V_k})]]></c>, then - Rep(F) = - <c><![CDATA[{attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}]]></c>. For Rep(V), see below.</item> - <item>If F is a wild attribute <c><![CDATA[-A(T)]]></c>, then - Rep(F) = <c><![CDATA[{attribute,LINE,A,T}]]></c>. - <br></br></item> - <item>If F is a function declaration <c><![CDATA[Name Fc_1 ; ... ; Name Fc_k]]></c>, - where each <c><![CDATA[Fc_i]]></c> is a function clause with a - pattern sequence of the same length <c><![CDATA[Arity]]></c>, then - Rep(F) = <c><![CDATA[{function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}]]></c>.</item> + <item> + <p>If D is a module declaration consisting of the forms + <c>F_1</c>, ..., <c>F_k</c>, then + Rep(D) = <c>[Rep(F_1), ..., Rep(F_k)]</c>.</p> + </item> + <item> + <p>If F is an attribute <c>-export([Fun_1/A_1, ..., Fun_k/A_k])</c>, + then Rep(F) = + <c>{attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}</c>.</p> + </item> + <item> + <p>If F is an attribute <c>-import(Mod,[Fun_1/A_1, ..., Fun_k/A_k])</c>, + then Rep(F) = + <c>{attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., + {Fun_k,A_k}]}}</c>.</p> + </item> + <item> + <p>If F is an attribute <c>-module(Mod)</c>, then + Rep(F) = <c>{attribute,LINE,module,Mod}</c>.</p> + </item> + <item> + <p>If F is an attribute <c>-file(File,Line)</c>, then + Rep(F) = <c>{attribute,LINE,file,{File,Line}}</c>.</p> + </item> + <item> + <p>If F is a function declaration <c>Name Fc_1 ; ... ; Name Fc_k</c>, + where each <c>Fc_i</c> is a function clause with a pattern sequence of + the same length <c>Arity</c>, then Rep(F) = + <c>{function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}</c>.</p> + </item> + <item> + <p>If F is a function specification <c>-Spec Name Ft_1; ...; Ft_k</c>, + where <c>Spec</c> is either the atom <c>spec</c> or the atom + <c>callback</c>, and each <c>Ft_i</c> is a possibly constrained + function type with an argument sequence of the same length + <c>Arity</c>, then Rep(F) = + <c>{attribute,Line,Spec,{{Name,Arity},[Rep(Ft_1), ..., + Rep(Ft_k)]}}</c>.</p> + </item> + <item> + <p>If F is a function specification + <c>-spec Mod:Name Ft_1; ...; Ft_k</c>, where each <c>Ft_i</c> is a + possibly constrained function type with an argument sequence of the + same length <c>Arity</c>, then Rep(F) = + <c>{attribute,Line,spec,{{Mod,Name,Arity},[Rep(Ft_1), ..., + Rep(Ft_k)]}}</c>.</p> + </item> + <item> + <p>If F is a record declaration <c>-record(Name,{V_1, ..., V_k})</c>, + where each <c>V_i</c> is a record field, then Rep(F) = + <c>{attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}</c>. + For Rep(V), see below.</p> + </item> + <item> + <p>If F is a type declaration <c>-Type Name(V_1, ..., V_k) :: T</c>, + where <c>Type</c> is either the atom <c>type</c> or the atom + <c>opaque</c>, each <c>V_i</c> is a variable, and <c>T</c> is a type, + then Rep(F) = + <c>{attribute,LINE,Type,{Name,Rep(T),[Rep(V_1), ..., + Rep(V_k)]}}</c>.</p> + </item> + <item> + <p>If F is a wild attribute <c>-A(T)</c>, then + Rep(F) = <c>{attribute,LINE,A,T}</c>.</p> + </item> </list> <section> - <title>Record fields</title> - <p>Each field in a record declaration may have an optional - explicit default initializer expression</p> + <title>Record Fields</title> + <p>Each field in a record declaration can have an optional, + explicit, default initializer expression, and an + optional type.</p> + <list type="bulleted"> - <item>If V is <c><![CDATA[A]]></c>, then - Rep(V) = <c><![CDATA[{record_field,LINE,Rep(A)}]]></c>.</item> - <item>If V is <c><![CDATA[A = E]]></c>, then - Rep(V) = <c><![CDATA[{record_field,LINE,Rep(A),Rep(E)}]]></c>.</item> + <item> + <p>If V is <c>A</c>, then + Rep(V) = <c>{record_field,LINE,Rep(A)}</c>.</p> + </item> + <item> + <p>If V is <c>A = E</c>, where <c>E</c> is an expression, then + Rep(V) = <c>{record_field,LINE,Rep(A),Rep(E)}</c>.</p> + </item> + <item> + <p>If V is <c>A :: T</c>, where <c>T</c> is a type, then Rep(V) = + <c>{typed_record_field,{record_field,LINE,Rep(A)},Rep(T)}</c>.</p> + </item> + <item> + <p>If V is <c>A = E :: T</c>, where + <c>E</c> is an expression and <c>T</c> is a type, then Rep(V) = + <c>{typed_record_field,{record_field,LINE,Rep(A),Rep(E)},Rep(T)}</c>. + </p> + </item> </list> </section> <section> - <title>Representation of parse errors and end of file</title> + <title>Representation of Parse Errors and End-of-File</title> <p>In addition to the representations of forms, the list that represents - a module declaration (as returned by functions in <c><![CDATA[erl_parse]]></c> and - <c><![CDATA[epp]]></c>) may contain tuples <c><![CDATA[{error,E}]]></c> and <c><![CDATA[{warning,W}]]></c>, denoting - syntactically incorrect forms and warnings, and <c><![CDATA[{eof,LINE}]]></c>, denoting an end - of stream encountered before a complete form had been parsed.</p> + a module declaration (as returned by functions in + <seealso marker="stdlib:epp"><c>epp(3)</c></seealso> and + <seealso marker="stdlib:erl_parse"><c>erl_parse(3)</c></seealso>) + can contain the following:</p> + + <list type="bulleted"> + <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> <section> - <title>Atomic literals</title> + <title>Atomic Literals</title> <p>There are five kinds of atomic literals, which are represented in the - same way in patterns, expressions and guards:</p> + same way in patterns, expressions, and guards:</p> + <list type="bulleted"> - <item>If L is an integer or character literal, then - Rep(L) = <c><![CDATA[{integer,LINE,L}]]></c>.</item> - <item>If L is a float literal, then - Rep(L) = <c><![CDATA[{float,LINE,L}]]></c>.</item> - <item>If L is a string literal consisting of the characters - <c><![CDATA[C_1]]></c>, ..., <c><![CDATA[C_k]]></c>, then - Rep(L) = <c><![CDATA[{string,LINE,[C_1, ..., C_k]}]]></c>.</item> - <item>If L is an atom literal, then - Rep(L) = <c><![CDATA[{atom,LINE,L}]]></c>.</item> + <item> + <p>If L is an atom literal, then Rep(L) = <c>{atom,LINE,L}</c>.</p> + </item> + <item> + <p>If L is a character literal, then Rep(L) = <c>{char,LINE,L}</c>.</p> + </item> + <item> + <p>If L is a float literal, then Rep(L) = <c>{float,LINE,L}</c>.</p> + </item> + <item> + <p>If L is an integer literal, then + Rep(L) = <c>{integer,LINE,L}</c>.</p> + </item> + <item> + <p>If L is a string literal consisting of the characters + <c>C_1</c>, ..., <c>C_k</c>, then + Rep(L) = <c>{string,LINE,[C_1, ..., C_k]}</c>.</p> + </item> </list> - <p>Note that negative integer and float literals do not occur as such; they are - parsed as an application of the unary negation operator.</p> + + <p>Notice that negative integer and float literals do not occur as such; + they are parsed as an application of the unary negation operator.</p> </section> <section> <title>Patterns</title> - <p>If <c><![CDATA[Ps]]></c> is a sequence of patterns <c><![CDATA[P_1, ..., P_k]]></c>, then - Rep(Ps) = <c><![CDATA[[Rep(P_1), ..., Rep(P_k)]]]></c>. Such sequences occur as the + <p>If Ps is a sequence of patterns <c>P_1, ..., P_k</c>, then + Rep(Ps) = <c>[Rep(P_1), ..., Rep(P_k)]</c>. Such sequences occur as the list of arguments to a function or fun.</p> + <p>Individual patterns are represented as follows:</p> + <list type="bulleted"> - <item>If P is an atomic literal L, then Rep(P) = Rep(L).</item> - <item>If P is a compound pattern <c><![CDATA[P_1 = P_2]]></c>, then - Rep(P) = <c><![CDATA[{match,LINE,Rep(P_1),Rep(P_2)}]]></c>.</item> - <item>If P is a variable pattern <c><![CDATA[V]]></c>, then - Rep(P) = <c><![CDATA[{var,LINE,A}]]></c>, - where A is an atom with a printname consisting of the same characters as - <c><![CDATA[V]]></c>.</item> - <item>If P is a universal pattern <c><![CDATA[_]]></c>, then - Rep(P) = <c><![CDATA[{var,LINE,'_'}]]></c>.</item> - <item>If P is a tuple pattern <c><![CDATA[{P_1, ..., P_k}]]></c>, then - Rep(P) = <c><![CDATA[{tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}]]></c>.</item> - <item>If P is a nil pattern <c><![CDATA[[]]]></c>, then - Rep(P) = <c><![CDATA[{nil,LINE}]]></c>.</item> - <item>If P is a cons pattern <c><![CDATA[[P_h | P_t]]]></c>, then - Rep(P) = <c><![CDATA[{cons,LINE,Rep(P_h),Rep(P_t)}]]></c>.</item> - <item>If E is a binary pattern <c><![CDATA[<<P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>>]]></c>, then - Rep(E) = <c><![CDATA[{bin,LINE,[{bin_element,LINE,Rep(P_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(P_k),Rep(Size_k),Rep(TSL_k)}]}]]></c>. - For Rep(TSL), see below. - An omitted <c><![CDATA[Size]]></c> is represented by <c><![CDATA[default]]></c>. An omitted <c><![CDATA[TSL]]></c> - (type specifier list) is represented by <c><![CDATA[default]]></c>.</item> - <item>If P is <c><![CDATA[P_1 Op P_2]]></c>, where <c><![CDATA[Op]]></c> is a binary operator (this - is either an occurrence of <c><![CDATA[++]]></c> applied to a literal string or character - list, or an occurrence of an expression that can be evaluated to a number - at compile time), - then Rep(P) = <c><![CDATA[{op,LINE,Op,Rep(P_1),Rep(P_2)}]]></c>.</item> - <item>If P is <c><![CDATA[Op P_0]]></c>, where <c><![CDATA[Op]]></c> is a unary operator (this is an - occurrence of an expression that can be evaluated to a number at compile - time), then Rep(P) = <c><![CDATA[{op,LINE,Op,Rep(P_0)}]]></c>.</item> - <item>If P is a record pattern <c><![CDATA[#Name{Field_1=P_1, ..., Field_k=P_k}]]></c>, - then Rep(P) = - <c><![CDATA[{record,LINE,Name, [{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(P_k)}]}]]></c>.</item> - <item>If P is <c><![CDATA[#Name.Field]]></c>, then - Rep(P) = <c><![CDATA[{record_index,LINE,Name,Rep(Field)}]]></c>.</item> - <item>If P is <c><![CDATA[( P_0 )]]></c>, then - Rep(P) = <c><![CDATA[Rep(P_0)]]></c>, - i.e., patterns cannot be distinguished from their bodies.</item> + <item> + <p>If P is an atomic literal <c>L</c>, then Rep(P) = Rep(L).</p> + </item> + <item> + <p>If P is a bitstring pattern + <c><<P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>></c>, where each + <c>Size_i</c> is an expression that can be evaluated to an integer, + and each <c>TSL_i</c> is a type specificer list, then Rep(P) = + <c>{bin,LINE,[{bin_element,LINE,Rep(P_1),Rep(Size_1),Rep(TSL_1)}, + ..., {bin_element,LINE,Rep(P_k),Rep(Size_k),Rep(TSL_k)}]}</c>. + For Rep(TSL), see below. + An omitted <c>Size_i</c> is represented by <c>default</c>. + An omitted <c>TSL_i</c> is represented by <c>default</c>.</p> + </item> + <item> + <p>If P is a compound pattern <c>P_1 = P_2</c>, then Rep(P) = + <c>{match,LINE,Rep(P_1),Rep(P_2)}</c>.</p> + </item> + <item> + <p>If P is a cons pattern <c>[P_h | P_t]</c>, then Rep(P) = + <c>{cons,LINE,Rep(P_h),Rep(P_t)}</c>.</p> + </item> + <item> + <p>If P is a map pattern <c>#{A_1, ..., A_k}</c>, where each + <c>A_i</c> is an association <c>P_i_1 := P_i_2</c>, then Rep(P) = + <c>{map,LINE,[Rep(A_1), ..., Rep(A_k)]}</c>. + For Rep(A), see below.</p> + </item> + <item> + <p>If P is a nil pattern <c>[]</c>, then Rep(P) = + <c>{nil,LINE}</c>.</p> + </item> + <item> + <p>If P is an operator pattern <c>P_1 Op P_2</c>, where <c>Op</c> is a + binary operator (this is either an occurrence of <c>++</c> applied to + a literal string or character list, or an occurrence of an expression + that can be evaluated to a number at compile time), then Rep(P) = + <c>{op,LINE,Op,Rep(P_1),Rep(P_2)}</c>.</p> + </item> + <item> + <p>If P is an operator pattern <c>Op P_0</c>, where <c>Op</c> is a + unary operator (this is an occurrence of an expression that can be + evaluated to a number at compile time), then Rep(P) = + <c>{op,LINE,Op,Rep(P_0)}</c>.</p> + </item> + <item> + <p>If P is a parenthesized pattern <c>( P_0 )</c>, then Rep(P) = + <c>Rep(P_0)</c>, that is, parenthesized patterns cannot be + distinguished from their bodies.</p> + </item> + <item> + <p>If P is a record field index pattern <c>#Name.Field</c>, + where <c>Field</c> is an atom, then Rep(P) = + <c>{record_index,LINE,Name,Rep(Field)}</c>.</p> + </item> + <item> + <p>If P is a record pattern <c>#Name{Field_1=P_1, ..., Field_k=P_k}</c>, + where each <c>Field_i</c> is an atom or <c>_</c>, then Rep(P) = + <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., + {record_field,LINE,Rep(Field_k),Rep(P_k)}]}</c>.</p> + </item> + <item> + <p>If P is a tuple pattern <c>{P_1, ..., P_k}</c>, then Rep(P) = + <c>{tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}</c>.</p> + </item> + <item> + <p>If P is a universal pattern <c>_</c>, then Rep(P) = + <c>{var,LINE,'_'}</c>.</p></item> + <item> + <p>If P is a variable pattern <c>V</c>, then Rep(P) = + <c>{var,LINE,A}</c>, where A is an atom with a printname consisting + of the same characters as <c>V</c>.</p> + </item> </list> - <p>Note that every pattern has the same source form as some expression, and is - represented the same way as the corresponding expression.</p> + + <p>Notice that every pattern has the same source form as some expression, + and is represented in the same way as the corresponding expression.</p> </section> <section> <title>Expressions</title> - <p>A body B is a sequence of expressions <c><![CDATA[E_1, ..., E_k]]></c>, and - Rep(B) = <c><![CDATA[[Rep(E_1), ..., Rep(E_k)]]]></c>.</p> - <p>An expression E is one of the following alternatives:</p> + <p>A body B is a non-empty sequence of expressions <c>E_1, ..., E_k</c>, + and Rep(B) = <c>[Rep(E_1), ..., Rep(E_k)]</c>.</p> + + <p>An expression E is one of the following:</p> + <list type="bulleted"> - <item>If P is an atomic literal <c><![CDATA[L]]></c>, then - Rep(P) = Rep(L).</item> - <item>If E is <c><![CDATA[P = E_0]]></c>, then - Rep(E) = <c><![CDATA[{match,LINE,Rep(P),Rep(E_0)}]]></c>.</item> - <item>If E is a variable <c><![CDATA[V]]></c>, then - Rep(E) = <c><![CDATA[{var,LINE,A}]]></c>, - where <c><![CDATA[A]]></c> is an atom with a printname consisting of the same - characters as <c><![CDATA[V]]></c>.</item> - <item>If E is a tuple skeleton <c><![CDATA[{E_1, ..., E_k}]]></c>, then - Rep(E) = <c><![CDATA[{tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}]]></c>.</item> - <item>If E is <c><![CDATA[[]]]></c>, then - Rep(E) = <c><![CDATA[{nil,LINE}]]></c>.</item> - <item>If E is a cons skeleton <c><![CDATA[[E_h | E_t]]]></c>, then - Rep(E) = <c><![CDATA[{cons,LINE,Rep(E_h),Rep(E_t)}]]></c>.</item> - <item>If E is a binary constructor <c><![CDATA[<<V_1:Size_1/TSL_1, ..., V_k:Size_k/TSL_k>>]]></c>, then - Rep(E) = <c><![CDATA[{bin,LINE,[{bin_element,LINE,Rep(V_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(V_k),Rep(Size_k),Rep(TSL_k)}]}]]></c>. - For Rep(TSL), see below. - An omitted <c><![CDATA[Size]]></c> is represented by <c><![CDATA[default]]></c>. An omitted <c><![CDATA[TSL]]></c> - (type specifier list) is represented by <c><![CDATA[default]]></c>.</item> - <item>If E is <c><![CDATA[E_1 Op E_2]]></c>, where <c><![CDATA[Op]]></c> is a binary operator, - then Rep(E) = <c><![CDATA[{op,LINE,Op,Rep(E_1),Rep(E_2)}]]></c>.</item> - <item>If E is <c><![CDATA[Op E_0]]></c>, where <c><![CDATA[Op]]></c> is a unary operator, then - Rep(E) = <c><![CDATA[{op,LINE,Op,Rep(E_0)}]]></c>.</item> - <item>If E is <c><![CDATA[#Name{Field_1=E_1, ..., Field_k=E_k}]]></c>, then - Rep(E) = - <c><![CDATA[{record,LINE,Name, [{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}]]></c>.</item> - <item>If E is <c><![CDATA[E_0#Name{Field_1=E_1, ..., Field_k=E_k}]]></c>, then - Rep(E) = - <c><![CDATA[{record,LINE,Rep(E_0),Name, [{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}]]></c>.</item> - <item>If E is <c><![CDATA[#Name.Field]]></c>, then - Rep(E) = <c><![CDATA[{record_index,LINE,Name,Rep(Field)}]]></c>.</item> - <item>If E is <c><![CDATA[E_0#Name.Field]]></c>, then - Rep(E) = <c><![CDATA[{record_field,LINE,Rep(E_0),Name,Rep(Field)}]]></c>.</item> - <item>If E is <c><![CDATA[#{W_1, ..., W_k}]]></c> where each - <c><![CDATA[W_i]]></c> is a map assoc or exact field, then Rep(E) = - <c><![CDATA[{map,LINE,[Rep(W_1), ..., Rep(W_k)]}]]></c>. For Rep(W), see - below.</item> - <item>If E is <c><![CDATA[E_0#{W_1, ..., W_k}]]></c> where - <c><![CDATA[W_i]]></c> is a map assoc or exact field, then Rep(E) = - <c><![CDATA[{map,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}]]></c>. For - Rep(W), see below.</item> - <item>If E is <c><![CDATA[catch E_0]]></c>, then - Rep(E) = <c><![CDATA[{'catch',LINE,Rep(E_0)}]]></c>.</item> - <item>If E is <c><![CDATA[E_0(E_1, ..., E_k)]]></c>, then - Rep(E) = <c><![CDATA[{call,LINE,Rep(E_0),[Rep(E_1), ..., Rep(E_k)]}]]></c>.</item> - <item>If E is <c><![CDATA[E_m:E_0(E_1, ..., E_k)]]></c>, then - Rep(E) = - <c><![CDATA[{call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., Rep(E_k)]}]]></c>.</item> - <item>If E is a list comprehension <c><![CDATA[[E_0 || W_1, ..., W_k]]]></c>, - where each <c><![CDATA[W_i]]></c> is a generator or a filter, then - Rep(E) = <c><![CDATA[{lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}]]></c>. For Rep(W), see - below.</item> - <item>If E is a binary comprehension <c><![CDATA[<<E_0 || W_1, ..., W_k>>]]></c>, - where each <c><![CDATA[W_i]]></c> is a generator or a filter, then - Rep(E) = <c><![CDATA[{bc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}]]></c>. For Rep(W), see - below.</item> - <item>If E is <c><![CDATA[begin B end]]></c>, where <c><![CDATA[B]]></c> is a body, then - Rep(E) = <c><![CDATA[{block,LINE,Rep(B)}]]></c>.</item> - <item>If E is <c><![CDATA[if Ic_1 ; ... ; Ic_k end]]></c>, - where each <c><![CDATA[Ic_i]]></c> is an if clause then - Rep(E) = - <c><![CDATA[{'if',LINE,[Rep(Ic_1), ..., Rep(Ic_k)]}]]></c>.</item> - <item>If E is <c><![CDATA[case E_0 of Cc_1 ; ... ; Cc_k end]]></c>, - where <c><![CDATA[E_0]]></c> is an expression and each <c><![CDATA[Cc_i]]></c> is a - case clause then - Rep(E) = - <c><![CDATA[{'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}]]></c>.</item> - <item>If E is <c><![CDATA[try B catch Tc_1 ; ... ; Tc_k end]]></c>, - where <c><![CDATA[B]]></c> is a body and each <c><![CDATA[Tc_i]]></c> is a catch clause then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],[]}]]></c>.</item> - <item>If E is <c><![CDATA[try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end]]></c>, - where <c><![CDATA[B]]></c> is a body, - each <c><![CDATA[Cc_i]]></c> is a case clause and - each <c><![CDATA[Tc_j]]></c> is a catch clause then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],[]}]]></c>.</item> - <item>If E is <c><![CDATA[try B after A end]]></c>, - where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are bodies then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[],[],Rep(A)}]]></c>.</item> - <item>If E is <c><![CDATA[try B of Cc_1 ; ... ; Cc_k after A end]]></c>, - where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are a bodies and - each <c><![CDATA[Cc_i]]></c> is a case clause then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[],Rep(A)}]]></c>.</item> - <item>If E is <c><![CDATA[try B catch Tc_1 ; ... ; Tc_k after A end]]></c>, - where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are bodies and - each <c><![CDATA[Tc_i]]></c> is a catch clause then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],Rep(A)}]]></c>.</item> - <item>If E is <c><![CDATA[try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A end]]></c>, - where <c><![CDATA[B]]></c> and <c><![CDATA[A]]></c> are a bodies, - each <c><![CDATA[Cc_i]]></c> is a case clause and - each <c><![CDATA[Tc_j]]></c> is a catch clause then - Rep(E) = - <c><![CDATA[{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],Rep(A)}]]></c>.</item> - <item>If E is <c><![CDATA[receive Cc_1 ; ... ; Cc_k end]]></c>, - where each <c><![CDATA[Cc_i]]></c> is a case clause then - Rep(E) = - <c><![CDATA[{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}]]></c>.</item> - <item>If E is <c><![CDATA[receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end]]></c>, - where each <c><![CDATA[Cc_i]]></c> is a case clause, - <c><![CDATA[E_0]]></c> is an expression and <c><![CDATA[B_t]]></c> is a body, then - Rep(E) = - <c><![CDATA[{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)],Rep(E_0),Rep(B_t)}]]></c>.</item> - <item>If E is <c><![CDATA[fun Name / Arity]]></c>, then - Rep(E) = <c><![CDATA[{'fun',LINE,{function,Name,Arity}}]]></c>.</item> - <item>If E is <c><![CDATA[fun Module:Name/Arity]]></c>, then - Rep(E) = <c><![CDATA[{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}]]></c>. - (Before the R15 release: Rep(E) = <c><![CDATA[{'fun',LINE,{function,Module,Name,Arity}}]]></c>.)</item> - <item>If E is <c><![CDATA[fun Fc_1 ; ... ; Fc_k end]]></c> - where each <c><![CDATA[Fc_i]]></c> is a function clause then Rep(E) = - <c><![CDATA[{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}]]></c>.</item> - <item>If E is <c><![CDATA[fun Name Fc_1 ; ... ; Name Fc_k end]]></c> - where <c><![CDATA[Name]]></c> is a variable and each - <c><![CDATA[Fc_i]]></c> is a function clause then Rep(E) = - <c><![CDATA[{named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}]]></c>. - </item> - <item>If E is <c><![CDATA[query [E_0 || W_1, ..., W_k] end]]></c>, - where each <c><![CDATA[W_i]]></c> is a generator or a filter, then - Rep(E) = <c><![CDATA[{'query',LINE,{lc,LINE,Rep(E_0),[Rep(W_1), ..., Rep(W_k)]}}]]></c>. - For Rep(W), see below.</item> - <item>If E is <c><![CDATA[E_0.Field]]></c>, a Mnesia record access - inside a query, then - Rep(E) = <c><![CDATA[{record_field,LINE,Rep(E_0),Rep(Field)}]]></c>.</item> - <item>If E is <c><![CDATA[( E_0 )]]></c>, then - Rep(E) = <c><![CDATA[Rep(E_0)]]></c>, - i.e., parenthesized expressions cannot be distinguished from their bodies.</item> + <item> + <p>If E is an atomic literal <c>L</c>, then Rep(E) = Rep(L).</p> + </item> + <item> + <p>If E is a bitstring comprehension + <c><<E_0 || Q_1, ..., Q_k>></c>, + where each <c>Q_i</c> is a qualifier, then Rep(E) = + <c>{bc,LINE,Rep(E_0),[Rep(Q_1), ..., Rep(Q_k)]}</c>. + For Rep(Q), see below.</p> + </item> + <item> + <p>If E is a bitstring constructor + <c><<E_1:Size_1/TSL_1, ..., E_k:Size_k/TSL_k>></c>, + where each <c>Size_i</c> is an expression and each + <c>TSL_i</c> is a type specificer list, then Rep(E) = + <c>{bin,LINE,[{bin_element,LINE,Rep(E_1),Rep(Size_1),Rep(TSL_1)}, + ..., {bin_element,LINE,Rep(E_k),Rep(Size_k),Rep(TSL_k)}]}</c>. + For Rep(TSL), see below. + An omitted <c>Size_i</c> is represented by <c>default</c>. + An omitted <c>TSL_i</c> is represented by <c>default</c>.</p> + </item> + <item> + <p>If E is a block expression <c>begin B end</c>, + where <c>B</c> is a body, then Rep(E) = + <c>{block,LINE,Rep(B)}</c>.</p> + </item> + <item> + <p>If E is a case expression <c>case E_0 of Cc_1 ; ... ; Cc_k end</c>, + where <c>E_0</c> is an expression and each <c>Cc_i</c> is a + case clause, then Rep(E) = + <c>{'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}</c>.</p> + </item> + <item> + <p>If E is a catch expression <c>catch E_0</c>, then Rep(E) = + <c>{'catch',LINE,Rep(E_0)}</c>.</p> + </item> + <item> + <p>If E is a cons skeleton <c>[E_h | E_t]</c>, then Rep(E) = + <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) = + <c>{'fun',LINE,{function,Name,Arity}}</c>.</p> + </item> + <item> + <p>If E is a fun expression <c>fun Module:Name/Arity</c>, then Rep(E) = + <c>{'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}</c>. + (Before Erlang/OTP R15: Rep(E) = + <c>{'fun',LINE,{function,Module,Name,Arity}}</c>.)</p> + </item> + <item> + <p>If E is a fun expression <c>fun Fc_1 ; ... ; Fc_k end</c>, + where each <c>Fc_i</c> is a function clause, then Rep(E) = + <c>{'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}</c>.</p> + </item> + <item> + <p>If E is a fun expression <c>fun Name Fc_1 ; ... ; Name Fc_k end</c>, + where <c>Name</c> is a variable and each + <c>Fc_i</c> is a function clause, then Rep(E) = + <c>{named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}</c>.</p> + </item> + <item> + <p>If E is a function call <c>E_0(E_1, ..., E_k)</c>, then Rep(E) = + <c>{call,LINE,Rep(E_0),[Rep(E_1), ..., Rep(E_k)]}</c>.</p> + </item> + <item> + <p>If E is a function call <c>E_m:E_0(E_1, ..., E_k)</c>, then Rep(E) = + <c>{call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., + Rep(E_k)]}</c>.</p> + </item> + <item> + <p>If E is an if expression <c>if Ic_1 ; ... ; Ic_k end</c>, + where each <c>Ic_i</c> is an if clause, then Rep(E) = + <c>{'if',LINE,[Rep(Ic_1), ..., Rep(Ic_k)]}</c>.</p> + </item> + <item> + <p>If E is a list comprehension <c>[E_0 || Q_1, ..., Q_k]</c>, + where each <c>Q_i</c> is a qualifier, then Rep(E) = + <c>{lc,LINE,Rep(E_0),[Rep(Q_1), ..., Rep(Q_k)]}</c>. + For Rep(Q), see below.</p> + </item> + <item> + <p>If E is a map creation <c>#{A_1, ..., A_k}</c>, + where each <c>A_i</c> is an association <c>E_i_1 => E_i_2</c>, + then Rep(E) = <c>{map,LINE,[Rep(A_1), ..., Rep(A_k)]}</c>. + For Rep(A), see below.</p> + </item> + <item> + <p>If E is a map update <c>E_0#{A_1, ..., A_k}</c>, + where each <c>A_i</c> is an association <c>E_i_1 => E_i_2</c> + or <c>E_i_1 := E_i_2</c>, then Rep(E) = + <c>{map,LINE,Rep(E_0),[Rep(A_1), ..., Rep(A_k)]}</c>. + For Rep(A), see below.</p> + </item> + <item> + <p>If E is a match operator expression <c>P = E_0</c>, + where <c>P</c> is a pattern, then Rep(E) = + <c>{match,LINE,Rep(P),Rep(E_0)}</c>.</p> + </item> + <item> + <p>If E is nil, <c>[]</c>, then Rep(E) = <c>{nil,LINE}</c>.</p> + </item> + <item> + <p>If E is an operator expression <c>E_1 Op E_2</c>, + where <c>Op</c> is a binary operator other than match operator + <c>=</c>, then Rep(E) = + <c>{op,LINE,Op,Rep(E_1),Rep(E_2)}</c>.</p> + </item> + <item> + <p>If E is an operator expression <c>Op E_0</c>, + where <c>Op</c> is a unary operator, then Rep(E) = + <c>{op,LINE,Op,Rep(E_0)}</c>.</p> + </item> + <item> + <p>If E is a parenthesized expression <c>( E_0 )</c>, then Rep(E) = + <c>Rep(E_0)</c>, that is, parenthesized expressions cannot be + distinguished from their bodies.</p> + </item> + <item> + <p>If E is a receive expression <c>receive Cc_1 ; ... ; Cc_k end</c>, + where each <c>Cc_i</c> is a case clause, then Rep(E) = + <c>{'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}</c>.</p> + </item> + <item> + <p>If E is a receive expression + <c>receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end</c>, + where each <c>Cc_i</c> is a case clause, <c>E_0</c> is an expression, + and <c>B_t</c> is a body, then Rep(E) = + <c>{'receive',LINE,[Rep(Cc_1), ..., + Rep(Cc_k)],Rep(E_0),Rep(B_t)}</c>.</p> + </item> + <item> + <p>If E is a record creation + <c>#Name{Field_1=E_1, ..., Field_k=E_k}</c>, + where each <c>Field_i</c> is an atom or <c>_</c>, then Rep(E) = + <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, + ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}</c>.</p> + </item> + <item> + <p>If E is a record field access <c>E_0#Name.Field</c>, + where <c>Field</c> is an atom, then Rep(E) = + <c>{record_field,LINE,Rep(E_0),Name,Rep(Field)}</c>.</p> + </item> + <item> + <p>If E is a record field index <c>#Name.Field</c>, + where <c>Field</c> is an atom, then Rep(E) = + <c>{record_index,LINE,Name,Rep(Field)}</c>.</p></item> + <item> + <p>If E is a record update + <c>E_0#Name{Field_1=E_1, ..., Field_k=E_k}</c>, + where each <c>Field_i</c> is an atom, then Rep(E) = + <c>{record,LINE,Rep(E_0),Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, + ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}</c>.</p> + </item> + <item> + <p>If E is a tuple skeleton <c>{E_1, ..., E_k}</c>, then Rep(E) = + <c>{tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}</c>.</p> + </item> + <item> + <p>If E is a try expression <c>try B catch Tc_1 ; ... ; Tc_k end</c>, + where <c>B</c> is a body and each <c>Tc_i</c> is a catch clause, + then Rep(E) = + <c>{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],[]}</c>.</p> + </item> + <item> + <p>If E is a try expression + <c>try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end</c>, + where <c>B</c> is a body, each <c>Cc_i</c> is a case clause, and + each <c>Tc_j</c> is a catch clause, then Rep(E) = + <c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., + Rep(Tc_n)],[]}</c>.</p> + </item> + <item> + <p>If E is a try expression <c>try B after A end</c>, + where <c>B</c> and <c>A</c> are bodies, then Rep(E) = + <c>{'try',LINE,Rep(B),[],[],Rep(A)}</c>.</p> + </item> + <item> + <p>If E is a try expression + <c>try B of Cc_1 ; ... ; Cc_k after A end</c>, + where <c>B</c> and <c>A</c> are a bodies, + and each <c>Cc_i</c> is a case clause, then Rep(E) = + <c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., + Rep(Cc_k)],[],Rep(A)}</c>.</p> + </item> + <item> + <p>If E is a try expression + <c>try B catch Tc_1 ; ... ; Tc_k after A end</c>, + where <c>B</c> and <c>A</c> are bodies, + and each <c>Tc_i</c> is a catch clause, then Rep(E) = + <c>{'try',LINE,Rep(B),[],[Rep(Tc_1), ..., + Rep(Tc_k)],Rep(A)}</c>.</p> + </item> + <item> + <p>If E is a try expression + <c>try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A + end</c>, where <c>B</c> and <c>A</c> are a bodies, + each <c>Cc_i</c> is a case clause, + and each <c>Tc_j</c> is a catch clause, then Rep(E) = + <c>{'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., + Rep(Tc_n)],Rep(A)}</c>.</p> + </item> + <item> + <p>If E is a variable <c>V</c>, then Rep(E) = <c>{var,LINE,A}</c>, + where <c>A</c> is an atom with a printname consisting of the same + characters as <c>V</c>.</p> + </item> </list> <section> - <title>Generators and filters</title> - <p>When W is a generator or a filter (in the body of a list or binary comprehension), then:</p> + <title>Qualifiers</title> + <p>A qualifier Q is one of the following:</p> + <list type="bulleted"> - <item>If W is a generator <c><![CDATA[P <- E]]></c>, where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[E]]></c> - is an expression, then - Rep(W) = <c><![CDATA[{generate,LINE,Rep(P),Rep(E)}]]></c>.</item> - <item>If W is a generator <c><![CDATA[P <= E]]></c>, where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[E]]></c> - is an expression, then - Rep(W) = <c><![CDATA[{b_generate,LINE,Rep(P),Rep(E)}]]></c>.</item> - <item>If W is a filter <c><![CDATA[E]]></c>, which is an expression, then - Rep(W) = <c><![CDATA[Rep(E)]]></c>.</item> + <item> + <p>If Q is a filter <c>E</c>, where <c>E</c> is an expression, then + Rep(Q) = <c>Rep(E)</c>.</p> + </item> + <item> + <p>If Q is a generator <c>P <- E</c>, where <c>P</c> is + a pattern and <c>E</c> is an expression, then Rep(Q) = + <c>{generate,LINE,Rep(P),Rep(E)}</c>.</p> + </item> + <item> + <p>If Q is a bitstring generator <c>P <= E</c>, where <c>P</c> is + a pattern and <c>E</c> is an expression, then Rep(Q) = + <c>{b_generate,LINE,Rep(P),Rep(E)}</c>.</p> + </item> </list> </section> <section> - <title>Binary element type specifiers</title> - <p>A type specifier list TSL for a binary element is a sequence of type - specifiers <c><![CDATA[TS_1 - ... - TS_k]]></c>. - Rep(TSL) = <c><![CDATA[[Rep(TS_1), ..., Rep(TS_k)]]]></c>.</p> - <p>When TS is a type specifier for a binary element, then:</p> + <title>Bitstring Element Type Specifiers</title> + <p>A type specifier list TSL for a bitstring element is a sequence + of type specifiers <c>TS_1 - ... - TS_k</c>, and + Rep(TSL) = <c>[Rep(TS_1), ..., Rep(TS_k)]</c>.</p> + <list type="bulleted"> - <item>If TS is an atom <c><![CDATA[A]]></c>, Rep(TS) = <c><![CDATA[A]]></c>.</item> - <item>If TS is a couple <c><![CDATA[A:Value]]></c> where <c><![CDATA[A]]></c> is an atom and <c><![CDATA[Value]]></c> - is an integer, Rep(TS) = <c><![CDATA[{A, Value}]]></c>.</item> + <item> + <p>If TS is a type specifier <c>A</c>, where <c>A</c> is an atom, + then Rep(TS) = <c>A</c>.</p> + </item> + <item> + <p>If TS is a type specifier <c>A:Value</c>, + where <c>A</c> is an atom and <c>Value</c> is an integer, + then Rep(TS) = <c>{A,Value}</c>.</p> + </item> </list> </section> <section> - <title>Map assoc and exact fields</title> - <p>When W is an assoc or exact field (in the body of a map), then:</p> + <title>Associations</title> + <p>An association A is one of the following:</p> + <list type="bulleted"> - <item>If W is an assoc field <c><![CDATA[K => V]]></c>, where - <c><![CDATA[K]]></c> and <c><![CDATA[V]]></c> are both expressions, - then Rep(W) = <c><![CDATA[{map_field_assoc,LINE,Rep(K),Rep(V)}]]></c>. - </item> - <item>If W is an exact field <c><![CDATA[K := V]]></c>, where - <c><![CDATA[K]]></c> and <c><![CDATA[V]]></c> are both expressions, - then Rep(W) = <c><![CDATA[{map_field_exact,LINE,Rep(K),Rep(V)}]]></c>. - </item> + <item> + <p>If A is an association <c>K => V</c>, + then Rep(A) = <c>{map_field_assoc,LINE,Rep(K),Rep(V)}</c>.</p> + </item> + <item> + <p>If A is an association <c>K := V</c>, + then Rep(A) = <c>{map_field_exact,LINE,Rep(K),Rep(V)}</c>.</p> + </item> </list> </section> </section> <section> <title>Clauses</title> - <p>There are function clauses, if clauses, case clauses + <p>There are function clauses, if clauses, case clauses, and catch clauses.</p> - <p>A clause <c><![CDATA[C]]></c> is one of the following alternatives:</p> + + <p>A clause C is one of the following:</p> + <list type="bulleted"> - <item>If C is a function clause <c><![CDATA[( Ps ) -> B]]></c> - where <c><![CDATA[Ps]]></c> is a pattern sequence and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,Rep(Ps),[],Rep(B)}]]></c>.</item> - <item>If C is a function clause <c><![CDATA[( Ps ) when Gs -> B]]></c> - where <c><![CDATA[Ps]]></c> is a pattern sequence, - <c><![CDATA[Gs]]></c> is a guard sequence and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}]]></c>.</item> - <item>If C is an if clause <c><![CDATA[Gs -> B]]></c> - where <c><![CDATA[Gs]]></c> is a guard sequence and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[],Rep(Gs),Rep(B)}]]></c>.</item> - <item>If C is a case clause <c><![CDATA[P -> B]]></c> - where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep(P)],[],Rep(B)}]]></c>.</item> - <item>If C is a case clause <c><![CDATA[P when Gs -> B]]></c> - where <c><![CDATA[P]]></c> is a pattern, - <c><![CDATA[Gs]]></c> is a guard sequence and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep(P)],Rep(Gs),Rep(B)}]]></c>.</item> - <item>If C is a catch clause <c><![CDATA[P -> B]]></c> - where <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep({throw,P,_})],[],Rep(B)}]]></c>.</item> - <item>If C is a catch clause <c><![CDATA[X : P -> B]]></c> - where <c><![CDATA[X]]></c> is an atomic literal or a variable pattern, - <c><![CDATA[P]]></c> is a pattern and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep({X,P,_})],[],Rep(B)}]]></c>.</item> - <item>If C is a catch clause <c><![CDATA[P when Gs -> B]]></c> - where <c><![CDATA[P]]></c> is a pattern, <c><![CDATA[Gs]]></c> is a guard sequence - and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}]]></c>.</item> - <item>If C is a catch clause <c><![CDATA[X : P when Gs -> B]]></c> - where <c><![CDATA[X]]></c> is an atomic literal or a variable pattern, - <c><![CDATA[P]]></c> is a pattern, <c><![CDATA[Gs]]></c> is a guard sequence - and <c><![CDATA[B]]></c> is a body, then - Rep(C) = <c><![CDATA[{clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}]]></c>.</item> + <item> + <p>If C is a case clause <c>P -> B</c>, + where <c>P</c> is a pattern and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep(P)],[],Rep(B)}</c>.</p> + </item> + <item> + <p>If C is a case clause <c>P when Gs -> B</c>, + where <c>P</c> is a pattern, + <c>Gs</c> is a guard sequence, and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep(P)],Rep(Gs),Rep(B)}</c>.</p> + </item> + <item> + <p>If C is a catch clause <c>P -> B</c>, + where <c>P</c> is a pattern and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],[],Rep(B)}</c>, + that is, a catch clause with an explicit exception class + <c>throw</c> and with or without an explicit stacktrace + variable <c>_</c> cannot be distinguished from a catch clause + without an explicit exception class and without an explicit + stacktrace variable.</p> + </item> + <item> + <p>If C is a catch clause <c>X : P -> B</c>, + where <c>X</c> is an atomic literal or a variable pattern, + <c>P</c> is a pattern, and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],[],Rep(B)}</c>, + that is, a catch clause with an explicit exception class and + with an explicit stacktrace variable <c>_</c> cannot be + distinguished from a catch clause with an explicit exception + class and without an explicit stacktrace variable.</p> + </item> + <item> + <p>If C is a catch clause <c>X : P : S -> B</c>, + where <c>X</c> is an atomic literal or a variable pattern, + <c>P</c> is a pattern, <c>S</c> is a variable, and <c>B</c> + is a body, then + Rep(C) = <c>{clause,LINE,[Rep({X,P,S})],[],Rep(B)}</c>.</p> + </item> + <item> + <p>If C is a catch clause <c>P when Gs -> B</c>, + where <c>P</c> is a pattern, <c>Gs</c> is a guard sequence, + and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}</c>, + that is, a catch clause with an explicit exception class + <c>throw</c> and with or without an explicit stacktrace + variable <c>_</c> cannot be distinguished from a catch clause + without an explicit exception class and without an explicit + stacktrace variable.</p> + </item> + <item> + <p>If C is a catch clause <c>X : P when Gs -> B</c>, + where <c>X</c> is an atomic literal or a variable pattern, + <c>P</c> is a pattern, <c>Gs</c> is a guard sequence, + and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}</c>, + that is, a catch clause with an explicit exception class and + with an explicit stacktrace variable <c>_</c> cannot be + distinguished from a catch clause with an explicit exception + class and without an explicit stacktrace variable.</p> + </item> + <item> + <p>If C is a catch clause <c>X : P : S when Gs -> B</c>, + where <c>X</c> is an atomic literal or a variable pattern, + <c>P</c> is a pattern, <c>Gs</c> is a guard sequence, + <c>S</c> is a variable, and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[Rep({X,P,S})],Rep(Gs),Rep(B)}</c>.</p> + </item> + <item> + <p>If C is a function clause <c>( Ps ) -> B</c>, + where <c>Ps</c> is a pattern sequence and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,Rep(Ps),[],Rep(B)}</c>.</p> + </item> + <item> + <p>If C is a function clause <c>( Ps ) when Gs -> B</c>, + where <c>Ps</c> is a pattern sequence, + <c>Gs</c> is a guard sequence and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}</c>.</p> + </item> + <item> + <p>If C is an if clause <c>Gs -> B</c>, + where <c>Gs</c> is a guard sequence and <c>B</c> is a body, then + Rep(C) = <c>{clause,LINE,[],Rep(Gs),Rep(B)}</c>.</p> + </item> </list> </section> <section> <title>Guards</title> - <p>A guard sequence Gs is a sequence of guards <c><![CDATA[G_1; ...; G_k]]></c>, and - Rep(Gs) = <c><![CDATA[[Rep(G_1), ..., Rep(G_k)]]]></c>. If the guard sequence is - empty, Rep(Gs) = <c><![CDATA[[]]]></c>.</p> - <p>A guard G is a nonempty sequence of guard tests <c><![CDATA[Gt_1, ..., Gt_k]]></c>, and - Rep(G) = <c><![CDATA[[Rep(Gt_1), ..., Rep(Gt_k)]]]></c>.</p> - <p>A guard test <c><![CDATA[Gt]]></c> is one of the following alternatives:</p> + <p>A guard sequence Gs is a sequence of guards <c>G_1; ...; G_k</c>, and + Rep(Gs) = <c>[Rep(G_1), ..., Rep(G_k)]</c>. If the guard sequence is + empty, then Rep(Gs) = <c>[]</c>.</p> + + <p>A guard G is a non-empty sequence of guard tests + <c>Gt_1, ..., Gt_k</c>, and Rep(G) = + <c>[Rep(Gt_1), ..., Rep(Gt_k)]</c>.</p> + + <p>A guard test Gt is one of the following:</p> + + <list type="bulleted"> + <item> + <p>If Gt is an atomic literal <c>L</c>, then Rep(Gt) = Rep(L).</p> + </item> + <item> + <p>If Gt is a bitstring constructor + <c><<Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>></c>, + where each <c>Size_i</c> is a guard test and each + <c>TSL_i</c> is a type specificer list, then Rep(Gt) = + <c>{bin,LINE,[{bin_element,LINE,Rep(Gt_1),Rep(Size_1),Rep(TSL_1)}, + ..., {bin_element,LINE,Rep(Gt_k),Rep(Size_k),Rep(TSL_k)}]}</c>. + For Rep(TSL), see above. + An omitted <c>Size_i</c> is represented by <c>default</c>. + An omitted <c>TSL_i</c> is represented by <c>default</c>.</p> + </item> + <item> + <p>If Gt is a cons skeleton <c>[Gt_h | Gt_t]</c>, then Rep(Gt) = + <c>{cons,LINE,Rep(Gt_h),Rep(Gt_t)}</c>.</p> + </item> + <item> + <p>If Gt is a function call <c>A(Gt_1, ..., Gt_k)</c>, + where <c>A</c> is an atom, then Rep(Gt) = + <c>{call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</p> + </item> + <item> + <p>If Gt is a function call <c>A_m:A(Gt_1, ..., Gt_k)</c>, + where <c>A_m</c> is the atom <c>erlang</c> and <c>A</c> is + an atom or an operator, then Rep(Gt) = + <c>{call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., + Rep(Gt_k)]}</c>.</p> + </item> + <item> + <p>If Gt is a map creation <c>#{A_1, ..., A_k}</c>, + where each <c>A_i</c> is an association <c>Gt_i_1 => Gt_i_2</c>, + then Rep(Gt) = <c>{map,LINE,[Rep(A_1), ..., Rep(A_k)]}</c>. + For Rep(A), see above.</p> + </item> + <item> + <p>If Gt is a map update <c>Gt_0#{A_1, ..., A_k}</c>, + where each <c>A_i</c> is an association <c>Gt_i_1 => Gt_i_2</c> + or <c>Gt_i_1 := Gt_i_2</c>, then Rep(Gt) = + <c>{map,LINE,Rep(Gt_0),[Rep(A_1), ..., Rep(A_k)]}</c>. + For Rep(A), see above.</p> + </item> + <item> + <p>If Gt is nil, <c>[]</c>, then Rep(Gt) = <c>{nil,LINE}</c>.</p> + </item> + <item> + <p>If Gt is an operator guard test <c>Gt_1 Op Gt_2</c>, + where <c>Op</c> is a binary operator other than match + operator <c>=</c>, then Rep(Gt) = + <c>{op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}</c>.</p> + </item> + <item> + <p>If Gt is an operator guard test <c>Op Gt_0</c>, + where <c>Op</c> is a unary operator, then Rep(Gt) = + <c>{op,LINE,Op,Rep(Gt_0)}</c>.</p> + </item> + <item> + <p>If Gt is a parenthesized guard test <c>( Gt_0 )</c>, then Rep(Gt) = + <c>Rep(Gt_0)</c>, that is, parenthesized + guard tests cannot be distinguished from their bodies.</p> + </item> + <item> + <p>If Gt is a record creation + <c>#Name{Field_1=Gt_1, ..., Field_k=Gt_k}</c>, + where each <c>Field_i</c> is an atom or <c>_</c>, then Rep(Gt) = + <c>{record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, + ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}</c>.</p> + </item> + <item> + <p>If Gt is a record field access <c>Gt_0#Name.Field</c>, + where <c>Field</c> is an atom, then Rep(Gt) = + <c>{record_field,LINE,Rep(Gt_0),Name,Rep(Field)}</c>.</p> + </item> + <item> + <p>If Gt is a record field index <c>#Name.Field</c>, + where <c>Field</c> is an atom, then Rep(Gt) = + <c>{record_index,LINE,Name,Rep(Field)}</c>.</p> + </item> + <item> + <p>If Gt is a tuple skeleton <c>{Gt_1, ..., Gt_k}</c>, then Rep(Gt) = + <c>{tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}</c>.</p> + </item> + <item> + <p>If Gt is a variable pattern <c>V</c>, then Rep(Gt) = + <c>{var,LINE,A}</c>, where A is an atom with + a printname consisting of the same characters as <c>V</c>.</p> + </item> + </list> + + <p>Notice that every guard test has the same source form as some expression, + and is represented in the same way as the corresponding expression.</p> + </section> + + <section> + <title>Types</title> <list type="bulleted"> - <item>If Gt is an atomic literal L, then Rep(Gt) = Rep(L).</item> - <item>If Gt is a variable pattern <c><![CDATA[V]]></c>, then - Rep(Gt) = <c><![CDATA[{var,LINE,A}]]></c>, - where A is an atom with a printname consisting of the same characters as - <c><![CDATA[V]]></c>.</item> - <item>If Gt is a tuple skeleton <c><![CDATA[{Gt_1, ..., Gt_k}]]></c>, then - Rep(Gt) = <c><![CDATA[{tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item> - <item>If Gt is <c><![CDATA[[]]]></c>, then - Rep(Gt) = <c><![CDATA[{nil,LINE}]]></c>.</item> - <item>If Gt is a cons skeleton <c><![CDATA[[Gt_h | Gt_t]]]></c>, then - Rep(Gt) = <c><![CDATA[{cons,LINE,Rep(Gt_h),Rep(Gt_t)}]]></c>.</item> - <item>If Gt is a binary constructor <c><![CDATA[<<Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>>]]></c>, then - Rep(Gt) = <c><![CDATA[{bin,LINE,[{bin_element,LINE,Rep(Gt_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(Gt_k),Rep(Size_k),Rep(TSL_k)}]}]]></c>. - For Rep(TSL), see above. - An omitted <c><![CDATA[Size]]></c> is represented by <c><![CDATA[default]]></c>. An omitted <c><![CDATA[TSL]]></c> - (type specifier list) is represented by <c><![CDATA[default]]></c>.</item> - <item>If Gt is <c><![CDATA[Gt_1 Op Gt_2]]></c>, where <c><![CDATA[Op]]></c> - is a binary operator, then Rep(Gt) = <c><![CDATA[{op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}]]></c>.</item> - <item>If Gt is <c><![CDATA[Op Gt_0]]></c>, where <c><![CDATA[Op]]></c> is a unary operator, then - Rep(Gt) = <c><![CDATA[{op,LINE,Op,Rep(Gt_0)}]]></c>.</item> - <item>If Gt is <c><![CDATA[#Name{Field_1=Gt_1, ..., Field_k=Gt_k}]]></c>, then - Rep(E) = - <c><![CDATA[{record,LINE,Name, [{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}]]></c>.</item> - <item>If Gt is <c><![CDATA[#Name.Field]]></c>, then - Rep(Gt) = <c><![CDATA[{record_index,LINE,Name,Rep(Field)}]]></c>.</item> - <item>If Gt is <c><![CDATA[Gt_0#Name.Field]]></c>, then - Rep(Gt) = <c><![CDATA[{record_field,LINE,Rep(Gt_0),Name,Rep(Field)}]]></c>.</item> - <item>If Gt is <c><![CDATA[A(Gt_1, ..., Gt_k)]]></c>, where <c><![CDATA[A]]></c> is an atom, then - Rep(Gt) = <c><![CDATA[{call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item> - <item>If Gt is <c><![CDATA[A_m:A(Gt_1, ..., Gt_k)]]></c>, where <c><![CDATA[A_m]]></c> is - the atom <c><![CDATA[erlang]]></c> and <c><![CDATA[A]]></c> is an atom or an operator, then - Rep(Gt) = <c><![CDATA[{call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item> - <item>If Gt is <c><![CDATA[{A_m,A}(Gt_1, ..., Gt_k)]]></c>, where <c><![CDATA[A_m]]></c> is - the atom <c><![CDATA[erlang]]></c> and <c><![CDATA[A]]></c> is an atom or an operator, then - Rep(Gt) = <c><![CDATA[{call,LINE,Rep({A_m,A}),[Rep(Gt_1), ..., Rep(Gt_k)]}]]></c>.</item> - <item>If Gt is <c><![CDATA[( Gt_0 )]]></c>, then - Rep(Gt) = <c><![CDATA[Rep(Gt_0)]]></c>, - i.e., parenthesized guard tests cannot be distinguished from their bodies.</item> + <item> + <p>If T is an annotated type <c>A :: T_0</c>, + where <c>A</c> is a variable, then Rep(T) = + <c>{ann_type,LINE,[Rep(A),Rep(T_0)]}</c>.</p> + </item> + <item> + <p>If T is an atom, a character, or an integer literal L, + then Rep(T) = Rep(L).</p> + </item> + <item> + <p>If T is a bitstring type <c><<_:M,_:_*N>></c>, + where <c>M</c> and <c>N</c> are singleton integer types, then Rep(T) = + <c>{type,LINE,binary,[Rep(M),Rep(N)]}</c>.</p> + </item> + <item> + <p>If T is the empty list type <c>[]</c>, then Rep(T) = + <c>{type,Line,nil,[]}</c>, that is, the empty list type + <c>[]</c> cannot be distinguished from the predefined type + <c>nil()</c>.</p> + </item> + <item> + <p>If T is a fun type <c>fun()</c>, then Rep(T) = + <c>{type,LINE,'fun',[]}</c>.</p> + </item> + <item> + <p>If T is a fun type <c>fun((...) -> T_0)</c>, then Rep(T) = + <c>{type,LINE,'fun',[{type,LINE,any},Rep(T_0)]}</c>.</p> + </item> + <item> + <p>If T is a fun type <c>fun(Ft)</c>, where + <c>Ft</c> is a function type, then Rep(T) = <c>Rep(Ft)</c>. + For Rep(Ft), see below.</p> + </item> + <item> + <p>If T is an integer range type <c>L .. H</c>, + where <c>L</c> and <c>H</c> are singleton integer types, then Rep(T) = + <c>{type,LINE,range,[Rep(L),Rep(H)]}</c>.</p> + </item> + <item> + <p>If T is a map type <c>map()</c>, then Rep(T) = + <c>{type,LINE,map,any}</c>.</p> + </item> + <item> + <p>If T is a map type <c>#{A_1, ..., A_k}</c>, where each + <c>A_i</c> is an association type, then Rep(T) = + <c>{type,LINE,map,[Rep(A_1), ..., Rep(A_k)]}</c>. + For Rep(A), see below.</p> + </item> + <item> + <p>If T is an operator type <c>T_1 Op T_2</c>, + where <c>Op</c> is a binary operator (this is an occurrence of + an expression that can be evaluated to an integer at compile + time), then Rep(T) = + <c>{op,LINE,Op,Rep(T_1),Rep(T_2)}</c>.</p> + </item> + <item> + <p>If T is an operator type <c>Op T_0</c>, where <c>Op</c> is a + unary operator (this is an occurrence of an expression that can + be evaluated to an integer at compile time), then Rep(T) = + <c>{op,LINE,Op,Rep(T_0)}</c>.</p> + </item> + <item> + <p>If T is <c>( T_0 )</c>, then Rep(T) = <c>Rep(T_0)</c>, that is, + parenthesized types cannot be distinguished from their bodies.</p> + </item> + <item> + <p>If T is a predefined (or built-in) type <c>N(T_1, ..., T_k)</c>, + then Rep(T) = <c>{type,LINE,N,[Rep(T_1), ..., Rep(T_k)]}</c>.</p> + </item> + <item> + <p>If T is a record type <c>#Name{F_1, ..., F_k}</c>, + where each <c>F_i</c> is a record field type, then Rep(T) = + <c>{type,LINE,record,[Rep(Name),Rep(F_1), ..., Rep(F_k)]}</c>. + For Rep(F), see below.</p> + </item> + <item> + <p>If T is a remote type <c>M:N(T_1, ..., T_k)</c>, then Rep(T) = + <c>{remote_type,LINE,[Rep(M),Rep(N),[Rep(T_1), ..., + Rep(T_k)]]}</c>.</p> + </item> + <item> + <p>If T is a tuple type <c>tuple()</c>, then Rep(T) = + <c>{type,LINE,tuple,any}</c>.</p> + </item> + <item> + <p>If T is a tuple type <c>{T_1, ..., T_k}</c>, then Rep(T) = + <c>{type,LINE,tuple,[Rep(T_1), ..., Rep(T_k)]}</c>.</p> + </item> + <item> + <p>If T is a type union <c>T_1 | ... | T_k</c>, then Rep(T) = + <c>{type,LINE,union,[Rep(T_1), ..., Rep(T_k)]}</c>.</p> + </item> + <item> + <p>If T is a type variable <c>V</c>, then Rep(T) = + <c>{var,LINE,A}</c>, where <c>A</c> is an atom with a printname + consisting of the same characters as <c>V</c>. A type variable + is any variable except underscore (<c>_</c>).</p> + </item> + <item> + <p>If T is a user-defined type <c>N(T_1, ..., T_k)</c>, then Rep(T) = + <c>{user_type,LINE,N,[Rep(T_1), ..., Rep(T_k)]}</c>.</p> + </item> </list> - <p>Note that every guard test has the same source form as some expression, - and is represented the same way as the corresponding expression.</p> + + <section> + <title>Function Types</title> + <p>A function type Ft is one of the following:</p> + + <list type="bulleted"> + <item> + <p>If Ft is a constrained function type <c>Ft_1 when Fc</c>, + where <c>Ft_1</c> is a function type and + <c>Fc</c> is a function constraint, then Rep(T) = + <c>{type,LINE,bounded_fun,[Rep(Ft_1),Rep(Fc)]}</c>. + For Rep(Fc), see below.</p> + </item> + <item> + <p>If Ft is a function type <c>(T_1, ..., T_n) -> T_0</c>, + where each <c>T_i</c> is a type, then Rep(Ft) = + <c>{type,LINE,'fun',[{type,LINE,product,[Rep(T_1), ..., + Rep(T_n)]},Rep(T_0)]}</c>.</p> + </item> + </list> + </section> + + <section> + <title>Function Constraints</title> + <p>A function constraint Fc is a non-empty sequence of constraints + <c>C_1, ..., C_k</c>, and + Rep(Fc) = <c>[Rep(C_1), ..., Rep(C_k)]</c>.</p> + + <list type="bulleted"> + <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>. + </item> + </list> + </section> + + <section> + <title>Association Types</title> + <list type="bulleted"> + <item> + <p>If A is an association type <c>K => V</c>, + where <c>K</c> and <c>V</c> are types, then Rep(A) = + <c>{type,LINE,map_field_assoc,[Rep(K),Rep(V)]}</c>.</p> + </item> + <item> + <p>If A is an association type <c>K := V</c>, + where <c>K</c> and <c>V</c> are types, then Rep(A) = + <c>{type,LINE,map_field_exact,[Rep(K),Rep(V)]}</c>.</p> + </item> + </list> + </section> + + <section> + <title>Record Field Types</title> + <list type="bulleted"> + <item>If F is a record field type <c>Name :: Type</c>, + where <c>Type</c> is a type, then Rep(F) = + <c>{type,LINE,field_type,[Rep(Name),Rep(Type)]}</c>. + </item> + </list> + </section> </section> <section> - <title>The abstract format after preprocessing</title> - <p>The compilation option <c><![CDATA[debug_info]]></c> can be given to the - compiler to have the abstract code stored in - the <c><![CDATA[abstract_code]]></c> chunk in the BEAM file + <title>The Abstract Format after Preprocessing</title> + <p>The compilation option <c>debug_info</c> can be specified to the + compiler to have the abstract code stored in + the <c>abstract_code</c> chunk in the Beam file (for debugging purposes).</p> - <p>In OTP R9C and later, the <c><![CDATA[abstract_code]]></c> chunk will - contain</p> - <p><c><![CDATA[{raw_abstract_v1,AbstractCode}]]></c></p> - <p>where <c><![CDATA[AbstractCode]]></c> is the abstract code as described - in this document.</p> - <p>In releases of OTP prior to R9C, the abstract code after some more - processing was stored in the BEAM file. The first element of the - tuple would be either <c><![CDATA[abstract_v1]]></c> (R7B) or <c><![CDATA[abstract_v2]]></c> - (R8B).</p> + + <p>As from Erlang/OTP R9C, the <c>abstract_code</c> chunk contains + <c>{raw_abstract_v1,AbstractCode}</c>, where <c>AbstractCode</c> is the + abstract code as described in this section.</p> + + <p>In OTP releases before R9C, the abstract code after some more + processing was stored in the Beam file. The first element of the + tuple would be either <c>abstract_v1</c> (in OTP R7B) or + <c>abstract_v2</c> (in OTP R8B).</p> </section> </chapter> diff --git a/erts/doc/src/alt_disco.xml b/erts/doc/src/alt_disco.xml new file mode 100644 index 0000000000..d04221b9b3 --- /dev/null +++ b/erts/doc/src/alt_disco.xml @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2018</year><year>2018</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + </legalnotice> + + <title>How to Implement an Alternative Service Discovery for Erlang Distribution + </title> + <prepared>Timmo Verlaan</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>2018-04-25</date> + <rev>PA1</rev> + <file>alt_disco.xml</file> + </header> + <p> + This section describes how to implement an alternative discovery mechanism + for Erlang distribution. Discovery is normally done using DNS and the + Erlang Port Mapper Daemon (EPMD) for port discovery. + </p> + + <note><p> + Support for alternative service discovery mechanisms was added in Erlang/OTP + 21. + </p></note> + + + <section> + <title>Introduction</title> + <p>To implement your own service discovery module you have to write your own + EPMD module. The <seealso marker="kernel:erl_epmd">EPMD module</seealso> is + responsible for providing the location of another node. The distribution + modules (<c>inet_tcp_dist</c>/<c>inet_tls_dist</c>) call the EPMD module to + get the IP address and port of the other node. The EPMD module that is part + of Erlang/OTP will resolve the hostname using DNS and uses the EPMD unix + process to get the port of another node. The EPMD unix process does this by + connecting to the other node on a well-known port, port 4369.</p> + </section> + + <section> + <title>Discovery module</title> + <p>The discovery module needs to implement the same API as the regular + <seealso marker="kernel:erl_epmd">EPMD module</seealso>. However, instead of + communicating with EPMD you can connect to any service to find out + connection details of other nodes. A discovery module is enabled + by setting <seealso marker="erts:erl#epmd_module">-epmd_module</seealso> + when starting erlang. The discovery module must implement the following + callbacks:</p> + + <taglist> + <tag><seealso marker="kernel:erl_epmd#start_link/0">start_link/0</seealso></tag> + <item>Start any processes needed by the discovery module.</item> + <tag><seealso marker="kernel:erl_epmd#names/1">names/1</seealso></tag> + <item>Return node names held by the registrar for the given host.</item> + <tag><seealso marker="kernel:erl_epmd#register_node/2">register_node/2</seealso></tag> + <item>Register the given node name with the registrar.</item> + <tag><seealso marker="kernel:erl_epmd#port_please/3">port_please/3</seealso></tag> + <item>Return the distribution port used by the given node.</item> + </taglist> + + <p>The discovery module may implement the following callback:</p> + + <taglist> + <tag><seealso marker="kernel:erl_epmd#address_please/3">address_please/3</seealso></tag> + <item><p>Return the address of the given node. + If not implemented, <seealso marker="kernel:inet#gethostbyname/1"> + inet:gethostbyname/1</seealso> will be used instead</p> + <p>This callback may also return the port of the given node. In that case + <seealso marker="kernel:erl_epmd#port_please/3">port_please/3</seealso> + may be omitted.</p></item> + </taglist> + </section> +</chapter> diff --git a/erts/doc/src/alt_dist.xml b/erts/doc/src/alt_dist.xml index e4912576f7..e6245130fc 100644 --- a/erts/doc/src/alt_dist.xml +++ b/erts/doc/src/alt_dist.xml @@ -4,24 +4,26 @@ <chapter> <header> <copyright> - <year>2000</year><year>2013</year> + <year>2000</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> - <title>How to implement an alternative carrier for the Erlang distribution</title> + <title>How to Implement an Alternative Carrier for the Erlang Distribution + </title> <prepared>Patrik Nyblom</prepared> <responsible></responsible> <docno></docno> @@ -31,203 +33,981 @@ <rev>PA2</rev> <file>alt_dist.xml</file> </header> - <p>This document describes how one can implement ones own carrier + <p>This section describes how to implement an alternative carrier protocol for the Erlang distribution. The distribution is normally - carried by the TCP/IP protocol. What's explained here is the method for - replacing TCP/IP with another protocol. </p> - <p>The document is a step by step explanation of the <c><![CDATA[uds_dist]]></c> example - application (seated in the kernel applications <c><![CDATA[examples]]></c> directory). - The <c><![CDATA[uds_dist]]></c> application implements distribution over Unix domain - sockets and is written for the Sun Solaris 2 operating environment. The - mechanisms are however general and applies to any operating system Erlang - runs on. The reason the C code is not made portable, is simply readability.</p> - <note><p>This document was written a long time ago. Most of it is still - valid, but some things have changed since it was first written. - Most notably the driver interface. There have been some updates - to the documentation of the driver presented in this documentation, - but more could be done and are planned for the future. The - reader is encouraged to also read the - <seealso marker="erl_driver">erl_driver</seealso>, and the - <seealso marker="erl_driver">driver_entry</seealso> documentation. - </p></note> + carried by TCP/IP. Here is explained a method for replacing TCP/IP + with another protocol.</p> + + <p>The section is a step-by-step explanation of the + <c><![CDATA[uds_dist]]></c> example application (in the + Kernel application <c><![CDATA[examples]]></c> directory). The + <c><![CDATA[uds_dist]]></c> application implements distribution over Unix + domain sockets and is written for the Sun Solaris 2 operating environment. + The mechanisms are however general and apply to any operating system Erlang + runs on. The reason the C code is not made portable, is simply + readability.</p> <section> <title>Introduction</title> - <p>To implement a new carrier for the Erlang distribution, one must first - make the protocol available to the Erlang machine, which involves writing - an Erlang driver. There is no way one can use a port program, - there <em>has</em> to - be an Erlang driver. Erlang drivers can either be statically - linked - to the emulator, which can be an alternative when using the open source - distribution of Erlang, or dynamically loaded into the Erlang machines - address space, which is the only alternative if a precompiled version of - Erlang is to be used. </p> - <p>Writing an Erlang driver is by no means easy. The driver is written - as a couple of call-back functions called by the Erlang emulator when - data is sent to the driver or the driver has any data available on a file - descriptor. As the driver call-back routines execute in the main - thread of the Erlang machine, the call-back functions can perform - no blocking activity whatsoever. The call-backs should only set up - file descriptors for waiting and/or read/write available data. All - I/O has to be non blocking. Driver call-backs are however executed - in sequence, why a global state can safely be updated within the - routines. </p> - <p>When the driver is implemented, one would preferably write an - Erlang interface for the driver to be able to test the - functionality of the driver separately. This interface can then - be used by the distribution module which will cover the details of - the protocol from the <c><![CDATA[net_kernel]]></c>. The easiest path is to - mimic the <c><![CDATA[inet]]></c> and <c><![CDATA[inet_tcp]]></c> interfaces, but a lot of - functionality in those modules need not be implemented. In the - example application, only a few of the usual interfaces are - implemented, and they are much simplified.</p> - <p>When the protocol is available to Erlang through a driver and an - Erlang interface module, a distribution module can be - written. The distribution module is a module with well defined - call-backs, much like a <c><![CDATA[gen_server]]></c> (there is no compiler support - for checking the call-backs though). The details of finding other - nodes (i.e. talking to epmd or something similar), creating a - listen port (or similar), connecting to other nodes and performing - the handshakes/cookie verification are all implemented by this - module. There is however a utility module, <c><![CDATA[dist_util]]></c>, that - will do most of the hard work of handling handshakes, cookies, - timers and ticking. Using <c><![CDATA[dist_util]]></c> makes implementing a - distribution module much easier and that's what we are doing in - the example application.</p> - <p>The last step is to create boot scripts to make the protocol - implementation available at boot time. The implementation can be - debugged by starting the distribution when all of the system is - running, but in a real system the distribution should start very - early, why a boot-script and some command line parameters are - necessary. This last step also implies that the Erlang code in the - interface and distribution modules is written in such a way that - it can be run in the startup phase. Most notably there can be no - calls to the <c><![CDATA[application]]></c> module or to any modules not - loaded at boot-time (i.e. only <c><![CDATA[kernel]]></c>, <c><![CDATA[stdlib]]></c> and the - application itself can be used).</p> + <p>To implement a new carrier for the Erlang distribution, the main + steps are as follows.</p> + + <note><p> + As of ERTS version 10.0 support for distribution controller + processes has been introduced. That is, the traffic over a + distribution channel can be managed by a process instead of + only by a port. This makes it possible to implement large + parts of the logic in Erlang code, and you perhaps do not + even need a new driver for the protocol. One example could + be Erlang distribution over UDP using <c>gen_udp</c> (your + Erlang code will of course have to take care of retranspissions, + etc in this example). That is, depending on what you want + to do you perhaps do not need to implement a driver at all + and can then skip the driver related sections below. + The <c>gen_tcp_dist</c> example described in the + <seealso marker="#distribution_module">Distribution + Module</seealso> section utilize distribution controller + processes and can be worth having a look at if you want to + use distribution controller processes. + </p></note> + + <section> + <title>Writing an Erlang Driver</title> + <p>First, the protocol must be available to the Erlang machine, which + involves writing an Erlang driver. A port program cannot be used, + an Erlang driver is required. Erlang drivers can be:</p> + + <list type="bulleted"> + <item> + <p>Statically linked to the emulator, which can be an alternative + when using the open source distribution of Erlang, or</p> + </item> + <item> + <p>Dynamically loaded into the Erlang machines address space, + which is the only alternative if a precompiled version of + Erlang is to be used</p> + </item> + </list> + + <p>Writing an Erlang driver is not easy. The driver is written + as some callback functions called by the Erlang emulator when + data is sent to the driver, or the driver has any data available on + a file descriptor. As the driver callback routines execute in the main + thread of the Erlang machine, the callback functions can perform + no blocking activity whatsoever. The callbacks are only to set up + file descriptors for waiting and/or read/write available data. All + I/O must be non-blocking. Driver callbacks are however executed + in sequence, why a global state can safely be updated within the + routines.</p> + </section> + + <section> + <title>Writing an Erlang Interface for the Driver</title> + <p>When the driver is implemented, one would preferably write an + Erlang interface for the driver to be able to test the + functionality of the driver separately. This interface can then + be used by the distribution module, which will cover the details of + the protocol from the <c><![CDATA[net_kernel]]></c>.</p> + + <p>The easiest path + is to mimic the <c><![CDATA[inet]]></c> and <c><![CDATA[inet_tcp]]></c> + interfaces, but not much + functionality in those modules needs to be implemented. In the + example application, only a few of the usual interfaces are + implemented, and they are much simplified.</p> + </section> + + <section> + <title>Writing a Distribution Module</title> + <p>When the protocol is available to Erlang through a driver and an + Erlang interface module, a distribution module can be written. + The distribution module is a module with well-defined callbacks, + much like a <c><![CDATA[gen_server]]></c> (there is no compiler support + for checking the callbacks, though). This module implements:</p> + + <list type="bulleted"> + <item>The details of finding other nodes (that is, talking to + <c>epmd</c> or something similar)</item> + <item>Creating a listen port (or similar)</item> + <item>Connecting to other nodes</item> + <item>Performing the handshakes/cookie verification</item> + </list> + + <p>There is however a utility module, <c><![CDATA[dist_util]]></c>, which + does most of the hard work of handling handshakes, cookies, timers, + and ticking. Using <c><![CDATA[dist_util]]></c> makes implementing a + distribution module much easier and that is done in + the example application.</p> + </section> + + <section> + <title>Creating Boot Scripts</title> + <p>The last step is to create boot scripts to make the protocol + implementation available at boot time. The implementation can be + debugged by starting the distribution when all the system is + running, but in a real system the distribution is to start very + early, why a boot script and some command-line parameters are + necessary.</p> + + <p>This step also implies that the Erlang code in the + interface and distribution modules is written in such a way that + it can be run in the startup phase. In particular, there can be no + calls to the <c><![CDATA[application]]></c> module or to any modules + not loaded at boot time. That is, only <c><![CDATA[Kernel]]></c>, + <c><![CDATA[STDLIB]]></c>, and the application itself can be used.</p> + </section> + </section> + + <section> + <marker id="distribution_module"/> + <title>Distribution Module</title> + <p> + The distribution module expose an API that <c>net_kernel</c> call + in order to manage connections to other nodes. The module name + should have the suffix <c>_dist</c>. + </p> + <p> + The module needs to create some kind of listening entity (process + or port) and an acceptor process that accepts incoming connections + using the listening entity. For each connection, the module at least + needs to create one connection supervisor process, which also is + responsible for the handshake when setting up the connection, and + a distribution controller (process or port) responsible for + transport of data over the connection. The distribution controller + and the connection supervisor process should be linked together + so both of them are cleaned up when the connection is taken down. + </p> + <p> + Note that there need to be exactly one distribution controller + per connection. A process or port can only be distribution + controller for one connection. The registration as distribution + controller cannot be undone. It will stick until the distribution + controller terminates. The distribution controller should not + ignore exit signals. It is allowed to trap exits, but it should + then voluntarily terminate when an exit signal is received. + </p> + <p> + An example implementation of a distribution module can be found + in + <url href="gen_tcp_dist.erl">$ERL_TOP/lib/kernel/examples/gen_tcp_dist/src/gen_tcp_dist.erl</url>. + It implements the distribution over TCP/IP using the <c>gen_tcp</c> + API with distribution controllers implemented by processes. This + instead of using port distribution controllers as the ordinary TCP/IP + distribution uses. + </p> + + <section> + <marker id="distribution_module_exported_callback_functions"/> + <title>Exported Callback Functions</title> + + <p> + The following functions are mandatory: + </p> + <taglist> + <tag><marker id="listen"/><c>listen(Name) -></c><br/> <c>{ok, {Listen, Address, Creation}} | {error, Error} </c></tag> + <item> + <p> + <c>listen/1</c> is called once in order to listen for incoming + connection requests. The call is made when the distribution is brought + up. The argument <c>Name</c> is the part of the node name before + the <c>@</c> sign in the full node name. It can be either an atom or a + string. + </p> + <p> + The return value consists of a <c>Listen</c> handle (which is + later passed to the <seealso marker="#accept"><c>accept/1</c></seealso> + callback), <c>Address</c> which is a <c>#net_address{}</c> record + with information about the address for the node (the + <c>#net_address{}</c> record is defined in + <c>kernel/include/net_address.hrl</c>), and <c>Creation</c> which + (currently) is an integer <c>1</c>, <c>2</c>, or <c>3</c>. + </p> + <p> + If <seealso marker="erts:epmd"><c>epmd</c></seealso> is to be used + for node discovery, you typically want to use the (unfortunately + undocumented) <c>erl_epmd</c> module (part of the <c>kernel</c> + application) in order to register the listen port with <c>epmd</c> + and retrieve <c>Creation</c> to use. + </p> + </item> + + <tag><marker id="accept"/><c>accept(Listen) -></c><br/> <c>AcceptorPid</c></tag> + <item> + <p> + <c>accept/1</c> should spawn a process that accepts connections. This + process should preferably execute on <c>max</c> priority. The process + identifier of this process should be returned. + </p> + <p> + The <c>Listen</c> argument will be the same as the <c>Listen</c> handle + part of the return value of the + <seealso marker="#listen"><c>listen/1</c></seealso> callback above. + <c>accept/1</c> is called only once when the distribution protocol is + started. + </p> + <p> + The caller of this function is a representative for <c>net_kernel</c> + (this may or may not be the process registered as <c>net_kernel</c>) + and is in this document identified as <c>Kernel</c>. + When a connection has been accepted by the acceptor process, it needs + to inform <c>Kernel</c> about the accepted connection. This is done by + passing a message on the form: + </p> + <code type="none"><![CDATA[Kernel ! {accept, AcceptorPid, DistController, Family, Proto}]]></code> + <p> + <c>DistController</c> is either the process or port identifier + of the distribution controller for the connection. The + distribution controller should be created by the acceptor + processes when a new connection is accepted. Its job is to + dispatch traffic on the connection. + </p> + <c>Kernel</c> responds with one of the following messages: + <taglist> + <tag><c>{Kernel, controller, SupervisorPid}</c></tag> + <item> + <p> + The request was accepted and <c>SupervisorPid</c> is the + process identifier of the connection supervisor process + (which is created in the + <seealso marker="#accept_connection"><c>accept_connection/5</c></seealso> + callback). + </p> + </item> + <tag><c>{Kernel, unsupported_protocol}</c></tag> + <item> + <p> + The request was rejected. This is a fatal error. The acceptor + process should terminate. + </p> + </item> + </taglist> + <p> + When an accept sequence has been completed the acceptor process + is expected to continue accepting further requests. + </p> + </item> + + <tag><marker id="accept_connection"/><c>accept_connection(AcceptorPid, DistCtrl, MyNode, Allowed, SetupTime) -></c><br/> <c>ConnectionSupervisorPid</c></tag> + <item> + <p> + <c>accept_connection/5</c> should spawn a process that will + perform the Erlang distribution handshake for the connection. + If the handshake successfully completes it should continue to + function as a connection supervisor. This process + should preferably execute on <c>max</c> priority. + </p> + <p>The arguments:</p> + <taglist> + <tag><c>AcceptorPid</c></tag> + <item> + <p> + Process identifier of the process created by the + <seealso marker="#accept"><c>accept/1</c></seealso> + callback. + </p> + </item> + <tag><c>DistCtrl</c></tag> + <item> + <p>The identifier of the distribution controller identifier + created by the acceptor process. To be passed along to + <c>dist_util:handshake_other_started(HsData)</c>. + </p> + </item> + <tag><c>MyNode</c></tag> + <item> + <p> + Node name of this node. To be passed along to + <c>dist_util:handshake_other_started(HsData)</c>. + </p> + </item> + <tag><c>Allowed</c></tag> + <item> + <p> + To be passed along to + <c>dist_util:handshake_other_started(HsData)</c>. + </p> + </item> + <tag><c>SetupTime</c></tag> + <item> + <p> + Time used for creating a setup timer by a + call to <c>dist_util:start_timer(SetupTime)</c>. + The timer should be passed along to + <c>dist_util:handshake_other_started(HsData)</c>. + </p> + </item> + </taglist> + <p> + The created process should provide callbacks and other + information needed for the handshake in a + <seealso marker="#hs_data_record"><c>#hs_data{}</c></seealso> + record and call <c>dist_util:handshake_other_started(HsData)</c> + with this record. + </p> + <p> + <c>dist_util:handshake_other_started(HsData)</c> will perform + the handshake and if the handshake successfully completes this + process will then continue in a connection supervisor loop + as long as the connection is up. + </p> + </item> + + <tag><marker id="setup"/><c>setup(Node, Type, MyNode, LongOrShortNames, SetupTime) -></c><br/> <c>ConnectionSupervisorPid</c></tag> + <item> + <p> + <c>setup/5</c> should spawn a process that connects to + <c>Node</c>. When connection has been established it should + perform the Erlang distribution handshake for the connection. + If the handshake successfully completes it should continue to + function as a connection supervisor. This process + should preferably execute on <c>max</c> priority. + </p> + <p>The arguments:</p> + <taglist> + <tag><c>Node</c></tag> + <item> + <p> + Node name of remote node. To be passed along to + <c>dist_util:handshake_we_started(HsData)</c>. + </p> + </item> + <tag><c>Type</c></tag> + <item> + <p> + Connection type. To be passed along to + <c>dist_util:handshake_we_started(HsData)</c>. + </p> + </item> + <tag><c>MyNode</c></tag> + <item> + <p> + Node name of this node. To be passed along to + <c>dist_util:handshake_we_started(HsData)</c>. + </p> + </item> + <tag><c>LongOrShortNames</c></tag> + <item> + <p> + Either the atom <c>longnames</c> or + the atom <c>shortnames</c> indicating + whether long or short names is used. + </p> + </item> + <tag><c>SetupTime</c></tag> + <item> + <p> + Time used for creating a setup timer by a + call to <c>dist_util:start_timer(SetupTime)</c>. + The timer should be passed along to + <c>dist_util:handshake_we_started(HsData)</c>. + </p> + </item> + </taglist> + <p> + The caller of this function is a representative for <c>net_kernel</c> + (this may or may not be the process registered as <c>net_kernel</c>) + and is in this document identified as <c>Kernel</c>. + </p> + <p> + This function should, besides spawning the connection supervisor, + also create a distribution controller. The distribution + controller is either a process or a port which is responsible + for dispatching traffic. + </p> + <p> + The created process should provide callbacks and other + information needed for the handshake in a + <seealso marker="#hs_data_record"><c>#hs_data{}</c></seealso> + record and call <c>dist_util:handshake_we_started(HsData)</c> + with this record. + </p> + <p> + <c>dist_util:handshake_we_started(HsData)</c> will perform + the handshake and the handshake successfully completes this + process will then continue in a connection supervisor loop + as long as the connection is up. + </p> + </item> + + <tag><marker id="close"/><c>close(Listen) -></c><br/> <c>void()</c></tag> + + <item><p> + Called in order to close the <c>Listen</c> handle + that originally was passed from the + <seealso marker="#listen"><c>listen/1</c></seealso> callback. + </p></item> + + <tag><marker id="select"/><c>select(NodeName) -></c><br/> <c>boolean()</c></tag> + <item> + <p>Return <c>true</c> if the host name part + of the <c>NodeName</c> is valid for use + with this protocol; otherwise, <c>false</c>. + </p> + </item> + + </taglist> + + <p> + There are also two optional functions that may be + exported: + </p> + <taglist> + <tag><marker id="select"/><c>setopts(Listen, Opts) -></c><br/> <c>ok | {error, Error}</c></tag> + <item> + <p> + The argument <c>Listen</c> is the handle originally passed + from the + <seealso marker="#listen"><c>listen/1</c></seealso> callback. + The argument <c>Opts</c> is a list of options to set on future + connections. + </p> + </item> + + <tag><marker id="select"/><c>getopts(Listen, Opts) -></c><br/> <c>{ok, OptionValues} | {error, Error}</c></tag> + <item> + <p> + The argument <c>Listen</c> is the handle originally passed + from the + <seealso marker="#listen"><c>listen/1</c></seealso> callback. + The argument <c>Opts</c> is a list of options to read for future + connections. + </p> + </item> + </taglist> + + </section> + <section> + <marker id="hs_data_record"/> + <title>The #hs_data{} Record</title> + <p> + The <c>dist_util:handshake_we_started/1</c> and + <c>dist_util:handshake_other_started/1</c> functions + takes a <c>#hs_data{}</c> record as argument. There + are quite a lot of fields in this record that you + need to set. The record is defined in + <c>kernel/include/dist_util.hrl</c>. Not documented + fields should not be set, i.e., should be left as + <c>undefined</c>. + </p> + <p> + The following <c>#hs_data{}</c> record fields need + to be set unless otherwise stated:</p> + <taglist> + <tag><marker id="hs_data_kernel_pid"/><c>kernel_pid</c></tag> + <item> + <p> + Process identifier of the <c>Kernel</c> process. That is, + the process that called either + <seealso marker="#setup"><c>setup/5</c></seealso> or + <seealso marker="#accept_connection"><c>accept_connection/5</c></seealso>. + </p> + </item> + + <tag><marker id="hs_data_other_node"/><c>other_node</c></tag> + <item> + <p>Name of the other node. This field is only + mandatory when this node initiates the connection. + That is, when connection is set up via + <seealso marker="#setup"><c>setup/5</c></seealso>. + </p> + </item> + + <tag><marker id="hs_data_this_node"/><c>this_node</c></tag> + <item> + <p> + The node name of this node. + </p> + </item> + + <tag><marker id="hs_data_socket"/><c>socket</c></tag> + <item> + <p> + The identifier of the distribution controller. + </p> + </item> + + <tag><marker id="hs_data_timer"/><c>timer</c></tag> + <item> + <p> + The timer created using <c>dist_util:start_timer/1</c>. + </p> + </item> + + <tag><marker id="hs_data_allowed"/><c>allowed</c></tag> + <item> + <p>Information passed as <c>Allowed</c> to + <c>accept_connection/5</c>. This field is only + mandatory when the remote node initiated the + connection. That is, when the connection is set + up via + <seealso marker="#accept_connection"><c>accept_connection/5</c></seealso>. + </p> + </item> + + <tag><marker id="hs_data_f_send"/><c>f_send</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrlr, Data) -> ok | {error, Error}]]></code> + <p> + where <c>DistCtrlr</c> is the identifier of + the distribution controller and <c>Data</c> + is io data to pass to the other side. + </p> + <p>Only used during handshake phase.</p> + </item> + + <tag><marker id="hs_data_f_recv"/><c>f_recv</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrlr, Length) -> {ok, Packet} | {error, Reason}]]></code> + <p> + where <c>DistCtrlr</c> is the identifier of the distribution + controller. + If <c>Length</c> is <c>0</c>, all available bytes should be + returned. If <c>Length > 0</c>, exactly <c>Length</c> bytes + should be returned, or an error; possibly discarding less + than <c>Length</c> bytes of data when the connection is + closed from the other side. + It is used for passive receive of data from the + other end. + </p> + <p>Only used during handshake phase.</p> + </item> + + <tag><marker id="hs_data_f_setopts_pre_nodeup"/><c>f_setopts_pre_nodeup</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrlr) -> ok | {error, Error}]]></code> + <p> + where <c>DistCtrlr</c> is the identifier of + the distribution controller. Called just + before the distribution channel is taken up + for normal traffic. + </p> + <p>Only used during handshake phase.</p> + </item> + + <tag><marker id="hs_data_f_setopts_post_nodeup"/><c>f_setopts_post_nodeup</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrlr) -> ok | {error, Error}]]></code> + <p> + where <c>DistCtrlr</c> is the identifier of + the distribution controller. Called just + after distribution channel has been taken + up for normal traffic. + </p> + <p>Only used during handshake phase.</p> + </item> + + <tag><marker id="hs_data_f_getll"/><c>f_getll</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrlr) -> ID]]></code> + <p> + where <c>DistCtrlr</c> is the identifier of + the distribution controller and <c>ID</c> is + the identifier of the low level entity that + handles the connection (often <c>DistCtrlr</c> + itself). + </p> + <p>Only used during handshake phase.</p> + </item> + + <tag><marker id="hs_data_f_address"/><c>f_address</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrlr, Node) -> NetAddress]]></code> + <p> + where <c>DistCtrlr</c> is the identifier of + the distribution controller, <c>Node</c> + is the node name of the node on the other end, + and <c>NetAddress</c> is a <c>#net_address{}</c> + record with information about the address + for the <c>Node</c> on the other end of the + connection. The <c>#net_address{}</c> record + is defined in + <c>kernel/include/net_address.hrl</c>. + </p> + <p>Only used during handshake phase.</p> + </item> + + <tag><marker id="hs_data_mf_tick"/><c>mf_tick</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrlr) -> void()]]></code> + <p> + where <c>DistCtrlr</c> is the identifier + of the distribution controller. This + function should send information over + the connection that is not interpreted + by the other end while increasing the + statistics of received packets on the + other end. This is usually implemented by + sending an empty packet. + </p> + <note><p> + It is of vital importance that this operation + does not block the caller for a long time. + This since it is called from the connection + supervisor. + </p></note> + <p>Used when connection is up.</p> + </item> + + <tag><marker id="hs_data_mf_getstat"/><c>mf_getstat</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrlr) -> {ok, Received, Sent, PendSend}]]></code> + <p> + where <c>DistCtrlr</c> is the identifier + of the distribution controller, <c>Received</c> + is received packets, <c>Sent</c> is + sent packets, and <c>PendSend</c> is + amount of packets in queue to be sent + or a <c>boolean()</c> indicating whether + there are packets in queue to be sent. + </p> + <note><p> + It is of vital importance that this operation + does not block the caller for a long time. + This since it is called from the connection + supervisor. + </p></note> + <p>Used when connection is up.</p> + </item> + + <tag><marker id="hs_data_request_type"/><c>request_type</c></tag> + <item> + <p> + The request <c>Type</c> as passed to + <seealso marker="#setup"><c>setup/5</c></seealso>. + This is only mandatory when the connection has + been initiated by this node. That is, the connection + is set up via <c>setup/5</c>. + </p> + </item> + + <tag><marker id="hs_data_mf_setopts"/><c>mf_setopts</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrl, Opts) -> ok | {error, Error}]]></code> + <p> + where <c>DistCtrlr</c> is the identifier + of the distribution controller and <c>Opts</c> + is a list of options to set on the connection. + </p> + <p>This function is optional. Used when connection is up.</p> + </item> + + <tag><marker id="hs_data_mf_getopts"/><c>mf_getopts</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrl, Opts) -> {ok, OptionValues} | {error, Error}]]></code> + <p> + where <c>DistCtrlr</c> is the identifier + of the distribution controller and <c>Opts</c> + is a list of options to read for the connection. + </p> + <p>This function is optional. Used when connection is up.</p> + </item> + + <tag><marker id="hs_data_f_handshake_complete"/><c>f_handshake_complete</c></tag> + <item> + <p> + A fun with the following signature: + </p> + <code type="none"><![CDATA[fun (DistCtrlr, Node, DHandle) -> void()]]></code> + <p> + where <c>DistCtrlr</c> is the identifier + of the distribution controller, <c>Node</c> is + the node name of the node connected at the other + end, and <c>DHandle</c> is a distribution handle + needed by a distribution controller process when + calling the following BIFs: + </p> + <list> + <item><p><seealso marker="erts:erlang#dist_ctrl_get_data/1"><c>erlang:dist_ctrl_get_data/1</c></seealso></p></item> + <item><p><seealso marker="erts:erlang#dist_ctrl_get_data_notification/1"><c>erlang:dist_ctrl_get_data_notification/1</c></seealso></p></item> + <item><p><seealso marker="erts:erlang#dist_ctrl_input_handler/2"><c>erlang:dist_ctrl_input_handler/2</c></seealso></p></item> + <item><p><seealso marker="erts:erlang#dist_ctrl_put_data/2"><c>erlang:dist_ctrl_put_data/2</c></seealso></p></item> + </list> + <p> + This function is called when the handshake has + completed and the distribution channel is up. + The distribution controller can begin dispatching + traffic over the channel. This function is optional. + </p> + <p>Only used during handshake phase.</p> + </item> + + <tag><marker id="hs_data_add_flags"/><c>add_flags</c></tag> + <item> + <p> + <seealso marker="erl_dist_protocol#dflags">Distribution flags</seealso> + to add to the connection. Currently all (non obsolete) flags will + automatically be enabled. + </p> + <p> + This flag field is optional. + </p> + </item> + + <tag><marker id="hs_data_reject_flags"/><c>reject_flags</c></tag> + <item> + <p> + <seealso marker="erl_dist_protocol#dflags">Distribution flags</seealso> + to reject. Currently the following distribution flags can be rejected: + </p> + <taglist> + <tag><c>DFLAG_DIST_HDR_ATOM_CACHE</c></tag> + <item>Do not use atom cache over this connection.</item> + </taglist> + <p>Use function <c>dist_util:strict_order_flags/0</c> to get all flags + for features that require strict order delivery.</p> + <p> + This flag field is optional. + </p> + </item> + + <tag><marker id="hs_data_require_flags"/><c>require_flags</c></tag> + <item> + <p> + Require these <seealso marker="erl_dist_protocol#dflags">distribution + flags</seealso> to be used. The connection will be aborted during the + handshake if the other end does not use them. + </p> + <p> + This flag field is optional. + </p> + </item> + + </taglist> + </section> + + <section> + <marker id="distribution_data_delivery"/> + <title>Distribution Data Delivery</title> + <p> + When using the default configuration, the data to pass + over a connection needs to be delivered as is + to the node on the receiving end in the <em>exact same + order</em>, with no loss of data what so ever, as sent + from the sending node. + </p> + <p> + The data delivery order can be relaxed by disabling + features that require strict ordering. This is done by + passing the + <seealso marker="erl_dist_protocol#dflags">distribution flags</seealso> + returned by <c>dist_util:strict_order_flags/0</c> in the + <seealso marker="alt_dist#hs_data_reject_flags"><c>reject_flags</c></seealso> + field of the <seealso marker="#hs_data_record"><c>#hs_data{}</c></seealso> + record used when setting up the connection. When relaxed + ordering is used, only the order of signals with the same + sender/receiver pair has to be preserved. + However, note that disabling the features that require + strict ordering may have a negative impact on performance, + throughput, and/or latency. + </p> + </section> + + <section> + <marker id="enable_your_distribution_module"/> + <title>Enable Your Distribution Module</title> + + <p>For <c>net_kernel</c> to find out which distribution module to use, + the <c>erl</c> command-line argument <c>-proto_dist</c> is used. It + is followed by one or more distribution module names, with suffix + "_dist" removed. That is, <c>gen_tcp_dist</c> as a distribution module + is specified as <c>-proto_dist gen_tcp</c>.</p> + + <p>If no <c>epmd</c> (TCP port mapper daemon) is used, also command-line + option <c>-no_epmd</c> is to be specified, which makes + Erlang skip the <c>epmd</c> startup, both as an OS process and as an + Erlang ditto.</p> + </section> + </section> <section> - <title>The driver</title> - <p>Although Erlang drivers in general may be beyond the scope of this - document, a brief introduction seems to be in place.</p> + <title>The Driver</title> + + <note> + <p>This section was written a long time ago. Most of it is still + valid, but some things have changed since then. Some updates have + been made to the documentation of the driver presented here, + but more can be done and is planned for the future. + The reader is encouraged to read the + <seealso marker="erl_driver"><c>erl_driver</c></seealso> and + <seealso marker="driver_entry"><c>driver_entry</c></seealso> + documentation also.</p> + </note> + + <p>Although Erlang drivers in general can be beyond the scope of this + section, a brief introduction seems to be in place.</p> <section> - <title>Drivers in general</title> + <title>Drivers in General</title> <p>An Erlang driver is a native code module written in C (or - assembler) which serves as an interface for some special operating + assembler), which serves as an interface for some special operating system service. This is a general mechanism that is used throughout the Erlang emulator for all kinds of I/O. An Erlang driver can be dynamically linked (or loaded) to the Erlang emulator at runtime by using the <c><![CDATA[erl_ddll]]></c> Erlang module. Some of the drivers in OTP are however statically linked - to the runtime system, but that's more an optimization than a + to the runtime system, but that is more an optimization than a necessity.</p> - <p>The driver data-types and the functions available to the driver - writer are defined in the header file <c><![CDATA[erl_driver.h]]></c> (there - is also an deprecated version called <c><![CDATA[driver.h]]></c>, don't use - that one.) seated in Erlang's include directory (and in - $ERL_TOP/erts/emulator/beam in the source code - distribution). Refer to that file for function prototypes etc.</p> + + <p>The driver data types and the functions available to the driver + writer are defined in header file <c><![CDATA[erl_driver.h]]></c> + seated in Erlang's include directory. See the + <seealso marker="erts:erl_driver">erl_driver</seealso> documentation + for details of which functions are available.</p> + <p>When writing a driver to make a communications protocol available to Erlang, one should know just about everything worth knowing - about that particular protocol. All operation has to be non - blocking and all possible situations should be accounted for in - the driver. A non stable driver will affect and/or crash the - whole Erlang runtime system, which is seldom what's wanted. </p> + about that particular protocol. All operation must be + non-blocking and all possible situations are to be accounted for in + the driver. A non-stable driver will affect and/or crash the + whole Erlang runtime system.</p> + <p>The emulator calls the driver in the following situations:</p> + <list type="bulleted"> - <item>When the driver is loaded. This call-back has to have a - special name and will inform the emulator of what call-backs should - be used by returning a pointer to a <c><![CDATA[ErlDrvEntry]]></c> struct, - which should be properly filled in (see below).</item> - <item>When a port to the driver is opened (by a <c><![CDATA[open_port]]></c> - call from Erlang). This routine should set up internal data - structures and return an opaque data entity of the type - <c><![CDATA[ErlDrvData]]></c>, which is a data-type large enough to hold a - pointer. The pointer returned by this function will be the first - argument to all other call-backs concerning this particular - port. It is usually called the port handle. The emulator only - stores the handle and does never try to interpret it, why it can - be virtually anything (well anything not larger than a pointer - that is) and can point to anything if it is a pointer. Usually - this pointer will refer to a structure holding information about - the particular port, as i t does in our example.</item> - <item>When an Erlang process sends data to the port. The data will - arrive as a buffer of bytes, the interpretation is not defined, - but is up to the implementor. This call-back returns nothing to the - caller, answers are sent to the caller as messages (using a - routine called <c><![CDATA[driver_output]]></c> available to all - drivers). There is also a way to talk in a synchronous way to - drivers, described below. There can be an additional call-back - function for handling data that is fragmented (sent in a deep - io-list). That interface will get the data in a form suitable for - Unix <c><![CDATA[writev]]></c> rather than in a single buffer. There is no - need for a distribution driver to implement such a call-back, so - we wont.</item> - <item>When a file descriptor is signaled for input. This call-back - is called when the emulator detects input on a file descriptor - which the driver has marked for monitoring by using the interface - <c><![CDATA[driver_select]]></c>. The mechanism of driver select makes it - possible to read non blocking from file descriptors by calling - <c><![CDATA[driver_select]]></c> when reading is needed and then do the actual - reading in this call-back (when reading is actually possible). The - typical scenario is that <c><![CDATA[driver_select]]></c> is called when an - Erlang process orders a read operation, and that this routine - sends the answer when data is available on the file descriptor.</item> - <item>When a file descriptor is signaled for output. This call-back - is called in a similar way as the previous, but when writing to a - file descriptor is possible. The usual scenario is that Erlang - orders writing on a file descriptor and that the driver calls - <c><![CDATA[driver_select]]></c>. When the descriptor is ready for output, - this call-back is called an the driver can try to send the - output. There may of course be queuing involved in such - operations, and there are some convenient queue routines available - to the driver writer to use in such situations.</item> - <item>When a port is closed, either by an Erlang process or by the - driver calling one of the <c><![CDATA[driver_failure_XXX]]></c> routines. This - routine should clean up everything connected to one particular - port. Note that when other call-backs call a - <c><![CDATA[driver_failure_XXX]]></c> routine, this routine will be - immediately called and the call-back routine issuing the error can - make no more use of the data structures for the port, as this - routine surely has freed all associated data and closed all file - descriptors. If the queue utility available to driver writes is - used, this routine will however <em>not</em> be called until the - queue is empty.</item> - <item>When an Erlang process calls <c>erlang:port_control/3</c>, - which is a synchronous interface to drivers. The control interface - is used to set driver options, change states of ports etc. We'll - use this interface quite a lot in our example.</item> - <item>When a timer expires. The driver can set timers with the - function <c><![CDATA[driver_set_timer]]></c>. When such timers expire, a - specific call-back function is called. We will not use timers in - our example.</item> - <item>When the whole driver is unloaded. Every resource allocated - by the driver should be freed.</item> + <item> + <p>When the driver is loaded. This callback must have a special + name and inform the emulator of what callbacks are to be used + by returning a pointer to a <c><![CDATA[ErlDrvEntry]]></c> struct, + which is to be properly filled in (see below).</p> + </item> + <item> + <p>When a port to the driver is opened (by a + <c><![CDATA[open_port]]></c> call from Erlang). This routine is to + set up internal data structures and return an opaque data entity of + the type <c><![CDATA[ErlDrvData]]></c>, which is a data type large + enough to hold a pointer. + The pointer returned by this function is the first + argument to all other callbacks concerning this particular + port. It is usually called the port handle. The emulator only + stores the handle and does never try to interpret it, why it can + be virtually anything (anything not larger than a pointer + that is) and can point to anything if it is a pointer. Usually + this pointer refers to a structure holding information about + the particular port, as it does in the example.</p> + </item> + <item> + <p>When an Erlang process sends data to the port. The data + arrives as a buffer of bytes, the interpretation is not defined, + but is up to the implementor. This callback returns nothing to the + caller, answers are sent to the caller as messages (using a + routine called <c><![CDATA[driver_output]]></c> available to all + drivers). There is also a way to talk in a synchronous way to + drivers, described below. There can be an additional callback + function for handling data that is fragmented (sent in a deep + io-list). That interface gets the data in a form suitable for + Unix <c><![CDATA[writev]]></c> rather than in a single buffer. + There is no need for a distribution driver to implement such a + callback, so we will not.</p> + </item> + <item> + <p>When a file descriptor is signaled for input. This callback + is called when the emulator detects input on a file descriptor + that the driver has marked for monitoring by using the interface + <c><![CDATA[driver_select]]></c>. The mechanism of driver select + makes it possible to read non-blocking from file descriptors by + calling <c><![CDATA[driver_select]]></c> when reading is needed, and + then do the reading in this callback (when reading is possible). + The typical scenario is that <c><![CDATA[driver_select]]></c> is + called when an Erlang process orders a read operation, and that + this routine sends the answer when data is available on the file + descriptor.</p> + </item> + <item> + <p>When a file descriptor is signaled for output. This callback + is called in a similar way as the previous, but when writing to a + file descriptor is possible. The usual scenario is that Erlang + orders writing on a file descriptor and that the driver calls + <c><![CDATA[driver_select]]></c>. When the descriptor is ready for + output, this callback is called and the driver can try to send the + output. Queuing can be involved in such operations, and there are + convenient queue routines available to the driver writer to use.</p> + </item> + <item> + <p>When a port is closed, either by an Erlang process or by the + driver calling one of the <c><![CDATA[driver_failure_XXX]]></c> + routines. This routine is to clean up everything connected to one + particular port. When other callbacks call a + <c><![CDATA[driver_failure_XXX]]></c> routine, this routine is + immediately called. The callback routine issuing the error can + make no more use of the data structures for the port, as this + routine surely has freed all associated data and closed all file + descriptors. If the queue utility available to driver writer is + used, this routine is however <em>not</em> called until the + queue is empty.</p> + </item> + <item> + <p>When an Erlang process calls + <seealso marker="erlang#port_control/3"> + <c>erlang:port_control/3</c></seealso>, + which is a synchronous interface to drivers. The control interface + is used to set driver options, change states of ports, and so on. + This interface is used a lot in the example.</p> + </item> + <item> + <p>When a timer expires. The driver can set timers with the function + <c><![CDATA[driver_set_timer]]></c>. When such timers expire, a + specific callback function is called. No timers are used in + the example.</p> + </item> + <item> + <p>When the whole driver is unloaded. Every resource allocated + by the driver is to be freed.</p> + </item> </list> </section> <section> - <title>The distribution driver's data structures</title> - <p>The driver used for Erlang distribution should implement a - reliable, order maintaining, variable length packet oriented - protocol. All error correction, re-sending and such need to be + <title>The Data Structures of the Distribution Driver</title> + <p>The driver used for Erlang distribution is to implement a + reliable, order maintaining, variable length packet-oriented + protocol. All error correction, resending and such need to be implemented in the driver or by the underlying communications - protocol. If the protocol is stream oriented (as is the case with + protocol. If the protocol is stream-oriented (as is the case with both TCP/IP and our streamed Unix domain sockets), some mechanism for packaging is needed. We will use the simple method of having a - header of four bytes containing the length of the package in a big - endian 32 bit integer (as Unix domain sockets only can be used - between processes on the same machine, we actually don't need to - code the integer in some special endianess, but I'll do it anyway - because in most situation you do need to do it. Unix domain - sockets are reliable and order maintaining, so we don't need to - implement resends and such in our driver.</p> - <p>Lets start writing our example Unix domain sockets driver by - declaring prototypes and filling in a static ErlDrvEntry - structure.</p> + header of four bytes containing the length of the package in a + big-endian 32-bit integer. As Unix domain sockets only can be used + between processes on the same machine, we do not need to + code the integer in some special endianess, but we will do it anyway + because in most situation you need to do it. Unix domain + sockets are reliable and order maintaining, so we do not need to + implement resends and such in the driver.</p> + + <p>We start writing the example Unix domain sockets driver by + declaring prototypes and filling in a static <c>ErlDrvEntry</c> + structure:</p> + <code type="none"><![CDATA[ ( 1) #include <stdio.h> ( 2) #include <stdlib.h> @@ -285,94 +1065,122 @@ (51) NULL, /* process_exit callback */ (52) NULL /* stop_select callback */ (53) };]]></code> - <p>On line 1 to 10 we have included the OS headers needed for our - driver. As this driver is written for Solaris, we know that the - header <c><![CDATA[uio.h]]></c> exists, why we can define the preprocessor - variable <c><![CDATA[HAVE_UIO_H]]></c> before we include <c><![CDATA[erl_driver.h]]></c> - at line 12. The definition of <c><![CDATA[HAVE_UIO_H]]></c> will make the + + <p>On line 1-10 the OS headers needed for the driver are included. + As this driver is written for Solaris, we know that the + header <c><![CDATA[uio.h]]></c> exists. So the preprocessor variable + <c><![CDATA[HAVE_UIO_H]]></c> can be defined before + <c><![CDATA[erl_driver.h]]></c> is included on line 12. + The definition of <c><![CDATA[HAVE_UIO_H]]></c> will make the I/O vectors used in Erlang's driver queues to correspond to the operating systems ditto, which is very convenient.</p> - <p>The different call-back functions are declared ("forward - declarations") on line 16 to 23.</p> - <p>The driver structure is similar for statically linked in - drivers and dynamically loaded. However some of the fields - should be left empty (i.e. initialized to NULL) in the + + <p>On line 16-23 the different callback functions are declared ("forward + declarations").</p> + + <p>The driver structure is similar for statically linked-in + drivers and dynamically loaded. However, some of the fields + are to be left empty (that is, initialized to NULL) in the different types of drivers. The first field (the <c><![CDATA[init]]></c> function pointer) is always left blank in a dynamically loaded - driver, which can be seen on line 26. The NULL on line 37 - should always be there, the field is no longer used and is - retained for backward compatibility. We use no timers in this - driver, why no call-back for timers is needed. The <c>outputv</c> field + driver, see line 26. <c>NULL</c> on line 37 + is always to be there, the field is no longer used and is + retained for backward compatibility. No timers are used in this + driver, why no callback for timers is needed. The <c>outputv</c> field (line 40) can be used to implement an interface similar to Unix <c><![CDATA[writev]]></c> for output. The Erlang runtime - system could previously not use <c>outputv</c> for the - distribution, but since erts version 5.7.2 it can. - Since this driver was written before erts version 5.7.2 it does - not use the <c>outputv</c> callback. Using the <c>outputv</c> - callback is preferred since it reduces copying of data. (We - will however use scatter/gather I/O internally in the driver).</p> - <p>As of erts version 5.5.3 the driver interface was extended with - version control and the possibility to pass capability information. - Capability flags are present at line 48. As of erts version 5.7.4 - the - <seealso marker="driver_entry#driver_flags">ERL_DRV_FLAG_SOFT_BUSY</seealso> - flag is required for drivers that are to be used by the distribution. - The soft busy flag implies that the driver is capable of handling - calls to the <c>output</c> and <c>outputv</c> callbacks even though - it has marked itself as busy. This has always been a requirement - on drivers used by the distribution, but there have previously not - been any capability information available about this. For more - information see - <seealso marker="erl_driver#set_busy_port">set_busy_port()</seealso>). -</p> + system could previously not use <c>outputv</c> for the + distribution, but it can as from ERTS 5.7.2. + As this driver was written before ERTS 5.7.2 it does + not use the <c>outputv</c> callback. Using the <c>outputv</c> + callback is preferred, as it reduces copying of data. (We + will however use scatter/gather I/O internally in the driver.)</p> + + <p>As from ERTS 5.5.3 the driver interface was extended with + version control and the possibility to pass capability information. + Capability flags are present on line 48. As from ERTS 5.7.4 flag + <seealso marker="driver_entry#driver_flags"> + <c>ERL_DRV_FLAG_SOFT_BUSY</c></seealso> is required for drivers that + are to be used by the distribution. The soft busy flag implies that the + driver can handle calls to the <c>output</c> and <c>outputv</c> + callbacks although it has marked itself as busy. This has always been a + requirement on drivers used by the distribution, but no capability + information has been available about this previously. For more + information. see <seealso marker="erl_driver#set_busy_port"> + <c>erl_driver:set_busy_port()</c></seealso>).</p> + <p>This driver was written before the runtime system had SMP support. - The driver will still function in the runtime system with SMP support, - but performance will suffer from lock contention on the driver lock - used for the driver. This can be alleviated by reviewing and perhaps - rewriting the code so that each instance of the driver safely can - execute in parallel. When instances safely can execute in parallel it - is safe to enable instance specific locking on the driver. This is done - by passing - <seealso marker="driver_entry#driver_flags">ERL_DRV_FLAG_USE_PORT_LOCKING</seealso> - as a driver flag. This is left as an exercise for the reader.</p> - <p>Our defined call-backs thus are:</p> - <list type="bulleted"> - <item>uds_start, which shall initiate data for a port. We wont - create any actual sockets here, just initialize data structures.</item> - <item>uds_stop, the function called when a port is closed.</item> - <item>uds_command, which will handle messages from Erlang. The - messages can either be plain data to be sent or more subtle - instructions to the driver. We will use this function mostly for - data pumping.</item> - <item>uds_input, this is the call-back which is called when we have - something to read from a socket.</item> - <item>uds_output, this is the function called when we can write to a - socket.</item> - <item>uds_finish, which is called when the driver is unloaded. A - distribution driver will actually (or hopefully) never be unloaded, - but we include this for completeness. Being able to clean up after - oneself is always a good thing.</item> - <item>uds_control, the <c>erlang:port_control/2</c> call-back, which - will be used a lot in this implementation.</item> - </list> - <p>The ports implemented by this driver will operate in two major - modes, which i will call the <em>command</em> and <em>data</em> - modes. In command mode, only passive reading and writing (like - gen_tcp:recv/gen_tcp:send) can be - done, and this is the mode the port will be in during the - distribution handshake. When the connection is up, the port will - be switched to data mode and all data will be immediately read and - passed further to the Erlang emulator. In data mode, no data - arriving to the uds_command will be interpreted, but just packaged - and sent out on the socket. The uds_control call-back will do the - switching between those two modes.</p> - <p>While the <c><![CDATA[net_kernel]]></c> informs different subsystems that the - connection is coming up, the port should accept data to send, but - not receive any data, to avoid that data arrives from another node - before every kernel subsystem is prepared to handle it. We have a - third mode for this intermediate stage, lets call it the - <em>intermediate</em> mode.</p> - <p>Lets define an enum for the different types of ports we have:</p> + The driver will still function in the runtime system with SMP support, + but performance will suffer from lock contention on the driver lock + used for the driver. This can be alleviated by reviewing and perhaps + rewriting the code so that each instance of the driver safely can + execute in parallel. When instances safely can execute in parallel, it + is safe to enable instance-specific locking on the driver. This is done + by passing <seealso marker="driver_entry#driver_flags"> + <c>ERL_DRV_FLAG_USE_PORT_LOCKING</c></seealso> as a driver flag. This + is left as an exercise for the reader.</p> + + <p>Thus, the defined callbacks are as follows:</p> + + <taglist> + <tag><c>uds_start</c></tag> + <item> + <p>Must initiate data for a port. We do not create any sockets + here, only initialize data structures.</p> + </item> + <tag><c>uds_stop</c></tag> + <item> + <p>Called when a port is closed.</p> + </item> + <tag><c>uds_command</c></tag> + <item> + <p>Handles messages from Erlang. The + messages can either be plain data to be sent or more subtle + instructions to the driver. This function is here mostly for + data pumping.</p> + </item> + <tag><c>uds_input</c></tag> + <item> + <p>Called when there is something to read from a socket.</p> + </item> + <tag><c>uds_output</c></tag> + <item> + <p>Called when it is possible to write to a socket.</p> + </item> + <tag><c>uds_finish</c></tag> + <item> + <p>Called when the driver is unloaded. A distribution driver will + never be unloaded, but we include this for completeness. To be + able to clean up after oneself is always a good thing.</p> + </item> + <tag><c>uds_control</c></tag> + <item> + <p>The <seealso marker="erlang#port_control/3"> + <c>erlang:port_control/3</c></seealso> callback, which is + used a lot in this implementation.</p> + </item> + </taglist> + + <p>The ports implemented by this driver operate in two major modes, + named <c>command</c> and <c>data</c>. In <c>command</c> mode, + only passive reading and writing (like + <c>gen_tcp:recv</c>/<c>gen_tcp:send</c>) can be done. The port is in + this mode during the distribution handshake. When the connection is up, + the port is switched to <c>data</c> mode and all data is immediately + read and passed further to the Erlang emulator. In <c>data</c> + mode, no data arriving to <c>uds_command</c> is interpreted, only + packaged and sent out on the socket. The <c>uds_control</c> callback + does the switching between those two modes.</p> + + <p>While <c><![CDATA[net_kernel]]></c> informs different subsystems + that the connection is coming up, the port is to accept data to send. + However, the port should not receive any data, to avoid that data + arrives from another node before every kernel subsystem is prepared + to handle it. A third mode, named <c>intermediate</c>, is used for this + intermediate stage.</p> + + <p>An enum is defined for the different types of ports:</p> + <code type="none"><![CDATA[ ( 1) typedef enum { ( 2) portTypeUnknown, /* An uninitialized port */ @@ -383,40 +1191,63 @@ ( 7) portTypeCommand, /* A connected open port in command mode */ ( 8) portTypeIntermediate, /* A connected open port in special ( 9) half active mode */ -(10) portTypeData /* A connectec open port in data mode */ +(10) portTypeData /* A connected open port in data mode */ (11) } PortType; ]]></code> - <p>Lets look at the different types:</p> - <list type="bulleted"> - <item>portTypeUnknown - The type a port has when it's opened, but - not actually bound to any file descriptor.</item> - <item>portTypeListener - A port that is connected to a listen - socket. This port will not do especially much, there will be no data - pumping done on this socket, but there will be read data available - when one is trying to do an accept on the port.</item> - <item>portTypeAcceptor - This is a port that is to represent the - result of an accept operation. It is created when one wants to - accept from a listen socket, and it will be converted to a - portTypeCommand when the accept succeeds.</item> - <item>portTypeConnector - Very similar to portTypeAcceptor, an - intermediate stage between the request for a connect operation and - that the socket is really connected to an accepting ditto in the - other end. As soon as the sockets are connected, the port will - switch type to portTypeCommand.</item> - <item>portTypeCommand - A connected socket (or accepted socket if - you want) that is in the command mode mentioned earlier.</item> - <item>portTypeIntermediate - The intermediate stage for a connected - socket. There should be no processing of input for this socket.</item> - <item>portTypeData - The mode where data is pumped through the port - and the uds_command routine will regard every call as a call where - sending is wanted. In this mode all input available will be read and - sent to Erlang as soon as it arrives on the socket, much like in the - active mode of a <c><![CDATA[gen_tcp]]></c> socket.</item> - </list> - <p>Now lets look at the state we'll need for our ports. One can note - that not all fields are used for all types of ports and that one - could save some space by using unions, but that would clutter the - code with multiple indirections, so i simply use one struct for - all types of ports, for readability.</p> + + <p>The different types are as follows:</p> + + <taglist> + <tag><c>portTypeUnknown</c></tag> + <item> + <p>The type a port has when it is opened, but + not bound to any file descriptor.</p> + </item> + <tag><c>portTypeListener</c></tag> + <item> + <p>A port that is connected to a listen socket. This port does not + do much, no data pumping is done on this socket, but read data is + available when one is trying to do an accept on the port.</p> + </item> + <tag><c>portTypeAcceptor</c></tag> + <item> + <p>This port is to represent the result of an accept operation. It is + created when one wants to accept from a listen socket, and it is + converted to a <c>portTypeCommand</c> when the accept succeeds.</p> + </item> + <tag><c>portTypeConnector</c></tag> + <item> + <p>Very similar to <c>portTypeAcceptor</c>, an + intermediate stage between the request for a connect operation and + that the socket is connected to an accepting ditto in the + other end. When the sockets are connected, the port + switches type to <c>portTypeCommand</c>.</p> + </item> + <tag><c>portTypeCommand</c></tag> + <item> + <p>A connected socket (or accepted socket) in <c>command</c> mode + mentioned earlier.</p> + </item> + <tag><c>portTypeIntermediate</c></tag> + <item> + <p>The intermediate stage for a connected socket. + There is to be no processing of input for this socket.</p> + </item> + <tag><c>portTypeData</c></tag> + <item> + <p>The mode where data is pumped through the port and the + <c>uds_command</c> routine regards every call as a call where + sending is wanted. In this mode, all input available is read and + sent to Erlang when it arrives on the socket, much like in the + active mode of a <c><![CDATA[gen_tcp]]></c> socket.</p> + </item> + </taglist> + + <p>We study the state that is needed for the ports. Notice + that not all fields are used for all types of ports. Some space + could be saved by using unions, but that would clutter the + code with multiple indirections, so here is used one struct for + all types of ports, for readability:</p> + <code type="none"><![CDATA[ ( 1) typedef unsigned char Byte; ( 2) typedef unsigned int Word; @@ -427,7 +1258,7 @@ ( 6) int lockfd; /* The file descriptor for a lock file in ( 7) case of listen sockets */ ( 8) Byte creation; /* The creation serial derived from the -( 9) lockfile */ +( 9) lock file */ (10) PortType type; /* Type of port */ (11) char *name; /* Short name of socket for unlink */ (12) Word sent; /* Bytes sent */ @@ -441,114 +1272,154 @@ (20) input buffer */ (21) Byte *buffer; /* The actual input buffer */ (22) } UdsData; ]]></code> + <p>This structure is used for all types of ports although some fields are useless for some types. The least memory consuming solution would be to arrange this structure as a union of - structures, but the multiple indirections in the code to - access a field in such a structure will clutter the code to + structures. However, the multiple indirections in the code to + access a field in such a structure would clutter the code too much for an example.</p> - <p>Let's look at the fields in our structure:</p> - <list type="bulleted"> - <item>fd - The file descriptor of the socket associated with the - port.</item> - <item>port - The port identifier for the port which this structure - corresponds to. It is needed for most <c><![CDATA[driver_XXX]]></c> - calls from the driver back to the emulator.</item> + + <p>The fields in the structure are as follows:</p> + + <taglist> + <tag><c>fd</c></tag> + <item> + <p>The file descriptor of the socket associated with the port.</p> + </item> + <tag><c>port</c></tag> <item> - <p>lockfd - If the socket is a listen socket, we use a separate + <p>The port identifier for the port that this structure + corresponds to. It is needed for most <c><![CDATA[driver_XXX]]></c> + calls from the driver back to the emulator.</p> + </item> + <tag><c>lockfd</c></tag> + <item> + <p>If the socket is a listen socket, we use a separate (regular) file for two purposes:</p> <list type="bulleted"> - <item>We want a locking mechanism that gives no race - conditions, so that we can be sure of if another Erlang - node uses the listen socket name we require or if the - file is only left there from a previous (crashed) - session.</item> <item> - <p>We store the <em>creation</em> serial number in the - file. The <em>creation</em> is a number that should + <p>We want a locking mechanism that gives no race + conditions, to be sure if another Erlang + node uses the listen socket name we require or if the + file is only left there from a previous (crashed) session.</p> + </item> + <item> + <p>We store the <c>creation</c> serial number in the + file. The <c>creation</c> is a number that is to change between different instances of different Erlang emulators with the same name, so that process - identifiers from one emulator won't be valid when sent + identifiers from one emulator do not become valid when sent to a new emulator with the same distribution name. The - creation can be between 0 and 3 (two bits) and is stored - in every process identifier sent to another node. </p> - <p>In a system with TCP based distribution, this data is + creation can be from 0 through 3 (two bits) and is stored + in every process identifier sent to another node.</p> + <p>In a system with TCP-based distribution, this data is kept in the <em>Erlang port mapper daemon</em> (<c><![CDATA[epmd]]></c>), which is contacted when a distributed - node starts. The lock-file and a convention for the UDS - listen socket's name will remove the need for + node starts. The lock file and a convention for the UDS + listen socket's name remove the need for <c><![CDATA[epmd]]></c> when using this distribution module. UDS is always restricted to one host, why avoiding a port mapper is easy.</p> </item> </list> </item> - <item>creation - The creation number for a listen socket, which is - calculated as (the value found in the lock-file + 1) rem - 4. This creation value is also written back into the - lock-file, so that the next invocation of the emulator will - found our value in the file.</item> - <item>type - The current type/state of the port, which can be one - of the values declared above.</item> - <item>name - The name of the socket file (the path prefix - removed), which allows for deletion (<c><![CDATA[unlink]]></c>) when the - socket is closed.</item> - <item>sent - How many bytes that have been sent over the - socket. This may wrap, but that's no problem for the - distribution, as the only thing that interests the Erlang - distribution is if this value has changed (the Erlang - net_kernel <em>ticker</em> uses this value by calling the - driver to fetch it, which is done through the - <c>erlang:port_control</c> routine).</item> - <item>received - How many bytes that are read (received) from the - socket, used in similar ways as <c><![CDATA[sent]]></c>.</item> - <item>partner - A pointer to another port structure, which is - either the listen port from which this port is accepting a - connection or the other way around. The "partner relation" - is always bidirectional.</item> - <item>next - Pointer to next structure in a linked list of all - port structures. This list is used when accepting - connections and when the driver is unloaded.</item> - <item>buffer_size, buffer_pos, header_pos, buffer - data for input - buffering. Refer to the source code (in the kernel/examples - directory) for details about the input buffering. That - certainly goes beyond the scope of this document.</item> - </list> + <tag><c>creation</c></tag> + <item> + <p>The creation number for a listen socket, which is + calculated as (the value found in the lock-file + 1) rem 4. + This creation value is also written back into the + lock file, so that the next invocation of the emulator + finds our value in the file.</p> + </item> + <tag><c>type</c></tag> + <item> + <p>The current type/state of the port, which can be one + of the values declared above.</p> + </item> + <tag><c>name</c></tag> + <item> + <p>The name of the socket file (the path prefix removed), + which allows for deletion (<c><![CDATA[unlink]]></c>) when the + socket is closed.</p> + </item> + <tag><c>sent</c></tag> + <item> + <p>How many bytes that have been sent over the + socket. This can wrap, but that is no problem for the + distribution, as the Erlang distribution is only interested in + if this value has changed. (The Erlang + <c>net_kernel</c> <c>ticker</c> uses this value by calling the + driver to fetch it, which is done through the + <seealso marker="erlang#port_control/3"> + <c>erlang:port_control/3</c></seealso> routine.)</p> + </item> + <tag><c>received</c></tag> + <item> + <p>How many bytes that are read (received) from the + socket, used in similar ways as <c><![CDATA[sent]]></c>.</p> + </item> + <tag><c>partner</c></tag> + <item> + <p>A pointer to another port structure, which is + either the listen port from which this port is accepting a + connection or conversely. The "partner relation" + is always bidirectional.</p> + </item> + <tag><c>next</c></tag> + <item> + <p>Pointer to next structure in a linked list of all + port structures. This list is used when accepting + connections and when the driver is unloaded.</p> + </item> + <tag><c>buffer_size</c>, <c>buffer_pos</c>, <c>header_pos</c>, + <c>buffer</c></tag> + <item> + <p>Data for input buffering. For details about the input buffering, + see the source code in directory <c>kernel/examples</c>. That + certainly goes beyond the scope of this section.</p> + </item> + </taglist> </section> <section> - <title>Selected parts of the distribution driver implementation</title> - <p>The distribution drivers implementation is not completely - covered in this text, details about buffering and other things + <title>Selected Parts of the Distribution Driver Implementation</title> + <p>The implemenation of the distribution driver is not completely + covered here, details about buffering and other things unrelated to driver writing are not explained. Likewise are some peculiarities of the UDS protocol not explained in detail. The chosen protocol is not important.</p> - <p>Prototypes for the driver call-back routines can be found in + + <p>Prototypes for the driver callback routines can be found in the <c><![CDATA[erl_driver.h]]></c> header file.</p> + <p>The driver initialization routine is (usually) declared with a macro to make the driver easier to port between different - operating systems (and flavours of systems). This is the only - routine that has to have a well defined name. All other - call-backs are reached through the driver structure. The macro + operating systems (and flavors of systems). This is the only + routine that must have a well-defined name. All other + callbacks are reached through the driver structure. The macro to use is named <c><![CDATA[DRIVER_INIT]]></c> and takes the driver name - as parameter.</p> + as parameter:</p> + <code type="none"><![CDATA[ (1) /* Beginning of linked list of ports */ (2) static UdsData *first_data; - (3) DRIVER_INIT(uds_drv) (4) { (5) first_data = NULL; (6) return &uds_driver_entry; (7) } ]]></code> + <p>The routine initializes the single global data structure and - returns a pointer to the driver entry. The routine will be - called when <c><![CDATA[erl_ddll:load_driver]]></c> is called from Erlang.</p> - <p>The <c><![CDATA[uds_start]]></c> routine is called when a port is opened - from Erlang. In our case, we only allocate a structure and + returns a pointer to the driver entry. The routine is called + when <c><![CDATA[erl_ddll:load_driver]]></c> is called from Erlang.</p> + + <p>The <c><![CDATA[uds_start]]></c> routine is called when a port is + opened from Erlang. In this case, we only allocate a structure and initialize it. Creating the actual socket is left to the <c><![CDATA[uds_command]]></c> routine.</p> + <code type="none"><![CDATA[ ( 1) static ErlDrvData uds_start(ErlDrvPort port, char *buff) ( 2) { @@ -573,15 +1444,18 @@ (21) (22) return((ErlDrvData) ud); (23) } ]]></code> - <p>Every data item is initialized, so that no problems will arise + + <p>Every data item is initialized, so that no problems arise when a newly created port is closed (without there being any corresponding socket). This routine is called when - <c><![CDATA[open_port({spawn, "uds_drv"},[])]]></c> is called from Erlang.</p> - <p>The <c><![CDATA[uds_command]]></c> routine is the routine called when an - Erlang process sends data to the port. All asynchronous - commands when the port is in <em>command mode</em> as well as - the sending of all data when the port is in <em>data mode</em> - is handled in this9s routine. Let's have a look at it:</p> + <c><![CDATA[open_port({spawn, "uds_drv"},[])]]></c> is called from + Erlang.</p> + + <p>The <c><![CDATA[uds_command]]></c> routine is the routine called when + an Erlang process sends data to the port. This routine handles all + asynchronous commands when the port is in <c>command</c> mode and + the sending of all data when the port is in <c>data</c> mode:</p> + <code type="none"><![CDATA[ ( 1) static void uds_command(ErlDrvData handle, char *buff, int bufflen) ( 2) { @@ -635,57 +1509,77 @@ (49) return; (50) } (51) } ]]></code> - <p>The command routine takes three parameters; the handle - returned for the port by <c><![CDATA[uds_start]]></c>, which is a pointer - to the internal port structure, the data buffer and the length + + <p>The command routine takes three parameters; the handle returned for + the port by <c><![CDATA[uds_start]]></c>, which is a pointer + to the internal port structure, the data buffer, and the length of the data buffer. The buffer is the data sent from Erlang - (a list of bytes) converted to an C array (of bytes). </p> - <p>If Erlang sends i.e. the list <c><![CDATA[[$a,$b,$c]]]></c> to the port, - the <c><![CDATA[bufflen]]></c> variable will be <c><![CDATA[3]]></c> ant the - <c><![CDATA[buff]]></c> variable will contain <c><![CDATA[{'a','b','c'}]]></c> (no - null termination). Usually the first byte is used as an - opcode, which is the case in our driver to (at least when the - port is in command mode). The opcodes are defined as:</p> - <list type="bulleted"> - <item>'L'<socketname>: Create and listen on socket with the - given name.</item> - <item>'A'<listennumber as 32 bit bigendian>: Accept from the - listen socket identified by the given identification - number. The identification number is retrieved with the - uds_control routine.</item> - <item>'C'<socketname>: Connect to the socket named - <socketname>.</item> - <item>'S'<data>: Send the data <data> on the - connected/accepted socket (in command mode). The sending is - acked when the data has left this process.</item> - <item>'R': Receive one packet of data.</item> - </list> - <p>One may wonder what is meant by "one packet of data" in the - 'R' command. This driver always sends data packeted with a 4 - byte header containing a big endian 32 bit integer that + (a list of bytes) converted to an C array (of bytes).</p> + + <p>If Erlang sends, for example, the list <c><![CDATA[[$a,$b,$c]]]></c> + to the port, the <c><![CDATA[bufflen]]></c> variable is + <c><![CDATA[3]]></c> and the <c><![CDATA[buff]]></c> variable contains + <c><![CDATA[{'a','b','c'}]]></c> (no + <c>NULL</c> termination). Usually the first byte is used as an + opcode, which is the case in this driver too (at least when the + port is in <c>command</c> mode). The opcodes are defined as follows:</p> + + <taglist> + <tag><c>'L'<socket name></c></tag> + <item> + <p>Creates and listens on socket with the specified name.</p> + </item> + <tag><c>'A'<listen number as 32-bit big-endian></c></tag> + <item> + <p>Accepts from the listen socket identified by the specified + identification number. The identification number is retrieved with + the <c>uds_control</c> routine.</p> + </item> + <tag><c>'C'<socket name></c></tag> + <item> + <p>Connects to the socket named <socket name>.</p> + </item> + <tag><c>'S'<data></c></tag> + <item> + <p>Sends the data <data> on the + connected/accepted socket (in <c>command</c> mode). The sending is + acknowledged when the data has left this process.</p> + </item> + <tag><c>'R'</c></tag> + <item> + <p>Receives one packet of data.</p> + </item> + </taglist> + + <p>"One packet of data" in command <c>'R'</c> can be explained + as follows. This driver always sends data packaged with a 4 + byte header containing a big-endian 32-bit integer that represents the length of the data in the packet. There is no need for different packet sizes or some kind of streamed - mode, as this driver is for the distribution only. One may - wonder why the header word is coded explicitly in big endian - when an UDS socket is local to the host. The answer simply is - that I see it as a good practice when writing a distribution - driver, as distribution in practice usually cross the host - boundaries. </p> - <p>On line 4-8 we handle the case where the port is in data or - intermediate mode, the rest of the routine handles the - different commands. We see (first on line 15) that the routine - uses the <c><![CDATA[driver_failure_posix()]]></c> routine to report - errors. One important thing to remember is that the failure - routines make a call to our <c><![CDATA[uds_stop]]></c> routine, which - will remove the internal port data. The handle (and the casted - handle <c><![CDATA[ud]]></c>) is therefore <em>invalid pointers</em> after a - <c><![CDATA[driver_failure]]></c> call and we should <em>immediately return</em>. The runtime system will send exit signals to all + mode, as this driver is for the distribution only. + Why is the header word coded explicitly in big-endian when a UDS + socket is local to the host? It is good practice when writing a + distribution driver, as distribution in practice usually crosses + the host boundaries.</p> + + <p>On line 4-8 is handled the case where the port is in <c>data</c> mode + or <c>intermediate</c> mode and the remaining routine handles the + different commands. The routine uses the + <c><![CDATA[driver_failure_posix()]]></c> routine to report errors + (see, for example, line 15). Notice that the failure routines make + a call to the <c><![CDATA[uds_stop]]></c> routine, which will + remove the internal port data. The handle (and the casted handle + <c><![CDATA[ud]]></c>) is therefore <em>invalid pointers</em> after a + <c><![CDATA[driver_failure]]></c> call and we should <em>return + immediately</em>. The runtime system will send exit signals to all linked processes.</p> - <p>The uds_input routine gets called when data is available on a - file descriptor previously passed to the <c><![CDATA[driver_select]]></c> - routine. Typically this happens when a read command is issued - and no data is available. Lets look at the <c><![CDATA[do_recv]]></c> - routine:</p> + + <p>The <c>uds_input</c> routine is called when data is available on a + file descriptor previously passed to the + <c><![CDATA[driver_select]]></c> routine. This occurs typically when + a read command is issued and no data is available. The + <c><![CDATA[do_recv]]></c> routine is as follows:</p> + <code type="none"><![CDATA[ ( 1) static void do_recv(UdsData *ud) ( 2) { @@ -715,29 +1609,34 @@ (26) } (27) } (28) } ]]></code> + <p>The routine tries to read data until a packet is read or the <c><![CDATA[buffered_read_package]]></c> routine returns a - <c><![CDATA[NORMAL_READ_FAILURE]]></c> (an internally defined constant for - the module that means that the read operation resulted in an - <c><![CDATA[EWOULDBLOCK]]></c>). If the port is in command mode, the - reading stops when one package is read, but if it is in data - mode, the reading continues until the socket buffer is empty - (read failure). If no more data can be read and more is wanted - (always the case when socket is in data mode) driver_select is - called to make the <c><![CDATA[uds_input]]></c> call-back be called when - more data is available for reading.</p> - <p>When the port is in data mode, all data is sent to Erlang in a - format that suits the distribution, in fact the raw data will + <c><![CDATA[NORMAL_READ_FAILURE]]></c> (an internally defined constant + for the module, which means that the read operation resulted in an + <c><![CDATA[EWOULDBLOCK]]></c>). If the port is in <c>command</c> mode, + the reading stops when one package is read. If the port is in + <c>data</c> mode, the reading continues until the socket buffer is empty + (read failure). If no more data can be read and more is wanted (which + is always the case when the socket is in <c>data</c> mode), + <c>driver_select</c> is called to make the <c><![CDATA[uds_input]]></c> + callback be called when more data is available for reading.</p> + + <p>When the port is in <c>data</c> mode, all data is sent to Erlang in a + format that suits the distribution. In fact, the raw data will never reach any Erlang process, but will be translated/interpreted by the emulator itself and then delivered in the correct format to the correct processes. In - the current emulator version, received data should be tagged - with a single byte of 100. Thats what the macro - <c><![CDATA[DIST_MAGIC_RECV_TAG]]></c> is defined to. The tagging of data - in the distribution will possibly change in the future.</p> - <p>The <c><![CDATA[uds_input]]></c> routine will handle other input events - (like nonblocking <c><![CDATA[accept]]></c>), but most importantly handle + the current emulator version, received data is to be tagged + with a single byte of 100. That is what the macro + <c><![CDATA[DIST_MAGIC_RECV_TAG]]></c> is defined to. The tagging of + data in the distribution can be changed in the future.</p> + + <p>The <c><![CDATA[uds_input]]></c> routine handles other input events + (like non-blocking <c><![CDATA[accept]]></c>), but most importantly + handle data arriving at the socket by calling <c><![CDATA[do_recv]]></c>:</p> + <code type="none"><![CDATA[ ( 1) static void uds_input(ErlDrvData handle, ErlDrvEvent event) ( 2) { @@ -767,13 +1666,16 @@ (24) } (25) do_recv(ud); (26) } ]]></code> - <p>The important line here is the last line in the function, the - <c><![CDATA[do_read]]></c> routine is called to handle new input. The rest - of the function handles input on a listen socket, which means - that there should be possible to do an accept on the + + <p>The important line is the last line in the function: the + <c><![CDATA[do_read]]></c> routine is called to handle new input. + The remaining function handles input on a listen socket, which means + that it is to be possible to do an accept on the socket, which is also recognized as a read event.</p> - <p>The output mechanisms are similar to the input. Lets first - look at the <c><![CDATA[do_send]]></c> routine:</p> + + <p>The output mechanisms are similar to the input. + The <c><![CDATA[do_send]]></c> routine is as follows:</p> + <code type="none"><![CDATA[ ( 1) static void do_send(UdsData *ud, char *buff, int bufflen) ( 2) { @@ -815,33 +1717,36 @@ (37) driver_enqv(ud->port, &eio, written); (38) send_out_queue(ud); (39) } ]]></code> + <p>This driver uses the <c><![CDATA[writev]]></c> system call to send data - onto the socket. A combination of writev and the driver output - queues is very convenient. An <em>ErlIOVec</em> structure - contains a <em>SysIOVec</em> (which is equivalent to the - <c><![CDATA[struct iovec]]></c> structure defined in <c><![CDATA[uio.h]]></c>. The - ErlIOVec also contains an array of <em>ErlDrvBinary</em> + onto the socket. A combination of <c>writev</c> and the driver output + queues is very convenient. An <c>ErlIOVec</c> structure + contains a <c>SysIOVec</c> (which is equivalent to the + <c><![CDATA[struct iovec]]></c> structure defined in + <c><![CDATA[uio.h]]></c>. The + <c>ErlIOVec</c> also contains an array of <c>ErlDrvBinary</c> pointers, of the same length as the number of buffers in the I/O vector itself. One can use this to allocate the binaries - for the queue "manually" in the driver, but we'll just fill - the binary array with NULL values (line 7) , which will make - the runtime system allocate its own buffers when we call - <c><![CDATA[driver_enqv]]></c> (line 37).</p> - <p></p> + for the queue "manually" in the driver, but here + the binary array is filled with <c>NULL</c> values (line 7). + The runtime system then allocates its own buffers when + <c><![CDATA[driver_enqv]]></c> is called (line 37).</p> + <p>The routine builds an I/O vector containing the header bytes and the buffer (the opcode has been removed and the buffer length decreased by the output routine). If the queue is - empty, we'll write the data directly to the socket (or at + empty, we write the data directly to the socket (or at least try to). If any data is left, it is stored in the queue - and then we try to send the queue (line 38). An ack is sent - when the message is delivered completely (line 22). The - <c><![CDATA[send_out_queue]]></c> will send acks if the sending is - completed there. If the port is in command mode, the Erlang + and then we try to send the queue (line 38). An acknowledgement + is sent when the message is delivered completely (line 22). The + <c><![CDATA[send_out_queue]]></c> sends acknowledgements if the sending + is completed there. If the port is in <c>command</c> mode, the Erlang code serializes the send operations so that only one packet - can be waiting for delivery at a time. Therefore the ack can - be sent simply whenever the queue is empty.</p> - <p></p> - <p>A short look at the <c><![CDATA[send_out_queue]]></c> routine:</p> + can be waiting for delivery at a time. Therefore the acknowledgement + can be sent whenever the queue is empty.</p> + + <p>The <c><![CDATA[send_out_queue]]></c> routine is as follows:</p> + <code type="none"><![CDATA[ ( 1) static int send_out_queue(UdsData *ud) ( 2) { @@ -873,20 +1778,24 @@ (28) ud->sent += wrote; (29) } (30) } ]]></code> - <p>What we do is simply to pick out an I/O vector from the queue - (which is the whole queue as an <em>SysIOVec</em>). If the I/O - vector is to long (IO_VECTOR_MAX is defined to 16), the vector + + <p>We simply pick out an I/O vector from the queue + (which is the whole queue as a <c>SysIOVec</c>). If the I/O + vector is too long (<c>IO_VECTOR_MAX</c> is defined to 16), the vector length is decreased (line 15), otherwise the <c><![CDATA[writev]]></c> - (line 17) call will - fail. Writing is tried and anything written is dequeued (line - 27). If the write fails with <c><![CDATA[EWOULDBLOCK]]></c> (note that all - sockets are in nonblocking mode), <c><![CDATA[driver_select]]></c> is + call (line 17) fails. Writing is tried and anything written is dequeued + (line 27). + If the write fails with <c><![CDATA[EWOULDBLOCK]]></c> (notice that all + sockets are in non-blocking mode), <c><![CDATA[driver_select]]></c> is called to make the <c><![CDATA[uds_output]]></c> routine be called when there is space to write again.</p> - <p>We will continue trying to write until the queue is empty or - the writing would block.</p> - <p>The routine above are called from the <c><![CDATA[uds_output]]></c> - routine, which looks like this:</p> + + <p>We continue trying to write until the queue is empty or + the writing blocks.</p> + + <p>The routine above is called from the <c><![CDATA[uds_output]]></c> + routine:</p> + <code type="none"><![CDATA[ ( 1) static void uds_output(ErlDrvData handle, ErlDrvEvent event) ( 2) { @@ -899,51 +1808,80 @@ ( 9) } (10) send_out_queue(ud); (11) } ]]></code> - <p>The routine is simple, it first handles the fact that the + + <p>The routine is simple: it first handles the fact that the output select will concern a socket in the business of connecting (and the connecting blocked). If the socket is in - a connected state it simply sends the output queue, this - routine is called when there is possible to write to a socket + a connected state, it simply sends the output queue. This + routine is called when it is possible to write to a socket where we have an output queue, so there is no question what to do.</p> + <p>The driver implements a control interface, which is a synchronous interface called when Erlang calls - <c><![CDATA[erlang:port_control/3]]></c>. This is the only interface - that can control the driver when it is in data mode and it may + <seealso marker="erlang#port_control/3"> + <c>erlang:port_control/3</c></seealso>. Only this interface + can control the driver when it is in <c>data</c> mode. It can be called with the following opcodes:</p> - <list type="bulleted"> - <item>'C': Set port in command mode.</item> - <item>'I': Set port in intermediate mode.</item> - <item>'D': Set port in data mode.</item> - <item>'N': Get identification number for listen port, this - identification number is used in an accept command to the - driver, it is returned as a big endian 32 bit integer, which - happens to be the file identifier for the listen socket.</item> - <item>'S': Get statistics, which is the number of bytes received, - the number of bytes sent and the number of bytes pending in - the output queue. This data is used when the distribution - checks that a connection is alive (ticking). The statistics - is returned as 3 32 bit big endian integers.</item> - <item>'T': Send a tick message, which is a packet of length - 0. Ticking is done when the port is in data mode, so the - command for sending data cannot be used (besides it ignores - zero length packages in command mode). This is used by the - ticker to send dummy data when no other traffic is present. - <em>Note</em> that it is important that the interface for - sending ticks is not blocking. This implementation uses - <c>erlang:port_control/3</c> which does not block the caller. - If <c>erlang:port_command</c> is used, use - <c>erlang:port_command/3</c> and pass <c>[force]</c> as - option list; otherwise, the caller can be blocked indefinitely - on a busy port and prevent the system from taking down a - connection that is not functioning.</item> - <item>'R': Get creation number of listen socket, which is used to - dig out the number stored in the lock file to differentiate - between invocations of Erlang nodes with the same name.</item> - </list> + + <taglist> + <tag><c>'C'</c></tag> + <item> + <p>Sets port in <c>command</c> mode.</p> + </item> + <tag><c>'I'</c></tag> + <item> + <p>Sets port in <c>intermediate</c> mode.</p> + </item> + <tag><c>'D'</c></tag> + <item> + <p>Sets port in <c>data</c> mode.</p> + </item> + <tag><c>'N'</c></tag> + <item> + <p>Gets identification number for listen port. This + identification number is used in an accept command to the + driver. It is returned as a big-endian 32-bit integer, which + is the file identifier for the listen socket.</p> + </item> + <tag><c>'S'</c></tag> + <item> + <p>Gets statistics, which is the number of bytes received, + the number of bytes sent, and the number of bytes pending in + the output queue. This data is used when the distribution + checks that a connection is alive (ticking). The statistics + is returned as three 32-bit big-endian integers.</p> + </item> + <tag><c>'T'</c></tag> + <item> + <p>Sends a tick message, which is a packet of length 0. + Ticking is done when the port is in <c>data</c> mode, so the + command for sending data cannot be used (besides it ignores + zero length packages in <c>command</c> mode). This is used by the + ticker to send dummy data when no other traffic is present.</p> + <p><em>Note:</em> It is important that the interface for + sending ticks is not blocking. This implementation uses + <seealso marker="erlang#port_control/3"> + <c>erlang:port_control/3</c></seealso>, which does not block the + caller. If <c>erlang:port_command</c> is used, use + <seealso marker="erlang#port_command/3"> + <c>erlang:port_command/3</c></seealso> and pass <c>[force]</c> as + option list; otherwise the caller can be blocked indefinitely + on a busy port and prevent the system from taking down a + connection that is not functioning.</p> + </item> + <tag><c>'R'</c></tag> + <item> + <p>Gets creation number of a listen socket, which is used to + dig out the number stored in the lock file to differentiate + between invocations of Erlang nodes with the same name.</p> + </item> + </taglist> + <p>The control interface gets a buffer to return its value in, - but is free to allocate its own buffer is the provided one is - to small. Here is the code for <c><![CDATA[uds_control]]></c>:</p> + but is free to allocate its own buffer if the provided one is + too small. The <c><![CDATA[uds_control]]></c> code is as follows:</p> + <code type="none"><![CDATA[ ( 1) static int uds_control(ErlDrvData handle, unsigned int command, ( 2) char* buf, int count, char** res, int res_size) @@ -1024,47 +1962,55 @@ (75) } (76) #undef ENSURE (77) } ]]></code> - <p>The macro <c><![CDATA[ENSURE]]></c> (line 5 to 10) is used to ensure that - the buffer is large enough for our answer. We switch on the - command and take actions, there is not much to say about this - routine. Worth noting is that we always has read select active - on a port in data mode (achieved by calling <c><![CDATA[do_recv]]></c> on - line 45), but turn off read selection in intermediate and - command modes (line 27 and 36).</p> - <p>The rest of the driver is more or less UDS specific and not of + + <p>The macro <c><![CDATA[ENSURE]]></c> (line 5-10) is used to ensure that + the buffer is large enough for the answer. We switch on the command and + take actions. We always have read select active on a port in <c>data</c> + mode (achieved by calling <c><![CDATA[do_recv]]></c> on line 45), but + we turn off read selection in <c>intermediate</c> and <c>command</c> + modes (line 27 and 36).</p> + + <p>The rest of the driver is more or less UDS-specific and not of general interest.</p> </section> </section> <section> - <title>Putting it all together</title> - <p>To test the distribution, one can use the - <c><![CDATA[net_kernel:start/1]]></c> function, which is useful as it starts - the distribution on a running system, where tracing/debugging - can be performed. The <c><![CDATA[net_kernel:start/1]]></c> routine takes a - list as its single argument. The lists first element should be - the node name (without the "@hostname") as an atom, and the second (and - last) element should be one of the atoms <c><![CDATA[shortnames]]></c> or - <c><![CDATA[longnames]]></c>. In the example case <c><![CDATA[shortnames]]></c> is - preferred. </p> - <p>For net kernel to find out which distribution module to use, the - command line argument <c><![CDATA[-proto_dist]]></c> is used. The argument - is followed by one or more distribution module names, with the - "_dist" suffix removed, i.e. uds_dist as a distribution module + <title>Putting It All Together</title> + <p>To test the distribution, the <c><![CDATA[net_kernel:start/1]]></c> + function can be used. It is useful, as it starts the distribution on a + running system, where tracing/debugging can be performed. + The <c><![CDATA[net_kernel:start/1]]></c> routine takes a + list as its single argument. The list first element in the list is to be + the node name (without the "@hostname") as an atom. The second (and + last) element is to be one of the atoms <c><![CDATA[shortnames]]></c> or + <c><![CDATA[longnames]]></c>. In the example case, + <c><![CDATA[shortnames]]></c> is preferred.</p> + + <p>For <c>net_kernel</c> to find out which distribution module to use, + command-line argument <c><![CDATA[-proto_dist]]></c> is used. It + is followed by one or more distribution module names, with suffix + "_dist" removed, that is, <c>uds_dist</c> as a distribution module is specified as <c><![CDATA[-proto_dist uds]]></c>.</p> - <p>If no epmd (TCP port mapper daemon) is used, one should also - specify the command line option <c><![CDATA[-no_epmd]]></c>, which will make - Erlang skip the epmd startup, both as a OS process and as an + + <p>If no <c>epmd</c> (TCP port mapper daemon) is used, also command-line + option <c><![CDATA[-no_epmd]]></c> is to be specified, which makes + Erlang skip the <c>epmd</c> startup, both as an OS process and as an Erlang ditto.</p> + <p>The path to the directory where the distribution modules reside - must be known at boot, which can either be achieved by - specifying <c><![CDATA[-pa <path>]]></c> on the command line or by building - a boot script containing the applications used for your - distribution protocol (in the uds_dist protocol, it's only the - uds_dist application that needs to be added to the script).</p> - <p>The distribution will be started at boot if all the above is + must be known at boot. This can be achieved either by + specifying <c><![CDATA[-pa <path>]]></c> on the command line or by + building a boot script containing the applications used for your + distribution protocol. (In the <c>uds_dist</c> protocol, only the + <c>uds_dist</c> application needs to be added to the script.)</p> + + <p>The distribution starts at boot if all the above is specified and an <c><![CDATA[-sname <name>]]></c> flag is present at the - command line, here follows two examples: </p> + command line.</p> + + <p><em>Example 1:</em></p> + <pre> $ <input>erl -pa $ERL_TOP/lib/kernel/examples/uds_dist/ebin -proto_dist uds -no_epmd</input> Erlang (BEAM) emulator version 5.0 @@ -1073,7 +2019,9 @@ Eshell V5.0 (abort with ^G) 1> <input>net_kernel:start([bing,shortnames]).</input> {ok,<0.30.0>} (bing@hador)2></pre> - <p>...</p> + + <p><em>Example 2:</em></p> + <pre> $ <input>erl -pa $ERL_TOP/lib/kernel/examples/uds_dist/ebin -proto_dist uds \ </input> <input> -no_epmd -sname bong</input> @@ -1081,8 +2029,10 @@ Erlang (BEAM) emulator version 5.0 Eshell V5.0 (abort with ^G) (bong@hador)1></pre> - <p>One can utilize the ERL_FLAGS environment variable to store the + + <p>The <c>ERL_FLAGS</c> environment variable can be used to store the complicated parameters in:</p> + <pre> $ <input>ERL_FLAGS=-pa $ERL_TOP/lib/kernel/examples/uds_dist/ebin \ </input> <input> -proto_dist uds -no_epmd</input> @@ -1092,8 +2042,8 @@ Erlang (BEAM) emulator version 5.0 Eshell V5.0 (abort with ^G) (bang@hador)1></pre> - <p>The <c><![CDATA[ERL_FLAGS]]></c> should preferably not include the name of - the node.</p> + + <p><c><![CDATA[ERL_FLAGS]]></c> should not include the node name.</p> </section> </chapter> diff --git a/erts/doc/src/book.xml b/erts/doc/src/book.xml index dc02edc5c6..a0780c91d9 100644 --- a/erts/doc/src/book.xml +++ b/erts/doc/src/book.xml @@ -4,20 +4,21 @@ <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> diff --git a/erts/doc/src/communication.xml b/erts/doc/src/communication.xml index 02040c9edb..7e18a73aa8 100644 --- a/erts/doc/src/communication.xml +++ b/erts/doc/src/communication.xml @@ -4,20 +4,21 @@ <chapter> <header> <copyright> - <year>2012</year><year>2013</year> + <year>2012</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -25,63 +26,72 @@ <prepared>Rickard Green</prepared> <responsible></responsible> <docno></docno> - <approved></approved> + <approved>uy</approved> <checked></checked> <date>2012-12-03</date> <rev>PA1</rev> <file>communication.xml</file> </header> <p>Communication in Erlang is conceptually performed using - asynchronous signaling. All different executing entities - such as processes, and ports communicate via asynchronous + asynchronous signaling. All different executing entities, + such as processes and ports, communicate through asynchronous signals. The most commonly used signal is a message. Other - common signals are exit, link, unlink, monitor, demonitor + common signals are exit, link, unlink, monitor, and demonitor signals.</p> + <section> <title>Passing of Signals</title> - <p>The amount of time that passes between a signal being sent + <p>The amount of time that passes between a signal is sent and the arrival of the signal at the destination is unspecified - but positive. If the receiver has terminated, the signal will - not arrive, but it is possible that it triggers another signal. - For example, a link signal sent to a non-existing process will - trigger an exit signal which will be sent back to where the link + but positive. If the receiver has terminated, the signal does + not arrive, but it can trigger another signal. + For example, a link signal sent to a non-existing process + triggers an exit signal, which is sent back to where the link signal originated from. When communicating over the distribution, - signals may be lost if the distribution channel goes down.</p> - <p>The only signal ordering guarantee given is the following. If + signals can be lost if the distribution channel goes down.</p> + + <p>The only signal ordering guarantee given is the following: if an entity sends multiple signals to the same destination entity, - the order will be preserved. That is, if <c>A</c> sends + the order is preserved; that is, if <c>A</c> sends a signal <c>S1</c> to <c>B</c>, and later sends - the signal <c>S2</c> to <c>B</c>, <c>S1</c> is guaranteed not to + signal <c>S2</c> to <c>B</c>, <c>S1</c> is guaranteed not to arrive after <c>S2</c>.</p> </section> + <section> <title>Synchronous Communication</title> <p>Some communication is synchronous. If broken down into pieces, - a synchronous communication operation, consists of two asynchronous - signals. One request signal and one reply signal. An example of - such a synchronous communication is a call to <c>process_info/2</c> - when the first argument is not <c>self()</c>. The caller will send - an asynchronous signal requesting information, and will then - wait for the reply signal containing the requested information. When - the request signal reaches its destination the destination process + a synchronous communication operation consists of two asynchronous + signals; one request signal and one reply signal. An example of + such a synchronous communication is a call to + <seealso marker="erlang:process_info/2"> + <c>erlang:process_info/2</c></seealso> + when the first argument is not <c>self()</c>. The caller sends + an asynchronous signal requesting information, and then + waits for the reply signal containing the requested information. When + the request signal reaches its destination, the destination process replies with the requested information.</p> </section> + <section> <title>Implementation</title> - <p>The implementation of different asynchronous signals in the - VM may vary over time, but the behaviour will always respect this + <p>The implementation of different asynchronous signals in the virtual + machine can vary over time, but the behavior always respects this concept of asynchronous signals being passed between entities as described above.</p> - <p>By inspecting the implementation you might notice that some - specific signal actually gives a stricter guarantee than described + + <p>By inspecting the implementation, you might notice that some + specific signal gives a stricter guarantee than described above. It is of vital importance that such knowledge about the - implementation is <em>not</em> used by Erlang code, since the - implementation might change at any time without prior notice.</p> - <p>Some example of major implementation changes:</p> + implementation is <em>not</em> used by Erlang code, as the + implementation can change at any time without prior notice.</p> + + <p>Examples of major implementation changes:</p> + <list type="bulleted"> - <item>As of ERTS version 5.5.2 exit signals to processes are truly + <item>As from ERTS 5.5.2 exit signals to processes are truly asynchronously delivered.</item> - <item>As of ERTS version 5.10 all signals from processes to ports + <item>As from ERTS 5.10 all signals from processes to ports are truly asynchronously delivered.</item> </list> </section> diff --git a/erts/doc/src/crash_dump.xml b/erts/doc/src/crash_dump.xml index 2b5fc877c3..a9aeb1888c 100644 --- a/erts/doc/src/crash_dump.xml +++ b/erts/doc/src/crash_dump.xml @@ -4,24 +4,25 @@ <chapter> <header> <copyright> - <year>1999</year><year>2013</year> + <year>1999</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> - <title>How to interpret the Erlang crash dumps</title> + <title>How to Interpret the Erlang Crash Dumps</title> <prepared>Patrik Nyblom</prepared> <responsible></responsible> <docno></docno> @@ -31,326 +32,529 @@ <rev>PA1</rev> <file>crash_dump.xml</file> </header> - <p>This document describes the <c><![CDATA[erl_crash.dump]]></c> file generated - upon abnormal exit of the Erlang runtime system.</p> - <p><em>Important:</em> For OTP release R9C the Erlang crash dump has - had a major facelift. This means that the information in this - document will not be directly applicable for older dumps. However, - if you use the Crashdump Viewer tool on older dumps, the crash - dumps are translated into a format similar to this.</p> - <p>The system will write the crash dump in the current directory of + <p>This section describes the <c><![CDATA[erl_crash.dump]]></c> file + generated upon abnormal exit of the Erlang runtime system.</p> + + <note> + <p>The Erlang crash dump had a major facelift in Erlang/OTP R9C. The + information in this section is therefore not directly applicable for + older dumps. However, if you use <seealso marker="observer:crashdump_viewer"> + <c>crashdump_viewer(3)</c></seealso> on older dumps, + the crash dumps are translated into a format similar to this.</p> + </note> + + <p>The system writes the crash dump in the current directory of the emulator or in the file pointed out by the environment variable (whatever that means on the current operating system) - ERL_CRASH_DUMP. For a crash dump to be written, there has to be a - writable file system mounted.</p> + <c>ERL_CRASH_DUMP</c>. For a crash dump to be written, a + writable file system must be mounted.</p> + <p>Crash dumps are written mainly for one of two reasons: either the - builtin function <c><![CDATA[erlang:halt/1]]></c> is called explicitly with a - string argument from running Erlang code, or else the runtime + built-in function <c><![CDATA[erlang:halt/1]]></c> is called explicitly + with a string argument from running Erlang code, or the runtime system has detected an error that cannot be handled. The most - usual reason that the system can't handle the error is that the + usual reason that the system cannot handle the error is that the cause is external limitations, such as running out of memory. A - crash dump due to an internal error may be caused by the system + crash dump caused by an internal error can be caused by the system reaching limits in the emulator itself (like the number of atoms - in the system, or too many simultaneous ets tables). Usually the + in the system, or too many simultaneous ETS tables). Usually the emulator or the operating system can be reconfigured to avoid the crash, which is why interpreting the crash dump correctly is important.</p> - <p>The erlang crash dump is a readable text file, but it might not be - very easy to read. Using the Crashdump Viewer tool in the - <c><![CDATA[observer]]></c> application will simplify the task. This is an - HTML based tool for browsing Erlang crash dumps.</p> + + <p>On systems that support OS signals, it is also possible to stop + the runtime system and generate a crash dump by sending the <c>SIGUSR1</c> + signal.</p> + + <p>The Erlang crash dump is a readable text file, but it can be difficult + to read. Using the Crashdump Viewer tool in the + <c><![CDATA[Observer]]></c> application simplifies the task. This is a + wx-widget-based tool for browsing Erlang crash dumps.</p> <section> <marker id="general_info"></marker> - <title>General information</title> - <p>The first part of the dump shows the creation time for the dump, - a slogan indicating the reason for the dump, the system version, - of the node from which the dump originates, the compile time of - the emulator running the originating node and the number of - atoms in the atom table. - </p> + <title>General Information</title> + <p>The first part of the crash dump shows the following:</p> + + <list type="bulleted"> + <item>The creation time for the dump</item> + <item>A slogan indicating the reason for the dump</item> + <item>The system version of the node from which the dump originates</item> + <item>The compile time of the emulator running the originating node</item> + <item>The number of atoms in the atom table</item> + <item>The runtime system thread that caused the crash dump</item> + </list> <section> - <title>Reasons for crash dumps (slogan)</title> - <p>The reason for the dump is noted in the beginning of the file - as <em>Slogan: <reason></em> (the word "slogan" has historical - roots). If the system is halted by the BIF + <title>Reasons for Crash Dumps (Slogan)</title> + <p>The reason for the dump is shown in the beginning of the file as:</p> + + <pre> +Slogan: <reason></pre> + + <p>If the system is halted by the BIF <c><![CDATA[erlang:halt/1]]></c>, the slogan is the string parameter passed to the BIF, otherwise it is a description generated by the emulator or the (Erlang) kernel. Normally the message - should be enough to understand the problem, but nevertheless - some messages are described here. Note however that the - suggested reasons for the crash are <em>only suggestions</em>. The exact reasons for the errors may vary + is enough to understand the problem, but + some messages are described here. Notice that the + suggested reasons for the crash are <em>only suggestions</em>. + The exact reasons for the errors can vary depending on the local applications and the underlying operating system.</p> - <list type="bulleted"> - <item>"<em><A></em>: Cannot allocate <em><N></em> - bytes of memory (of type "<em><T></em>", thread - <em><I></em>em>)." - The system has run out of memory. <A> - is the allocator that failed to allocate memory, <N> is the - number of bytes that <A> tried to allocate, <T> is the - memory block type that the memory was needed for, and <I> is the - thread identifier. The most common case is that a process stores huge - amounts of data. In this case <T> is most often - <c><![CDATA[heap]]></c>, <c><![CDATA[old_heap]]></c>, - <c><![CDATA[heap_frag]]></c>, or <c><![CDATA[binary]]></c>. - For more information on allocators see - <seealso marker="erts_alloc">erts_alloc(3)</seealso>.</item> - <item>"<em><A></em>: Cannot reallocate <em><N></em> - bytes of memory (of type "<em><T></em>", thread - <em><I></em>em>)." - Same as above with the exception that memory - was being reallocated instead of being allocated when the system ran - out of memory.</item> - <item>"Unexpected op code <em>N</em>" - Error in compiled - code, <c><![CDATA[beam]]></c> file damaged or error in the compiler.</item> - <item>"Module <em>Name</em> undefined" <c><![CDATA[|]]></c> "Function - <em>Name</em> undefined" <c><![CDATA[|]]></c> "No function - <em>Name</em>:<em>Name</em>/1" <c><![CDATA[|]]></c> "No function - <em>Name</em>:start/2" - The kernel/stdlib applications are - damaged or the start script is damaged.</item> - <item>"Driver_select called with too large file descriptor - <c><![CDATA[N]]></c>" - The number of file descriptors for sockets - exceed 1024 (Unix only). The limit on file-descriptors in - some Unix flavors can be set to over 1024, but only 1024 - sockets/pipes can be used simultaneously by Erlang (due to - limitations in the Unix <c><![CDATA[select]]></c> call). The number of - open regular files is not affected by this.</item> - <item>"Received SIGUSR1" - Sending the SIGUSR1 signal to a - Erlang machine (Unix only) forces a crash dump. This slogan reflects - that the Erlang machine crash-dumped due to receiving that signal.</item> - <item>"Kernel pid terminated (<em>Who</em>) - (<em>Exit-reason</em>)" - The kernel supervisor has detected - a failure, usually that the <c><![CDATA[application_controller]]></c> - has shut down (<c><![CDATA[Who]]></c> = <c><![CDATA[application_controller]]></c>, - <c><![CDATA[Why]]></c> = <c><![CDATA[shutdown]]></c>). The application controller - may have shut down for a number of reasons, the most usual - being that the node name of the distributed Erlang node is - already in use. A complete supervisor tree "crash" (i.e., - the top supervisors have exited) will give about the same - result. This message comes from the Erlang code and not from - the virtual machine itself. It is always due to some kind of - failure in an application, either within OTP or a - "user-written" one. Looking at the error log for your - application is probably the first step to take.</item> - <item>"Init terminating in do_boot ()" - The primitive Erlang boot - sequence was terminated, most probably because the boot - script has errors or cannot be read. This is usually a - configuration error - the system may have been started with - a faulty <c><![CDATA[-boot]]></c> parameter or with a boot script from - the wrong version of OTP.</item> - <item>"Could not start kernel pid (<em>Who</em>) ()" - One of the - kernel processes could not start. This is probably due to - faulty arguments (like errors in a <c><![CDATA[-config]]></c> argument) - or faulty configuration files. Check that all files are in - their correct location and that the configuration files (if - any) are not damaged. Usually there are also messages - written to the controlling terminal and/or the error log - explaining what's wrong.</item> - </list> - <p>Other errors than the ones mentioned above may occur, as the - <c><![CDATA[erlang:halt/1]]></c> BIF may generate any message. If the + + <taglist> + <tag><em><A>: Cannot allocate <N> bytes of memory (of type + "<T>")</em></tag> + <item> + <p>The system has run out of memory. <A> is the allocator that + failed to allocate memory, <N> is the number of bytes that + <A> tried to allocate, and <T> is the memory block + type that the memory was needed for. The most common case is + that a process stores huge amounts of data. In this case + <T> is most often <c><![CDATA[heap]]></c>, + <c><![CDATA[old_heap]]></c>, <c><![CDATA[heap_frag]]></c>, or + <c><![CDATA[binary]]></c>. For more information on allocators, see + <seealso marker="erts_alloc"><c>erts_alloc(3)</c></seealso>.</p> + </item> + <tag><em><A>: Cannot reallocate <N> bytes of memory (of + type "<T>")</em></tag> + <item> + <p>Same as above except that memory was reallocated + instead of allocated when the system ran out of memory.</p> + </item> + <tag><em>Unexpected op code <N></em></tag> + <item> + <p>Error in compiled code, <c><![CDATA[beam]]></c> file damaged, or + error in the compiler.</p> + </item> + <tag><em>Module <Name> undefined <c><![CDATA[|]]></c> Function + <Name> undefined <c><![CDATA[|]]></c> No function + <Name>:<Name>/1 <c><![CDATA[|]]></c> No function + <Name>:start/2</em></tag> + <item> + <p>The Kernel/STDLIB applications are + damaged or the start script is damaged.</p> + </item> + <tag><em>Driver_select called with too large file descriptor + <c><![CDATA[N]]></c></em></tag> + <item> + <p>The number of file descriptors for sockets + exceeds 1024 (Unix only). The limit on file descriptors in + some Unix flavors can be set to over 1024, but only 1024 + sockets/pipes can be used simultaneously by Erlang (because of + limitations in the Unix <c><![CDATA[select]]></c> call). The number + of open regular files is not affected by this.</p> + </item> + <tag><em>Received SIGUSR1</em></tag> + <item> + <p>Sending the <c>SIGUSR1</c> signal to an Erlang machine (Unix only) + forces a crash dump. This slogan reflects that the Erlang machine + crash-dumped because of receiving that signal.</p> + </item> + <tag><em>Kernel pid terminated (<Who>) (<Exit + reason>)</em></tag> + <item> + <p>The kernel supervisor has detected a failure, usually that the + <c><![CDATA[application_controller]]></c> has shut down + (<c><![CDATA[Who]]></c> = <c><![CDATA[application_controller]]></c>, + <c><![CDATA[Why]]></c> = <c><![CDATA[shutdown]]></c>). + The application controller + can have shut down for many reasons, the most usual + is that the node name of the distributed Erlang node is + already in use. A complete supervisor tree "crash" (that is, + the top supervisors have exited) gives about the same + result. This message comes from the Erlang code and not from + the virtual machine itself. It is always because of some + failure in an application, either within OTP or a + "user-written" one. Looking at the error log for your + application is probably the first step to take.</p> + </item> + <tag><em>Init terminating in do_boot ()</em></tag> + <item> + <p>The primitive Erlang boot sequence was terminated, most probably + because the boot script has errors or cannot be read. This is + usually a configuration error; the system can have been started + with a faulty <c><![CDATA[-boot]]></c> parameter or with a boot + script from the wrong OTP version.</p> + </item> + <tag><em>Could not start kernel pid (<Who>) ()</em></tag> + <item> + <p>One of the kernel processes could not start. This is probably + because of faulty arguments (like errors in a + <c><![CDATA[-config]]></c> argument) + or faulty configuration files. Check that all files are in + their correct location and that the configuration files (if + any) are not damaged. Usually messages are also + written to the controlling terminal and/or the error log + explaining what is wrong.</p> + </item> + </taglist> + + <p>Other errors than these can occur, as the + <c><![CDATA[erlang:halt/1]]></c> BIF can generate any message. If the message is not generated by the BIF and does not occur in the - list above, it may be due to an error in the emulator. There - may however be unusual messages that I haven't mentioned, that - still are connected to an application failure. There is a lot - more information available, so more thorough reading of the - crash dump may reveal the crash reason. The size of processes, - the number of ets tables and the Erlang data on each process - stack can be useful for tracking down the problem.</p> + list above, it can be because of an error in the emulator. There + can however be unusual messages, not mentioned here, which + are still connected to an application failure. There is much + more information available, so a thorough reading of the + crash dump can reveal the crash reason. The size of processes, + the number of ETS tables, and the Erlang data on each process + stack can be useful to find the problem.</p> </section> <section> - <title>Number of atoms</title> + <title>Number of Atoms</title> <p>The number of atoms in the system at the time of the crash is shown as <em>Atoms: <number></em>. Some ten thousands atoms is - perfectly normal, but more could indicate that the BIF - <c><![CDATA[erlang:list_to_atom/1]]></c> is used to dynamically generate a - lot of <em>different</em> atoms, which is never a good idea.</p> + perfectly normal, but more can indicate that the BIF + <c><![CDATA[erlang:list_to_atom/1]]></c> is used to generate many + <em>different</em> atoms dynamically, which is never a good idea.</p> </section> </section> <section> + <marker id="scheduler"></marker> + <title>Scheduler Information</title> + <p>Under the tag <em>=scheduler</em> is shown information about the current + state and statistics of the schedulers in the runtime system. On + operating systems that allow suspension of other threads, the + data within this section reflects what the runtime system looks like + when a crash occurs.</p> + + <p>The following fields can exist for a process:</p> + + <taglist> + <tag><em>=scheduler:id</em></tag> + <item> + <p>Heading. States the scheduler identifier.</p> + </item> + <tag><em>Scheduler Sleep Info Flags</em></tag> + <item> + <p>If empty, the scheduler was doing some work. + If not empty, the scheduler is either in some state of sleep, + or suspended. This entry is only present in an SMP-enabled + emulator.</p> + </item> + <tag><em>Scheduler Sleep Info Aux Work</em></tag> + <item> + <p>If not empty, a scheduler internal auxiliary work is scheduled + to be done.</p> + </item> + <tag><em>Current Port</em></tag> + <item> + <p>The port identifier of the port that is currently + executed by the scheduler.</p> + </item> + <tag><em>Current Process</em></tag> + <item> + <p>The process identifier of the process that is currently + executed by the scheduler. If there is such a process, this entry is + followed by the <em>State</em>, <em>Internal State</em>, + <em>Program Counter</em>, and <em>CP</em> of that same process. + The entries are described in section + <seealso marker="#processes">Process Information</seealso>.</p> + <p>Notice that this is a snapshot of what the entries are exactly when + the crash dump is starting to be generated. Therefore they are most + likely different (and more telling) than the entries for the same + processes found in the <em>=proc</em> section. If there is no + currently running process, only the <em>Current Process</em> entry is + shown.</p> + </item> + <tag><em>Current Process Limited Stack Trace</em></tag> + <item> + <p>This entry is shown only if there is a current process. It is + similar to <seealso marker="#proc_data"> + <em>=proc_stack</em></seealso>, except that only the function frames + are shown (that is, the stack variables are omitted). + Also, only the top and bottom part of the stack are shown. If the + stack is small (< 512 slots), the entire stack is shown. Otherwise + the entry <em>skipping ## slots</em> is shown, where <c>##</c> + is replaced by the number of slots that has been skipped.</p> + </item> + <tag><em>Run Queue</em></tag> + <item> + <p>Shows statistics about how many processes and ports + of different priorities are scheduled on this scheduler.</p> + </item> + <tag><em>** crashed **</em></tag> + <item> + <p>This entry is normally not shown. It signifies that getting the rest + of the information about this scheduler failed for some reason.</p> + </item> + </taglist> + </section> + + <section> <marker id="memory"></marker> - <title>Memory information</title> - <p>Under the tag <em>=memory</em> you will find information similar - to what you can obtain on a living node with - <seealso marker="erts:erlang#erlang:memory/0">erlang:memory()</seealso>.</p> + <title>Memory Information</title> + <p>Under the tag <em>=memory</em> is shown information similar + to what can be obtainted on a living node with + <seealso marker="erts:erlang#erlang:memory/0"> + <c>erlang:memory()</c></seealso>.</p> </section> <section> <marker id="internal_tables"></marker> - <title>Internal table information</title> - <p>The tags <em>=hash_table:<table_name></em> and - <em>=index_table:<table_name></em> presents internal - tables. These are mostly of interest for runtime system - developers.</p> + <title>Internal Table Information</title> + <p>Under the tags <em>=hash_table:<table_name></em> and + <em>=index_table:<table_name></em> is shown internal + tables. These are mostly of interest for runtime system developers.</p> </section> <section> <marker id="allocated_areas"></marker> - <title>Allocated areas</title> - <p>Under the tag <em>=allocated_areas</em> you will find information - similar to what you can obtain on a living node with - <seealso marker="erts:erlang#system_info_allocated_areas">erlang:system_info(allocated_areas)</seealso>.</p> + <title>Allocated Areas</title> + <p>Under the tag <em>=allocated_areas</em> is shown information + similar to what can be obtained on a living node with + <seealso marker="erts:erlang#system_info_allocated_areas"> + <c>erlang:system_info(allocated_areas)</c></seealso>.</p> </section> <section> <marker id="allocator"></marker> <title>Allocator</title> - <p>Under the tag <em>=allocator:<A></em> you will find + <p>Under the tag <em>=allocator:<A></em> is shown various information about allocator <A>. The information - is similar to what you can obtain on a living node with - <seealso marker="erts:erlang#system_info_allocator_tuple">erlang:system_info({allocator, <A>})</seealso>. - For more information see the documentation of - <seealso marker="erts:erlang#system_info_allocator_tuple">erlang:system_info({allocator, <A>})</seealso>, - and the - <seealso marker="erts_alloc">erts_alloc(3)</seealso> - documentation.</p> + is similar to what can be obtained on a living node with + <seealso marker="erts:erlang#system_info_allocator_tuple"> + <c>erlang:system_info({allocator, <A>})</c></seealso>. + For more information, see also + <seealso marker="erts_alloc"><c>erts_alloc(3)</c></seealso>.</p> </section> <section> <marker id="processes"></marker> - <title>Process information</title> + <title>Process Information</title> <p>The Erlang crashdump contains a listing of each living Erlang - process in the system. The process information for one process - may look like this (line numbers have been added): - </p> - <p>The following fields can exist for a process:</p> + process in the system. The following fields can exist for a process:</p> + <taglist> <tag><em>=proc:<pid></em></tag> - <item>Heading, states the process identifier</item> + <item> + <p>Heading. States the process identifier.</p> + </item> <tag><em>State</em></tag> <item> <p>The state of the process. This can be one of the following:</p> - <list type="bulleted"> - <item><em>Scheduled</em> - The process was scheduled to run - but not currently running ("in the run queue").</item> - <item><em>Waiting</em> - The process was waiting for - something (in <c><![CDATA[receive]]></c>).</item> - <item><em>Running</em> - The process was currently - running. If the BIF <c><![CDATA[erlang:halt/1]]></c> was called, this was - the process calling it.</item> - <item><em>Exiting</em> - The process was on its way to - exit.</item> - <item><em>Garbing</em> - This is bad luck, the process was - garbage collecting when the crash dump was written, the rest - of the information for this process is limited.</item> - <item><em>Suspended</em> - The process is suspended, either - by the BIF <c><![CDATA[erlang:suspend_process/1]]></c> or because it is - trying to write to a busy port.</item> - </list> + <taglist> + <tag><em>Scheduled</em></tag> + <item>The process was scheduled to run + but is currently not running ("in the run queue").</item> + <tag><em>Waiting</em></tag> + <item>The process was waiting for + something (in <c><![CDATA[receive]]></c>).</item> + <tag><em>Running</em></tag> + <item>The process was currently running. + If the BIF <c><![CDATA[erlang:halt/1]]></c> was called, this was + the process calling it.</item> + <tag><em>Exiting</em></tag> + <item>The process was on its way to exit.</item> + <tag><em>Garbing</em></tag> + <item>This is bad luck, the process was + garbage collecting when the crash dump was written. The rest + of the information for this process is limited.</item> + <tag><em>Suspended</em></tag> + <item>The process is suspended, either + by the BIF <c><![CDATA[erlang:suspend_process/1]]></c> or because + it tries to write to a busy port.</item> + </taglist> </item> <tag><em>Registered name</em></tag> - <item>The registered name of the process, if any.</item> + <item> + <p>The registered name of the process, if any.</p> + </item> <tag><em>Spawned as</em></tag> - <item>The entry point of the process, i.e., what function was - referenced in the <c><![CDATA[spawn]]></c> or <c><![CDATA[spawn_link]]></c> call that - started the process.</item> + <item> + <p>The entry point of the process, that is, what function was + referenced in the <c><![CDATA[spawn]]></c> or + <c><![CDATA[spawn_link]]></c> call that + started the process.</p> + </item> <tag><em>Last scheduled in for | Current call</em></tag> - <item>The current function of the process. These fields will not - always exist.</item> - <tag><em>Run queue</em></tag> - <item>The identifier of the scheduler run queue in which the process is - running.</item> + <item> + <p>The current function of the process. These fields do not + always exist.</p> + </item> <tag><em>Spawned by</em></tag> - <item>The parent of the process, i.e. the process which executed - <c><![CDATA[spawn]]></c> or <c><![CDATA[spawn_link]]></c>.</item> + <item> + <p>The parent of the process, that is, the process that executed + <c><![CDATA[spawn]]></c> or <c><![CDATA[spawn_link]]></c>.</p> + </item> <tag><em>Started</em></tag> - <item>The date and time when the process was started.</item> + <item> + <p>The date and time when the process was started.</p> + </item> <tag><em>Message queue length</em></tag> - <item>The number of messages in the process' message queue.</item> + <item> + <p>The number of messages in the process' message queue.</p> + </item> <tag><em>Number of heap fragments</em></tag> - <item>The number of allocated heap fragments.</item> + <item> + <p>The number of allocated heap fragments.</p> + </item> <tag><em>Heap fragment data</em></tag> - <item>Size of fragmented heap data. This is data either created by - messages being sent to the process or by the Erlang BIFs. This - amount depends on so many things that this field is utterly - uninteresting.</item> + <item> + <p>Size of fragmented heap data. This is data either created by + messages sent to the process or by the Erlang BIFs. This + amount depends on so many things that this field is utterly + uninteresting.</p> + </item> <tag><em>Link list</em></tag> - <item>Process id's of processes linked to this one. May also contain - ports. If process monitoring is used, this field also tells in - which direction the monitoring is in effect, i.e., a link - being "to" a process tells you that the "current" process was - monitoring the other and a link "from" a process tells you - that the other process was monitoring the current one.</item> + <item> + <p>Process IDs of processes linked to this one. Can also contain + ports. If process monitoring is used, this field also tells in + which direction the monitoring is in effect. That is, a link + "to" a process tells you that the "current" process was + monitoring the other, and a link "from" a process tells you + that the other process was monitoring the current one.</p> + </item> <tag><em>Reductions</em></tag> - <item>The number of reductions consumed by the process.</item> + <item> + <p>The number of reductions consumed by the process.</p> + </item> <tag><em>Stack+heap</em></tag> - <item>The size of the stack and heap (they share memory segment)</item> + <item> + <p>The size of the stack and heap (they share memory segment).</p> + </item> <tag><em>OldHeap</em></tag> - <item>The size of the "old heap". The Erlang virtual machine uses - generational garbage collection with two generations. There is - one heap for new data items and one for the data that have - survived two garbage collections. The assumption (which is - almost always correct) is that data that survive two garbage - collections can be "tenured" to a heap more seldom garbage - collected, as they will live for a long period. This is a - quite usual technique in virtual machines. The sum of the - heaps and stack together constitute most of the process's - allocated memory.</item> + <item> + <p>The size of the "old heap". The Erlang virtual machine uses + generational garbage collection with two generations. There is + one heap for new data items and one for the data that has + survived two garbage collections. The assumption (which is + almost always correct) is that data surviving two garbage + collections can be "tenured" to a heap more seldom garbage + collected, as they will live for a long period. This is a + usual technique in virtual machines. The sum of the + heaps and stack together constitute most of the + allocated memory of the process.</p> + </item> <tag><em>Heap unused, OldHeap unused</em></tag> - <item>The amount of unused memory on each heap. This information is - usually useless.</item> - <tag><em>Stack</em></tag> - <item>If the system uses shared heap, the fields - <em>Stack+heap</em>, <em>OldHeap</em>, <em>Heap unused</em> - and <em>OldHeap unused</em> do not exist. Instead this field - presents the size of the process' stack.</item> + <item> + <p>The amount of unused memory on each heap. This information is + usually useless.</p> + </item> <tag><em>Memory</em></tag> - <item>The total memory used by this process. This includes call stack, - heap and internal structures. Same as <seealso marker="erlang#process_info-2">erlang:process_info(Pid,memory)</seealso>. + <item> + <p>The total memory used by this process. This includes call stack, + heap, and internal structures. Same as + <seealso marker="erlang#process_info-2"> + <c>erlang:process_info(Pid,memory)</c></seealso>.</p> </item> <tag><em>Program counter</em></tag> - <item>The current instruction pointer. This is only interesting for - runtime system developers. The function into which the program - counter points is the current function of the process.</item> + <item> + <p>The current instruction pointer. This is only of interest for + runtime system developers. The function into which the program + counter points is the current function of the process.</p> + </item> <tag><em>CP</em></tag> - <item>The continuation pointer, i.e. the return address for the - current call. Usually useless for other than runtime system - developers. This may be followed by the function into which - the CP points, which is the function calling the current - function.</item> + <item> + <p>The continuation pointer, that is, the return address for the + current call. Usually useless for other than runtime system + developers. This can be followed by the function into which + the CP points, which is the function calling the current + function.</p> + </item> <tag><em>Arity</em></tag> - <item>The number of live argument registers. The argument registers, - if any are live, will follow. These may contain the arguments - of the function if they are not yet moved to the stack.</item> + <item> + <p>The number of live argument registers. The argument registers + if any are live will follow. These can contain the arguments + of the function if they are not yet moved to the stack.</p> + </item> + <tag><em>Internal State</em></tag> + <item> + <p>A more detailed internal representation of the state of + this process.</p> + </item> </taglist> - <p>See also the section about <seealso marker="#proc_data">process data</seealso>.</p> + <p>See also section <seealso marker="#proc_data">Process Data</seealso>.</p> </section> <section> <marker id="ports"></marker> - <title>Port information</title> + <title>Port Information</title> <p>This section lists the open ports, their owners, any linked - processed, and the name of their driver or external process.</p> + processes, and the name of their driver or external process.</p> </section> <section> <marker id="ets_tables"></marker> - <title>ETS tables</title> + <title>ETS Tables</title> <p>This section contains information about all the ETS tables in - the system. The following fields are interesting for each table:</p> + the system. The following fields are of interest for each table:</p> + <taglist> <tag><em>=ets:<owner></em></tag> - <item>Heading, states the owner of the table (a process identifier)</item> + <item> + <p>Heading. States the table owner (a process identifier).</p> + </item> <tag><em>Table</em></tag> - <item>The identifier for the table. If the table is a - <c><![CDATA[named_table]]></c>, this is the name.</item> + <item> + <p>The identifier for the table. If the table is a + <c><![CDATA[named_table]]></c>, this is the name.</p> + </item> <tag><em>Name</em></tag> - <item>The name of the table, regardless of whether it is a - <c><![CDATA[named_table]]></c> or not.</item> - <tag><em>Buckets</em></tag> - <item>This occurs if the table is a hash table, i.e. if it is not an - <c><![CDATA[ordered_set]]></c>.</item> + <item> + <p>The table name, regardless of if it is a + <c><![CDATA[named_table]]></c> or not.</p> + </item> + <tag><em>Hash table, Buckets</em></tag> + <item> + <p>If the table is a hash table, that is, if it is not an + <c><![CDATA[ordered_set]]></c>.</p> + </item> + <tag><em>Hash table, Chain Length</em></tag> + <item> + <p>If the table is a hash table. Contains statistics about the + table, such as the maximum, minimum, and average chain length. + Having a maximum much larger than the average, and a standard + deviation much larger than the expected standard deviation is + a sign that the hashing of the terms + behaves badly for some reason.</p> + </item> <tag><em>Ordered set (AVL tree), Elements</em></tag> - <item>This occurs only if the table is an <c><![CDATA[ordered_set]]></c>. (The - number of elements is the same as the number of objects in the - table.)</item> + <item> + <p>If the table is an <c><![CDATA[ordered_set]]></c>. (The + number of elements is the same as the number of objects in the + table.)</p> + </item> + <tag><em>Fixed</em></tag> + <item> + <p>If the table is fixed using + <seealso marker="stdlib:ets#safe_fixtable/2"> + <c>ets:safe_fixtable/2</c></seealso> or some internal mechanism.</p> + </item> <tag><em>Objects</em></tag> - <item>The number of objects in the table</item> + <item> + <p>The number of objects in the table.</p> + </item> <tag><em>Words</em></tag> - <item>The number of words (usually 4 bytes/word) allocated to data - in the table.</item> + <item> + <p>The number of words (usually 4 bytes/word) allocated to data + in the table.</p> + </item> + <tag><em>Type</em></tag> + <item> + <p>The table type, that is, <c>set</c>, <c>bag</c>, + <c>dublicate_bag</c>, or <c>ordered_set</c>.</p> + </item> + <tag><em>Compressed</em></tag> + <item> + <p>If the table was compressed.</p> + </item> + <tag><em>Protection</em></tag> + <item> + <p>The protection of the table.</p> + </item> + <tag><em>Write Concurrency</em></tag> + <item> + <p>If <c>write_concurrency</c> was enabled for the table.</p> + </item> + <tag><em>Read Concurrency</em></tag> + <item> + <p>If <c>read_concurrency</c> was enabled for the table.</p> + </item> </taglist> </section> @@ -359,167 +563,252 @@ <title>Timers</title> <p>This section contains information about all the timers started with the BIFs <c><![CDATA[erlang:start_timer/3]]></c> and - <c><![CDATA[erlang:send_after/3]]></c>. The following fields exists for each - timer:</p> + <c><![CDATA[erlang:send_after/3]]></c>. The following fields exist + for each timer:</p> + <taglist> <tag><em>=timer:<owner></em></tag> - <item>Heading, states the owner of the timer (a process identifier) - i.e. the process to receive the message when the timer - expires.</item> + <item> + <p>Heading. States the timer owner (a process identifier), + that is, the process to receive the message when the timer + expires.</p> + </item> <tag><em>Message</em></tag> - <item>The message to be sent.</item> + <item> + <p>The message to be sent.</p> + </item> <tag><em>Time left</em></tag> - <item>Number of milliseconds left until the message would have been - sent.</item> + <item> + <p>Number of milliseconds left until the message would have been + sent.</p> + </item> </taglist> </section> <section> <marker id="distribution_info"></marker> - <title>Distribution information</title> - <p>If the Erlang node was alive, i.e., set up for communicating + <title>Distribution Information</title> + <p>If the Erlang node was alive, that is, set up for communicating with other nodes, this section lists the connections that were active. The following fields can exist:</p> + <taglist> <tag><em>=node:<node_name></em></tag> - <item>The name of the node</item> + <item> + <p>The node name.</p> + </item> <tag><em>no_distribution</em></tag> - <item>This will only occur if the node was not distributed.</item> + <item> + <p>If the node was not distributed.</p> + </item> <tag><em>=visible_node:<channel></em></tag> - <item>Heading for a visible nodes, i.e. an alive node with a - connection to the node that crashed. States the channel number - for the node.</item> + <item> + <p>Heading for a visible node, that is, an alive node with a + connection to the node that crashed. States the channel number + for the node.</p> + </item> <tag><em>=hidden_node:<channel></em></tag> - <item>Heading for a hidden node. A hidden node is the same as a - visible node, except that it is started with the "-hidden" - flag. States the channel number for the node.</item> + <item> + <p>Heading for a hidden node. A hidden node is the same as a + visible node, except that it is started with the <c>"-hidden"</c> + flag. States the channel number for the node.</p> + </item> <tag><em>=not_connected:<channel></em></tag> - <item>Heading for a node which is has been connected to the crashed - node earlier. References (i.e. process or port identifiers) - to the not connected node existed at the time of the crash. - exist. States the channel number for the node.</item> + <item> + <p>Heading for a node that was connected to the crashed + node earlier. References (that is, process or port identifiers) + to the not connected node existed at the time of the crash. + States the channel number for the node.</p> + </item> <tag><em>Name</em></tag> - <item>The name of the remote node.</item> + <item> + <p>The name of the remote node.</p> + </item> <tag><em>Controller</em></tag> - <item>The port which controls the communication with the remote node.</item> + <item> + <p>The port controlling communication with the remote node.</p> + </item> <tag><em>Creation</em></tag> - <item>An integer (1-3) which together with the node name identifies - a specific instance of the node.</item> - <tag><em>Remote monitoring: <local_proc> <remote_proc></em></tag> - <item>The local process was monitoring the remote process at the - time of the crash.</item> - <tag><em>Remotely monitored by: <local_proc> <remote_proc></em></tag> - <item>The remote process was monitoring the local process at the - time of the crash.</item> + <item> + <p>An integer (1-3) that together with the node name identifies + a specific instance of the node.</p> + </item> + <tag><em>Remote monitoring: <local_proc> <remote_proc></em> + </tag> + <item> + <p>The local process was monitoring the remote process at the + time of the crash.</p> + </item> + <tag><em>Remotely monitored by: <local_proc> + <remote_proc></em></tag> + <item> + <p>The remote process was monitoring the local process at the + time of the crash.</p> + </item> <tag><em>Remote link: <local_proc> <remote_proc></em></tag> - <item>A link existed between the local process and the remote - process at the time of the crash.</item> + <item> + <p>A link existed between the local process and the remote + process at the time of the crash.</p> + </item> </taglist> </section> <section> <marker id="loaded_modules"></marker> - <title>Loaded module information</title> - <p>This section contains information about all loaded modules. - First, the memory usage by loaded code is summarized. There is - one field for "Current code" which is code that is the current - latest version of the modules. There is also a field for "Old - code" which is code where there exists a newer version in the - system, but the old version is not yet purged. The memory usage - is in bytes.</p> - <p>All loaded modules are then listed. The following fields exist:</p> + <title>Loaded Module Information</title> + <p>This section contains information about all loaded modules.</p> + + <p>First, the memory use by the loaded code is summarized:</p> + + <taglist> + <tag><em>Current code</em></tag> + <item> + <p>Code that is the current latest version of the modules.</p> + </item> + <tag><em>Old code</em></tag> + <item> + <p>Code where there exists a newer version in the + system, but the old version is not yet purged.</p> + </item> + </taglist> + + <p>The memory use is in bytes.</p> + + <p>Then, all loaded modules are listed. The following fields exist:</p> + <taglist> <tag><em>=mod:<module_name></em></tag> - <item>Heading, and the name of the module.</item> + <item> + <p>Heading. States the module name.</p> + </item> <tag><em>Current size</em></tag> - <item>Memory usage for the loaded code in bytes</item> + <item> + <p>Memory use for the loaded code, in bytes.</p> + </item> <tag><em>Old size</em></tag> - <item>Memory usage for the old code, if any.</item> + <item> + <p>Memory use for the old code, if any.</p> + </item> <tag><em>Current attributes</em></tag> - <item>Module attributes for the current code. This field is decoded - when looked at by the Crashdump Viewer tool.</item> + <item> + <p>Module attributes for the current code. This field is decoded + when looked at by the Crashdump Viewer tool.</p> + </item> <tag><em>Old attributes</em></tag> - <item>Module attributes for the old code, if any. This field is - decoded when looked at by the Crashdump Viewer tool.</item> + <item> + <p>Module attributes for the old code, if any. This field is + decoded when looked at by the Crashdump Viewer tool.</p> + </item> <tag><em>Current compilation info</em></tag> - <item>Compilation information (options) for the current code. This - field is decoded when looked at by the Crashdump Viewer tool.</item> + <item> + <p>Compilation information (options) for the current code. This + field is decoded when looked at by the Crashdump Viewer tool.</p> + </item> <tag><em>Old compilation info</em></tag> - <item>Compilation information (options) for the old code, if - any. This field is decoded when looked at by the Crashdump - Viewer tool.</item> + <item> + <p>Compilation information (options) for the old code, if + any. This field is decoded when looked at by the Crashdump + Viewer tool.</p> + </item> </taglist> </section> <section> <marker id="funs"></marker> - <title>Fun information</title> - <p>In this section, all funs are listed. The following fields exist - for each fun:</p> + <title>Fun Information</title> + <p>This section lists all funs. The following fields exist for each fun:</p> + <taglist> <tag><em>=fun</em></tag> - <item>Heading</item> + <item> + <p>Heading.</p> + </item> <tag><em>Module</em></tag> - <item>The name of the module where the fun was defined.</item> + <item> + <p>The name of the module where the fun was defined.</p> + </item> <tag><em>Uniq, Index</em></tag> - <item>Identifiers</item> + <item> + <p>Identifiers.</p> + </item> <tag><em>Address</em></tag> - <item>The address of the fun's code.</item> + <item> + <p>The address of the fun's code.</p> + </item> <tag><em>Native_address</em></tag> - <item>The address of the fun's code when HiPE is enabled.</item> + <item> + <p>The address of the fun's code when HiPE is enabled.</p> + </item> <tag><em>Refc</em></tag> - <item>The number of references to the fun.</item> + <item> + <p>The number of references to the fun.</p> + </item> </taglist> </section> <section> <marker id="proc_data"></marker> <title>Process Data</title> - <p>For each process there will be at least one <em>=proc_stack</em> - and one <em>=proc_heap</em> tag followed by the raw memory + <p>For each process there is at least one <em>=proc_stack</em> + and one <em>=proc_heap</em> tag, followed by the raw memory information for the stack and heap of the process.</p> - <p>For each process there will also be a <em>=proc_messages</em> - tag if the process' message queue is non-empty and a - <em>=proc_dictionary</em> tag if the process' dictionary (the - <c><![CDATA[put/2]]></c> and <c><![CDATA[get/1]]></c> thing) is non-empty.</p> + + <p>For each process there is also a <em>=proc_messages</em> + tag if the process message queue is non-empty, and a + <em>=proc_dictionary</em> tag if the process dictionary (the + <c><![CDATA[put/2]]></c> and <c><![CDATA[get/1]]></c> thing) is + non-empty.</p> + <p>The raw memory information can be decoded by the Crashdump - Viewer tool. You will then be able to see the stack dump, the - message queue (if any) and the dictionary (if any).</p> + Viewer tool. You can then see the stack dump, the + message queue (if any), and the dictionary (if any).</p> + <p>The stack dump is a dump of the Erlang process stack. Most of - the live data (i.e., variables currently in use) are placed on - the stack; thus this can be quite interesting. One has to - "guess" what's what, but as the information is symbolic, - thorough reading of this information can be very useful. As an - example we can find the state variable of the Erlang primitive - loader on line <c><![CDATA[(5)]]></c> in the example below:</p> + the live data (that is, variables currently in use) are placed on + the stack; thus this can be interesting. One has to + "guess" what is what, but as the information is symbolic, + thorough reading of this information can be useful. As an + example, we can find the state variable of the Erlang primitive + loader online <c><![CDATA[(5)]]></c> and <c><![CDATA[(6)]]></c> + in the following example:</p> + <code type="none"><![CDATA[ (1) 3cac44 Return addr 0x13BF58 (<terminate process normally>) -(2) y(0) ["/view/siri_r10_dev/clearcase/otp/erts/lib/kernel/ebin","/view/siri_r10_dev/ -(3) clearcase/otp/erts/lib/stdlib/ebin"] +(2) y(0) ["/view/siri_r10_dev/clearcase/otp/erts/lib/kernel/ebin", +(3) "/view/siri_r10_dev/clearcase/otp/erts/lib/stdlib/ebin"] (4) y(1) <0.1.0> -(5) y(2) {state,[],none,#Fun<erl_prim_loader.6.7085890>,undefined,#Fun<erl_prim_loader.7.9000327>,#Fun<erl_prim_loader.8.116480692>,#Port<0.2>,infinity,#Fun<erl_prim_loader.9.10708760>} -(6) y(3) infinity ]]></code> +(5) y(2) {state,[],none,#Fun<erl_prim_loader.6.7085890>,undefined,#Fun<erl_prim_loader.7.9000327>, +(6) #Fun<erl_prim_loader.8.116480692>,#Port<0.2>,infinity,#Fun<erl_prim_loader.9.10708760>} +(7) y(3) infinity ]]></code> + <p>When interpreting the data for a process, it is helpful to know - that anonymous function objects (funs) are given a name - constructed from the name of the function in which they are - created, and a number (starting with 0) indicating the number of - that fun within that function.</p> + that anonymous function objects (funs) are given the following:</p> + + <list type="bulleted"> + <item>A name constructed from the name of the function in which they are + created + </item> + <item>A number (starting with 0) indicating the number of that fun within + that function + </item> + </list> </section> <section> <marker id="atoms"></marker> <title>Atoms</title> - <p>Now all the atoms in the system are written. This is only - interesting if one suspects that dynamic generation of atoms could + <p>This section presents all the atoms in the system. This is only + of interest if one suspects that dynamic generation of atoms can be a problem, otherwise this section can be ignored.</p> - <p>Note that the last created atom is printed first.</p> + + <p>Notice that the last created atom is shown first.</p> </section> <section> <title>Disclaimer</title> - <p>The format of the crash dump evolves between releases of - OTP. Some information here may not apply to your - version. A description as this will never be complete; it is meant as + <p>The format of the crash dump evolves between OTP releases. + Some information described here may not apply to your + version. A description like this will never be complete; it is meant as an explanation of the crash dump in general and as a help when trying to find application errors, not as a complete specification.</p> diff --git a/erts/doc/src/driver.xml b/erts/doc/src/driver.xml index 616703fdef..8f31df4cad 100644 --- a/erts/doc/src/driver.xml +++ b/erts/doc/src/driver.xml @@ -4,120 +4,133 @@ <chapter> <header> <copyright> - <year>2001</year><year>2013</year> + <year>2001</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> - <title>How to implement a driver</title> + <title>How to Implement a Driver</title> <prepared>Jakob C</prepared> <docno></docno> <date>2000-11-28</date> <rev>PA1</rev> <file>driver.xml</file> </header> - - <note><p>This document was written a long time ago. A lot of it is still - interesting since it explains important concepts, but it was - written for an older driver interface so the examples do not - work anymore. The reader is encouraged to read - <seealso marker="erl_driver">erl_driver</seealso> and the - <seealso marker="driver_entry">driver_entry</seealso> documentation. - </p></note> + <note> + <p>This section was written a long time ago. Most of it is still + valid, as it explains important concepts, but this was + written for an older driver interface so the examples do not + work anymore. The reader is encouraged to read the + <seealso marker="erl_driver"><c>erl_driver</c></seealso> and + <seealso marker="driver_entry"><c>driver_entry</c></seealso> + documentation also.</p> + </note> <section> <title>Introduction</title> - <p>This chapter tells you how to build your own driver for erlang.</p> - <p>A driver in Erlang is a library written in C, that is linked to - the Erlang emulator and called from erlang. Drivers can be used - when C is more suitable than Erlang, to speed things up, or to - provide access to OS resources not directly accessible from - Erlang.</p> + <p>This section describes how to build your own driver for Erlang.</p> + + <p>A driver in Erlang is a library written in C, which is linked to + the Erlang emulator and called from Erlang. Drivers can be used + when C is more suitable than Erlang, to speed up things, or to + provide access to OS resources not directly accessible from Erlang.</p> + <p>A driver can be dynamically loaded, as a shared library (known as - a DLL on windows), or statically loaded, linked with the emulator + a DLL on Windows), or statically loaded, linked with the emulator when it is compiled and linked. Only dynamically loaded drivers are described here, statically linked drivers are beyond the scope - of this chapter.</p> - <p>When a driver is loaded it is executed in the context of the - emulator, shares the same memory and the same thread. This means - that all operations in the driver must be non-blocking, and that - any crash in the driver will bring the whole emulator down. In - short: you have to be extremely careful!</p> - <p></p> + of this section.</p> + + <warning> + <p>When a driver is loaded it is executed in the context of the + emulator, shares the same memory and the same thread. This means + that all operations in the driver must be non-blocking, and that + any crash in the driver brings the whole emulator down. In short, + be careful.</p> + </warning> </section> <section> - <title>Sample driver</title> - <p>This is a simple driver for accessing a postgres + <title>Sample Driver</title> + <p>This section describes a simple driver for accessing a postgres database using the libpq C client library. Postgres - is used because it's free and open source. For information - on postgres, refer to the website - <url href="http://www.postgres.org">www.postgres.org</url>.</p> + is used because it is free and open source. For information on postgres, + see <url href="http://www.postgres.org">www.postgres.org</url>.</p> + <p>The driver is synchronous, it uses the synchronous calls of - the client library. This is only for simplicity, and is - generally not good, since it will - halt the emulator while waiting for the database. - This will be improved on below with an asynchronous - sample driver.</p> - <p>The code is quite straight-forward: all + the client library. This is only for simplicity, but not good, as it + halts the emulator while waiting for the database. + This is improved below with an asynchronous sample driver.</p> + + <p>The code is straightforward: all communication between Erlang and the driver is done with <c><![CDATA[port_control/3]]></c>, and the driver returns data back using the <c><![CDATA[rbuf]]></c>.</p> + <p>An Erlang driver only exports one function: the driver entry function. This is defined with a macro, - <c><![CDATA[DRIVER_INIT]]></c>, and returns a pointer to a + <c><![CDATA[DRIVER_INIT]]></c>, which returns a pointer to a C <c><![CDATA[struct]]></c> containing the entry points that are called from the emulator. The <c><![CDATA[struct]]></c> defines the entries that the emulator calls to call the driver, with a <c><![CDATA[NULL]]></c> pointer for entries that are not defined and used by the driver.</p> + <p>The <c><![CDATA[start]]></c> entry is called when the driver is opened as a port with <c><![CDATA[open_port/2]]></c>. Here we allocate memory for a user data structure. - This user data will be passed every time the emulator - calls us. First we store the driver handle, because it - is needed in subsequent calls. We allocate memory for + This user data is passed every time the emulator + calls us. First we store the driver handle, as it + is needed in later calls. We allocate memory for the connection handle that is used by LibPQ. We also set the port to return allocated driver binaries, by - setting the flag <c><![CDATA[PORT_CONTROL_FLAG_BINARY]]></c>, calling + setting flag <c><![CDATA[PORT_CONTROL_FLAG_BINARY]]></c>, calling <c><![CDATA[set_port_control_flags]]></c>. (This is because - we don't know whether our data will fit in the - result buffer of <c><![CDATA[control]]></c>, which has a default size - set up by the emulator, currently 64 bytes.)</p> - <p>There is an entry <c><![CDATA[init]]></c> which is called when - the driver is loaded, but we don't use this, since + we do not know if our data will fit in the + result buffer of <c><![CDATA[control]]></c>, which has a default size, + 64 bytes, set up by the emulator.)</p> + + <p>An entry <c><![CDATA[init]]></c> is called when + the driver is loaded. However, we do not use this, as it is executed only once, and we want to have the possibility of several instances of the driver.</p> + <p>The <c><![CDATA[stop]]></c> entry is called when the port is closed.</p> + <p>The <c><![CDATA[control]]></c> entry is called from the emulator when the Erlang code calls <c><![CDATA[port_control/3]]></c>, to do the actual work. We have defined a simple set of - commands: <c><![CDATA[connect]]></c> to login to the database, <c><![CDATA[disconnect]]></c> - to log out and <c><![CDATA[select]]></c> to send a SQL-query and get the result. + commands: <c><![CDATA[connect]]></c> to log in to the database, + <c><![CDATA[disconnect]]></c> to log out, and <c><![CDATA[select]]></c> + to send a SQL-query and get the result. All results are returned through <c><![CDATA[rbuf]]></c>. - The library <c><![CDATA[ei]]></c> in <c><![CDATA[erl_interface]]></c> is used - to encode data in binary term format. The result is returned + The library <c><![CDATA[ei]]></c> in <c><![CDATA[erl_interface]]></c> is + used to encode data in binary term format. The result is returned to the emulator as binary terms, so <c><![CDATA[binary_to_term]]></c> is called in Erlang to convert the result to term form.</p> - <p>The code is available in <c><![CDATA[pg_sync.c]]></c> in the <c><![CDATA[sample]]></c> - directory of <c><![CDATA[erts]]></c>.</p> + + <p>The code is available in <c><![CDATA[pg_sync.c]]></c> in the + <c><![CDATA[sample]]></c> directory of <c><![CDATA[erts]]></c>.</p> + <p>The driver entry contains the functions that - will be called by the emulator. In our simple - example, we only provide <c><![CDATA[start]]></c>, <c><![CDATA[stop]]></c> - and <c><![CDATA[control]]></c>.</p> + will be called by the emulator. In this example, + only <c><![CDATA[start]]></c>, <c><![CDATA[stop]]></c>, + and <c><![CDATA[control]]></c> are provided:</p> + <code type="none"><![CDATA[ /* Driver interface declarations */ static ErlDrvData start(ErlDrvPort port, char *command); @@ -127,15 +140,15 @@ static int control(ErlDrvData drv_data, unsigned int command, char *buf, static ErlDrvEntry pq_driver_entry = { NULL, /* init */ - start, - stop, + start, + stop, NULL, /* output */ NULL, /* ready_input */ - NULL, /* ready_output */ + NULL, /* ready_output */ "pg_sync", /* the name of the driver */ NULL, /* finish */ NULL, /* handle */ - control, + control, NULL, /* timeout */ NULL, /* outputv */ NULL, /* ready_async */ @@ -144,14 +157,18 @@ static ErlDrvEntry pq_driver_entry = { NULL /* event */ }; ]]></code> + <p>We have a structure to store state needed by the driver, - in this case we only need to keep the database connection.</p> + in this case we only need to keep the database connection:</p> + <code type="none"><![CDATA[ typedef struct our_data_s { PGconn* conn; } our_data_t; ]]></code> - <p>These are control codes we have defined.</p> + + <p>The control codes that we have defined are as follows:</p> + <code type="none"><![CDATA[ /* Keep the following definitions in alignment with the * defines in erl_pq_sync.erl @@ -161,10 +178,12 @@ typedef struct our_data_s { #define DRV_DISCONNECT 'D' #define DRV_SELECT 'S' ]]></code> - <p>This just returns the driver structure. The macro + + <p>This returns the driver structure. The macro <c><![CDATA[DRIVER_INIT]]></c> defines the only exported function. All the other functions are static, and will not be exported from the library.</p> + <code type="none"><![CDATA[ /* INITIALIZATION AFTER LOADING */ @@ -179,9 +198,11 @@ DRIVER_INIT(pq_drv) return &pq_driver_entry; } ]]></code> - <p>Here we do some initialization, <c><![CDATA[start]]></c> is called from - <c><![CDATA[open_port]]></c>. The data will be passed to <c><![CDATA[control]]></c> - and <c><![CDATA[stop]]></c>.</p> + + <p>Here some initialization is done, <c><![CDATA[start]]></c> is called from + <c><![CDATA[open_port]]></c>. The data will be passed to + <c><![CDATA[control]]></c> and <c><![CDATA[stop]]></c>.</p> + <code type="none"><![CDATA[ /* DRIVER INTERFACE */ static ErlDrvData start(ErlDrvPort port, char *command) @@ -194,8 +215,10 @@ static ErlDrvData start(ErlDrvPort port, char *command) return (ErlDrvData)data; } ]]></code> + <p>We call disconnect to log out from the database. (This should have been done from Erlang, but just in case.)</p> + <code type="none"><![CDATA[ static int do_disconnect(our_data_t* data, ei_x_buff* x); @@ -207,22 +230,27 @@ static void stop(ErlDrvData drv_data) driver_free(data); } ]]></code> + <p>We use the binary format only to return data to the emulator; - input data is a string paramater for <c><![CDATA[connect]]></c> and + input data is a string parameter for <c><![CDATA[connect]]></c> and <c><![CDATA[select]]></c>. The returned data consists of Erlang terms.</p> - <p>The functions <c><![CDATA[get_s]]></c> and <c><![CDATA[ei_x_to_new_binary]]></c> are - utilities that are used to make the code shorter. <c><![CDATA[get_s]]></c> - duplicates the string and zero-terminates it, since the + + <p>The functions <c><![CDATA[get_s]]></c> and + <c><![CDATA[ei_x_to_new_binary]]></c> are utilities that are used to + make the code shorter. <c><![CDATA[get_s]]></c> + duplicates the string and zero-terminates it, as the postgres client library wants that. <c><![CDATA[ei_x_to_new_binary]]></c> - takes an <c><![CDATA[ei_x_buff]]></c> buffer and allocates a binary and - copies the data there. This binary is returned in <c><![CDATA[*rbuf]]></c>. - (Note that this binary is freed by the emulator, not by us.)</p> + takes an <c><![CDATA[ei_x_buff]]></c> buffer, allocates a binary, and + copies the data there. This binary is returned in + <c><![CDATA[*rbuf]]></c>. + (Notice that this binary is freed by the emulator, not by us.)</p> + <code type="none"><![CDATA[ static char* get_s(const char* buf, int len); static int do_connect(const char *s, our_data_t* data, ei_x_buff* x); static int do_select(const char* s, our_data_t* data, ei_x_buff* x); -/* Since we are operating in binary mode, the return value from control +/* As we are operating in binary mode, the return value from control * is irrelevant, as long as it is not negative. */ static int control(ErlDrvData drv_data, unsigned int command, char *buf, @@ -245,10 +273,12 @@ static int control(ErlDrvData drv_data, unsigned int command, char *buf, return r; } ]]></code> - <p><c><![CDATA[do_connect]]></c> is where we log in to the database. If the connection - was successful we store the connection handle in our driver - data, and return ok. Otherwise, we return the error message - from postgres, and store <c><![CDATA[NULL]]></c> in the driver data.</p> + + <p><c><![CDATA[do_connect]]></c> is where we log in to the database. If the + connection was successful, we store the connection handle in the driver + data, and return <c>'ok'</c>. Otherwise, we return the error message + from postgres and store <c><![CDATA[NULL]]></c> in the driver data.</p> + <code type="none"><![CDATA[ static int do_connect(const char *s, our_data_t* data, ei_x_buff* x) { @@ -264,10 +294,13 @@ static int do_connect(const char *s, our_data_t* data, ei_x_buff* x) return 0; } ]]></code> - <p>If we are connected (if the connection handle is not <c><![CDATA[NULL]]></c>), + + <p>If we are connected (and if the connection handle is not + <c><![CDATA[NULL]]></c>), we log out from the database. We need to check if we should - encode an ok, since we might get here from the <c><![CDATA[stop]]></c> - function, which doesn't return data to the emulator.</p> + encode an <c>'ok'</c>, as we can get here from function + <c><![CDATA[stop]]></c>, which does not return data to the emulator:</p> + <code type="none"><![CDATA[ static int do_disconnect(our_data_t* data, ei_x_buff* x) { @@ -280,9 +313,11 @@ static int do_disconnect(our_data_t* data, ei_x_buff* x) return 0; } ]]></code> - <p>We execute a query and encode the result. Encoding is done - in another C module, <c><![CDATA[pg_encode.c]]></c> which is also provided + + <p>We execute a query and encode the result. Encoding is done in + another C module, <c><![CDATA[pg_encode.c]]></c>, which is also provided as sample code.</p> + <code type="none"><![CDATA[ static int do_select(const char* s, our_data_t* data, ei_x_buff* x) { @@ -292,12 +327,14 @@ static int do_select(const char* s, our_data_t* data, ei_x_buff* x) return 0; } ]]></code> - <p>Here we simply check the result from postgres, and - if it's data we encode it as lists of lists with + + <p>Here we check the result from postgres. + If it is data, we encode it as lists of lists with column data. Everything from postgres is C strings, - so we just use <c><![CDATA[ei_x_encode_string]]></c> to send + so we use <c><![CDATA[ei_x_encode_string]]></c> to send the result as strings to Erlang. (The head of the list contains the column names.)</p> + <code type="none"><![CDATA[ void encode_result(ei_x_buff* x, PGresult* res, PGconn* conn) { @@ -337,33 +374,36 @@ void encode_result(ei_x_buff* x, PGresult* res, PGconn* conn) </section> <section> - <title>Compiling and linking the sample driver</title> - <p>The driver should be compiled and linked to a shared - library (DLL on windows). With gcc this is done - with the link flags <c><![CDATA[-shared]]></c> and <c><![CDATA[-fpic]]></c>. - Since we use the <c><![CDATA[ei]]></c> library we should include + <title>Compiling and Linking the Sample Driver</title> + <p>The driver is to be compiled and linked to a shared + library (DLL on Windows). With gcc, this is done with + link flags <c><![CDATA[-shared]]></c> and <c><![CDATA[-fpic]]></c>. + As we use the <c><![CDATA[ei]]></c> library, we should include it too. There are several versions of <c><![CDATA[ei]]></c>, compiled for debug or non-debug and multi-threaded or single-threaded. - In the makefile for the samples the <c><![CDATA[obj]]></c> directory + In the makefile for the samples, the <c><![CDATA[obj]]></c> directory is used for the <c><![CDATA[ei]]></c> library, meaning that we use the non-debug, single-threaded version.</p> </section> <section> - <title>Calling a driver as a port in Erlang</title> + <title>Calling a Driver as a Port in Erlang</title> <p>Before a driver can be called from Erlang, it must be loaded and opened. Loading is done using the <c><![CDATA[erl_ddll]]></c> module (the <c><![CDATA[erl_ddll]]></c> driver that loads dynamic - driver, is actually a driver itself). If loading is ok + driver is actually a driver itself). If loading is successfull, the port can be opened with <c><![CDATA[open_port/2]]></c>. The port name must match the name of the shared library and the name in the driver entry structure.</p> + <p>When the port has been opened, the driver can be called. In - the <c><![CDATA[pg_sync]]></c> example, we don't have any data from + the <c><![CDATA[pg_sync]]></c> example, we do not have any data from the port, only the return value from the <c><![CDATA[port_control]]></c>.</p> + <p>The following code is the Erlang part of the synchronous - postgres driver, <c><![CDATA[pg_sync.erl]]></c>.</p> + postgres driver, <c><![CDATA[pg_sync.erl]]></c>:</p> + <code type="none"><![CDATA[ -module(pg_sync). @@ -393,20 +433,35 @@ disconnect(Port) -> select(Port, Query) -> binary_to_term(port_control(Port, ?DRV_SELECT, Query)). ]]></code> - <p>The API is simple: <c><![CDATA[connect/1]]></c> loads the driver, opens it - and logs on to the database, returning the Erlang port - if successful, <c><![CDATA[select/2]]></c> sends a query to the driver, - and returns the result, <c><![CDATA[disconnect/1]]></c> closes the - database connection and the driver. (It does not unload it, - however.) The connection string should be a connection - string for postgres.</p> - <p>The driver is loaded with <c><![CDATA[erl_ddll:load_driver/2]]></c>, - and if this is successful, or if it's already loaded, + + <p>The API is simple:</p> + + <list type="bulleted"> + <item> + <p><c><![CDATA[connect/1]]></c> loads the driver, opens it, + and logs on to the database, returning the Erlang port + if successful.</p> + </item> + <item> + <p><c><![CDATA[select/2]]></c> sends a query to the driver + and returns the result.</p> + </item> + <item> + <p><c><![CDATA[disconnect/1]]></c> closes the database + connection and the driver. (However, it does not unload it.)</p> + </item> + </list> + + <p>The connection string is to be a connection string for postgres.</p> + + <p>The driver is loaded with <c><![CDATA[erl_ddll:load_driver/2]]></c>. + If this is successful, or if it is already loaded, it is opened. This will call the <c><![CDATA[start]]></c> function in the driver.</p> + <p>We use the <c><![CDATA[port_control/3]]></c> function for all - calls into the driver, the result from the driver is - returned immediately, and converted to terms by calling + calls into the driver. The result from the driver is + returned immediately and converted to terms by calling <c><![CDATA[binary_to_term/1]]></c>. (We trust that the terms returned from the driver are well-formed, otherwise the <c><![CDATA[binary_to_term]]></c> calls could be contained in a @@ -414,16 +469,18 @@ select(Port, Query) -> </section> <section> - <title>Sample asynchronous driver</title> - <p>Sometimes database queries can take long time to + <title>Sample Asynchronous Driver</title> + <p>Sometimes database queries can take a long time to complete, in our <c><![CDATA[pg_sync]]></c> driver, the emulator halts while the driver is doing its job. This is - often not acceptable, since no other Erlang process + often not acceptable, as no other Erlang process gets a chance to do anything. To improve on our - postgres driver, we reimplement it using the asynchronous + postgres driver, we re-implement it using the asynchronous calls in LibPQ.</p> - <p>The asynchronous version of the driver is in the - sample files <c><![CDATA[pg_async.c]]></c> and <c><![CDATA[pg_asyng.erl]]></c>.</p> + + <p>The asynchronous version of the driver is in the sample files + <c><![CDATA[pg_async.c]]></c> and <c><![CDATA[pg_asyng.erl]]></c>.</p> + <code type="none"><![CDATA[ /* Driver interface declarations */ static ErlDrvData start(ErlDrvPort port, char *command); @@ -458,22 +515,26 @@ typedef struct our_data_t { int connecting; } our_data_t; ]]></code> - <p>Here some things have changed from <c><![CDATA[pg_sync.c]]></c>: we use the - entry <c><![CDATA[ready_io]]></c> for <c><![CDATA[ready_input]]></c> and - <c><![CDATA[ready_output]]></c> which will be called from the emulator only - when there is input to be read from the socket. (Actually, the + + <p>Some things have changed from <c><![CDATA[pg_sync.c]]></c>: we use + the entry <c><![CDATA[ready_io]]></c> for <c><![CDATA[ready_input]]></c> + and <c><![CDATA[ready_output]]></c>, which is called from the emulator + only when there is input to be read from the socket. (Actually, the socket is used in a <c><![CDATA[select]]></c> function inside - the emulator, and when the socket is signalled, - indicating there is data to read, the <c><![CDATA[ready_input]]></c> entry - is called. More on this below.)</p> + the emulator, and when the socket is signaled, + indicating there is data to read, the <c><![CDATA[ready_input]]></c> + entry is called. More about this below.)</p> + <p>Our driver data is also extended, we keep track of the socket used for communication with postgres, and also the port, which is needed when we send data to the port with - <c><![CDATA[driver_output]]></c>. We have a flag <c><![CDATA[connecting]]></c> to tell + <c><![CDATA[driver_output]]></c>. We have a flag + <c><![CDATA[connecting]]></c> to tell whether the driver is waiting for a connection or waiting - for the result of a query. (This is needed since the entry - <c><![CDATA[ready_io]]></c> will be called both when connecting and + for the result of a query. (This is needed, as the entry + <c><![CDATA[ready_io]]></c> is called both when connecting and when there is a query result.)</p> + <code type="none"><![CDATA[ static int do_connect(const char *s, our_data_t* data) { @@ -497,16 +558,20 @@ static int do_connect(const char *s, our_data_t* data) return 0; } ]]></code> - <p>The <c><![CDATA[connect]]></c> function looks a bit different too. We connect - using the asynchronous <c><![CDATA[PQconnectStart]]></c> function. After the - connection is started, we retrieve the socket for the connection + + <p>The <c><![CDATA[connect]]></c> function looks a bit different too. We + connect using the asynchronous <c><![CDATA[PQconnectStart]]></c> function. + After the connection is started, we retrieve the socket for the connection with <c><![CDATA[PQsocket]]></c>. This socket is used with the <c><![CDATA[driver_select]]></c> function to wait for connection. When - the socket is ready for input or for output, the <c><![CDATA[ready_io]]></c> - function will be called.</p> - <p>Note that we only return data (with <c><![CDATA[driver_output]]></c>) if there + the socket is ready for input or for output, the + <c><![CDATA[ready_io]]></c> function is called.</p> + + <p>Notice that we only return data (with <c><![CDATA[driver_output]]></c>) + if there is an error here, otherwise we wait for the connection to be completed, - in which case our <c><![CDATA[ready_io]]></c> function will be called.</p> + in which case our <c><![CDATA[ready_io]]></c> function is called.</p> + <code type="none"><![CDATA[ static int do_select(const char* s, our_data_t* data) { @@ -524,9 +589,11 @@ static int do_select(const char* s, our_data_t* data) return 0; } ]]></code> + <p>The <c><![CDATA[do_select]]></c> function initiates a select, and returns - if there is no immediate error. The actual result will be returned + if there is no immediate error. The result is returned when <c><![CDATA[ready_io]]></c> is called.</p> + <code type="none"><![CDATA[ static void ready_io(ErlDrvData drv_data, ErlDrvEvent event) { @@ -565,26 +632,31 @@ static void ready_io(ErlDrvData drv_data, ErlDrvEvent event) ei_x_free(&x); } ]]></code> - <p>The <c><![CDATA[ready_io]]></c> function will be called when the socket + + <p>The <c><![CDATA[ready_io]]></c> function is called when the socket we got from postgres is ready for input or output. Here we first check if we are connecting to the database. In that - case we check connection status and return ok if the - connection is successful, or error if it's not. If the - connection is not yet established, we simply return; <c><![CDATA[ready_io]]></c> - will be called again.</p> + case, we check connection status and return OK if the + connection is successful, or error if it is not. If the + connection is not yet established, we simply return; + <c><![CDATA[ready_io]]></c> is called again.</p> + <p>If we have a result from a connect, indicated by having data in the <c><![CDATA[x]]></c> buffer, we no longer need to select on output (<c><![CDATA[ready_output]]></c>), so we remove this by calling <c><![CDATA[driver_select]]></c>.</p> - <p>If we're not connecting, we're waiting for results from a + + <p>If we are not connecting, we wait for results from a <c><![CDATA[PQsendQuery]]></c>, so we get the result and return it. The encoding is done with the same functions as in the earlier example.</p> - <p>We should add error handling here, for instance checking - that the socket is still open, but this is just a simple - example.</p> + + <p>Error handling is to be added here, for example, checking + that the socket is still open, but this is only a simple example.</p> + <p>The Erlang part of the asynchronous driver consists of the sample file <c><![CDATA[pg_async.erl]]></c>.</p> + <code type="none"><![CDATA[ -module(pg_async). @@ -625,45 +697,50 @@ return_port_data(Port) -> binary_to_term(Data) end. ]]></code> - <p>The Erlang code is slightly different, this is because we - don't return the result synchronously from <c><![CDATA[port_control]]></c>, + + <p>The Erlang code is slightly different, as we do not + return the result synchronously from <c><![CDATA[port_control]]></c>, instead we get it from <c><![CDATA[driver_output]]></c> as data in the message queue. The function <c><![CDATA[return_port_data]]></c> above - receives data from the port. Since the data is in + receives data from the port. As the data is in binary format, we use <c><![CDATA[binary_to_term/1]]></c> to convert - it to an Erlang term. Note that the driver is opened in - binary mode (<c><![CDATA[open_port/2]]></c> is called with the option + it to an Erlang term. Notice that the driver is opened in + binary mode (<c><![CDATA[open_port/2]]></c> is called with option <c><![CDATA[[binary]]]></c>). This means that data sent from the driver - to the emulator is sent as binaries. Without the <c><![CDATA[binary]]></c> - option, they would have been lists of integers.</p> + to the emulator is sent as binaries. Without option + <c><![CDATA[binary]]></c>, they would have been lists of integers.</p> </section> <section> - <title>An asynchronous driver using driver_async</title> - <p>As a final example we demonstrate the use of <c><![CDATA[driver_async]]></c>. + <title>An Asynchronous Driver Using driver_async</title> + <p>As a final example we demonstrate the use of + <c><![CDATA[driver_async]]></c>. We also use the driver term interface. The driver is written - in C++. This enables us to use an algorithm from STL. We will - use the <c><![CDATA[next_permutation]]></c> algorithm to get the next permutation - of a list of integers. For large lists (more than 100000 - elements), this will take some time, so we will perform this + in C++. This enables us to use an algorithm from STL. We use + the <c><![CDATA[next_permutation]]></c> algorithm to get the next + permutation of a list of integers. For large lists (> 100,000 + elements), this takes some time, so we perform this as an asynchronous task.</p> - <p>The asynchronous API for drivers is quite complicated. First - of all, the work must be prepared. In our example we do this - in <c><![CDATA[output]]></c>. We could have used <c><![CDATA[control]]></c> just as well, - but we want some variation in our examples. In our driver, we allocate - a structure that contains anything that's needed for the asynchronous task - to do the work. This is done in the main emulator thread. + + <p>The asynchronous API for drivers is complicated. First, + the work must be prepared. In the example, this is done in + <c><![CDATA[output]]></c>. We could have used <c><![CDATA[control]]></c>, + but we want some variation in the examples. In our driver, we allocate + a structure that contains anything that is needed for the asynchronous + task to do the work. This is done in the main emulator thread. Then the asynchronous function is called from a driver thread, - separate from the main emulator thread. Note that the driver-functions - are not reentrant, so they shouldn't be used. + separate from the main emulator thread. Notice that the driver functions + are not re-entrant, so they are not to be used. Finally, after the function is completed, the driver callback <c><![CDATA[ready_async]]></c> is called from the main emulator thread, - this is where we return the result to Erlang. (We can't - return the result from within the asynchronous function, since - we can't call the driver-functions.)</p> - <p>The code below is from the sample file <c><![CDATA[next_perm.cc]]></c>.</p> - <p>The driver entry looks like before, but also contains the - call-back <c><![CDATA[ready_async]]></c>.</p> + this is where we return the result to Erlang. (We cannot + return the result from within the asynchronous function, as + we cannot call the driver functions.)</p> + + <p>The following code is from the sample file + <c><![CDATA[next_perm.cc]]></c>. The driver entry looks like before, + but also contains the callback <c><![CDATA[ready_async]]></c>.</p> + <code type="none"><![CDATA[ static ErlDrvEntry next_perm_driver_entry = { NULL, /* init */ @@ -684,17 +761,21 @@ static ErlDrvEntry next_perm_driver_entry = { NULL /* event */ }; ]]></code> - <p>The <c><![CDATA[output]]></c> function allocates the work-area of the - asynchronous function. Since we use C++, we use a struct, - and stuff the data in it. We have to copy the original data, + + <p>The <c><![CDATA[output]]></c> function allocates the work area of the + asynchronous function. As we use C++, we use a struct, + and stuff the data in it. We must copy the original data, it is not valid after we have returned from the <c><![CDATA[output]]></c> - function, and the <c><![CDATA[do_perm]]></c> function will be called later, - and from another thread. We return no data here, instead it will - be sent later from the <c><![CDATA[ready_async]]></c> call-back.</p> - <p>The <c><![CDATA[async_data]]></c> will be passed to the <c><![CDATA[do_perm]]></c> function. - We do not use a <c><![CDATA[async_free]]></c> function (the last argument to - <c><![CDATA[driver_async]]></c>), it's only used if the task is cancelled + function, and the <c><![CDATA[do_perm]]></c> function is called + later, and from another thread. We return no data here, instead it + is sent later from the <c><![CDATA[ready_async]]></c> callback.</p> + + <p>The <c><![CDATA[async_data]]></c> is passed to the + <c><![CDATA[do_perm]]></c> function. We do not use a + <c><![CDATA[async_free]]></c> function (the last argument to + <c><![CDATA[driver_async]]></c>), it is only used if the task is cancelled programmatically.</p> + <code type="none"><![CDATA[ struct our_async_data { bool prev; @@ -719,8 +800,10 @@ static void output(ErlDrvData drv_data, char *buf, int len) driver_async(port, NULL, do_perm, async_data, do_free); } ]]></code> - <p>In the <c><![CDATA[do_perm]]></c> we simply do the work, operating + + <p>In the <c><![CDATA[do_perm]]></c> we do the work, operating on the structure that was allocated in <c><![CDATA[output]]></c>.</p> + <code type="none"><![CDATA[ static void do_perm(void* async_data) { @@ -731,13 +814,17 @@ static void do_perm(void* async_data) next_permutation(d->data.begin(), d->data.end()); } ]]></code> - <p>In the <c><![CDATA[ready_async]]></c> function, the output is sent back to the + + <p>In the <c><![CDATA[ready_async]]></c> function the output is sent back + to the emulator. We use the driver term format instead of <c><![CDATA[ei]]></c>. - This is the only way to send Erlang terms directly to a driver, - without having the Erlang code to call <c><![CDATA[binary_to_term/1]]></c>. In - our simple example this works well, and we don't need to use + This is the only way to send Erlang terms directly to a driver, without + having the Erlang code to call <c><![CDATA[binary_to_term/1]]></c>. In + the simple example this works well, and we do not need to use <c><![CDATA[ei]]></c> to handle the binary term format.</p> - <p>When the data is returned we deallocate our data.</p> + + <p>When the data is returned, we deallocate our data.</p> + <code type="none"><![CDATA[ static void ready_async(ErlDrvData drv_data, ErlDrvThreadData async_data) { @@ -758,12 +845,15 @@ static void ready_async(ErlDrvData drv_data, ErlDrvThreadData async_data) delete d; } ]]></code> - <p>This driver is called like the others from Erlang, however, since + + <p>This driver is called like the others from Erlang. However, as we use <c><![CDATA[driver_output_term]]></c>, there is no need to call - binary_to_term. The Erlang code is in the sample file + <c>binary_to_term</c>. The Erlang code is in the sample file <c><![CDATA[next_perm.erl]]></c>.</p> + <p>The input is changed into a list of integers and sent to the driver.</p> + <code type="none"><![CDATA[ -module(next_perm). diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml index b34ca136f3..fd7d6223f6 100644 --- a/erts/doc/src/driver_entry.xml +++ b/erts/doc/src/driver_entry.xml @@ -4,20 +4,21 @@ <cref> <header> <copyright> - <year>2001</year><year>2013</year> + <year>2001</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -32,55 +33,64 @@ <file>driver_entry.xml</file> </header> <lib>driver_entry</lib> - <libsummary>The driver-entry structure used by erlang drivers.</libsummary> + <libsummary>The driver-entry structure used by Erlang drivers.</libsummary> <description> <marker id="WARNING"/> - <warning><p><em>Use this functionality with extreme care!</em></p> + <warning> + <p><em>Use this functionality with extreme care.</em></p> <p>A driver callback is executed as a direct extension of the - native code of the VM. Execution is not made in a safe environment. - The VM can <em>not</em> provide the same services as provided when - executing Erlang code, such as preemptive scheduling or memory - protection. If the driver callback function doesn't behave well, - the whole VM will misbehave.</p> - <list> - <item><p>A driver callback that crash will crash the whole VM.</p></item> - <item><p>An erroneously implemented driver callback might cause - a VM internal state inconsistency which may cause a crash of the VM, - or miscellaneous misbehaviors of the VM at any point after the call - to the driver callback.</p></item> - <item><p>A driver callback that do - <seealso marker="erl_driver#lengthy_work">lengthy work</seealso> - before returning will degrade responsiveness of the VM, - and may cause miscellaneous strange behaviors. Such strange behaviors - include, but are not limited to, extreme memory usage, and bad load - balancing between schedulers. Strange behaviors that might occur due - to lengthy work may also vary between OTP releases.</p></item> + native code of the VM. Execution is not made in a safe environment. + The VM <em>cannot</em> provide the same services as provided when + executing Erlang code, such as pre-emptive scheduling or memory + protection. If the driver callback function does not behave well, + the whole VM will misbehave.</p> + <list type="bulleted"> + <item> + <p>A driver callback that crash will crash the whole VM.</p> + </item> + <item> + <p>An erroneously implemented driver callback can cause a VM + internal state inconsistency, which can cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the + call to the driver callback.</p> + </item> + <item> + <p>A driver callback doing + <seealso marker="erl_driver#lengthy_work">lengthy work</seealso> + before returning degrades responsiveness of the VM, and can cause + miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage, and bad + load balancing between schedulers. Strange behaviors that can + occur because of lengthy work can also vary between Erlang/OTP + releases.</p> + </item> </list> - </warning> - <p> - As of erts version 5.9 (OTP release R15B) the driver interface + </warning> + + <p>As from ERTS 5.9 (Erlang/OTP R15B) the driver interface has been changed with larger types for the callbacks - <seealso marker="#output">output</seealso>, - <seealso marker="#control">control</seealso> and - <seealso marker="#call">call</seealso>. + <seealso marker="#output"><c>output</c></seealso>, + <seealso marker="#control"><c>control</c></seealso>, and + <seealso marker="#call"><c>call</c></seealso>. See driver <seealso marker="erl_driver#version_management"> version management</seealso> in - <seealso marker="erl_driver">erl_driver</seealso>. - </p> + <seealso marker="erl_driver"><c>erl_driver</c></seealso>.</p> + <note> <p>Old drivers (compiled with an <c>erl_driver.h</c> from an - earlier erts version than 5.9) have to be updated and have - to use the extended interface (with - <seealso marker="erl_driver#version_management">version management - </seealso>).</p> + ERTS version earlier than 5.9) must be updated and have + to use the extended interface (with + <seealso marker="erl_driver#version_management">version management + </seealso>).</p> </note> - <p>The <c>driver_entry</c> structure is a C struct that all erlang - drivers define. It contains entry points for the erlang driver - that are called by the erlang emulator when erlang code accesses + + <p>The <c>driver_entry</c> structure is a C struct that all Erlang + drivers define. It contains entry points for the Erlang driver, + which are called by the Erlang emulator when Erlang code accesses the driver.</p> - <p> - <marker id="emulator"></marker> - The <seealso marker="erl_driver">erl_driver</seealso> driver + + <p><marker id="emulator"></marker> + The <seealso marker="erl_driver"><c>erl_driver</c></seealso> driver API functions need a port handle that identifies the driver instance (and the port in the emulator). This is only passed to the <c>start</c> function, but @@ -89,412 +99,463 @@ common practice is to have the <c>start</c> function allocate some application-defined structure and stash the <c>port</c> handle in it, to use it later with the driver API functions.</p> - <p>The driver call-back functions are called synchronously from the - erlang emulator. If they take too long before completing, they - can cause timeouts in the emulator. Use the queue or - asynchronous calls if necessary, since the emulator must be + + <p>The driver callback functions are called synchronously from the + Erlang emulator. If they take too long before completing, they + can cause time-outs in the emulator. Use the queue or + asynchronous calls if necessary, as the emulator must be responsive.</p> - <p>The driver structure contains the name of the driver and some - 15 function pointers. These pointers are called at different + + <p>The driver structure contains the driver name and some + 15 function pointers, which are called at different times by the emulator.</p> + <p>The only exported function from the driver is <c>driver_init</c>. This function returns the <c>driver_entry</c> structure that points to the other functions in the driver. The - <c>driver_init</c> function is declared with a macro - <c>DRIVER_INIT(drivername)</c>. (This is because different OS's - have different names for it.)</p> - <p>When writing a driver in C++, the driver entry should be of - <c>"C"</c> linkage. One way to do this is to put this line - somewhere before the driver entry: - <c>extern "C" DRIVER_INIT(drivername);</c>.</p> + <c>driver_init</c> function is declared with a macro, + <c>DRIVER_INIT(drivername)</c>. (This is because different + operating systems have different names for it.)</p> + + <p>When writing a driver in C++, the driver entry is to be of + <c>"C"</c> linkage. One way to do this is to put the + following line somewhere before the driver entry:</p> + + <pre> +extern "C" DRIVER_INIT(drivername);</pre> + <p>When the driver has passed the <c>driver_entry</c> over to the emulator, the driver is <em>not</em> allowed to modify the <c>driver_entry</c>.</p> - <p>If compiling a driver for static inclusion via --enable-static-drivers you - have to define STATIC_ERLANG_DRIVER before the DRIVER_INIT declaration.</p> + + <p>If compiling a driver for static inclusion through + <c>--enable-static-drivers</c>, you must define + <c>STATIC_ERLANG_DRIVER</c> before the <c>DRIVER_INIT</c> declaration.</p> + <note> - <p>Do <em>not</em> declare the <c>driver_entry</c> <c>const</c>. This since the emulator needs to - modify the <c>handle</c>, and the <c>handle2</c> - fields. A statically allocated, and <c>const</c> - declared <c>driver_entry</c> may be located in - read only memory which will cause the emulator - to crash.</p> + <p>Do <em>not</em> declare the <c>driver_entry</c> <c>const</c>. + This because the emulator must + modify the <c>handle</c> and the <c>handle2</c> + fields. A statically allocated, and <c>const</c>-declared + <c>driver_entry</c> can be located in + read-only memory, which causes the emulator to crash.</p> </note> </description> <section> - <title>DATA TYPES</title> - <taglist> - <tag><b>ErlDrvEntry</b></tag> - <item> - <p/> + <title>Data Types</title> + <p><c>ErlDrvEntry</c></p> <code type="none"> typedef struct erl_drv_entry { - int (*init)(void); /* called at system start up for statically + int (*init)(void); /* Called at system startup for statically linked drivers, and after loading for - dynamically loaded drivers */ - + dynamically loaded drivers */ #ifndef ERL_SYS_DRV ErlDrvData (*start)(ErlDrvPort port, char *command); - /* called when open_port/2 is invoked. - return value -1 means failure. */ + /* Called when open_port/2 is invoked, + return value -1 means failure */ #else ErlDrvData (*start)(ErlDrvPort port, char *command, SysDriverOpts* opts); - /* special options, only for system driver */ + /* Special options, only for system driver */ #endif void (*stop)(ErlDrvData drv_data); - /* called when port is closed, and when the - emulator is halted. */ + /* Called when port is closed, and when the + emulator is halted */ void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); - /* called when we have output from erlang to + /* Called when we have output from Erlang to the port */ void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event); - /* called when we have input from one of + /* Called when we have input from one of the driver's handles */ void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event); - /* called when output is possible to one of + /* Called when output is possible to one of the driver's handles */ - char *driver_name; /* name supplied as command - in open_port XXX ? */ - void (*finish)(void); /* called before unloading the driver - - DYNAMIC DRIVERS ONLY */ - void *handle; /* Reserved -- Used by emulator internally */ + char *driver_name; /* Name supplied as command in + erlang:open_port/2 */ + void (*finish)(void); /* Called before unloading the driver - + dynamic drivers only */ + void *handle; /* Reserved, used by emulator internally */ ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); - /* "ioctl" for drivers - invoked by + /* "ioctl" for drivers - invoked by port_control/3 */ - void (*timeout)(ErlDrvData drv_data); /* Handling of timeout in driver */ + void (*timeout)(ErlDrvData drv_data); + /* Handling of time-out in driver */ void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev); - /* called when we have output from erlang + /* Called when we have output from Erlang to the port */ void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data); void (*flush)(ErlDrvData drv_data); - /* called when the port is about to be - closed, and there is data in the - driver queue that needs to be flushed + /* Called when the port is about to be + closed, and there is data in the + driver queue that must be flushed before 'stop' can be called */ ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags); /* Works mostly like 'control', a synchronous - call into the driver. */ - void (*event)(ErlDrvData drv_data, ErlDrvEvent event, - ErlDrvEventData event_data); - /* Called when an event selected by - driver_event() has occurred */ + call into the driver */ + void* unused_event_callback; int extended_marker; /* ERL_DRV_EXTENDED_MARKER */ int major_version; /* ERL_DRV_EXTENDED_MAJOR_VERSION */ int minor_version; /* ERL_DRV_EXTENDED_MINOR_VERSION */ int driver_flags; /* ERL_DRV_FLAGs */ - void *handle2; /* Reserved -- Used by emulator internally */ + void *handle2; /* Reserved, used by emulator internally */ void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor); /* Called when a process monitor fires */ void (*stop_select)(ErlDrvEvent event, void* reserved); /* Called to close an event object */ - } ErlDrvEntry; - </code> - <p/> + } ErlDrvEntry;</code> <taglist> - <tag><marker id="init"/>int (*init)(void)</tag> - <item> - <p>This is called directly after the driver has been loaded by - <c>erl_ddll:load_driver/2</c>. (Actually when the driver is - added to the driver list.) The driver should return 0, or if - the driver can't initialize, -1.</p> + <tag><marker id="init"/><c>int (*init)(void)</c></tag> + <item> + <p>Called directly after the driver has been loaded by + <seealso marker="kernel:erl_ddll#load_driver/2"> + <c>erl_ddll:load_driver/2</c></seealso> (actually when the driver is + added to the driver list). The driver is to return <c>0</c>, or, if + the driver cannot initialize, <c>-1</c>.</p> </item> - <tag><marker id="start"/>ErlDrvData (*start)(ErlDrvPort port, char* command)</tag> + <tag><marker id="start"/> + <c>ErlDrvData (*start)(ErlDrvPort port, char* command)</c></tag> <item> - <p>This is called when the driver is instantiated, when - <c>open_port/2</c> is called. The driver should return a - number >= 0 or a pointer, or if the driver can't be started, - one of three error codes should be returned:</p> - <p>ERL_DRV_ERROR_GENERAL - general error, no error code</p> - <p>ERL_DRV_ERROR_ERRNO - error with error code in erl_errno</p> - <p>ERL_DRV_ERROR_BADARG - error, badarg</p> - <p>If an error code is returned, the port isn't started.</p> + <p>Called when the driver is instantiated, when + <seealso marker="erlang#open_port/2"> + <c>erlang:open_port/2</c></seealso> is called. + The driver is to return a number >= 0 or a pointer, or, if the + driver cannot be started, one of three error codes:</p> + <taglist> + <tag><c>ERL_DRV_ERROR_GENERAL</c></tag> + <item>General error, no error code</item> + <tag><c>ERL_DRV_ERROR_ERRNO</c></tag> + <item>Error with error code in <c>errno</c></item> + <tag><c>ERL_DRV_ERROR_BADARG</c></tag> + <item>Error, <c>badarg</c></item> + </taglist> + <p>If an error code is returned, the port is not started.</p> </item> - <tag><marker id="stop"/>void (*stop)(ErlDrvData drv_data)</tag> + <tag><marker id="stop"/><c>void (*stop)(ErlDrvData drv_data)</c></tag> <item> - <p>This is called when the port is closed, with - <c>port_close/1</c> or <c>Port ! {self(), close}</c>. Note - that terminating the port owner process also closes the + <p>Called when the port is closed, with + <seealso marker="erlang#port_close/1"> + <c>erlang:port_close/1</c></seealso> or <c>Port ! {self(), close}</c>. + Notice that terminating the port owner process also closes the port. If <c>drv_data</c> is a pointer to memory allocated in - <c>start</c>, then <c>stop</c> is the place to deallocate that - memory.</p> + <c>start</c>, then <c>stop</c> is the place to deallocate that + memory.</p> </item> - <tag><marker id="output"/>void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)</tag> + <tag><marker id="output"/> + <c>void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len)</c> + </tag> <item> - <p>This is called when an erlang process has sent data to the - port. The data is pointed to by <c>buf</c>, and is - <c>len</c> bytes. Data is sent to the port with <c>Port ! {self(), {command, Data}}</c>, or with - <c>port_command/2</c>. Depending on how the port was opened, - it should be either a list of integers 0...255 or a - binary. See <c>open_port/3</c> and <c>port_command/2</c>.</p> + <p>Called when an Erlang process has sent data to the port. The data is + pointed to by <c>buf</c>, and is <c>len</c> bytes. Data is sent to + the port with <c>Port ! {self(), {command, Data}}</c> or with + <c>erlang:port_command/2</c>. Depending on how the port was + opened, it is to be either a list of integers <c>0...255</c> or a + binary. See <seealso marker="erlang#open_port/2"> + <c>erlang:open_port/2</c></seealso> and + <seealso marker="erlang#port_command/2"> + <c>erlang:port_command/2</c></seealso>.</p> </item> - - <tag><marker id="ready_input"/>void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event)</tag> - <tag><marker id="ready_output"/>void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event)</tag> + <tag><marker id="ready_input"/> + <c>void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event)</c> + </tag> + <item></item> + <tag><marker id="ready_output"/> + <c>void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event)</c> + </tag> <item> - <p>This is called when a driver event (given in the - <c>event</c> parameter) is signaled. This is used to help - asynchronous drivers "wake up" when something happens.</p> - <p>On unix the <c>event</c> is a pipe or socket handle (or + <p>Called when a driver event (specified in parameter + <c>event</c>) is signaled. This is used to help + asynchronous drivers "wake up" when something occurs.</p> + <p>On Unix the <c>event</c> is a pipe or socket handle (or something that the <c>select</c> system call understands).</p> - <p>On Windows the <c>event</c> is an Event or Semaphore (or - something that the <c>WaitForMultipleObjects</c> API + <p>On Windows the <c>event</c> is an <c>Event</c> or <c>Semaphore</c> + (or something that the <c>WaitForMultipleObjects</c> API function understands). (Some trickery in the emulator allows more than the built-in limit of 64 <c>Events</c> to be used.)</p> - <p>On Enea OSE the <c>event</c> is one or more signals that can - be retrieved using <seealso marker="ose:ose_erl_driver#erl_drv_ose_get_signal">erl_drv_ose_get_signal</seealso>.</p> <p>To use this with threads and asynchronous routines, create a - pipe on unix, an Event on Windows or a unique signal number on - Enea OSE. When the routine + pipe on Unix and an <c>Event</c> on Windows. When the routine completes, write to the pipe (use <c>SetEvent</c> on - Windows or send a message to the emulator process on Enea OSE), - this will make the emulator call + Windows), this makes the emulator call <c>ready_input</c> or <c>ready_output</c>.</p> - <p>Spurious events may happen. That is, calls to <c>ready_input</c> - or <c>ready_output</c> even though no real events are signaled. In - reality it should be rare (and OS dependant), but a robust driver + <p>False events can occur. That is, calls to <c>ready_input</c> + or <c>ready_output</c> although no real events are signaled. In + reality, it is rare (and OS-dependant), but a robust driver must nevertheless be able to handle such cases.</p> </item> - <tag><marker id="driver_name"/>char *driver_name</tag> + <tag><marker id="driver_name"/><c>char *driver_name</c></tag> <item> - <p>This is the name of the driver, it must correspond to the - atom used in <c>open_port</c>, and the name of the driver + <p>The driver name. It must correspond to the atom used in + <seealso marker="erlang#open_port/2"> + <c>erlang:open_port/2</c></seealso>, and the name of the driver library file (without the extension).</p> </item> - <tag><marker id="finish"/>void (*finish)(void)</tag> + <tag><marker id="finish"/><c>void (*finish)(void)</c></tag> <item> - <p>This function is called by the <c>erl_ddll</c> driver when the + <p>Called by the <c>erl_ddll</c> driver when the driver is unloaded. (It is only called in dynamic drivers.)</p> <p>The driver is only unloaded as a result of calling - <c>unload_driver/1</c>, or when the emulator halts.</p> + <seealso marker="kernel:erl_ddll#unload_driver/1"> + <c>erl_ddll:unload_driver/1</c></seealso>, + or when the emulator halts.</p> </item> - <tag>void *handle</tag> + <tag><c>void *handle</c></tag> <item> <p>This field is reserved for the emulator's internal use. The - emulator will modify this field; therefore, it is important - that the <c>driver_entry</c> isn't declared <c>const</c>.</p> + emulator will modify this field, so it is important + that the <c>driver_entry</c> is not declared <c>const</c>.</p> </item> - <tag><marker id="control"></marker>ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)</tag> + <tag><marker id="control"></marker> + <c>ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen)</c></tag> <item> - <p>This is a special routine invoked with the erlang function - <c>port_control/3</c>. It works a little like an "ioctl" for - erlang drivers. The data given to <c>port_control/3</c> - arrives in <c>buf</c> and <c>len</c>. The driver may send + <p>A special routine invoked with + <seealso marker="erlang#port_control/3"> + <c>erlang:port_control/3</c></seealso>. + It works a little like an "ioctl" for + Erlang drivers. The data specified to <c>port_control/3</c> + arrives in <c>buf</c> and <c>len</c>. The driver can send data back, using <c>*rbuf</c> and <c>rlen</c>.</p> <p>This is the fastest way of calling a driver and get a - response. It won't make any context switch in the erlang - emulator, and requires no message passing. It is suitable - for calling C function to get faster execution, when erlang + response. It makes no context switch in the Erlang + emulator and requires no message passing. It is suitable + for calling C function to get faster execution, when Erlang is too slow.</p> - <p>If the driver wants to return data, it should return it in + <p>If the driver wants to return data, it is to return it in <c>rbuf</c>. When <c>control</c> is called, <c>*rbuf</c> points to a default buffer of <c>rlen</c> bytes, which - can be used to return data. Data is returned different depending on + can be used to return data. Data is returned differently depending on the port control flags (those that are set with - <seealso marker="erl_driver#set_port_control_flags">set_port_control_flags</seealso>). - </p> + <seealso marker="erl_driver#set_port_control_flags"> + <c>erl_driver:set_port_control_flags</c></seealso>).</p> <p>If the flag is set to <c>PORT_CONTROL_FLAG_BINARY</c>, - a binary will be returned. Small binaries can be returned by writing - the raw data into the default buffer. A binary can also be - returned by setting <c>*rbuf</c> to point to a binary allocated with - <seealso marker="erl_driver#driver_alloc_binary">driver_alloc_binary</seealso>. - This binary will be freed automatically after <c>control</c> has returned. + a binary is returned. Small binaries can be returned by writing + the raw data into the default buffer. A binary can also be + returned by setting <c>*rbuf</c> to point to a binary allocated with + <seealso marker="erl_driver#driver_alloc_binary"> + <c>erl_driver:driver_alloc_binary</c></seealso>. + This binary is freed automatically after <c>control</c> has returned. The driver can retain the binary for <em>read only</em> access with - <seealso marker="erl_driver#driver_binary_inc_refc">driver_binary_inc_refc</seealso> to be freed later with - <seealso marker="erl_driver#driver_free_binary">driver_free_binary</seealso>. - It is never allowed to alter the binary after <c>control</c> has returned. - If <c>*rbuf</c> is set to NULL, an empty list will be returned. - </p> + <seealso marker="erl_driver#driver_binary_inc_refc"> + <c>erl_driver:driver_binary_inc_refc</c></seealso> to be freed later + with <seealso marker="erl_driver#driver_free_binary"> + <c>erl_driver:driver_free_binary</c></seealso>. + It is never allowed to change the binary after <c>control</c> has + returned. If <c>*rbuf</c> is set to <c>NULL</c>, an empty list is + returned.</p> <p>If the flag is set to <c>0</c>, data is returned as a list of integers. Either use the default buffer or set <c>*rbuf</c> to point to a larger buffer allocated with - <seealso marker="erl_driver#driver_alloc">driver_alloc</seealso>. - The buffer will be freed automatically after <c>control</c> has returned.</p> + <seealso marker="erl_driver#driver_alloc"> + <c>erl_driver:driver_alloc</c></seealso>. The + buffer is freed automatically after <c>control</c> has returned.</p> <p>Using binaries is faster if more than a few bytes are returned.</p> - <p>The return value is the number of bytes returned in - <c>*rbuf</c>.</p> + <p>The return value is the number of bytes returned in <c>*rbuf</c>.</p> </item> - - <tag><marker id="timeout"/>void (*timeout)(ErlDrvData drv_data)</tag> + <tag><marker id="timeout"/><c>void (*timeout)(ErlDrvData drv_data)</c> + </tag> <item> - <p>This function is called any time after the driver's timer - reaches 0. The timer is activated with - <c>driver_set_timer</c>. There are no priorities or ordering - among drivers, so if several drivers time out at the same - time, any one of them is called first.</p> + <p>Called any time after the driver's timer reaches <c>0</c>. + The timer is activated with + <seealso marker="erl_driver#driver_set_timer"> + <c>erl_driver:driver_set_timer</c></seealso>. No priorities or + ordering exist among drivers, so if several drivers time out at + the same time, anyone of them is called first.</p> </item> - - <tag><marker id="outputv"/>void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev)</tag> + <tag><marker id="outputv"/> + <c>void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev)</c></tag> <item> - <p>This function is called whenever the port is written to. If + <p>Called whenever the port is written to. If it is <c>NULL</c>, the <c>output</c> function is called - instead. This function is faster than <c>output</c>, because + instead. This function is faster than <c>output</c>, as it takes an <c>ErlIOVec</c> directly, which requires no - copying of the data. The port should be in binary mode, see - <c>open_port/2</c>.</p> - <p>The <c>ErlIOVec</c> contains both a <c>SysIOVec</c>, + copying of the data. The port is to be in binary mode, see + <seealso marker="erlang#open_port/2"> + <c>erlang:open_port/2</c></seealso>.</p> + <p><c>ErlIOVec</c> contains both a <c>SysIOVec</c>, suitable for <c>writev</c>, and one or more binaries. If - these binaries should be retained, when the driver returns - from <c>outputv</c>, they can be queued (using <seealso marker="erl_driver#driver_enq_bin">driver_enq_bin</seealso> - for instance), or if they are kept in a static or global + these binaries are to be retained when the driver returns + from <c>outputv</c>, they can be queued (using, for example, + <seealso marker="erl_driver#driver_enq_bin"> + <c>erl_driver:driver_enq_bin</c></seealso>) + or, if they are kept in a static or global variable, the reference counter can be incremented.</p> </item> - <tag><marker id="ready_async"/>void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data)</tag> + <tag><marker id="ready_async"/> + <c>void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData + thread_data)</c></tag> <item> - <p>This function is called after an asynchronous call has - completed. The asynchronous call is started with <seealso marker="erl_driver#driver_async">driver_async</seealso>. - This function is called from the erlang emulator thread, as + <p>Called after an asynchronous call has completed. + The asynchronous call is started with + <seealso marker="erl_driver#driver_async"> + <c>erl_driver:driver_async</c></seealso>. + This function is called from the Erlang emulator thread, as opposed to the asynchronous function, which is called in - some thread (if multithreading is enabled).</p> + some thread (if multi-threading is enabled).</p> </item> - <tag><marker id="call"/>ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags)</tag> + <tag><c>void (*flush)(ErlDrvData drv_data)</c></tag> <item> - <p>This function is called from <c>erlang:port_call/3</c>. It - works a lot like the <c>control</c> call-back, but uses the + <p>Called when the port is about to be closed, + and there is data in the driver queue that must be flushed + before 'stop' can be called.</p> + </item> + <tag><marker id="call"/><c>ErlDrvSSizeT (*call)(ErlDrvData drv_data, + unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, + ErlDrvSizeT rlen, unsigned int *flags)</c></tag> + <item> + <p>Called from <seealso marker="erlang#port_call/3"> + <c>erlang:port_call/3</c></seealso>. + It works a lot like the <c>control</c> callback, but uses the external term format for input and output.</p> <p><c>command</c> is an integer, obtained from the call from - erlang (the second argument to <c>erlang:port_call/3</c>).</p> + Erlang (the second argument to <c>erlang:port_call/3</c>).</p> <p><c>buf</c> and <c>len</c> provide the arguments to the call (the third argument to <c>erlang:port_call/3</c>). They can be decoded using <c>ei</c> functions.</p> <p><c>rbuf</c> points to a return buffer, <c>rlen</c> bytes - long. The return data should be a valid erlang term in the - external (binary) format. This is converted to an erlang + long. The return data is to be a valid Erlang term in the + external (binary) format. This is converted to an Erlang term and returned by <c>erlang:port_call/3</c> to the - caller. If more space than <c>rlen</c> bytes is needed to + caller. If more space than <c>rlen</c> bytes is needed to return data, <c>*rbuf</c> can be set to memory allocated with - <c>driver_alloc</c>. This memory will be freed automatically - after <c>call</c> has returned.</p> + <seealso marker="erl_driver#driver_alloc"> + <c>erl_driver:driver_alloc</c></seealso>. + This memory is freed automatically after <c>call</c> has returned.</p> <p>The return value is the number of bytes returned in <c>*rbuf</c>. If <c>ERL_DRV_ERROR_GENERAL</c> is returned - (or in fact, anything < 0), <c>erlang:port_call/3</c> will - throw a <c>BAD_ARG</c>.</p> + (or in fact, anything < 0), <c>erlang:port_call/3</c> + throws a <c>BAD_ARG</c>.</p> </item> - <tag>void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data)</tag> + <tag><c>void (*event)(ErlDrvData drv_data, ErlDrvEvent event, + ErlDrvEventData event_data)</c></tag> <item> <p>Intentionally left undocumented.</p> </item> - <tag><marker id="extended_marker"/>int extended_marker</tag> + <tag><marker id="extended_marker"/><c>int extended_marker</c></tag> <item> - <p> - This field should either be equal to <c>ERL_DRV_EXTENDED_MARKER</c> + <p>This field is either to be equal to <c>ERL_DRV_EXTENDED_MARKER</c> or <c>0</c>. An old driver (not aware of the extended driver - interface) should set this field to <c>0</c>. If this field is - equal to <c>0</c>, all the fields following this field also - <em>have</em> to be <c>0</c>, or <c>NULL</c> in case it is a - pointer field. - </p> + interface) is to set this field to <c>0</c>. If this field is + <c>0</c>, all the following fields <em>must</em> also be <c>0</c>, + or <c>NULL</c> if it is a pointer field.</p> </item> - <tag>int major_version</tag> + <tag><c>int major_version</c></tag> <item> - <p>This field should equal <c>ERL_DRV_EXTENDED_MAJOR_VERSION</c> if - the <c>extended_marker</c> field equals + <p>This field is to equal <c>ERL_DRV_EXTENDED_MAJOR_VERSION</c> if + field <c>extended_marker</c> equals <c>ERL_DRV_EXTENDED_MARKER</c>.</p> </item> - <tag>int minor_version</tag> + <tag><c>int minor_version</c></tag> <item> - <p> - This field should equal <c>ERL_DRV_EXTENDED_MINOR_VERSION</c> if - the <c>extended_marker</c> field equals - <c>ERL_DRV_EXTENDED_MARKER</c>. - </p> + <p>This field is to equal <c>ERL_DRV_EXTENDED_MINOR_VERSION</c> if + field <c>extended_marker</c> equals + <c>ERL_DRV_EXTENDED_MARKER</c>.</p> </item> - - <tag><marker id="driver_flags"/>int driver_flags</tag> + <tag><marker id="driver_flags"/><c>int driver_flags</c></tag> <item> <p>This field is used to pass driver capability and other - information to the runtime system. If the - <c>extended_marker</c> field equals <c>ERL_DRV_EXTENDED_MARKER</c>, - it should contain <c>0</c> or driver flags (<c>ERL_DRV_FLAG_*</c>) - ored bitwise. Currently the following driver flags exist: - </p> + information to the runtime system. If + field <c>extended_marker</c> equals <c>ERL_DRV_EXTENDED_MARKER</c>, + it is to contain <c>0</c> or driver flags (<c>ERL_DRV_FLAG_*</c>) + OR'ed bitwise. The following driver flags exist:</p> <taglist> <tag><c>ERL_DRV_FLAG_USE_PORT_LOCKING</c></tag> <item> - The runtime system will use port level locking on - all ports executing this driver instead of driver - level locking when the driver is run in a runtime - system with SMP support. For more information see the - <seealso marker="erl_driver#smp_support">erl_driver</seealso> - documentation. - </item> + <p>The runtime system uses port-level locking on + all ports executing this driver instead of driver-level + locking when the driver is run in a runtime + system with SMP support. For more information, see + <seealso marker="erl_driver#smp_support"> + <c>erl_driver</c></seealso>.</p> + </item> <tag><c>ERL_DRV_FLAG_SOFT_BUSY</c></tag> <item> - Marks that driver instances can handle being called - in the <seealso marker="#output">output</seealso> and/or - <seealso marker="#outputv">outputv</seealso> callbacks even - though a driver instance has marked itself as busy (see - <seealso marker="erl_driver#set_busy_port">set_busy_port()</seealso>). - Since erts version 5.7.4 this flag is required for drivers used - by the Erlang distribution (the behaviour has always been - required by drivers used by the distribution). + <p>Marks that driver instances can handle being called + in the <seealso marker="#output"><c>output</c></seealso> and/or + <seealso marker="#outputv"><c>outputv</c></seealso> callbacks + although a driver instance has marked itself as busy (see + <seealso marker="erl_driver#set_busy_port"> + <c>erl_driver:set_busy_port</c></seealso>). + As from ERTS 5.7.4 this flag is required for drivers used + by the Erlang distribution (the behavior has always been + required by drivers used by the distribution).</p> </item> <tag><c>ERL_DRV_FLAG_NO_BUSY_MSGQ</c></tag> - <item>Disable busy port message queue functionality. For - more information, see the documentation of the - <seealso marker="erl_driver#erl_drv_busy_msgq_limits">erl_drv_busy_msgq_limits()</seealso> - function. + <item> + <p>Disables busy port message queue functionality. For + more information, see + <seealso marker="erl_driver#erl_drv_busy_msgq_limits"> + <c>erl_driver:erl_drv_busy_msgq_limits</c></seealso>.</p> + </item> + <tag><c>ERL_DRV_FLAG_USE_INIT_ACK</c></tag> + <item> + <p>When this flag is specified, the linked-in driver must manually + acknowledge that the port has been successfully started using + <seealso marker="erl_driver#erl_drv_init_ack"> + <c>erl_driver:erl_drv_init_ack()</c></seealso>. + This allows the implementor to make the + <c>erlang:open_port</c> exit with <c>badarg</c> after some + initial asynchronous initialization has been done.</p> </item> - </taglist> + </taglist> </item> - <tag>void *handle2</tag> + <tag><c>void *handle2</c></tag> <item> - <p> - This field is reserved for the emulator's internal use. The - emulator will modify this field; therefore, it is important - that the <c>driver_entry</c> isn't declared <c>const</c>. - </p> + <p>This field is reserved for the emulator's internal use. The + emulator modifies this field, so it is important + that the <c>driver_entry</c> is not declared <c>const</c>.</p> </item> - <tag><marker id="process_exit"/>void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor)</tag> + <tag><marker id="process_exit"/> + <c>void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor)</c> + </tag> <item> - <p>This callback is called when a monitored process exits. The + <p>Called when a monitored process exits. The <c>drv_data</c> is the data associated with the port for which - the process is monitored (using <seealso marker="erl_driver#driver_monitor_process">driver_monitor_process</seealso>) - and the <c>monitor</c> corresponds to the <c>ErlDrvMonitor</c> + the process is monitored (using + <seealso marker="erl_driver#driver_monitor_process"> + <c>erl_driver:driver_monitor_process</c></seealso>) + and the <c>monitor</c> corresponds to the <c>ErlDrvMonitor</c> structure filled in when creating the monitor. The driver interface function - <seealso marker="erl_driver#driver_get_monitored_process">driver_get_monitored_process</seealso> - can be used to retrieve the process id of the exiting process as + <seealso marker="erl_driver#driver_get_monitored_process"> + <c>erl_driver:driver_get_monitored_process</c></seealso> + can be used to retrieve the process ID of the exiting process as an <c>ErlDrvTermData</c>.</p> </item> - <tag><marker id="stop_select"/>void (*stop_select)(ErlDrvEvent event, void* reserved)</tag> + <tag><marker id="stop_select"/> + <c>void (*stop_select)(ErlDrvEvent event, void* reserved)</c></tag> <item> - <p>This function is called on behalf of - <seealso marker="erl_driver#driver_select">driver_select</seealso> - when it is safe to close an event object.</p> + <p>Called on behalf of + <seealso marker="erl_driver#driver_select"> + <c>erl_driver:driver_select</c></seealso> + when it is safe to close an event object.</p> <p>A typical implementation on Unix is to do - <c>close((int)event)</c>.</p> - <p>Argument <c>reserved</c> is intended for future use and should be ignored.</p> - <p>In contrast to most of the other call-back functions, - <c>stop_select</c> is called independent of any port. No - <c>ErlDrvData</c> argument is passed to the function. No - driver lock or port lock is guaranteed to be held. The port that - called <c>driver_select</c> might even be closed at the - time <c>stop_select</c> is called. But it could also be - the case that <c>stop_select</c> is called directly by - <c>driver_select</c>.</p> + <c>close((int)event)</c>.</p> + <p>Argument <c>reserved</c> is intended for future use and is to be + ignored.</p> + <p>In contrast to most of the other callback functions, + <c>stop_select</c> is called independent of any port. No + <c>ErlDrvData</c> argument is passed to the function. No + driver lock or port lock is guaranteed to be held. The port that + called <c>driver_select</c> can even be closed at the + time <c>stop_select</c> is called. But it can also be + the case that <c>stop_select</c> is called directly by + <c>erl_driver:driver_select</c>.</p> <p>It is not allowed to call any functions in the - <seealso marker="erl_driver">driver API</seealso> from - <c>stop_select</c>. This strict limitation is due to the - volatile context that <c>stop_select</c> may be called.</p> + <seealso marker="erl_driver">driver API</seealso> from + <c>stop_select</c>. This strict limitation is because the + volatile context that <c>stop_select</c> can be called.</p> </item> - - </taglist> - </item> - </taglist> </section> <section> - <title>SEE ALSO</title> - <p><seealso marker="erl_driver">erl_driver(3)</seealso>, - <seealso marker="kernel:erl_ddll">erl_ddll(3)</seealso>, - <seealso marker="erlang">erlang(3)</seealso>, - kernel(3)</p> + <title>See Also</title> + <p><seealso marker="erl_driver"><c>erl_driver(3)</c></seealso>, + <seealso marker="erlang"><c>erlang(3)</c></seealso>, + <seealso marker="kernel:erl_ddll"><c>erl_ddll(3)</c></seealso></p> </section> </cref> diff --git a/erts/doc/src/epmd.xml b/erts/doc/src/epmd.xml index 25f819ab50..311483022d 100644 --- a/erts/doc/src/epmd.xml +++ b/erts/doc/src/epmd.xml @@ -4,20 +4,21 @@ <comref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -27,242 +28,259 @@ <docno>1</docno> <approved></approved> <checked></checked> - <date>98-01-05</date> + <date>1998-01-05</date> <rev>A</rev> <file>epmd.xml</file> </header> <com>epmd</com> - <comsummary> - <p>Erlang Port Mapper Daemon</p> - <taglist> - <tag><c><![CDATA[epmd [-d|-debug] [DbgExtra...] [-port No] [-daemon] [-relaxed_command_check]]]></c></tag> - <item> - <p>Starts the port mapper daemon</p> - </item> - <tag><c><![CDATA[epmd [-d|-debug] [-port No] [-names|-kill|-stop Name]]]></c></tag> - <item> - <p>Communicates with a running port mapper daemon</p> - </item> - </taglist> - </comsummary> + <comsummary>Erlang Port Mapper Daemon</comsummary> + <description> - <p>This daemon acts as a name server on all hosts involved in - distributed Erlang computations. When an Erlang node - starts, the node has a name and it obtains an address from the host - OS kernel. - The name and the address are sent to the + <taglist> + <tag><c><![CDATA[epmd [-d|-debug] [DbgExtra...] [-address Addresses] + [-port No] [-daemon] [-relaxed_command_check]]]></c></tag> + <item> + <p>Starts the port mapper daemon.</p> + </item> + <tag><c><![CDATA[epmd [-d|-debug] [-port No] + [-names|-kill|-stop Name]]]></c></tag> + <item> + <p>Communicates with a running port mapper daemon.</p> + </item> + </taglist> + + <p>This daemon acts as a name server on all hosts involved in + distributed Erlang computations. When an Erlang node starts, + the node has a name and it obtains an address from the host + OS kernel. The name and address are sent to the <c><![CDATA[epmd]]></c> daemon running on the local host. In a TCP/IP environment, the address consists - of the IP address and a port number. The name of the node is + of the IP address and a port number. The node name is an atom on the form of <c><![CDATA[Name@Node]]></c>. The job of the <c><![CDATA[epmd]]></c> daemon is to keep track of which node name listens on which address. Hence, <c><![CDATA[epmd]]></c> maps symbolic node names to machine addresses.</p> - <p>The TCP/IP <c>epmd</c> daemon actually only keeps track of + <p>The TCP/IP <c>epmd</c> daemon only keeps track of the <c>Name</c> (first) part of an Erlang node name. The <c>Host</c> part (whatever is after the <c><![CDATA[@]]></c>) is implicit in the - node name where the <c>epmd</c> daemon was actually contacted, + node name where the <c>epmd</c> daemon was contacted, as is the IP address where the Erlang node can be reached. Consistent and correct TCP naming services are therefore required for an Erlang network to function correctly.</p> <taglist> - <tag>Starting the port mapper daemon</tag> - <item> - - <p>The daemon is started automatically by the <c>erl</c> - command if the node is to be distributed and there is no - running instance present. If automatically launched, - environment variables have to be used to alter the behavior of - the daemon. See the <seealso - marker="#environment_variables">Environment - variables</seealso> section below.</p> - - <p>If the -daemon argument is not given, - <c><![CDATA[epmd]]></c> runs as a normal program with the - controlling terminal of the shell in which it is - started. Normally, it should run as a daemon.</p> - - <p>Regular start-up options are described in the - <seealso marker="#daemon_flags">Regular options</seealso> - section below.</p> - - <p>The <c>DbgExtra</c> options are described in the - <seealso marker="#debug_flags">DbgExtra options</seealso> - section below.</p> - - </item> - <tag>Communicating with a running port mapper daemon</tag> - <item> - - <p>Communicating with the running epmd daemon by means of the - <c>epmd</c> program is done primarily for debugging - purposes.</p> - - <p>The different queries are described in the <seealso - marker="#interactive_flags">Interactive options</seealso> - section below.</p> - - </item> - </taglist> + <tag>Starting the port mapper daemon</tag> + <item> + <p>The daemon is started automatically by command + <seealso marker="erl"><c>erl(1)</c></seealso> + if the node is to be distributed and no running + instance is present. If automatically launched + environment variables must be used to change the behavior + of the daemon; see section + <seealso marker="#environment_variables">Environment + Variables</seealso>.</p> + <p>If argument <c>-daemon</c> is not specified, + <c><![CDATA[epmd]]></c> runs as a normal program with the + controlling terminal of the shell in which it is + started. Normally, it is to be run as a daemon.</p> + <p>Regular startup options are described in section + <seealso marker="#daemon_flags">Regular Options</seealso>.</p> + <p>The <c>DbgExtra</c> options are described in section + <seealso marker="#debug_flags">DbgExtra Options</seealso>.</p> + </item> + <tag>Communicating with a running port mapper daemon</tag> + <item> + <p>Communicating with the running <c>epmd</c> daemon by the + <c>epmd</c> program is done primarily for debugging purposes.</p> + <p>The different queries are described in section <seealso + marker="#interactive_flags">Interactive options</seealso>.</p> + </item> + </taglist> </description> + <section> <marker id="daemon_flags"></marker> - <title>Regular options</title> + <title>Regular Options</title> + <p>These options are available when starting the name server. The name + server is normally started automatically by command + <seealso marker="erl"><c>erl(1)</c></seealso> (if not already available), + but it can also be started at system startup.</p> - <p>These options are available when starting the actual name server. The name server is normally started automatically by the <c>erl</c> command (if not already available), but it can also be started at i.e. system start-up.</p> <taglist> - <tag><c><![CDATA[-address List]]></c></tag> - <item> - <p>Let this instance of <c>epmd</c> listen only on the - comma-separated list of IP addresses and on the loopback address - (which is implicitly added to the list if it has not been - specified). This can also be set using the - <c><![CDATA[ERL_EPMD_ADDRESS]]></c> environment variable. See the - section <seealso marker="#environment_variables">Environment - variables</seealso> below.</p> - </item> - <tag><c><![CDATA[-port No]]></c></tag> - <item> - <p>Let this instance of epmd listen to another TCP port than - default 4369. This can also be set using the - <c><![CDATA[ERL_EPMD_PORT]]></c> environment variable. See the - section <seealso marker="#environment_variables">Environment - variables</seealso> below</p> - </item> - <tag><c><![CDATA[-d | -debug]]></c></tag> - <item> - - <p>Enable debug output. The more <c>-d</c> flags given, the more - debug output you will get (to a certain limit). This option is - most useful when the epmd daemon is not started as a daemon.</p> - </item> - <tag><c><![CDATA[-daemon]]></c></tag> - <item> - <p>Start epmd detached from the controlling terminal. Logging will end up in syslog when available and correctly configured. If the epmd daemon is started at boot, this option should definitely be used. It is also used when the <c>erl</c> command automatically starts <c>epmd</c>.</p> - </item> - <tag><c><![CDATA[-relaxed_command_check]]></c></tag> - <item> - <p>Start the epmd program with relaxed command checking (mostly for backward compatibility). This affects the following:</p> - <list type="bulleted"> - <item> - <p>With relaxed command checking, the <c>epmd</c> daemon can be killed from the localhost with i.e. <c>epmd -kill</c> even if there are active nodes registered. Normally only daemons with an empty node database can be killed with the <c>epmd -kill</c> command.</p> + <tag><c><![CDATA[-address List]]></c></tag> + <item> + <p>Lets this instance of <c>epmd</c> listen only on the + comma-separated list of IP addresses and on the loopback address + (which is implicitly added to the list if it has not been + specified). This can also be set using environment variable + <c><![CDATA[ERL_EPMD_ADDRESS]]></c>; see section <seealso + marker="#environment_variables">Environment Variables</seealso>.</p> + </item> + <tag><c><![CDATA[-port No]]></c></tag> + <item> + <p>Lets this instance of <c>epmd</c> listen to another TCP port than + default 4369. This can also be set using environment variable + <c><![CDATA[ERL_EPMD_PORT]]></c>; see section <seealso + marker="#environment_variables">Environment Variables</seealso>.</p> + </item> + <tag><c><![CDATA[-d | -debug]]></c></tag> + <item> + <p>Enables debug output. The more <c>-d</c> flags specified, the more + debug output you will get (to a certain limit). This option is most + useful when the <c>epmd</c> daemon is not started as a daemon.</p> + </item> + <tag><c><![CDATA[-daemon]]></c></tag> + <item> + <p>Starts <c>epmd</c> detached from the controlling terminal. Logging + ends up in syslog when available and correctly configured. If the + <c>epmd</c> daemon is started at boot, this option is definitely + to be used. It is also used when command <c>erl</c> automatically + starts <c>epmd</c>.</p> + </item> + <tag><c><![CDATA[-relaxed_command_check]]></c></tag> + <item> + <p>Starts the <c>epmd</c> program with relaxed command checking + (mostly for backward compatibility). This affects the following:</p> + <list type="bulleted"> + <item> + <p>With relaxed command checking, the <c>epmd</c> daemon can be + killed from the local host with, for example, command + <c>epmd -kill</c> even if active nodes are registered. Normally + only daemons with an empty node database can be killed with + <c>epmd -kill</c>.</p> </item> <item> - <p>The <c>epmd -stop</c> command (and the corresponding messages to epmd, as can be given using <c>erl_interface/ei</c>) is normally always ignored, as it opens up the possibility of a strange situation where two nodes of the same name can be alive at the same time. A node unregisters itself by just closing the connection to epmd, which is why the <c>stop</c> command was only intended for use in debugging situations.</p> - <p>With relaxed command checking enabled, you can forcibly unregister live nodes.</p> + <p>Command <c>epmd -stop</c> (and the corresponding messages to + <c>epmd</c>, as can be specified using <seealso + marker="erl_interface:ei"><c>erl_interface:ei(3)</c></seealso>) is + normally always ignored. This because it can cause a strange + situation where two nodes of the same name can be alive at the + same time. A node unregisters itself by only closing the + connection to <c>epmd</c>, which is why command <c>stop</c> + was only intended for use in debugging situations.</p> + <p>With relaxed command checking enabled, you can forcibly + unregister live nodes.</p> </item> - </list> - <p>Relaxed command checking can also be enabled by setting the environment variable <c>ERL_EPMD_RELAXED_COMMAND_CHECK</c> prior to starting <c>epmd</c>.</p> - <p>Only use relaxed command checking on systems with very limited interactive usage.</p> - </item> - </taglist> + </list> + <p>Relaxed command checking can also be enabled by setting environment + variable <c>ERL_EPMD_RELAXED_COMMAND_CHECK</c> before starting + <c>epmd</c>.</p> + <p>Use relaxed command checking only on systems with very limited + interactive usage.</p> + </item> + </taglist> </section> <section> <marker id="debug_flags"></marker> - <title>DbgExtra options</title> - <p>These options are purely for debugging and testing epmd clients. They should not be used in normal operation.</p> + <title>DbgExtra Options</title> + <note> + <p>These options are only for debugging and testing <c>epmd</c> clients. + They are not to be used in normal operation.</p> + </note> <taglist> - <tag><c><![CDATA[-packet_timeout Seconds]]></c></tag> - <item> - <p>Set the number of seconds a connection can be - inactive before epmd times out and closes the - connection (default 60).</p> - </item> - <tag><c><![CDATA[-delay_accept Seconds]]></c></tag> - <item> - <p>To simulate a busy server you can insert a delay between when epmd - gets notified that a new connection is requested and - when the connection gets accepted.</p> - </item> - <tag><c><![CDATA[-delay_write Seconds]]></c></tag> - <item> - <p>Also a simulation of a busy server. Inserts - a delay before a reply is sent.</p> - </item> + <tag><c><![CDATA[-packet_timeout Seconds]]></c></tag> + <item> + <p>Sets the number of seconds a connection can be + inactive before <c>epmd</c> times out and closes the + connection. Defaults to 60.</p> + </item> + <tag><c><![CDATA[-delay_accept Seconds]]></c></tag> + <item> + <p>To simulate a busy server, you can insert a delay between when + <c>epmd</c> gets notified that a new connection is requested and + when the connection gets accepted.</p> + </item> + <tag><c><![CDATA[-delay_write Seconds]]></c></tag> + <item> + <p>Also a simulation of a busy server. Inserts + a delay before a reply is sent.</p> + </item> </taglist> </section> + <section> <marker id="interactive_flags"></marker> - <title>Interactive options</title> - <p>These options make <c>epmd</c> run as an interactive command, displaying the results of sending queries to an already running instance of <c>epmd</c>. The epmd contacted is always on the local node, but the <c>-port</c> option can be used to select between instances if several are running using different ports on the host.</p> - <taglist> - <tag><c><![CDATA[-port No]]></c></tag> - <item> - <p>Contacts the <c>epmd</c> listening on the given TCP port number - (default 4369). This can also be set using the - <c><![CDATA[ERL_EPMD_PORT]]></c> environment variable. See the - section <seealso marker="#environment_variables">Environment - variables</seealso> below.</p> - </item> - <tag><c><![CDATA[-names]]></c></tag> - <item> - <p>List names registered with the currently running epmd</p> - </item> - <tag><c><![CDATA[-kill]]></c></tag> - <item> - <p>Kill the currently running <c>epmd</c>.</p> - - <p>Killing the running <c>epmd</c> is only allowed if <c>epmd - -names</c> shows an empty database or - <c>-relaxed_command_check</c> was given when the running - instance of <c>epmd</c> was started. Note that - <c>-relaxed_command_check</c> is given when starting the - daemon that is to accept killing when it has live nodes - registered. When running epmd interactively, - <c>-relaxed_command_check</c> has no effect. A daemon that is - started without relaxed command checking has to be killed - using i.e. signals or some other OS specific method if it has - active clients registered.</p> - </item> - <tag><c><![CDATA[-stop Name]]></c></tag> - <item> - <p>Forcibly unregister a live node from <c>epmd</c>'s database</p> + <title>Interactive Options</title> + <p>These options make <c>epmd</c> run as an interactive command, + displaying the results of sending queries to an already running + instance of <c>epmd</c>. The <c>epmd</c> contacted is always on the + local node, but option <c>-port</c> can be used to select between + instances if several are running using different ports on the host.</p> - <p>This command can only be used when contacting <c>epmd</c> - instances started with the <c>-relaxed_command_check</c> - flag. Note that relaxed command checking has to be enabled for - the <c>epmd</c> daemon contacted. When running epmd - interactively, - <c>-relaxed_command_check</c> has no effect.</p> - </item> - </taglist> + <taglist> + <tag><c><![CDATA[-port No]]></c></tag> + <item> + <p>Contacts the <c>epmd</c> listening on the specified TCP port + number (default 4369). This can also be set using environment + variable <c><![CDATA[ERL_EPMD_PORT]]></c>; see section <seealso + marker="#environment_variables">Environment Variables</seealso>.</p> + </item> + <tag><c><![CDATA[-names]]></c></tag> + <item> + <p>Lists names registered with the currently running <c>epmd</c>.</p> + </item> + <tag><c><![CDATA[-kill]]></c></tag> + <item> + <p>Kills the currently running <c>epmd</c>.</p> + <p>Killing the running <c>epmd</c> is only allowed if + <c>epmd -names</c> shows an empty database or if + <c>-relaxed_command_check</c> was specified when the running + instance of <c>epmd</c> was started.</p> + <p>Notice that <c>-relaxed_command_check</c> is specified when + starting the daemon that is to accept killing when it has live + nodes registered. When running <c>epmd</c> interactively, + <c>-relaxed_command_check</c> has no effect. A daemon that is + started without relaxed command checking must be killed using, + for example, signals or some other OS-specific method if it has + active clients registered.</p> + </item> + <tag><c><![CDATA[-stop Name]]></c></tag> + <item> + <p>Forcibly unregisters a live node from the <c>epmd</c> database.</p> + <p>This command can only be used when contacting <c>epmd</c> + instances started with flag <c>-relaxed_command_check</c>.</p> + <p>Notice that relaxed command checking must enabled for the + <c>epmd</c> daemon contacted. When running <c>epmd</c> + interactively, <c>-relaxed_command_check</c> has no effect.</p> + </item> + </taglist> </section> + <section> <marker id="environment_variables"></marker> - <title>Environment variables</title> + <title>Environment Variables</title> <taglist> <tag><c><![CDATA[ERL_EPMD_ADDRESS]]></c></tag> <item> - <p>This environment variable may be set to a comma-separated - list of IP addresses, in which case the <c>epmd</c> daemon - will listen only on the specified address(es) and on the - loopback address (which is implicitly added to the list if it - has not been specified). The default behaviour is to listen on - all available IP addresses.</p> + <p>Can be set to a comma-separated + list of IP addresses, in which case the <c>epmd</c> daemon + will listen only on the specified address(es) and on the + loopback address (which is implicitly added to the list if it + has not been specified). The default behavior is to listen on + all available IP addresses.</p> </item> <tag><c><![CDATA[ERL_EPMD_PORT]]></c></tag> <item> - <p>This environment variable can contain the port number epmd will use. - The default port will work fine in most cases. A different port can - be specified to allow several instances of epmd, representing - independent clusters of nodes, to co-exist on the same host. - All nodes in a cluster must use the same epmd port number.</p> + <p>Can contain the port number <c>epmd</c> will use. + The default port will work fine in most cases. A different port can + be specified to allow several instances of <c>epmd</c>, representing + independent clusters of nodes, to co-exist on the same host. + All nodes in a cluster must use the same <c>epmd</c> port number.</p> </item> <tag><c><![CDATA[ERL_EPMD_RELAXED_COMMAND_CHECK]]></c></tag> <item> - <p>If set prior to start, the <c>epmd</c> daemon will behave - as if the <c>-relaxed_command_check</c> option was given at - start-up. Consequently, if this option is set before starting - the Erlang virtual machine, the automatically started - <c>epmd</c> will accept the <c>-kill</c> and <c>-stop</c> - commands without restrictions.</p> + <p>If set before start, the <c>epmd</c> daemon behaves + as if option <c>-relaxed_command_check</c> was specified at + startup. Consequently, if this option is set before starting + the Erlang virtual machine, the automatically started + <c>epmd</c> accepts the <c>-kill</c> and <c>-stop</c> + commands without restrictions.</p> </item> </taglist> </section> @@ -270,41 +288,45 @@ <section> <title>Logging</title> <p>On some operating systems <em>syslog</em> will be used for - error reporting when epmd runs as an daemon. To enable - the error logging you have to edit <path unix="" windows="">/etc/syslog.conf</path> - file and add an entry</p> + error reporting when <c>epmd</c> runs as a daemon. To enable + the error logging, you must edit the + <path unix="" windows="">/etc/syslog.conf</path> file and add an + entry:</p> + <code type="none"><![CDATA[ - !epmd - *.*<TABs>/var/log/epmd.log - ]]></code> - <p>where <TABs> are at least one real tab character. Spaces will - silently be ignored. - </p> + !epmd + *.*<TABs>/var/log/epmd.log +]]></code> + + <p>where <c><TABs></c> are at least one real tab character. + Spaces are silently ignored.</p> </section> + <section> - <title>Access restrictions</title> - <p>The <c>epmd</c> daemon accepts messages from both localhost and - remote hosts. However, only the query commands are answered (and - acted upon) if the query comes from a remote host. It is always an - error to try to register a nodename if the client is not a process - located on the same host as the <c>epmd</c> instance is running on- - such requests are considered hostile and the connection is - immediately closed.</p> + <title>Access Restrictions</title> + <p>The <c>epmd</c> daemon accepts messages from both the local host and + remote hosts. However, only the query commands are answered (and + acted upon) if the query comes from a remote host. It is always an + error to try to register a node name if the client is not a process + on the same host as the <c>epmd</c> instance is running on. Such + requests are considered hostile and the connection is closed + immediately.</p> - <p>The queries accepted from remote nodes are:</p> - <list type="bulleted"> - <item> - <p>Port queries - i.e. on which port does the node with a given - name listen</p> - </item> - <item> - <p>Name listing - i.e. give a list of all names registered on + <p>The following queries are accepted from remote nodes:</p> + + <list type="bulleted"> + <item> + <p>Port queries, that is, on which port the node with a specified + name listens</p> + </item> + <item> + <p>Name listing, that is, gives a list of all names registered on the host</p> - </item> - </list> - <p>To restrict access further, firewall software has to be used.</p> - </section> + </item> + </list> + <p>To restrict access further, firewall software must be used.</p> + </section> </comref> diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index f08467bfc6..05a9895687 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -4,20 +4,21 @@ <comref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -29,86 +30,92 @@ <file>erl.xml</file> </header> <com>erl</com> - <comsummary>The Erlang Emulator</comsummary> + <comsummary>The Erlang emulator.</comsummary> <description> <p>The <c><![CDATA[erl]]></c> program starts an Erlang runtime system. - The exact details (for example, whether <c><![CDATA[erl]]></c> is a script or - a program and which other programs it calls) are system-dependent.</p> - <p>Windows users probably wants to use the <c><![CDATA[werl]]></c> program + The exact details (for example, whether <c><![CDATA[erl]]></c> is a + script or a program and which other programs it calls) are + system-dependent.</p> + + <p>Windows users probably want to use the <c><![CDATA[werl]]></c> program instead, which runs in its own window with scrollbars and supports - command-line editing. The <c><![CDATA[erl]]></c> program on Windows provides - no line editing in its shell, and on Windows 95 there is no way - to scroll back to text which has scrolled off the screen. - The <c><![CDATA[erl]]></c> program must be used, however, in pipelines or if + command-line editing. The <c><![CDATA[erl]]></c> program on Windows + provides no line editing in its shell, and on Windows 95 there is no way + to scroll back to text that has scrolled off the screen. The + <c><![CDATA[erl]]></c> program must be used, however, in pipelines or if you want to redirect standard input or output.</p> - <note><p>As of ERTS version 5.9 (OTP-R15B) the runtime system will by - default <em>not</em> bind schedulers to logical processors. - For more information see documentation of the - <seealso marker="#+sbt">+sbt</seealso> system flag. - </p> - </note> + + <note> + <p>As from ERTS 5.9 (Erlang/OTP R15B) the runtime system does by + default <em>not</em> bind schedulers to logical processors. + For more information, see system flag + <seealso marker="#+sbt"><c>+sbt</c></seealso>.</p> + </note> </description> + <funcs> <func> <name>erl <arguments></name> - <fsummary>Start an Erlang runtime system</fsummary> + <fsummary>Start an Erlang runtime system.</fsummary> <desc> - <p>Starts an Erlang runtime system.</p> - <p>The arguments can be divided into <em>emulator flags</em>, - <em>flags</em> and <em>plain arguments</em>:</p> - <list type="bulleted"> - <item> - <p>Any argument starting with the character <c><![CDATA[+]]></c> is - interpreted as an <seealso marker="#emu_flags">emulator flag</seealso>.</p> - <p>As indicated by the name, emulator flags controls - the behavior of the emulator.</p> - </item> - <item> - <p>Any argument starting with the character <c><![CDATA[-]]></c> - (hyphen) is interpreted as a - <seealso marker="#init_flags">flag</seealso> which should - be passed to the Erlang part of the runtime system, more - specifically to the <c><![CDATA[init]]></c> system process, see - <seealso marker="init">init(3)</seealso>.</p> - <p>The <c><![CDATA[init]]></c> process itself interprets some of these - flags, the <em>init flags</em>. It also stores any - remaining flags, the <em>user flags</em>. The latter can - be retrieved by calling <c><![CDATA[init:get_argument/1]]></c>.</p> - <p>It can be noted that there are a small number of "-" - flags which now actually are emulator flags, see - the description below.</p> - </item> - <item> - <p>Plain arguments are not interpreted in any way. They are - also stored by the <c><![CDATA[init]]></c> process and can be - retrieved by calling <c><![CDATA[init:get_plain_arguments/0]]></c>. - Plain arguments can occur before the first flag, or after - a <c><![CDATA[--]]></c> flag. Additionally, the flag <c><![CDATA[-extra]]></c> - causes everything that follows to become plain arguments.</p> - </item> - </list> - <p>Example:</p> - <pre> + <p>Starts an Erlang runtime system.</p> + <p>The arguments can be divided into <em>emulator flags</em>, + <em>flags</em>, and <em>plain arguments</em>:</p> + <list type="bulleted"> + <item> + <p>Any argument starting with character <c><![CDATA[+]]></c> is + interpreted as an + <seealso marker="#emu_flags">emulator flag</seealso>.</p> + <p>As indicated by the name, emulator flags control + the behavior of the emulator.</p> + </item> + <item> + <p>Any argument starting with character <c><![CDATA[-]]></c> + (hyphen) is interpreted as a + <seealso marker="#init_flags">flag</seealso>, which is to + be passed to the Erlang part of the runtime system, more + specifically to the <c><![CDATA[init]]></c> system process, see + <seealso marker="init"><c>init(3)</c></seealso>.</p> + <p>The <c><![CDATA[init]]></c> process itself interprets some of + these flags, the <em>init flags</em>. It also stores any + remaining flags, the <em>user flags</em>. The latter can be + retrieved by calling <c><![CDATA[init:get_argument/1]]></c>.</p> + <p>A small number of "-" flags exist, which now actually are + emulator flags, see the description below.</p> + </item> + <item> + <p>Plain arguments are not interpreted in any way. They are also + stored by the <c><![CDATA[init]]></c> process and can be retrieved + by calling <c><![CDATA[init:get_plain_arguments/0]]></c>. + Plain arguments can occur before the first flag, or after a + <c><![CDATA[--]]></c> flag. Also, the <c><![CDATA[-extra]]></c> + flag causes everything that follows to become plain arguments.</p> + </item> + </list> + <p><em>Examples:</em></p> + <pre> % <input>erl +W w -sname arnie +R 9 -s my_init -extra +bertie</input> (arnie@host)1> <input>init:get_argument(sname).</input> {ok,[["arnie"]]} (arnie@host)2> <input>init:get_plain_arguments().</input> ["+bertie"]</pre> - <p>Here <c><![CDATA[+W w]]></c> and <c><![CDATA[+R 9]]></c> are emulator flags. - <c><![CDATA[-s my_init]]></c> is an init flag, interpreted by <c><![CDATA[init]]></c>. - <c><![CDATA[-sname arnie]]></c> is a user flag, stored by <c><![CDATA[init]]></c>. - It is read by Kernel and will cause the Erlang runtime system - to become distributed. Finally, everything after <c><![CDATA[-extra]]></c> - (that is, <c><![CDATA[+bertie]]></c>) is considered as plain arguments.</p> - <pre> + <p>Here <c><![CDATA[+W w]]></c> and <c><![CDATA[+R 9]]></c> are + emulator flags. <c><![CDATA[-s my_init]]></c> is an init flag, + interpreted by <c><![CDATA[init]]></c>. + <c><![CDATA[-sname arnie]]></c> is a user flag, stored by + <c><![CDATA[init]]></c>. It is read by Kernel and causes the + Erlang runtime system to become distributed. Finally, everything after + <c><![CDATA[-extra]]></c> (that is, <c><![CDATA[+bertie]]></c>) is + considered as plain arguments.</p> + <pre> % <input>erl -myflag 1</input> 1> <input>init:get_argument(myflag).</input> {ok,[["1"]]} 2> <input>init:get_plain_arguments().</input> []</pre> - <p>Here the user flag <c><![CDATA[-myflag 1]]></c> is passed to and stored - by the <c><![CDATA[init]]></c> process. It is a user defined flag, - presumably used by some user defined application.</p> + <p>Here the user flag <c><![CDATA[-myflag 1]]></c> is passed to and + stored by the <c><![CDATA[init]]></c> process. It is a user-defined + flag, presumably used by some user-defined application.</p> </desc> </func> </funcs> @@ -116,50 +123,54 @@ <section> <marker id="init_flags"></marker> <title>Flags</title> - <p>In the following list, init flags are marked (init flag). + <p>In the following list, init flags are marked "(init flag)". Unless otherwise specified, all other flags are user flags, for which the values can be retrieved by calling - <c><![CDATA[init:get_argument/1]]></c>. Note that the list of user flags is - not exhaustive, there may be additional, application specific - flags which instead are documented in the corresponding + <c><![CDATA[init:get_argument/1]]></c>. Notice that the list of user + flags is not exhaustive, there can be more application-specific + flags that instead are described in the corresponding application documentation.</p> <taglist> - <tag><c><![CDATA[--]]></c>(init flag)</tag> + <tag><c><![CDATA[--]]></c> (init flag)</tag> <item> <p>Everything following <c><![CDATA[--]]></c> up to the next flag - (<c><![CDATA[-flag]]></c> or <c><![CDATA[+flag]]></c>) is considered plain arguments - and can be retrieved using <c><![CDATA[init:get_plain_arguments/0]]></c>.</p> + (<c><![CDATA[-flag]]></c> or <c><![CDATA[+flag]]></c>) is considered + plain arguments and can be retrieved using + <c><![CDATA[init:get_plain_arguments/0]]></c>.</p> </item> <tag><c><![CDATA[-Application Par Val]]></c></tag> <item> - <p>Sets the application configuration parameter <c><![CDATA[Par]]></c> to - the value <c><![CDATA[Val]]></c> for the application <c><![CDATA[Application]]></c>, - see <seealso marker="kernel:app">app(4)</seealso> and - <seealso marker="kernel:application">application(3)</seealso>.</p> - </item> - <tag><marker id="args_file"><c><![CDATA[-args_file FileName]]></c></marker></tag> - <item> - <p>Command line arguments are read from the file <c><![CDATA[FileName]]></c>. - The arguments read from the file replace the - '<c><![CDATA[-args_file FileName]]></c>' flag on the resulting command line.</p> - <p>The file <c><![CDATA[FileName]]></c> should be a plain text file and may - contain comments and command line arguments. A comment begins - with a # character and continues until next end of line character. - Backslash (\\) is used as quoting character. All command line - arguments accepted by <c><![CDATA[erl]]></c> are allowed, also the - <c><![CDATA[-args_file FileName]]></c> flag. Be careful not to cause circular - dependencies between files containing the <c><![CDATA[-args_file]]></c> flag, - though.</p> - <p>The <c><![CDATA[-extra]]></c> flag is treated specially. Its scope ends - at the end of the file. Arguments following an <c><![CDATA[-extra]]></c> - flag are moved on the command line into the <c><![CDATA[-extra]]></c> section, - i.e. the end of the command line following after an <c><![CDATA[-extra]]></c> - flag.</p> + <p>Sets the application configuration parameter <c><![CDATA[Par]]></c> + to the value <c><![CDATA[Val]]></c> for the application + <c><![CDATA[Application]]></c>; see + <seealso marker="kernel:app"><c>app(4)</c></seealso> and + <seealso marker="kernel:application"> + <c>application(3)</c></seealso>.</p> + </item> + <tag><marker id="args_file"/><c><![CDATA[-args_file FileName]]></c></tag> + <item> + <p>Command-line arguments are read from the file + <c><![CDATA[FileName]]></c>. The arguments read from the file replace + flag '<c><![CDATA[-args_file FileName]]></c>' on the resulting + command line.</p> + <p>The file <c><![CDATA[FileName]]></c> is to be a plain text file and + can contain comments and command-line arguments. A comment begins + with a <c>#</c> character and continues until the next end of line + character. Backslash (\\) is used as quoting character. All + command-line arguments accepted by <c><![CDATA[erl]]></c> are allowed, + also flag <c><![CDATA[-args_file FileName]]></c>. Be careful not to + cause circular dependencies between files containing flag + <c><![CDATA[-args_file]]></c>, though.</p> + <p>The flag <c><![CDATA[-extra]]></c> is treated in special way. Its + scope ends at the end of the file. Arguments following an + <c><![CDATA[-extra]]></c> flag are moved on the command line into the + <c><![CDATA[-extra]]></c> section, that is, the end of the command + line following after an <c><![CDATA[-extra]]></c> flag.</p> </item> <tag><c><![CDATA[-async_shell_start]]></c></tag> <item> <p>The initial Erlang shell does not read user input until - the system boot procedure has been completed (Erlang 5.4 and + the system boot procedure has been completed (Erlang/OTP 5.4 and later). This flag disables the start synchronization feature and lets the shell start in parallel with the rest of the system.</p> @@ -167,52 +178,56 @@ <tag><c><![CDATA[-boot File]]></c></tag> <item> <p>Specifies the name of the boot file, <c><![CDATA[File.boot]]></c>, - which is used to start the system. See - <seealso marker="init">init(3)</seealso>. Unless + which is used to start the system; see + <seealso marker="init"><c>init(3)</c></seealso>. Unless <c><![CDATA[File]]></c> contains an absolute path, the system searches - for <c><![CDATA[File.boot]]></c> in the current and <c><![CDATA[$ROOT/bin]]></c> - directories.</p> + for <c><![CDATA[File.boot]]></c> in the current and + <c><![CDATA[$ROOT/bin]]></c> directories.</p> <p>Defaults to <c><![CDATA[$ROOT/bin/start.boot]]></c>.</p> </item> <tag><c><![CDATA[-boot_var Var Dir]]></c></tag> <item> - <p>If the boot script contains a path variable <c><![CDATA[Var]]></c> other - than <c><![CDATA[$ROOT]]></c>, this variable is expanded to <c><![CDATA[Dir]]></c>. - Used when applications are installed in another directory - than <c><![CDATA[$ROOT/lib]]></c>, see - <seealso marker="sasl:systools#make_script/1">systools:make_script/1,2</seealso>.</p> + <p>If the boot script contains a path variable <c><![CDATA[Var]]></c> + other than <c><![CDATA[$ROOT]]></c>, this variable is expanded to + <c><![CDATA[Dir]]></c>. Used when applications are installed in + another directory than <c><![CDATA[$ROOT/lib]]></c>; see + <seealso marker="sasl:systools#make_script/1"> + <c>systools:make_script/1,2</c></seealso> in SASL.</p> </item> <tag><c><![CDATA[-code_path_cache]]></c></tag> <item> - <p>Enables the code path cache of the code server, see - <seealso marker="kernel:code">code(3)</seealso>.</p> + <p>Enables the code path cache of the code server; see + <seealso marker="kernel:code"><c>code(3)</c></seealso>.</p> </item> <tag><c><![CDATA[-compile Mod1 Mod2 ...]]></c></tag> <item> <p>Compiles the specified modules and then terminates (with non-zero exit code if the compilation of some file did not - succeed). Implies <c><![CDATA[-noinput]]></c>. Not recommended - use - <seealso marker="erlc">erlc</seealso> instead.</p> + succeed). Implies <c><![CDATA[-noinput]]></c>.</p> + <p>Not recommended; use <seealso marker="erlc"><c>erlc</c></seealso> + instead.</p> </item> <tag><c><![CDATA[-config Config]]></c></tag> <item> <p>Specifies the name of a configuration file, <c><![CDATA[Config.config]]></c>, which is used to configure - applications. See - <seealso marker="kernel:app">app(4)</seealso> and - <seealso marker="kernel:application">application(3)</seealso>.</p> + applications; see + <seealso marker="kernel:app"><c>app(4)</c></seealso> and + <seealso marker="kernel:application"> + <c>application(3)</c></seealso>.</p> </item> - <tag><marker id="connect_all"><c><![CDATA[-connect_all false]]></c></marker></tag> + <tag><marker id="connect_all"/><c><![CDATA[-connect_all false]]></c></tag> <item> - <p>If this flag is present, <c><![CDATA[global]]></c> will not maintain a - fully connected network of distributed Erlang nodes, and then - global name registration cannot be used. See - <seealso marker="kernel:global">global(3)</seealso>.</p> + <p>If this flag is present, <c><![CDATA[global]]></c> does not maintain + a fully connected network of distributed Erlang nodes, and then + global name registration cannot be used; see + <seealso marker="kernel:global"><c>global(3)</c></seealso>.</p> </item> <tag><c><![CDATA[-cookie Cookie]]></c></tag> <item> <p>Obsolete flag without any effect and common misspelling for - <c><![CDATA[-setcookie]]></c>. Use <c><![CDATA[-setcookie]]></c> instead.</p> + <c><![CDATA[-setcookie]]></c>. Use <c><![CDATA[-setcookie]]></c> + instead.</p> </item> <tag><c><![CDATA[-detached]]></c></tag> <item> @@ -222,8 +237,14 @@ </item> <tag><c><![CDATA[-emu_args]]></c></tag> <item> - <p>Useful for debugging. Prints out the actual arguments - sent to the emulator.</p> + <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> @@ -233,14 +254,21 @@ <pre> % <input>erl -env DISPLAY gin:0</input></pre> <p>In this example, an Erlang runtime system is started with - the <c><![CDATA[DISPLAY]]></c> environment variable set to <c><![CDATA[gin:0]]></c>.</p> + environment variable <c><![CDATA[DISPLAY]]></c> set to + <c><![CDATA[gin:0]]></c>.</p> + </item> + <tag><c><![CDATA[-epmd_module Module]]></c> (init flag)</tag> + <item> + <p>Configures the module responsible to communicate to + <seealso marker="epmd">epmd</seealso>. Defaults to <c>erl_epmd</c>.</p> </item> - <tag><c><![CDATA[-eval Expr]]></c>(init flag)</tag> + <tag><c><![CDATA[-eval Expr]]></c> (init flag)</tag> <item> - <p>Makes <c><![CDATA[init]]></c> evaluate the expression <c><![CDATA[Expr]]></c>, see - <seealso marker="init">init(3)</seealso>.</p> + <p>Makes <c><![CDATA[init]]></c> evaluate the expression + <c><![CDATA[Expr]]></c>; see + <seealso marker="init"><c>init(3)</c></seealso>.</p> </item> - <tag><c><![CDATA[-extra]]></c>(init flag)</tag> + <tag><c><![CDATA[-extra]]></c> (init flag)</tag> <item> <p>Everything following <c><![CDATA[-extra]]></c> is considered plain arguments and can be retrieved using @@ -248,8 +276,9 @@ </item> <tag><c><![CDATA[-heart]]></c></tag> <item> - <p>Starts heart beat monitoring of the Erlang runtime system. - See <seealso marker="kernel:heart">heart(3)</seealso>.</p> + <p>Starts heartbeat monitoring of the Erlang runtime system; + see <seealso marker="kernel:heart"> + <c>heart(3)</c></seealso>.</p> </item> <tag><c><![CDATA[-hidden]]></c></tag> <item> @@ -257,90 +286,110 @@ run as a distributed node. Hidden nodes always establish hidden connections to all other nodes except for nodes in the same global group. Hidden connections are not published on - either of the connected nodes, i.e. neither of the connected - nodes are part of the result from <c><![CDATA[nodes/0]]></c> on the other - node. See also hidden global groups, - <seealso marker="kernel:global_group">global_group(3)</seealso>.</p> + any of the connected nodes, that is, none of the connected + nodes are part of the result from <c><![CDATA[nodes/0]]></c> on the + other node. See also hidden global groups; + <seealso marker="kernel:global_group"> + <c>global_group(3)</c></seealso>.</p> </item> <tag><c><![CDATA[-hosts Hosts]]></c></tag> <item> - <p>Specifies the IP addresses for the hosts on which Erlang - boot servers are running, see - <seealso marker="kernel:erl_boot_server">erl_boot_server(3)</seealso>. - This flag is mandatory if the <c><![CDATA[-loader inet]]></c> flag is - present.</p> - <p>The IP addresses must be given in the standard form (four - decimal numbers separated by periods, for example - <c><![CDATA["150.236.20.74"]]></c>. Hosts names are not acceptable, but - a broadcast address (preferably limited to the local network) + <p>Specifies the IP addresses for the hosts on which Erlang boot servers + are running, see <seealso marker="kernel:erl_boot_server"> + <c>erl_boot_server(3)</c></seealso>. This flag + is mandatory if flag <c><![CDATA[-loader inet]]></c> is present.</p> + <p>The IP addresses must be specified in the standard form (four + decimal numbers separated by periods, for example, + <c><![CDATA["150.236.20.74"]]></c>. Hosts names are not acceptable, + but a broadcast address (preferably limited to the local network) is.</p> </item> <tag><c><![CDATA[-id Id]]></c></tag> <item> <p>Specifies the identity of the Erlang runtime system. If it is run as a distributed node, <c><![CDATA[Id]]></c> must be identical to - the name supplied together with the <c><![CDATA[-sname]]></c> or - <c><![CDATA[-name]]></c> flag.</p> + the name supplied together with flag <c><![CDATA[-sname]]></c> or + <c><![CDATA[-name]]></c>.</p> </item> <tag><c><![CDATA[-init_debug]]></c></tag> <item> <p>Makes <c><![CDATA[init]]></c> write some debug information while interpreting the boot script.</p> </item> - <tag><marker id="instr"><c><![CDATA[-instr]]></c>(emulator flag)</marker></tag> + <tag><marker id="instr"/><c><![CDATA[-instr]]></c> (emulator flag)</tag> <item> <p>Selects an instrumented Erlang runtime system (virtual machine) to run, instead of the ordinary one. When running an instrumented runtime system, some resource usage data can be - obtained and analysed using the module <c><![CDATA[instrument]]></c>. + obtained and analyzed using the <c><![CDATA[instrument]]></c> module. Functionally, it behaves exactly like an ordinary Erlang runtime system.</p> </item> <tag><c><![CDATA[-loader Loader]]></c></tag> <item> - <p>Specifies the method used by <c><![CDATA[erl_prim_loader]]></c> to load - Erlang modules into the system. See - <seealso marker="erl_prim_loader">erl_prim_loader(3)</seealso>. - Two <c><![CDATA[Loader]]></c> methods are supported, <c><![CDATA[efile]]></c> and - <c><![CDATA[inet]]></c>. <c><![CDATA[efile]]></c> means use the local file system, - this is the default. <c><![CDATA[inet]]></c> means use a boot server on - another machine, and the <c><![CDATA[-id]]></c>, <c><![CDATA[-hosts]]></c> and - <c><![CDATA[-setcookie]]></c> flags must be specified as well. If - <c><![CDATA[Loader]]></c> is something else, the user supplied + <p>Specifies the method used by <c><![CDATA[erl_prim_loader]]></c> to + load Erlang modules into the system; see + <seealso marker="erl_prim_loader"><c>erl_prim_loader(3)</c></seealso>. + Two <c><![CDATA[Loader]]></c> methods are supported:</p> + <list type="bulleted"> + <item> + <p><c><![CDATA[efile]]></c>, which means use the local file system, + this is the default.</p> + </item> + <item> + <p><c><![CDATA[inet]]></c>, which means use a boot server on + another machine. The flags <c><![CDATA[-id]]></c>, + <c><![CDATA[-hosts]]></c> and <c><![CDATA[-setcookie]]></c> must + also be specified.</p> + </item> + </list> + <p>If <c><![CDATA[Loader]]></c> is something else, the user-supplied <c><![CDATA[Loader]]></c> port program is started.</p> </item> <tag><c><![CDATA[-make]]></c></tag> <item> - <p>Makes the Erlang runtime system invoke <c><![CDATA[make:all()]]></c> in - the current working directory and then terminate. See - <seealso marker="tools:make">make(3)</seealso>. Implies + <p>Makes the Erlang runtime system invoke <c><![CDATA[make:all()]]></c> + in the current working directory and then terminate; see + <seealso marker="tools:make"><c>make(3)</c></seealso>. Implies <c><![CDATA[-noinput]]></c>.</p> </item> <tag><c><![CDATA[-man Module]]></c></tag> <item> - <p>Displays the manual page for the Erlang module <c><![CDATA[Module]]></c>. - Only supported on Unix.</p> + <p>Displays the manual page for the Erlang module + <c><![CDATA[Module]]></c>. Only supported on Unix.</p> </item> <tag><c><![CDATA[-mode interactive | embedded]]></c></tag> <item> - <p>Indicates if the system should load code dynamically - (<c><![CDATA[interactive]]></c>), or if all code should be loaded - during system initialization (<c><![CDATA[embedded]]></c>), see - <seealso marker="kernel:code">code(3)</seealso>. Defaults to - <c><![CDATA[interactive]]></c>.</p> + <p>Modules are auto loaded when they are first referenced if the + runtime system runs in <c><![CDATA[interactive]]></c> mode, which is + the default. In <c><![CDATA[embedded]]></c> mode modules are not auto + loaded. The latter is recommended when the boot script preloads all + modules, as conventionally happens in OTP releases. See + <seealso marker="kernel:code"><c>code(3)</c></seealso></p>. </item> <tag><c><![CDATA[-name Name]]></c></tag> <item> <p>Makes the Erlang runtime system into a distributed node. This flag invokes all network servers necessary for a node to - become distributed. See - <seealso marker="kernel:net_kernel">net_kernel(3)</seealso>. - It is also ensured that <c><![CDATA[epmd]]></c> runs on the current host - before Erlang is started. See - <seealso marker="epmd">epmd(1)</seealso>.</p> - <p>The name of the node will be <c><![CDATA[Name@Host]]></c>, where - <c><![CDATA[Host]]></c> is the fully qualified host name of the current - host. For short names, use the <c><![CDATA[-sname]]></c> flag instead.</p> + become distributed; see <seealso marker="kernel:net_kernel"> + <c>net_kernel(3)</c></seealso>. It is also ensured that + <c><![CDATA[epmd]]></c> runs on the current host before Erlang is + started; see <seealso marker="epmd"><c>epmd(1)</c></seealso>.and the + <seealso marker="#start_epmd"><c>-start_epmd</c></seealso> option.</p> + <p>The node name will be <c><![CDATA[Name@Host]]></c>, where + <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> @@ -351,105 +400,148 @@ <item> <p>Starts an Erlang runtime system with no shell. This flag makes it possible to have the Erlang runtime system as a - component in a series of UNIX pipes.</p> + component in a series of Unix pipes.</p> </item> <tag><c><![CDATA[-nostick]]></c></tag> <item> <p>Disables the sticky directory facility of the Erlang code - server, see - <seealso marker="kernel:code">code(3)</seealso>.</p> + server; see + <seealso marker="kernel:code"><c>code(3)</c></seealso>.</p> </item> <tag><c><![CDATA[-oldshell]]></c></tag> <item> - <p>Invokes the old Erlang shell from Erlang 3.3. The old shell + <p>Invokes the old Erlang shell from Erlang/OTP 3.3. The old shell can still be used.</p> </item> <tag><c><![CDATA[-pa Dir1 Dir2 ...]]></c></tag> <item> <p>Adds the specified directories to the beginning of the code - path, similar to <c><![CDATA[code:add_pathsa/1]]></c>. See - <seealso marker="kernel:code">code(3)</seealso>. - As an alternative to <c>-pa</c>, if several directories are - to be prepended to the code and the directories have a - common parent directory, that parent directory could be - specified in the <c>ERL_LIBS</c> environment variable. - See <seealso marker="kernel:code">code(3)</seealso>.</p> + path, similar to <seealso marker="kernel:code#add_pathsa/1"> + <c><![CDATA[code:add_pathsa/1]]></c></seealso>. Note that the + order of the given directories will be reversed in the + resulting path.</p> + <p>As an alternative to <c>-pa</c>, if several directories are + to be prepended to the code path and the directories have a + common parent directory, that parent directory can be + specified in environment variable <c>ERL_LIBS</c>; see + <seealso marker="kernel:code"><c>code(3)</c></seealso>.</p> </item> <tag><c><![CDATA[-pz Dir1 Dir2 ...]]></c></tag> <item> <p>Adds the specified directories to the end of the code path, - similar to <c><![CDATA[code:add_pathsz/1]]></c>. See - <seealso marker="kernel:code">code(3)</seealso>.</p> + similar to <c><![CDATA[code:add_pathsz/1]]></c>; see + <seealso marker="kernel:code"><c>code(3)</c></seealso>.</p> + </item> + <tag><c><![CDATA[-path Dir1 Dir2 ...]]></c></tag> + <item> + <p>Replaces the path specified in the boot script; see + <seealso marker="sasl:script"><c>script(4)</c></seealso>.</p> + </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, 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> + <p>For example, to start up IPv6 distributed nodes:</p> +<pre> +% <input>erl -name [email protected] -proto_dist inet6_tcp</input></pre> </item> <tag><c><![CDATA[-remsh Node]]></c></tag> <item> - <p>Starts Erlang with a remote shell connected to <c><![CDATA[Node]]></c>.</p> + <p>Starts Erlang with a remote shell connected to + <c><![CDATA[Node]]></c>.</p> </item> <tag><c><![CDATA[-rsh Program]]></c></tag> <item> - <p>Specifies an alternative to <c><![CDATA[rsh]]></c> for starting a slave - node on a remote host. See - <seealso marker="stdlib:slave">slave(3)</seealso>.</p> + <p>Specifies an alternative to <c><![CDATA[rsh]]></c> for starting a + slave node on a remote host; see + <seealso marker="stdlib:slave"><c>slave(3)</c></seealso>.</p> </item> - <tag><c><![CDATA[-run Mod [Func [Arg1, Arg2, ...]]]]></c>(init flag)</tag> + <tag><c><![CDATA[-run Mod [Func [Arg1, Arg2, ...]]]]></c> (init + flag)</tag> <item> - <p>Makes <c><![CDATA[init]]></c> call the specified function. <c><![CDATA[Func]]></c> - defaults to <c><![CDATA[start]]></c>. If no arguments are provided, - the function is assumed to be of arity 0. Otherwise it is - assumed to be of arity 1, taking the list - <c><![CDATA[[Arg1,Arg2,...]]]></c> as argument. All arguments are passed - as strings. See - <seealso marker="init">init(3)</seealso>.</p> + <p>Makes <c><![CDATA[init]]></c> call the specified function. + <c><![CDATA[Func]]></c> defaults to <c><![CDATA[start]]></c>. + If no arguments are provided, the function is assumed to be of + arity 0. Otherwise it is assumed to be of arity 1, taking the list + <c><![CDATA[[Arg1,Arg2,...]]]></c> as argument. All arguments are + passed as strings. See <seealso marker="init"> + <c>init(3)</c></seealso>.</p> </item> - <tag><c><![CDATA[-s Mod [Func [Arg1, Arg2, ...]]]]></c>(init flag)</tag> + <tag><c><![CDATA[-s Mod [Func [Arg1, Arg2, ...]]]]></c> (init flag)</tag> <item> - <p>Makes <c><![CDATA[init]]></c> call the specified function. <c><![CDATA[Func]]></c> - defaults to <c><![CDATA[start]]></c>. If no arguments are provided, - the function is assumed to be of arity 0. Otherwise it is - assumed to be of arity 1, taking the list - <c><![CDATA[[Arg1,Arg2,...]]]></c> as argument. All arguments are passed - as atoms. See - <seealso marker="init">init(3)</seealso>.</p> + <p>Makes <c><![CDATA[init]]></c> call the specified function. + <c><![CDATA[Func]]></c> defaults to <c><![CDATA[start]]></c>. + If no arguments are provided, the function is assumed to be of + arity 0. Otherwise it is assumed to be of arity 1, taking the list + <c><![CDATA[[Arg1,Arg2,...]]]></c> as argument. All arguments are + passed as atoms. See <seealso marker="init"> + <c>init(3)</c></seealso>.</p> </item> <tag><c><![CDATA[-setcookie Cookie]]></c></tag> <item> - <p>Sets the magic cookie of the node to <c><![CDATA[Cookie]]></c>, see - <seealso marker="erlang#set_cookie/2">erlang:set_cookie/2</seealso>.</p> + <p>Sets the magic cookie of the node to <c><![CDATA[Cookie]]></c>; see + <seealso marker="erlang#set_cookie/2"> + <c>erlang:set_cookie/2</c></seealso>.</p> </item> <tag><c><![CDATA[-shutdown_time Time]]></c></tag> <item> <p>Specifies how long time (in milliseconds) the <c><![CDATA[init]]></c> process is allowed to spend shutting down the system. If - <c><![CDATA[Time]]></c> ms have elapsed, all processes still existing are - killed. Defaults to <c><![CDATA[infinity]]></c>.</p> + <c><![CDATA[Time]]></c> milliseconds have elapsed, all processes still + existing are killed. Defaults to <c><![CDATA[infinity]]></c>.</p> </item> <tag><c><![CDATA[-sname Name]]></c></tag> <item> - <p>Makes the Erlang runtime system into a distributed node, - similar to <c><![CDATA[-name]]></c>, but the host name portion of the node + <p>Makes the Erlang runtime system into a distributed node, similar to + <c><![CDATA[-name]]></c>, but the host name portion of the node name <c><![CDATA[Name@Host]]></c> will be the short name, not fully qualified.</p> <p>This is sometimes the only way to run distributed Erlang if - the DNS (Domain Name System) is not running. There can be no - communication between nodes running with the <c><![CDATA[-sname]]></c> - flag and those running with the <c><![CDATA[-name]]></c> flag, as node + the Domain Name System (DNS) is not running. No communication can + 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="smp"><c><![CDATA[-smp [enable|auto|disable]]]></c></marker></tag> + <tag><marker id="start_epmd"/><c>-start_epmd true | false</c></tag> <item> - <p><c>-smp enable</c> and <c>-smp</c> starts the Erlang runtime - system with SMP support enabled. This may fail if no runtime - system with SMP support is available. <c>-smp auto</c> starts - the Erlang runtime system with SMP support enabled if it is - available and more than one logical processor are detected. - <c>-smp disable</c> starts a runtime system without SMP support.</p> - <p><em>NOTE</em>: The runtime system with SMP support will not - be available on all supported platforms. See also the - <seealso marker="#+S">+S</seealso> flag.</p> + + <p>Specifies whether Erlang should start + <seealso marker="epmd">epmd</seealso> on startup. By default + this is <c>true</c>, but if you prefer to start epmd + manually, set this to <c>false</c>.</p> + + <p>This only applies if Erlang is started as a distributed node, + i.e. if <c>-name</c> or <c>-sname</c> is specified. Otherwise, + epmd is not started even if <c>-start_epmd true</c> is given.</p> + + <p>Note that a distributed node will fail to start if epmd is + not running.</p> </item> - <tag><c><![CDATA[-version]]></c>(emulator flag)</tag> + <tag><c><![CDATA[-version]]></c> (emulator flag)</tag> <item> - <p>Makes the emulator print out its version number. The same + <p>Makes the emulator print its version number. The same as <c><![CDATA[erl +V]]></c>.</p> </item> </taglist> @@ -461,122 +553,171 @@ <p><c><![CDATA[erl]]></c> invokes the code for the Erlang emulator (virtual machine), which supports the following flags:</p> <taglist> - <tag><marker id="async_thread_stack_size"><c><![CDATA[+a size]]></c></marker></tag> + <tag><marker id="async_thread_stack_size"/> + <c><![CDATA[+a size]]></c></tag> <item> <p>Suggested stack size, in kilowords, for threads in the - async-thread pool. Valid range is 16-8192 kilowords. The - default suggested stack size is 16 kilowords, i.e, 64 + async thread pool. Valid range is 16-8192 kilowords. The + default suggested stack size is 16 kilowords, that is, 64 kilobyte on 32-bit architectures. This small default size - has been chosen since the amount of async-threads might - be quite large. The default size is enough for drivers - delivered with Erlang/OTP, but might not be sufficiently - large for other dynamically linked in drivers that use the - <seealso marker="erl_driver#driver_async">driver_async()</seealso> - functionality. Note that the value passed is only a - suggestion, and it might even be ignored on some - platforms.</p> + has been chosen because the number of async threads can + be large. The default size is enough for drivers + delivered with Erlang/OTP, but might not be large + enough for other dynamically linked-in drivers that use the + <seealso marker="erl_driver#driver_async"> + <c>driver_async()</c></seealso> functionality. + Notice that the value passed is only a suggestion, + and it can even be ignored on some platforms.</p> </item> - <tag><marker id="async_thread_pool_size"><c><![CDATA[+A size]]></c></marker></tag> + <tag><marker id="async_thread_pool_size"/><c><![CDATA[+A size]]></c></tag> <item> - <p>Sets the number of threads in async thread pool, valid range - is 0-1024. If thread support is available, the default is 10.</p> + <p>Sets the number of threads in async thread pool. Valid range + is 0-1024. Defaults to 1.</p> </item> <tag><c><![CDATA[+B [c | d | i]]]></c></tag> <item> - <p>The <c><![CDATA[c]]></c> option makes <c><![CDATA[Ctrl-C]]></c> interrupt the current - shell instead of invoking the emulator break handler. - The <c><![CDATA[d]]></c> option (same as specifying <c><![CDATA[+B]]></c> without an - extra option) disables the break handler. The <c><![CDATA[i]]></c> option - makes the emulator ignore any break signal.</p> - <p>If the <c><![CDATA[c]]></c> option is used with <c><![CDATA[oldshell]]></c> on Unix, - <c><![CDATA[Ctrl-C]]></c> will restart the shell process rather than - interrupt it.</p> - <p>Note that on Windows, this flag is only applicable for - <c><![CDATA[werl]]></c>, not <c><![CDATA[erl]]></c> (<c><![CDATA[oldshell]]></c>). Note also that - <c><![CDATA[Ctrl-Break]]></c> is used instead of <c><![CDATA[Ctrl-C]]></c> on Windows.</p> - </item> - <tag><marker id="+c"><c><![CDATA[+c]]></c></marker></tag> - <item> - <p>Disable compensation for sudden changes of system time.</p> - <p>Normally, <c><![CDATA[erlang:now/0]]></c> will not immediately reflect - sudden changes in the system time, in order to keep timers - (including <c><![CDATA[receive-after]]></c>) working. Instead, the time - maintained by <c><![CDATA[erlang:now/0]]></c> is slowly adjusted towards - the new system time. (Slowly means in one percent adjustments; - if the time is off by one minute, the time will be adjusted - in 100 minutes.)</p> - <p>When the <c><![CDATA[+c]]></c> option is given, this slow adjustment - will not take place. Instead <c><![CDATA[erlang:now/0]]></c> will always - reflect the current system time. Note that timers are based - on <c><![CDATA[erlang:now/0]]></c>. If the system time jumps, timers - then time out at the wrong time.</p> - <p><em>NOTE</em>: You can check whether the adjustment is enabled or - disabled by calling - <seealso marker="erlang#system_info_tolerant_timeofday">erlang:system_info(tolerant_timeofday)</seealso>.</p> + <p>Option <c><![CDATA[c]]></c> makes <c><![CDATA[Ctrl-C]]></c> + interrupt the current shell instead of invoking the emulator break + handler. Option <c><![CDATA[d]]></c> (same as specifying + <c><![CDATA[+B]]></c> without an extra option) disables the break + handler. Option <c><![CDATA[i]]></c> makes the emulator ignore any + break signal.</p> + <p>If option <c><![CDATA[c]]></c> is used with + <c><![CDATA[oldshell]]></c> on Unix, <c><![CDATA[Ctrl-C]]></c> will + restart the shell process rather than interrupt it.</p> + <p>Notice that on Windows, this flag is only applicable for + <c><![CDATA[werl]]></c>, not <c><![CDATA[erl]]></c> + (<c><![CDATA[oldshell]]></c>). Notice also that + <c><![CDATA[Ctrl-Break]]></c> is used instead of + <c><![CDATA[Ctrl-C]]></c> on Windows.</p> + </item> + <tag><marker id="+c"/><c><![CDATA[+c true | false]]></c></tag> + <item> + <p>Enables or disables + <seealso marker="time_correction#Time_Correction">time + correction</seealso>:</p> + <taglist> + <tag><c>true</c></tag> + <item>Enables time correction. This is the default if + time correction is supported on the specific platform.</item> + <tag><c>false</c></tag> + <item>Disables time correction.</item> + </taglist> + <p>For backward compatibility, the boolean value can be omitted. + This is interpreted as <c>+c false</c>.</p> + </item> + <tag><marker id="+C_"/><c><![CDATA[+C no_time_warp | single_time_warp | + multi_time_warp]]></c></tag> + <item> + <p>Sets <seealso marker="time_correction#Time_Warp_Modes">time warp + mode</seealso>:</p> + <taglist> + <tag><c>no_time_warp</c></tag> + <item><seealso marker="time_correction#No_Time_Warp_Mode"> + No time warp mode</seealso> (the default)</item> + <tag><c>single_time_warp</c></tag> + <item><seealso marker="time_correction#Single_Time_Warp_Mode"> + Single time warp mode</seealso></item> + <tag><c>multi_time_warp</c></tag> + <item><seealso marker="time_correction#Multi_Time_Warp_Mode"> + Multi-time warp mode</seealso></item> + </taglist> </item> <tag><c><![CDATA[+d]]></c></tag> <item> <p>If the emulator detects an internal error (or runs out of memory), - it will by default generate both a crash dump and a core dump. - The core dump will, however, not be very useful since the content - of process heaps is destroyed by the crash dump generation.</p> - - <p>The <c>+d</c> option instructs the emulator to only produce a - core dump and no crash dump if an internal error is detected.</p> - - <p>Calling <c>erlang:halt/1</c> with a string argument will still - produce a crash dump. On Unix systems, sending an emulator process - a SIGUSR1 signal will also force a crash dump.</p> - </item> - <tag><marker id="+e"><c><![CDATA[+e Number]]></c></marker></tag> - <item> - <p>Set max number of ETS tables.</p> + it, by default, generates both a crash dump and a core dump. + The core dump is, however, not very useful as the content + of process heaps is destroyed by the crash dump generation.</p> + <p>Option <c>+d</c> instructs the emulator to produce only a + core dump and no crash dump if an internal error is detected.</p> + <p>Calling <seealso marker="erlang#halt/1"> + <c>erlang:halt/1</c></seealso> with a string argument still + produces a crash dump. On Unix systems, sending an emulator process + a <c>SIGUSR1</c> signal also forces a crash dump.</p> + </item> + <tag><marker id="+e"/><c><![CDATA[+e Number]]></c></tag> + <item> + <p>Sets the maximum number of ETS tables. This limit is + <seealso marker="stdlib:ets#max_ets_tables">partially obsolete</seealso>. + </p> </item> <tag><c><![CDATA[+ec]]></c></tag> <item> - <p>Force the <c>compressed</c> option on all ETS tables. - Only intended for test and evaluation.</p> + <p>Forces option <c>compressed</c> on all ETS tables. + Only intended for test and evaluation.</p> </item> - <tag><marker id="file_name_encoding"></marker><c><![CDATA[+fnl]]></c></tag> + <tag><marker id="file_name_encoding"></marker> + <c><![CDATA[+fnl]]></c></tag> <item> - <p>The VM works with file names as if they are encoded using the ISO-latin-1 encoding, disallowing Unicode characters with codepoints beyond 255.</p> - <p>See <seealso marker="stdlib:unicode_usage#unicode_file_names">STDLIB User's Guide</seealso> for more infomation about unicode file names. Note that this value also applies to command-line parameters and environment variables (see <seealso marker="stdlib:unicode_usage#unicode_in_environment_and_parameters">STDLIB User's Guide</seealso>).</p> + <p>The virtual machine works with filenames as if they are encoded + using the ISO Latin-1 encoding, disallowing Unicode characters with + code points > 255.</p> + <p>For more information about Unicode filenames, see section + <seealso marker="stdlib:unicode_usage#unicode_file_names">Unicode + Filenames</seealso> in the STDLIB User's Guide. Notice that + 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 Environment and Parameters</seealso> in the STDLIB + User's Guide).</p> </item> <tag><c><![CDATA[+fnu[{w|i|e}]]]></c></tag> <item> - <p>The VM works with file names as if they are encoded using - UTF-8 (or some other system specific Unicode encoding). This - is the default on operating systems that enforce Unicode - encoding, i.e. Windows and MacOS X.</p> - <p>The <c>+fnu</c> switch can be followed by <c>w</c>, - <c>i</c>, or <c>e</c> to control the way wrongly encoded file - names are to be reported. <c>w</c> means that a warning is - sent to the <c>error_logger</c> whenever a wrongly encoded - file name is "skipped" in directory listings, <c>i</c> means - that those wrongly encoded file names are silently ignored and - <c>e</c> means that the API function will return an error - whenever a wrongly encoded file (or directory) name is - encountered. <c>w</c> is the default. Note that - <c>file:read_link/1</c> will always return an error if the - link points to an invalid file name.</p> - <p>See <seealso marker="stdlib:unicode_usage#unicode_file_names">STDLIB User's Guide</seealso> for more infomation about unicode file names. Note that this value also applies to command-line parameters and environment variables (see <seealso marker="stdlib:unicode_usage#unicode_in_environment_and_parameters">STDLIB User's Guide</seealso>).</p> + <p>The virtual machine works with filenames as if they are encoded + using UTF-8 (or some other system-specific Unicode encoding). This is + the default on operating systems that enforce Unicode encoding, that + is, Windows and MacOS X.</p> + <p>The <c>+fnu</c> switch can be followed by <c>w</c>, <c>i</c>, or + <c>e</c> to control how wrongly encoded filenames are to be + reported:</p> + <list type="bulleted"> + <item> + <p><c>w</c> means that a warning is sent to the <c>error_logger</c> + whenever a wrongly encoded filename is "skipped" in directory + listings. This is the default.</p> + </item> + <item> + <p><c>i</c> means that those wrongly encoded filenames are silently + ignored.</p> + </item> + <item> + <p><c>e</c> means that the API function returns an error whenever a + wrongly encoded filename (or directory name) is encountered.</p> + </item> + </list> + <p>Notice that <seealso marker="kernel:file#read_link/1"> + <c>file:read_link/1</c></seealso> always returns an error if the link + points to an invalid filename.</p> + <p>For more information about Unicode filenames, see section + <seealso marker="stdlib:unicode_usage#unicode_file_names">Unicode + Filenames</seealso> in the STDLIB User's Guide. Notice that + 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 Environment and Parameters</seealso> in the STDLIB + User's Guide).</p> </item> <tag><c><![CDATA[+fna[{w|i|e}]]]></c></tag> <item> <p>Selection between <c>+fnl</c> and <c>+fnu</c> is done based - on the current locale settings in the OS, meaning that if you - have set your terminal for UTF-8 encoding, the filesystem is - expected to use the same encoding for file names. This is - default on all operating systems except MacOS X and - Windows.</p> - <p>The <c>+fna</c> switch can be followed by <c>w</c>, - <c>i</c>, or <c>e</c>. This will have effect if the locale - settings cause the behavior of <c>+fnu</c> to be selected. - See the description of <c>+fnu</c> above. If the locale - settings cause the behavior of <c>+fnl</c> to be selected, - then <c>w</c>, <c>i</c>, or <c>e</c> will not have any - effect.</p> - <p>See <seealso marker="stdlib:unicode_usage#unicode_file_names">STDLIB User's Guide</seealso> for more infomation about unicode file names. Note that this value also applies to command-line parameters and environment variables (see <seealso marker="stdlib:unicode_usage#unicode_in_environment_and_parameters">STDLIB User's Guide</seealso>).</p> + on the current locale settings in the OS. This means that if you + have set your terminal for UTF-8 encoding, the filesystem is + expected to use the same encoding for filenames. This is + default on all operating systems, except MacOS X and Windows.</p> + <p>The <c>+fna</c> switch can be followed by <c>w</c>, <c>i</c>, or + <c>e</c>. This has effect if the locale settings cause the behavior + of <c>+fnu</c> to be selected; see the description of <c>+fnu</c> + above. If the locale settings cause the behavior of <c>+fnl</c> to be + selected, then <c>w</c>, <c>i</c>, or <c>e</c> have no effect.</p> + <p>For more information about Unicode filenames, see section + <seealso marker="stdlib:unicode_usage#unicode_file_names">Unicode + Filenames</seealso> in the STDLIB User's Guide. Notice that + 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 Environment and Parameters</seealso> in the STDLIB + User's Guide).</p> </item> <tag><c><![CDATA[+hms Size]]></c></tag> <item> @@ -588,93 +729,118 @@ <p>Sets the default binary virtual heap size of processes to the size <c><![CDATA[Size]]></c>.</p> </item> + <tag><marker id="+hmax"/><c><![CDATA[+hmax Size]]></c></tag> + <item> + <p>Sets the default maximum heap size of processes to the size + <c><![CDATA[Size]]></c>. Defaults to <c>0</c>, which means that no + maximum heap size is used. For more information, see + <seealso marker="erlang#process_flag_max_heap_size"> + <c>process_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> + </item> + <tag><marker id="+hmaxel"/><c><![CDATA[+hmaxel true|false]]></c></tag> + <item> + <p>Sets whether to send an error logger message or not for processes + reaching the maximum heap size. Defaults to <c>true</c>. + For more information, see + <seealso marker="erlang#process_flag_max_heap_size"> + <c>process_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> + </item> + <tag><marker id="+hmaxk"/><c><![CDATA[+hmaxk true|false]]></c></tag> + <item> + <p>Sets whether to kill processes reaching the maximum heap size or not. + Default to <c>true</c>. For more information, see + <seealso marker="erlang#process_flag_max_heap_size"> + <c>process_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> + </item> <tag><c><![CDATA[+hpds Size]]></c></tag> <item> <p>Sets the initial process dictionary size of processes to the size <c><![CDATA[Size]]></c>.</p> </item> - <tag><c><![CDATA[+K true | false]]></c></tag> + <tag><marker id="+hmqd"/><c>+hmqd off_heap|on_heap</c></tag> + <item> + <p>Sets the default value for process flag <c>message_queue_data</c>. + Defaults to <c>on_heap</c>. If <c>+hmqd</c> is not + passed, <c>on_heap</c> will be the default. For more information, see + <seealso marker="erlang#process_flag_message_queue_data"> + <c>process_flag(message_queue_data, MQD)</c></seealso>.</p> + </item> + <tag><marker id="+IOp"/><c>+IOp PollSets</c></tag> + <item> + <p>Sets the number of IO pollsets to use when polling for I/O. + This option is only used on platforms that support concurrent + updates of a pollset, otherwise the same number of pollsets + are used as IO poll threads. + The default is 1. + </p> + </item> + <tag><marker id="+IOt"/><c>+IOt PollThreads</c></tag> + <item> + <p>Sets the number of IO poll threads to use when polling for I/O. + The maximum number of poll threads allowed is 1024. The default is 1. + </p> + <p>A good way to check if more IO poll threads are needed is to use + <seealso marker="runtime_tools:msacc">microstate accounting</seealso> + and see what the load of the IO poll thread is. If it is high it could + be a good idea to add more threads.</p> + </item> + <tag><marker id="+IOPp"/><c>+IOPp PollSetsPercentage</c></tag> <item> - <p>Enables or disables the kernel poll functionality if - the emulator supports it. Default is <c><![CDATA[false]]></c> (disabled). - If the emulator does not support kernel poll, and - the <c><![CDATA[+K]]></c> flag is passed to the emulator, a warning is - issued at startup.</p> + <p>Similar to <seealso marker="#+IOp"><c>+IOp</c></seealso> but uses + percentages to set the number of IO pollsets to create, based on the + number of poll threads configured. If both <c>+IOPp</c> and <c>+IOp</c> + are used, <c>+IOPp</c> is ignored. + </p> + </item> + <tag><marker id="+IOPt"/><c>+IOPt PollThreadsPercentage</c></tag> + <item> + <p>Similar to <seealso marker="#+IOt"><c>+IOt</c></seealso> but uses + percentages to set the number of IO poll threads to create, based on + the number of schedulers configured. If both <c>+IOPt</c> and + <c>+IOt</c> are used, <c>+IOPt</c> is ignored. + </p> </item> <tag><c><![CDATA[+l]]></c></tag> <item> - <p>Enables auto load tracing, displaying info while loading + <p>Enables autoload tracing, displaying information while loading code.</p> </item> <tag><c><![CDATA[+L]]></c></tag> <item> - <p>Don't load information about source file names and line numbers. - This will save some memory, but exceptions will not contain - information about the file names and line numbers. - </p> + <p>Prevents loading information about source filenames and line + numbers. This saves some memory, but exceptions do not contain + information about the filenames and line numbers.</p> </item> - <tag><marker id="erts_alloc"><c><![CDATA[+MFlag Value]]></c></marker></tag> - <item> - <p>Memory allocator specific flags, see - <seealso marker="erts_alloc">erts_alloc(3)</seealso> for - further information.</p> - </item> - <tag><marker id="+n"/><c><![CDATA[+n Behavior]]></c></tag> - <item> - <p>Control behavior of signals to ports.</p> - <p>As of OTP-R16 signals to ports are truly asynchronously - delivered. Note that signals always have been documented as - asynchronous. The underlying implementation has, however, - previously delivered these signals synchronously. Correctly - written Erlang programs should be able to handle this without - any issues. Bugs in existing Erlang programs that make false - assumptions about signals to ports may, however, be tricky to - find. This switch has been introduced in order to at least - make it easier to compare behaviors during a transition period. - Note that <em>this flag is deprecated</em> as of its - introduction, and is scheduled for removal in OTP-R17. - <c>Behavior</c> should be one of the following characters:</p> - <taglist> - <tag><c>d</c></tag> - <item>The default. Asynchronous signals. A process that sends - a signal to a port may continue execution before the signal - has been delivered to the port.</item> - <tag><c>s</c></tag> - <item>Synchronous signals. A processes that sends a signal - to a port will not continue execution until the signal has - been delivered. Should <em>only</em> be used for testing and - debugging.</item> - <tag><c>a</c></tag> - <item>Asynchronous signals. As the default, but a processes - that sends a signal will even more frequently continue - execution before the signal has been delivered to the - port. Should <em>only</em> be used for testing and - debugging.</item> - </taglist> - </item> - <tag><marker id="+pc"/><marker id="printable_character_range"><c><![CDATA[+pc Range]]></c></marker></tag> - <item> - <p>Sets the range of characters that the system will consider printable in heuristic detection of strings. This typically affects the shell, debugger and io:format functions (when ~tp is used in the format string).</p> - <p>Currently two values for the <c>Range</c> are supported: - <taglist> - <tag><c>latin1</c></tag> <item>The default. Only characters - in the ISO-latin-1 range can be considered printable, which means - that a character with a code point > 255 will never be - considered printable and that lists containing such - characters will be displayed as lists of integers rather - than text strings by tools.</item> - <tag><c>unicode</c></tag> - <item>All printable Unicode characters are considered when - determining if a list of integers is to be displayed in - string syntax. This may give unexpected results if for - example your font does not cover all Unicode - characters.</item> - </taglist> - </p> - <p>Se also <seealso marker="stdlib:io#printable_range/0"> - io:printable_range/0</seealso>.</p> + <tag><marker id="erts_alloc"/><c><![CDATA[+MFlag Value]]></c></tag> + <item> + <p>Memory allocator-specific flags. For more information, see + <seealso marker="erts_alloc"><c>erts_alloc(3)</c></seealso>.</p> </item> - <tag><marker id="+P"/><marker id="max_processes"><c><![CDATA[+P Number|legacy]]></c></marker></tag> + <tag><marker id="+pc"/><marker id="printable_character_range"/> + <c><![CDATA[+pc Range]]></c></tag> + <item> + <p>Sets the range of characters that the system considers printable in + heuristic detection of strings. This typically affects the shell, + debugger, and <c>io:format</c> functions (when <c>~tp</c> is used in + the format string).</p> + <p>Two values are supported for <c>Range</c>:</p> + <taglist> + <tag><c>latin1</c></tag> + <item>The default. Only characters in the ISO Latin-1 range can be + considered printable. This means that a character with a code point + > 255 is never considered printable and that lists containing + such characters are displayed as lists of integers rather than text + strings by tools.</item> + <tag><c>unicode</c></tag> + <item>All printable Unicode characters are considered when + determining if a list of integers is to be displayed in + string syntax. This can give unexpected results if, for + example, your font does not cover all Unicode characters.</item> + </taglist> + <p>See also <seealso marker="stdlib:io#printable_range/0"> + <c>io:printable_range/0</c></seealso> in STDLIB.</p> + </item> + <tag><marker id="+P"/><marker id="max_processes"/><c><![CDATA[+P Number]]></c></tag> <item> <p>Sets the maximum number of simultaneously existing processes for this system if a <c>Number</c> is passed as value. Valid range for @@ -686,15 +852,8 @@ checked by calling <seealso marker="erlang#system_info_process_limit">erlang:system_info(process_limit)</seealso>.</p> <p>The default value is <c>262144</c></p> - <p>If <c>legacy</c> is passed as value, the legacy algorithm for - allocation of process identifiers will be used. Using the legacy - algorithm, identifiers will be allocated in a strictly increasing - fashion until largest possible identifier has been reached. Note that - this algorithm suffers from performance issues and can under certain - circumstances be extremely expensive. The legacy algoritm is deprecated, - and the <c>legacy</c> option is scheduled for removal in OTP-R18.</p> </item> - <tag><marker id="+Q"/><marker id="max_ports"><c><![CDATA[+Q Number|legacy]]></c></marker></tag> + <tag><marker id="+Q"/><marker id="max_ports"/><c><![CDATA[+Q Number]]></c></tag> <item> <p>Sets the maximum number of simultaneously existing ports for this system if a Number is passed as value. Valid range for <c>Number</c> @@ -711,403 +870,421 @@ than <c>65536</c>, the chosen value will increased to a value larger or equal to the maximum amount of file descriptors that can be opened.</p> - <p>On Windows the default value is set to <c>8196</c> because the + <p>On Windows the default value is set to <c>8196</c> because the normal OS limitations are set higher than most machines can handle.</p> - <p>Previously the environment variable <c>ERL_MAX_PORTS</c> was used - for setting the maximum number of simultaneously existing ports. This - environment variable is deprecated, and scheduled for removal in - OTP-R17, but can still be used.</p> - <p>If <c>legacy</c> is passed as value, the legacy algorithm for - allocation of port identifiers will be used. Using the legacy - algorithm, identifiers will be allocated in a strictly increasing - fashion until largest possible identifier has been reached. Note that - this algorithm suffers from performance issues and can under certain - circumstances be extremely expensive. The legacy algoritm is deprecated, - and the <c>legacy</c> option is scheduled for removal in OTP-R18.</p> - </item> - <tag><marker id="compat_rel"><c><![CDATA[+R ReleaseNumber]]></c></marker></tag> + </item> + <tag><marker id="compat_rel"/><c><![CDATA[+R ReleaseNumber]]></c></tag> <item> <p>Sets the compatibility mode.</p> - <p>The distribution mechanism is not backwards compatible by - default. This flags sets the emulator in compatibility mode + <p>The distribution mechanism is not backward compatible by + default. This flag sets the emulator in compatibility mode with an earlier Erlang/OTP release <c><![CDATA[ReleaseNumber]]></c>. The release number must be in the range <c><![CDATA[<current release>-2..<current release>]]></c>. This - limits the emulator, making it possible for it to communicate - with Erlang nodes (as well as C- and Java nodes) running that - earlier release.</p> - <p>Note: Make sure all nodes (Erlang-, C-, and Java nodes) of - a distributed Erlang system is of the same Erlang/OTP release, - or from two different Erlang/OTP releases X and Y, where - <em>all</em> Y nodes have compatibility mode X.</p> + limits the emulator, making it possible for it to communicate + with Erlang nodes (as well as C- and Java nodes) running that + earlier release.</p> + <note> + <p>Ensure that all nodes (Erlang-, C-, and Java nodes) of + a distributed Erlang system is of the same Erlang/OTP release, + or from two different Erlang/OTP releases X and Y, where + <em>all</em> Y nodes have compatibility mode X.</p> + </note> </item> <tag><c><![CDATA[+r]]></c></tag> <item> - <p>Force ets memory block to be moved on realloc.</p> - </item> - <tag><marker id="+rg"><c><![CDATA[+rg ReaderGroupsLimit]]></c></marker></tag> - <item> - <p>Limits the amount of reader groups used by read/write locks - optimized for read operations in the Erlang runtime system. By - default the reader groups limit equals 64.</p> - <p>When the amount of schedulers is less than or equal to the reader - groups limit, each scheduler has its own reader group. When the - amount of schedulers is larger than the reader groups limit, - schedulers share reader groups. Shared reader groups degrades - read lock and read unlock performance while a large amount of - reader groups degrades write lock performance, so the limit is a - tradeoff between performance for read operations and performance - for write operations. Each reader group currently consumes 64 byte - in each read/write lock. Also note that a runtime system using - shared reader groups benefits from <seealso marker="#+sbt">binding - schedulers to logical processors</seealso>, since the reader groups - are distributed better between schedulers.</p> - </item> - <tag><marker id="+S"><c><![CDATA[+S Schedulers:SchedulerOnline]]></c></marker></tag> - <item> - <p>Sets the number of scheduler threads to create and scheduler - threads to set online when SMP support has been enabled. The maximum for - both values is 1024. If the Erlang runtime system is able to determine the - amount of logical processors configured and logical processors available, - <c>Schedulers</c> will default to logical processors configured, and - <c>SchedulersOnline</c> will default to logical processors available; - otherwise, the default values will be 1. <c>Schedulers</c> may be omitted - if <c>:SchedulerOnline</c> is not and vice versa. The number of schedulers - online can be changed at run time via - <seealso marker="erlang#system_flag_schedulers_online">erlang:system_flag(schedulers_online, SchedulersOnline)</seealso>. - </p> - <p>If <c>Schedulers</c> or <c>SchedulersOnline</c> is specified as a - negative number, the value is subtracted from the default number of - logical processors configured or logical processors available, respectively. - </p> - <p>Specifying the value 0 for <c>Schedulers</c> or <c>SchedulersOnline</c> - resets the number of scheduler threads or scheduler threads online respectively - to its default value. - </p> - <p>This option is ignored if the emulator doesn't have - SMP support enabled (see the <seealso marker="#smp">-smp</seealso> - flag).</p> - </item> - <tag><marker id="+SP"><c><![CDATA[+SP SchedulersPercentage:SchedulersOnlinePercentage]]></c></marker></tag> - <item> - <p>Similar to <seealso marker="#+S">+S</seealso> but uses percentages to set the - number of scheduler threads to create, based on logical processors configured, - and scheduler threads to set online, based on logical processors available, when - SMP support has been enabled. Specified values must be greater than 0. For example, - <c>+SP 50:25</c> sets the number of scheduler threads to 50% of the logical processors - configured and the number of scheduler threads online to 25% of the logical processors available. - <c>SchedulersPercentage</c> may be omitted if <c>:SchedulersOnlinePercentage</c> is - not and vice versa. The number of schedulers online can be changed at run time via - <seealso marker="erlang#system_flag_schedulers_online">erlang:system_flag(schedulers_online, SchedulersOnline)</seealso>. - </p> - <p>This option interacts with <seealso marker="#+S">+S</seealso> settings. - For example, on a system with 8 logical cores configured and 8 logical cores - available, the combination of the options <c>+S 4:4 +SP 50:25</c> (in either order) - results in 2 scheduler threads (50% of 4) and 1 scheduler thread online (25% of 4). - </p> - <p>This option is ignored if the emulator doesn't have - SMP support enabled (see the <seealso marker="#smp">-smp</seealso> - flag).</p> - </item> - <tag><marker id="+SDcpu"><c><![CDATA[+SDcpu DirtyCPUSchedulers:DirtyCPUSchedulersOnline]]></c></marker></tag> - <item> - <p>Sets the number of dirty CPU scheduler threads to create and dirty - CPU scheduler threads to set online when threading support has been - enabled. The maximum for both values is 1024, and each value is further - limited by the settings for normal schedulers: the number of dirty CPU - scheduler threads created cannot exceed the number of normal scheduler - threads created, and the number of dirty CPU scheduler threads online - cannot exceed the number of normal scheduler threads online (see the - <seealso marker="#+S">+S</seealso> and <seealso marker="#+SP">+SP</seealso> - flags for more details). By default, the number of dirty CPU scheduler - threads created equals the number of normal scheduler threads created, - and the number of dirty CPU scheduler threads online equals the number - of normal scheduler threads online. <c>DirtyCPUSchedulers</c> may be - omitted if <c>:DirtyCPUSchedulersOnline</c> is not and vice versa. The - number of dirty CPU schedulers online can be changed at run time via - <seealso marker="erlang#system_flag_dirty_cpu_schedulers_online">erlang:system_flag(dirty_cpu_schedulers_online, DirtyCPUSchedulersOnline)</seealso>. - </p> - <p>This option is ignored if the emulator doesn't have threading support - enabled. Currently, <em>this option is experimental</em> and is supported only - if the emulator was configured and built with support for dirty schedulers - enabled (it's disabled by default). - </p> - </item> - <tag><marker id="+SDPcpu"><c><![CDATA[+SDPcpu DirtyCPUSchedulersPercentage:DirtyCPUSchedulersOnlinePercentage]]></c></marker></tag> - <item> - <p>Similar to <seealso marker="#+SDcpu">+SDcpu</seealso> but uses percentages to set the - number of dirty CPU scheduler threads to create and number of dirty CPU scheduler threads - to set online when threading support has been enabled. Specified values must be greater - than 0. For example, <c>+SDPcpu 50:25</c> sets the number of dirty CPU scheduler threads - to 50% of the logical processors configured and the number of dirty CPU scheduler threads - online to 25% of the logical processors available. <c>DirtyCPUSchedulersPercentage</c> may - be omitted if <c>:DirtyCPUSchedulersOnlinePercentage</c> is not and vice versa. The - number of dirty CPU schedulers online can be changed at run time via - <seealso marker="erlang#system_flag_dirty_cpu_schedulers_online">erlang:system_flag(dirty_cpu_schedulers_online, DirtyCPUSchedulersOnline)</seealso>. - </p> - <p>This option interacts with <seealso marker="#+SDcpu">+SDcpu</seealso> settings. - For example, on a system with 8 logical cores configured and 8 logical cores available, - the combination of the options <c>+SDcpu 4:4 +SDPcpu 50:25</c> (in either order) results - in 2 dirty CPU scheduler threads (50% of 4) and 1 dirty CPU scheduler thread online (25% of 4). - </p> - <p>This option is ignored if the emulator doesn't have threading support - enabled. Currently, <em>this option is experimental</em> and is supported only - if the emulator was configured and built with support for dirty schedulers - enabled (it's disabled by default). - </p> - </item> - <tag><marker id="+SDio"><c><![CDATA[+SDio IOSchedulers]]></c></marker></tag> - <item> - <p>Sets the number of dirty I/O scheduler threads to create when threading - support has been enabled. The valid range is 0-1024. By default, the number - of dirty I/O scheduler threads created is 10, same as the default number of - threads in the <seealso marker="#async_thread_pool_size">async thread pool - </seealso>. - </p> - <p>This option is ignored if the emulator doesn't have threading support - enabled. Currently, <em>this option is experimental</em> and is supported only - if the emulator was configured and built with support for dirty schedulers - enabled (it's disabled by default). - </p> + <p>Forces ETS memory block to be moved on realloc.</p> + </item> + <tag><marker id="+rg"/><c><![CDATA[+rg ReaderGroupsLimit]]></c></tag> + <item> + <p>Limits the number of reader groups used by read/write locks + optimized for read operations in the Erlang runtime system. By + default the reader groups limit is 64.</p> + <p>When the number of schedulers is less than or equal to the reader + groups limit, each scheduler has its own reader group. When the + number of schedulers is larger than the reader groups limit, + schedulers share reader groups. Shared reader groups degrade + read lock and read unlock performance while many + reader groups degrade write lock performance. So, the limit is a + tradeoff between performance for read operations and performance + for write operations. Each reader group consumes 64 byte + in each read/write lock.</p> + <p>Notice that a runtime system using shared reader groups benefits from + <seealso marker="#+sbt">binding schedulers to logical + processors</seealso>, as the reader groups are distributed better + between schedulers.</p> + </item> + <tag><marker id="+S"/> + <c><![CDATA[+S Schedulers:SchedulerOnline]]></c></tag> + <item> + <p>Sets the number of scheduler threads to create and scheduler threads + to set online. The maximum for both + values is 1024. If the Erlang runtime system is able to determine the + number of logical processors configured and logical processors + available, <c>Schedulers</c> defaults to logical processors + configured, and <c>SchedulersOnline</c> defaults to logical processors + available; otherwise the default values are 1. <c>Schedulers</c> can + be omitted if <c>:SchedulerOnline</c> is not and conversely. The + number of schedulers online can be changed at runtime through + <seealso marker="erlang#system_flag_schedulers_online"> + <c>erlang:system_flag(schedulers_online, + SchedulersOnline)</c></seealso>.</p> + <p>If <c>Schedulers</c> or <c>SchedulersOnline</c> is specified as a + negative number, the value is subtracted from the default number of + logical processors configured or logical processors available, + respectively.</p> + <p>Specifying value <c>0</c> for <c>Schedulers</c> or + <c>SchedulersOnline</c> resets the number of scheduler threads or + scheduler threads online, respectively, to its default value.</p> + </item> + <tag><marker id="+SP"/><c><![CDATA[+SP + SchedulersPercentage:SchedulersOnlinePercentage]]></c></tag> + <item> + <p>Similar to <seealso marker="#+S"><c>+S</c></seealso> but uses + percentages to set the number of scheduler threads to create, based + on logical processors configured, and scheduler threads to set online, + based on logical processors available. + Specified values must be > 0. For example, + <c>+SP 50:25</c> sets the number of scheduler threads to 50% of the + logical processors configured, and the number of scheduler threads + online to 25% of the logical processors available. + <c>SchedulersPercentage</c> can be omitted if + <c>:SchedulersOnlinePercentage</c> is not and conversely. The number + of schedulers online can be changed at runtime through + <seealso marker="erlang#system_flag_schedulers_online"> + <c>erlang:system_flag(schedulers_online, + SchedulersOnline)</c></seealso>.</p> + <p>This option interacts with <seealso marker="#+S"><c>+S</c></seealso> + settings. For example, on a system with 8 logical cores configured + and 8 logical cores available, the combination of the options + <c>+S 4:4 +SP 50:25</c> (in either order) results in 2 scheduler + threads (50% of 4) and 1 scheduler thread online (25% of 4).</p> + </item> + <tag><marker id="+SDcpu"/><c><![CDATA[+SDcpu + DirtyCPUSchedulers:DirtyCPUSchedulersOnline]]></c></tag> + <item> + <p>Sets the number of dirty CPU scheduler threads to create and dirty + CPU scheduler threads to set online. + The maximum for both values is 1024, and each value is + further limited by the settings for normal schedulers:</p> + <list type="bulleted"> + <item>The number of dirty CPU scheduler threads created cannot exceed + the number of normal scheduler threads created.</item> + <item>The number of dirty CPU scheduler threads online cannot exceed + the number of normal scheduler threads online.</item> + </list> + <p>For details, see the <seealso marker="#+S"><c>+S</c></seealso> and + <seealso marker="#+SP"><c>+SP</c></seealso>. By default, the number + of dirty CPU scheduler threads created equals the number of normal + scheduler threads created, and the number of dirty CPU scheduler + threads online equals the number of normal scheduler threads online. + <c>DirtyCPUSchedulers</c> can be omitted if + <c>:DirtyCPUSchedulersOnline</c> is not and conversely. The number of + dirty CPU schedulers online can be changed at runtime through + <seealso marker="erlang#system_flag_dirty_cpu_schedulers_online"> + <c>erlang:system_flag(dirty_cpu_schedulers_online, + DirtyCPUSchedulersOnline)</c></seealso>.</p> + <p>The amount of dirty CPU schedulers is limited by the amount of + normal schedulers in order to limit the effect on processes + executing on ordinary schedulers. If the amount of dirty CPU + schedulers was allowed to be unlimited, dirty CPU bound jobs would + potentially starve normal jobs.</p> + </item> + <tag><marker id="+SDPcpu"/><c><![CDATA[+SDPcpu + DirtyCPUSchedulersPercentage:DirtyCPUSchedulersOnlinePercentage]]></c></tag> + <item> + <p>Similar to <seealso marker="#+SDcpu"><c>+SDcpu</c></seealso> but + uses percentages to set the number of dirty CPU scheduler threads to + create and the number of dirty CPU scheduler threads to set online. + Specified values must be + > 0. For example, <c>+SDPcpu 50:25</c> sets the number of dirty + CPU scheduler threads to 50% of the logical processors configured + and the number of dirty CPU scheduler threads online to 25% of the + logical processors available. <c>DirtyCPUSchedulersPercentage</c> can + be omitted if <c>:DirtyCPUSchedulersOnlinePercentage</c> is not and + conversely. The number of dirty CPU schedulers online can be changed + at runtime through + <seealso marker="erlang#system_flag_dirty_cpu_schedulers_online"> + <c>erlang:system_flag(dirty_cpu_schedulers_online, + DirtyCPUSchedulersOnline)</c></seealso>.</p> + <p>This option interacts with <seealso + marker="#+SDcpu"><c>+SDcpu</c></seealso> settings. For example, on a + system with 8 logical cores configured and 8 logical cores available, + the combination of the options <c>+SDcpu 4:4 +SDPcpu 50:25</c> (in + either order) results in 2 dirty CPU scheduler threads (50% of 4) and + 1 dirty CPU scheduler thread online (25% of 4).</p> + </item> + <tag><marker id="+SDio"/><c><![CDATA[+SDio DirtyIOSchedulers]]></c></tag> + <item> + <p>Sets the number of dirty I/O scheduler threads to create. + Valid range is 0-1024. By + default, the number of dirty I/O scheduler threads created is 10, + same as the default number of threads in the <seealso + marker="#async_thread_pool_size">async thread pool</seealso>.</p> + <p>The amount of dirty IO schedulers is not limited by the amount of + normal schedulers <seealso marker="#+SDcpu">like the amount of + dirty CPU schedulers</seealso>. This since only I/O bound work is + expected to execute on dirty I/O schedulers. If the user should schedule CPU + bound jobs on dirty I/O schedulers, these jobs might starve ordinary + jobs executing on ordinary schedulers.</p> </item> <tag><c><![CDATA[+sFlag Value]]></c></tag> <item> <p>Scheduling specific flags.</p> <taglist> - <tag><marker id="+sbt"><c>+sbt BindType</c></marker></tag> + <tag><marker id="+sbt"/><c>+sbt BindType</c></tag> <item> - <p>Set scheduler bind type.</p> - <p>Schedulers can also be bound using the - <seealso marker="#+stbt">+stbt</seealso> flag. The only difference - between these two flags is how the following errors are handled:</p> - <list> - <item>Binding of schedulers is not supported on the specific - platform.</item> - <item>No available CPU topology. That is the runtime system - was not able to automatically detected the CPU topology, and - no <seealso marker="#+sct">user defined CPU topology</seealso> - was set.</item> - </list> - <p>If any of these errors occur when <c>+sbt</c> has been passed, - the runtime system will print an error message, and refuse to - start. If any of these errors occur when <c>+stbt</c> has been - passed, the runtime system will silently ignore the error, and - start up using unbound schedulers.</p> - <p>Currently valid <c>BindType</c>s: - </p> - <taglist> - <tag><c>u</c></tag> - <item> - <p><c>unbound</c> - Schedulers will not be bound to logical - processors, i.e., the operating system decides where the - scheduler threads execute, and when to migrate them. This is - the default.</p> + <p>Sets scheduler bind type.</p> + <p>Schedulers can also be bound using flag + <seealso marker="#+stbt"><c>+stbt</c></seealso>. The only + difference between these two flags is how the following errors + are handled:</p> + <list type="bulleted"> + <item>Binding of schedulers is not supported on the specific + platform.</item> + <item>No available CPU topology. That is, the runtime system was + not able to detect the CPU topology automatically, and no + <seealso marker="#+sct">user-defined CPU topology</seealso> + was set.</item> + </list> + <p>If any of these errors occur when <c>+sbt</c> has been passed, + the runtime system prints an error message, and refuses to + start. If any of these errors occur when <c>+stbt</c> has been + passed, the runtime system silently ignores the error, and + start up using unbound schedulers.</p> + <p>Valid <c>BindType</c>s:</p> + <taglist> + <tag><c>u</c></tag> + <item><c>unbound</c> - Schedulers are not bound to logical + processors, that is, the operating system decides where the + scheduler threads execute, and when to migrate them. This is + the default. </item> - <tag><c>ns</c></tag> - <item> - <p><c>no_spread</c> - Schedulers with close scheduler - identifiers will be bound as close as possible in hardware.</p> + <tag><c>ns</c></tag> + <item><c>no_spread</c> - Schedulers with close scheduler + identifiers are bound as close as possible in hardware. </item> - <tag><c>ts</c></tag> - <item> - <p><c>thread_spread</c> - Thread refers to hardware threads - (e.g. Intel's hyper-threads). Schedulers with low scheduler - identifiers, will be bound to the first hardware thread of - each core, then schedulers with higher scheduler identifiers - will be bound to the second hardware thread of each core, - etc.</p> + <tag><c>ts</c></tag> + <item><c>thread_spread</c> - Thread refers to hardware threads + (such as Intel's hyper-threads). Schedulers with low scheduler + identifiers, are bound to the first hardware thread of + each core, then schedulers with higher scheduler identifiers + are bound to the second hardware thread of each core,and so on. </item> - <tag><c>ps</c></tag> - <item> - <p><c>processor_spread</c> - Schedulers will be spread like - <c>thread_spread</c>, but also over physical processor chips.</p> + <tag><c>ps</c></tag> + <item><c>processor_spread</c> - Schedulers are spread like + <c>thread_spread</c>, but also over physical processor chips. </item> - <tag><c>s</c></tag> - <item> - <p><c>spread</c> - Schedulers will be spread as much as - possible.</p> + <tag><c>s</c></tag> + <item><c>spread</c> - Schedulers are spread as much as possible. </item> - <tag><c>nnts</c></tag> - <item> - <p><c>no_node_thread_spread</c> - Like <c>thread_spread</c>, - but if multiple NUMA (Non-Uniform Memory Access) nodes exists, - schedulers will be spread over one NUMA node at a time, - i.e., all logical processors of one NUMA node will be bound - to schedulers in sequence.</p> + <tag><c>nnts</c></tag> + <item><c>no_node_thread_spread</c> - Like <c>thread_spread</c>, + but if multiple Non-Uniform Memory Access (NUMA) nodes exist, + schedulers are spread over one NUMA node at a time, + that is, all logical processors of one NUMA node are bound + to schedulers in sequence. </item> - <tag><c>nnps</c></tag> - <item> - <p><c>no_node_processor_spread</c> - Like - <c>processor_spread</c>, but if multiple NUMA nodes exists, - schedulers will be spread over one NUMA node at a time, i.e., - all logical processors of one NUMA node will be bound to - schedulers in sequence.</p> + <tag><c>nnps</c></tag> + <item><c>no_node_processor_spread</c> - Like + <c>processor_spread</c>, but if multiple NUMA nodes exist, + schedulers are spread over one NUMA node at a time, that is, + all logical processors of one NUMA node are bound to + schedulers in sequence. </item> - <tag><c>tnnps</c></tag> - <item> - <p><c>thread_no_node_processor_spread</c> - A combination of - <c>thread_spread</c>, and <c>no_node_processor_spread</c>. - Schedulers will be spread over hardware threads across NUMA - nodes, but schedulers will only be spread over processors - internally in one NUMA node at a time.</p> + <tag><c>tnnps</c></tag> + <item><c>thread_no_node_processor_spread</c> - A combination of + <c>thread_spread</c>, and <c>no_node_processor_spread</c>. + Schedulers are spread over hardware threads across NUMA + nodes, but schedulers are only spread over processors + internally in one NUMA node at a time. </item> - <tag><c>db</c></tag> - <item> - <p><c>default_bind</c> - Binds schedulers the default way. - Currently the default is <c>thread_no_node_processor_spread</c> - (which might change in the future).</p> + <tag><c>db</c></tag> + <item><c>default_bind</c> - Binds schedulers the default way. + Defaults to <c>thread_no_node_processor_spread</c> + (which can change in the future). </item> - </taglist> - <p>Binding of schedulers is currently only supported on newer - Linux, Solaris, FreeBSD, and Windows systems.</p> - <p>If no CPU topology is available when the <c>+sbt</c> flag - is processed and <c>BindType</c> is any other type than - <c>u</c>, the runtime system will fail to start. CPU - topology can be defined using the - <seealso marker="#+sct">+sct</seealso> flag. Note - that the <c>+sct</c> flag may have to be passed before the - <c>+sbt</c> flag on the command line (in case no CPU topology - has been automatically detected).</p> - <p>The runtime system will by default <em>not</em> bind schedulers - to logical processors. - </p> - <p><em>NOTE:</em> If the Erlang runtime system is the only operating system - process that binds threads to logical processors, this - improves the performance of the runtime system. However, - if other operating system processes (as for example - another Erlang runtime system) also bind threads to - logical processors, there might be a performance penalty - instead. In some cases this performance penalty might be - severe. If this is the case, you are advised to not - bind the schedulers.</p> + </taglist> + <p>Binding of schedulers is only supported on newer + Linux, Solaris, FreeBSD, and Windows systems.</p> + <p>If no CPU topology is available when flag <c>+sbt</c> + is processed and <c>BindType</c> is any other type than + <c>u</c>, the runtime system fails to start. CPU + topology can be defined using flag + <seealso marker="#+sct"><c>+sct</c></seealso>. Notice + that flag <c>+sct</c> can have to be passed before flag + <c>+sbt</c> on the command line (if no CPU topology + has been automatically detected).</p> + <p>The runtime system does by default <em>not</em> bind schedulers + to logical processors.</p> + <note> + <p>If the Erlang runtime system is the only operating system + process that binds threads to logical processors, this + improves the performance of the runtime system. However, + if other operating system processes (for example + another Erlang runtime system) also bind threads to + logical processors, there can be a performance penalty + instead. This performance penalty can sometimes be + severe. If so, you are advised not to + bind the schedulers.</p> + </note> <p>How schedulers are bound matters. For example, in - situations when there are fewer running processes than - schedulers online, the runtime system tries to migrate - processes to schedulers with low scheduler identifiers. - The more the schedulers are spread over the hardware, - the more resources will be available to the runtime - system in such situations. - </p> - <p> - <em>NOTE:</em> If a scheduler fails to bind, this - will often be silently ignored. This since it isn't always - possible to verify valid logical processor identifiers. If - an error is reported, it will be reported to the - <c>error_logger</c>. If you want to verify that the - schedulers actually have bound as requested, call - <seealso marker="erlang#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>. - </p> + situations when there are fewer running processes than + schedulers online, the runtime system tries to migrate + processes to schedulers with low scheduler identifiers. + The more the schedulers are spread over the hardware, + the more resources are available to the runtime + system in such situations.</p> + <note> + <p>If a scheduler fails to bind, this is + often silently ignored, as it is not always + possible to verify valid logical processor identifiers. If + an error is reported, it is reported to the + <c>error_logger</c>. If you want to verify that the + schedulers have bound as requested, call + <seealso marker="erlang#system_info_scheduler_bindings"> + <c>erlang:system_info(scheduler_bindings)</c></seealso>.</p> + </note> </item> - <tag><marker id="+sbwt"><c>+sbwt none|very_short|short|medium|long|very_long</c></marker></tag> - <item> - <p>Set scheduler busy wait threshold. Default is <c>medium</c>. - The threshold determines how long schedulers should busy - wait when running out of work before going to sleep. - </p> - <p><em>NOTE:</em> This flag may be removed or changed at any time - without prior notice. - </p> - </item> - <tag><marker id="+scl"><c>+scl true|false</c></marker></tag> + <tag><marker id="+sbwt"/> + <c>+sbwt none|very_short|short|medium|long|very_long</c></tag> + <item> + <p>Sets scheduler busy wait threshold. Defaults to <c>medium</c>. + The threshold determines how long schedulers are to busy + wait when running out of work before going to sleep.</p> + <note> + <p>This flag can be removed or changed at any time + without prior notice.</p> + </note> + </item> + <tag><marker id="+sbwtdcpu"/> + <c>+sbwtdcpu none|very_short|short|medium|long|very_long</c></tag> + <item> + <p>As <seealso marker="#+sbwt"><c>+sbwt</c></seealso> but affects + dirty CPU schedulers. Defaults to <c>short</c>.</p> + <note> + <p>This flag can be removed or changed at any time + without prior notice.</p> + </note> + </item> + <tag><marker id="+sbwtdio"/> + <c>+sbwtdio none|very_short|short|medium|long|very_long</c></tag> + <item> + <p>As <seealso marker="#+sbwt"><c>+sbwt</c></seealso> but affects + dirty IO schedulers. Defaults to <c>short</c>.</p> + <note> + <p>This flag can be removed or changed at any time + without prior notice.</p> + </note> + </item> +<tag><marker id="+scl"/><c>+scl true|false</c></tag> <item> - <p>Enable or disable scheduler compaction of load. By default - scheduler compaction of load is enabled. When enabled, load - balancing will strive for a load distribution which causes - as many scheduler threads as possible to be fully loaded (i.e., - not run out of work). This is accomplished by migrating load - (e.g. runnable processes) into a smaller set of schedulers - when schedulers frequently run out of work. When disabled, - the frequency with which schedulers run out of work will - not be taken into account by the load balancing logic. - <br/> <c>+scl false</c> is similar to - <seealso marker="#+sub">+sub true</seealso> with the difference - that <c>+sub true</c> also will balance scheduler utilization - between schedulers. - </p> + <p>Enables or disables scheduler compaction of load. By default + scheduler compaction of load is enabled. When enabled, load + balancing strives for a load distribution, which causes + as many scheduler threads as possible to be fully loaded (that is, + not run out of work). This is accomplished by migrating load + (for example, runnable processes) into a smaller set of schedulers + when schedulers frequently run out of work. When disabled, + the frequency with which schedulers run out of work is + not taken into account by the load balancing logic.</p> + <p><c>+scl false</c> is similar to + <seealso marker="#+sub"><c>+sub true</c></seealso>, but + <c>+sub true</c> also balances scheduler utilization + between schedulers.</p> </item> - <tag><marker id="+sct"><c>+sct CpuTopology</c></marker></tag> + <tag><marker id="+sct"/><c>+sct CpuTopology</c></tag> <item> <list type="bulleted"> - <item><c><![CDATA[<Id> = integer(); when 0 =< <Id> =< 65535]]></c></item> + <item><c><![CDATA[<Id> = integer(); when 0 =< <Id> =< 65535]]></c> + </item> <item><c><![CDATA[<IdRange> = <Id>-<Id>]]></c></item> <item><c><![CDATA[<IdOrIdRange> = <Id> | <IdRange>]]></c></item> - <item><c><![CDATA[<IdList> = <IdOrIdRange>,<IdOrIdRange> | <IdOrIdRange>]]></c></item> + <item><c><![CDATA[<IdList> = <IdOrIdRange>,<IdOrIdRange> | + <IdOrIdRange>]]></c></item> <item><c><![CDATA[<LogicalIds> = L<IdList>]]></c></item> - <item><c><![CDATA[<ThreadIds> = T<IdList> | t<IdList>]]></c></item> + <item><c><![CDATA[<ThreadIds> = T<IdList> | t<IdList>]]></c> + </item> <item><c><![CDATA[<CoreIds> = C<IdList> | c<IdList>]]></c></item> - <item><c><![CDATA[<ProcessorIds> = P<IdList> | p<IdList>]]></c></item> + <item><c><![CDATA[<ProcessorIds> = P<IdList> | p<IdList>]]></c> + </item> <item><c><![CDATA[<NodeIds> = N<IdList> | n<IdList>]]></c></item> - <item><c><![CDATA[<IdDefs> = <LogicalIds><ThreadIds><CoreIds><ProcessorIds><NodeIds> | <LogicalIds><ThreadIds><CoreIds><NodeIds><ProcessorIds>]]></c></item> - <item><c><![CDATA[CpuTopology = <IdDefs>:<IdDefs> | <IdDefs>]]></c></item> + <item><c><![CDATA[<IdDefs> = + <LogicalIds><ThreadIds><CoreIds><ProcessorIds><NodeIds> | + <LogicalIds><ThreadIds><CoreIds><NodeIds><ProcessorIds>]]></c> + </item> + <item><c><![CDATA[CpuTopology = <IdDefs>:<IdDefs> | + <IdDefs>]]></c></item> + </list> + <p>Sets a user-defined CPU topology. The user-defined + CPU topology overrides any automatically detected + CPU topology. The CPU topology is used when + <seealso marker="#+sbt">binding schedulers to logical + processors</seealso>.</p> + <p>Uppercase letters signify real identifiers and lowercase + letters signify fake identifiers only used for description + of the topology. Identifiers passed as real identifiers can + be used by the runtime system when trying to access specific + hardware; if they are incorrect the behavior is + undefined. Faked logical CPU identifiers are not accepted, + as there is no point in defining the CPU topology without + real logical CPU identifiers. Thread, core, processor, and + node identifiers can be omitted. If omitted, the thread ID + defaults to <c>t0</c>, the core ID defaults to <c>c0</c>, + the processor ID defaults to <c>p0</c>, and the node ID is + left undefined. Either each logical processor must + belong to only one NUMA node, or no logical + processors must belong to any NUMA nodes.</p> + <p>Both increasing and decreasing <c><![CDATA[<IdRange>]]></c>s + are allowed.</p> + <p>NUMA node identifiers are system wide. That is, each NUMA + node on the system must have a unique identifier. Processor + identifiers are also system wide. Core identifiers are + processor wide. Thread identifiers are core wide.</p> + <p>The order of the identifier types implies the hierarchy of the + CPU topology. The valid orders are as follows:</p> + <list type="bulleted"> + <item> + <p><c><![CDATA[<LogicalIds><ThreadIds><CoreIds><ProcessorIds><NodeIds>]]></c>, + that is, thread is part of a core that is part of a processor, + which is part of a NUMA node.</p> + </item> + <item> + <p><c><![CDATA[<LogicalIds><ThreadIds><CoreIds><NodeIds><ProcessorIds>]]></c>, + that is, thread is part of a core that is part of a NUMA node, + which is part of a processor.</p> + </item> </list> - <p>Set a user defined CPU topology. The user defined - CPU topology will override any automatically detected - CPU topology. The CPU topology is used when - <seealso marker="#+sbt">binding schedulers to logical - processors</seealso>. - </p> - <p>Upper-case letters signify real identifiers and lower-case - letters signify fake identifiers only used for description - of the topology. Identifiers passed as real identifiers may - be used by the runtime system when trying to access specific - hardware and if they are not correct the behavior is - undefined. Faked logical CPU identifiers are not accepted - since there is no point in defining the CPU topology without - real logical CPU identifiers. Thread, core, processor, and - node identifiers may be left out. If left out, thread id - defaults to <c>t0</c>, core id defaults to <c>c0</c>, - processor id defaults to <c>p0</c>, and node id will - be left undefined. Either each logical processor must - belong to one and only one NUMA node, or no logical - processors must belong to any NUMA nodes. - </p> - <p>Both increasing and decreasing <c><![CDATA[<IdRange>]]></c>s - are allowed.</p> - <p>NUMA node identifiers are system wide. That is, each NUMA - node on the system have to have a unique identifier. Processor - identifiers are also system wide. Core identifiers are - processor wide. Thread identifiers are core wide.</p> - <p>The order of the identifier types imply the hierarchy of the - CPU topology. Valid orders are either - <c><![CDATA[<LogicalIds><ThreadIds><CoreIds><ProcessorIds><NodeIds>]]></c>, - or - <c><![CDATA[<LogicalIds><ThreadIds><CoreIds><NodeIds><ProcessorIds>]]></c>. - That is, thread is part of a core which is part of a processor - which is part of a NUMA node, or thread is part of a core which - is part of a NUMA node which is part of a processor. A cpu - topology can consist of both processor external, and processor - internal NUMA nodes as long as each logical processor belongs - to one and only one NUMA node. If <c><![CDATA[<ProcessorIds>]]></c> - is left out, its default position will be before - <c><![CDATA[<NodeIds>]]></c>. That is, the default is - processor external NUMA nodes. - </p> - <p>If a list of identifiers is used in an - <c><![CDATA[<IdDefs>]]></c>:</p> - <list type="bulleted"> - <item><c><![CDATA[<LogicalIds>]]></c> have to be a list - of identifiers.</item> - <item>At least one other identifier type apart from - <c><![CDATA[<LogicalIds>]]></c> also have to have a - list of identifiers.</item> - <item>All lists of identifiers have to produce the - same amount of identifiers.</item> - </list> - <p>A simple example. A single quad core processor may be - described this way:</p> + <p>A CPU topology can consist of both processor external, and + processor internal NUMA nodes as long as each logical processor + belongs to only one NUMA node. If + <c><![CDATA[<ProcessorIds>]]></c> is omitted, its default position + is before <c><![CDATA[<NodeIds>]]></c>. That is, the default is + processor external NUMA nodes.</p> + <p>If a list of identifiers is used in an + <c><![CDATA[<IdDefs>]]></c>:</p> + <list type="bulleted"> + <item><c><![CDATA[<LogicalIds>]]></c> must be a list + of identifiers.</item> + <item>At least one other identifier type besides + <c><![CDATA[<LogicalIds>]]></c> must also have a + list of identifiers.</item> + <item>All lists of identifiers must produce the + same number of identifiers.</item> + </list> + <p>A simple example. A single quad core processor can be + described as follows:</p> <pre> % <input>erl +sct L0-3c0-3</input> 1> <input>erlang:system_info(cpu_topology).</input> [{processor,[{core,{logical,0}}, {core,{logical,1}}, {core,{logical,2}}, - {core,{logical,3}}]}] -</pre> - <p>A little more complicated example. Two quad core - processors. Each processor in its own NUMA node. - The ordering of logical processors is a little weird. - This in order to give a better example of identifier - lists:</p> + {core,{logical,3}}]}]</pre> + <p>A more complicated example with two quad core + processors, each processor in its own NUMA node. + The ordering of logical processors is a bit weird. + This to give a better example of identifier lists:</p> <pre> % <input>erl +sct L0-1,3-2c0-3p0N0:L7,4,6-5c0-3p1N1</input> 1> <input>erlang:system_info(cpu_topology).</input> @@ -1118,226 +1295,262 @@ {node,[{processor,[{core,{logical,7}}, {core,{logical,4}}, {core,{logical,6}}, - {core,{logical,5}}]}]}] -</pre> - <p>As long as real identifiers are correct it is okay - to pass a CPU topology that is not a correct - description of the CPU topology. When used with - care this can actually be very useful. This in - order to trick the emulator to bind its schedulers - as you want. For example, if you want to run multiple - Erlang runtime systems on the same machine, you - want to reduce the amount of schedulers used and - manipulate the CPU topology so that they bind to - different logical CPUs. An example, with two Erlang - runtime systems on a quad core machine:</p> + {core,{logical,5}}]}]}]</pre> + <p>As long as real identifiers are correct, it is OK + to pass a CPU topology that is not a correct + description of the CPU topology. When used with + care this can be very useful. This + to trick the emulator to bind its schedulers + as you want. For example, if you want to run multiple + Erlang runtime systems on the same machine, you + want to reduce the number of schedulers used and + manipulate the CPU topology so that they bind to + different logical CPUs. An example, with two Erlang + runtime systems on a quad core machine:</p> <pre> % <input>erl +sct L0-3c0-3 +sbt db +S3:2 -detached -noinput -noshell -sname one</input> -% <input>erl +sct L3-0c0-3 +sbt db +S3:2 -detached -noinput -noshell -sname two</input> -</pre> - <p>In this example each runtime system have two - schedulers each online, and all schedulers online - will run on different cores. If we change to one - scheduler online on one runtime system, and three - schedulers online on the other, all schedulers - online will still run on different cores.</p> - <p>Note that a faked CPU topology that does not reflect - how the real CPU topology looks like is likely to - decrease the performance of the runtime system.</p> - <p>For more information, see - <seealso marker="erlang#system_info_cpu_topology">erlang:system_info(cpu_topology)</seealso>.</p> +% <input>erl +sct L3-0c0-3 +sbt db +S3:2 -detached -noinput -noshell -sname two</input></pre> + <p>In this example, each runtime system have two + schedulers each online, and all schedulers online + will run on different cores. If we change to one + scheduler online on one runtime system, and three + schedulers online on the other, all schedulers + online will still run on different cores.</p> + <p>Notice that a faked CPU topology that does not reflect + how the real CPU topology looks like is likely to + decrease the performance of the runtime system.</p> + <p>For more information, see + <seealso marker="erlang#system_info_cpu_topology"> + <c>erlang:system_info(cpu_topology)</c></seealso>.</p> </item> - <tag><marker id="+secio"><c>+secio true|false</c></marker></tag> + <tag><marker id="+sfwi"/><c>+sfwi Interval</c></tag> <item> - <p>Enable or disable eager check I/O scheduling. The default - is currently <c>false</c>, but will most likely be changed - to <c>true</c> in OTP 18. The behaviour before this flag - was introduced corresponds to <c>+secio false</c>.</p> - <p>The flag effects when schedulers will check for I/O - operations possible to execute, and when such I/O operations - will execute. As the name of the parameter implies, - schedulers will be more eager to check for I/O when - <c>true</c> is passed. This however also implies that - execution of outstanding I/O operation will not be - prioritized to the same extent as when <c>false</c> is - passed.</p> - <p><seealso marker="erlang#system_info_eager_check_io"><c>erlang:system_info(eager_check_io)</c></seealso> - returns the value of this parameter used when starting the VM.</p> + <p>Sets scheduler-forced wakeup interval. All run queues are + scanned each <c>Interval</c> milliseconds. While there are + sleeping schedulers in the system, one scheduler is woken + for each non-empty run queue found. <c>Interval</c> default + to <c>0</c>, meaning this feature is disabled.</p> + <note> + <p>This feature has been introduced as a temporary workaround + for long-executing native code, and native code that does not + bump reductions properly in OTP. When these bugs have be fixed, + this flag will be removed.</p> + </note> </item> - <tag><marker id="+sfwi"><c>+sfwi Interval</c></marker></tag> + <tag><marker id="+spp"/><c>+spp Bool</c></tag> <item> - <p>Set scheduler forced wakeup interval. All run queues will - be scanned each <c>Interval</c> milliseconds. While there are - sleeping schedulers in the system, one scheduler will be woken - for each non-empty run queue found. An <c>Interval</c> of zero - disables this feature, which also is the default. - </p> - <p>This feature has been introduced as a temporary workaround - for lengthy executing native code, and native code that do not - bump reductions properly in OTP. When these bugs have be fixed - the <c>+sfwi</c> flag will be removed. - </p> - </item> - <tag><marker id="+stbt"><c>+stbt BindType</c></marker></tag> + <p>Sets default scheduler hint for port parallelism. If set to + <c>true</c>, the virtual machine schedules port tasks when it + improves parallelism in the system. If set to <c>false</c>, the + virtual machine tries to perform port tasks immediately, + improving latency at the expense of parallelism. Default to + <c>false</c>. The default used can be inspected in runtime by + calling <seealso marker="erlang#system_info_port_parallelism"> + <c>erlang:system_info(port_parallelism)</c></seealso>. + The default can be overridden on port creation by passing option + <seealso marker="erlang#open_port_parallelism"> + <c>parallelism</c></seealso> to + <seealso marker="erlang#open_port/2"> + <c>erlang:open_port/2</c></seealso></p>. + </item> + <tag><marker id="sched_thread_stack_size"/> + <c><![CDATA[+sss size]]></c></tag> <item> - <p>Try to set scheduler bind type. The same as the - <seealso marker="#+sbt">+sbt</seealso> flag with the exception of - how some errors are handled. For more information, see the - documentation of the <seealso marker="#+sbt">+sbt</seealso> flag. - </p> - </item> - <tag><marker id="+sub"><c>+sub true|false</c></marker></tag> + <p>Suggested stack size, in kilowords, for scheduler threads. + 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>Enable or disable - <seealso marker="erts:erlang#statistics_scheduler_wall_time">scheduler - utilization</seealso> balancing of load. By default scheduler - utilization balancing is disabled and instead scheduler - compaction of load is enabled which will strive for a load - distribution which causes as many scheduler threads as possible - to be fully loaded (i.e., not run out of work). When scheduler - utilization balancing is enabled the system will instead try to - balance scheduler utilization between schedulers. That is, - strive for equal scheduler utilization on all schedulers. - <br/> <c>+sub true</c> is only supported on - systems where the runtime system detects and use a monotonically - increasing high resolution clock. On other systems, the runtime - system will fail to start. - <br/> <c>+sub true</c> implies - <seealso marker="#+scl">+scl false</seealso>. The difference - between <c>+sub true</c> and <c>+scl false</c> is that - <c>+scl false</c> will not try to balance the scheduler - utilization. - </p> + <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="+swct"><c>+swct very_eager|eager|medium|lazy|very_lazy</c></marker></tag> - <item> - <p> - Set scheduler wake cleanup threshold. Default is <c>medium</c>. - This flag controls how eager schedulers should be requesting - wake up due to certain cleanup operations. When a lazy setting - is used, more outstanding cleanup operations can be left undone - while a scheduler is idling. When an eager setting is used, - schedulers will more frequently be woken, potentially increasing - CPU-utilization. - </p> - <p><em>NOTE:</em> This flag may be removed or changed at any time without prior notice. - </p> - </item> - <tag><marker id="+sws"><c>+sws default|legacy</c></marker></tag> - <item> - <p> - Set scheduler wakeup strategy. Default strategy changed in erts-5.10/OTP-R16A. This strategy was previously known as <c>proposal</c> in OTP-R15. The <c>legacy</c> strategy was used as default from R13 up to and including R15. - </p> - <p><em>NOTE:</em> This flag may be removed or changed at any time without prior notice. - </p> - </item> - <tag><marker id="+swt"><c>+swt very_low|low|medium|high|very_high</c></marker></tag> - <item> - <p>Set scheduler wakeup threshold. Default is <c>medium</c>. - The threshold determines when to wake up sleeping schedulers - when more work than can be handled by currently awake schedulers - exist. A low threshold will cause earlier wakeups, and a high - threshold will cause later wakeups. Early wakeups will - distribute work over multiple schedulers faster, but work will - more easily bounce between schedulers. - </p> - <p><em>NOTE:</em> This flag may be removed or changed at any time - without prior notice. - </p> - </item> - <tag><marker id="+spp"><c>+spp Bool</c></marker></tag> + <tag><marker id="dio_sched_thread_stack_size"/> + <c><![CDATA[+sssdio size]]></c></tag> <item> - <p>Set default scheduler hint for port parallelism. If set to - <c>true</c>, the VM will schedule port tasks when doing so will - improve parallelism in the system. If set to <c>false</c>, the VM - will try to perform port tasks immediately, improving latency at the - expense of parallelism. If this flag has not been passed, the - default scheduler hint for port parallelism is currently - <c>false</c>. The default used can be inspected in runtime by - calling <seealso - marker="erlang#system_info_port_parallelism">erlang:system_info(port_parallelism)</seealso>. - The default can be overriden on port creation by passing the - <seealso marker="erlang#open_port_parallelism">parallelism</seealso> - option to <seealso - marker="erlang#open_port/2">open_port/2</seealso></p>. - </item> - <tag><marker id="sched_thread_stack_size"><c><![CDATA[+sss size]]></c></marker></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> - </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> + <p>Tries to set the scheduler bind type. The same as flag + <seealso marker="#+sbt"><c>+sbt</c></seealso> except + how some errors are handled. For more information, see + <seealso marker="#+sbt"><c>+sbt</c></seealso>.</p> + </item> + <tag><marker id="+sub"/><c>+sub true|false</c></tag> + <item> + <p>Enables or disables + <seealso marker="erts:erlang#statistics_scheduler_wall_time"> + scheduler utilization</seealso> balancing of load. By default + scheduler utilization balancing is disabled and instead scheduler + compaction of load is enabled, which strives for a load + distribution that causes as many scheduler threads as possible + to be fully loaded (that is, not run out of work). When scheduler + utilization balancing is enabled, the system instead tries to + balance scheduler utilization between schedulers. That is, + strive for equal scheduler utilization on all schedulers.</p> + <p><c>+sub true</c> is only supported on systems where the runtime + system detects and uses a monotonically increasing high-resolution + clock. On other systems, the runtime system fails to start.</p> + <p><c>+sub true</c> implies <seealso marker="#+scl"> + <c>+scl false</c></seealso>. The difference between + <c>+sub true</c> and <c>+scl false</c> is that <c>+scl false</c> + does not try to balance the scheduler utilization.</p> + </item> + <tag><marker id="+swct"/> + <c>+swct very_eager|eager|medium|lazy|very_lazy</c></tag> + <item> + <p>Sets scheduler wake cleanup threshold. Defaults to <c>medium</c>. + Controls how eager schedulers are to be requesting + wakeup because of certain cleanup operations. When a lazy setting + is used, more outstanding cleanup operations can be left undone + while a scheduler is idling. When an eager setting is used, + schedulers are more frequently woken, potentially increasing + CPU-utilization.</p> + <note> + <p>This flag can be removed or changed at any time without prior + notice.</p> + </note> + </item> + <tag><marker id="+sws"/><c>+sws default|legacy</c></tag> + <item> + <p>Sets scheduler wakeup strategy. Default strategy changed in + ERTS 5.10 (Erlang/OTP R16A). This strategy was known as + <c>proposal</c> in Erlang/OTP R15. The <c>legacy</c> strategy + was used as default from R13 up to and including R15.</p> + <note> + <p>This flag can be removed or changed at any time without prior + notice.</p> + </note> + </item> + <tag><marker id="+swt"/> + <c>+swt very_low|low|medium|high|very_high</c></tag> + <item> + <p>Sets scheduler wakeup threshold. Defaults to <c>medium</c>. + The threshold determines when to wake up sleeping schedulers + when more work than can be handled by currently awake schedulers + exists. A low threshold causes earlier wakeups, and a high + threshold causes later wakeups. Early wakeups distribute work + over multiple schedulers faster, but work does more easily bounce + between schedulers.</p> + <note> + <p>This flag can be removed or changed at any time without prior + notice.</p> + </note> + </item> + <tag><marker id="+swtdcpu"/> + <c>+swtdcpu very_low|low|medium|high|very_high</c></tag> + <item> + <p>As <seealso marker="#+swt"><c>+swt</c></seealso> but + affects dirty CPU schedulers. Defaults to <c>medium</c>.</p> + <note> + <p>This flag can be removed or changed at any time + without prior notice.</p> + </note> + </item> + <tag><marker id="+swtdio"/> + <c>+swtdio very_low|low|medium|high|very_high</c></tag> + <item> + <p>As <seealso marker="#+swt"><c>+swt</c></seealso> but affects + dirty IO schedulers. Defaults to <c>medium</c>.</p> + <note> + <p>This flag can be removed or changed at any time + without prior notice.</p> + </note> + </item> </taglist> </item> - <tag><marker id="+t"><c><![CDATA[+t size]]></c></marker></tag> + <tag><marker id="+t"/><c><![CDATA[+t size]]></c></tag> <item> - <p>Set the maximum number of atoms the VM can handle. Default is 1048576.</p> + <p>Sets the maximum number of atoms the virtual machine can handle. + Defaults to 1,048,576.</p> </item> - <tag><marker id="+T"><c><![CDATA[+T Level]]></c></marker></tag> + <tag><marker id="+T"/><c><![CDATA[+T Level]]></c></tag> <item> - <p>Enables modified timing and sets the modified timing level. - Currently valid range is 0-9. The timing of the runtime system - will change. A high level usually means a greater change than - a low level. Changing the timing can be very useful for finding - timing related bugs.</p> - <p>Currently, modified timing affects the following:</p> + <p>Enables modified timing and sets the modified timing level. Valid + range is 0-9. The timing of the runtime system is changed. A high + level usually means a greater change than a low level. Changing the + timing can be very useful for finding timing-related bugs.</p> + <p>Modified timing affects the following:</p> <taglist> <tag>Process spawning</tag> - <item> - <p>A process calling <c><![CDATA[spawn]]></c>, <c><![CDATA[spawn_link]]></c>, - <c><![CDATA[spawn_monitor]]></c>, or <c><![CDATA[spawn_opt]]></c> will be scheduled - out immediately after completing the call. When higher modified - timing levels are used, the caller will also sleep for a while - after being scheduled out.</p> + <item>A process calling <c><![CDATA[spawn]]></c>, + <c><![CDATA[spawn_link]]></c>, <c><![CDATA[spawn_monitor]]></c>, + or <c><![CDATA[spawn_opt]]></c> is scheduled out immediately + after completing the call. When higher modified timing levels are + used, the caller also sleeps for a while after it is scheduled out. </item> <tag>Context reductions</tag> - <item>The amount of reductions a process is a allowed to - use before being scheduled out is increased or reduced.</item> + <item>The number of reductions a process is allowed to use before it + is scheduled out is increased or reduced. + </item> <tag>Input reductions</tag> - <item>The amount of reductions performed before checking I/O - is increased or reduced.</item> + <item>The number of reductions performed before checking I/O is + increased or reduced. + </item> </taglist> - <p><em>NOTE:</em> Performance will suffer when modified timing - is enabled. This flag is <em>only</em> intended for testing and - debugging. Also note that <c><![CDATA[return_to]]></c> and <c><![CDATA[return_from]]></c> - trace messages will be lost when tracing on the spawn BIFs. This - flag may be removed or changed at any time without prior notice.</p> - </item> - <tag><c><![CDATA[+V]]></c></tag> - <item> - <p>Makes the emulator print out its version number.</p> + <note> + <p>Performance suffers when modified timing is enabled. This flag is + <em>only</em> intended for testing and debugging.</p> + <p><c><![CDATA[return_to]]></c> and <c><![CDATA[return_from]]></c> + trace messages are lost when tracing on the spawn BIFs.</p> + <p>This flag can be removed or changed at any time without prior + notice.</p> + </note> </item> <tag><c><![CDATA[+v]]></c></tag> <item> <p>Verbose.</p> </item> - <tag><c><![CDATA[+W w | i]]></c></tag> + <tag><c><![CDATA[+V]]></c></tag> + <item> + <p>Makes the emulator print its version number.</p> + </item> + <tag><c><![CDATA[+W w | i | e]]></c></tag> <item> - <p>Sets the mapping of warning messages for <c><![CDATA[error_logger]]></c>. - Messages sent to the error logger using one of the warning - routines can be mapped either to errors (default), warnings - (<c><![CDATA[+W w]]></c>), or info reports (<c><![CDATA[+W i]]></c>). The current - mapping can be retrieved using - <c><![CDATA[error_logger:warning_map/0]]></c>. See - <seealso marker="kernel:error_logger#warning_map/0">error_logger(3)</seealso> - for further information.</p> + <p>Sets the mapping of warning messages for + <c><![CDATA[error_logger]]></c>. Messages sent to the error logger + using one of the warning routines can be mapped to errors + (<c><![CDATA[+W e]]></c>), warnings (<c><![CDATA[+W w]]></c>), or + information reports (<c><![CDATA[+W i]]></c>). Defaults to warnings. + The current mapping can be retrieved using + <c><![CDATA[error_logger:warning_map/0]]></c>. For more information, + see <seealso marker="kernel:error_logger#warning_map/0"> + <c>error_logger:warning_map/0</c></seealso> in Kernel.</p> </item> <tag><c><![CDATA[+zFlag Value]]></c></tag> <item> - <p>Miscellaneous flags.</p> + <p>Miscellaneous flags:</p> <taglist> - <tag><marker id="+zdbbl"><c>+zdbbl size</c></marker></tag> + <tag><marker id="+zdbbl"/><c>+zdbbl size</c></tag> + <item> + <p>Sets the distribution buffer busy limit + (<seealso marker="erlang#system_info_dist_buf_busy_limit"> + <c>dist_buf_busy_limit</c></seealso>) + in kilobytes. Valid range is 1-2097151. Defaults to 1024.</p> + <p>A larger buffer limit allows processes to buffer + more outgoing messages over the distribution. When the + buffer limit has been reached, sending processes will be + suspended until the buffer size has shrunk. The buffer + limit is per distribution channel. A higher limit + gives lower latency and higher throughput at the expense + of higher memory use.</p> + </item> + <tag><marker id="+zdntgc"/><c>+zdntgc time</c></tag> <item> - <p>Set the distribution buffer busy limit - (<seealso marker="erlang#system_info_dist_buf_busy_limit">dist_buf_busy_limit</seealso>) - in kilobytes. Valid range is 1-2097151. Default is 1024.</p> - <p>A larger buffer limit will allow processes to buffer - more outgoing messages over the distribution. When the - buffer limit has been reached, sending processes will be - suspended until the buffer size has shrunk. The buffer - limit is per distribution channel. A higher limit will - give lower latency and higher throughput at the expense - of higher memory usage.</p> + <p>Sets the delayed node table garbage collection time + (<seealso marker="erlang#system_info_delayed_node_table_gc"> + <c>delayed_node_table_gc</c></seealso>) + in seconds. Valid values are either <c>infinity</c> or + an integer in the range 0-100000000. Defaults to 60.</p> + <p>Node table entries that are not referred linger + in the table for at least the amount of time that this + parameter determines. The lingering prevents repeated + deletions and insertions in the tables from occurring.</p> </item> </taglist> </item> @@ -1346,164 +1559,180 @@ <section> <marker id="environment_variables"></marker> - <title>Environment variables</title> + <title>Environment Variables</title> <taglist> <tag><c><![CDATA[ERL_CRASH_DUMP]]></c></tag> <item> <p>If the emulator needs to write a crash dump, the value of this - variable will be the file name of the crash dump file. - If the variable is not set, the name of the crash dump file will - be <c><![CDATA[erl_crash.dump]]></c> in the current directory.</p> + variable is the filename of the crash dump file. + If the variable is not set, the name of the crash dump file is + <c><![CDATA[erl_crash.dump]]></c> in the current directory.</p> </item> <tag><c><![CDATA[ERL_CRASH_DUMP_NICE]]></c></tag> <item> - <p><em>Unix systems</em>: If the emulator needs to write a crash dump, - it will use the value of this variable to set the nice value - for the process, thus lowering its priority. The allowable range is - 1 through 39 (higher values will be replaced with 39). The highest - value, 39, will give the process the lowest priority.</p> + <p><em>Unix systems</em>: If the emulator needs to write a crash dump, + it uses the value of this variable to set the nice value + for the process, thus lowering its priority. Valid range is + 1-39 (higher values are replaced with 39). The highest + value, 39, gives the process the lowest priority.</p> </item> <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS]]></c></tag> <item> - <p><em>Unix systems</em>: This variable gives the number of seconds that - the emulator will be allowed to spend writing a crash dump. When - the given number of seconds have elapsed, the emulator will be - terminated by a SIGALRM signal.</p> - - <p> If the environment variable is <em>not</em> set or it is set to zero seconds, <c><![CDATA[ERL_CRASH_DUMP_SECONDS=0]]></c>, - the runtime system will not even attempt to write the crash dump file. It will just terminate. - </p> - <p> If the environment variable is set to negative valie, e.g. <c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c>, - the runtime system will wait indefinitely for the crash dump file to be written. - </p> - <p> This environment variable is used in conjuction with - <seealso marker="kernel:heart"><c>heart</c></seealso> if <c>heart</c> is running: - </p> - <taglist> - <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=0]]></c></tag> - <item><p> - Suppresses the writing a crash dump file entirely, - thus rebooting the runtime system immediately. - This is the same as not setting the environment variable. - </p> - </item> - <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=-1]]></c></tag> - <item><p>Setting the environment variable to a negative value will cause the - termination of the runtime system to wait until the crash dump file - has been completly written. - </p> - </item> - <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=S]]></c></tag> - <item><p> - Will wait for <c>S</c> seconds to complete the crash dump file and - then terminate the runtime system. - </p> - </item> - </taglist> - </item> - <tag><marker id="ERL_AFLAGS"><c><![CDATA[ERL_AFLAGS]]></c></marker></tag> - <item> - <p>The content of this environment variable will be added to the - beginning of the command line for <c><![CDATA[erl]]></c>.</p> - <p>The <c><![CDATA[-extra]]></c> flag is treated specially. Its scope ends - at the end of the environment variable content. Arguments - following an <c><![CDATA[-extra]]></c> flag are moved on the command line into - the <c><![CDATA[-extra]]></c> section, i.e. the end of the command line - following after an <c><![CDATA[-extra]]></c> flag.</p> - </item> - <tag><marker id="ERL_ZFLAGS"><c><![CDATA[ERL_ZFLAGS]]></c></marker> and <marker id="ERL_FLAGS"><c><![CDATA[ERL_FLAGS]]></c></marker></tag> - <item> - <p>The content of these environment variables will be added to the - end of the command line for <c><![CDATA[erl]]></c>.</p> - <p>The <c><![CDATA[-extra]]></c> flag is treated specially. Its scope ends - at the end of the environment variable content. Arguments - following an <c><![CDATA[-extra]]></c> flag are moved on the command line into - the <c><![CDATA[-extra]]></c> section, i.e. the end of the command line - following after an <c><![CDATA[-extra]]></c> flag.</p> + <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.</p> + <taglist> + <tag><c><![CDATA[ERL_CRASH_DUMP_SECONDS=0]]></c></tag> + <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>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> + <p>This variable sets the maximum size of a crash dump file in bytes. + The crash dump will be truncated if this limit is exceeded. If the + variable is not set, no size limit is enforced by default. If the + variable is set to <c>0</c>, the runtime system does not even attempt + to write a crash dump file.</p> + <p>Introduced in ERTS 8.1.2 (Erlang/OTP 19.2).</p> + </item> + <tag><marker id="ERL_AFLAGS"/><c><![CDATA[ERL_AFLAGS]]></c></tag> + <item> + <p>The content of this variable is added to the beginning of the + command line for <c><![CDATA[erl]]></c>.</p> + <p>Flag <c><![CDATA[-extra]]></c> is treated in a special way. Its + scope ends at the end of the environment variable content. Arguments + following an <c><![CDATA[-extra]]></c> flag are moved on the command + line into section <c><![CDATA[-extra]]></c>, that is, the end of the + command line following an <c><![CDATA[-extra]]></c> flag.</p> + </item> + <tag><marker id="ERL_ZFLAGS"/><c><![CDATA[ERL_ZFLAGS]]></c> and + <marker id="ERL_FLAGS"/><c><![CDATA[ERL_FLAGS]]></c></tag> + <item> + <p>The content of these variables are added to the end of the command + line for <c><![CDATA[erl]]></c>.</p> + <p>Flag <c><![CDATA[-extra]]></c> is treated in a special way. Its + scope ends at the end of the environment variable content. Arguments + following an <c><![CDATA[-extra]]></c> flag are moved on the command + line into section <c><![CDATA[-extra]]></c>, that is, the end of the + command line following an <c><![CDATA[-extra]]></c> flag.</p> </item> <tag><c><![CDATA[ERL_LIBS]]></c></tag> <item> - <p>This environment variable contains a list of additional library - directories that the code server will search for applications and - add to the code path. - See <seealso marker="kernel:code">code(3)</seealso>.</p> + <p>Contains a list of additional library directories that the code + server searches for applications and adds to the code path; see + <seealso marker="kernel:code"><c>code(3)</c></seealso>.</p> </item> <tag><c><![CDATA[ERL_EPMD_ADDRESS]]></c></tag> <item> - <p>This environment variable may be set to a comma-separated - list of IP addresses, in which case the - <seealso marker="epmd">epmd</seealso> daemon - will listen only on the specified address(es) and on the - loopback address (which is implicitly added to the list if it - has not been specified).</p> + <p>Can be set to a comma-separated list of IP addresses, in which case + the <seealso marker="epmd"><c>epmd</c></seealso> daemon listens only + on the specified address(es) and on the loopback address (which is + implicitly added to the list if it has not been specified).</p> </item> <tag><c><![CDATA[ERL_EPMD_PORT]]></c></tag> <item> - <p>This environment variable can contain the port number to use when - communicating with <seealso marker="epmd">epmd</seealso>. The default - port will work fine in most cases. A different port can be specified + <p>Can contain the port number to use when communicating with + <seealso marker="epmd"><c>epmd</c></seealso>. The default port works + fine in most cases. A different port can be specified to allow nodes of independent clusters to co-exist on the same host. - All nodes in a cluster must use the same epmd port number.</p> + All nodes in a cluster must use the same <c>epmd</c> port number.</p> </item> </taglist> </section> <section> + <marker id="signals"></marker> + <title>Signals</title> + <p>On Unix systems, the Erlang runtime will interpret two types of signals.</p> + <taglist> + <tag><c>SIGUSR1</c></tag> + <item> + <p>A <c>SIGUSR1</c> signal forces a crash dump.</p> + </item> + <tag><c>SIGTERM</c></tag> + <item> + <p>A <c>SIGTERM</c> will produce a <c>stop</c> message to the <c>init</c> process. + This is equivalent to a <c>init:stop/0</c> call.</p> + <p>Introduced in ERTS 8.3 (Erlang/OTP 19.3)</p> + </item> + </taglist> + <p>The signal <c>SIGUSR2</c> is reserved for internal usage. No other signals are handled.</p> + </section> + + <section> <marker id="configuration"></marker> <title>Configuration</title> - <p>The standard Erlang/OTP system can be re-configured to change the default - behavior on start-up.</p> + <p>The standard Erlang/OTP system can be reconfigured to change the default + behavior on startup.</p> <taglist> - <tag>The .erlang Start-up File</tag> - <item> - <p>When Erlang/OTP is started, the system searches for a file named .erlang - in the directory where Erlang/OTP is started. If not found, the user's home - directory is searched for an .erlang file.</p> - <p>If an .erlang file is found, it is assumed to contain valid Erlang expressions. - These expressions are evaluated as if they were input to the shell.</p> - <p>A typical .erlang file contains a set of search paths, for example:</p> - <code type="none"><![CDATA[ - io:format("executing user profile in HOME/.erlang\n",[]). - code:add_path("/home/calvin/test/ebin"). - code:add_path("/home/hobbes/bigappl-1.2/ebin"). - io:format(".erlang rc finished\n",[]). - ]]></code> - </item> - <tag>user_default and shell_default</tag> - <item> - <p>Functions in the shell which are not prefixed by a module name are assumed - to be functional objects (Funs), built-in functions (BIFs), or belong to the - module user_default or shell_default.</p> - <p>To include private shell commands, define them in a module user_default and - add the following argument as the first line in the .erlang file.</p> + <tag>The <c>.erlang</c> startup file</tag> + <item> + <p>When Erlang/OTP is started, the system searches for a file named + <c>.erlang</c> in the user's home directory.</p> + <p>If an <c>.erlang</c> file is found, it is assumed to contain valid + Erlang expressions. These expressions are evaluated as if they were + input to the shell.</p> + <p>A typical <c>.erlang</c> file contains a set of search paths, for + example:</p> <code type="none"><![CDATA[ - code:load_abs("..../user_default"). - ]]></code> - </item> - <tag>erl</tag> - <item> - <p>If the contents of .erlang are changed and a private version of - user_default is defined, it is possible to customize the Erlang/OTP environment. - More powerful changes can be made by supplying command line arguments in the - start-up script erl. Refer to erl(1) and <seealso marker="init">init(3)</seealso> - for further information.</p> - </item> +io:format("executing user profile in HOME/.erlang\n",[]). +code:add_path("/home/calvin/test/ebin"). +code:add_path("/home/hobbes/bigappl-1.2/ebin"). +io:format(".erlang rc finished\n",[]). ]]></code> + </item> + <tag>user_default and shell_default</tag> + <item> + <p>Functions in the shell that are not prefixed by a module name are + assumed to be functional objects (funs), built-in functions (BIFs), + or belong to the module <c>user_default</c> or + <c>shell_default</c>.</p> + <p>To include private shell commands, define them in a module + <c>user_default</c> and add the following argument as the first line + in the <c>.erlang</c> file:</p> + <code type="none"><![CDATA[ +code:load_abs("..../user_default"). ]]></code> + </item> + <tag>erl</tag> + <item> + <p>If the contents of <c>.erlang</c> are changed and a private version + of <c>user_default</c> is defined, the Erlang/OTP environment can be + customized. More powerful changes can be made by supplying + command-line arguments in the startup script <c>erl</c>. For more + information, see <seealso marker="init"><c>init(3)</c></seealso>.</p> + </item> </taglist> </section> - <section> - <title>SEE ALSO</title> - <p><seealso marker="init">init(3)</seealso>, - <seealso marker="erl_prim_loader">erl_prim_loader(3)</seealso>, - <seealso marker="kernel:erl_boot_server">erl_boot_server(3)</seealso>, - <seealso marker="kernel:code">code(3)</seealso>, - <seealso marker="kernel:application">application(3)</seealso>, - <seealso marker="kernel:heart">heart(3)</seealso>, - <seealso marker="kernel:net_kernel">net_kernel(3)</seealso>, - <seealso marker="kernel:auth">auth(3)</seealso>, - <seealso marker="tools:make">make(3)</seealso>, - <seealso marker="epmd">epmd(1)</seealso>, - <seealso marker="erts_alloc">erts_alloc(3)</seealso></p> + <section> + <title>See Also</title> + <p><seealso marker="epmd"><c>epmd(1)</c></seealso>, + <seealso marker="erl_prim_loader"><c>erl_prim_loader(3)</c></seealso>, + <seealso marker="erts_alloc"><c>erts_alloc(3)</c></seealso>, + <seealso marker="init"><c>init(3)</c></seealso>, + <seealso marker="kernel:application"> + <c>application(3)</c></seealso>, + <seealso marker="kernel:auth"><c>auth(3)</c></seealso>, + <seealso marker="kernel:code"><c>code(3)</c></seealso>, + <seealso marker="kernel:erl_boot_server"> + <c>erl_boot_server(3)</c></seealso>, + <seealso marker="kernel:heart"><c>heart(3)</c></seealso>, + <seealso marker="kernel:net_kernel"><c>net_kernel(3)</c></seealso>, + <seealso marker="tools:make"><c>make(3)</c></seealso></p> </section> </comref> - diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml index 890293d802..c90c8f9521 100644 --- a/erts/doc/src/erl_dist_protocol.xml +++ b/erts/doc/src/erl_dist_protocol.xml @@ -5,20 +5,21 @@ <header> <copyright> <year>2007</year> - <year>2013</year> + <year>2018</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. The Initial Developer of the Original Code is Ericsson AB. </legalnotice> @@ -31,1049 +32,1069 @@ <file>erl_dist_protocol.xml</file> </header> -<p> -The description here is far from complete and will therefore be further -refined in upcoming releases. - -The protocols both from Erlang nodes towards -EPMD (Erlang Port Mapper Daemon) and between Erlang nodes, however, are -stable since many years. -</p> - -<p>The distribution protocol can be divided into four (4) parts:</p> -<list> - <item> + <p>This description is far from complete. It will be updated if the + protocol is updated. However, the protocols, both from Erlang + nodes to the Erlang Port Mapper Daemon (EPMD) and between Erlang nodes + are stable since many years.</p> + + <p>The distribution protocol can be divided into four parts:</p> + + <list type="bulleted"> + <item> + <p>Low-level socket connection (1)</p> + </item> + <item> + <p>Handshake, interchange node name, and authenticate (2)</p> + </item> + <item> + <p>Authentication (done by <seealso marker="kernel:net_kernel"> + <c>net_kernel(3)</c></seealso>) (3)</p> + </item> + <item> + <p>Connected (4)</p> + </item> + </list> + + <p>A node fetches the port number of another node through the EPMD (at the + other host) to initiate a connection request.</p> + + <p>For each host, where a distributed Erlang node is running, also an EPMD + is to be running. The EPMD can be started explicitly or automatically + as a result of the Erlang node startup.</p> + + <p>By default the EPMD listens on port 4369.</p> + + <p>(3) and (4) above are performed at the same level but the <c>net_kernel</c> + disconnects the other node if it communicates using an invalid cookie (after + 1 second).</p> + + <p>The integers in all multibyte fields are in big-endian order.</p> + + <warning> <p> - 1. Low level socket connection. + 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> - </item> - <item> - 2. Handshake, interchange node name and authenticate. - </item> - <item> - 3. Authentication (done by net_kernel). - </item> - <item> - 4. Connected. - </item> -</list> -<p> - A node fetches the Port number of another node through the EPMD (at the - other host) in order to initiate a connection request. -</p> -<p> -For each host where a distributed Erlang node is running there should also -be an EPMD running. The EPMD can be started explicitly or automatically -as a result of the Erlang node startup. -</p> -<p> -By default EPMD listens on port 4369. -</p> -<p> - 3 and 4 are performed at the same level but the net_kernel disconnects the - other node if it communicates using an invalid cookie (after one (1) second). -</p> - -<p>The integers in all multi-byte fields are in big-endian order.</p> + </warning> <section> <title>EPMD Protocol</title> - <p> - The requests served by the EPMD (Erlang Port Mapper Daemon) are - summarized in the figure below. - </p> + <p>The requests served by the EPMD are summarized in the following + figure.</p> + + <image file="erl_ext_fig.gif"> + <icaption>Summary of EPMD Requests</icaption> + </image> + + <p>Each request <c>*_REQ</c> is preceded by a 2 byte length field. + Thus, the overall request format is as follows:</p> + + <table align="left"> + <row> + <cell align="center">2</cell> + <cell align="center">n</cell> + </row> + <row> + <cell align="center"><c>Length</c></cell> + <cell align="center"><c>Request</c></cell> + </row> + <tcaption>Request Format</tcaption> + </table> - <image file="erl_ext_fig.gif"> - <icaption> - Summary of EPMD requests. - </icaption> - </image> - <p> - Each request <c>*_REQ</c> is preceded by a two-byte length field. - Thus, the overall request format is: - </p> + <section> + <title>Register a Node in EPMD</title> + <p>When a distributed node is started it registers itself in the EPMD. + The message <c>ALIVE2_REQ</c> described below is sent from the node to + the EPMD. The response from the EPMD is <c>ALIVE2_RESP</c>.</p> <table align="left"> - <row> - <cell align="center">2</cell> - <cell align="center">n</cell> - </row> - <row> - <cell align="center">Length</cell> - <cell align="center">Request</cell> - </row> - <tcaption></tcaption></table> - - <section> - <title>Register a node in the EPMD</title> - <p> - When a distributed node is started it registers itself in EPMD. - The message ALIVE2_REQ described below is sent from the node towards - EPMD. The response from EPMD is ALIVE2_RESP. - </p> - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">2</cell> - <cell align="center">1</cell> - <cell align="center">1</cell> - <cell align="center">2</cell> - <cell align="center">2</cell> - <cell align="center">2</cell> - <cell align="center">Nlen</cell> - <cell align="center">2</cell> - <cell align="center">Elen</cell> - </row> - <row> - <cell align="center">120</cell> - <cell align="center">PortNo</cell> - <cell align="center">NodeType</cell> - <cell align="center">Protocol</cell> - <cell align="center">HighestVersion</cell> - <cell align="center">LowestVersion</cell> - <cell align="center">Nlen</cell> - <cell align="center">NodeName</cell> - <cell align="center">Elen</cell> - <cell align="center">Extra</cell> - </row> - <tcaption>ALIVE2_REQ (120)</tcaption></table> - <taglist> - <tag><c>PortNo</c></tag> - <item> - The port number on which the node accept connection requests. - </item> - <tag><c>NodeType</c></tag> - <item> - 77 = normal Erlang node, 72 = hidden node (C-node),... - </item> - <tag><c>Protocol</c></tag> - <item> - 0 = tcp/ip-v4, ... - </item> - <tag><c>HighestVersion</c></tag> - <item> - The highest distribution version that this node can handle. - The value in R6B and later is 5. - </item> - <tag><c>LowestVersion</c></tag> - <item> - The lowest distribution version that this node can handle. - The value in R6B and later is 5. - </item> - <tag><c>Nlen</c></tag> - <item> - The length (in bytes) of the <c>NodeName</c> field. - </item> - <tag><c>NodeName</c></tag> - <item> - The NodeName as an UTF-8 encoded string of - <c>Nlen</c> bytes. - </item> - <tag><c>Elen</c></tag> - <item> - The length of the <c>Extra</c> field. - </item> - <tag><c>Extra</c></tag> - <item> - Extra field of <c>Elen</c> bytes. - </item> - </taglist> - <p> - The connection created to the EPMD must be kept as long as the - node is a distributed node. When the connection is closed - the node is automatically unregistered from the EPMD. - </p> - <p> - The response message ALIVE2_RESP is described below. - </p> + <row> + <cell align="center">1</cell> + <cell align="center">2</cell> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">2</cell> + <cell align="center">2</cell> + <cell align="center">2</cell> + <cell align="center">Nlen</cell> + <cell align="center">2</cell> + <cell align="center">Elen</cell> + </row> + <row> + <cell align="center"><c>120</c></cell> + <cell align="center"><c>PortNo</c></cell> + <cell align="center"><c>NodeType</c></cell> + <cell align="center"><c>Protocol</c></cell> + <cell align="center"><c>HighestVersion</c></cell> + <cell align="center"><c>LowestVersion</c></cell> + <cell align="center"><c>Nlen</c></cell> + <cell align="center"><c>NodeName</c></cell> + <cell align="center"><c>Elen</c></cell> + <cell align="center"><c>Extra</c></cell> + </row> + <tcaption>ALIVE2_REQ (120)</tcaption> + </table> - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">1</cell> - <cell align="center">2</cell> - </row> - <row> - <cell align="center">121</cell> - <cell align="center">Result</cell> - <cell align="center">Creation</cell> - </row> - <tcaption>ALIVE2_RESP (121)</tcaption></table> - <p> - Result = 0 -> ok, Result > 0 -> error - </p> - </section> + <taglist> + <tag><c>PortNo</c></tag> + <item> + <p>The port number on which the node accept connection requests.</p> + </item> + <tag><c>NodeType</c></tag> + <item> + <p>77 = normal Erlang node, 72 = hidden node (C-node), ...</p> + </item> + <tag><c>Protocol</c></tag> + <item> + <p>0 = TCP/IPv4, ...</p> + </item> + <tag><c>HighestVersion</c></tag> + <item> + <p>The highest distribution version that this node can handle. + The value in Erlang/OTP R6B and later is 5.</p> + </item> + <tag><c>LowestVersion</c></tag> + <item> + <p>The lowest distribution version that this node can handle. + The value in Erlang/OTP R6B and later is 5.</p> + </item> + <tag><c>Nlen</c></tag> + <item> + <p>The length (in bytes) of field <c>NodeName</c>.</p> + </item> + <tag><c>NodeName</c></tag> + <item> + <p>The node name as an UTF-8 encoded string of <c>Nlen</c> bytes.</p> + </item> + <tag><c>Elen</c></tag> + <item> + <p>The length of field <c>Extra</c>.</p> + </item> + <tag><c>Extra</c></tag> + <item> + <p>Extra field of <c>Elen</c> bytes.</p> + </item> + </taglist> - <section> - <title>Unregister a node from the EPMD</title> - <p> - A node unregisters itself from the EPMD by simply closing the - TCP connection towards EPMD established when the node was registered. - </p> - </section> + <p>The connection created to the EPMD must be kept as long as the + node is a distributed node. When the connection is closed, + the node is automatically unregistered from the EPMD.</p> - <section> - <title>Get the distribution port of another node</title> - <p> - When one node wants to connect to another node it starts with - a PORT_PLEASE2_REQ request towards EPMD on the host where the - node resides in order to get the distribution port that the node - listens to. - </p> + <p>The response message <c>ALIVE2_RESP</c> is as follows:</p> - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">N</cell> - </row> - <row> - <cell align="center">122</cell> - <cell align="center">NodeName</cell> - </row> - <tcaption>PORT_PLEASE2_REQ (122)</tcaption></table> - <p> - where N = Length - 1 - </p> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">2</cell> + </row> + <row> + <cell align="center"><c>121</c></cell> + <cell align="center"><c>Result</c></cell> + <cell align="center"><c>Creation</c></cell> + </row> + <tcaption>ALIVE2_RESP (121)</tcaption> + </table> + + <p>Result = 0 -> ok, result > 0 -> error.</p> + </section> + + <section> + <title>Unregister a Node from EPMD</title> + <p>A node unregisters itself from the EPMD by closing the TCP + connection to EPMD established when the node was registered.</p> + </section> + + <section> + <title>Get the Distribution Port of Another Node</title> + <p>When one node wants to connect to another node it starts with + a <c>PORT_PLEASE2_REQ</c> request to the EPMD on the host where the + node resides to get the distribution port that the node listens to.</p> - <p> - </p> <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">1</cell> - </row> - <row> - <cell align="center">119</cell> - <cell align="center">Result</cell> - </row> - <tcaption> - PORT2_RESP (119) response indicating error, Result > 0. - </tcaption> + <row> + <cell align="center">1</cell> + <cell align="center">N</cell> + </row> + <row> + <cell align="center"><c>122</c></cell> + <cell align="center"><c>NodeName</c></cell> + </row> + <tcaption>PORT_PLEASE2_REQ (122)</tcaption> </table> - <p>Or</p> + + <p>where N = <c>Length</c> - 1.</p> + <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">1</cell> - <cell align="center">2</cell> - <cell align="center">1</cell> - <cell align="center">1</cell> - <cell align="center">2</cell> - <cell align="center">2</cell> - <cell align="center">2</cell> - <cell align="center">Nlen</cell> - <cell align="center">2</cell> - <cell align="center">Elen</cell> - </row> - <row> - <cell align="center">119</cell> - <cell align="center">Result</cell> - <cell align="center">PortNo</cell> - <cell align="center">NodeType</cell> - <cell align="center">Protocol</cell> - <cell align="center">HighestVersion</cell> - <cell align="center">LowestVersion</cell> - <cell align="center">Nlen</cell> - <cell align="center">NodeName</cell> - <cell align="center">Elen</cell> - <cell align="center">Extra</cell> - </row> - <tcaption>PORT2_RESP when Result = 0.</tcaption></table> -<p> -If Result > 0, the packet only consists of [119, Result]. -</p> - - <p>EPMD will close the socket as soon as it has sent the information.</p> - </section> - - <section> - <title>Get all registered names from EPMD</title> - <p> - This request is used via the Erlang function - <c>net_adm:names/1,2</c>. A TCP connection is opened - towards EPMD and this request is sent. - </p> - <table align="left"> - <row> - <cell align="center">1</cell> - </row> - <row> - <cell align="center">110</cell> - </row> - <tcaption>NAMES_REQ (110)</tcaption></table> - - - <p>The response for a <c>NAMES_REQ</c> looks like this:</p> - <table align="left"> - <row> - <cell align="center">4</cell> - <cell align="center"> </cell> - </row> - <row> - <cell align="center">EPMDPortNo</cell> - <cell align="center">NodeInfo*</cell> - </row> - <tcaption>NAMES_RESP</tcaption></table> - <p> - NodeInfo is a string written for each active node. - When all NodeInfo has been written the connection is - closed by EPMD. - </p> - <p> - NodeInfo is, as expressed in Erlang: - </p> - <code> - io:format("name ~ts at port ~p~n", [NodeName, Port]). - </code> - </section> + <row> + <cell align="center">1</cell> + <cell align="center">1</cell> + </row> + <row> + <cell align="center"><c>119</c></cell> + <cell align="center"><c>Result</c></cell> + </row> + <tcaption>PORT2_RESP (119) Response Indicating Error, Result > 0 + </tcaption> + </table> + <p>or</p> - <section> - <title>Dump all data from EPMD</title> - <p> - This request is not really used, it should be regarded as a debug - feature. - </p> - <table align="left"> - <row> - <cell align="center">1</cell> - </row> - <row> - <cell align="center">100</cell> - </row> - <tcaption>DUMP_REQ</tcaption></table> - - <p>The response for a <c>DUMP_REQ</c> looks like this:</p> - <table align="left"> - <row> - <cell align="center">4</cell> - <cell align="center"> </cell> - </row> - <row> - <cell align="center">EPMDPortNo</cell> - <cell align="center">NodeInfo*</cell> - </row> - <tcaption>DUMP_RESP</tcaption></table> - <p> - NodeInfo is a string written for each node kept in EPMD. - When all NodeInfo has been written the connection is - closed by EPMD. - </p> - <p> - NodeInfo is, as expressed in Erlang: - </p> - <code> - io:format("active name ~ts at port ~p, fd = ~p ~n", - [NodeName, Port, Fd]). - </code> - <p> - or - </p> - <code> - io:format("old/unused name ~ts at port ~p, fd = ~p~n", - [NodeName, Port, Fd]). - </code> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">2</cell> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">2</cell> + <cell align="center">2</cell> + <cell align="center">2</cell> + <cell align="center">Nlen</cell> + <cell align="center">2</cell> + <cell align="center">Elen</cell> + </row> + <row> + <cell align="center"><c>119</c></cell> + <cell align="center"><c>Result</c></cell> + <cell align="center"><c>PortNo</c></cell> + <cell align="center"><c>NodeType</c></cell> + <cell align="center"><c>Protocol</c></cell> + <cell align="center"><c>HighestVersion</c></cell> + <cell align="center"><c>LowestVersion</c></cell> + <cell align="center"><c>Nlen</c></cell> + <cell align="center"><c>NodeName</c></cell> + <cell align="center"><c>Elen</c></cell> + <cell align="center">><c>Extra</c></cell> + </row> + <tcaption>PORT2_RESP, Result = 0</tcaption> + </table> - </section> + <p>If <c>Result</c> > 0, the packet only consists of + <c>[119, Result]</c>.</p> - <section> - <title>Kill the EPMD</title> - <p> - This request will kill the running EPMD. It is almost never used. - </p> - <table align="left"> - <row> - <cell align="center">1</cell> - </row> - <row> - <cell align="center">107</cell> - </row> - <tcaption>KILL_REQ</tcaption></table> - - <p>The response fo a <c>KILL_REQ</c> looks like this:</p> - <table align="left"> - <row> - <cell align="center">2</cell> - </row> - <row> - <cell align="center">OKString</cell> - </row> - <tcaption>KILL_RESP</tcaption></table> - <p> - where <c>OKString</c> is "OK". - </p> - </section> - - <section> - <title>STOP_REQ (Not Used)</title> - <p></p> - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">n</cell> - </row> - <row> - <cell align="center">115</cell> - <cell align="center">NodeName</cell> - </row> - <tcaption>STOP_REQ</tcaption></table> - <p> - where n = Length - 1 - </p> - <p> - The current implementation of Erlang does not care if the connection - to the EPMD is broken. - </p> - <p>The response for a <c>STOP_REQ</c> looks like this.</p> - <table align="left"> - <row> - <cell align="center">7</cell> - </row> - <row> - <cell align="center">OKString</cell> - </row> - <tcaption>STOP_RESP</tcaption></table> - <p> - where OKString is "STOPPED". - </p> - <p>A negative response can look like this.</p> - <table align="left"> - <row> - <cell align="center">7</cell> - </row> - <row> - <cell align="center">NOKString</cell> - </row> - <tcaption>STOP_NOTOK_RESP</tcaption></table> - <p> - where NOKString is "NOEXIST". - </p> - </section> -<!-- - <section> - <title>ALIVE_REQ (97)</title> - <p></p> - - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">2</cell> - <cell align="center">n</cell> - </row> - <row> - <cell align="center">97</cell> - <cell align="center">PortNo</cell> - <cell align="center">NodeName</cell> - </row> - <tcaption></tcaption></table> + <p>The EPMD closes the socket when it has sent the information.</p> + </section> - <p> - where n = Length - 3 - </p> - <p> - The connection created to the EPMD must be kept until the node is - not a distributed node any longer. - </p> - </section> - - <section> - <title>ALIVE_OK_RESP (89)</title> - <p></p> - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">2</cell> - </row> - <row> - <cell align="center">89</cell> - <cell align="center">Creation</cell> - </row> - <tcaption></tcaption></table> - </section> - - - <section> - <title>ALIVE_NOTOK_RESP ()</title> - <p> - EPMD closed the connection. - </p> - </section> + <section> + <title>Get All Registered Names from EPMD</title> + <p>This request is used through the Erlang function + <seealso marker="kernel:net_adm#names/1,2"> + <c>net_adm:names/1,2</c></seealso>. A TCP connection is opened + to the EPMD and this request is sent.</p> - <section> - <title>PORT_PLEASE_REQ (112)</title> - <p></p> <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">n</cell> - </row> - <row> - <cell align="center">112</cell> - <cell align="center">NodeName</cell> - </row> - <tcaption></tcaption></table> - <p> - where n = Length - 1 - </p> - </section> - - <section> - <title>PORT_OK_RESP ()</title> - <p></p> - <table align="left"> - <row> - <cell align="center">2</cell> - </row> - <row> - <cell align="center">PortNo</cell> - </row> - <tcaption></tcaption></table> - - </section> - - <section> - <title>PORT_NOTOK_RESP ()</title> - <p> - EPMD closed the connection. - </p> - </section> + <row> + <cell align="center">1</cell> + </row> + <row> + <cell align="center"><c>110</c></cell> + </row> + <tcaption>NAMES_REQ (110)</tcaption> + </table> + <p>The response for a <c>NAMES_REQ</c> is as follows:</p> - <section> - <title>PORT_NOTOK_RESP ()</title> - <p> - EPMD closed the connection. - </p> - </section> ---> + <table align="left"> + <row> + <cell align="center">4</cell> + <cell align="center"> </cell> + </row> + <row> + <cell align="center"><c>EPMDPortNo</c></cell> + <cell align="center"><c>NodeInfo*</c></cell> + </row> + <tcaption>NAMES_RESP</tcaption> + </table> + + <p><c>NodeInfo</c> is a string written for each active node. + When all <c>NodeInfo</c> has been written the connection is + closed by the EPMD.</p> + + <p><c>NodeInfo</c> is, as expressed in Erlang:</p> + <code> +io:format("name ~ts at port ~p~n", [NodeName, Port]).</code> </section> - <marker id="distribution_handshake"/> - <section> - <title>Distribution Handshake</title> - <p> - This section describes the distribution handshake protocol - introduced in the OTP-R6 release of Erlang/OTP. This - description was previously located in - <c>$ERL_TOP/lib/kernel/internal_doc/distribution_handshake.txt</c>, - and has more or less been copied and "formatted" here. It has been - more or less unchanged since the year 1999, but the handshake - should not have changed much since then either. - </p> - <section> - <title>General</title> - <p> - The TCP/IP distribution uses a handshake which expects a - connection based protocol, i.e. the protocol does not include - any authentication after the handshake procedure. - </p> - <p> - This is not entirely safe, as it is vulnerable against takeover - attacks, but it is a tradeoff between fair safety and performance. - </p> - <p> - The cookies are never sent in cleartext and the handshake procedure - expects the client (called A) to be the first one to prove that it can - generate a sufficient digest. The digest is generated with the - MD5 message digest algorithm and the challenges are expected to be very - random numbers. - </p> - </section> - <section> - <title>Definitions</title> - <p> - A challenge is a 32 bit integer number in big endian order. Below the function - <c>gen_challenge()</c> returns a random 32 bit integer used as a challenge. - </p> - <p> - A digest is a (16 bytes) MD5 hash of the Challenge (as text) concatenated - with the cookie (as text). Below, the function <c>gen_digest(Challenge, Cookie)</c> - generates a digest as described above. - </p> - <p> - An out_cookie is the cookie used in outgoing communication to a certain node, - so that A's out_cookie for B should correspond with B's in_cookie for A and - the other way around. A's out_cookie for B and A's in_cookie for B need <em>NOT</em> - be the same. Below the function <c>out_cookie(Node)</c> returns the current - node's out_cookie for <c>Node</c>. - </p> - <p> - An in_cookie is the cookie expected to be used by another node when - communicating with us, so that A's in_cookie for B corresponds with B's - out_cookie for A. Below the function <c>in_cookie(Node)</c> returns the current - node's <c>in_cookie</c> for <c>Node</c>. - </p> - <p> - The cookies are text strings that can be viewed as passwords. - </p> - <p> - Every message in the handshake starts with a 16 bit big endian integer - which contains the length of the message (not counting the two initial bytes). - In erlang this corresponds to the <c>gen_tcp</c> option <c>{packet, 2}</c>. Note that after - the handshake, the distribution switches to 4 byte packet headers. - </p> - </section> - <section> - <title>The Handshake in Detail</title> - <p> - Imagine two nodes, node A, which initiates the handshake and node B, which - accepts the connection. - </p> - <taglist> - <tag>1) connect/accept</tag> - <item><p>A connects to B via TCP/IP and B accepts the connection.</p></item> - <tag>2) send_name/receive_name</tag> - <item><p>A sends an initial identification to B. B receives the message. - The message looks like this (every "square" being one byte and the packet - header removed): - </p> -<pre> -+---+--------+--------+-----+-----+-----+-----+-----+-----+-...-+-----+ -|'n'|Version0|Version1|Flag0|Flag1|Flag2|Flag3|Name0|Name1| ... |NameN| -+---+--------+--------+-----+-----+-----+-----+-----+-----+-... +-----+ -</pre> - <p> - The 'n' is just a message tag. - Version0 and Version1 is the distribution version selected by node A, - based on information from EPMD. (16 bit big endian) - Flag0 ... Flag3 are capability flags, the capabilities defined in - <c>$ERL_TOP/lib/kernel/include/dist.hrl</c>. - (32 bit big endian) - Name0 ... NameN is the full nodename of A, as a string of bytes (the - packet length denotes how long it is). - </p></item> - <tag>3) recv_status/send_status</tag> - <item><p>B sends a status message to A, which indicates - if the connection is allowed. The following status codes are defined:</p> - <taglist> - <tag><c>ok</c></tag> - <item>The handshake will continue.</item> - <tag><c>ok_simultaneous</c></tag> - <item>The handshake will continue, but A is informed that B - has another ongoing connection attempt that will be - shut down (simultaneous connect where A's name is - greater than B's name, compared literally).</item> - <tag><c>nok</c></tag> - <item>The handshake will not continue, as B already has an ongoing handshake - which it itself has initiated. (simultaneous connect where B's name is - greater than A's).</item> - <tag><c>not_allowed</c></tag> - <item>The connection is disallowed for some (unspecified) security - reason.</item> - <tag><c>alive</c></tag> - <item>A connection to the node is already active, which either means - that node A is confused or that the TCP connection breakdown - of a previous node with this name has not yet reached node B. - See 3B below.</item> - </taglist> - <p>This is the format of the status message:</p> -<pre> -+---+-------+-------+-...-+-------+ -|'s'|Status0|Status1| ... |StatusN| -+---+-------+-------+-...-+-------+ -</pre> - <p> - 's' is the message tag Status0 ... StatusN is the status as a string (not terminated) - </p> - </item> - <tag>3B) send_status/recv_status</tag> - <item><p>If status was 'alive', node A will answer with - another status message containing either 'true' which means that the - connection should continue (The old connection from this node is broken), or - <c>'false'</c>, which simply means that the connection should be closed, the - connection attempt was a mistake.</p></item> - <tag>4) recv_challenge/send_challenge</tag> - <item><p>If the status was <c>ok</c> or <c>ok_simultaneous</c>, - The handshake continues with B sending A another message, the challenge. - The challenge contains the same type of information as the "name" message - initially sent from A to B, with the addition of a 32 bit challenge:</p> -<pre> -+---+--------+--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-...-+-----+ -|'n'|Version0|Version1|Flag0|Flag1|Flag2|Flag3|Chal0|Chal1|Chal2|Chal3|Name0|Name1| ... |NameN| -+---+--------+--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-... +-----+ -</pre> - <p> - Where Chal0 ... Chal3 is the challenge as a 32 bit big endian integer - and the other fields are B's version, flags and full nodename. - </p></item> - <tag>5) send_challenge_reply/recv_challenge_reply</tag> - <item><p>Now A has generated a digest and its own challenge. Those are - sent together in a package to B:</p> -<pre> -+---+-----+-----+-----+-----+-----+-----+-----+-----+-...-+------+ -|'r'|Chal0|Chal1|Chal2|Chal3|Dige0|Dige1|Dige2|Dige3| ... |Dige15| -+---+-----+-----+-----+-----+-----+-----+-----+-----+-...-+------+ -</pre> - <p> - Where 'r' is the tag, Chal0 ... Chal3 is A's challenge for B to handle and - Dige0 ... Dige15 is the digest that A constructed from the challenge B sent - in the previous step. - </p></item> - <tag>6) recv_challenge_ack/send_challenge_ack</tag> - <item><p>B checks that the digest received from A is correct and generates a - digest from the challenge received from A. The digest is then sent to A. The - message looks like this:</p> -<pre> -+---+-----+-----+-----+-----+-...-+------+ -|'a'|Dige0|Dige1|Dige2|Dige3| ... |Dige15| -+---+-----+-----+-----+-----+-...-+------+ -</pre> - <p> - Where 'a' is the tag and Dige0 ... Dige15 is the digest calculated by B - for A's challenge.</p></item> - <tag>7)</tag> - <item><p>A checks the digest from B and the connection is up.</p></item> - </taglist> - </section> - <section> - <title>Semigraphic View</title> -<pre> -A (initiator) B (acceptor) - -TCP connect -----------------------------------------> - TCP accept - -send_name -----------------------------------------> - recv_name - - <---------------------------------------- send_status -recv_status -(if status was 'alive' - send_status - - - - - - - - - - - - - - - - - - - -> - recv_status) - ChB = gen_challenge() - (ChB) - <---------------------------------------- send_challenge -recv_challenge + <section> + <title>Dump All Data from EPMD</title> + <p>This request is not really used, it is to be regarded as a debug + feature.</p> -ChA = gen_challenge(), -OCA = out_cookie(B), -DiA = gen_digest(ChB,OCA) - (ChA, DiA) -send_challenge_reply --------------------------------> - recv_challenge_reply - ICB = in_cookie(A), - check: - DiA == gen_digest - (ChB, ICB) ? - - if OK: - OCB = out_cookie(A), - DiB = gen_digest - (DiB) (ChA, OCB) - <----------------------------------------- send_challenge_ack -recv_challenge_ack DONE -ICA = in_cookie(B), - else -check: CLOSE -DiB == gen_digest(ChA,ICA) ? -- if OK - DONE -- else - CLOSE -</pre> - </section> - <marker id="dflags"/> - <section> - <title>The Currently Defined Distribution Flags</title> - <p> - Currently (OTP-R16) the following capability flags are defined: - </p> -<pre> -%% The node should be published and part of the global namespace --define(DFLAG_PUBLISHED,1). + <table align="left"> + <row> + <cell align="center">1</cell> + </row> + <row> + <cell align="center"><c>100</c></cell> + </row> + <tcaption>DUMP_REQ</tcaption> + </table> + + <p>The response for a <c>DUMP_REQ</c> is as follows:</p> + + <table align="left"> + <row> + <cell align="center">4</cell> + <cell align="center"> </cell> + </row> + <row> + <cell align="center"><c>EPMDPortNo</c></cell> + <cell align="center"><c>NodeInfo*</c></cell> + </row> + <tcaption>DUMP_RESP</tcaption> + </table> + + <p><c>NodeInfo</c> is a string written for each node kept in the EPMD. + When all <c>NodeInfo</c> has been written the connection is + closed by the EPMD.</p> + + <p><c>NodeInfo</c> is, as expressed in Erlang:</p> + + <code> +io:format("active name ~ts at port ~p, fd = ~p~n", + [NodeName, Port, Fd]).</code> + + <p>or</p> + + <code> +io:format("old/unused name ~ts at port ~p, fd = ~p ~n", + [NodeName, Port, Fd]).</code> + </section> + + <section> + <title>Kill EPMD</title> + <p>This request kills the running EPMD. It is almost never used.</p> -%% The node implements an atom cache (obsolete) --define(DFLAG_ATOM_CACHE,2). + <table align="left"> + <row> + <cell align="center">1</cell> + </row> + <row> + <cell align="center"><c>107</c></cell> + </row> + <tcaption>KILL_REQ</tcaption> + </table> -%% The node implements extended (3 * 32 bits) references. This is -%% required today. If not present connection will be refused. --define(DFLAG_EXTENDED_REFERENCES,4). + <p>The response for a <c>KILL_REQ</c> is as follows:</p> -%% The node implements distributed process monitoring. --define(DFLAG_DIST_MONITOR,8). + <table align="left"> + <row> + <cell align="center">2</cell> + </row> + <row> + <cell align="center"><c>OKString</c></cell> + </row> + <tcaption>KILL_RESP</tcaption> + </table> -%% The node uses separate tag for fun's (lambdas) in the distribution protocol. --define(DFLAG_FUN_TAGS,16#10). + <p>where <c>OKString</c> is "OK".</p> + </section> -%% The node implements distributed named process monitoring. --define(DFLAG_DIST_MONITOR_NAME,16#20). + <section> + <title>STOP_REQ (Not Used)</title> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">n</cell> + </row> + <row> + <cell align="center"><c>115</c></cell> + <cell align="center"><c>NodeName</c></cell> + </row> + <tcaption>STOP_REQ</tcaption> + </table> -%% The (hidden) node implements atom cache (obsolete) --define(DFLAG_HIDDEN_ATOM_CACHE,16#40). + <p>where n = <c>Length</c> - 1.</p> -%% The node understand new fun-tags --define(DFLAG_NEW_FUN_TAGS,16#80). + <p>The current implementation of Erlang does not care if the connection + to the EPMD is broken.</p> -%% The node is capable of handling extended pids and ports. This is -%% required today. If not present connection will be refused. --define(DFLAG_EXTENDED_PIDS_PORTS,16#100). + <p>The response for a <c>STOP_REQ</c> is as follows:</p> -%% --define(DFLAG_EXPORT_PTR_TAG,16#200). + <table align="left"> + <row> + <cell align="center">7</cell> + </row> + <row> + <cell align="center"><c>OKString</c></cell> + </row> + <tcaption>STOP_RESP</tcaption> + </table> -%% --define(DFLAG_BIT_BINARIES,16#400). + <p>where <c>OKString</c> is "STOPPED".</p> -%% The node understands new float format --define(DFLAG_NEW_FLOATS,16#800). + <p>A negative response can look as follows:</p> -%% --define(DFLAG_UNICODE_IO,16#1000). + <table align="left"> + <row> + <cell align="center">7</cell> + </row> + <row> + <cell align="center"><c>NOKString</c></cell> + </row> + <tcaption>STOP_NOTOK_RESP</tcaption> + </table> -%% The node implements atom cache in distribution header. --define(DFLAG_DIST_HDR_ATOM_CACHE,16#2000). + <p>where <c>NOKString</c> is "NOEXIST".</p> + </section> +<!-- + <section> + <title>ALIVE_REQ (97)</title> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">2</cell> + <cell align="center">n</cell> + </row> + <row> + <cell align="center"><c>97</c></cell> + <cell align="center"><c>PortNo</c></cell> + <cell align="center"><c>NodeName</c></cell> + </row> + <tcaption></tcaption> + </table> -%% The node understand the SMALL_ATOM_EXT tag --define(DFLAG_SMALL_ATOM_TAGS, 16#4000). + <p>where n = <c>Length</c> - 3.</p> -%% The node understand UTF-8 encoded atoms --define(DFLAG_UTF8_ATOMS, 16#10000). + <p>The connection created to the EPMD must be kept until the node is + not a distributed node any longer.</p> + </section> -</pre> - </section> - </section> + <section> + <title>ALIVE_OK_RESP (89)</title> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">2</cell> + </row> + <row> + <cell align="center"><c>89</c></cell> + <cell align="center"><c>Creation</c></cell> + </row> + <tcaption></tcaption> + </table> + </section> - <section> - <marker id="connected_nodes"/> - <title>Protocol between connected nodes</title> - <p> - As of erts version 5.7.2 the runtime system passes a distribution - flag in the handshake stage that enables the use of a - <seealso marker="erl_ext_dist#distribution_header">distribution - header</seealso> on all messages passed. Messages passed between - nodes are in this case on the following format: - </p> - <table align="left"> - <row> - <cell align="center">4</cell> - <cell align="center">d</cell> - <cell align="center">n</cell> - <cell align="center">m</cell> - </row> - <row> - <cell align="center"><c>Length</c></cell> - <cell align="center"><c>DistributionHeader</c></cell> - <cell align="center"><c>ControlMessage</c></cell> - <cell align="center"><c>Message</c></cell> - </row> - <tcaption></tcaption></table> - <p> - where: - </p> - <p> - <c>Length</c> is equal to d + n + m - </p> - <p> - <c>ControlMessage</c> is a tuple passed using the external format of - Erlang. - </p> - <p> - <c>Message</c> is the message sent to another node using the '!' - (in external format). Note that <c>Message</c> is only passed in - combination with a <c>ControlMessage</c> encoding a send ('!'). - </p> - <p> - Also note that <seealso marker="erl_ext_dist#overall_format">the - version number is omitted from the terms that follow a - distribution header</seealso>. - </p> - <p> - Nodes with an erts version less than 5.7.2 does not pass the - distribution flag that enables the distribution header. Messages - passed between nodes are in this case on the following format: - </p> - <table align="left"> - <row> - <cell align="center">4</cell> - <cell align="center">1</cell> - <cell align="center">n</cell> - <cell align="center">m</cell> - </row> - <row> - <cell align="center"><c>Length</c></cell> - <cell align="center"><c>Type</c></cell> - <cell align="center"><c>ControlMessage</c></cell> - <cell align="center"><c>Message</c></cell> - </row> - <tcaption></tcaption></table> - <p> - where: - </p> - <p> - <c>Length</c> is equal to 1 + n + m - </p> - <p> - Type is: 112 (pass through) - </p> - <p> - <c>ControlMessage</c> is a tuple passed using the external format of - Erlang. - </p> - <p> - <c>Message</c> is the message sent to another node using the '!' - (in external format). Note that <c>Message</c> is only passed in - combination with a <c>ControlMessage</c> encoding a send ('!'). - </p> - <p> - The <c>ControlMessage</c> is a tuple, where the first element - indicates which distributed operation it encodes. - </p> - <taglist> - <tag><c>LINK</c></tag> - <item> - <p> - <c>{1, FromPid, ToPid}</c> - </p> - </item> - - <tag><c>SEND</c></tag> - <item> - <p> - <c>{2, Cookie, ToPid}</c> - </p> - <p> - <em>Note</em> followed by <c>Message</c> - </p> - </item> - - <tag><c>EXIT</c></tag> - <item> - <p> - <c>{3, FromPid, ToPid, Reason}</c> - </p> - </item> - - <tag><c>UNLINK</c></tag> - <item> - <p> - <c>{4, FromPid, ToPid}</c> - </p> - </item> - - <tag><c>NODE_LINK</c></tag> - <item> - <p> - <c>{5}</c> - </p> - </item> - - <tag><c>REG_SEND</c></tag> - <item> - <p> - <c>{6, FromPid, Cookie, ToName}</c> - </p> - <p> - <em>Note</em> followed by <c>Message</c> - </p> - </item> - - <tag><c>GROUP_LEADER</c></tag> - <item> - <p> - <c>{7, FromPid, ToPid}</c> - </p> - </item> - - <tag><c>EXIT2</c></tag> - <item> - <p> - <c>{8, FromPid, ToPid, Reason}</c> - </p> - </item> - </taglist> - </section> - - <section> - <title>New Ctrlmessages for distrvsn = 1 (OTP R4)</title> - <taglist> - <tag><c>SEND_TT</c></tag> - <item> - <p> - <c>{12, Cookie, ToPid, TraceToken}</c> - </p> - <p> - <em>Note</em> followed by <c>Message</c> - </p> - </item> + <title>ALIVE_NOTOK_RESP ()</title> + <p>The EPMD closed the connection.</p> + </section> - <tag><c>EXIT_TT</c></tag> - <item> - <p> - <c>{13, FromPid, ToPid, TraceToken, Reason}</c> - </p> - </item> - - <tag><c>REG_SEND_TT</c></tag> - <item> - <p> - <c>{16, FromPid, Cookie, ToName, TraceToken}</c> - </p> - <p> - <em>Note</em> followed by <c>Message</c> - </p> - </item> - - <tag><c>EXIT2_TT</c></tag> - <item> - <p> - <c>{18, FromPid, ToPid, TraceToken, Reason}</c> - </p> - </item> - </taglist> + <section> + <title>PORT_PLEASE_REQ (112)</title> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">n</cell> + </row> + <row> + <cell align="center"><c>112</c></cell> + <cell align="center"><c>NodeName</c></cell> + </row> + <tcaption></tcaption> + </table> + + <p>where n = <c>Length</c> - 1.</p> </section> - + <section> - <title>New Ctrlmessages for distrvsn = 2</title> - <p> - distrvsn 2 was never used. - </p> + <title>PORT_OK_RESP ()</title> + <table align="left"> + <row> + <cell align="center">2</cell> + </row> + <row> + <cell align="center"><c>PortNo</c></cell> + </row> + <tcaption></tcaption> + </table> </section> - + <section> - <title>New Ctrlmessages for distrvsn = 3 (OTP R5C)</title> - <p> - None, but the version number was increased anyway. - </p> + <title>PORT_NOTOK_RESP ()</title> + <p>The EPMD closed the connection.</p> + </section> + + <section> + <title>PORT_NOTOK_RESP ()</title> + <p>The EPMD closed the connection.</p> + </section> +--> + </section> + + <section> + <marker id="distribution_handshake"/> + <title>Distribution Handshake</title> + <p>This section describes the distribution handshake protocol introduced + in Erlang/OTP R6. This description was previously located in + <c>$ERL_TOP/lib/kernel/internal_doc/distribution_handshake.txt</c> and + has more or less been copied and "formatted" here. It has been almost + unchanged since 1999, but the handshake has not changed much since then + either.</p> + + <section> + <title>General</title> + <p>The TCP/IP distribution uses a handshake that expects a + connection-based protocol, that is, the protocol does not include any + authentication after the handshake procedure.</p> + + <p>This is not entirely safe, as it is vulnerable against takeover + attacks, but it is a tradeoff between fair safety and performance.</p> + + <p>The cookies are never sent in cleartext and the handshake procedure + expects the client (called <c>A</c>) to be the first one to prove that + it can generate a sufficient digest. The digest is generated with the + MD5 message digest algorithm and the challenges are expected to be + random numbers.</p> + </section> + + <section> + <title>Definitions</title> + <p>A challenge is a 32-bit integer in big-endian order. Below the function + <c>gen_challenge()</c> returns a random 32-bit integer used as a + challenge.</p> + + <p>A digest is a (16 bytes) MD5 hash of the challenge (as text) + concatenated with the cookie (as text). Below, the function + <c>gen_digest(Challenge, Cookie)</c> generates a digest as described + above.</p> + + <p>An <c>out_cookie</c> is the cookie used in outgoing communication to a + certain node, so that <c>A</c>'s <c>out_cookie</c> for <c>B</c> is to + correspond with <c>B</c>'s <c>in_cookie</c> for <c>A</c> and conversely. + <c>A</c>'s <c>out_cookie</c> for <c>B</c> and <c>A</c>'s + <c>in_cookie</c> for <c>B</c> need <em>not</em> be the same. Below the + function <c>out_cookie(Node)</c> returns the current node's + <c>out_cookie</c> for <c>Node</c>.</p> + + <p>An <c>in_cookie</c> is the cookie expected to be used by another node + when communicating with us, so that <c>A</c>'s <c>in_cookie</c> for + <c>B</c> corresponds with <c>B</c>'s <c>out_cookie</c> for <c>A</c>. + Below the function <c>in_cookie(Node)</c> returns the current node's + <c>in_cookie</c> for <c>Node</c>.</p> + + <p>The cookies are text strings that can be viewed as passwords.</p> + + <p>Every message in the handshake starts with a 16-bit big-endian integer, + which contains the message length (not counting the two initial bytes). + In Erlang this corresponds to option <c>{packet, 2}</c> in + <seealso marker="kernel:gen_tcp"><c>gen_tcp(3)</c></seealso>. + Notice that after the handshake, the distribution switches to 4 byte + packet headers.</p> </section> <section> - <title>New Ctrlmessages for distrvsn = 4 (OTP R6)</title> + <title>The Handshake in Detail</title> + <p>Imagine two nodes, <c>A</c> that initiates the handshake and <c>B</c> + that accepts the connection.</p> + + <taglist> + <tag>1) connect/accept</tag> + <item> + <p><c>A</c> connects to <c>B</c> through TCP/IP and <c>B</c> accepts + the connection.</p> + </item> + <tag>2) <c>send_name</c>/<c>receive_name</c></tag> + <item> + <p><c>A</c> sends an initial identification to <c>B</c>, which + receives the message. The message looks as follows (every "square" + is one byte and the packet header is removed):</p> + <pre> ++---+--------+--------+-----+-----+-----+-----+-----+-----+-...-+-----+ +|'n'|Version0|Version1|Flag0|Flag1|Flag2|Flag3|Name0|Name1| ... |NameN| ++---+--------+--------+-----+-----+-----+-----+-----+-----+-... +-----+</pre> + <p>'n' is the message tag. 'Version0' and 'Version1' is the + distribution version selected by <c>A</c>, based on information + from the EPMD. (16-bit big-endian) 'Flag0' ... 'Flag3' are + capability flags, the capabilities are defined in + <c>$ERL_TOP/lib/kernel/include/dist.hrl</c>. (32-bit big-endian) + 'Name0' ... 'NameN' is the full node name of <c>A</c>, as a string + of bytes (the packet length denotes how long it is).</p> + </item> + <tag>3) <c>recv_status</c>/<c>send_status</c></tag> + <item> + <p><c>B</c> sends a status message to <c>A</c>, which indicates if the + connection is allowed. The following status codes are defined:</p> + <taglist> + <tag><c>ok</c></tag> + <item> + <p>The handshake will continue.</p> + </item> + <tag><c>ok_simultaneous</c></tag> + <item> + <p>The handshake will continue, but <c>A</c> is informed that + <c>B</c> has another ongoing connection attempt that will be + shut down (simultaneous connect where <c>A</c>'s name is + greater than <c>B</c>'s name, compared literally).</p> + </item> + <tag><c>nok</c></tag> + <item> + <p>The handshake will not continue, as <c>B</c> already has an + ongoing handshake, which it itself has initiated (simultaneous + connect where <c>B</c>'s name is greater than <c>A</c>'s).</p> + </item> + <tag><c>not_allowed</c></tag> + <item> + <p>The connection is disallowed for some (unspecified) security + reason.</p> + </item> + <tag><c>alive</c></tag> + <item> + <p>A connection to the node is already active, which either means + that node <c>A</c> is confused or that the TCP connection + breakdown of a previous node with this name has not yet reached + node <c>B</c>. See step 3B below.</p> + </item> + </taglist> + <p>The format of the status message is as follows:</p> + <pre> ++---+-------+-------+-...-+-------+ +|'s'|Status0|Status1| ... |StatusN| ++---+-------+-------+-...-+-------+</pre> + <p>'s' is the message tag. 'Status0' ... 'StatusN' is the status as a + string (not terminated).</p> + </item> + <tag>3B) <c>send_status</c>/<c>recv_status</c></tag> + <item> + <p>If status was <c>alive</c>, node <c>A</c> answers with another + status message containing either <c>true</c>, which means that the + connection is to continue (the old connection from this node is + broken), or <c>false</c>, which means that the connection is to be + closed (the connection attempt was a mistake.</p> + </item> + <tag>4) <c>recv_challenge</c>/<c>send_challenge</c></tag> + <item> + <p>If the status was <c>ok</c> or <c>ok_simultaneous</c>, the + handshake continues with <c>B</c> sending <c>A</c> another message, + the challenge. The challenge contains the same type of information + as the "name" message initially sent from <c>A</c> to <c>B</c>, plus + a 32-bit challenge:</p> + <pre> ++---+--------+--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-...-+-----+ +|'n'|Version0|Version1|Flag0|Flag1|Flag2|Flag3|Chal0|Chal1|Chal2|Chal3|Name0|Name1| ... |NameN| ++---+--------+--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-... +-----+</pre> + <p>'Chal0' ... 'Chal3' is the challenge as a 32-bit big-endian integer + and the other fields are <c>B</c>'s version, flags, and full node + name.</p> + </item> + <tag>5) <c>send_challenge_reply</c>/<c>recv_challenge_reply</c></tag> + <item> + <p>Now <c>A</c> has generated a digest and its own challenge. Those + are sent together in a package to <c>B</c>:</p> + <pre> ++---+-----+-----+-----+-----+-----+-----+-----+-----+-...-+------+ +|'r'|Chal0|Chal1|Chal2|Chal3|Dige0|Dige1|Dige2|Dige3| ... |Dige15| ++---+-----+-----+-----+-----+-----+-----+-----+-----+-...-+------+</pre> + <p>'r' is the tag. 'Chal0' ... 'Chal3' is <c>A</c>'s challenge for + <c>B</c> to handle. 'Dige0' ... 'Dige15' is the digest that <c>A</c> + constructed from the challenge <c>B</c> sent in the previous + step.</p> + </item> + <tag>6) <c>recv_challenge_ack</c>/<c>send_challenge_ack</c></tag> + <item> + <p><c>B</c> checks that the digest received from <c>A</c> is correct + and generates a digest from the challenge received from <c>A</c>. + The digest is then sent to <c>A</c>. The message is as follows:</p> + <pre> ++---+-----+-----+-----+-----+-...-+------+ +|'a'|Dige0|Dige1|Dige2|Dige3| ... |Dige15| ++---+-----+-----+-----+-----+-...-+------+</pre> + <p>'a' is the tag. 'Dige0' ... 'Dige15' is the digest calculated by + <c>B</c> for <c>A</c>'s challenge.</p> + </item> + <tag>7) check</tag> + <item> + <p><c>A</c> checks the digest from <c>B</c> and the connection is + up.</p> + </item> + </taglist> + </section> + + <section> + <title>Semigraphic View</title> + <pre> +A (initiator) B (acceptor) + +TCP connect ------------------------------------> + TCP accept + +send_name --------------------------------------> + recv_name + + <---------------------------------------------- send_status +recv_status +(if status was 'alive' + send_status - - - - - - - - - - - - - - - - - -> + recv_status) + ChB = gen_challenge() + (ChB) + <---------------------------------------------- send_challenge +recv_challenge +ChA = gen_challenge(), +OCA = out_cookie(B), +DiA = gen_digest(ChB, OCA) + (ChA, DiA) +send_challenge_reply ---------------------------> + recv_challenge_reply + ICB = in_cookie(A), + check: + DiA == gen_digest (ChB, ICB)? + - if OK: + OCB = out_cookie(A), + DiB = gen_digest (ChA, OCB) + (DiB) + <----------------------------------------------- send_challenge_ack +recv_challenge_ack DONE +ICA = in_cookie(B), - else: +check: CLOSE +DiB == gen_digest(ChA, ICA)? +- if OK: + DONE +- else: + CLOSE</pre> + </section> + + <section> + <marker id="dflags"/> + <title>Distribution Flags</title> + <p>The following capability flags are defined:</p> + <taglist> + <tag><c>-define(DFLAG_PUBLISHED,16#1).</c></tag> + <item> + <p>The node is to be published and part of the global namespace.</p> + </item> + <tag><c>-define(DFLAG_ATOM_CACHE,16#2).</c></tag> + <item> + <p>The node implements an atom cache (obsolete).</p> + </item> + <tag><c>-define(DFLAG_EXTENDED_REFERENCES,16#4).</c></tag> + <item> + <p>The node implements extended (3 × 32 bits) references. This + is required today. If not present, the connection is refused.</p> + </item> + <tag><c>-define(DFLAG_DIST_MONITOR,16#8).</c></tag> + <item> + <p>The node implements distributed process monitoring.</p> + </item> + <tag><c>-define(DFLAG_FUN_TAGS,16#10).</c></tag> + <item> + <p>The node uses separate tag for funs (lambdas) in the distribution + protocol.</p> + </item> + <tag><c>-define(DFLAG_DIST_MONITOR_NAME,16#20).</c></tag> + <item> + <p>The node implements distributed named process monitoring.</p> + </item> + <tag><c>-define(DFLAG_HIDDEN_ATOM_CACHE,16#40).</c></tag> + <item> + <p>The (hidden) node implements atom cache (obsolete).</p> + </item> + <tag><c>-define(DFLAG_NEW_FUN_TAGS,16#80).</c></tag> + <item> + <p>The node understand new fun tags.</p> + </item> + <tag><c>-define(DFLAG_EXTENDED_PIDS_PORTS,16#100).</c></tag> + <item> + <p>The node can handle extended pids and ports. This is required + today. If not present, the connection is refused.</p> + </item> + <tag><c>-define(DFLAG_EXPORT_PTR_TAG,16#200).</c></tag> + <item> + </item> + <tag><c>-define(DFLAG_BIT_BINARIES,16#400).</c></tag> + <item> + </item> + <tag><c>-define(DFLAG_NEW_FLOATS,16#800).</c></tag> + <item> + <p>The node understands new float format.</p> + </item> + <tag><c>-define(DFLAG_UNICODE_IO,16#1000).</c></tag> + <item> + </item> + <tag><c>-define(DFLAG_DIST_HDR_ATOM_CACHE,16#2000).</c></tag> + <item> + <p>The node implements atom cache in distribution header.</p> + </item> + <tag><c>-define(DFLAG_SMALL_ATOM_TAGS, 16#4000).</c></tag> + <item> + <p>The node understand the <c>SMALL_ATOM_EXT</c> tag.</p> + </item> + <tag><c>-define(DFLAG_UTF8_ATOMS, 16#10000).</c></tag> + <item> + <p>The node understand UTF-8 encoded atoms.</p> + </item> + <tag><c>-define(DFLAG_MAP_TAG, 16#20000).</c></tag> + <item> + <p>The node understand the map tag.</p> + </item> + <tag><c>-define(DFLAG_BIG_CREATION, 16#40000).</c></tag> + <item> + <p>The node understand big node creation.</p> + </item> + <tag><c>-define(DFLAG_SEND_SENDER, 16#80000).</c></tag> + <item> + <p> + Use the <c>SEND_SENDER</c> + <seealso marker="#control_message">control message</seealso> + instead of the <c>SEND</c> control message and use the + <c>SEND_SENDER_TT</c> control message instead + of the <c>SEND_TT</c> control message. + </p> + </item> + </taglist> <p> - These are only recognized by Erlang nodes, not by hidden nodes. + There is also function <c>dist_util:strict_order_flags/0</c> + returning all flags (bitwise or:ed together) corresponding to features + that require strict ordering of data over distribution channels. </p> - <taglist> - <tag><c>MONITOR_P</c></tag> - <item> - <p> - <c>{19, FromPid, ToProc, Ref}</c> - - <c>FromPid</c> = monitoring process - <c>ToProc</c> = monitored process pid or name (atom) - </p> - </item> - - <tag><c>DEMONITOR_P</c></tag> - <item> + </section> + </section> + + <section> + <marker id="connected_nodes"/> + <title>Protocol between Connected Nodes</title> + <p>As from ERTS 5.7.2 the runtime system passes a distribution flag + in the handshake stage that enables the use of a + <seealso marker="erl_ext_dist#distribution_header">distribution header + </seealso> on all messages passed. Messages passed between nodes have in + this case the following format:</p> + + <table align="left"> + <row> + <cell align="center">4</cell> + <cell align="center">d</cell> + <cell align="center">n</cell> + <cell align="center">m</cell> + </row> + <row> + <cell align="center"><c>Length</c></cell> + <cell align="center"><c>DistributionHeader</c></cell> + <cell align="center"><c>ControlMessage</c></cell> + <cell align="center"><c>Message</c></cell> + </row> + <tcaption>Format of Messages Passed between Nodes (as from ERTS 5.7.2) + </tcaption> + </table> + + <taglist> + <tag><c>Length</c></tag> + <item> + <p>Equal to d + n + m.</p> + </item> + <tag><c>ControlMessage</c></tag> + <item> + <p>A tuple passed using the external format of Erlang.</p> + </item> + <tag><c>Message</c></tag> + <item> + <p>The message sent to another node using the '!' (in external format). + Notice that <c>Message</c> is only passed in combination with a + <c>ControlMessage</c> encoding a send ('!').</p> + </item> + </taglist> + + <p>Notice that <seealso marker="erl_ext_dist#overall_format">the version + number is omitted from the terms that follow a distribution header + </seealso>.</p> + + <p>Nodes with an ERTS version earlier than 5.7.2 does not pass the + distribution flag that enables the distribution header. Messages passed + between nodes have in this case the following format:</p> + + <table align="left"> + <row> + <cell align="center">4</cell> + <cell align="center">1</cell> + <cell align="center">n</cell> + <cell align="center">m</cell> + </row> + <row> + <cell align="center"><c>Length</c></cell> + <cell align="center"><c>Type</c></cell> + <cell align="center"><c>ControlMessage</c></cell> + <cell align="center"><c>Message</c></cell> + </row> + <tcaption>Format of Messages Passed between Nodes (before ERTS 5.7.2) + </tcaption> + </table> + + <taglist> + <tag><c>Length</c></tag> + <item> + <p>Equal to 1 + n + m.</p> + </item> + <tag><c>Type</c></tag> + <item> + <p>Equal to <c>112</c> (pass through).</p> + </item> + <tag><c>ControlMessage</c></tag> + <item> + <p>A tuple passed using the external format of Erlang.</p> + </item> + <tag><c>Message</c></tag> + <item> + <p>The message sent to another node using the '!' (in external format). + Notice that <c>Message</c> is only passed in combination with a + <c>ControlMessage</c> encoding a send ('!').</p> + </item> + </taglist> + + <marker id="control_message"/> + <p>The <c>ControlMessage</c> is a tuple, where the first element indicates + which distributed operation it encodes:</p> + + <taglist> + <tag><c>LINK</c></tag> + <item> + <p><c>{1, FromPid, ToPid}</c></p> + </item> + <tag><c>SEND</c></tag> + <item> + <p><c>{2, Unused, ToPid}</c></p> + <p>Followed by <c>Message</c>.</p> + <p><c>Unused</c> is kept for backward compatibility.</p> + </item> + <tag><c>EXIT</c></tag> + <item> + <p><c>{3, FromPid, ToPid, Reason}</c></p> + </item> + <tag><c>UNLINK</c></tag> + <item> + <p><c>{4, FromPid, ToPid}</c></p> + </item> + <tag><c>NODE_LINK</c></tag> + <item> + <p><c>{5}</c></p> + </item> + <tag><c>REG_SEND</c></tag> + <item> + <p><c>{6, FromPid, Unused, ToName}</c></p> + <p>Followed by <c>Message</c>.</p> + <p><c>Unused</c> is kept for backward compatibility.</p> + </item> + <tag><c>GROUP_LEADER</c></tag> + <item> + <p><c>{7, FromPid, ToPid}</c></p> + </item> + <tag><c>EXIT2</c></tag> + <item> + <p><c>{8, FromPid, ToPid, Reason}</c></p> + </item> + </taglist> + </section> + + <section> + <title>New Ctrlmessages for distrvsn = 1 (Erlang/OTP R4)</title> + <taglist> + <tag><c>SEND_TT</c></tag> + <item> + <p><c>{12, Unused, ToPid, TraceToken}</c></p> + <p>Followed by <c>Message</c>.</p> + <p><c>Unused</c> is kept for backward compatibility.</p> + </item> + <tag><c>EXIT_TT</c></tag> + <item> + <p><c>{13, FromPid, ToPid, TraceToken, Reason}</c></p> + </item> + <tag><c>REG_SEND_TT</c></tag> + <item> + <p><c>{16, FromPid, Unused, ToName, TraceToken}</c></p> + <p>Followed by <c>Message</c>.</p> + <p><c>Unused</c> is kept for backward compatibility.</p> + </item> + <tag><c>EXIT2_TT</c></tag> + <item> + <p><c>{18, FromPid, ToPid, TraceToken, Reason}</c></p> + </item> + </taglist> + </section> + + <section> + <title>New Ctrlmessages for distrvsn = 2</title> + <p><c>distrvsn</c> 2 was never used.</p> + </section> + + <section> + <title>New Ctrlmessages for distrvsn = 3 (Erlang/OTP R5C)</title> + <p>None, but the version number was increased anyway.</p> + </section> + + <section> + <title>New Ctrlmessages for distrvsn = 4 (Erlang/OTP R6)</title> + <p>These are only recognized by Erlang nodes, not by hidden nodes.</p> + + <taglist> + <tag><c>MONITOR_P</c></tag> + <item> + <p><c>{19, FromPid, ToProc, Ref}</c>, where + <c>FromPid</c> = monitoring process and + <c>ToProc</c> = monitored process pid or name (atom)</p> + </item> + <tag><c>DEMONITOR_P</c></tag> + <item> + <p><c>{20, FromPid, ToProc, Ref}</c>, where + <c>FromPid</c> = monitoring process and + <c>ToProc</c> = monitored process pid or name (atom)</p> + <p>We include <c>FromPid</c> just in case we want to trace this.</p> + </item> + <tag><c>MONITOR_P_EXIT</c></tag> + <item> + <p><c>{21, FromProc, ToPid, Ref, Reason}</c>, where + <c>FromProc</c> = monitored process pid or name (atom), + <c>ToPid</c> = monitoring process, and + <c>Reason</c> = exit reason for the monitored process</p> + </item> + </taglist> + </section> + + <section> + <title>New Ctrlmessages for Erlang/OTP 21</title> + <taglist> + <tag><c>SEND_SENDER</c></tag> + <item> + <p><c>{22, FromPid, ToPid}</c></p> + <p>Followed by <c>Message</c>.</p> <p> - <c>{20, FromPid, ToProc, Ref}</c> - We include the FromPid just in case we want to trace this. - - <c>FromPid</c> = monitoring process - <c>ToProc</c> = monitored process pid or name (atom) + This control messages replace the <c>SEND</c> control + message and will be sent when the distribution flag + <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_SEND_SENDER</c></seealso> + has been negotiated in the connection setup handshake. </p> - </item> - - <tag><c>MONITOR_P_EXIT</c></tag> - <item> + <note><p> + Messages encoded before the connection has + been set up may still use the <c>SEND</c> control + message. However, once a <c>SEND_SENDER</c> or <c>SEND_SENDER_TT</c> + control message has been sent, no more <c>SEND</c> + control messages will be sent in the same direction + on the connection. + </p></note> + </item> + <tag><c>SEND_SENDER_TT</c></tag> + <item> + <p><c>{23, FromPid, ToPid, TraceToken}</c></p> + <p>Followed by <c>Message</c>.</p> <p> - <c>{21, FromProc, ToPid, Ref, Reason}</c> - - <c>FromProc</c> = monitored process pid or name (atom) - <c>ToPid</c> = monitoring process - <c>Reason</c> = exit reason for the monitored process + This control messages replace the <c>SEND_TT</c> control + message and will be sent when the distribution flag + <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_SEND_SENDER</c></seealso> + has been negotiated in the connection setup handshake. </p> - </item> - </taglist> - </section> - </chapter> + <note><p> + Messages encoded before the connection has + been set up may still use the <c>SEND_TT</c> control + message. However, once a <c>SEND_SENDER</c> or <c>SEND_SENDER_TT</c> + control message has been sent, no more <c>SEND_TT</c> + control messages will be sent in the same direction + on the connection. + </p></note> + </item> + </taglist> + </section> + +</chapter> diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml index 77fc906aca..7055889e4a 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -4,23 +4,23 @@ <cref> <header> <copyright> - <year>2001</year><year>2014</year> + <year>2001</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> - <title>erl_driver</title> <prepared>Jakob Cederlund</prepared> <responsible>Jakob Cederlund</responsible> @@ -32,509 +32,545 @@ <file>erl_driver.xml</file> </header> <lib>erl_driver</lib> - <libsummary>API functions for an Erlang driver</libsummary> + <libsummary>API functions for an Erlang driver.</libsummary> <description> <p>An Erlang driver is a library containing a set of native driver - callback functions that the Erlang VM calls when certain - events occur. There may be multiple instances of a driver, each + callback functions that the Erlang Virtual Machine calls when certain + events occur. There can be multiple instances of a driver, each instance is associated with an Erlang port.</p> + <marker id="WARNING"/> - <warning><p><em>Use this functionality with extreme care!</em></p> + <warning> + <p><em>Use this functionality with extreme care.</em></p> <p>A driver callback is executed as a direct extension of the - native code of the VM. Execution is not made in a safe environment. - The VM can <em>not</em> provide the same services as provided when - executing Erlang code, such as preemptive scheduling or memory - protection. If the driver callback function doesn't behave well, - the whole VM will misbehave.</p> - <list> - <item><p>A driver callback that crash will crash the whole VM.</p></item> - <item><p>An erroneously implemented driver callback might cause - a VM internal state inconsistency which may cause a crash of the VM, - or miscellaneous misbehaviors of the VM at any point after the call - to the driver callback.</p></item> - <item><p>A driver callback that do <seealso marker="#lengthy_work">lengthy - work</seealso> before returning will degrade responsiveness of the VM, - and may cause miscellaneous strange behaviors. Such strange behaviors - include, but are not limited to, extreme memory usage, and bad load - balancing between schedulers. Strange behaviors that might occur due - to lengthy work may also vary between OTP releases.</p></item> + native code of the VM. Execution is not made in a safe environment. + The VM <em>cannot</em> provide the same services as provided when + executing Erlang code, such as pre-emptive scheduling or memory + protection. If the driver callback function does not behave well, + the whole VM will misbehave.</p> + <list type="bulleted"> + <item> + <p>A driver callback that crash will crash the whole VM.</p> + </item> + <item> + <p>An erroneously implemented driver callback can cause a VM + internal state inconsistency, which can cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the + call to the driver callback.</p> + </item> + <item> + <p>A driver callback doing + <seealso marker="#lengthy_work">lengthy work</seealso> before + returning degrades responsiveness of the VM and can cause + miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage and bad + load balancing between schedulers. Strange behaviors that can + occur because of lengthy work can also vary between Erlang/OTP + releases.</p> + </item> </list> - </warning> - <p>As of erts version 5.5.3 the driver interface has been extended - (see <seealso marker="driver_entry#extended_marker">extended marker</seealso>). - The extended interface introduce + </warning> + + <p>As from ERTS 5.5.3 the driver interface has been extended + (see <seealso marker="driver_entry#extended_marker"> + <c>extended marker</c></seealso>). The extended interface introduces <seealso marker="#version_management">version management</seealso>, - the possibility to pass capability flags - (see <seealso marker="driver_entry#driver_flags">driver flags</seealso>) - to the runtime system at driver initialization, and some new - driver API functions. </p> + the possibility to pass capability flags (see + <seealso marker="driver_entry#driver_flags"> + <c>driver_flags</c></seealso>) to the runtime system at driver + initialization, and some new driver API functions.</p> + <note> - <p>As of erts version 5.9 old drivers have to be recompiled - and have to use the extended interface. They also have to be - adjusted to the - <seealso marker="#rewrites_for_64_bits">64-bit capable driver interface. - </seealso> - </p> + <p>As from ERTS 5.9 old drivers must be recompiled + and use the extended interface. They must also be adjusted to the + <seealso marker="#rewrites_for_64_bits"> + 64-bit capable driver interface</seealso>.</p> </note> + <p>The driver calls back to the emulator, using the API functions declared in <c>erl_driver.h</c>. They are used for - outputting data from the driver, using timers, etc.</p> + outputting data from the driver, using timers, and so on.</p> + <p>Each driver instance is associated with a port. Every port has a port owner process. Communication with the port is normally done through the port owner process. Most of the functions take the <c>port</c> handle as an argument. This identifies the driver - instance. Note that this port handle must be stored by the driver, + instance. Notice that this port handle must be stored by the driver, it is not given when the driver is called from the emulator (see - <seealso marker="driver_entry#emulator">driver_entry</seealso>).</p> + <seealso marker="driver_entry#emulator"> + <c>driver_entry</c></seealso>).</p> + <p>Some of the functions take a parameter of type - <c>ErlDrvBinary</c>, a driver binary. It should be both + <c>ErlDrvBinary</c>, a driver binary. It is to be both allocated and freed by the caller. Using a binary directly avoids one extra copying of data.</p> + <p>Many of the output functions have a "header buffer", with <c>hbuf</c> and <c>hlen</c> parameters. This buffer is sent as a list before the binary (or list, depending on port mode) that is sent. This is convenient when matching on messages received from - the port. (Although in the latest versions of Erlang, there is - the binary syntax, that enables you to match on the beginning of - a binary.) - <marker id="smp_support"></marker> -</p> - <p>In the runtime system with SMP support, drivers are locked either - on driver level or port level (driver instance level). By default - driver level locking will be used, i.e., only one emulator thread + the port. (Although in the latest Erlang versions there is + the binary syntax, which enables you to match on the beginning of + a binary.)</p> + <p><marker id="smp_support"></marker>In the runtime system with + SMP support, drivers are locked either on driver level + or port level (driver instance level). By default + driver level locking will be used, that is, only one emulator thread will execute code in the driver at a time. If port level locking - is used, multiple emulator threads may execute code in the driver - at the same time. There will only be one thread at a time calling - driver call-backs corresponding to the same port, though. In order - to enable port level locking set the <c>ERL_DRV_FLAG_USE_PORT_LOCKING</c> + is used, multiple emulator threads can execute code in the driver + at the same time. Only one thread at a time will call + driver callbacks corresponding to the same port, though. + To enable port level locking, set the <c>ERL_DRV_FLAG_USE_PORT_LOCKING</c> <seealso marker="driver_entry#driver_flags">driver flag</seealso> in - the <seealso marker="driver_entry">driver_entry</seealso> - used by the driver. When port level locking is used it is the - responsibility of the driver writer to synchronize all accesses + the <seealso marker="driver_entry"><c>driver_entry</c></seealso> + used by the driver. When port level locking is used, + the driver writer is responsible for synchronizing all accesses to data shared by the ports (driver instances).</p> + <p>Most drivers written before the runtime system with SMP - support existed will be able to run in the runtime system - with SMP support without being rewritten if driver + support existed can run in the runtime system + with SMP support, without being rewritten, if driver level locking is used.</p> + <note> <p>It is assumed that drivers do not access other drivers. If - drivers should access each other they have to provide their own - mechanism for thread safe synchronization. Such "inter driver + drivers access each other, they must provide their own + mechanism for thread-safe synchronization. Such "inter-driver communication" is strongly discouraged.</p> </note> + <p>Previously, in the runtime system without SMP support, - specific driver call-backs were always called from the same + specific driver callbacks were always called from the same thread. This is <em>not</em> the case in the runtime system with SMP support. Regardless of locking scheme used, calls - to driver call-backs may be made from different threads, e.g., - two consecutive calls to exactly the same call-back for exactly - the same port may be made from two different threads. This - will for <em>most</em> drivers not be a problem, but it might. - Drivers that depend on all call-backs being called in the - same thread, <em>have</em> to be rewritten before being used + to driver callbacks can be made from different threads. For example, + two consecutive calls to exactly the same callback for exactly + the same port can be made from two different threads. This + is for <em>most</em> drivers not a problem, but it can be. + Drivers that depend on all callbacks that are called in the + same thread, <em>must</em> be rewritten before they are used in the runtime system with SMP support.</p> + <note> <p>Regardless of locking scheme used, calls to driver - call-backs may be made from different threads.</p> + callbacks can be made from different threads.</p> </note> - <p>Most functions in this API are <em>not</em> thread-safe, i.e., - they may <em>not</em> be called from an arbitrary thread. Functions - that are not documented as thread-safe may only be called from - driver call-backs or function calls descending from a driver - call-back call. Note that driver call-backs may be called from + + <p>Most functions in this API are <em>not</em> thread-safe, that is, + they <em>cannot</em> be called from arbitrary threads. Functions + that are not documented as thread-safe can only be called from + driver callbacks or function calls descending from a driver + callback call. Notice that driver callbacks can be called from different threads. This, however, is not a problem for any - function in this API, since the emulator has control over + function in this API, as the emulator has control over these threads.</p> + <warning> - <p>Functions not explicitly documented as thread safe are - <em>not</em> thread safe. Also note that some functions - are <em>only</em> thread safe when used in a runtime + <p>Functions not explicitly documented as thread-safe are + <em>not</em> thread safe. Also notice that some functions + are <em>only</em> thread-safe when used in a runtime system with SMP support.</p> - <p>A function not explicitly documented as thread safe may at - some point in time have a thread safe implementation in the - runtime system. Such an implementation may however change to - a thread <em>unsafe</em> implementation at any time <em>without - any notice</em> at all. - </p> - <p><em>Only use functions explicitly documented as thread safe - from arbitrary threads.</em></p> + <p>A function not explicitly documented as thread-safe can, at + some point in time, have a thread-safe implementation in the + runtime system. Such an implementation can however change to + a thread <em>unsafe</em> implementation at any time <em>without + any notice</em>.</p> + <p><em>Only use functions explicitly documented as thread-safe + from arbitrary threads.</em></p> </warning> - <p><marker id="lengthy_work"/> - As mentioned in the <seealso marker="#WARNING">warning</seealso> text at - the beginning of this document it is of vital importance that a driver callback - does return relatively fast. It is hard to give an exact maximum amount - of time that a driver callback is allowed to work, but as a rule of thumb - a well behaving driver callback should return before a millisecond has - passed. This can be achieved using different approaches. - If you have full control over the code that are to execute in the driver - callback, the best approach is to divide the work into multiple chunks of - work and trigger multiple calls to the - <seealso marker="driver_entry#timeout">timeout callback</seealso> using - zero timeouts. The - <seealso marker="#erl_drv_consume_timeslice"><c>erl_drv_consume_timeslice()</c></seealso> - function can be useful in order to determine when to trigger such - timeout callback calls. It might, however, not always be possible to - implement it this way, e.g. when calling third party libraries. In this - case you typically want to dispatch the work to another thread. - Information about thread primitives can be found below.</p> + + <p><marker id="lengthy_work"/> + As mentioned in the <seealso marker="#WARNING">warning</seealso> text at + the beginning of this section, it is of vital importance that a driver + callback returns relatively fast. It is difficult to give an exact + maximum amount of time that a driver callback is allowed to work, but + usually a well-behaving driver callback is to return within 1 millisecond. + This can be achieved using different approaches. + If you have full control over the code to execute in the driver + callback, the best approach is to divide the work into multiple chunks of + work, and trigger multiple calls to the + <seealso marker="driver_entry#timeout">time-out callback</seealso> using + zero time-outs. Function <seealso marker="#erl_drv_consume_timeslice"> + <c>erl_drv_consume_timeslice</c></seealso> can be useful to + determine when to trigger such time-out callback calls. However, sometimes + it cannot be implemented this way, for example when calling + third-party libraries. In this case, you typically want to dispatch the + work to another thread. Information about thread primitives is provided + below.</p> </description> <section> - <title>FUNCTIONALITY</title> + <title>Functionality</title> <p>All functions that a driver needs to do with Erlang are - performed through driver API functions. There are functions + performed through driver API functions. Functions exist for the following functionality:</p> + <taglist> <tag>Timer functions</tag> - <item>Timer functions are used to control the timer that a driver - may use. The timer will have the emulator call the - <seealso marker="driver_entry#timeout">timeout</seealso> entry - function after a specified time. Only one timer is available - for each driver instance.</item> + <item> + <p>Control the timer that a driver can use. The timer has the + emulator call the <seealso marker="driver_entry#timeout"> + <c>timeout</c></seealso> entry function after a specified time. + Only one timer is available for each driver instance.</p> + </item> <tag>Queue handling</tag> <item> <p>Every driver instance has an associated queue. This queue is a - <c>SysIOVec</c> that works as a buffer. It's mostly used for - the driver to buffer data that should be written to a device, + <c>SysIOVec</c>, which works as a buffer. It is mostly used for + the driver to buffer data that is to be written to a device, it is a byte stream. If the port owner process closes the - driver, and the queue is not empty, the driver will not be + driver, and the queue is not empty, the driver is not closed. This enables the driver to flush its buffers before closing.</p> - <p>The queue can be manipulated from arbitrary threads if - a port data lock is used. See documentation of the - <seealso marker="#ErlDrvPDL">ErlDrvPDL</seealso> type for - more information.</p> + <p>The queue can be manipulated from any threads if + a port data lock is used. For more information, see + <seealso marker="#ErlDrvPDL"><c>ErlDrvPDL</c></seealso>.</p> </item> <tag>Output functions</tag> - <item>With the output functions, the driver sends data back to - the emulator. They will be received as messages by the port owner - process, see <c>open_port/2</c>. The vector function and the - function taking a driver binary are faster, because they avoid - copying the data buffer. There is also a fast way of sending - terms from the driver, without going through the binary term - format.</item> + <item> + <p>With these functions, the driver sends data back to the emulator. + The data is received as messages by the port owner process, see + <seealso marker="erlang:open_port/2"> + <c>erlang:open_port/2</c></seealso>. The vector function and the + function taking a driver binary are faster, as they avoid + copying the data buffer. There is also a fast way of sending + terms from the driver, without going through the binary term + format.</p></item> <tag>Failure</tag> - <item>The driver can exit and signal errors up to Erlang. This is - only for severe errors, when the driver can't possibly keep - open.</item> + <item> + <p>The driver can exit and signal errors up to Erlang. This is + only for severe errors, when the driver cannot possibly keep + open.</p> + </item> <tag>Asynchronous calls</tag> - <item>The latest Erlang versions (R7B and later) has provision for - asynchronous function calls, using a thread pool provided by - Erlang. There is also a select call, that can be used for - asynchronous drivers.</item> - <tag><marker id="multi_threading">Multi-threading</marker></tag> <item> - <p>A POSIX thread like API for multi-threading is provided. The - Erlang driver thread API only provide a subset of the functionality - provided by the POSIX thread API. The subset provided is - more or less the basic functionality needed for multi-threaded - programming: - </p> - <list> - <item><seealso marker="#ErlDrvTid">Threads</seealso></item> - <item><seealso marker="#ErlDrvMutex">Mutexes</seealso></item> - <item><seealso marker="#ErlDrvCond">Condition variables</seealso></item> - <item><seealso marker="#ErlDrvRWLock">Read/Write locks</seealso></item> - <item><seealso marker="#ErlDrvTSDKey">Thread specific data</seealso></item> - </list> - <p>The Erlang driver thread API can be used in conjunction with - the POSIX thread API on UN-ices and with the Windows native thread - API on Windows. The Erlang driver thread API has the advantage of - being portable, but there might exist situations where you want to - use functionality from the POSIX thread API or the Windows - native thread API. - </p> - <p>The Erlang driver thread API only returns error codes when it is - reasonable to recover from an error condition. If it isn't reasonable - to recover from an error condition, the whole runtime system is - terminated. For example, if a create mutex operation fails, an error - code is returned, but if a lock operation on a mutex fails, the - whole runtime system is terminated. - </p> - <p>Note that there exists no "condition variable wait with timeout" in - the Erlang driver thread API. This is due to issues with - <c>pthread_cond_timedwait()</c>. When the system clock suddenly - is changed, it isn't always guaranteed that you will wake up from - the call as expected. An Erlang runtime system has to be able to - cope with sudden changes of the system clock. Therefore, we have - omitted it from the Erlang driver thread API. In the Erlang driver - case, timeouts can and should be handled with the timer functionality - of the Erlang driver API. - </p> - <p>In order for the Erlang driver thread API to function, thread - support has to be enabled in the runtime system. An Erlang driver - can check if thread support is enabled by use of - <seealso marker="#driver_system_info">driver_system_info()</seealso>. - Note that some functions in the Erlang driver API are thread-safe - only when the runtime system has SMP support, also this - information can be retrieved via - <seealso marker="#driver_system_info">driver_system_info()</seealso>. - Also note that a lot of functions in the Erlang driver API are - <em>not</em> thread-safe regardless of whether SMP support is - enabled or not. If a function isn't documented as thread-safe it - is <em>not</em> thread-safe. - </p> - <p><em>NOTE</em>: When executing in an emulator thread, it is - <em>very important</em> that you unlock <em>all</em> locks you - have locked before letting the thread out of your control; - otherwise, you are <em>very likely</em> to deadlock the whole - emulator. If you need to use thread specific data in an emulator - thread, only have the thread specific data set while the thread is - under your control, and clear the thread specific data before - you let the thread out of your control. - </p> - <p>In the future there will probably be debug functionality - integrated with the Erlang driver thread API. All functions - that create entities take a <c>name</c> argument. Currently - the <c>name</c> argument is unused, but it will be used when - the debug functionality has been implemented. If you name all - entities created well, the debug functionality will be able - to give you better error reports. - </p> + <p>Erlang/OTP R7B and later versions have provision for + asynchronous function calls, using a thread pool provided by + Erlang. There is also a select call, which can be used for + asynchronous drivers.</p> + </item> + <tag><marker id="multi_threading"/>Multi-threading</tag> + <item> + <p>A POSIX thread like API for multi-threading is provided. The + Erlang driver thread API only provides a subset of the functionality + provided by the POSIX thread API. The subset provided is + more or less the basic functionality needed for multi-threaded + programming:</p> + <list> + <item><seealso marker="#ErlDrvTid">Threads</seealso></item> + <item><seealso marker="#ErlDrvMutex">Mutexes</seealso></item> + <item><seealso marker="#ErlDrvCond"> + Condition variables</seealso></item> + <item><seealso marker="#ErlDrvRWLock"> + Read/write locks</seealso></item> + <item><seealso marker="#ErlDrvTSDKey"> + Thread-specific data</seealso></item> + </list> + <p>The Erlang driver thread API can be used in conjunction with + the POSIX thread API on UN-ices and with the Windows native thread + API on Windows. The Erlang driver thread API has the advantage of + being portable, but there can exist situations where you want to + use functionality from the POSIX thread API or the Windows + native thread API.</p> + <p>The Erlang driver thread API only returns error codes when it is + reasonable to recover from an error condition. If it is not reasonable + to recover from an error condition, the whole runtime system is + terminated. For example, if a create mutex operation fails, an error + code is returned, but if a lock operation on a mutex fails, the + whole runtime system is terminated.</p> + <p>Notice that there is no "condition variable wait with time-out" in + the Erlang driver thread API. This because of issues with + <c>pthread_cond_timedwait</c>. When the system clock suddenly + is changed, it is not always guaranteed that you will wake up from + the call as expected. An Erlang runtime system must be able to + cope with sudden changes of the system clock. Therefore, we have + omitted it from the Erlang driver thread API. In the Erlang driver + case, time-outs can and are to be handled with the timer functionality + of the Erlang driver API.</p> + <p>In order for the Erlang driver thread API to function, thread + support must be enabled in the runtime system. An Erlang driver + can check if thread support is enabled by use of + <seealso marker="#driver_system_info"> + <c>driver_system_info</c></seealso>. + Notice that some functions in the Erlang driver API are thread-safe + only when the runtime system has SMP support, also this + information can be retrieved through + <seealso marker="#driver_system_info"> + <c>driver_system_info</c></seealso>. + Also notice that many functions in the Erlang driver API are + <em>not</em> thread-safe, regardless of whether SMP support is + enabled or not. If a function is not documented as thread-safe, it + is <em>not</em> thread-safe.</p> + <note> + <p>When executing in an emulator thread, it is + <em>very important</em> that you unlock <em>all</em> locks you + have locked before letting the thread out of your control; + otherwise you are <em>very likely</em> to deadlock the whole + emulator.</p> + <p>If you need to use thread-specific data in an emulator + thread, only have the thread-specific data set while the thread is + under your control, and clear the thread-specific data before + you let the thread out of your control.</p> + </note> + <p>In the future, debug functionality will probably be + integrated with the Erlang driver thread API. All functions + that create entities take a <c>name</c> argument. Currently + the <c>name</c> argument is unused, but it will be used when + the debug functionality is implemented. If you name all + entities created well, the debug functionality will be able + to give you better error reports.</p> + </item> + <tag>Adding/removing drivers</tag> + <item> + <p>A driver can add and later remove drivers.</p> </item> - <tag>Adding / removing drivers</tag> - <item><p>A driver can add and later remove drivers.</p></item> <tag>Monitoring processes</tag> - <item><p>A driver can monitor a process that does not own a port.</p></item> - <tag><marker id="version_management">Version management</marker></tag> + <item> + <p>A driver can monitor a process that does not own a port.</p> + </item> + <tag><marker id="version_management"/>Version management</tag> <item> <p>Version management is enabled for drivers that have set the - <seealso marker="driver_entry#extended_marker">extended_marker</seealso> - field of their - <seealso marker="driver_entry">driver_entry</seealso> - to <c>ERL_DRV_EXTENDED_MARKER</c>. <c>erl_driver.h</c> defines - <c>ERL_DRV_EXTENDED_MARKER</c>, - <c>ERL_DRV_EXTENDED_MAJOR_VERSION</c>, and - <c>ERL_DRV_EXTENDED_MINOR_VERSION</c>. - <c>ERL_DRV_EXTENDED_MAJOR_VERSION</c> will be incremented when - driver incompatible changes are made to the Erlang runtime - system. Normally it will suffice to recompile drivers when the - <c>ERL_DRV_EXTENDED_MAJOR_VERSION</c> has changed, but it - could, under rare circumstances, mean that drivers have to - be slightly modified. If so, this will of course be documented. - <c>ERL_DRV_EXTENDED_MINOR_VERSION</c> will be incremented when - new features are added. The runtime system uses the minor version - of the driver to determine what features to use. - The runtime system will normally refuse to load a driver if the major + <seealso marker="driver_entry#extended_marker"> + <c>extended_marker</c></seealso> field of their + <seealso marker="driver_entry"><c>driver_entry</c></seealso> + to <c>ERL_DRV_EXTENDED_MARKER</c>. <c>erl_driver.h</c> defines:</p> + <list type="bulleted"> + <item> + <p><c>ERL_DRV_EXTENDED_MARKER</c></p> + </item> + <item> + <p><c>ERL_DRV_EXTENDED_MAJOR_VERSION</c>, which is incremented when + driver incompatible changes are made to the Erlang runtime + system. Normally it suffices to recompile drivers when + <c>ERL_DRV_EXTENDED_MAJOR_VERSION</c> has changed, but it + can, under rare circumstances, mean that drivers must + be slightly modified. If so, this will of course be + documented.</p> + </item> + <item> + <p><c>ERL_DRV_EXTENDED_MINOR_VERSION</c>, which is incremented when + new features are added. The runtime system uses the minor version + of the driver to determine what features to use.</p> + </item> + </list> + <p>The runtime system normally refuses to load a driver if the major versions differ, or if the major versions are equal and the minor version used by the driver is greater than the one used by the runtime system. Old drivers with lower major versions - will however be allowed after a bump of the major version during - a transition period of two major releases. Such old drivers might - however fail if deprecated features are used.</p> - <p>The emulator will refuse to load a driver that does not use - the extended driver interface, - to allow for 64-bit capable drivers, - since incompatible type changes for the callbacks - <seealso marker="driver_entry#output">output</seealso>, - <seealso marker="driver_entry#control">control</seealso> and - <seealso marker="driver_entry#call">call</seealso> - were introduced in release R15B. A driver written - with the old types would compile with warnings and when - called return garbage sizes to the emulator causing it - to read random memory and create huge incorrect result blobs.</p> - <p>Therefore it is not enough to just recompile drivers written with - version management for pre-R15B types; the types have to be changed - in the driver suggesting other rewrites especially regarding - size variables. Investigate all warnings when recompiling!</p> - <p>Also, the API driver functions <c>driver_output*</c>, - <c>driver_vec_to_buf</c>, <c>driver_alloc/realloc*</c> - and the <c>driver_*</c> queue functions were changed to have - larger length arguments and return values. This is a - lesser problem since code that passes smaller types - will get them auto converted in the calls and as long as - the driver does not handle sizes that overflow an <c>int</c> - all will work as before.</p> + are however allowed after a bump of the major version during + a transition period of two major releases. Such old drivers can, + however, fail if deprecated features are used.</p> + <p>The emulator refuses to load a driver that does not use + the extended driver interface, to allow for 64-bit capable drivers, + as incompatible type changes for the callbacks + <seealso marker="driver_entry#output"><c>output</c></seealso>, + <seealso marker="driver_entry#control"><c>control</c></seealso>, and + <seealso marker="driver_entry#call"><c>call</c></seealso> + were introduced in Erlang/OTP R15B. A driver written + with the old types would compile with warnings and when + called return garbage sizes to the emulator, causing it + to read random memory and create huge incorrect result blobs.</p> + <p>Therefore it is not enough to only recompile drivers written with + version management for pre R15B types; the types must be changed + in the driver suggesting other rewrites, especially regarding size + variables. <em>Investigate all warnings when recompiling.</em></p> + <p>Also, the API driver functions <c>driver_output*</c> and + <c>driver_vec_to_buf</c>, <c>driver_alloc/realloc*</c>, and the + <c>driver_*</c> queue functions were changed to have + larger length arguments and return values. This is a + lesser problem, as code that passes smaller types + gets them auto-converted in the calls, and as long as + the driver does not handle sizes that overflow an <c>int</c>, + all will work as before.</p> + </item> + <tag><marker id="time_measurement"/>Time measurement</tag> + <item> + <p>Support for time measurement in drivers:</p> + <list type="bulleted"> + <item><seealso marker="#ErlDrvTime"> + <c>ErlDrvTime</c></seealso></item> + <item><seealso marker="#ErlDrvTimeUnit"> + <c>ErlDrvTimeUnit</c></seealso></item> + <item><seealso marker="#erl_drv_monotonic_time"> + <c>erl_drv_monotonic_time</c></seealso></item> + <item><seealso marker="#erl_drv_time_offset"> + <c>erl_drv_time_offset</c></seealso></item> + <item><seealso marker="#erl_drv_convert_time_unit"> + <c>erl_drv_convert_time_unit</c></seealso></item> + </list> </item> </taglist> </section> <section> <marker id="rewrites_for_64_bits"/> - <title> - REWRITES FOR 64-BIT DRIVER INTERFACE - </title> - <p> - For erts-5.9 two new integer types - <seealso marker="#ErlDrvSizeT">ErlDrvSizeT</seealso> and - <seealso marker="#ErlDrvSSizeT">ErlDrvSSizeT</seealso> - were introduced that can hold 64-bit sizes if necessary. - </p> - <p> - To not update a driver and just recompile it probably works + <title>Rewrites for 64-Bit Driver Interface</title> + <p>ERTS 5.9 introduced two new integer types, + <seealso marker="#ErlDrvSizeT"><c>ErlDrvSizeT</c></seealso> and + <seealso marker="#ErlDrvSSizeT"><c>ErlDrvSSizeT</c></seealso>, + which can hold 64-bit sizes if necessary.</p> + + <p>To not update a driver and only recompile, it probably works when building for a 32-bit machine creating a false sense of security. Hopefully that will generate many important warnings. - But when recompiling the same driver later on for a 64-bit machine + But when recompiling the same driver later on for a 64-bit machine, there <em>will</em> be warnings and almost certainly crashes. - So it is a BAD idea to postpone updating the driver and - not fixing the warnings! - </p> - <p> - When recompiling with <c>gcc</c> use the <c>-Wstrict-prototypes</c> - flag to get better warnings. Try to find a similar flag if you - are using some other compiler. - </p> - <p> - Here follows a checklist for rewriting a pre erts-5.9 driver, - most important first. - </p> + So it is a <em>bad</em> idea to postpone updating the driver and + not fixing the warnings.</p> + + <p>When recompiling with <c>gcc</c>, use flag <c>-Wstrict-prototypes</c> + to get better warnings. Try to find a similar flag if you use + another compiler.</p> + + <p>The following is a checklist for rewriting a pre ERTS 5.9 driver, + most important first:</p> + <taglist> <tag>Return types for driver callbacks</tag> <item> - <p> - Rewrite driver callback - <c><seealso marker="driver_entry#control">control</seealso></c> - to use return type <c>ErlDrvSSizeT</c> instead of <c>int</c>. - </p> - <p> - Rewrite driver callback - <c><seealso marker="driver_entry#call">call</seealso></c> - to use return type <c>ErlDrvSSizeT</c> instead of <c>int</c>. - </p> + <p>Rewrite driver callback + <seealso marker="driver_entry#control"><c>control</c></seealso> + to use return type <c>ErlDrvSSizeT</c> instead of <c>int</c>.</p> + <p>Rewrite driver callback + <seealso marker="driver_entry#call"><c>call</c></seealso> + to use return type <c>ErlDrvSSizeT</c> instead of <c>int</c>.</p> <note> - <p> - These changes are essential to not crash the emulator + <p>These changes are essential not to crash the emulator or worse cause malfunction. - Without them a driver may return garbage in the high 32 bits - to the emulator causing it to build a huge result from random - bytes either crashing on memory allocation or succeeding with - a random result from the driver call. - </p> + Without them a driver can return garbage in the high 32 bits + to the emulator, causing it to build a huge result from random + bytes, either crashing on memory allocation or succeeding with + a random result from the driver call.</p> </note> </item> <tag>Arguments to driver callbacks</tag> <item> - <p> - Driver callback - <c><seealso marker="driver_entry#output">output</seealso></c> + <p>Driver callback + <seealso marker="driver_entry#output"><c>output</c></seealso> now gets <c>ErlDrvSizeT</c> as 3rd argument instead - of previously <c>int</c>. - </p> - <p> - Driver callback - <c><seealso marker="driver_entry#control">control</seealso></c> + of previously <c>int</c>.</p> + <p>Driver callback + <seealso marker="driver_entry#control"><c>control</c></seealso> now gets <c>ErlDrvSizeT</c> as 4th and 6th arguments instead - of previously <c>int</c>. - </p> - <p> - Driver callback - <c><seealso marker="driver_entry#call">call</seealso></c> + of previously <c>int</c>.</p> + <p>Driver callback + <seealso marker="driver_entry#call"><c>call</c></seealso> now gets <c>ErlDrvSizeT</c> as 4th and 6th arguments instead - of previously <c>int</c>. - </p> - <p> - Sane compiler's calling conventions probably make these changes + of previously <c>int</c>.</p> + <p>Sane compiler's calling conventions probably make these changes necessary only for a driver to handle data chunks that require - 64-bit size fields (mostly larger than 2 GB since that is what + 64-bit size fields (mostly larger than 2 GB, as that is what an <c>int</c> of 32 bits can hold). But it is possible to think of non-sane calling conventions that would make the driver - callbacks mix up the arguments causing malfunction. - </p> + callbacks mix up the arguments causing malfunction.</p> <note> - <p> - The argument type change is from signed to unsigned which - may cause problems for e.g. loop termination conditions or - error conditions if you just change the types all over the place. - </p> + <p>The argument type change is from signed to unsigned. This + can cause problems for, for example, loop termination conditions or + error conditions if you only change the types all over the place. + </p> </note> </item> <tag>Larger <c>size</c> field in <c>ErlIOVec</c></tag> <item> - <p> - The <c>size</c> field in + <p>The <c>size</c> field in <seealso marker="#ErlIOVec"><c>ErlIOVec</c></seealso> has been changed to <c>ErlDrvSizeT</c> from <c>int</c>. - Check all code that use that field. - </p> - <p> - Automatic type casting probably makes these changes necessary only - for a driver that encounters sizes larger than 32 bits. - </p> + Check all code that use that field.</p> + <p>Automatic type-casting probably makes these changes necessary only + for a driver that encounters sizes > 32 bits.</p> <note> - <p> - The <c>size</c> field changed from signed to unsigned which - may cause problems for e.g. loop termination conditions or - error conditions if you just change the types all over the place. - </p> + <p>The <c>size</c> field changed from signed to unsigned. This + can cause problems for, for example, loop termination conditions or + error conditions if you only change the types all over the place. + </p> </note> </item> <tag>Arguments and return values in the driver API</tag> <item> - <p> - Many driver API functions have changed argument type + <p>Many driver API functions have changed argument type and/or return value to <c>ErlDrvSizeT</c> from mostly <c>int</c>. - Automatic type casting probably makes these changes necessary only - for a driver that encounters sizes larger than 32 bits. - </p> + Automatic type-casting probably makes these changes necessary only + for a driver that encounters sizes > 32 bits.</p> <taglist> - <tag><seealso marker="#driver_output">driver_output</seealso></tag> + <tag><seealso marker="#driver_output"> + <c>driver_output</c></seealso></tag> <item>3rd argument</item> - <tag><seealso marker="#driver_output2">driver_output2</seealso></tag> + <tag><seealso marker="#driver_output2"> + <c>driver_output2</c></seealso></tag> <item>3rd and 5th arguments</item> - <tag> - <seealso marker="#driver_output_binary">driver_output_binary</seealso> - </tag> - <item>3rd 5th and 6th arguments</item> - <tag><seealso marker="#driver_outputv">driver_outputv</seealso></tag> + <tag><seealso marker="#driver_output_binary"> + <c>driver_output_binary</c></seealso></tag> + <item>3rd, 5th, and 6th arguments</item> + <tag><seealso marker="#driver_outputv"> + <c>driver_outputv</c></seealso></tag> <item>3rd and 5th arguments</item> - <tag> - <seealso marker="#driver_vec_to_buf">driver_vec_to_buf</seealso> - </tag> + <tag><seealso marker="#driver_vec_to_buf"> + <c>driver_vec_to_buf</c></seealso></tag> <item>3rd argument and return value</item> - <tag><seealso marker="#driver_alloc">driver_alloc</seealso></tag> + <tag><seealso marker="#driver_alloc"> + <c>driver_alloc</c></seealso></tag> <item>1st argument</item> - <tag><seealso marker="#driver_realloc">driver_realloc</seealso></tag> + <tag><seealso marker="#driver_realloc"> + <c>driver_realloc</c></seealso></tag> <item>2nd argument</item> - <tag> - <seealso marker="#driver_alloc_binary">driver_alloc_binary</seealso> - </tag> + <tag><seealso marker="#driver_alloc_binary"> + <c>driver_alloc_binary</c></seealso></tag> <item>1st argument</item> - <tag> - <seealso marker="#driver_realloc_binary">driver_realloc_binary</seealso> - </tag> + <tag><seealso marker="#driver_realloc_binary"> + <c>driver_realloc_binary</c></seealso></tag> <item>2nd argument</item> - <tag><seealso marker="#driver_enq">driver_enq</seealso></tag> + <tag><seealso marker="#driver_enq"> + <c>driver_enq</c></seealso></tag> <item>3rd argument</item> - <tag><seealso marker="#driver_pushq">driver_pushq</seealso></tag> + <tag><seealso marker="#driver_pushq"> + <c>driver_pushq</c></seealso></tag> <item>3rd argument</item> - <tag><seealso marker="#driver_deq">driver_deq</seealso></tag> + <tag><seealso marker="#driver_deq"> + <c>driver_deq</c></seealso></tag> <item>2nd argument and return value</item> - <tag><seealso marker="#driver_sizeq">driver_sizeq</seealso></tag> - <item>return value</item> - <tag><seealso marker="#driver_enq_bin">driver_enq_bin</seealso></tag> - <item>3rd and 4th argument</item> - <tag><seealso marker="#driver_pushq_bin">driver_pushq_bin</seealso></tag> - <item>3rd and 4th argument</item> - <tag><seealso marker="#driver_enqv">driver_enqv</seealso></tag> + <tag><seealso marker="#driver_sizeq"> + <c>driver_sizeq</c></seealso></tag> + <item>Return value</item> + <tag><seealso marker="#driver_enq_bin"> + <c>driver_enq_bin</c></seealso></tag> + <item>3rd and 4th arguments</item> + <tag><seealso marker="#driver_pushq_bin"> + <c>driver_pushq_bin</c></seealso></tag> + <item>3rd and 4th arguments</item> + <tag><seealso marker="#driver_enqv"> + <c>driver_enqv</c></seealso></tag> <item>3rd argument</item> - <tag><seealso marker="#driver_pushqv">driver_pushqv</seealso></tag> + <tag><seealso marker="#driver_pushqv"> + <c>driver_pushqv</c></seealso></tag> <item>3rd argument</item> - <tag><seealso marker="#driver_peekqv">driver_peekqv</seealso></tag> - <item>return value</item> + <tag><seealso marker="#driver_peekqv"> + <c>driver_peekqv</c></seealso></tag> + <item>Return value</item> </taglist> <note> - <p> - This is a change from signed to unsigned which - may cause problems for e.g. loop termination conditions and - error conditions if you just change the types all over the place. - </p> + <p>This is a change from signed to unsigned. This can cause + problems for, for example, loop termination conditions and error + conditions if you only change the types all over the place.</p> </note> </item> </taglist> </section> <section> - <title>DATA TYPES</title> - + <title>Data Types</title> <taglist> - <tag><marker id="ErlDrvSizeT"/>ErlDrvSizeT</tag> - <item><p>An unsigned integer type to be used as <c>size_t</c></p></item> - <tag><marker id="ErlDrvSSizeT"/>ErlDrvSSizeT</tag> - <item><p>A signed integer type the size of <c>ErlDrvSizeT</c></p></item> - <tag><marker id="ErlDrvSysInfo"/>ErlDrvSysInfo</tag> + <tag><marker id="ErlDrvSizeT"/><c>ErlDrvSizeT</c></tag> + <item> + <p>An unsigned integer type to be used as <c>size_t</c>.</p> + </item> + <tag><marker id="ErlDrvSSizeT"/><c>ErlDrvSSizeT</c></tag> + <item> + <p>A signed integer type, the size of <c>ErlDrvSizeT</c>.</p> + </item> + <tag><marker id="ErlDrvSysInfo"/><c>ErlDrvSysInfo</c></tag> <item> - <p/> - <code type="none"> + <code type="none"> typedef struct ErlDrvSysInfo { int driver_major_version; int driver_minor_version; @@ -547,2462 +583,2643 @@ typedef struct ErlDrvSysInfo { int nif_major_version; int nif_minor_version; int dirty_scheduler_support; -} ErlDrvSysInfo; - </code> - - <p> - The <c>ErlDrvSysInfo</c> structure is used for storage of - information about the Erlang runtime system. - <seealso marker="#driver_system_info">driver_system_info()</seealso> - will write the system information when passed a reference to - a <c>ErlDrvSysInfo</c> structure. A description of the - fields in the structure follows: - </p> - <taglist> - <tag><c>driver_major_version</c></tag> - <item>The value of - <seealso marker="#version_management">ERL_DRV_EXTENDED_MAJOR_VERSION</seealso> - when the runtime system was compiled. This value is the same - as the value of - <seealso marker="#version_management">ERL_DRV_EXTENDED_MAJOR_VERSION</seealso> - used when compiling the driver; otherwise, the runtime system - would have refused to load the driver. - </item> - <tag><c>driver_minor_version</c></tag> - <item>The value of - <seealso marker="#version_management">ERL_DRV_EXTENDED_MINOR_VERSION</seealso> - when the runtime system was compiled. This value might differ - from the value of - <seealso marker="#version_management">ERL_DRV_EXTENDED_MINOR_VERSION</seealso> - used when compiling the driver. - </item> - <tag><c>erts_version</c></tag> - <item>A string containing the version number of the runtime system - (the same as returned by - <seealso marker="erlang#system_info_version">erlang:system_info(version)</seealso>). - </item> - <tag><c>otp_release</c></tag> - <item>A string containing the OTP release number - (the same as returned by - <seealso marker="erlang#system_info_otp_release">erlang:system_info(otp_release)</seealso>). - </item> - <tag><c>thread_support</c></tag> - <item>A value <c>!= 0</c> if the runtime system has thread support; - otherwise, <c>0</c>. - </item> - <tag><c>smp_support</c></tag> - <item>A value <c>!= 0</c> if the runtime system has SMP support; - otherwise, <c>0</c>. - </item> - <tag><c>async_threads</c></tag> - <item>The number of async threads in the async thread pool used - by <seealso marker="#driver_async">driver_async()</seealso> - (the same as returned by - <seealso marker="erlang#system_info_thread_pool_size">erlang:system_info(thread_pool_size)</seealso>). - </item> - <tag><c>scheduler_threads</c></tag> - <item>The number of scheduler threads used by the runtime system - (the same as returned by - <seealso marker="erlang#system_info_schedulers">erlang:system_info(schedulers)</seealso>). - </item> - <tag><c>nif_major_version</c></tag> - <item>The value of <c>ERL_NIF_MAJOR_VERSION</c> when the runtime system was compiled. - </item> - <tag><c>nif_minor_version</c></tag> - <item>The value of <c>ERL_NIF_MINOR_VERSION</c> when the runtime system was compiled. - </item> - <tag><c>dirty_scheduler_support</c></tag> - <item>A value <c>!= 0</c> if the runtime system has support for dirty scheduler threads; - otherwise <c>0</c>. - </item> +} ErlDrvSysInfo;</code> + <p>The <c>ErlDrvSysInfo</c> structure is used for storage of + information about the Erlang runtime system. + <seealso marker="#driver_system_info"> + <c>driver_system_info</c></seealso> + writes the system information when passed a reference to + a <c>ErlDrvSysInfo</c> structure. The fields in the structure + are as follows:</p> + <taglist> + <tag><c>driver_major_version</c></tag> + <item> + <p>The value of <seealso marker="#version_management"> + <c>ERL_DRV_EXTENDED_MAJOR_VERSION</c></seealso> + when the runtime system was compiled. This value is the same + as the value of <seealso marker="#version_management"> + <c>ERL_DRV_EXTENDED_MAJOR_VERSION</c></seealso> + used when compiling the driver; otherwise the runtime system + would have refused to load the driver.</p> + </item> + <tag><c>driver_minor_version</c></tag> + <item> + <p>The value of <seealso marker="#version_management"> + <c>ERL_DRV_EXTENDED_MINOR_VERSION</c></seealso> + when the runtime system was compiled. This value can differ + from the value of <seealso marker="#version_management"> + <c>ERL_DRV_EXTENDED_MINOR_VERSION</c></seealso> + used when compiling the driver.</p> + </item> + <tag><c>erts_version</c></tag> + <item> + <p>A string containing the version number of the runtime system + (the same as returned by + <seealso marker="erlang#system_info_version"> + <c>erlang:system_info(version)</c></seealso>).</p> + </item> + <tag><c>otp_release</c></tag> + <item> + <p>A string containing the OTP release number + (the same as returned by + <seealso marker="erlang#system_info_otp_release"> + <c>erlang:system_info(otp_release)</c></seealso>).</p> + </item> + <tag><c>thread_support</c></tag> + <item> + <p>A value <c>!= 0</c> if the runtime system has thread support; + otherwise <c>0</c>.</p> + </item> + <tag><c>smp_support</c></tag> + <item> + <p>A value <c>!= 0</c> if the runtime system has SMP support; + otherwise <c>0</c>.</p> + </item> + <tag><c>async_threads</c></tag> + <item> + <p>The number of async threads in the async thread pool used by + <seealso marker="#driver_async"><c>driver_async</c></seealso> + (the same as returned by + <seealso marker="erlang#system_info_thread_pool_size"> + <c>erlang:system_info(thread_pool_size)</c></seealso>).</p> + </item> + <tag><c>scheduler_threads</c></tag> + <item> + <p>The number of scheduler threads used by the runtime system + (the same as returned by + <seealso marker="erlang#system_info_schedulers"> + <c>erlang:system_info(schedulers)</c></seealso>).</p> + </item> + <tag><c>nif_major_version</c></tag> + <item> + <p>The value of <c>ERL_NIF_MAJOR_VERSION</c> when the runtime + system was compiled.</p> + </item> + <tag><c>nif_minor_version</c></tag> + <item> + <p>The value of <c>ERL_NIF_MINOR_VERSION</c> when the runtime + system was compiled.</p> + </item> + <tag><c>dirty_scheduler_support</c></tag> + <item> + <p>A value <c>!= 0</c> if the runtime system has support for dirty + scheduler threads; otherwise <c>0</c>.</p> + </item> </taglist> </item> - <tag><marker id="ErlDrvBinary"/>ErlDrvBinary</tag> + <tag><marker id="ErlDrvBinary"/><c>ErlDrvBinary</c></tag> <item> - <p/> - <code type="none"> + <code type="none"> typedef struct ErlDrvBinary { ErlDrvSint orig_size; char orig_bytes[]; -} ErlDrvBinary; -</code> +} ErlDrvBinary;</code> <p>The <c>ErlDrvBinary</c> structure is a binary, as sent between the emulator and the driver. All binaries are reference counted; when <c>driver_binary_free</c> is called, the reference count is decremented, when it reaches zero, - the binary is deallocated. The <c>orig_size</c> is the size - of the binary, and <c>orig_bytes</c> is the buffer. The - <c>ErlDrvBinary</c> does not have a fixed size, its size is + the binary is deallocated. <c>orig_size</c> is the binary size + and <c>orig_bytes</c> is the buffer. + <c>ErlDrvBinary</c> has not a fixed size, its size is <c>orig_size + 2 * sizeof(int)</c>.</p> <note> <p>The <c>refc</c> field has been removed. The reference count of an <c>ErlDrvBinary</c> is now stored elsewhere. The - reference count of an <c>ErlDrvBinary</c> can be accessed via - <seealso marker="#driver_binary_get_refc">driver_binary_get_refc()</seealso>, - <seealso marker="#driver_binary_inc_refc">driver_binary_inc_refc()</seealso>, - and - <seealso marker="#driver_binary_dec_refc">driver_binary_dec_refc()</seealso>.</p> + reference count of an <c>ErlDrvBinary</c> can be accessed through + <seealso marker="#driver_binary_get_refc"> + <c>driver_binary_get_refc</c></seealso>, + <seealso marker="#driver_binary_inc_refc"> + <c>driver_binary_inc_refc</c></seealso>, and + <seealso marker="#driver_binary_dec_refc"> + <c>driver_binary_dec_refc</c></seealso>.</p> </note> <p>Some driver calls, such as <c>driver_enq_binary</c>, increment the driver reference count, and others, such as <c>driver_deq</c> decrement it.</p> - <p>Using a driver binary instead of a normal buffer, is often - faster, since the emulator doesn't need to copy the data, + <p>Using a driver binary instead of a normal buffer is often + faster, as the emulator needs not to copy the data, only the pointer is used.</p> <p>A driver binary allocated in the driver, with - <c>driver_alloc_binary</c>, should be freed in the driver (unless otherwise stated), - with <c>driver_free_binary</c>. (Note that this doesn't + <c>driver_alloc_binary</c>, is to be freed in the driver + (unless otherwise stated) + with <c>driver_free_binary</c>. (Notice that this does not necessarily deallocate it, if the driver is still referred in the emulator, the ref-count will not go to zero.)</p> <p>Driver binaries are used in the <c>driver_output2</c> and <c>driver_outputv</c> calls, and in the queue. Also the - driver call-back <seealso marker="driver_entry#outputv">outputv</seealso> uses driver - binaries.</p> - <p>If the driver for some reason or another, wants to keep a - driver binary around, in a static variable for instance, the - reference count should be incremented, - and the binary can later be freed in the <seealso marker="driver_entry#stop">stop</seealso> call-back, with - <c>driver_free_binary</c>.</p> - <p>Note that since a driver binary is shared by the driver and - the emulator, a binary received from the emulator or sent to - the emulator, must not be changed by the driver.</p> - <p>Since erts version 5.5 (OTP release R11B), orig_bytes is + driver callback <seealso marker="driver_entry#outputv"> + <c>outputv</c></seealso> uses driver binaries.</p> + <p>If the driver for some reason wants to keep a + driver binary around, for example in a static variable, the + reference count is to be incremented, and the binary can later + be freed in the <seealso marker="driver_entry#stop"> + <c>stop</c></seealso> callback, with <c>driver_free_binary</c>.</p> + <p>Notice that as a driver binary is shared by the driver and + the emulator. A binary received from the emulator or sent to + the emulator must not be changed by the driver.</p> + <p>Since ERTS 5.5 (Erlang/OTP R11B), <c>orig_bytes</c> is guaranteed to be properly aligned for storage of an array of doubles (usually 8-byte aligned).</p> </item> - <tag>ErlDrvData</tag> + <tag><c>ErlDrvData</c></tag> <item> - <p>The <c>ErlDrvData</c> is a handle to driver-specific data, - passed to the driver call-backs. It is a pointer, and is + <p>A handle to driver-specific data, + passed to the driver callbacks. It is a pointer, and is most often type cast to a specific pointer in the driver.</p> </item> - <tag>SysIOVec</tag> + <tag><c>SysIOVec</c></tag> <item> - <p>This is a system I/O vector, as used by <c>writev</c> on - unix and <c>WSASend</c> on Win32. It is used in + <p>A system I/O vector, as used by <c>writev</c> on + Unix and <c>WSASend</c> on Win32. It is used in <c>ErlIOVec</c>.</p> </item> - <tag><marker id="ErlIOVec"/>ErlIOVec</tag> + <tag><marker id="ErlIOVec"/><c>ErlIOVec</c></tag> <item> - <p/> - <code type="none"> + <code type="none"> typedef struct ErlIOVec { int vsize; ErlDrvSizeT size; SysIOVec* iov; ErlDrvBinary** binv; -} ErlIOVec; -</code> - <p>The I/O vector used by the emulator and drivers, is a list +} ErlIOVec;</code> + <p>The I/O vector used by the emulator and drivers is a list of binaries, with a <c>SysIOVec</c> pointing to the buffers of the binaries. It is used in <c>driver_outputv</c> and the - <seealso marker="driver_entry#outputv">outputv</seealso> - driver call-back. Also, the driver queue is an + <seealso marker="driver_entry#outputv"><c>outputv</c></seealso> + driver callback. Also, the driver queue is an <c>ErlIOVec</c>.</p> </item> - - <tag>ErlDrvMonitor</tag> + <tag><c>ErlDrvMonitor</c></tag> <item> <p>When a driver creates a monitor for a process, a <c>ErlDrvMonitor</c> is filled in. This is an opaque - data-type which can be assigned to but not compared without - using the supplied compare function (i.e. it behaves like a struct).</p> - <p>The driver writer should provide the memory for storing the - monitor when calling <seealso marker="#driver_monitor_process">driver_monitor_process</seealso>. The + data type that can be assigned to, but not compared without + using the supplied compare function (that is, it behaves like + a struct).</p> + <p>The driver writer is to provide the memory for storing the + monitor when calling <seealso marker="#driver_monitor_process"> + <c>driver_monitor_process</c></seealso>. The address of the data is not stored outside of the driver, so - the <c>ErlDrvMonitor</c> can be used as any other datum, it - can be copied, moved in memory, forgotten etc.</p> + <c>ErlDrvMonitor</c> can be used as any other data, it + can be copied, moved in memory, forgotten, and so on.</p> </item> - <tag><marker id="ErlDrvNowData"/>ErlDrvNowData</tag> + <tag><marker id="ErlDrvNowData"/><c>ErlDrvNowData</c></tag> <item> - <p>The <c>ErlDrvNowData</c> structure holds a timestamp + <p>The <c>ErlDrvNowData</c> structure holds a time stamp consisting of three values measured from some arbitrary point in the past. The three structure members are:</p> <taglist> - <tag>megasecs</tag> + <tag><c>megasecs</c></tag> <item>The number of whole megaseconds elapsed since the arbitrary - point in time</item> - <tag>secs</tag> + point in time</item> + <tag><c>secs</c></tag> <item>The number of whole seconds elapsed since the arbitrary - point in time</item> - <tag>microsecs</tag> + point in time</item> + <tag><c>microsecs</c></tag> <item>The number of whole microseconds elapsed since the arbitrary - point in time</item> + point in time</item> </taglist> </item> - <tag><marker id="ErlDrvPDL"/>ErlDrvPDL</tag> + <tag><marker id="ErlDrvPDL"/><c>ErlDrvPDL</c></tag> <item> - <p>If certain port specific data have to be accessed from other - threads than those calling the driver call-backs, a port data lock - can be used in order to synchronize the operations on the data. - Currently, the only port specific data that the emulator + <p>If certain port-specific data must be accessed from other + threads than those calling the driver callbacks, a port data lock + can be used to synchronize the operations on the data. + Currently, the only port-specific data that the emulator associates with the port data lock is the driver queue.</p> - <p>Normally a driver instance does not have a port data lock. If - the driver instance wants to use a port data lock, it has to + <p>Normally a driver instance has no port data lock. If + the driver instance wants to use a port data lock, it must create the port data lock by calling - <seealso marker="#driver_pdl_create">driver_pdl_create()</seealso>. - <em>NOTE</em>: Once the port data lock has been created, every - access to data associated with the port data lock has to be done - while having the port data lock locked. The port data lock is - locked, and unlocked, respectively, by use of - <seealso marker="#driver_pdl_lock">driver_pdl_lock()</seealso>, and - <seealso marker="#driver_pdl_unlock">driver_pdl_unlock()</seealso>.</p> + <seealso marker="#driver_pdl_create"> + <c>driver_pdl_create</c></seealso>.</p> + <note> + <p>Once the port data lock has been created, every + access to data associated with the port data lock must be done + while the port data lock is locked. The port data lock is + locked and unlocked by + <seealso marker="#driver_pdl_lock"> + <c>driver_pdl_lock</c></seealso>, and + <seealso marker="#driver_pdl_unlock"> + <c>driver_pdl_unlock</c></seealso>, respectively.</p> + </note> <p>A port data lock is reference counted, and when the reference - count reaches zero, it will be destroyed. The emulator will at - least increment the reference count once when the lock is - created and decrement it once when the port associated with - the lock terminates. The emulator will also increment the - reference count when an async job is enqueued and decrement - it after an async job has been invoked. Besides - this, it is the responsibility of the driver to ensure that + count reaches zero, it is destroyed. The emulator at + least increments the reference count once when the lock is + created and decrements it once the port associated with + the lock terminates. The emulator also increments the + reference count when an async job is enqueued and decrements + it when an async job has been invoked. + Also, the driver is responsible for ensuring that the reference count does not reach zero before the last use of the lock by the driver has been made. The reference count - can be read, incremented, and decremented, respectively, by - use of - <seealso marker="#driver_pdl_get_refc">driver_pdl_get_refc()</seealso>, - <seealso marker="#driver_pdl_inc_refc">driver_pdl_inc_refc()</seealso>, and - <seealso marker="#driver_pdl_dec_refc">driver_pdl_dec_refc()</seealso>.</p> + can be read, incremented, and decremented by + <seealso marker="#driver_pdl_get_refc"> + <c>driver_pdl_get_refc</c></seealso>, + <seealso marker="#driver_pdl_inc_refc"> + <c>driver_pdl_inc_refc</c></seealso>, and + <seealso marker="#driver_pdl_dec_refc"> + <c>driver_pdl_dec_refc</c></seealso>, respectively.</p> </item> - - <tag><marker id="ErlDrvTid"/>ErlDrvTid</tag> + <tag><marker id="ErlDrvTid"/><c>ErlDrvTid</c></tag> <item> <p>Thread identifier.</p> - <p>See also: - <seealso marker="#erl_drv_thread_create">erl_drv_thread_create()</seealso>, - <seealso marker="#erl_drv_thread_exit">erl_drv_thread_exit()</seealso>, - <seealso marker="#erl_drv_thread_join">erl_drv_thread_join()</seealso>, - <seealso marker="#erl_drv_thread_self">erl_drv_thread_self()</seealso>, - and - <seealso marker="#erl_drv_equal_tids">erl_drv_equal_tids()</seealso>. - </p> + <p>See also <seealso marker="#erl_drv_thread_create"> + <c>erl_drv_thread_create</c></seealso>, + <seealso marker="#erl_drv_thread_exit"> + <c>erl_drv_thread_exit</c></seealso>, + <seealso marker="#erl_drv_thread_join"> + <c>erl_drv_thread_join</c></seealso>, + <seealso marker="#erl_drv_thread_self"> + <c>erl_drv_thread_self</c></seealso>, and + <seealso marker="#erl_drv_equal_tids"> + <c>erl_drv_equal_tids</c></seealso>.</p> </item> - <tag><marker id="ErlDrvThreadOpts"/>ErlDrvThreadOpts</tag> + <tag><marker id="ErlDrvThreadOpts"/><c>ErlDrvThreadOpts</c></tag> <item> - <p/> - <code type="none"> - int suggested_stack_size; - </code> + <code type="none"> +int suggested_stack_size;</code> <p>Thread options structure passed to - <seealso marker="#erl_drv_thread_create">erl_drv_thread_create()</seealso>. - Currently the following fields exist: - </p> + <seealso marker="#erl_drv_thread_create"> + <c>erl_drv_thread_create</c></seealso>. + The following field exists:</p> <taglist> - <tag>suggested_stack_size</tag> - <item>A suggestion, in kilo-words, on how large a stack to use. A value less - than zero means default size. + <tag><c>suggested_stack_size</c></tag> + <item>A suggestion, in kilowords, on how large a stack to use. + A value < 0 means default size. </item> </taglist> - <p>See also: - <seealso marker="#erl_drv_thread_opts_create">erl_drv_thread_opts_create()</seealso>, - <seealso marker="#erl_drv_thread_opts_destroy">erl_drv_thread_opts_destroy()</seealso>, - and - <seealso marker="#erl_drv_thread_create">erl_drv_thread_create()</seealso>. - </p> + <p>See also <seealso marker="#erl_drv_thread_opts_create"> + <c>erl_drv_thread_opts_create</c></seealso>, + <seealso marker="#erl_drv_thread_opts_destroy"> + <c>erl_drv_thread_opts_destroy</c></seealso>, and + <seealso marker="#erl_drv_thread_create"> + <c>erl_drv_thread_create</c></seealso>.</p> </item> - - <tag><marker id="ErlDrvMutex"/>ErlDrvMutex</tag> + <tag><marker id="ErlDrvMutex"/><c>ErlDrvMutex</c></tag> <item> <p>Mutual exclusion lock. Used for synchronizing access to shared data. - Only one thread at a time can lock a mutex. - </p> - <p>See also: - <seealso marker="#erl_drv_mutex_create">erl_drv_mutex_create()</seealso>, - <seealso marker="#erl_drv_mutex_destroy">erl_drv_mutex_destroy()</seealso>, - <seealso marker="#erl_drv_mutex_lock">erl_drv_mutex_lock()</seealso>, - <seealso marker="#erl_drv_mutex_trylock">erl_drv_mutex_trylock()</seealso>, - and - <seealso marker="#erl_drv_mutex_unlock">erl_drv_mutex_unlock()</seealso>. - </p> + Only one thread at a time can lock a mutex.</p> + <p>See also <seealso marker="#erl_drv_mutex_create"> + <c>erl_drv_mutex_create</c></seealso>, + <seealso marker="#erl_drv_mutex_destroy"> + <c>erl_drv_mutex_destroy</c></seealso>, + <seealso marker="#erl_drv_mutex_lock"> + <c>erl_drv_mutex_lock</c></seealso>, + <seealso marker="#erl_drv_mutex_trylock"> + <c>erl_drv_mutex_trylock</c></seealso>, and + <seealso marker="#erl_drv_mutex_unlock"> + <c>erl_drv_mutex_unlock</c></seealso>.</p> </item> - <tag><marker id="ErlDrvCond"/>ErlDrvCond</tag> + <tag><marker id="ErlDrvCond"/><c>ErlDrvCond</c></tag> <item> - <p>Condition variable. Used when threads need to wait for a specific - condition to appear before continuing execution. Condition variables - need to be used with associated mutexes. - </p> - <p>See also: - <seealso marker="#erl_drv_cond_create">erl_drv_cond_create()</seealso>, - <seealso marker="#erl_drv_cond_destroy">erl_drv_cond_destroy()</seealso>, - <seealso marker="#erl_drv_cond_signal">erl_drv_cond_signal()</seealso>, - <seealso marker="#erl_drv_cond_broadcast">erl_drv_cond_broadcast()</seealso>, - and - <seealso marker="#erl_drv_cond_wait">erl_drv_cond_wait()</seealso>. - </p> + <p>Condition variable. Used when threads must wait for a specific + condition to appear before continuing execution. Condition variables + must be used with associated mutexes.</p> + <p>See also <seealso marker="#erl_drv_cond_create"> + <c>erl_drv_cond_create</c></seealso>, + <seealso marker="#erl_drv_cond_destroy"> + <c>erl_drv_cond_destroy</c></seealso>, + <seealso marker="#erl_drv_cond_signal"> + <c>erl_drv_cond_signal</c></seealso>, + <seealso marker="#erl_drv_cond_broadcast"> + <c>erl_drv_cond_broadcast</c></seealso>, and + <seealso marker="#erl_drv_cond_wait"> + <c>erl_drv_cond_wait</c></seealso>.</p> </item> - <tag><marker id="ErlDrvRWLock"/>ErlDrvRWLock</tag> + <tag><marker id="ErlDrvRWLock"/><c>ErlDrvRWLock</c></tag> <item> <p>Read/write lock. Used to allow multiple threads to read shared data - while only allowing one thread to write the same data. Multiple threads - can read lock an rwlock at the same time, while only one thread can - read/write lock an rwlock at a time. - </p> - <p>See also: - <seealso marker="#erl_drv_rwlock_create">erl_drv_rwlock_create()</seealso>, - <seealso marker="#erl_drv_rwlock_destroy">erl_drv_rwlock_destroy()</seealso>, - <seealso marker="#erl_drv_rwlock_rlock">erl_drv_rwlock_rlock()</seealso>, - <seealso marker="#erl_drv_rwlock_tryrlock">erl_drv_rwlock_tryrlock()</seealso>, - <seealso marker="#erl_drv_rwlock_runlock">erl_drv_rwlock_runlock()</seealso>, - <seealso marker="#erl_drv_rwlock_rwlock">erl_drv_rwlock_rwlock()</seealso>, - <seealso marker="#erl_drv_rwlock_tryrwlock">erl_drv_rwlock_tryrwlock()</seealso>, - and - <seealso marker="#erl_drv_rwlock_rwunlock">erl_drv_rwlock_rwunlock()</seealso>. - </p> + while only allowing one thread to write the same data. Multiple + threads can read lock an rwlock at the same time, while only + one thread can read/write lock an rwlock at a time.</p> + <p>See also <seealso marker="#erl_drv_rwlock_create"> + <c>erl_drv_rwlock_create</c></seealso>, + <seealso marker="#erl_drv_rwlock_destroy"> + <c>erl_drv_rwlock_destroy</c></seealso>, + <seealso marker="#erl_drv_rwlock_rlock"> + <c>erl_drv_rwlock_rlock</c></seealso>, + <seealso marker="#erl_drv_rwlock_tryrlock"> + <c>erl_drv_rwlock_tryrlock</c></seealso>, + <seealso marker="#erl_drv_rwlock_runlock"> + <c>erl_drv_rwlock_runlock</c></seealso>, + <seealso marker="#erl_drv_rwlock_rwlock"> + <c>erl_drv_rwlock_rwlock</c></seealso>, + <seealso marker="#erl_drv_rwlock_tryrwlock"> + <c>erl_drv_rwlock_tryrwlock</c></seealso>, and + <seealso marker="#erl_drv_rwlock_rwunlock"> + <c>erl_drv_rwlock_rwunlock</c></seealso>.</p> + </item> + <tag><marker id="ErlDrvTSDKey"/><c>ErlDrvTSDKey</c></tag> + <item> + <p>Key that thread-specific data can be associated with.</p> + <p>See also <seealso marker="#erl_drv_tsd_key_create"> + <c>erl_drv_tsd_key_create</c></seealso>, + <seealso marker="#erl_drv_tsd_key_destroy"> + <c>erl_drv_tsd_key_destroy</c></seealso>, + <seealso marker="#erl_drv_tsd_set"> + <c>erl_drv_tsd_set</c></seealso>, and + <seealso marker="#erl_drv_tsd_get"> + <c>erl_drv_tsd_get</c></seealso>.</p> </item> - <tag><marker id="ErlDrvTSDKey"/>ErlDrvTSDKey</tag> + <tag><marker id="ErlDrvTime"/><c>ErlDrvTime</c></tag> <item> - <p>Key which thread specific data can be associated with.</p> - <p>See also: - <seealso marker="#erl_drv_tsd_key_create">erl_drv_tsd_key_create()</seealso>, - <seealso marker="#erl_drv_tsd_key_destroy">erl_drv_tsd_key_destroy()</seealso>, - <seealso marker="#erl_drv_tsd_set">erl_drv_tsd_set()</seealso>, - and - <seealso marker="#erl_drv_tsd_get">erl_drv_tsd_get()</seealso>. - </p> + <p>A signed 64-bit integer type for time representation.</p> </item> - </taglist> - </section> + <tag><marker id="ErlDrvTimeUnit"/><c>ErlDrvTimeUnit</c></tag> + <item> + <p>An enumeration of time units supported by the driver API:</p> + <taglist> + <tag><c>ERL_DRV_SEC</c></tag> + <item>Seconds</item> + <tag><c>ERL_DRV_MSEC</c></tag> + <item>Milliseconds</item> + <tag><c>ERL_DRV_USEC</c></tag> + <item>Microseconds</item> + <tag><c>ERL_DRV_NSEC</c></tag> + <item>Nanoseconds</item> + </taglist> + </item> + </taglist> + </section> <funcs> <func> - <name><ret>void</ret><nametext>driver_system_info(ErlDrvSysInfo *sys_info_ptr, size_t size)</nametext></name> - <fsummary>Get information about the Erlang runtime system</fsummary> + <name><ret>void</ret><nametext>add_driver_entry(ErlDrvEntry + *de)</nametext></name> + <fsummary>Add a driver entry.</fsummary> <desc> - <marker id="driver_system_info"></marker> - <p>This function will write information about the Erlang runtime - system into the - <seealso marker="#ErlDrvSysInfo">ErlDrvSysInfo</seealso> - structure referred to by the first argument. The second - argument should be the size of the - <seealso marker="#ErlDrvSysInfo">ErlDrvSysInfo</seealso> - structure, i.e., <c>sizeof(ErlDrvSysInfo)</c>.</p> - <p>See the documentation of the - <seealso marker="#ErlDrvSysInfo">ErlDrvSysInfo</seealso> - structure for information about specific fields.</p> + <marker id="add_driver_entry"></marker> + <p>Adds a driver entry to the list of drivers known by Erlang. + The <seealso marker="driver_entry#init"><c>init</c></seealso> + function of parameter <c>de</c> is called.</p> + <note> + <p>To use this function for adding drivers residing in + dynamically loaded code is dangerous. If the driver code + for the added driver resides in the same dynamically + loaded module (that is, <c>.so</c> file) as a normal + dynamically loaded driver (loaded with the <c>erl_ddll</c> + interface), the caller is to call + <seealso marker="#driver_lock_driver"> + <c>driver_lock_driver</c></seealso> before + adding driver entries.</p> + <p><em>Use of this function is generally deprecated.</em></p> + </note> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_output(ErlDrvPort port, char *buf, ErlDrvSizeT len)</nametext></name> - <fsummary>Send data from driver to port owner</fsummary> + <name><ret>void *</ret> + <nametext>driver_alloc(ErlDrvSizeT size)</nametext></name> + <fsummary>Allocate memory.</fsummary> <desc> - <marker id="driver_output"></marker> - <p>The <c>driver_output</c> function is used to send data from - the driver up to the emulator. The data will be received as - terms or binary data, depending on how the driver port was - opened.</p> - <p>The data is queued in the port owner process' message - queue. Note that this does not yield to the emulator. (Since - the driver and the emulator run in the same thread.)</p> - <p>The parameter <c>buf</c> points to the data to send, and - <c>len</c> is the number of bytes.</p> - <p>The return value for all output functions is 0. (Unless the - driver is used for distribution, in which case it can fail - and return -1. For normal use, the output function always - returns 0.)</p> + <marker id="driver_alloc"></marker> + <p>Allocates a memory block of the size specified + in <c>size</c>, and returns it. This fails only on out of + memory, in which case <c>NULL</c> is returned. (This is most + often a wrapper for <c>malloc</c>).</p> + <p>Memory allocated must be explicitly freed with a corresponding + call to <seealso marker="#driver_free"><c>driver_free</c></seealso> + (unless otherwise stated).</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_output2(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len)</nametext></name> - <fsummary>Send data and binary data to port owner</fsummary> + <name><ret>ErlDrvBinary *</ret> + <nametext>driver_alloc_binary(ErlDrvSizeT size)</nametext></name> + <fsummary>Allocate a driver binary.</fsummary> <desc> - <marker id="driver_output2"></marker> - <p>The <c>driver_output2</c> function first sends <c>hbuf</c> - (length in <c>hlen</c>) data as a list, regardless of port - settings. Then <c>buf</c> is sent as a binary or list. - E.g. if <c>hlen</c> is 3 then the port owner process will - receive <c>[H1, H2, H3 | T]</c>.</p> - <p>The point of sending data as a list header, is to facilitate - matching on the data received.</p> - <p>The return value is 0 for normal use.</p> + <marker id="driver_alloc_binary"></marker> + <p>Allocates a driver binary with a memory block + of at least <c>size</c> bytes, and returns a pointer to it, + or <c>NULL</c> on failure (out of memory). When a driver binary has + been sent to the emulator, it must not be changed. Every + allocated binary is to be freed by a corresponding call to + <seealso marker="#driver_free_binary"> + <c>driver_free_binary</c></seealso> (unless otherwise stated).</p> + <p>Notice that a driver binary has an internal reference counter. + This means that calling <c>driver_free_binary</c>, it may not + actually dispose of it. If it is sent to the emulator, it can + be referenced there.</p> + <p>The driver binary has a field, <c>orig_bytes</c>, which + marks the start of the data in the binary.</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_output_binary(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, ErlDrvBinary* bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name> - <fsummary>Send data from a driver binary to port owner</fsummary> + <name><ret>long</ret><nametext>driver_async(ErlDrvPort port, unsigned + int* key, void (*async_invoke)(void*), void* async_data, void + (*async_free)(void*))</nametext></name> + <fsummary>Perform an asynchronous call within a driver.</fsummary> <desc> - <marker id="driver_output_binary"></marker> - <p>This function sends data to port owner process from a - driver binary, it has a header buffer (<c>hbuf</c> - and <c>hlen</c>) just like <c>driver_output2</c>. The - <c>hbuf</c> parameter can be <c>NULL</c>.</p> - <p>The parameter <c>offset</c> is an offset into the binary and - <c>len</c> is the number of bytes to send.</p> - <p>Driver binaries are created with <c>driver_alloc_binary</c>.</p> - <p>The data in the header is sent as a list and the binary as - an Erlang binary in the tail of the list.</p> - <p>E.g. if <c>hlen</c> is 2, then the port owner process will - receive <c><![CDATA[[H1, H2 | <<T>>]]]></c>.</p> - <p>The return value is 0 for normal use.</p> - <p>Note that, using the binary syntax in Erlang, the driver - application can match the header directly from the binary, - so the header can be put in the binary, and hlen can be set - to 0.</p> + <marker id="driver_async"></marker> + <p>Performs an asynchronous call. The function + <c>async_invoke</c> is invoked in a thread separate from the + emulator thread. This enables the driver to perform + time-consuming, blocking operations without blocking the + emulator.</p> + <p>The async thread pool size can be set with command-line argument + <seealso marker="erl#async_thread_pool_size"><c>+A</c></seealso> + in <seealso marker="erl"><c>erl(1)</c></seealso>. + If an async thread pool is unavailable, the call is made + synchronously in the thread calling <c>driver_async</c>. The + current number of async threads in the async thread pool can be + retrieved through <seealso marker="#driver_system_info"> + <c>driver_system_info</c></seealso>.</p> + <p>If a thread pool is available, a thread is used. + If argument <c>key</c> is <c>NULL</c>, the threads from the + pool are used in a round-robin way, each call to + <c>driver_async</c> uses the next thread in the pool. With + argument <c>key</c> set, this behavior is changed. The two + same values of <c>*key</c> always get the same thread.</p> + <p>To ensure that a driver instance always uses the same + thread, the following call can be used:</p> + <code type="none"><![CDATA[ +unsigned int myKey = driver_async_port_key(myPort); + +r = driver_async(myPort, &myKey, myData, myFunc); ]]></code> + <p>It is enough to initialize <c>myKey</c> once for each + driver instance.</p> + <p>If a thread is already working, the calls are + queued up and executed in order. Using the same thread for + each driver instance ensures that the calls are made in sequence.</p> + <p>The <c>async_data</c> is the argument to the functions + <c>async_invoke</c> and <c>async_free</c>. It is typically a + pointer to a structure containing a pipe or event that + can be used to signal that the async operation completed. + The data is to be freed in <c>async_free</c>.</p> + <p>When the async operation is done, + <seealso marker="driver_entry#ready_async"> + <c>ready_async</c></seealso> driver + entry function is called. If <c>ready_async</c> is <c>NULL</c> in + the driver entry, the <c>async_free</c> function is called + instead.</p> + <p>The return value is <c>-1</c> if the <c>driver_async</c> call + fails.</p> + <note> + <p>As from ERTS 5.5.4.3 the default stack size for + threads in the async-thread pool is 16 kilowords, + that is, 64 kilobyte on 32-bit architectures. + This small default size has been chosen because the + amount of async-threads can be quite large. The + default stack size is enough for drivers delivered + with Erlang/OTP, but is possibly not sufficiently large + for other dynamically linked-in drivers that use the + <c>driver_async</c> functionality. A suggested stack size + for threads in the async-thread pool can be configured + through command-line argument + <seealso marker="erl#async_thread_stack_size"><c>+a</c></seealso> + in <seealso marker="erl"><c>erl(1)</c></seealso>.</p> + </note> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_outputv(ErlDrvPort port, char* hbuf, ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name> - <fsummary>Send vectorized data to port owner</fsummary> + <name><ret>unsigned int</ret><nametext>driver_async_port_key(ErlDrvPort + port)</nametext></name> + <fsummary>Calculate an async key from an ErlDrvPort.</fsummary> <desc> - <marker id="driver_outputv"></marker> - <p>This function sends data from an IO vector, <c>ev</c>, to - the port owner process. It has a header buffer (<c>hbuf</c> - and <c>hlen</c>), just like <c>driver_output2</c>.</p> - <p>The <c>skip</c> parameter is a number of bytes to skip of - the <c>ev</c> vector from the head.</p> - <p>You get vectors of <c>ErlIOVec</c> type from the driver - queue (see below), and the <seealso marker="driver_entry#outputv">outputv</seealso> driver entry - function. You can also make them yourself, if you want to - send several <c>ErlDrvBinary</c> buffers at once. Often - it is faster to use <c>driver_output</c> or - <c>driver_output_binary</c>.</p> - <p>E.g. if <c>hlen</c> is 2 and <c>ev</c> points to an array of - three binaries, the port owner process will receive <c><![CDATA[[H1, H2, <<B1>>, <<B2>> | <<B3>>]]]></c>.</p> - <p>The return value is 0 for normal use.</p> - <p>The comment for <c>driver_output_binary</c> applies for - <c>driver_outputv</c> too.</p> + <marker id="driver_async_port_key"></marker> + <p>Calculates a key for later use in <seealso + marker="#driver_async"><c>driver_async</c></seealso>. The keys are + evenly distributed so that a fair mapping between port IDs + and async thread IDs is achieved.</p> + <note> + <p>Before Erlang/OTP R16, the port ID could be used as a key + with proper casting, but after the rewrite of the port + subsystem, this is no longer the case. With this function, you + can achieve the same distribution based on port IDs as before + Erlang/OTP R16.</p> + </note> </desc> </func> + <func> - <name><ret>ErlDrvSizeT</ret><nametext>driver_vec_to_buf(ErlIOVec *ev, char *buf, ErlDrvSizeT len)</nametext></name> - <fsummary>Collect data segments into a buffer</fsummary> + <name><ret>long</ret> + <nametext>driver_binary_dec_refc(ErlDrvBinary *bin)</nametext></name> + <fsummary>Decrement the reference count of a driver binary.</fsummary> <desc> - <marker id="driver_vec_to_buf"></marker> - <p>This function collects several segments of data, referenced - by <c>ev</c>, by copying them in order to the buffer - <c>buf</c>, of the size <c>len</c>.</p> - <p>If the data is to be sent from the driver to the port owner - process, it is faster to use <c>driver_outputv</c>.</p> - <p>The return value is the space left in the buffer, i.e. if - the <c>ev</c> contains less than <c>len</c> bytes it's the - difference, and if <c>ev</c> contains <c>len</c> bytes or - more, it's 0. This is faster if there is more than one header byte, - since the binary syntax can construct integers directly from - the binary.</p> + <marker id="driver_binary_dec_refc"></marker> + <p>Decrements the reference count on <c>bin</c> and returns + the reference count reached after the decrement.</p> + <p>This function is thread-safe.</p> + <note> + <p>The reference count of driver binary is normally to be decremented + by calling <seealso marker="#driver_free_binary"> + <c>driver_free_binary</c></seealso>.</p> + <p><c>driver_binary_dec_refc</c> does <em>not</em> free + the binary if the reference count reaches zero. <em>Only</em> + use <c>driver_binary_dec_refc</c> when you are sure + <em>not</em> to reach a reference count of zero.</p> + </note> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_set_timer(ErlDrvPort port, unsigned long time)</nametext></name> - <fsummary>Set a timer to call the driver</fsummary> + <name><ret>long</ret> + <nametext>driver_binary_get_refc(ErlDrvBinary *bin)</nametext></name> + <fsummary>Get the reference count of a driver binary.</fsummary> <desc> - <marker id="driver_set_timer"></marker> - <p>This function sets a timer on the driver, which will count - down and call the driver when it is timed out. The - <c>time</c> parameter is the time in milliseconds before the - timer expires.</p> - <p>When the timer reaches 0 and expires, the driver entry - function <seealso marker="driver_entry#timeout">timeout</seealso> is called.</p> - <p>Note that there is only one timer on each driver instance; - setting a new timer will replace an older one.</p> - <p>Return value is 0 (-1 only when the <c>timeout</c> driver - function is <c>NULL</c>).</p> + <marker id="driver_binary_get_refc"></marker> + <p>Returns the current reference count on <c>bin</c>.</p> + <p>This function is thread-safe.</p> + </desc> + </func> + + <func> + <name><ret>long</ret> + <nametext>driver_binary_inc_refc(ErlDrvBinary *bin)</nametext></name> + <fsummary>Increment the reference count of a driver binary.</fsummary> + <desc> + <marker id="driver_binary_inc_refc"></marker> + <p>Increments the reference count on <c>bin</c> and returns + the reference count reached after the increment.</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_cancel_timer(ErlDrvPort port)</nametext></name> - <fsummary>Cancel a previously set timer</fsummary> + <name><ret>ErlDrvTermData</ret><nametext>driver_caller(ErlDrvPort + port)</nametext></name> + <fsummary>Return the process making the driver call.</fsummary> + <desc> + <marker id="driver_caller"></marker> + <p>Returns the process ID of the process that + made the current call to the driver. The process ID can be used with + <seealso marker="#driver_send_term"><c>driver_send_term</c></seealso> + to send back data to the caller. + <c>driver_caller</c> only returns valid data + when currently executing in one of the following driver callbacks:</p> + <taglist> + <tag><seealso marker="driver_entry#start"> + <c>start</c></seealso></tag> + <item>Called from <seealso marker="erlang:open_port/2"> + <c>erlang:open_port/2</c></seealso>.</item> + <tag><seealso marker="driver_entry#output"> + <c>output</c></seealso></tag> + <item>Called from <seealso marker="erlang:send/2"> + <c>erlang:send/2</c></seealso> and + <seealso marker="erlang:port_command/2"> + <c>erlang:port_command/2</c></seealso>.</item> + <tag><seealso marker="driver_entry#outputv"> + <c>outputv</c></seealso></tag> + <item>Called from <seealso marker="erlang:send/2"> + <c>erlang:send/2</c></seealso> and + <seealso marker="erlang:port_command/2"> + <c>erlang:port_command/2</c></seealso>.</item> + <tag><seealso marker="driver_entry#control"> + <c>control</c></seealso></tag> + <item>Called from <seealso marker="erlang:port_control/3"> + <c>erlang:port_control/3</c></seealso>.</item> + <tag><seealso marker="driver_entry#call"> + <c>call</c></seealso></tag> + <item>Called from <seealso marker="erlang:port_call/3"> + <c>erlang:port_call/3</c></seealso>.</item> + </taglist> + <p>Notice that this function is <em>not</em> thread-safe, not + even when the emulator with SMP support is used.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>driver_cancel_timer(ErlDrvPort port)</nametext></name> + <fsummary>Cancel a previously set timer.</fsummary> <desc> <marker id="driver_cancel_timer"></marker> - <p>This function cancels a timer set with - <c>driver_set_timer</c>.</p> - <p>The return value is 0.</p> + <p>Cancels a timer set with + <seealso marker="#driver_set_timer"> + <c>driver_set_timer</c></seealso>.</p> + <p>The return value is <c>0</c>.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_read_timer(ErlDrvPort port, unsigned long *time_left)</nametext></name> - <fsummary>Read the time left before timeout</fsummary> + <name><ret>int</ret><nametext>driver_compare_monitors(const ErlDrvMonitor + *monitor1, const ErlDrvMonitor *monitor2)</nametext></name> + <fsummary>Compare two monitors.</fsummary> <desc> - <marker id="driver_read_timer"></marker> - <p>This function reads the current time of a timer, and places - the result in <c>time_left</c>. This is the time in - milliseconds, before the timeout will occur.</p> - <p>The return value is 0.</p> + <marker id="driver_compare_monitors"></marker> + <p>Compares two <c>ErlDrvMonitor</c>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>int</ret><nametext>driver_get_now(ErlDrvNowData *now)</nametext></name> - <fsummary>Read a system timestamp</fsummary> + <name><ret>ErlDrvTermData</ret><nametext>driver_connected(ErlDrvPort + port)</nametext></name> + <fsummary>Return the port owner process.</fsummary> <desc> - <marker id="driver_get_now"></marker> - <p>This function reads a timestamp into the memory pointed to by - the parameter <c>now</c>. See the description of <seealso marker="#ErlDrvNowData">ErlDrvNowData</seealso> for - specification of its fields. </p> - <p>The return value is 0 unless the <c>now</c> pointer is not - valid, in which case it is < 0. </p> + <marker id="driver_connected"></marker> + <p>Returns the port owner process.</p> + <p>Notice that this function is <em>not</em> thread-safe, not + even when the emulator with SMP support is used.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_select(ErlDrvPort port, ErlDrvEvent event, int mode, int on)</nametext></name> - <fsummary>Provide an event for having the emulator call the driver</fsummary> + <name><ret>ErlDrvPort</ret><nametext>driver_create_port(ErlDrvPort port, + ErlDrvTermData owner_pid, char* name, + ErlDrvData drv_data)</nametext></name> + <fsummary>Create a new port (driver instance).</fsummary> <desc> - <marker id="driver_select"></marker> - <p>This function is used by drivers to provide the emulator with - events to check for. This enables the emulator to call the driver - when something has happened asynchronously.</p> - <p>The <c>event</c> argument identifies an OS-specific event object. - On Unix systems, the functions <c>select</c>/<c>poll</c> are used. The - event object must be a socket or pipe (or other object that - <c>select</c>/<c>poll</c> can use). - On windows, the Win32 API function <c>WaitForMultipleObjects</c> - is used. This places other restrictions on the event object. - Refer to the Win32 SDK documentation. - On Enea OSE, the receive function is used. See the <seealso - marker="ose:ose_erl_driver"></seealso> for more details.</p> - <p>The <c>on</c> parameter should be <c>1</c> for setting events - and <c>0</c> for clearing them.</p> - <p>The <c>mode</c> argument is a bitwise-or combination of - <c>ERL_DRV_READ</c>, <c>ERL_DRV_WRITE</c> and <c>ERL_DRV_USE</c>. - The first two specify whether to wait for read events and/or write - events. A fired read event will call - <seealso marker="driver_entry#ready_input">ready_input</seealso> - while a fired write event will call - <seealso marker="driver_entry#ready_output">ready_output</seealso>. - </p> - <note> - <p>Some OS (Windows and Enea OSE) do not differentiate between read and write events. - The call-back for a fired event then only depends on the value of <c>mode</c>.</p> - </note> - <p><c>ERL_DRV_USE</c> specifies if we are using the event object or if we want to close it. - On an emulator with SMP support, it is not safe to clear all events - and then close the event object after <c>driver_select</c> has - returned. Another thread may still be using the event object - internally. To safely close an event object call - <c>driver_select</c> with <c>ERL_DRV_USE</c> and <c>on==0</c>. That - will clear all events and then call - <seealso marker="driver_entry#stop_select">stop_select</seealso> - when it is safe to close the event object. - <c>ERL_DRV_USE</c> should be set together with the first event - for an event object. It is harmless to set <c>ERL_DRV_USE</c> - even though it already has been done. Clearing all events but keeping - <c>ERL_DRV_USE</c> set will indicate that we are using the event - object and probably will set events for it again.</p> - <note> - <p>ERL_DRV_USE was added in OTP release R13. Old drivers will still work - as before. But it is recommended to update them to use <c>ERL_DRV_USE</c> and - <c>stop_select</c> to make sure that event objects are closed in a safe way.</p> - </note> - <p>The return value is 0 (failure, -1, only if the - <c>ready_input</c>/<c>ready_output</c> is - <c>NULL</c>).</p> + <p>Creates a new port executing the same driver + code as the port creating the new port.</p> + <taglist> + <tag><c>port</c></tag> + <item>The port handle of the port (driver instance) creating + the new port.</item> + <tag><c>owner_pid</c></tag> + <item>The process ID of the Erlang process to become + owner of the new port. This process will be linked + to the new port. You usually want to use + <c>driver_caller(port)</c> as <c>owner_pid</c>.</item> + <tag><c>name</c></tag> + <item>The port name of the new port. You usually want to + use the same port name as the driver name + (<seealso marker="driver_entry#driver_name"> + <c>driver_name</c></seealso> field of the + <seealso marker="driver_entry"><c>driver_entry</c></seealso>). + </item> + <tag><c>drv_data</c></tag> + <item>The driver-defined handle that is passed in later + calls to driver callbacks. Notice that the + <seealso marker="driver_entry#start">driver start + callback</seealso> is not called for this new driver instance. + The driver-defined handle is normally created in the + <seealso marker="driver_entry#start">driver start callback</seealso> + when a port is created through + <seealso marker="erlang#open_port/2"> + <c>erlang:open_port/2</c></seealso>. + </item> + </taglist> + <p>The caller of <c>driver_create_port</c> is allowed to + manipulate the newly created port when <c>driver_create_port</c> + has returned. When + <seealso marker="#smp_support">port level locking</seealso> + is used, the creating port is only allowed to + manipulate the newly created port until the current driver + callback, which was called by the emulator, returns.</p> </desc> </func> + <func> - <name><ret>void *</ret><nametext>driver_alloc(ErlDrvSizeT size)</nametext></name> - <fsummary>Allocate memory</fsummary> + <name><ret>int</ret><nametext>driver_demonitor_process(ErlDrvPort port, + const ErlDrvMonitor *monitor)</nametext></name> + <fsummary>Stop monitoring a process from a driver.</fsummary> <desc> - <marker id="driver_alloc"></marker> - <p>This function allocates a memory block of the size specified - in <c>size</c>, and returns it. This only fails on out of - memory, in that case <c>NULL</c> is returned. (This is most - often a wrapper for <c>malloc</c>).</p> - <p>Memory allocated must be explicitly freed with a corresponding - call to <c>driver_free</c> (unless otherwise stated).</p> - <p>This function is thread-safe.</p> + <marker id="driver_demonitor_process"></marker> + <p>Cancels a monitor created earlier.</p> + <p>Returns <c>0</c> if a monitor was removed and > 0 if the monitor + no longer exists.</p> </desc> </func> + <func> - <name><ret>void *</ret><nametext>driver_realloc(void *ptr, ErlDrvSizeT size)</nametext></name> - <fsummary>Resize an allocated memory block</fsummary> + <name><ret>ErlDrvSizeT</ret><nametext>driver_deq(ErlDrvPort port, + ErlDrvSizeT size)</nametext></name> + <fsummary>Dequeue data from the head of the driver queue.</fsummary> <desc> - <marker id="driver_realloc"></marker> - <p>This function resizes a memory block, either in place, or by - allocating a new block, copying the data and freeing the old - block. A pointer is returned to the reallocated memory. On - failure (out of memory), <c>NULL</c> is returned. (This is - most often a wrapper for <c>realloc</c>.)</p> - <p>This function is thread-safe.</p> + <marker id="driver_deq"></marker> + <p>Dequeues data by moving the head pointer + forward in the driver queue by <c>size</c> bytes. The data + in the queue is deallocated.</p> + <p>Returns the number of bytes remaining in the queue on success, + otherwise <c>-1</c>.</p> + <p>This function can be called from any thread if a + <seealso marker="#ErlDrvPDL">port data lock</seealso> + associated with the <c>port</c> is locked by the calling + thread during the call.</p> </desc> </func> + <func> - <name><ret>void</ret><nametext>driver_free(void *ptr)</nametext></name> - <fsummary>Free an allocated memory block</fsummary> + <name><ret>int</ret><nametext>driver_enq(ErlDrvPort port, char* buf, + ErlDrvSizeT len)</nametext></name> + <fsummary>Enqueue data in the driver queue.</fsummary> <desc> - <marker id="driver_free"></marker> - <p>This function frees the memory pointed to by <c>ptr</c>. The - memory should have been allocated with - <c>driver_alloc</c>. All allocated memory should be - deallocated, just once. There is no garbage collection in - drivers.</p> - <p>This function is thread-safe.</p> + <marker id="driver_enq"></marker> + <p>Enqueues data in the driver queue. The data in + <c>buf</c> is copied (<c>len</c> bytes) and placed at the + end of the driver queue. The driver queue is normally used + in a FIFO way.</p> + <p>The driver queue is available to queue output from the + emulator to the driver (data from the driver to the emulator + is queued by the emulator in normal Erlang message + queues). This can be useful if the driver must wait for + slow devices, and so on, and wants to yield back to the + emulator. The driver queue is implemented as an <c>ErlIOVec</c>.</p> + <p>When the queue contains data, the driver does not close until + the queue is empty.</p> + <p>The return value is <c>0</c>.</p> + <p>This function can be called from any thread if a + <seealso marker="#ErlDrvPDL">port data lock</seealso> + associated with the <c>port</c> is locked by the calling + thread during the call.</p> </desc> </func> + <func> - <name><ret>ErlDrvBinary *</ret><nametext>driver_alloc_binary(ErlDrvSizeT size)</nametext></name> - <fsummary>Allocate a driver binary</fsummary> + <name><ret>int</ret><nametext>driver_enq_bin(ErlDrvPort port, + ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext> + </name> + <fsummary>Enqueue binary in the driver queue.</fsummary> <desc> - <marker id="driver_alloc_binary"></marker> - <p>This function allocates a driver binary with a memory block - of at least <c>size</c> bytes, and returns a pointer to it, - or NULL on failure (out of memory). When a driver binary has - been sent to the emulator, it must not be altered. Every - allocated binary should be freed by a corresponding call to - <c>driver_free_binary</c> (unless otherwise stated).</p> - <p>Note that a driver binary has an internal reference counter, - this means that calling <c>driver_free_binary</c> it may not - actually dispose of it. If it's sent to the emulator, it may - be referenced there.</p> - <p>The driver binary has a field, <c>orig_bytes</c>, which - marks the start of the data in the binary.</p> - <p>This function is thread-safe.</p> + <marker id="driver_enq_bin"></marker> + <p>Enqueues a driver binary in the driver + queue. The data in <c>bin</c> at <c>offset</c> with length + <c>len</c> is placed at the end of the queue. This function + is most often faster than + <seealso marker="#driver_enq"><c>driver_enq</c></seealso>, + because no data must be copied.</p> + <p>This function can be called from any thread if a + <seealso marker="#ErlDrvPDL">port data lock</seealso> + associated with the <c>port</c> is locked by the calling + thread during the call.</p> + <p>The return value is <c>0</c>.</p> </desc> </func> + <func> - <name><ret>ErlDrvBinary *</ret><nametext>driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size)</nametext></name> - <fsummary>Resize a driver binary</fsummary> + <name><ret>int</ret><nametext>driver_enqv(ErlDrvPort port, ErlIOVec *ev, + ErlDrvSizeT skip)</nametext></name> + <fsummary>Enqueue vector in the driver queue.</fsummary> <desc> - <marker id="driver_realloc_binary"></marker> - <p>This function resizes a driver binary, while keeping the - data. The resized driver binary is returned. On failure (out - of memory), <c>NULL</c> is returned.</p> - <p>This function is only thread-safe when the emulator with SMP - support is used.</p> + <marker id="driver_enqv"></marker> + <p>Enqueues the data in <c>ev</c>, skipping the + first <c>skip</c> bytes of it, at the end of the driver + queue. It is faster than + <seealso marker="#driver_enq"><c>driver_enq</c></seealso>, + because no data must be copied.</p> + <p>The return value is <c>0</c>.</p> + <p>This function can be called from any thread if a + <seealso marker="#ErlDrvPDL">port data lock</seealso> + associated with the <c>port</c> is locked by the calling + thread during the call.</p> </desc> </func> + <func> - <name><ret>void</ret><nametext>driver_free_binary(ErlDrvBinary *bin)</nametext></name> - <fsummary>Free a driver binary</fsummary> + <name><ret>int</ret><nametext>driver_failure(ErlDrvPort port, int + error)</nametext></name> + <name><ret>int</ret><nametext>driver_failure_atom(ErlDrvPort port, char + *string)</nametext></name> + <name><ret>int</ret><nametext>driver_failure_posix(ErlDrvPort port, int + error)</nametext></name> + <fsummary>Fail with error.</fsummary> <desc> - <marker id="driver_free_binary"></marker> - <p>This function frees a driver binary <c>bin</c>, allocated - previously with <c>driver_alloc_binary</c>. Since binaries - in Erlang are reference counted, the binary may still be - around.</p> - <p>This function is only thread-safe when the emulator with SMP - support is used.</p> + <marker id="driver_failure_atom"></marker> + <marker id="driver_failure_posix"></marker> + <marker id="driver_failure"></marker> + <p>Signals to Erlang that the driver has + encountered an error and is to be closed. The port is + closed and the tuple <c>{'EXIT', error, Err}</c> is sent to + the port owner process, where error is an error atom + (<c>driver_failure_atom</c> and + <c>driver_failure_posix</c>) or an integer + (<c>driver_failure</c>).</p> + <p>The driver is to fail only when in severe error situations, + when the driver cannot possibly keep open, for example, + buffer allocation gets out of memory. For normal errors + it is more appropriate to send error codes with + <seealso marker="#driver_output"><c>driver_output</c></seealso>.</p> + <p>The return value is <c>0</c>.</p> </desc> </func> + <func> - <name><ret>long</ret><nametext>driver_binary_get_refc(ErlDrvBinary *bin)</nametext></name> - <fsummary>Get the reference count of a driver binary</fsummary> + <name><ret>int</ret><nametext>driver_failure_eof(ErlDrvPort + port)</nametext></name> + <fsummary>Fail with EOF.</fsummary> <desc> - <marker id="driver_binary_get_refc"></marker> - <p>Returns current reference count on <c>bin</c>.</p> - <p>This function is only thread-safe when the emulator with SMP - support is used.</p> + <marker id="driver_failure_eof"></marker> + <p>Signals to Erlang that the driver has + encountered an EOF and is to be closed, unless the port was + opened with option <c>eof</c>, in which case <c>eof</c> is sent + to the port. Otherwise the port is closed and an + <c>'EXIT'</c> message is sent to the port owner process.</p> + <p>The return value is <c>0</c>.</p> </desc> </func> + <func> - <name><ret>long</ret><nametext>driver_binary_inc_refc(ErlDrvBinary *bin)</nametext></name> - <fsummary>Increment the reference count of a driver binary</fsummary> + <name><ret>void</ret><nametext>driver_free(void *ptr)</nametext></name> + <fsummary>Free an allocated memory block.</fsummary> <desc> - <marker id="driver_binary_inc_refc"></marker> - <p>Increments the reference count on <c>bin</c> and returns - the reference count reached after the increment.</p> - <p>This function is only thread-safe when the emulator with SMP - support is used.</p> + <marker id="driver_free"></marker> + <p>Frees the memory pointed to by <c>ptr</c>. The + memory is to have been allocated with + <c>driver_alloc</c>. All allocated memory is to be + deallocated, only once. There is no garbage collection in + drivers.</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>long</ret><nametext>driver_binary_dec_refc(ErlDrvBinary *bin)</nametext></name> - <fsummary>Decrement the reference count of a driver binary</fsummary> + <name><ret>void</ret> + <nametext>driver_free_binary(ErlDrvBinary *bin)</nametext></name> + <fsummary>Free a driver binary.</fsummary> <desc> - <marker id="driver_binary_dec_refc"></marker> - <p>Decrements the reference count on <c>bin</c> and returns - the reference count reached after the decrement.</p> - <p>This function is only thread-safe when the emulator with SMP - support is used.</p> - <note> - <p>You should normally decrement the reference count of a - driver binary by calling - <seealso marker="#driver_free_binary">driver_free_binary()</seealso>. - <c>driver_binary_dec_refc()</c> does <em>not</em> free - the binary if the reference count reaches zero. <em>Only</em> - use <c>driver_binary_dec_refc()</c> when you are sure - <em>not</em> to reach a reference count of zero.</p> - </note> + <marker id="driver_free_binary"></marker> + <p>Frees a driver binary <c>bin</c>, allocated previously with + <seealso marker="#driver_alloc_binary"> + <c>driver_alloc_binary</c></seealso>. As binaries + in Erlang are reference counted, the binary can still be around.</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len)</nametext></name> - <fsummary>Enqueue data in the driver queue</fsummary> + <name><ret>ErlDrvTermData</ret> + <nametext>driver_get_monitored_process(ErlDrvPort port, const + ErlDrvMonitor *monitor)</nametext></name> + <fsummary>Retrieve the process ID from a monitor.</fsummary> <desc> - <marker id="driver_enq"></marker> - <p>This function enqueues data in the driver queue. The data in - <c>buf</c> is copied (<c>len</c> bytes) and placed at the - end of the driver queue. The driver queue is normally used - in a FIFO way.</p> - <p>The driver queue is available to queue output from the - emulator to the driver (data from the driver to the emulator - is queued by the emulator in normal erlang message - queues). This can be useful if the driver has to wait for - slow devices etc, and wants to yield back to the - emulator. The driver queue is implemented as an ErlIOVec.</p> - <p>When the queue contains data, the driver won't close, until - the queue is empty.</p> - <p>The return value is 0.</p> - <p>This function can be called from an arbitrary thread if a - <seealso marker="#ErlDrvPDL">port data lock</seealso> - associated with the <c>port</c> is locked by the calling - thread during the call.</p> + <marker id="driver_get_monitored_process"></marker> + <p>Returns the process ID associated with a living + monitor. It can be used in the + <seealso marker="driver_entry#process_exit"> + <c>process_exit</c></seealso> callback to + get the process identification for the exiting process.</p> + <p>Returns <c>driver_term_nil</c> if the monitor no longer exists.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_pushq(ErlDrvPort port, char* buf, ErlDrvSizeT len)</nametext></name> - <fsummary>Push data at the head of the driver queue</fsummary> + <name><ret>int</ret> + <nametext>driver_get_now(ErlDrvNowData *now)</nametext></name> + <fsummary>Read a system time stamp.</fsummary> <desc> - <marker id="driver_pushq"></marker> - <p>This function puts data at the head of the driver queue. The - data in <c>buf</c> is copied (<c>len</c> bytes) and placed - at the beginning of the queue.</p> - <p>The return value is 0.</p> - <p>This function can be called from an arbitrary thread if a - <seealso marker="#ErlDrvPDL">port data lock</seealso> - associated with the <c>port</c> is locked by the calling - thread during the call.</p> + <marker id="driver_get_now"></marker> + <warning> + <p><em>This function is deprecated. Do not use it.</em> Use + <seealso marker="#erl_drv_monotonic_time"> + <c>erl_drv_monotonic_time</c></seealso> (perhaps in combination with + <seealso marker="#erl_drv_time_offset"> + <c>erl_drv_time_offset</c></seealso>) instead.</p> + </warning> + <p>Reads a time stamp into the memory pointed to by + parameter <c>now</c>. For information about specific fields, see + <seealso marker="#ErlDrvNowData"><c>ErlDrvNowData</c></seealso>.</p> + <p>The return value is <c>0</c>, unless the <c>now</c> pointer is + invalid, in which case it is < <c>0</c>.</p> </desc> </func> + <func> - <name><ret>ErlDrvSizeT</ret><nametext>driver_deq(ErlDrvPort port, ErlDrvSizeT size)</nametext></name> - <fsummary>Dequeue data from the head of the driver queue</fsummary> + <name><ret>int</ret><nametext>driver_lock_driver(ErlDrvPort + port)</nametext></name> + <fsummary>Ensure the driver is never unloaded.</fsummary> <desc> - <marker id="driver_deq"></marker> - <p>This function dequeues data by moving the head pointer - forward in the driver queue by <c>size</c> bytes. The data - in the queue will be deallocated.</p> - <p>The return value is the number of bytes remaining in the queue - or -1 on failure.</p> - <p>This function can be called from an arbitrary thread if a - <seealso marker="#ErlDrvPDL">port data lock</seealso> - associated with the <c>port</c> is locked by the calling - thread during the call.</p> + <marker id="driver_lock_driver"></marker> + <p>Locks the driver used by the port <c>port</c> + in memory for the rest of the emulator process' + lifetime. After this call, the driver behaves as one of Erlang's + statically linked-in drivers.</p> </desc> </func> + <func> - <name><ret>ErlDrvSizeT</ret><nametext>driver_sizeq(ErlDrvPort port)</nametext></name> - <fsummary>Return the size of the driver queue</fsummary> + <name><ret>ErlDrvTermData</ret><nametext>driver_mk_atom(char* + string)</nametext></name> + <fsummary>Make an atom from a name.</fsummary> <desc> - <marker id="driver_sizeq"></marker> - <p>This function returns the number of bytes currently in the - driver queue.</p> - <p>This function can be called from an arbitrary thread if a - <seealso marker="#ErlDrvPDL">port data lock</seealso> - associated with the <c>port</c> is locked by the calling - thread during the call.</p> + <marker id="driver_mk_atom"></marker> + <p>Returns an atom given a name + <c>string</c>. The atom is created and does not change, so the + return value can be saved and reused, which is faster than + looking up the atom several times.</p> + <p>Notice that this function is <em>not</em> thread-safe, not + even when the emulator with SMP support is used.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name> - <fsummary>Enqueue binary in the driver queue</fsummary> + <name><ret>ErlDrvTermData</ret><nametext>driver_mk_port(ErlDrvPort + port)</nametext></name> + <fsummary>Make an Erlang term port from a port.</fsummary> <desc> - <marker id="driver_enq_bin"></marker> - <p>This function enqueues a driver binary in the driver - queue. The data in <c>bin</c> at <c>offset</c> with length - <c>len</c> is placed at the end of the queue. This function - is most often faster than <c>driver_enq</c>, because the - data doesn't have to be copied.</p> - <p>This function can be called from an arbitrary thread if a - <seealso marker="#ErlDrvPDL">port data lock</seealso> - associated with the <c>port</c> is locked by the calling - thread during the call.</p> - <p>The return value is 0.</p> + <marker id="driver_mk_port"></marker> + <p>Converts a port handle to the Erlang term format, usable in + <seealso marker="#erl_drv_output_term"> + <c>erl_drv_output_term</c></seealso> and + <seealso marker="#erl_drv_send_term"> + <c>erl_drv_send_term</c></seealso>.</p> + <p>Notice that this function is <em>not</em> thread-safe, not + even when the emulator with SMP support is used.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext></name> - <fsummary>Push binary at the head of the driver queue</fsummary> + <name><ret>int</ret><nametext>driver_monitor_process(ErlDrvPort port, + ErlDrvTermData process, ErlDrvMonitor *monitor)</nametext></name> + <fsummary>Monitor a process from a driver.</fsummary> <desc> - <marker id="driver_pushq_bin"></marker> - <p>This function puts data in the binary <c>bin</c>, at - <c>offset</c> with length <c>len</c> at the head of the - driver queue. It is most often faster than - <c>driver_pushq</c>, because the data doesn't have to be - copied.</p> - <p>This function can be called from an arbitrary thread if a - <seealso marker="#ErlDrvPDL">port data lock</seealso> - associated with the <c>port</c> is locked by the calling - thread during the call.</p> - <p>The return value is 0.</p> + <marker id="driver_monitor_process"></marker> + <p>Starts monitoring a process from a driver. When a process is + monitored, a process exit results in a call to the provided + <seealso marker="driver_entry#process_exit"> + <c>process_exit</c></seealso> callback + in the <seealso marker="driver_entry"><c>ErlDrvEntry</c></seealso> + structure. The <c>ErlDrvMonitor</c> structure is filled in, for later + removal or compare.</p> + <p>Parameter <c>process</c> is to be the return value of an + earlier call to <seealso marker="#driver_caller"> + <c>driver_caller</c></seealso> or + <seealso marker="#driver_connected"><c>driver_connected</c></seealso> + call.</p> + <p>Returns <c>0</c> on success, < 0 if no callback is + provided, and > 0 if the process is no longer alive.</p> </desc> </func> + <func> - <name><ret>ErlDrvSizeT</ret><nametext>driver_peekqv(ErlDrvPort port, ErlIOVec *ev)</nametext></name> - <fsummary>Get the driver queue as an IO vector</fsummary> + <name><ret>int</ret><nametext>driver_output(ErlDrvPort port, char *buf, + ErlDrvSizeT len)</nametext></name> + <fsummary>Send data from driver to port owner.</fsummary> <desc> - <marker id="driver_peekqv"></marker> - <p> - This function retrieves the driver queue into a supplied - <c>ErlIOVec</c> <c>ev</c>. It also returns the queue size. - This is one of two ways to get data out of the queue. - </p> - <p> - If <c>ev</c> is <c>NULL</c> all ones i.e. <c>-1</c> type cast to - <c>ErlDrvSizeT</c> is returned. - </p> - <p>Nothing is removed from the queue by this function, that must be done - with <c>driver_deq</c>.</p> - <p>This function can be called from an arbitrary thread if a - <seealso marker="#ErlDrvPDL">port data lock</seealso> - associated with the <c>port</c> is locked by the calling - thread during the call.</p> + <marker id="driver_output"></marker> + <p>Sends data from the driver up to the emulator. The data is received + as terms or binary data, depending on how the driver port was + opened.</p> + <p>The data is queued in the port owner process' message + queue. Notice that this does not yield to the emulator (as + the driver and the emulator run in the same thread).</p> + <p>Parameter <c>buf</c> points to the data to send, and + <c>len</c> is the number of bytes.</p> + <p>The return value for all output functions is <c>0</c> for normal use. + If the driver is used for distribution, it can fail and return + <c>-1</c>.</p> </desc> </func> + <func> - <name><ret>SysIOVec *</ret><nametext>driver_peekq(ErlDrvPort port, int *vlen)</nametext></name> - <fsummary>Get the driver queue as a vector</fsummary> + <name><ret>int</ret><nametext>driver_output_binary(ErlDrvPort port, char + *hbuf, ErlDrvSizeT hlen, ErlDrvBinary* bin, ErlDrvSizeT offset, + ErlDrvSizeT len)</nametext></name> + <fsummary>Send data from a driver binary to port owner.</fsummary> <desc> - <marker id="driver_peekq"></marker> - <p>This function retrieves the driver queue as a pointer to an - array of <c>SysIOVec</c>s. It also returns the number of - elements in <c>vlen</c>. This is one of two ways to get data - out of the queue.</p> - <p>Nothing is removed from the queue by this function, that must be done - with <c>driver_deq</c>.</p> - <p>The returned array is suitable to use with the Unix system - call <c>writev</c>.</p> - <p>This function can be called from an arbitrary thread if a - <seealso marker="#ErlDrvPDL">port data lock</seealso> - associated with the <c>port</c> is locked by the calling - thread during the call.</p> + <marker id="driver_output_binary"></marker> + <p>Sends data to a port owner process from a + driver binary. It has a header buffer (<c>hbuf</c> + and <c>hlen</c>) just like + <seealso marker="#driver_output2"><c>driver_output2</c></seealso>. + Parameter <c>hbuf</c> can be <c>NULL</c>.</p> + <p>Parameter <c>offset</c> is an offset into the binary and + <c>len</c> is the number of bytes to send.</p> + <p>Driver binaries are created with + <seealso marker="#driver_alloc_binary"> + <c>driver_alloc_binary</c></seealso>.</p> + <p>The data in the header is sent as a list and the binary as + an Erlang binary in the tail of the list.</p> + <p>For example, if <c>hlen</c> is <c>2</c>, the port owner process + receives <c><![CDATA[[H1, H2 | <<T>>]]]></c>.</p> + <p>The return value is <c>0</c> for normal use.</p> + <p>Notice that, using the binary syntax in Erlang, the driver + application can match the header directly from the binary, + so the header can be put in the binary, and <c>hlen</c> can be set + to <c>0</c>.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_enqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name> - <fsummary>Enqueue vector in the driver queue</fsummary> + <name><ret>int</ret><nametext>driver_output_term(ErlDrvPort port, + ErlDrvTermData* term, int n)</nametext></name> + <fsummary>Send term data from driver to port owner.</fsummary> <desc> - <marker id="driver_enqv"></marker> - <p>This function enqueues the data in <c>ev</c>, skipping the - first <c>skip</c> bytes of it, at the end of the driver - queue. It is faster than <c>driver_enq</c>, because the data - doesn't have to be copied.</p> - <p>The return value is 0.</p> - <p>This function can be called from an arbitrary thread if a - <seealso marker="#ErlDrvPDL">port data lock</seealso> - associated with the <c>port</c> is locked by the calling - thread during the call.</p> + <marker id="driver_output_term"></marker> + <warning> + <p><em>This function is deprecated.</em> + Use <seealso marker="#erl_drv_send_term"> + <c>erl_drv_output_term</c></seealso>instead.</p> + </warning> + <p>Parameters <c>term</c> and <c>n</c> work as in + <seealso marker="#erl_drv_output_term"> + <c>erl_drv_output_term</c></seealso>.</p> + <p>Notice that this function is <em>not</em> thread-safe, not + even when the emulator with SMP support is used.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_pushqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name> - <fsummary>Push vector at the head of the driver queue</fsummary> + <name><ret>int</ret><nametext>driver_output2(ErlDrvPort port, char *hbuf, + ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len)</nametext></name> + <fsummary>Send data and binary data to port owner.</fsummary> <desc> - <marker id="driver_pushqv"></marker> - <p>This function puts the data in <c>ev</c>, skipping the first - <c>skip</c> bytes of it, at the head of the driver queue. - It is faster than <c>driver_pushq</c>, because the data - doesn't have to be copied.</p> - <p>The return value is 0.</p> - <p>This function can be called from an arbitrary thread if a - <seealso marker="#ErlDrvPDL">port data lock</seealso> - associated with the <c>port</c> is locked by the calling - thread during the call.</p> + <marker id="driver_output2"></marker> + <p>First sends <c>hbuf</c> + (length in <c>hlen</c>) data as a list, regardless of port + settings. Then sends <c>buf</c> as a binary or list. + For example, if <c>hlen</c> is <c>3</c>, the port owner process + receives <c>[H1, H2, H3 | T]</c>.</p> + <p>The point of sending data as a list header, is to facilitate + matching on the data received.</p> + <p>The return value is <c>0</c> for normal use.</p> </desc> </func> + <func> - <name><ret>ErlDrvPDL</ret><nametext>driver_pdl_create(ErlDrvPort port)</nametext></name> - <fsummary>Create a port data lock</fsummary> + <name><ret>int</ret><nametext>driver_outputv(ErlDrvPort port, char* hbuf, + ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip)</nametext></name> + <fsummary>Send vectorized data to port owner.</fsummary> <desc> - <marker id="driver_pdl_create"></marker> - <p>This function creates a port data lock associated with - the <c>port</c>. <em>NOTE</em>: Once a port data lock has - been created, it has to be locked during all operations - on the driver queue of the <c>port</c>.</p> - <p>On success a newly created port data lock is returned. On - failure <c>NULL</c> is returned. <c>driver_pdl_create()</c> will - fail if <c>port</c> is invalid or if a port data lock already has - been associated with the <c>port</c>.</p> + <marker id="driver_outputv"></marker> + <p>Sends data from an I/O vector, <c>ev</c>, to + the port owner process. It has a header buffer (<c>hbuf</c> + and <c>hlen</c>), just like <seealso marker="#driver_output2"> + <c>driver_output2</c></seealso>.</p> + <p>Parameter <c>skip</c> is a number of bytes to skip of + the <c>ev</c> vector from the head.</p> + <p>You get vectors of <c>ErlIOVec</c> type from the driver + queue (see below), and the + <seealso marker="driver_entry#outputv"><c>outputv</c></seealso> + driver entry function. You can also make them yourself, if you want to + send several <c>ErlDrvBinary</c> buffers at once. Often + it is faster to use + <seealso marker="#driver_output"><c>driver_output</c></seealso> or + <seealso marker="#driver_output_binary"></seealso>.</p> + <p>For example, if <c>hlen</c> is <c>2</c> and <c>ev</c> points to an + array of three binaries, the port owner process receives + <c><![CDATA[[H1, H2, <<B1>>, <<B2>> | <<B3>>]]]></c>.</p> + <p>The return value is <c>0</c> for normal use.</p> + <p>The comment for <c>driver_output_binary</c> also applies for + <c>driver_outputv</c>.</p> </desc> </func> + <func> - <name><ret>void</ret><nametext>driver_pdl_lock(ErlDrvPDL pdl)</nametext></name> - <fsummary>Lock port data lock</fsummary> + <name><ret>ErlDrvPDL</ret> + <nametext>driver_pdl_create(ErlDrvPort port)</nametext></name> + <fsummary>Create a port data lock.</fsummary> <desc> - <marker id="driver_pdl_lock"></marker> - <p>This function locks the port data lock passed as argument - (<c>pdl</c>).</p> - <p>This function is thread-safe.</p> + <marker id="driver_pdl_create"></marker> + <p>Creates a port data lock associated with the <c>port</c>.</p> + <note> + <p>Once a port data lock has been created, it must be locked during + all operations on the driver queue of the <c>port</c>.</p> + </note> + <p>Returns a newly created port data lock on success, + otherwise <c>NULL</c>. The function fails + if <c>port</c> is invalid or if a port data lock already has + been associated with the <c>port</c>.</p> </desc> </func> + <func> - <name><ret>void</ret><nametext>driver_pdl_unlock(ErlDrvPDL pdl)</nametext></name> - <fsummary>Unlock port data lock</fsummary> + <name><ret>long</ret><nametext>driver_pdl_dec_refc(ErlDrvPDL + pdl)</nametext></name> + <fsummary></fsummary> <desc> - <marker id="driver_pdl_unlock"></marker> - <p>This function unlocks the port data lock passed as argument - (<c>pdl</c>).</p> + <marker id="driver_pdl_dec_refc"></marker> + <p>Decrements the reference count of + the port data lock passed as argument (<c>pdl</c>).</p> + <p>The current reference count after the decrement has + been performed is returned.</p> <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>long</ret><nametext>driver_pdl_get_refc(ErlDrvPDL pdl)</nametext></name> + <name><ret>long</ret> + <nametext>driver_pdl_get_refc(ErlDrvPDL pdl)</nametext></name> <fsummary></fsummary> <desc> <marker id="driver_pdl_get_refc"></marker> - <p>This function returns the current reference count of + <p>Returns the current reference count of the port data lock passed as argument (<c>pdl</c>).</p> <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>long</ret><nametext>driver_pdl_inc_refc(ErlDrvPDL pdl)</nametext></name> + <name><ret>long</ret> + <nametext>driver_pdl_inc_refc(ErlDrvPDL pdl)</nametext></name> <fsummary></fsummary> <desc> <marker id="driver_pdl_inc_refc"></marker> - <p>This function increments the reference count of + <p>Increments the reference count of the port data lock passed as argument (<c>pdl</c>).</p> <p>The current reference count after the increment has been performed is returned.</p> <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>long</ret><nametext>driver_pdl_dec_refc(ErlDrvPDL pdl)</nametext></name> - <fsummary></fsummary> + <name><ret>void</ret> + <nametext>driver_pdl_lock(ErlDrvPDL pdl)</nametext></name> + <fsummary>Lock port data lock.</fsummary> <desc> - <marker id="driver_pdl_dec_refc"></marker> - <p>This function decrements the reference count of - the port data lock passed as argument (<c>pdl</c>).</p> - <p>The current reference count after the decrement has - been performed is returned.</p> + <marker id="driver_pdl_lock"></marker> + <p>Locks the port data lock passed as argument (<c>pdl</c>).</p> <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_monitor_process(ErlDrvPort port, ErlDrvTermData process, ErlDrvMonitor *monitor)</nametext></name> - <fsummary>Monitor a process from a driver</fsummary> + <name><ret>void</ret> + <nametext>driver_pdl_unlock(ErlDrvPDL pdl)</nametext></name> + <fsummary>Unlock port data lock.</fsummary> <desc> - <marker id="driver_monitor_process"></marker> - <p>Start monitoring a process from a driver. When a process is - monitored, a process exit will result in a call to the - provided <seealso marker="driver_entry#process_exit">process_exit</seealso> call-back - in the <seealso marker="driver_entry">ErlDrvEntry</seealso> - structure. The <c>ErlDrvMonitor</c> structure is filled in, for later - removal or compare.</p> - <p>The <c>process</c> parameter should be the return value of an - earlier call to <seealso marker="#driver_caller">driver_caller</seealso> or <seealso marker="#driver_connected">driver_connected</seealso> call.</p> - <p>The function returns 0 on success, < 0 if no call-back is - provided and > 0 if the process is no longer alive.</p> + <marker id="driver_pdl_unlock"></marker> + <p>Unlocks the port data lock passed as argument (<c>pdl</c>).</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_demonitor_process(ErlDrvPort port, const ErlDrvMonitor *monitor)</nametext></name> - <fsummary>Stop monitoring a process from a driver</fsummary> + <name><ret>SysIOVec *</ret><nametext>driver_peekq(ErlDrvPort port, int + *vlen)</nametext></name> + <fsummary>Get the driver queue as a vector.</fsummary> <desc> - <marker id="driver_demonitor_process"></marker> - <p>This function cancels a monitor created earlier. </p> - <p>The function returns 0 if a monitor was removed and > 0 - if the monitor did no longer exist.</p> + <marker id="driver_peekq"></marker> + <p>Retrieves the driver queue as a pointer to an + array of <c>SysIOVec</c>s. It also returns the number of + elements in <c>vlen</c>. This is one of two ways to get data + out of the queue.</p> + <p>Nothing is removed from the queue by this function, that must be done + with <seealso marker="#driver_deq"><c>driver_deq</c></seealso>.</p> + <p>The returned array is suitable to use with the Unix system + call <c>writev</c>.</p> + <p>This function can be called from any thread if a + <seealso marker="#ErlDrvPDL">port data lock</seealso> + associated with the <c>port</c> is locked by the calling + thread during the call.</p> </desc> </func> + <func> - <name><ret>ErlDrvTermData</ret><nametext>driver_get_monitored_process(ErlDrvPort port, const ErlDrvMonitor *monitor)</nametext></name> - <fsummary>Retrieve the process id from a monitor</fsummary> + <name><ret>ErlDrvSizeT</ret><nametext>driver_peekqv(ErlDrvPort port, + ErlIOVec *ev)</nametext></name> + <fsummary>Get the driver queue as an I/O vector.</fsummary> <desc> - <marker id="driver_get_monitored_process"></marker> - <p>The function returns the process id associated with a living - monitor. It can be used in the <c>process_exit</c> call-back to - get the process identification for the exiting process.</p> - <p>The function returns <c>driver_term_nil</c> if the monitor - no longer exists.</p> + <marker id="driver_peekqv"></marker> + <p>Retrieves the driver queue into a supplied + <c>ErlIOVec</c> <c>ev</c>. It also returns the queue size. + This is one of two ways to get data out of the queue.</p> + <p>If <c>ev</c> is <c>NULL</c>, all ones that is <c>-1</c> type cast to + <c>ErlDrvSizeT</c> are returned.</p> + <p>Nothing is removed from the queue by this function, that must be done + with <seealso marker="#driver_deq"><c>driver_deq</c></seealso>.</p> + <p>This function can be called from any thread if a + <seealso marker="#ErlDrvPDL">port data lock</seealso> + associated with the <c>port</c> is locked by the calling + thread during the call.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_compare_monitors(const ErlDrvMonitor *monitor1, const ErlDrvMonitor *monitor2)</nametext></name> - <fsummary>Compare two monitors</fsummary> + <name><ret>int</ret><nametext>driver_pushq(ErlDrvPort port, char* buf, + ErlDrvSizeT len)</nametext></name> + <fsummary>Push data at the head of the driver queue.</fsummary> <desc> - <marker id="driver_compare_monitors"></marker> - <p>This function is used to compare two <c>ErlDrvMonitor</c>s. It - can also be used to imply some artificial order on monitors, - for whatever reason.</p> - <p>The function returns 0 if <c>monitor1</c> and - <c>monitor2</c> are equal, < 0 if <c>monitor1</c> is less - than <c>monitor2</c> and > 0 if <c>monitor1</c> is greater - than <c>monitor2</c>.</p> + <marker id="driver_pushq"></marker> + <p>Puts data at the head of the driver queue. The + data in <c>buf</c> is copied (<c>len</c> bytes) and placed + at the beginning of the queue.</p> + <p>The return value is <c>0</c>.</p> + <p>This function can be called from any thread if a + <seealso marker="#ErlDrvPDL">port data lock</seealso> + associated with the <c>port</c> is locked by the calling + thread during the call.</p> </desc> </func> + <func> - <name><ret>void</ret><nametext>add_driver_entry(ErlDrvEntry *de)</nametext></name> - <fsummary>Add a driver entry</fsummary> + <name><ret>int</ret><nametext>driver_pushq_bin(ErlDrvPort port, + ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len)</nametext> + </name> + <fsummary>Push binary at the head of the driver queue.</fsummary> <desc> - <marker id="add_driver_entry"></marker> - <p>This function adds a driver entry to the list of drivers - known by Erlang. The <seealso marker="driver_entry#init">init</seealso> function of the <c>de</c> - parameter is called.</p> - <note> - <p>To use this function for adding drivers residing in - dynamically loaded code is dangerous. If the driver code - for the added driver resides in the same dynamically - loaded module (i.e. <c>.so</c> file) as a normal - dynamically loaded driver (loaded with the <c>erl_ddll</c> - interface), the caller should call <seealso marker="#driver_lock_driver">driver_lock_driver</seealso> before - adding driver entries.</p> - <p>Use of this function is generally deprecated.</p> - </note> + <marker id="driver_pushq_bin"></marker> + <p>Puts data in the binary <c>bin</c>, at + <c>offset</c> with length <c>len</c> at the head of the + driver queue. It is most often faster than + <seealso marker="#driver_pushq"><c>driver_pushq</c></seealso>, + because no data must be copied.</p> + <p>This function can be called from any thread if a + <seealso marker="#ErlDrvPDL">port data lock</seealso> + associated with the <c>port</c> is locked by the calling + thread during the call.</p> + <p>The return value is <c>0</c>.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>remove_driver_entry(ErlDrvEntry *de)</nametext></name> - <fsummary>Remove a driver entry</fsummary> + <name><ret>int</ret><nametext>driver_pushqv(ErlDrvPort port, ErlIOVec + *ev, ErlDrvSizeT skip)</nametext></name> + <fsummary>Push vector at the head of the driver queue.</fsummary> <desc> - <marker id="remove_driver_entry"></marker> - <p>This function removes a driver entry <c>de</c> previously - added with <c>add_driver_entry</c>.</p> - <p>Driver entries added by the <c>erl_ddll</c> erlang interface can - not be removed by using this interface.</p> + <marker id="driver_pushqv"></marker> + <p>Puts the data in <c>ev</c>, skipping the first + <c>skip</c> bytes of it, at the head of the driver queue. + It is faster than + <seealso marker="#driver_pushq"><c>driver_pushq</c></seealso>, + because no data must be copied.</p> + <p>The return value is <c>0</c>.</p> + <p>This function can be called from any thread if a + <seealso marker="#ErlDrvPDL">port data lock</seealso> + associated with the <c>port</c> is locked by the calling + thread during the call.</p> </desc> </func> + <func> - <name><ret>char *</ret><nametext>erl_errno_id(int error)</nametext></name> - <fsummary>Get erlang error atom name from error number</fsummary> + <name><ret>int</ret><nametext>driver_read_timer(ErlDrvPort port, unsigned + long *time_left)</nametext></name> + <fsummary>Read the time left before time-out.</fsummary> <desc> - <marker id="erl_errno_id"></marker> - <p>This function returns the atom name of the erlang error, - given the error number in <c>error</c>. Error atoms are: - <c>einval</c>, <c>enoent</c>, etc. It can be used to make - error terms from the driver.</p> + <marker id="driver_read_timer"></marker> + <p>Reads the current time of a timer, and places + the result in <c>time_left</c>. This is the time in + milliseconds, before the time-out occurs.</p> + <p>The return value is <c>0</c>.</p> </desc> </func> + <func> - <name><ret>void</ret><nametext>erl_drv_busy_msgq_limits(ErlDrvPort port, ErlDrvSizeT *low, ErlDrvSizeT *high)</nametext></name> - <fsummary>Set and get limits for busy port message queue</fsummary> + <name><ret>void *</ret> + <nametext>driver_realloc(void *ptr, ErlDrvSizeT size)</nametext></name> + <fsummary>Resize an allocated memory block.</fsummary> <desc> - <marker id="erl_drv_busy_msgq_limits"></marker> - <p>Sets and gets limits that will be used for controling the - busy state of the port message queue.</p> - <p>The port message queue will be set into a busy - state when the amount of command data queued on the - message queue reaches the <c>high</c> limit. The port - message queue will be set into a not busy state when the - amount of command data queued on the message queue falls - below the <c>low</c> limit. Command data is in this - context data passed to the port using either - <c>Port ! {Owner, {command, Data}}</c>, or - <c>port_command/[2,3]</c>. Note that these limits - only concerns command data that have not yet reached the - port. The <seealso marker="#set_busy_port">busy port</seealso> - feature can be used for data that has reached the port.</p> - - <p>Valid limits are values in the range - <c>[ERL_DRV_BUSY_MSGQ_LIM_MIN, ERL_DRV_BUSY_MSGQ_LIM_MAX]</c>. - Limits will be automatically adjusted to be sane. That is, - the system will adjust values so that the low limit used is - lower than or equal to the high limit used. By default the high - limit will be 8 kB and the low limit will be 4 kB.</p> - - <p>By passing a pointer to an integer variable containing - the value <c>ERL_DRV_BUSY_MSGQ_READ_ONLY</c>, currently used - limit will be read and written back to the integer variable. - A new limit can be set by passing a pointer to an integer - variable containing a valid limit. The passed value will be - written to the internal limit. The internal limit will then - be adjusted. After this the adjusted limit will be written - back to the integer variable from which the new value was - read. Values are in bytes.</p> - - <p>The busy message queue feature can be disabled either - by setting the <c>ERL_DRV_FLAG_NO_BUSY_MSGQ</c> - <seealso marker="driver_entry#driver_flags">driver flag</seealso> - in the <seealso marker="driver_entry">driver_entry</seealso> - used by the driver, or by calling this function with - <c>ERL_DRV_BUSY_MSGQ_DISABLED</c> as a limit (either low or - high). When this feature has been disabled it cannot be - enabled again. When reading the limits both of them - will be <c>ERL_DRV_BUSY_MSGQ_DISABLED</c>, if this - feature has been disabled.</p> - - <p>Processes sending command data to the port will be suspended - if either the port is busy or if the port message queue is - busy. Suspended processes will be resumed when neither the - port is busy, nor the port message queue is busy.</p> - - <p>For information about busy port functionality - see the documentation of the - <seealso marker="#set_busy_port">set_busy_port()</seealso> - function.</p> - </desc> - </func> - <func> - <name><ret>void</ret><nametext>set_busy_port(ErlDrvPort port, int on)</nametext></name> - <fsummary>Signal or unsignal port as busy</fsummary> - <desc> - <marker id="set_busy_port"></marker> - <p>This function set and unset the busy state of the port. If - <c>on</c> is non-zero, the port is set to busy, if it's zero the port - is set to not busy. You typically want to combine - this feature with the <seealso marker="#erl_drv_busy_msgq_limits">busy - port message queue</seealso> functionality.</p> - <p>Processes sending command data to the port will be suspended - if either the port is busy or if the port message queue - is busy. Suspended processes will be resumed when neither the - port is busy, nor the port message queue is busy. Command data - is in this context data passed to the port using either - <c>Port ! {Owner, {command, Data}}</c>, or - <c>port_command/[2,3]</c>.</p> - <p>If the - <seealso marker="driver_entry#driver_flags"><![CDATA[ERL_DRV_FLAG_SOFT_BUSY]]></seealso> - has been set in the - <seealso marker="driver_entry">driver_entry</seealso>, - data can be forced into the driver via - <seealso marker="erlang#port_command/3">port_command(Port, Data, [force])</seealso> - even though the driver has signaled that it is busy. - </p> - <p>For information about busy port message queue functionality - see the documentation of the - <seealso marker="#erl_drv_busy_msgq_limits">erl_drv_busy_msgq_limits()</seealso> - function.</p> - </desc> - </func> - <func> - <name><ret>void</ret><nametext>set_port_control_flags(ErlDrvPort port, int flags)</nametext></name> - <fsummary>Set flags on how to handle control entry function</fsummary> - <desc> - <marker id="set_port_control_flags"></marker> - <p>This function sets flags for how the <seealso marker="driver_entry#control">control</seealso> driver entry - function will return data to the port owner process. (The - <c>control</c> function is called from <c>port_control/3</c> - in erlang.)</p> - <p>Currently there are only two meaningful values for - <c>flags</c>: 0 means that data is returned in a list, and - <c>PORT_CONTROL_FLAG_BINARY</c> means data is returned as - a binary from <c>control</c>.</p> + <marker id="driver_realloc"></marker> + <p>Resizes a memory block, either in place, or by + allocating a new block, copying the data, and freeing the old + block. A pointer is returned to the reallocated memory. On + failure (out of memory), <c>NULL</c> is returned. (This is + most often a wrapper for <c>realloc</c>.)</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_failure_eof(ErlDrvPort port)</nametext></name> - <fsummary>Fail with EOF</fsummary> + <name><ret>ErlDrvBinary *</ret> + <nametext>driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size) + </nametext></name> + <fsummary>Resize a driver binary.</fsummary> <desc> - <marker id="driver_failure_eof"></marker> - <p>This function signals to erlang that the driver has - encountered an EOF and should be closed, unless the port was - opened with the <c>eof</c> option, in that case eof is sent - to the port. Otherwise, the port is closed and an - <c>'EXIT'</c> message is sent to the port owner process.</p> - <p>The return value is 0.</p> + <marker id="driver_realloc_binary"></marker> + <p>Resizes a driver binary, while keeping the data.</p> + <p>Returns the resized driver binary on success. Returns <c>NULL</c> + on failure (out of memory).</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_failure_atom(ErlDrvPort port, char *string)</nametext></name> - <name><ret>int</ret><nametext>driver_failure_posix(ErlDrvPort port, int error)</nametext></name> - <name><ret>int</ret><nametext>driver_failure(ErlDrvPort port, int error)</nametext></name> - <fsummary>Fail with error</fsummary> + <name><ret>int</ret><nametext>driver_select(ErlDrvPort port, ErlDrvEvent + event, int mode, int on)</nametext></name> + <fsummary>Provides an event for having the emulator call the driver. + </fsummary> <desc> - <marker id="driver_failure_atom"></marker> - <marker id="driver_failure_posix"></marker> - <marker id="driver_failure"></marker> - <p>These functions signal to Erlang that the driver has - encountered an error and should be closed. The port is - closed and the tuple <c>{'EXIT', error, Err}</c>, is sent to - the port owner process, where error is an error atom - (<c>driver_failure_atom</c> and - <c>driver_failure_posix</c>), or an integer - (<c>driver_failure</c>).</p> - <p>The driver should fail only when in severe error situations, - when the driver cannot possibly keep open, for instance - buffer allocation gets out of memory. For normal errors - it is more appropriate to send error codes with - <c>driver_output</c>.</p> - <p>The return value is 0.</p> + <marker id="driver_select"></marker> + <p>This function is used by drivers to provide the emulator with + events to check for. This enables the emulator to call the driver + when something has occurred asynchronously.</p> + <p>Parameter <c>event</c> identifies an OS-specific event object. + On Unix systems, the functions <c>select</c>/<c>poll</c> are used. + The event object must be a socket or pipe (or other object that + <c>select</c>/<c>poll</c> can use). + On Windows, the Win32 API function <c>WaitForMultipleObjects</c> + is used. This places other restrictions on the event object; + see the Win32 SDK documentation.</p> + <p>Parameter <c>on</c> is to be <c>1</c> for setting events + and <c>0</c> for clearing them.</p> + <p>Parameter <c>mode</c> is a bitwise OR combination of + <c>ERL_DRV_READ</c>, <c>ERL_DRV_WRITE</c>, and <c>ERL_DRV_USE</c>. + The first two specify whether to wait for read events and/or write + events. A fired read event calls + <seealso marker="driver_entry#ready_input"> + <c>ready_input</c></seealso> and a fired write event calls + <seealso marker="driver_entry#ready_output"> + <c>ready_output</c></seealso>.</p> + <note> + <p>Some OS (Windows) do not differentiate between read and write + events. The callback for a fired event then only depends on the + value of <c>mode</c>.</p> + </note> + <p><c>ERL_DRV_USE</c> specifies if we are using the event object or + if we want to close it. + On an emulator with SMP support, it is not safe to clear all events + and then close the event object after <c>driver_select</c> has + returned. Another thread can still be using the event object + internally. To safely close an event object, call + <c>driver_select</c> with <c>ERL_DRV_USE</c> and <c>on==0</c>, which + clears all events and then either calls + <seealso marker="driver_entry#stop_select"><c>stop_select</c></seealso> + or schedules it to be called when it is safe to close the event + object. <c>ERL_DRV_USE</c> is to be set together with the first event + for an event object. It is harmless to set <c>ERL_DRV_USE</c> + even if it already has been done. Clearing all events but keeping + <c>ERL_DRV_USE</c> set indicates that we are using the event + object and probably will set events for it again.</p> + <note> + <p><c>ERL_DRV_USE</c> was added in Erlang/OTP R13. Old drivers still + work as before, but it is recommended to update them to use + <c>ERL_DRV_USE</c> and <c>stop_select</c> to ensure that event + objects are closed in a safe way.</p> + </note> + <p>The return value is <c>0</c>, unless + <c>ready_input</c>/<c>ready_output</c> is <c>NULL</c>, in which case + it is <c>-1</c>.</p> </desc> </func> + <func> - <name><ret>ErlDrvTermData</ret><nametext>driver_connected(ErlDrvPort port)</nametext></name> - <fsummary>Return the port owner process</fsummary> + <name><ret>int</ret><nametext>driver_send_term(ErlDrvPort port, + ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name> + <fsummary>Send term data to other process than port owner process. + </fsummary> <desc> - <marker id="driver_connected"></marker> - <p>This function returns the port owner process.</p> - <p>Note that this function is <em>not</em> thread-safe, not - even when the emulator with SMP support is used.</p> + <marker id="driver_send_term"></marker> + <warning> + <p><em>This function is deprecated.</em> + Use <seealso marker="#erl_drv_send_term"> + <c>erl_drv_send_term</c></seealso> instead.</p> + </warning> + <note> + <p>The parameters of this function + cannot be properly checked by the runtime system when + executed by arbitrary threads. This can cause the + function not to fail when it should.</p> + </note> + <p>Parameters <c>term</c> and <c>n</c> work as in + <seealso marker="#erl_drv_output_term"> + <c>erl_drv_output_term</c></seealso>.</p> + <p>This function is only thread-safe when the emulator with SMP + support is used.</p> </desc> </func> + <func> - <name><ret>ErlDrvTermData</ret><nametext>driver_caller(ErlDrvPort port)</nametext></name> - <fsummary>Return the process making the driver call</fsummary> + <name><ret>int</ret><nametext>driver_set_timer(ErlDrvPort port, unsigned + long time)</nametext></name> + <fsummary>Set a timer to call the driver.</fsummary> <desc> - <marker id="driver_caller"></marker> - <p>This function returns the process id of the process that - made the current call to the driver. The process id can be - used with <c>driver_send_term</c> to send back data to the - caller. <c>driver_caller()</c> only returns valid data - when currently executing in one of the following driver - callbacks:</p> - <taglist> - <tag><seealso marker="driver_entry#start">start</seealso></tag> - <item>Called from <c>open_port/2</c>.</item> - <tag><seealso marker="driver_entry#output">output</seealso></tag> - <item>Called from <c>erlang:send/2</c>, and - <c>erlang:port_command/2</c></item> - <tag><seealso marker="driver_entry#outputv">outputv</seealso></tag> - <item>Called from <c>erlang:send/2</c>, and - <c>erlang:port_command/2</c></item> - <tag><seealso marker="driver_entry#control">control</seealso></tag> - <item>Called from <c>erlang:port_control/3</c></item> - <tag><seealso marker="driver_entry#call">call</seealso></tag> - <item>Called from <c>erlang:port_call/3</c></item> - </taglist> - <p>Note that this function is <em>not</em> thread-safe, not - even when the emulator with SMP support is used.</p> + <marker id="driver_set_timer"></marker> + <p>Sets a timer on the driver, which will count + down and call the driver when it is timed out. Parameter + <c>time</c> is the time in milliseconds before the timer expires.</p> + <p>When the timer reaches <c>0</c> and expires, the driver entry + function <seealso marker="driver_entry#timeout"> + <c>timeout</c></seealso> is called.</p> + <p>Notice that only one timer exists on each driver instance; + setting a new timer replaces an older one.</p> + <p>Return value is <c>0</c>, unless the <c>timeout</c> + driver function is <c>NULL</c>, in which case it is <c>-1</c>.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>erl_drv_output_term(ErlDrvTermData port, ErlDrvTermData* term, int n)</nametext></name> - <fsummary>Send term data from driver to port owner</fsummary> + <name><ret>ErlDrvSizeT</ret> + <nametext>driver_sizeq(ErlDrvPort port)</nametext></name> + <fsummary>Return the size of the driver queue.</fsummary> <desc> - <marker id="erl_drv_output_term"></marker> - <p>This functions sends data in the special driver term - format to the port owner process. This is a fast way to - deliver term data from a driver. It also needs no binary - conversion, so the port owner process receives data as - normal Erlang terms. The - <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso> - functions can be used for sending to any arbitrary process - on the local node.</p> - <note><p>Note that the <c>port</c> parameter is <em>not</em> - an ordinary port handle, but a port handle converted using - <c>driver_mk_port()</c>.</p></note> - <p>The <c>term</c> parameter points to an array of - <c>ErlDrvTermData</c>, with <c>n</c> elements. This array - contains terms described in the driver term format. Every - term consists of one to four elements in the array. The - term first has a term type, and then arguments. The - <c>port</c> parameter specifies the sending port.</p> - <p>Tuples, maps and lists (with the exception of strings, see below), - are built in reverse polish notation, so that to build a - tuple, the elements are given first, and then the tuple - term, with a count. Likewise for lists and maps.</p> - <p>A tuple must be specified with the number of elements. (The - elements precede the <c>ERL_DRV_TUPLE</c> term.)</p> - <p>A list must be specified with the number of elements, - including the tail, which is the last term preceding - <c>ERL_DRV_LIST</c>.</p> - <p>A map must be specified with the number of key-value pairs <c>N</c>. - The key-value pairs must precede the <c>ERL_DRV_MAP</c> in this order: - <c>key1,value1,key2,value2,...,keyN,valueN</c>. - Duplicate keys are not allowed.</p> - <p>The special term <c>ERL_DRV_STRING_CONS</c> is used to - "splice" in a string in a list, a string given this way is - not a list per se, but the elements are elements of the - surrounding list.</p> - <pre> -Term type Argument(s) -=========================================== -ERL_DRV_NIL -ERL_DRV_ATOM ErlDrvTermData atom (from driver_mk_atom(char *string)) -ERL_DRV_INT ErlDrvSInt integer -ERL_DRV_UINT ErlDrvUInt integer -ERL_DRV_INT64 ErlDrvSInt64 *integer_ptr -ERL_DRV_UINT64 ErlDrvUInt64 *integer_ptr -ERL_DRV_PORT ErlDrvTermData port (from driver_mk_port(ErlDrvPort port)) -ERL_DRV_BINARY ErlDrvBinary *bin, ErlDrvUInt len, ErlDrvUInt offset -ERL_DRV_BUF2BINARY char *buf, ErlDrvUInt len -ERL_DRV_STRING char *str, int len -ERL_DRV_TUPLE int sz -ERL_DRV_LIST int sz -ERL_DRV_PID ErlDrvTermData pid (from driver_connected(ErlDrvPort port) or driver_caller(ErlDrvPort port)) -ERL_DRV_STRING_CONS char *str, int len -ERL_DRV_FLOAT double *dbl -ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len -ERL_DRV_MAP int sz - </pre> - <p>The unsigned integer data type <c>ErlDrvUInt</c> and the - signed integer data type <c>ErlDrvSInt</c> are 64 bits wide - on a 64 bit runtime system and 32 bits wide on a 32 bit - runtime system. They were introduced in erts version 5.6, - and replaced some of the <c>int</c> arguments in the list above. - </p> - <p>The unsigned integer data type <c>ErlDrvUInt64</c> and the - signed integer data type <c>ErlDrvSInt64</c> are always 64 bits - wide. They were introduced in erts version 5.7.4. - </p> - - <p>To build the tuple <c>{tcp, Port, [100 | Binary]}</c>, the - following call could be made.</p> - <code type="none"><![CDATA[ - ErlDrvBinary* bin = ... - ErlDrvPort port = ... - ErlDrvTermData spec[] = { - ERL_DRV_ATOM, driver_mk_atom("tcp"), - ERL_DRV_PORT, driver_mk_port(drvport), - ERL_DRV_INT, 100, - ERL_DRV_BINARY, bin, 50, 0, - ERL_DRV_LIST, 2, - ERL_DRV_TUPLE, 3, - }; - erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); - ]]> - </code> - <p>Where <c>bin</c> is a driver binary of length at least 50 - and <c>drvport</c> is a port handle. Note that the <c>ERL_DRV_LIST</c> - comes after the elements of the list, likewise the - <c>ERL_DRV_TUPLE</c>.</p> - <p>The term <c>ERL_DRV_STRING_CONS</c> is a way to construct - strings. It works differently from how <c>ERL_DRV_STRING</c> - works. <c>ERL_DRV_STRING_CONS</c> builds a string list in - reverse order, (as opposed to how <c>ERL_DRV_LIST</c> - works), concatenating the strings added to a list. The tail - must be given before <c>ERL_DRV_STRING_CONS</c>.</p> - <p>The <c>ERL_DRV_STRING</c> constructs a string, and ends - it. (So it's the same as <c>ERL_DRV_NIL</c> followed by - <c>ERL_DRV_STRING_CONS</c>.)</p> - <code type="none"><![CDATA[ - /* to send [x, "abc", y] to the port: */ - ErlDrvTermData spec[] = { - ERL_DRV_ATOM, driver_mk_atom("x"), - ERL_DRV_STRING, (ErlDrvTermData)"abc", 3, - ERL_DRV_ATOM, driver_mk_atom("y"), - ERL_DRV_NIL, - ERL_DRV_LIST, 4 - }; - erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); - ]]></code> - <p></p> - <code type="none"><![CDATA[ - /* to send "abc123" to the port: */ - ErlDrvTermData spec[] = { - ERL_DRV_NIL, /* with STRING_CONS, the tail comes first */ - ERL_DRV_STRING_CONS, (ErlDrvTermData)"123", 3, - ERL_DRV_STRING_CONS, (ErlDrvTermData)"abc", 3, - }; - erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); - ]]></code> - <p>The <c>ERL_DRV_EXT2TERM</c> term type is used for passing a - term encoded with the - <seealso marker="erl_ext_dist">external format</seealso>, - i.e., a term that has been encoded by - <seealso marker="erlang#term_to_binary/2">erlang:term_to_binary</seealso>, - <seealso marker="erl_interface:ei">erl_interface</seealso>, etc. - For example, if <c>binp</c> is a pointer to an <c>ErlDrvBinary</c> - that contains the term <c>{17, 4711}</c> encoded with the - <seealso marker="erl_ext_dist">external format</seealso> - and you want to wrap it in a two tuple with the tag <c>my_tag</c>, - i.e., <c>{my_tag, {17, 4711}}</c>, you can do as follows: - </p> - <code type="none"><![CDATA[ - ErlDrvTermData spec[] = { - ERL_DRV_ATOM, driver_mk_atom("my_tag"), - ERL_DRV_EXT2TERM, (ErlDrvTermData) binp->orig_bytes, binp->orig_size - ERL_DRV_TUPLE, 2, - }; - erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); - ]]></code> - - <p>To build the map <c>#{key1 => 100, key2 => {200, 300}}</c>, the - following call could be made.</p> - <code type="none"><![CDATA[ - ErlDrvPort port = ... - ErlDrvTermData spec[] = { - ERL_DRV_ATOM, driver_mk_atom("key1"), - ERL_DRV_INT, 100, - ERL_DRV_ATOM, driver_mk_atom("key2"), - ERL_DRV_INT, 200, - ERL_DRV_INT, 300, - ERL_DRV_TUPLE, 2, - ERL_DRV_MAP, 2 - }; - erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); - ]]> - </code> - - <p>If you want to pass a binary and don't already have the content - of the binary in an <c>ErlDrvBinary</c>, you can benefit from using - <c>ERL_DRV_BUF2BINARY</c> instead of creating an <c>ErlDrvBinary</c> - via <c>driver_alloc_binary()</c> and then pass the binary via - <c>ERL_DRV_BINARY</c>. The runtime system will often allocate - binaries smarter if <c>ERL_DRV_BUF2BINARY</c> is used. - However, if the content of the binary to pass already resides in - an <c>ErlDrvBinary</c>, it is normally better to pass the binary - using <c>ERL_DRV_BINARY</c> and the <c>ErlDrvBinary</c> in question. - </p> - <p>The <c>ERL_DRV_UINT</c>, <c>ERL_DRV_BUF2BINARY</c>, and - <c>ERL_DRV_EXT2TERM</c> term types were introduced in the 5.6 - version of erts. - </p> - <p>This function is only thread-safe when the emulator with SMP - support is used.</p> + <marker id="driver_sizeq"></marker> + <p>Returns the number of bytes currently in the driver queue.</p> + <p>This function can be called from any thread if a + <seealso marker="#ErlDrvPDL">port data lock</seealso> + associated with the <c>port</c> is locked by the calling + thread during the call.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_output_term(ErlDrvPort port, ErlDrvTermData* term, int n)</nametext></name> - <fsummary>Send term data from driver to port owner</fsummary> + <name><ret>void</ret><nametext>driver_system_info(ErlDrvSysInfo + *sys_info_ptr, size_t size)</nametext></name> + <fsummary>Get information about the Erlang runtime system.</fsummary> <desc> - <marker id="driver_output_term"></marker> - <warning><p><c>driver_output_term()</c> is deprecated and will - be removed in the OTP-R17 release. Use - <seealso marker="#erl_drv_send_term">erl_drv_output_term()</seealso> - instead.</p> - </warning> - <p>The parameters <c>term</c> and <c>n</c> do the same thing - as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p> - <p>Note that this function is <em>not</em> thread-safe, not - even when the emulator with SMP support is used.</p> + <marker id="driver_system_info"></marker> + <p>Writes information about the Erlang runtime system into the + <seealso marker="#ErlDrvSysInfo"><c>ErlDrvSysInfo</c></seealso> + structure referred to by the first argument. The second + argument is to be the size of the + <seealso marker="#ErlDrvSysInfo"><c>ErlDrvSysInfo</c></seealso> + structure, that is, <c>sizeof(ErlDrvSysInfo)</c>.</p> + <p>For information about specific fields, see + <seealso marker="#ErlDrvSysInfo"><c>ErlDrvSysInfo</c></seealso>.</p> </desc> </func> + <func> - <name><ret>ErlDrvTermData</ret><nametext>driver_mk_atom(char* string)</nametext></name> - <fsummary>Make an atom from a name</fsummary> + <name><ret>ErlDrvSizeT</ret><nametext>driver_vec_to_buf(ErlIOVec *ev, + char *buf, ErlDrvSizeT len)</nametext></name> + <fsummary>Collect data segments into a buffer.</fsummary> <desc> - <marker id="driver_mk_atom"></marker> - <p>This function returns an atom given a name - <c>string</c>. The atom is created and won't change, so the - return value may be saved and reused, which is faster than - looking up the atom several times.</p> - <p>Note that this function is <em>not</em> thread-safe, not - even when the emulator with SMP support is used.</p> + <marker id="driver_vec_to_buf"></marker> + <p>Collects several segments of data, referenced + by <c>ev</c>, by copying them in order to the buffer + <c>buf</c>, of the size <c>len</c>.</p> + <p>If the data is to be sent from the driver to the port owner + process, it is faster to use + <seealso marker="#driver_outputv"><c>driver_outputv</c></seealso>.</p> + <p>The return value is the space left in the buffer, that is, if + <c>ev</c> contains less than <c>len</c> bytes it is the + difference, and if <c>ev</c> contains <c>len</c> bytes or more, + it is <c>0</c>. This is faster if there is more than one header byte, + as the binary syntax can construct integers directly from + the binary.</p> </desc> </func> + <func> - <name><ret>ErlDrvTermData</ret><nametext>driver_mk_port(ErlDrvPort port)</nametext></name> - <fsummary>Make a erlang term port from a port</fsummary> + <name><ret>void</ret><nametext>erl_drv_busy_msgq_limits(ErlDrvPort port, + ErlDrvSizeT *low, ErlDrvSizeT *high)</nametext></name> + <fsummary>Set and get limits for busy port message queue.</fsummary> <desc> - <marker id="driver_mk_port"></marker> - <p>This function converts a port handle to the erlang term - format, usable in the <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>, and <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso> functions.</p> - <p>Note that this function is <em>not</em> thread-safe, not - even when the emulator with SMP support is used.</p> + <marker id="erl_drv_busy_msgq_limits"></marker> + <p>Sets and gets limits that will be used for controlling the + busy state of the port message queue.</p> + <p>The port message queue is set into a busy + state when the amount of command data queued on the + message queue reaches the <c>high</c> limit. The port + message queue is set into a not busy state when the + amount of command data queued on the message queue falls + below the <c>low</c> limit. Command data is in this + context data passed to the port using either + <c>Port ! {Owner, {command, Data}}</c> or + <c>port_command/[2,3]</c>. Notice that these limits + only concerns command data that have not yet reached the + port. The <seealso marker="#set_busy_port">busy port</seealso> + feature can be used for data that has reached the port.</p> + <p>Valid limits are values in the range + <c>[ERL_DRV_BUSY_MSGQ_LIM_MIN, ERL_DRV_BUSY_MSGQ_LIM_MAX]</c>. + Limits are automatically adjusted to be sane. That is, + the system adjusts values so that the low limit used is + lower than or equal to the high limit used. By default the high + limit is 8 kB and the low limit is 4 kB.</p> + <p>By passing a pointer to an integer variable containing + the value <c>ERL_DRV_BUSY_MSGQ_READ_ONLY</c>, the currently used + limit is read and written back to the integer variable. + A new limit can be set by passing a pointer to an integer + variable containing a valid limit. The passed value is + written to the internal limit. The internal limit is then + adjusted. After this the adjusted limit is written + back to the integer variable from which the new value was + read. Values are in bytes.</p> + <p>The busy message queue feature can be disabled either + by setting the <c>ERL_DRV_FLAG_NO_BUSY_MSGQ</c> + <seealso marker="driver_entry#driver_flags">driver flag</seealso> + in the <seealso marker="driver_entry"><c>driver_entry</c></seealso> + used by the driver, or by calling this function with + <c>ERL_DRV_BUSY_MSGQ_DISABLED</c> as a limit (either low or + high). When this feature has been disabled, it cannot be + enabled again. When reading the limits, both are + <c>ERL_DRV_BUSY_MSGQ_DISABLED</c> if this + feature has been disabled.</p> + <p>Processes sending command data to the port are suspended + if either the port is busy or if the port message queue is + busy. Suspended processes are resumed when neither the + port or the port message queue is busy.</p> + <p>For information about busy port functionality, see + <seealso marker="#set_busy_port"><c>set_busy_port</c></seealso>.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>erl_drv_send_term(ErlDrvTermData port, ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name> - <fsummary>Send term data to other process than port owner process</fsummary> + <name><ret>void</ret><nametext>erl_drv_cond_broadcast(ErlDrvCond + *cnd)</nametext></name> + <fsummary>Broadcast on a condition variable.</fsummary> <desc> - <marker id="erl_drv_send_term"></marker> - <p>This function is the only way for a driver to send data to - <em>other</em> processes than the port owner process. The - <c>receiver</c> parameter specifies the process to receive - the data.</p> - <note><p>Note that the <c>port</c> parameter is <em>not</em> - an ordinary port handle, but a port handle converted using - <c>driver_mk_port()</c>.</p></note> - <p>The parameters <c>port</c>, <c>term</c> and <c>n</c> do the same thing - as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p> - <p>This function is only thread-safe when the emulator with SMP - support is used.</p> + <marker id="erl_drv_cond_broadcast"></marker> + <p>Broadcasts on a condition variable. That is, if + other threads are waiting on the condition variable being + broadcast on, <em>all</em> of them are woken.</p> + <p><c>cnd</c> is a pointer to a condition variable to broadcast on.</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_send_term(ErlDrvPort port, ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name> - <fsummary>Send term data to other process than port owner process</fsummary> + <name><ret>ErlDrvCond *</ret><nametext>erl_drv_cond_create(char + *name)</nametext></name> + <fsummary>Create a condition variable.</fsummary> <desc> - <marker id="driver_send_term"></marker> - <warning><p><c>driver_send_term()</c> is deprecated and will - be removed in the OTP-R17 release. Use - <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso> - instead.</p> - <p>Also note that parameters of <c>driver_send_term()</c> - cannot be properly checked by the runtime system when - executed by arbitrary threads. This may cause the - <c>driver_send_term()</c> function not to fail when - it should.</p> - </warning> - <p>The parameters <c>term</c> and <c>n</c> do the same thing - as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p> - <p>This function is only thread-safe when the emulator with SMP - support is used.</p> + <marker id="erl_drv_cond_create"></marker> + <p>Creates a condition variable and returns a pointer to it.</p> + <p><c>name</c> is a string identifying the created condition variable. + It is used to identify the condition variable in planned + future debug functionality.</p> + <p>Returns <c>NULL</c> on failure. The driver + creating the condition variable is responsible for + destroying it before the driver is unloaded.</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>long</ret><nametext>driver_async (ErlDrvPort port, unsigned int* key, void (*async_invoke)(void*), void* async_data, void (*async_free)(void*))</nametext></name> - <fsummary>Perform an asynchronous call within a driver</fsummary> + <name><ret>void</ret><nametext>erl_drv_cond_destroy(ErlDrvCond + *cnd)</nametext></name> + <fsummary>Destroy a condition variable.</fsummary> <desc> - <marker id="driver_async"></marker> - <p>This function performs an asynchronous call. The function - <c>async_invoke</c> is invoked in a thread separate from the - emulator thread. This enables the driver to perform - time-consuming, blocking operations without blocking the - emulator.</p> - <p>The async thread pool size can be set with the - <seealso marker="erl#async_thread_pool_size">+A</seealso> - command line argument of <seealso marker="erl">erl(1)</seealso>. - If no async thread pool is available, the call is made - synchronously in the thread calling <c>driver_async()</c>. The - current number of async threads in the async thread pool can be - retrieved via - <seealso marker="#driver_system_info">driver_system_info()</seealso>.</p> - <p>If there is a thread pool available, a thread will be - used. If the <c>key</c> argument is null, the threads from the - pool are used in a round-robin way, each call to - <c>driver_async</c> uses the next thread in the pool. With the - <c>key</c> argument set, this behaviour is changed. The two - same values of <c>*key</c> always get the same thread.</p> - <p>To make sure that a driver instance always uses the same - thread, the following call can be used:</p> - <p></p> - <code type="none"><![CDATA[ - unsigned int myKey = driver_async_port_key(myPort); + <marker id="erl_drv_cond_destroy"></marker> + <p>Destroys a condition variable previously created by + <seealso marker="#erl_drv_cond_create"> + <c>erl_drv_cond_create</c></seealso>.</p> + <p><c>cnd</c> is a pointer to a condition variable to destroy.</p> + <p>This function is thread-safe.</p> + </desc> + </func> - r = driver_async(myPort, &myKey, myData, myFunc); - ]]></code> - <p>It is enough to initialize <c>myKey</c> once for each - driver instance.</p> - <p>If a thread is already working, the calls will be - queued up and executed in order. Using the same thread for - each driver instance ensures that the calls will be made in - sequence.</p> - <p>The <c>async_data</c> is the argument to the functions - <c>async_invoke</c> and <c>async_free</c>. It's typically a - pointer to a structure that contains a pipe or event that - can be used to signal that the async operation completed. - The data should be freed in <c>async_free</c>.</p> - <p>When the async operation is done, <seealso marker="driver_entry#ready_async">ready_async</seealso> driver - entry function is called. If <c>ready_async</c> is null in - the driver entry, the <c>async_free</c> function is called - instead.</p> - <p>The return value is -1 if the <c>driver_async</c> call - fails.</p> + <func> + <name><ret>char *</ret><nametext>erl_drv_cond_name(ErlDrvCond + *cnd)</nametext></name> + <fsummary>Get name of driver mutex.</fsummary> + <desc> + <marker id="erl_drv_cnd_name"></marker> + <p>Returns a pointer to the name of the condition.</p> + <p><c>cnd</c> is a pointer to an initialized condition.</p> <note> - <p>As of erts version 5.5.4.3 the default stack size for - threads in the async-thread pool is 16 kilowords, - i.e., 64 kilobyte on 32-bit architectures. - This small default size has been chosen since the - amount of async-threads might be quite large. The - default stack size is enough for drivers delivered - with Erlang/OTP, but might not be sufficiently large - for other dynamically linked in drivers that use the - driver_async() functionality. A suggested stack size - for threads in the async-thread pool can be configured - via the - <seealso marker="erl#async_thread_stack_size">+a</seealso> - command line argument of - <seealso marker="erl">erl(1)</seealso>.</p> + <p>This function is intended for debugging purposes only.</p> </note> </desc> </func> + <func> - <name><ret>unsigned int</ret><nametext>driver_async_port_key (ErlDrvPort port)</nametext></name> - <fsummary>Calculate an async key from an ErlDrvPort</fsummary> + <name><ret>void</ret><nametext>erl_drv_cond_signal(ErlDrvCond + *cnd)</nametext></name> + <fsummary>Signal on a condition variable.</fsummary> <desc> - <marker id="driver_async_port_key"></marker> - <p>This function calculates a key for later use in <seealso - marker="#driver_async">driver_async()</seealso>. The keys are - evenly distributed so that a fair mapping between port id's - and async thread id's is achieved.</p> - <note> - <p>Before OTP-R16, the actual port id could be used as a key - with proper casting, but after the rewrite of the port - subsystem, this is no longer the case. With this function, you - can achieve the same distribution based on port id's as before - OTP-R16.</p> - </note> + <marker id="erl_drv_cond_signal"></marker> + <p>Signals on a condition variable. That is, if + other threads are waiting on the condition variable being + signaled, <em>one</em> of them is woken.</p> + <p><c>cnd</c> is a pointer to a condition variable to signal on.</p> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>driver_lock_driver(ErlDrvPort port)</nametext></name> - <fsummary>Make sure the driver is never unloaded</fsummary> + <name><ret>void</ret><nametext>erl_drv_cond_wait(ErlDrvCond *cnd, + ErlDrvMutex *mtx)</nametext></name> + <fsummary>Wait on a condition variable.</fsummary> <desc> - <marker id="driver_lock_driver"></marker> - <p>This function locks the driver used by the port <c>port</c> - in memory for the rest of the emulator process' - lifetime. After this call, the driver behaves as one of Erlang's - statically linked in drivers.</p> + <marker id="erl_drv_cond_wait"></marker> + <p>Waits on a condition variable. The calling + thread is blocked until another thread wakes it by signaling + or broadcasting on the condition variable. Before the calling + thread is blocked, it unlocks the mutex passed as argument. + When the calling thread is woken, it locks the same mutex before + returning. That is, the mutex currently must be locked by + the calling thread when calling this function.</p> + <p><c>cnd</c> is a pointer to a condition variable to wait on. + <c>mtx</c> is a pointer to a mutex to unlock while waiting.</p> + <note> + <p><c>erl_drv_cond_wait</c> can return even if + no one has signaled or broadcast on the condition + variable. Code calling <c>erl_drv_cond_wait</c> is + always to be prepared for <c>erl_drv_cond_wait</c> + returning even if the condition that the thread was + waiting for has not occurred. That is, when returning from + <c>erl_drv_cond_wait</c>, always check if the condition + has occurred, and if not call <c>erl_drv_cond_wait</c> again.</p> + </note> + <p>This function is thread-safe.</p> </desc> </func> + <func> - <name><ret>ErlDrvPort</ret><nametext>driver_create_port(ErlDrvPort port, ErlDrvTermData owner_pid, char* name, ErlDrvData drv_data)</nametext></name> - <fsummary>Create a new port (driver instance)</fsummary> + <name><ret>int</ret><nametext>erl_drv_consume_timeslice(ErlDrvPort port, + int percent)</nametext></name> + <fsummary>Give the runtime system a hint about how much CPU time the + current driver callback call has consumed.</fsummary> <desc> - <p>This function creates a new port executing the same driver - code as the port creating the new port. - A short description of the arguments:</p> + <marker id="erl_drv_consume_timeslice"></marker> + <p>Gives the runtime system a hint about how much CPU time the current + driver callback call has consumed since the last hint, or since the + the start of the callback if no previous hint has been given.</p> <taglist> <tag><c>port</c></tag> - <item>The port handle of the port (driver instance) creating - the new port.</item> - <tag><c>owner_pid</c></tag> - <item>The process id of the Erlang process which will be - owner of the new port. This process will be linked - to the new port. You usually want to use - <c>driver_caller(port)</c> as <c>owner_pid</c>.</item> - <tag><c>name</c></tag> - <item>The port name of the new port. You usually want to - use the same port name as the driver name - (<seealso marker="driver_entry#driver_name">driver_name</seealso> - field of the - <seealso marker="driver_entry">driver_entry</seealso>).</item> - <tag><c>drv_data</c></tag> - <item>The driver defined handle that will be passed in subsequent - calls to driver call-backs. Note, that the - <seealso marker="driver_entry#start">driver start call-back</seealso> - will not be called for this new driver instance. - The driver defined handle is normally created in the - <seealso marker="driver_entry#start">driver start call-back</seealso> - when a port is created via - <seealso marker="erlang#open_port/2">erlang:open_port/2</seealso>. </item> + <item>Port handle of the executing port.</item> + <tag><c>percent</c></tag> + <item>Approximate consumed fraction of a full + time-slice in percent.</item> </taglist> - <p>The caller of <c>driver_create_port()</c> is allowed to - manipulate the newly created port when <c>driver_create_port()</c> - has returned. When - <seealso marker="#smp_support">port level locking</seealso> - is used, the creating port is, however, only allowed to - manipulate the newly created port until the current driver - call-back that was called by the emulator returns.</p> - <note> - <p>When - <seealso marker="#smp_support">port level locking</seealso> - is used, the creating port is only allowed to manipulate - the newly created port until the current driver call-back - returns.</p> - </note> + <p>The time is specified as a fraction, in percent, of a full time-slice + that a port is allowed to execute before it is to surrender the + CPU to other runnable ports or processes. Valid range is + <c>[1, 100]</c>. The scheduling time-slice is not an exact entity, + but can usually be approximated to about 1 millisecond.</p> + <p>Notice that it is up to the runtime system to determine if and + how to use this information. Implementations on some platforms + can use other means to determine the consumed fraction + of the time-slice. Lengthy driver callbacks should, regardless of + this, frequently call this function to determine if it is allowed + to continue execution or not.</p> + <p>This function returns a non-zero value + if the time-slice has been exhausted, and zero if the callback is + allowed to continue execution. If a non-zero value is + returned, the driver callback is to return as soon as possible in + order for the port to be able to yield.</p> + <p>This function is provided to better support co-operative scheduling, + improve system responsiveness, and to make it easier to prevent + misbehaviors of the VM because of a port monopolizing a scheduler + thread. It can be used when dividing lengthy work into some repeated + driver callback calls, without the need to use threads.</p> + <p>See also the important <seealso marker="#WARNING">warning</seealso> + text at the beginning of this manual page.</p> </desc> </func> <func> - <name><ret>int</ret><nametext>erl_drv_thread_create(char *name, - ErlDrvTid *tid, - void * (*func)(void *), - void *arg, - ErlDrvThreadOpts *opts)</nametext></name> - <fsummary>Create a thread</fsummary> + <name><ret>ErlDrvTime</ret><nametext>erl_drv_convert_time_unit(ErlDrvTime + val, ErlDrvTimeUnit from, ErlDrvTimeUnit to)</nametext></name> + <fsummary>Convert time unit of a time value.</fsummary> <desc> - <marker id="erl_drv_thread_create"></marker> - <p>Arguments:</p> + <marker id="erl_drv_convert_time_unit"></marker> + <p>Converts the <c>val</c> value of time unit <c>from</c> to + the corresponding value of time unit <c>to</c>. The result is + rounded using the floor function.</p> <taglist> - <tag><c>name</c></tag> - <item>A string identifying the created thread. It will be used - to identify the thread in planned future debug - functionality. - </item> - <tag><c>tid</c></tag> - <item>A pointer to a thread identifier variable.</item> - <tag><c>func</c></tag> - <item>A pointer to a function to execute in the created thread.</item> - <tag><c>arg</c></tag> - <item>A pointer to argument to the <c>func</c> function.</item> - <tag><c>opts</c></tag> - <item>A pointer to thread options to use or <c>NULL</c>.</item> + <tag><c>val</c></tag> + <item>Value to convert time unit for.</item> + <tag><c>from</c></tag> + <item>Time unit of <c>val</c>.</item> + <tag><c>to</c></tag> + <item>Time unit of returned value.</item> </taglist> - <p>This function creates a new thread. On success <c>0</c> is returned; - otherwise, an <c>errno</c> value is returned to indicate the error. - The newly created thread will begin executing in the function pointed - to by <c>func</c>, and <c>func</c> will be passed <c>arg</c> as - argument. When <c>erl_drv_thread_create()</c> returns the thread - identifier of the newly created thread will be available in - <c>*tid</c>. <c>opts</c> can be either a <c>NULL</c> pointer, or a - pointer to an - <seealso marker="#ErlDrvThreadOpts">ErlDrvThreadOpts</seealso> - structure. If <c>opts</c> is a <c>NULL</c> pointer, default options - will be used; otherwise, the passed options will be used. - </p> - <warning><p>You are not allowed to allocate the - <seealso marker="#ErlDrvThreadOpts">ErlDrvThreadOpts</seealso> - structure by yourself. It has to be allocated and - initialized by - <seealso marker="#erl_drv_thread_opts_create">erl_drv_thread_opts_create()</seealso>. - </p></warning> - <p>The created thread will terminate either when <c>func</c> returns - or if - <seealso marker="#erl_drv_thread_exit">erl_drv_thread_exit()</seealso> - is called by the thread. The exit value of the thread is either - returned from <c>func</c> or passed as argument to - <seealso marker="#erl_drv_thread_exit">erl_drv_thread_exit()</seealso>. - The driver creating the thread has the responsibility of joining the - thread, via - <seealso marker="#erl_drv_thread_join">erl_drv_thread_join()</seealso>, - before the driver is unloaded. It is not possible to create - "detached" threads, i.e., threads that don't need to be joined. - </p> - <warning><p>All created threads need to be joined by the driver before - it is unloaded. If the driver fails to join all threads - created before it is unloaded, the runtime system will - most likely crash when the code of the driver is unloaded. - </p></warning> - <p>This function is thread-safe.</p> + <p>Returns <c>ERL_DRV_TIME_ERROR</c> if called with an invalid + time unit argument.</p> + <p>See also <seealso marker="#ErlDrvTime"> + <c>ErlDrvTime</c></seealso> and + <seealso marker="#ErlDrvTimeUnit"> + <c>ErlDrvTimeUnit</c></seealso>.</p> </desc> </func> <func> - <name><ret>ErlDrvThreadOpts *</ret><nametext>erl_drv_thread_opts_create(char *name)</nametext></name> - <fsummary>Create thread options</fsummary> + <name><ret>int</ret><nametext>erl_drv_equal_tids(ErlDrvTid tid1, + ErlDrvTid tid2)</nametext></name> + <fsummary>Compare thread identifiers for equality.</fsummary> <desc> - <marker id="erl_drv_thread_opts_create"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>name</c></tag> - <item>A string identifying the created thread options. It will be used - to identify the thread options in planned future debug - functionality. - </item> - </taglist> - <p>This function allocates and initialize a thread option - structure. On failure <c>NULL</c> is returned. A thread option - structure is used for passing options to - <seealso marker="#erl_drv_thread_create">erl_drv_thread_create()</seealso>. - If the structure isn't modified before it is passed to - <seealso marker="#erl_drv_thread_create">erl_drv_thread_create()</seealso>, - the default values will be used. - </p> - <warning><p>You are not allowed to allocate the - <seealso marker="#ErlDrvThreadOpts">ErlDrvThreadOpts</seealso> - structure by yourself. It has to be allocated and - initialized by <c>erl_drv_thread_opts_create()</c>. - </p></warning> + <marker id="erl_drv_equal_tids"></marker> + <p>Compares two thread identifiers, <c>tid1</c> and <c>tid2</c>, + for equality.</p> + <p>Returns <c>0</c> it they are not equal, and a value not equal to + <c>0</c> if they are equal.</p> + <note> + <p>A thread identifier can be reused very quickly after + a thread has terminated. Therefore, if a thread + corresponding to one of the involved thread identifiers + has terminated since the thread identifier was saved, + the result of <c>erl_drv_equal_tids</c> does possibly not give + the expected result.</p> + </note> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts)</nametext></name> - <fsummary>Destroy thread options</fsummary> + <name><ret>int</ret><nametext>erl_drv_getenv(const char *key, char + *value, size_t *value_size)</nametext></name> + <fsummary>Get the value of an environment variable.</fsummary> <desc> - <marker id="erl_drv_thread_opts_destroy"></marker> - <p>Arguments:</p> + <marker id="erl_drv_getenv"></marker> + <p>Retrieves the value of an environment variable.</p> <taglist> - <tag><c>opts</c></tag> - <item>A pointer to thread options to destroy.</item> + <tag><c>key</c></tag> + <item>A <c>NULL</c>-terminated string containing the + name of the environment variable.</item> + <tag><c>value</c></tag> + <item>A pointer to an output buffer.</item> + <tag><c>value_size</c></tag> + <item>A pointer to an integer. The integer is used both for + passing input and output sizes (see below).</item> </taglist> - <p>This function destroys thread options previously created by - <seealso marker="#erl_drv_thread_opts_create">erl_drv_thread_opts_create()</seealso>. - </p> + <p>When this function is called, <c>*value_size</c> is to contain the + size of the <c>value</c> buffer.</p> + <p>On success, <c>0</c> is returned, + the value of the environment variable has been written to + the <c>value</c> buffer, and <c>*value_size</c> contains the + string length (excluding the terminating <c>NULL</c> character) of + the value written to the <c>value</c> buffer.</p> + <p>On failure, that is, no such environment variable was found, + a value < <c>0</c> is returned. When the size of the <c>value</c> + buffer is too small, a value > <c>0</c> is returned and + <c>*value_size</c> has been set to the buffer size needed.</p> + <warning> + <p>This function reads the emulated environment used by + <seealso marker="os:getenv/1"><c>os:getenv/1</c></seealso> and not + the environment used by libc's <c>getenv(3)</c> or similar. Drivers + that <em>require</em> that these are in sync will need to do so + themselves, but keep in mind that they are segregated for a reason; + <c>getenv(3)</c> and its friends are <em>not thread-safe</em> and + may cause unrelated code to misbehave or crash the emulator.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_thread_exit(void *exit_value)</nametext></name> - <fsummary>Terminate calling thread</fsummary> + <name><ret>void</ret><nametext>erl_drv_init_ack(ErlDrvPort port, + ErlDrvData res)</nametext></name> + <fsummary>Acknowledge the start of the port.</fsummary> <desc> - <marker id="erl_drv_thread_exit"></marker> - <p>Arguments:</p> + <marker id="erl_drv_init_ack"></marker> + <p>Acknowledges the start of the port.</p> <taglist> - <tag><c>exit_value</c></tag> - <item>A pointer to an exit value or <c>NULL</c>.</item> + <tag><c>port</c></tag> + <item>The port handle of the port (driver instance) + doing the acknowledgment. + </item> + <tag><c>res</c></tag> + <item>The result of the port initialization. Can be the same + values as the return value of <seealso marker="driver_entry#start"> + <c>start</c></seealso>, that is, any of the error codes or the + <c>ErlDrvData</c> that is to be used for this port. + </item> </taglist> - <p>This function terminates the calling thread with the exit - value passed as argument. You are only allowed to terminate - threads created with - <seealso marker="#erl_drv_thread_create">erl_drv_thread_create()</seealso>. - The exit value can later be retrieved by another thread via - <seealso marker="#erl_drv_thread_join">erl_drv_thread_join()</seealso>. - </p> + <p>When this function is called the initiating <c>erlang:open_port</c> + call is returned as if the <seealso marker="driver_entry#start"> + <c>start</c></seealso> function had just been called. It can only be + used when flag <seealso marker="driver_entry#driver_flags"> + <c>ERL_DRV_FLAG_USE_INIT_ACK</c></seealso> + has been set on the linked-in driver.</p> + </desc> + </func> + + <func> + <name><ret>ErlDrvTime</ret> + <nametext>erl_drv_monotonic_time(ErlDrvTimeUnit time_unit)</nametext> + </name> + <fsummary>Get Erlang monotonic time.</fsummary> + <desc> + <marker id="erl_drv_monotonic_time"></marker> + <p>Returns <seealso marker="time_correction#Erlang_Monotonic_Time"> + Erlang monotonic time</seealso>. Notice that negative values are + not uncommon.</p> + <p><c>time_unit</c> is time unit of returned value.</p> + <p>Returns <c>ERL_DRV_TIME_ERROR</c> if called with an invalid + time unit argument, or if called from a thread that is not a + scheduler thread.</p> + <p>See also <seealso marker="#ErlDrvTime"><c>ErlDrvTime</c></seealso> + and <seealso marker="#ErlDrvTimeUnit"> + <c>ErlDrvTimeUnit</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ErlDrvMutex *</ret><nametext>erl_drv_mutex_create(char + *name)</nametext></name> + <fsummary>Create a mutex.</fsummary> + <desc> + <marker id="erl_drv_mutex_create"></marker> + <p>Creates a mutex and returns a pointer to it.</p> + <p><c>name</c> is a string identifying the created mutex. It is used + to identify the mutex in planned future debug functionality.</p> + <p>Returns <c>NULL</c> on failure. The driver creating the mutex is + responsible for destroying it before the driver is unloaded.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>int</ret><nametext>erl_drv_thread_join(ErlDrvTid tid, void **exit_value)</nametext></name> - <fsummary>Join with another thread</fsummary> + <name><ret>void</ret><nametext>erl_drv_mutex_destroy(ErlDrvMutex + *mtx)</nametext></name> + <fsummary>Destroy a mutex.</fsummary> <desc> - <marker id="erl_drv_thread_join"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>tid</c></tag> - <item>The thread identifier of the thread to join.</item> - <tag><c>exit_value</c></tag> - <item>A pointer to a pointer to an exit value, or <c>NULL</c>.</item> - </taglist> - <p>This function joins the calling thread with another thread, i.e., - the calling thread is blocked until the thread identified by - <c>tid</c> has terminated. On success <c>0</c> is returned; - otherwise, an <c>errno</c> value is returned to indicate the error. - A thread can only be joined once. The behavior of joining - more than once is undefined, an emulator crash is likely. If - <c>exit_value == NULL</c>, the exit value of the terminated thread - will be ignored; otherwise, the exit value of the terminated thread - will be stored at <c>*exit_value</c>. - </p> + <marker id="erl_drv_mutex_destroy"></marker> + <p>Destroys a mutex previously created by + <seealso marker="#erl_drv_mutex_create"> + <c>erl_drv_mutex_create</c></seealso>. + The mutex must be in an unlocked state before it is destroyed.</p> + <p><c>mtx</c> is a pointer to a mutex to destroy.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>ErlDrvTid</ret><nametext>erl_drv_thread_self(void)</nametext></name> - <fsummary>Get the thread identifier of the current thread</fsummary> + <name><ret>void</ret><nametext>erl_drv_mutex_lock(ErlDrvMutex + *mtx)</nametext></name> + <fsummary>Lock a mutex.</fsummary> <desc> - <marker id="erl_drv_thread_self"></marker> - <p>This function returns the thread identifier of the - calling thread. - </p> + <marker id="erl_drv_mutex_lock"></marker> + <p>Locks a mutex. The calling thread is blocked until the mutex has + been locked. A thread that has currently locked the mutex + <em>cannot</em> lock the same mutex again.</p> + <p><c>mtx</c> is a pointer to a mutex to lock.</p> + <warning> + <p>If you leave a mutex locked in an emulator thread + when you let the thread out of your control, you will + <em>very likely</em> deadlock the whole emulator.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>int</ret><nametext>erl_drv_equal_tids(ErlDrvTid tid1, ErlDrvTid tid2)</nametext></name> - <fsummary>Compare thread identifiers for equality</fsummary> + <name><ret>char *</ret><nametext>erl_drv_mutex_name(ErlDrvMutex + *mtx)</nametext></name> + <fsummary>Get name of driver mutex.</fsummary> <desc> - <marker id="erl_drv_equal_tids"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>tid1</c></tag> - <item>A thread identifier.</item> - <tag><c>tid2</c></tag> - <item>A thread identifier.</item> - </taglist> - <p>This function compares two thread identifiers for equality, - and returns <c>0</c> it they aren't equal, and - a value not equal to <c>0</c> if they are equal.</p> - <note><p>A Thread identifier may be reused very quickly after - a thread has terminated. Therefore, if a thread - corresponding to one of the involved thread identifiers - has terminated since the thread identifier was saved, - the result of <c>erl_drv_equal_tids()</c> might not give - the expected result. - </p></note> + <marker id="erl_drv_mutex_name"></marker> + <p>Returns a pointer to the mutex name.</p> + <p><c>mtx</c> is a pointer to an initialized mutex.</p> + <note> + <p>This function is intended for debugging purposes only.</p> + </note> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>erl_drv_mutex_trylock(ErlDrvMutex + *mtx)</nametext></name> + <fsummary>Try lock a mutex.</fsummary> + <desc> + <marker id="erl_drv_mutex_trylock"></marker> + <p>Tries to lock a mutex. A thread that has currently locked the mutex + <em>cannot</em> try to lock the same mutex again.</p> + <p><c>mtx</c> is a pointer to a mutex to try to lock.</p> + <p>Returns <c>0</c> on success, otherwise <c>EBUSY</c>.</p> + <warning> + <p>If you leave a mutex locked in an emulator thread + when you let the thread out of your control, you will + <em>very likely</em> deadlock the whole emulator.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>ErlDrvMutex *</ret><nametext>erl_drv_mutex_create(char *name)</nametext></name> - <fsummary>Create a mutex</fsummary> + <name><ret>void</ret><nametext>erl_drv_mutex_unlock(ErlDrvMutex + *mtx)</nametext></name> + <fsummary>Unlock a mutex.</fsummary> <desc> - <marker id="erl_drv_mutex_create"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>name</c></tag> - <item>A string identifying the created mutex. It will be used - to identify the mutex in planned future debug functionality. - </item> - </taglist> - <p>This function creates a mutex and returns a pointer to it. On - failure <c>NULL</c> is returned. The driver creating the mutex - has the responsibility of destroying it before the driver is - unloaded. - </p> + <marker id="erl_drv_mutex_unlock"></marker> + <p>Unlocks a mutex. The mutex currently must be + locked by the calling thread.</p> + <p><c>mtx</c> is a pointer to a mutex to unlock.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_mutex_destroy(ErlDrvMutex *mtx)</nametext></name> - <fsummary>Destroy a mutex</fsummary> + <name><ret>int</ret><nametext>erl_drv_output_term(ErlDrvTermData port, + ErlDrvTermData* term, int n)</nametext></name> + <fsummary>Send term data from driver to port owner.</fsummary> <desc> - <marker id="erl_drv_mutex_destroy"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>mtx</c></tag> - <item>A pointer to a mutex to destroy.</item> - </taglist> - <p>This function destroys a mutex previously created by - <seealso marker="#erl_drv_mutex_create">erl_drv_mutex_create()</seealso>. - The mutex has to be in an unlocked state before being - destroyed. - </p> + <marker id="erl_drv_output_term"></marker> + <p>Sends data in the special driver term + format to the port owner process. This is a fast way to + deliver term data from a driver. It needs no binary + conversion, so the port owner process receives data as + normal Erlang terms. The <seealso marker="#erl_drv_send_term"> + <c>erl_drv_send_term</c></seealso> + functions can be used for sending to any process + on the local node.</p> + <note> + <p>Parameter <c>port</c> is <em>not</em> + an ordinary port handle, but a port handle converted using + <seealso marker="#driver_mk_port"> + <c>driver_mk_port</c></seealso>.</p> + </note> + <p>Parameter <c>term</c> points to an array of + <c>ErlDrvTermData</c> with <c>n</c> elements. This array + contains terms described in the driver term format. Every + term consists of 1-4 elements in the array. The + first term has a term type and then arguments. + Parameter <c>port</c> specifies the sending port.</p> + <p>Tuples, maps, and lists (except strings, see below) + are built in reverse polish notation, so that to build a + tuple, the elements are specified first, and then the tuple + term, with a count. Likewise for lists and maps.</p> + <list type="bulleted"> + <item> + <p>A tuple must be specified with the number of elements. (The + elements precede the <c>ERL_DRV_TUPLE</c> term.)</p> + </item> + <item> + <p>A map must be specified with the number of key-value pairs + <c>N</c>. The key-value pairs must precede the <c>ERL_DRV_MAP</c> + in this order: <c>key1,value1,key2,value2,...,keyN,valueN</c>. + Duplicate keys are not allowed.</p> + </item> + <item> + <p>A list must be specified with the number of elements, + including the tail, which is the last term preceding + <c>ERL_DRV_LIST</c>.</p> + </item> + </list> + <p>The special term <c>ERL_DRV_STRING_CONS</c> is used to + "splice" in a string in a list, a string specified this way is + not a list in itself, but the elements are elements of the + surrounding list.</p> + <pre> +Term type Arguments +--------- --------- +ERL_DRV_NIL +ERL_DRV_ATOM ErlDrvTermData atom (from driver_mk_atom(char *string)) +ERL_DRV_INT ErlDrvSInt integer +ERL_DRV_UINT ErlDrvUInt integer +ERL_DRV_INT64 ErlDrvSInt64 *integer_ptr +ERL_DRV_UINT64 ErlDrvUInt64 *integer_ptr +ERL_DRV_PORT ErlDrvTermData port (from driver_mk_port(ErlDrvPort port)) +ERL_DRV_BINARY ErlDrvBinary *bin, ErlDrvUInt len, ErlDrvUInt offset +ERL_DRV_BUF2BINARY char *buf, ErlDrvUInt len +ERL_DRV_STRING char *str, int len +ERL_DRV_TUPLE int sz +ERL_DRV_LIST int sz +ERL_DRV_PID ErlDrvTermData pid (from driver_connected(ErlDrvPort port) + or driver_caller(ErlDrvPort port)) +ERL_DRV_STRING_CONS char *str, int len +ERL_DRV_FLOAT double *dbl +ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len +ERL_DRV_MAP int sz</pre> + <p>The unsigned integer data type <c>ErlDrvUInt</c> and the + signed integer data type <c>ErlDrvSInt</c> are 64 bits wide + on a 64-bit runtime system and 32 bits wide on a 32-bit + runtime system. They were introduced in ERTS 5.6 + and replaced some of the <c>int</c> arguments in the list above.</p> + <p>The unsigned integer data type <c>ErlDrvUInt64</c> and the + signed integer data type <c>ErlDrvSInt64</c> are always 64 bits + wide. They were introduced in ERTS 5.7.4.</p> + <p>To build the tuple <c>{tcp, Port, [100 | Binary]}</c>, the + following call can be made.</p> + <code type="none"><![CDATA[ +ErlDrvBinary* bin = ... +ErlDrvPort port = ... +ErlDrvTermData spec[] = { + ERL_DRV_ATOM, driver_mk_atom("tcp"), + ERL_DRV_PORT, driver_mk_port(drvport), + ERL_DRV_INT, 100, + ERL_DRV_BINARY, bin, 50, 0, + ERL_DRV_LIST, 2, + ERL_DRV_TUPLE, 3, +}; +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]></code> + <p>Here <c>bin</c> is a driver binary of length at least 50 and + <c>drvport</c> is a port handle. Notice that <c>ERL_DRV_LIST</c> + comes after the elements of the list, likewise + <c>ERL_DRV_TUPLE</c>.</p> + <p>The <c>ERL_DRV_STRING_CONS</c> term is a way to construct + strings. It works differently from how <c>ERL_DRV_STRING</c> + works. <c>ERL_DRV_STRING_CONS</c> builds a string list in + reverse order (as opposed to how <c>ERL_DRV_LIST</c> + works), concatenating the strings added to a list. The tail + must be specified before <c>ERL_DRV_STRING_CONS</c>.</p> + <p><c>ERL_DRV_STRING</c> constructs a string, and ends + it. (So it is the same as <c>ERL_DRV_NIL</c> followed by + <c>ERL_DRV_STRING_CONS</c>.)</p> + <code type="none"><![CDATA[ +/* to send [x, "abc", y] to the port: */ +ErlDrvTermData spec[] = { + ERL_DRV_ATOM, driver_mk_atom("x"), + ERL_DRV_STRING, (ErlDrvTermData)"abc", 3, + ERL_DRV_ATOM, driver_mk_atom("y"), + ERL_DRV_NIL, + ERL_DRV_LIST, 4 +}; +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]></code> + <code type="none"><![CDATA[ +/* to send "abc123" to the port: */ +ErlDrvTermData spec[] = { + ERL_DRV_NIL, /* with STRING_CONS, the tail comes first */ + ERL_DRV_STRING_CONS, (ErlDrvTermData)"123", 3, + ERL_DRV_STRING_CONS, (ErlDrvTermData)"abc", 3, +}; +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]></code> + <p>The <c>ERL_DRV_EXT2TERM</c> term type is used for passing a + term encoded with the + <seealso marker="erl_ext_dist">external format</seealso>, + that is, a term that has been encoded by + <seealso marker="erlang#term_to_binary/2"> + <c>erlang:term_to_binary</c></seealso>, + <seealso marker="erl_interface:ei"><c>erl_interface:ei(3)</c></seealso>, + and so on. + For example, if <c>binp</c> is a pointer to an <c>ErlDrvBinary</c> + that contains term <c>{17, 4711}</c> encoded with the + <seealso marker="erl_ext_dist">external format</seealso>, + and you want to wrap it in a two-tuple with the tag <c>my_tag</c>, + that is, <c>{my_tag, {17, 4711}}</c>, you can do as follows:</p> + <code type="none"><![CDATA[ +ErlDrvTermData spec[] = { + ERL_DRV_ATOM, driver_mk_atom("my_tag"), + ERL_DRV_EXT2TERM, (ErlDrvTermData) binp->orig_bytes, binp->orig_size + ERL_DRV_TUPLE, 2, +}; +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]></code> + <p>To build the map <c>#{key1 => 100, key2 => {200, 300}}</c>, the + following call can be made.</p> + <code type="none"><![CDATA[ +ErlDrvPort port = ... +ErlDrvTermData spec[] = { + ERL_DRV_ATOM, driver_mk_atom("key1"), + ERL_DRV_INT, 100, + ERL_DRV_ATOM, driver_mk_atom("key2"), + ERL_DRV_INT, 200, + ERL_DRV_INT, 300, + ERL_DRV_TUPLE, 2, + ERL_DRV_MAP, 2 +}; +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]></code> + <p>If you want to pass a binary and do not already have the content + of the binary in an <c>ErlDrvBinary</c>, you can benefit from using + <c>ERL_DRV_BUF2BINARY</c> instead of creating an <c>ErlDrvBinary</c> + through <seealso marker="#driver_alloc_binary"> + <c>driver_alloc_binary</c></seealso> and then pass the binary through + <c>ERL_DRV_BINARY</c>. The runtime system often allocates + binaries smarter if <c>ERL_DRV_BUF2BINARY</c> is used. + However, if the content of the binary to pass already resides in + an <c>ErlDrvBinary</c>, it is normally better to pass the binary using + <c>ERL_DRV_BINARY</c> and the <c>ErlDrvBinary</c> in question.</p> + <p>The <c>ERL_DRV_UINT</c>, <c>ERL_DRV_BUF2BINARY</c>, and + <c>ERL_DRV_EXT2TERM</c> term types were introduced in + ERTS 5.6.</p> + <p>This function is only thread-safe when the emulator with SMP + support is used.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>erl_drv_putenv(const char *key, char + *value)</nametext></name> + <fsummary>Set the value of an environment variable.</fsummary> + <desc> + <marker id="erl_drv_putenv"></marker> + <p>Sets the value of an environment variable.</p> + <p><c>key</c> is a <c>NULL</c>-terminated string containing the + name of the environment variable.</p> + <p><c>value</c> is a <c>NULL</c>-terminated string containing the + new value of the environment variable.</p> + <p>Returns <c>0</c> on success, otherwise a value <c>!= 0</c>.</p> + <note> + <p>The result of passing the empty string (<c>""</c>) as a value + is platform-dependent. On some platforms the variable value + is set to the empty string, on others the + environment variable is removed.</p> + </note> + <warning> + <p>This function modifies the emulated environment used by + <seealso marker="os:putenv/2"><c>os:putenv/2</c></seealso> and not + the environment used by libc's <c>putenv(3)</c> or similar. Drivers + that <em>require</em> that these are in sync will need to do so + themselves, but keep in mind that they are segregated for a reason; + <c>putenv(3)</c> and its friends are <em>not thread-safe</em> and + may cause unrelated code to misbehave or crash the emulator.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_mutex_lock(ErlDrvMutex *mtx)</nametext></name> - <fsummary>Lock a mutex</fsummary> + <name><ret>ErlDrvRWLock *</ret><nametext>erl_drv_rwlock_create(char + *name)</nametext></name> + <fsummary>Create an rwlock.</fsummary> <desc> - <marker id="erl_drv_mutex_lock"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>mtx</c></tag> - <item>A pointer to a mutex to lock.</item> - </taglist> - <p>This function locks a mutex. The calling thread will be - blocked until the mutex has been locked. A thread - which currently has locked the mutex may <em>not</em> lock - the same mutex again. - </p> - <warning><p>If you leave a mutex locked in an emulator thread - when you let the thread out of your control, you will - <em>very likely</em> deadlock the whole emulator. - </p></warning> + <marker id="erl_drv_rwlock_create"></marker> + <p>Creates an rwlock and returns a pointer to it.</p> + <p><c>name</c> is a string identifying the created rwlock. + It is used to identify the rwlock in planned future + debug functionality.</p> + <p>Returns <c>NULL</c> on failure. The driver creating the rwlock + is responsible for destroying it before the driver is unloaded.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>int</ret><nametext>erl_drv_mutex_trylock(ErlDrvMutex *mtx)</nametext></name> - <fsummary>Try lock a mutex</fsummary> + <name><ret>void</ret><nametext>erl_drv_rwlock_destroy(ErlDrvRWLock + *rwlck)</nametext></name> + <fsummary>Destroy an rwlock.</fsummary> <desc> - <marker id="erl_drv_mutex_trylock"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>mtx</c></tag> - <item>A pointer to a mutex to try to lock.</item> - </taglist> - <p>This function tries to lock a mutex. If successful <c>0</c>, - is returned; otherwise, <c>EBUSY</c> is returned. A thread - which currently has locked the mutex may <em>not</em> try to - lock the same mutex again. - </p> - <warning><p>If you leave a mutex locked in an emulator thread - when you let the thread out of your control, you will - <em>very likely</em> deadlock the whole emulator. - </p></warning> + <marker id="erl_drv_rwlock_destroy"></marker> + <p>Destroys an rwlock previously created by + <seealso marker="#erl_drv_rwlock_create"> + <c>erl_drv_rwlock_create</c></seealso>. + The rwlock must be in an unlocked state before it is destroyed.</p> + <p><c>rwlck</c> is a pointer to an rwlock to destroy.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_mutex_unlock(ErlDrvMutex *mtx)</nametext></name> - <fsummary>Unlock a mutex</fsummary> + <name><ret>char *</ret><nametext>erl_drv_rwlock_name(ErlDrvRWLock + *rwlck)</nametext></name> + <fsummary>Get name of driver mutex.</fsummary> <desc> - <marker id="erl_drv_mutex_unlock"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>mtx</c></tag> - <item>A pointer to a mutex to unlock.</item> - </taglist> - <p>This function unlocks a mutex. The mutex currently has to be - locked by the calling thread. - </p> + <marker id="erl_drv_rwlock_name"></marker> + <p>Returns a pointer to the name of the rwlock.</p> + <p><c>rwlck</c> is a pointer to an initialized rwlock.</p> + <note> + <p>This function is intended for debugging purposes only.</p> + </note> + </desc> + </func> + + <func> + <name><ret>void</ret><nametext>erl_drv_rwlock_rlock(ErlDrvRWLock + *rwlck)</nametext></name> + <fsummary>Read lock an rwlock.</fsummary> + <desc> + <marker id="erl_drv_rwlock_rlock"></marker> + <p>Read locks an rwlock. The calling thread is + blocked until the rwlock has been read locked. A thread + that currently has read or read/write locked the rwlock + <em>cannot</em> lock the same rwlock again.</p> + <p><c>rwlck</c> is a pointer to the rwlock to read lock.</p> + <warning> + <p>If you leave an rwlock locked in an emulator thread + when you let the thread out of your control, you will + <em>very likely</em> deadlock the whole emulator.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>ErlDrvCond *</ret><nametext>erl_drv_cond_create(char *name)</nametext></name> - <fsummary>Create a condition variable</fsummary> + <name><ret>void</ret><nametext>erl_drv_rwlock_runlock(ErlDrvRWLock + *rwlck)</nametext></name> + <fsummary>Read unlock an rwlock.</fsummary> <desc> - <marker id="erl_drv_cond_create"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>name</c></tag> - <item>A string identifying the created condition variable. It - will be used to identify the condition variable in planned - future debug functionality. - </item> - </taglist> - <p>This function creates a condition variable and returns a - pointer to it. On failure <c>NULL</c> is returned. The driver - creating the condition variable has the responsibility of - destroying it before the driver is unloaded.</p> + <marker id="erl_drv_rwlock_runlock"></marker> + <p>Read unlocks an rwlock. The rwlock currently must + be read locked by the calling thread.</p> + <p><c>rwlck</c> is a pointer to an rwlock to read unlock.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_cond_destroy(ErlDrvCond *cnd)</nametext></name> - <fsummary>Destroy a condition variable</fsummary> + <name><ret>void</ret><nametext>erl_drv_rwlock_rwlock(ErlDrvRWLock + *rwlck)</nametext></name> + <fsummary>Read/write lock an rwlock.</fsummary> <desc> - <marker id="erl_drv_cond_destroy"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>cnd</c></tag> - <item>A pointer to a condition variable to destroy.</item> - </taglist> - <p>This function destroys a condition variable previously - created by - <seealso marker="#erl_drv_cond_create">erl_drv_cond_create()</seealso>. - </p> - <p>This function is thread-safe.</p> + <marker id="erl_drv_rwlock_rwlock"></marker> + <p>Read/write locks an rwlock. The calling thread + is blocked until the rwlock has been read/write locked. + A thread that currently has read or read/write locked the + rwlock <em>cannot</em> lock the same rwlock again.</p> + <p><c>rwlck</c> is a pointer to an rwlock to read/write lock.</p> + <warning> + <p>If you leave an rwlock locked in an emulator thread + when you let the thread out of your control, you will + <em>very likely</em> deadlock the whole emulator.</p> + </warning> + <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_cond_signal(ErlDrvCond *cnd)</nametext></name> - <fsummary>Signal on a condition variable</fsummary> + <name><ret>void</ret><nametext>erl_drv_rwlock_rwunlock(ErlDrvRWLock + *rwlck)</nametext></name> + <fsummary>Read/write unlock an rwlock.</fsummary> <desc> - <marker id="erl_drv_cond_signal"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>cnd</c></tag> - <item>A pointer to a condition variable to signal on.</item> - </taglist> - <p>This function signals on a condition variable. That is, if - other threads are waiting on the condition variable being - signaled, <em>one</em> of them will be woken. - </p> + <marker id="erl_drv_rwlock_rwunlock"></marker> + <p>Read/write unlocks an rwlock. The rwlock currently must be + read/write locked by the calling thread.</p> + <p><c>rwlck</c> is a pointer to an rwlock to read/write unlock.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_cond_broadcast(ErlDrvCond *cnd)</nametext></name> - <fsummary>Broadcast on a condition variable</fsummary> + <name><ret>int</ret><nametext>erl_drv_rwlock_tryrlock(ErlDrvRWLock + *rwlck)</nametext></name> + <fsummary>Try to read lock an rwlock.</fsummary> <desc> - <marker id="erl_drv_cond_broadcast"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>cnd</c></tag> - <item>A pointer to a condition variable to broadcast on.</item> - </taglist> - <p>This function broadcasts on a condition variable. That is, if - other threads are waiting on the condition variable being - broadcast on, <em>all</em> of them will be woken. - </p> + <marker id="erl_drv_rwlock_tryrlock"></marker> + <p>Tries to read lock an rwlock.</p> + <p><c>rwlck</c> is a pointer to an rwlock to try to read lock.</p> + <p>Returns <c>0</c> on success, otherwise <c>EBUSY</c>. + A thread that currently has read or read/write locked the + rwlock <em>cannot</em> try to lock the same rwlock again.</p> + <warning> + <p>If you leave an rwlock locked in an emulator thread + when you let the thread out of your control, you will + <em>very likely</em> deadlock the whole emulator.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_cond_wait(ErlDrvCond *cnd, ErlDrvMutex *mtx)</nametext></name> - <fsummary>Wait on a condition variable</fsummary> + <name><ret>int</ret><nametext>erl_drv_rwlock_tryrwlock(ErlDrvRWLock + *rwlck)</nametext></name> + <fsummary>Try to read/write lock an rwlock.</fsummary> <desc> - <marker id="erl_drv_cond_wait"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>cnd</c></tag> - <item>A pointer to a condition variable to wait on.</item> - <tag><c>mtx</c></tag> - <item>A pointer to a mutex to unlock while waiting.</item> - <tag><c></c></tag> - <item></item> - </taglist> - <p>This function waits on a condition variable. The calling - thread is blocked until another thread wakes it by signaling - or broadcasting on the condition variable. Before the calling - thread is blocked it unlocks the mutex passed as argument, and - when the calling thread is woken it locks the same mutex before - returning. That is, the mutex currently has to be locked by - the calling thread when calling this function. - </p> - <note><p><c>erl_drv_cond_wait()</c> might return even though - no-one has signaled or broadcast on the condition - variable. Code calling <c>erl_drv_cond_wait()</c> should - always be prepared for <c>erl_drv_cond_wait()</c> - returning even though the condition that the thread was - waiting for hasn't occurred. That is, when returning from - <c>erl_drv_cond_wait()</c> always check if the condition - has occurred, and if not call <c>erl_drv_cond_wait()</c> - again. - </p></note> + <marker id="erl_drv_rwlock_tryrwlock"></marker> + <p>Tries to read/write lock an rwlock. + A thread that currently has read or read/write locked the + rwlock <em>cannot</em> try to lock the same rwlock again.</p> + <p><c>rwlck</c>is pointer to an rwlock to try to read/write lock.</p> + <p>Returns <c>0</c> on success, otherwise <c>EBUSY</c>.</p> + <warning> + <p>If you leave an rwlock locked in an emulator thread + when you let the thread out of your control, you will + <em>very likely</em> deadlock the whole emulator.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>ErlDrvRWLock *</ret><nametext>erl_drv_rwlock_create(char *name)</nametext></name> - <fsummary>Create an rwlock</fsummary> + <name><ret>int</ret><nametext>erl_drv_send_term(ErlDrvTermData port, + ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name> + <fsummary>Send term data to other process than port owner process. + </fsummary> <desc> - <marker id="erl_drv_rwlock_create"></marker> - <p>Arguments:</p> + <marker id="erl_drv_send_term"></marker> + <p>This function is the only way for a driver to send data to + <em>other</em> processes than the port owner process. Parameter + <c>receiver</c> specifies the process to receive the data.</p> + <note> + <p>Parameter <c>port</c> is <em>not</em> an ordinary port handle, but + a port handle converted using + <seealso marker="#driver_mk_port"> + <c>driver_mk_port</c></seealso>.</p> + </note> + <p>Parameters <c>port</c>, <c>term</c>, and <c>n</c> work as in + <seealso marker="#erl_drv_output_term"> + <c>erl_drv_output_term</c></seealso>.</p> + <p>This function is only thread-safe when the emulator with SMP + support is used.</p> + </desc> + </func> + + <func> + <name><ret>void</ret><nametext>erl_drv_set_os_pid(ErlDrvPort port, + ErlDrvSInt pid)</nametext></name> + <fsummary>Set the os_pid for the port.</fsummary> + <desc> + <marker id="erl_drv_set_os_pid"></marker> + <p>Sets the <c>os_pid</c> seen when doing + <seealso marker="erlang:port_info/2"> + <c>erlang:port_info/2</c></seealso> on this port.</p> + <p><c>port</c> is the port handle of the port (driver instance) to set + the pid on. <c>pid</c>is the pid to set.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>erl_drv_thread_create(char *name, ErlDrvTid + *tid, void * (*func)(void *), void *arg, ErlDrvThreadOpts + *opts)</nametext></name> + <fsummary>Create a thread.</fsummary> + <desc> + <marker id="erl_drv_thread_create"></marker> + <p>Creates a new thread.</p> <taglist> <tag><c>name</c></tag> - <item>A string identifying the created rwlock. It will be used to - identify the rwlock in planned future debug functionality. - </item> + <item>A string identifying the created thread. It is used to + identify the thread in planned future debug functionality. + </item> + <tag><c>tid</c></tag> + <item>A pointer to a thread identifier variable.</item> + <tag><c>func</c></tag> + <item>A pointer to a function to execute in the created thread.</item> + <tag><c>arg</c></tag> + <item>A pointer to argument to the <c>func</c> function.</item> + <tag><c>opts</c></tag> + <item>A pointer to thread options to use or <c>NULL</c>.</item> </taglist> - <p>This function creates an rwlock and returns a pointer to it. On - failure <c>NULL</c> is returned. The driver creating the rwlock - has the responsibility of destroying it before the driver is - unloaded. - </p> + <p>Returns <c>0</c> on success, + otherwise an <c>errno</c> value is returned to indicate the error. + The newly created thread begins executing in the function pointed + to by <c>func</c>, and <c>func</c> is passed <c>arg</c> as + argument. When <c>erl_drv_thread_create</c> returns, the thread + identifier of the newly created thread is available in + <c>*tid</c>. <c>opts</c> can be either a <c>NULL</c> pointer, or a + pointer to an + <seealso marker="#ErlDrvThreadOpts"><c>ErlDrvThreadOpts</c></seealso> + structure. If <c>opts</c> is a <c>NULL</c> pointer, default options + are used, otherwise the passed options are used.</p> + <warning> + <p>You are not allowed to allocate the + <seealso marker="#ErlDrvThreadOpts"> + <c>ErlDrvThreadOpts</c></seealso> structure by yourself. + It must be allocated and initialized by + <seealso marker="#erl_drv_thread_opts_create"> + <c>erl_drv_thread_opts_create</c></seealso>.</p> + </warning> + <p>The created thread terminates either when <c>func</c> returns or if + <seealso marker="#erl_drv_thread_exit"> + <c>erl_drv_thread_exit</c></seealso> + is called by the thread. The exit value of the thread is either + returned from <c>func</c> or passed as argument to + <seealso marker="#erl_drv_thread_exit"> + <c>erl_drv_thread_exit</c></seealso>. + The driver creating the thread is responsible for joining the + thread, through <seealso marker="#erl_drv_thread_join"> + <c>erl_drv_thread_join</c></seealso>, + before the driver is unloaded. "Detached" threads cannot be created, + that is, threads that do not need to be joined.</p> + <warning> + <p>All created threads must be joined by the driver before + it is unloaded. If the driver fails to join all threads + created before it is unloaded, the runtime system + most likely crashes when the driver code is unloaded.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_rwlock_destroy(ErlDrvRWLock *rwlck)</nametext></name> - <fsummary>Destroy an rwlock</fsummary> + <name><ret>void</ret><nametext>erl_drv_thread_exit(void + *exit_value)</nametext></name> + <fsummary>Terminate calling thread.</fsummary> <desc> - <marker id="erl_drv_rwlock_destroy"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>rwlck</c></tag> - <item>A pointer to an rwlock to destroy.</item> - </taglist> - <p>This function destroys an rwlock previously created by - <seealso marker="#erl_drv_rwlock_create">erl_drv_rwlock_create()</seealso>. - The rwlock has to be in an unlocked state before being destroyed. - </p> + <marker id="erl_drv_thread_exit"></marker> + <p>Terminates the calling thread with the exit value passed as + argument. <c>exit_value</c> is a pointer to an exit value or + <c>NULL</c>.</p> + <p>You are only allowed to terminate threads created with + <seealso marker="#erl_drv_thread_create"> + <c>erl_drv_thread_create</c></seealso>.</p> + <p>The exit value can later be retrieved by another thread through + <seealso marker="#erl_drv_thread_join"> + <c>erl_drv_thread_join</c></seealso>.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_rwlock_rlock(ErlDrvRWLock *rwlck)</nametext></name> - <fsummary>Read lock an rwlock</fsummary> + <name><ret>int</ret><nametext>erl_drv_thread_join(ErlDrvTid tid, void + **exit_value)</nametext></name> + <fsummary>Join with another thread.</fsummary> <desc> - <marker id="erl_drv_rwlock_rlock"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>rwlck</c></tag> - <item>A pointer to an rwlock to read lock.</item> - </taglist> - <p>This function read locks an rwlock. The calling thread will be - blocked until the rwlock has been read locked. A thread - which currently has read or read/write locked the rwlock may - <em>not</em> lock the same rwlock again. - </p> - <warning><p>If you leave an rwlock locked in an emulator thread - when you let the thread out of your control, you will - <em>very likely</em> deadlock the whole emulator. - </p></warning> + <marker id="erl_drv_thread_join"></marker> + <p>Joins the calling thread with another thread, that is, + the calling thread is blocked until the thread identified by + <c>tid</c> has terminated.</p> + <p><c>tid</c> is the thread identifier of the thread to join. + <c>exit_value</c> is a pointer to a pointer to an exit value, + or <c>NULL</c>.</p> + <p>Returns <c>0</c> on success, otherwise an <c>errno</c> + value is returned to indicate the error.</p> + <p>A thread can only be joined once. The behavior of joining + more than once is undefined, an emulator crash is likely. If + <c>exit_value == NULL</c>, the exit value of the terminated thread + is ignored, otherwise the exit value of the terminated thread + is stored at <c>*exit_value</c>.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>int</ret><nametext>erl_drv_rwlock_tryrlock(ErlDrvRWLock *rwlck)</nametext></name> - <fsummary>Try to read lock an rwlock</fsummary> + <name><ret>char *</ret><nametext>erl_drv_thread_name(ErlDrvTid + tid)</nametext></name> + <fsummary>Get name of driver mutex.</fsummary> <desc> - <marker id="erl_drv_rwlock_tryrlock"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>rwlck</c></tag> - <item>A pointer to an rwlock to try to read lock.</item> - </taglist> - <p>This function tries to read lock an rwlock. If successful - <c>0</c>, is returned; otherwise, <c>EBUSY</c> is returned. - A thread which currently has read or read/write locked the - rwlock may <em>not</em> try to lock the same rwlock again. - </p> - <warning><p>If you leave an rwlock locked in an emulator thread - when you let the thread out of your control, you will - <em>very likely</em> deadlock the whole emulator. - </p></warning> - <p>This function is thread-safe.</p> + <marker id="erl_drv_rwlock_name"></marker> + <p>Returns a pointer to the name of the thread.</p> + <p><c>tid</c> is a thread identifier.</p> + <note> + <p>This function is intended for debugging purposes only.</p> + </note> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_rwlock_runlock(ErlDrvRWLock *rwlck)</nametext></name> - <fsummary>Read unlock an rwlock</fsummary> + <name><ret>ErlDrvThreadOpts *</ret> + <nametext>erl_drv_thread_opts_create(char *name)</nametext></name> + <fsummary>Create thread options.</fsummary> <desc> - <marker id="erl_drv_rwlock_runlock"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>rwlck</c></tag> - <item>A pointer to an rwlock to read unlock.</item> - </taglist> - <p>This function read unlocks an rwlock. The rwlock currently - has to be read locked by the calling thread. - </p> + <marker id="erl_drv_thread_opts_create"></marker> + <p>Allocates and initializes a thread option structure.</p> + <p><c>name</c> is a string identifying the created thread options. + It is used to identify the thread options in planned future debug + functionality.</p> + <p>Returns <c>NULL</c> on failure. A thread option + structure is used for passing options to + <seealso marker="#erl_drv_thread_create"> + <c>erl_drv_thread_create</c></seealso>. + If the structure is not modified before it is passed to + <seealso marker="#erl_drv_thread_create"> + <c>erl_drv_thread_create</c></seealso>, + the default values are used.</p> + <warning> + <p>You are not allowed to allocate the + <seealso marker="#ErlDrvThreadOpts"> + <c>ErlDrvThreadOpts</c></seealso> + structure by yourself. It must be allocated and initialized by + <c>erl_drv_thread_opts_create</c>.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_rwlock_rwlock(ErlDrvRWLock *rwlck)</nametext></name> - <fsummary>Read/Write lock an rwlock</fsummary> + <name><ret>void</ret> + <nametext>erl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts)</nametext> + </name> + <fsummary>Destroy thread options.</fsummary> <desc> - <marker id="erl_drv_rwlock_rwlock"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>rwlck</c></tag> - <item>A pointer to an rwlock to read/write lock.</item> - </taglist> - <p>This function read/write locks an rwlock. The calling thread - will be blocked until the rwlock has been read/write locked. - A thread which currently has read or read/write locked the - rwlock may <em>not</em> lock the same rwlock again. - </p> - <warning><p>If you leave an rwlock locked in an emulator thread - when you let the thread out of your control, you will - <em>very likely</em> deadlock the whole emulator. - </p></warning> + <marker id="erl_drv_thread_opts_destroy"></marker> + <p>Destroys thread options previously created by + <seealso marker="#erl_drv_thread_opts_create"> + <c>erl_drv_thread_opts_create</c></seealso>.</p> + <p><c>opts</c> is a pointer to thread options to destroy.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>int</ret><nametext>erl_drv_rwlock_tryrwlock(ErlDrvRWLock *rwlck)</nametext></name> - <fsummary>Try to read/write lock an rwlock</fsummary> + <name><ret>ErlDrvTid</ret> + <nametext>erl_drv_thread_self(void)</nametext></name> + <fsummary>Get the thread identifier of the current thread.</fsummary> <desc> - <marker id="erl_drv_rwlock_tryrwlock"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>rwlck</c></tag> - <item>A pointer to an rwlock to try to read/write lock.</item> - </taglist> - <p>This function tries to read/write lock an rwlock. If successful - <c>0</c>, is returned; otherwise, <c>EBUSY</c> is returned. - A thread which currently has read or read/write locked the - rwlock may <em>not</em> try to lock the same rwlock again. - </p> - <warning><p>If you leave an rwlock locked in an emulator thread - when you let the thread out of your control, you will - <em>very likely</em> deadlock the whole emulator. - </p></warning> + <marker id="erl_drv_thread_self"></marker> + <p>Returns the thread identifier of the calling thread.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_rwlock_rwunlock(ErlDrvRWLock *rwlck)</nametext></name> - <fsummary>Read/Write unlock an rwlock</fsummary> + <name><ret>ErlDrvTime</ret><nametext>erl_drv_time_offset(ErlDrvTimeUnit + time_unit)</nametext></name> + <fsummary>Get current time offset.</fsummary> + <desc> + <marker id="erl_drv_time_offset"></marker> + <p>Returns the current time offset between + <seealso marker="time_correction#Erlang_Monotonic_Time"> + Erlang monotonic time</seealso> and + <seealso marker="time_correction#Erlang_System_Time"> + Erlang system time</seealso> + converted into the <c>time_unit</c> passed as argument.</p> + <p><c>time_unit</c> is time unit of returned value.</p> + <p>Returns <c>ERL_DRV_TIME_ERROR</c> if called with an invalid + time unit argument, or if called from a thread that is not a + scheduler thread.</p> + <p>See also <seealso marker="#ErlDrvTime"> + <c>ErlDrvTime</c></seealso> and + <seealso marker="#ErlDrvTimeUnit"> + <c>ErlDrvTimeUnit</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void *</ret><nametext>erl_drv_tsd_get(ErlDrvTSDKey + key)</nametext></name> + <fsummary>Get thread-specific data.</fsummary> <desc> - <marker id="erl_drv_rwlock_rwunlock"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>rwlck</c></tag> - <item>A pointer to an rwlock to read/write unlock.</item> - </taglist> - <p>This function read/write unlocks an rwlock. The rwlock - currently has to be read/write locked by the calling thread. - </p> + <marker id="erl_drv_tsd_get"></marker> + <p>Returns the thread-specific data + associated with <c>key</c> for the calling thread.</p> + <p><c>key</c> is a thread-specific data key.</p> + <p>Returns <c>NULL</c> if no data has been associated + with <c>key</c> for the calling thread.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>int</ret><nametext>erl_drv_tsd_key_create(char *name, ErlDrvTSDKey *key)</nametext></name> - <fsummary>Create a thread specific data key</fsummary> + <name><ret>int</ret><nametext>erl_drv_tsd_key_create(char *name, + ErlDrvTSDKey *key)</nametext></name> + <fsummary>Create a thread-specific data key.</fsummary> <desc> <marker id="erl_drv_tsd_key_create"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>name</c></tag> - <item>A string identifying the created key. It will be used - to identify the key in planned future debug - functionality. - </item> - <tag><c>key</c></tag> - <item>A pointer to a thread specific data key variable.</item> - </taglist> - <p>This function creates a thread specific data key. On success - <c>0</c> is returned; otherwise, an <c>errno</c> value is returned - to indicate the error. The driver creating the key has the - responsibility of destroying it before the driver is unloaded. - </p> + <p>Creates a thread-specific data key.</p> + <p><c>name</c> is a string identifying the created key. It is used + to identify the key in planned future debug functionality.</p> + <p><c>key</c> is a pointer to a thread-specific data key variable.</p> + <p>Returns <c>0</c> on success, otherwise an <c>errno</c> value is + returned to indicate the error. The driver creating the key is + responsible for destroying it before the driver is unloaded.</p> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_tsd_key_destroy(ErlDrvTSDKey key)</nametext></name> - <fsummary>Destroy a thread specific data key</fsummary> + <name><ret>void</ret><nametext>erl_drv_tsd_key_destroy(ErlDrvTSDKey + key)</nametext></name> + <fsummary>Destroy a thread-specific data key.</fsummary> <desc> <marker id="erl_drv_tsd_key_destroy"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>key</c></tag> - <item>A thread specific data key to destroy.</item> - </taglist> - <p>This function destroys a thread specific data key - previously created by - <seealso marker="#erl_drv_tsd_key_create">erl_drv_tsd_key_create()</seealso>. - All thread specific data using this key in all threads - have to be cleared (see - <seealso marker="#erl_drv_tsd_set">erl_drv_tsd_set()</seealso>) - prior to the call to <c>erl_drv_tsd_key_destroy()</c>. - </p> - <warning><p>A destroyed key is very likely to be reused soon. - Therefore, if you fail to clear the thread specific - data using this key in a thread prior to destroying - the key, you will <em>very likely</em> get unexpected - errors in other parts of the system. - </p></warning> + <p>Destroys a thread-specific data key previously created by + <seealso marker="#erl_drv_tsd_key_create"> + <c>erl_drv_tsd_key_create</c></seealso>. + All thread-specific data using this key in all threads + must be cleared (see <seealso marker="#erl_drv_tsd_set"> + <c>erl_drv_tsd_set</c></seealso>) + before the call to <c>erl_drv_tsd_key_destroy</c>.</p> + <p><c>key</c> is a thread-specific data key to destroy.</p> + <warning> + <p>A destroyed key is very likely to be reused soon. + Therefore, if you fail to clear the thread-specific + data using this key in a thread before destroying + the key, you will <em>very likely</em> get unexpected + errors in other parts of the system.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void</ret><nametext>erl_drv_tsd_set(ErlDrvTSDKey key, void *data)</nametext></name> - <fsummary>Set thread specific data</fsummary> + <name><ret>void</ret><nametext>erl_drv_tsd_set(ErlDrvTSDKey key, void + *data)</nametext></name> + <fsummary>Set thread-specific data.</fsummary> <desc> <marker id="erl_drv_tsd_set"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>key</c></tag> - <item>A thread specific data key.</item> - <tag><c>data</c></tag> - <item>A pointer to data to associate with <c>key</c> - in calling thread. - </item> - </taglist> - <p>This function sets thread specific data associated with - <c>key</c> for the calling thread. You are only allowed to set - thread specific data for threads while they are fully under your - control. For example, if you set thread specific data in a thread - calling a driver call-back function, it has to be cleared, i.e. - set to <c>NULL</c>, before returning from the driver call-back - function. - </p> - <warning><p>If you fail to clear thread specific data in an - emulator thread before letting it out of your control, - you might not ever be able to clear this data with - later unexpected errors in other parts of the system as - a result. - </p></warning> + <p>Sets thread-specific data associated with + <c>key</c> for the calling thread. You are only allowed to set + thread-specific data for threads while they are fully under your + control. For example, if you set thread-specific data in a thread + calling a driver callback function, it must be cleared, that is, + set to <c>NULL</c>, before returning from the driver callback + function.</p> + <p><c>key</c> is a thread-specific data key.</p> + <p><c>data</c> is a pointer to data to associate with <c>key</c> + in the calling thread.</p> + <warning> + <p>If you fail to clear thread-specific data in an + emulator thread before letting it out of your control, + you might never be able to clear this data with + later unexpected errors in other parts of the system as + a result.</p> + </warning> <p>This function is thread-safe.</p> </desc> </func> <func> - <name><ret>void *</ret><nametext>erl_drv_tsd_get(ErlDrvTSDKey key)</nametext></name> - <fsummary>Get thread specific data</fsummary> + <name><ret>char *</ret><nametext>erl_errno_id(int error)</nametext></name> + <fsummary>Get Erlang error atom name from error number.</fsummary> <desc> - <marker id="erl_drv_tsd_get"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>key</c></tag> - <item>A thread specific data key.</item> - </taglist> - <p>This function returns the thread specific data - associated with <c>key</c> for the calling thread. - If no data has been associated with <c>key</c> for - the calling thread, <c>NULL</c> is returned. - </p> - <p>This function is thread-safe.</p> + <marker id="erl_errno_id"></marker> + <p>Returns the atom name of the Erlang error, + given the error number in <c>error</c>. The error atoms are + <c>einval</c>, <c>enoent</c>, and so on. It can be used to make + error terms from the driver.</p> </desc> </func> <func> - <name><ret>int</ret><nametext>erl_drv_putenv(char *key, char *value)</nametext></name> - <fsummary>Set the value of an environment variable</fsummary> + <name><ret>int</ret><nametext>remove_driver_entry(ErlDrvEntry + *de)</nametext></name> + <fsummary>Remove a driver entry.</fsummary> <desc> - <marker id="erl_drv_putenv"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>key</c></tag> - <item>A null terminated string containing the - name of the environment variable.</item> - <tag><c>value</c></tag> - <item>A null terminated string containing the - new value of the environment variable.</item> - </taglist> - <p>This function sets the value of an environment variable. - It returns <c>0</c> on success, and a value <c>!= 0</c> on - failure. - </p> - <note><p>The result of passing the empty string ("") as a value - is platform dependent. On some platforms the value of the - variable is set to the empty string, on others, the - environment variable is removed.</p> - </note> - <warning><p>Do <em>not</em> use libc's <c>putenv</c> or similar - C library interfaces from a driver. - </p></warning> - <p>This function is thread-safe.</p> + <marker id="remove_driver_entry"></marker> + <p>Removes a driver entry <c>de</c> previously added with + <seealso marker="#add_driver_entry"> + <c>add_driver_entry</c></seealso>.</p> + <p>Driver entries added by the <c>erl_ddll</c> Erlang interface + cannot be removed by using this interface.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>erl_drv_getenv(char *key, char *value, size_t *value_size)</nametext></name> - <fsummary>Get the value of an environment variable</fsummary> + <name><ret>void</ret><nametext>set_busy_port(ErlDrvPort port, int + on)</nametext></name> + <fsummary>Signal or unsignal port as busy.</fsummary> <desc> - <marker id="erl_drv_getenv"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>key</c></tag> - <item>A null terminated string containing the - name of the environment variable.</item> - <tag><c>value</c></tag> - <item>A pointer to an output buffer.</item> - <tag><c>value_size</c></tag> - <item>A pointer to an integer. The integer is both used for - passing input and output sizes (see below). - </item> - </taglist> - <p>This function retrieves the value of an environment variable. - When called, <c>*value_size</c> should contain the size of - the <c>value</c> buffer. On success <c>0</c> is returned, - the value of the environment variable has been written to - the <c>value</c> buffer, and <c>*value_size</c> contains the - string length (excluding the terminating null character) of - the value written to the <c>value</c> buffer. On failure, - i.e., no such environment variable was found, a value less than - <c>0</c> is returned. When the size of the <c>value</c> - buffer is too small, a value greater than <c>0</c> is returned - and <c>*value_size</c> has been set to the buffer size needed. - </p> - <warning><p>Do <em>not</em> use libc's <c>getenv</c> or similar - C library interfaces from a driver. - </p></warning> - <p>This function is thread-safe.</p> + <marker id="set_busy_port"></marker> + <p>Sets and unsets the busy state of the port. If + <c>on</c> is non-zero, the port is set to busy. If it is zero, + the port is set to not busy. You typically want to combine + this feature with the <seealso marker="#erl_drv_busy_msgq_limits"> + busy port message queue</seealso> functionality.</p> + <p>Processes sending command data to the port are suspended + if either the port or the port message queue + is busy. Suspended processes are resumed when neither the + port or the port message queue is busy. Command data + is in this context data passed to the port using either + <c>Port ! {Owner, {command, Data}}</c> or + <c>port_command/[2,3]</c>.</p> + <p>If the <seealso marker="driver_entry#driver_flags"> + <![CDATA[ERL_DRV_FLAG_SOFT_BUSY]]></seealso> has been set in the + <seealso marker="driver_entry"><c>driver_entry</c></seealso>, + data can be forced into the driver through + <seealso marker="erlang#port_command/3"> + <c>erlang:port_command(Port, Data, [force])</c></seealso> + even if the driver has signaled that it is busy.</p> + <p>For information about busy port message queue functionality, see + <seealso marker="#erl_drv_busy_msgq_limits"> + <c>erl_drv_busy_msgq_limits</c></seealso>.</p> </desc> </func> + <func> - <name><ret>int</ret><nametext>erl_drv_consume_timeslice(ErlDrvPort port, int percent)</nametext></name> - <fsummary>Give the runtime system a hint about how much CPU time the - current driver callback call has consumed</fsummary> + <name><ret>void</ret><nametext>set_port_control_flags(ErlDrvPort port, + int flags)</nametext></name> + <fsummary>Set flags on how to handle control entry function.</fsummary> <desc> - <marker id="erl_drv_consume_timeslice"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>port</c></tag> - <item>Port handle of the executing port.</item> - <tag><c>percent</c></tag> - <item>Approximate consumed fraction of a full - time-slice in percent.</item> - </taglist> - <p>Give the runtime system a hint about how much CPU time the - current driver callback call has consumed since last hint, or - since the start of the callback if no previous hint has been given. - The time is given as a fraction, in percent, of a full time-slice - that a port is allowed to execute before it should surrender the - CPU to other runnable ports or processes. Valid range is - <c>[1, 100]</c>. The scheduling time-slice is not an exact entity, - but can usually be approximated to about 1 millisecond.</p> - - <p>Note that it is up to the runtime system to determine if and - how to use this information. Implementations on some platforms - may use other means in order to determine the consumed fraction - of the time-slice. Lengthy driver callbacks should regardless of - this frequently call the <c>erl_drv_consume_timeslice()</c> - function in order to determine if it is allowed to continue - execution or not.</p> - - <p><c>erl_drv_consume_timeslice()</c> returns a non-zero value - if the time-slice has been exhausted, and zero if the callback is - allowed to continue execution. If a non-zero value is - returned the driver callback should return as soon as possible in - order for the port to be able to yield.</p> - - <p>This function is provided to better support co-operative scheduling, - improve system responsiveness, and to make it easier to prevent - misbehaviors of the VM due to a port monopolizing a scheduler thread. - It can be used when dividing length work into a number of repeated - driver callback calls without the need to use threads. Also see the - important <seealso marker="#WARNING">warning</seealso> text at the - beginning of this document.</p> - </desc> - </func> - - <func> - <name><ret>char *</ret><nametext>erl_drv_cond_name(ErlDrvCond *cnd)</nametext></name> - <fsummary>Get name of driver mutex.</fsummary> - <desc> - <marker id="erl_drv_cnd_name"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>cnd</c></tag> - <item>A pointer to an initialized condition.</item> - </taglist> - <p> - Returns a pointer to the name of the condition. - </p> - <note> - <p>This function is intended for debugging purposes only.</p> - </note> - </desc> - </func> - - <func> - <name><ret>char *</ret><nametext>erl_drv_mutex_name(ErlDrvMutex *mtx)</nametext></name> - <fsummary>Get name of driver mutex.</fsummary> - <desc> - <marker id="erl_drv_mutex_name"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>mtx</c></tag> - <item>A pointer to an initialized mutex.</item> - </taglist> - <p> - Returns a pointer to the name of the mutex. - </p> - <note> - <p>This function is intended for debugging purposes only.</p> - </note> - </desc> - </func> - - <func> - <name><ret>char *</ret><nametext>erl_drv_rwlock_name(ErlDrvRWLock *rwlck)</nametext></name> - <fsummary>Get name of driver mutex.</fsummary> - <desc> - <marker id="erl_drv_rwlock_name"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>rwlck</c></tag> - <item>A pointer to an initialized r/w-lock.</item> - </taglist> - <p> - Returns a pointer to the name of the r/w-lock. - </p> - <note> - <p>This function is intended for debugging purposes only.</p> - </note> - </desc> - </func> - - <func> - <name><ret>char *</ret><nametext>erl_drv_thread_name(ErlDrvTid tid)</nametext></name> - <fsummary>Get name of driver mutex.</fsummary> - <desc> - <marker id="erl_drv_rwlock_name"></marker> - <p>Arguments:</p> - <taglist> - <tag><c>tid</c></tag> - <item>A thread identifier.</item> - </taglist> - <p> - Returns a pointer to the name of the thread. - </p> - <note> - <p>This function is intended for debugging purposes only.</p> - </note> - </desc> - </func> - + <marker id="set_port_control_flags"></marker> + <p>Sets flags for how the <seealso marker="driver_entry#control"> + <c>control</c></seealso> driver entry + function will return data to the port owner process. + (The <c>control</c> function is called from + <seealso marker="erlang:port_control/3"> + <c>erlang:port_control/3</c></seealso>.)</p> + <p>Currently there are only two meaningful values for + <c>flags</c>: <c>0</c> means that data is returned in a list, + and <c>PORT_CONTROL_FLAG_BINARY</c> means data is returned as + a binary from <c>control</c>.</p> + </desc> + </func> </funcs> + <section> - <title>SEE ALSO</title> - <p><seealso marker="driver_entry">driver_entry(3)</seealso>, - <seealso marker="kernel:erl_ddll">erl_ddll(3)</seealso>, - <seealso marker="erlang">erlang(3)</seealso></p> - <p>An Alternative Distribution Driver (ERTS User's - Guide Ch. 3)</p> + <title>See Also</title> + <p><seealso marker="driver_entry"><c>driver_entry(3)</c></seealso>, + <seealso marker="erlang"><c>erlang(3)</c></seealso>, + <seealso marker="kernel:erl_ddll"><c>erl_ddll(3)</c></seealso>, + section <seealso marker="alt_dist">How to Implement an Alternative + Carrier for the Erlang Distribution</seealso> in the User's Guide</p> </section> </cref> diff --git a/erts/doc/src/erl_ext_dist.xml b/erts/doc/src/erl_ext_dist.xml index a6e7dddbed..b7090d0472 100644 --- a/erts/doc/src/erl_ext_dist.xml +++ b/erts/doc/src/erl_ext_dist.xml @@ -5,20 +5,21 @@ <header> <copyright> <year>2007</year> - <year>2014</year> + <year>2017</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. The Initial Developer of the Original Code is Ericsson AB. </legalnotice> @@ -34,135 +35,121 @@ <section> <title>Introduction</title> <p> - The external term format is mainly used in the distribution + The external term format is mainly used in the distribution mechanism of Erlang. </p> <p> - Since Erlang has a fixed number of types, there is no need for a - programmer to define a specification for the external format used + As Erlang has a fixed number of types, there is no need for a + programmer to define a specification for the external format used within some application. - All Erlang terms has an external representation and the interpretation - of the different terms are application specific. + All Erlang terms have an external representation and the interpretation + of the different terms is application-specific. </p> <p> - In Erlang the BIF <seealso marker="erts:erlang#term_to_binary/1">term_to_binary/1,2</seealso> is used to convert a - term into the external format. - To convert binary data encoding a term the BIF + In Erlang the BIF <seealso marker="erts:erlang#term_to_binary/1"> + <c>erlang:term_to_binary/1,2</c></seealso> is used to convert a + term into the external format. + To convert binary data encoding to a term, the BIF <seealso marker="erts:erlang#binary_to_term/1"> - binary_to_term/1 - </seealso> - is used. + <c>erlang:binary_to_term/1</c></seealso> is used. </p> <p> - The distribution does this implicitly when sending messages across + The distribution does this implicitly when sending messages across node boundaries. </p> <marker id="overall_format"/> <p> - The overall format of the term format is: + The overall format of the term format is as follows: </p> <table align="left"> <row> - <cell align="center">1</cell> - <cell align="center">1</cell> - <cell align="center">N</cell> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">N</cell> </row> - <row> - <cell align="center"><c>131</c></cell> - <cell align="center"><c>Tag</c></cell> - <cell align="center"><c>Data</c></cell> - </row> - <tcaption></tcaption></table> + <row> + <cell align="center"><c>131</c></cell> + <cell align="center"><c>Tag</c></cell> + <cell align="center"><c>Data</c></cell> + </row> + <tcaption>Term Format</tcaption></table> <note> - <p> - When messages are - <seealso marker="erl_dist_protocol#connected_nodes">passed between - connected nodes</seealso> and a - <seealso marker="#distribution_header">distribution - header</seealso> is used, the first byte containing the version - number (131) is omitted from the terms that follow the distribution - header. This since - the version number is implied by the version number in the - distribution header. - </p> + <p> + When messages are + <seealso marker="erl_dist_protocol#connected_nodes">passed between + connected nodes</seealso> and a + <seealso marker="#distribution_header">distribution + header</seealso> is used, the first byte containing the version + number (131) is omitted from the terms that follow the distribution + header. This is because the version number is implied by the version + number in the distribution header. + </p> </note> <p> - A compressed term looks like this: + The compressed term format is as follows: </p> <table align="left"> <row> - <cell align="center">1</cell> - <cell align="center">1</cell> - <cell align="center">4</cell> - <cell align="center">N</cell> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">4</cell> + <cell align="center">N</cell> </row> <row> - <cell align="center">131</cell> - <cell align="center">80</cell> - <cell align="center">UncompressedSize</cell> - <cell align="center">Zlib-compressedData</cell> + <cell align="center"><c>131</c></cell> + <cell align="center"><c>80</c></cell> + <cell align="center"><c>UncompressedSize</c></cell> + <cell align="center"><c>Zlib-compressedData</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>Compressed Term Format</tcaption></table> <p> - Uncompressed Size (unsigned 32 bit integer in big-endian byte order) + Uncompressed size (unsigned 32-bit integer in big-endian byte order) is the size of the data before it was compressed. - The compressed data has the following format when it has been - expanded: + The compressed data has the following format when it has been expanded: </p> <table align="left"> <row> - <cell align="center">1</cell> - <cell align="center">Uncompressed Size</cell> + <cell align="center">1</cell> + <cell align="center">Uncompressed Size</cell> </row> <row> - <cell align="center">Tag</cell> - <cell align="center">Data</cell> + <cell align="center"><c>Tag</c></cell> + <cell align="center"><c>Data</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>Compressed Data Format when Expanded</tcaption></table> <marker id="utf8_atoms"/> <note> - <p>As of ERTS version 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 Latin1 (ISO-8859-1) - are currently supported in atoms. The support for UTF-8 encoded atoms - in the external format has been implemented in order 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 Latin1, and <em>the behavior is - undefined</em>.</p> - <p>When the - <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_UTF8_ATOMS</c></seealso> - distribution flag has been exchanged between both nodes in the - <seealso marker="erl_dist_protocol#distribution_handshake">distribution handshake</seealso>, - all atoms in the distribution header will be encoded in UTF-8; otherwise, - all atoms in the distribution header will be encoded in Latin1. The two - new tags <seealso marker="#ATOM_UTF8_EXT">ATOM_UTF8_EXT</seealso>, and - <seealso marker="#SMALL_ATOM_UTF8_EXT">SMALL_ATOM_UTF8_EXT</seealso> - will only be used if the <c>DFLAG_UTF8_ATOMS</c> distribution flag has - been exchanged between nodes, or if an atom containing characters - that cannot be encoded in Latin1 is encountered. - </p> - <p>The maximum number of allowed characters in an atom is 255. In the - UTF-8 case each character may need 4 bytes to be encoded. - </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> </section> - <marker id="distribution_header"/> <section> - <title>Distribution header</title> + <title>Distribution Header</title> <p> - As of erts version 5.7.2 the old atom cache protocol was - dropped and a new one was introduced. This atom cache protocol - introduced the distribution header. Nodes with erts versions + <marker id="distribution_header"/> + As from ERTS 5.7.2 the old atom cache protocol was + dropped and a new one was introduced. This protocol + introduced the distribution header. Nodes with an ERTS version earlier than 5.7.2 can still communicate with new nodes, - but no distribution header and no atom cache will be used.</p> + but no distribution header and no atom cache are used.</p> <p> - The distribution header currently only contains an atom cache - reference section, but could in the future contain more + The distribution header only contains an atom cache + reference section, but can in the future contain more information. The distribution header precedes one or more Erlang - terms on the external format. For more information see the + terms on the external format. For more information, see the documentation of the <seealso marker="erl_dist_protocol#connected_nodes">protocol between connected nodes</seealso> in the @@ -172,37 +159,37 @@ <p> <seealso marker="#ATOM_CACHE_REF">ATOM_CACHE_REF</seealso> entries with corresponding <c>AtomCacheReferenceIndex</c> in terms - encoded on the external format following a distribution header refers + encoded on the external format following a distribution header refer to the atom cache references made in the distribution header. The range - is 0 <= <c>AtomCacheReferenceIndex</c> < 255, i.e., at most 255 + is 0 <= <c>AtomCacheReferenceIndex</c> < 255, that is, at most 255 different atom cache references from the following terms can be made. </p> <p> - The distribution header format is: + The distribution header format is as follows: </p> <table align="left"> <row> - <cell align="center">1</cell> - <cell align="center">1</cell> - <cell align="center">1</cell> - <cell align="center">NumberOfAtomCacheRefs/2+1 | 0</cell> - <cell align="center">N | 0</cell> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">NumberOfAtomCacheRefs/2+1 | 0</cell> + <cell align="center">N | 0</cell> </row> <row> - <cell align="center"><c>131</c></cell> - <cell align="center"><c>68</c></cell> - <cell align="center"><c>NumberOfAtomCacheRefs</c></cell> - <cell align="center"><c>Flags</c></cell> - <cell align="center"><c>AtomCacheRefs</c></cell> + <cell align="center"><c>131</c></cell> + <cell align="center"><c>68</c></cell> + <cell align="center"><c>NumberOfAtomCacheRefs</c></cell> + <cell align="center"><c>Flags</c></cell> + <cell align="center"><c>AtomCacheRefs</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>Distribution Header Format</tcaption></table> <p> - <c>Flags</c> consists of <c>NumberOfAtomCacheRefs/2+1</c> bytes, + <c>Flags</c> consist of <c>NumberOfAtomCacheRefs/2+1</c> bytes, unless <c>NumberOfAtomCacheRefs</c> is <c>0</c>. If <c>NumberOfAtomCacheRefs</c> is <c>0</c>, <c>Flags</c> and - <c>AtomCacheRefs</c> are omitted. Each atom cache reference have + <c>AtomCacheRefs</c> are omitted. Each atom cache reference has a half byte flag field. Flags corresponding to a specific - <c>AtomCacheReferenceIndex</c>, are located in flag byte number + <c>AtomCacheReferenceIndex</c> are located in flag byte number <c>AtomCacheReferenceIndex/2</c>. Flag byte 0 is the first byte after the <c>NumberOfAtomCacheRefs</c> byte. Flags for an even <c>AtomCacheReferenceIndex</c> are located in the least significant @@ -215,95 +202,97 @@ </p> <table align="left"> <row> - <cell align="center">1 bit</cell> - <cell align="center">3 bits</cell> + <cell align="center">1 bit</cell> + <cell align="center">3 bits</cell> </row> <row> - <cell align="center"><c>NewCacheEntryFlag</c></cell> - <cell align="center"><c>SegmentIndex</c></cell> + <cell align="center"><c>NewCacheEntryFlag</c></cell> + <cell align="center"><c>SegmentIndex</c></cell> </row> <tcaption></tcaption></table> <p> The most significant bit is the <c>NewCacheEntryFlag</c>. If set, the corresponding cache reference is new. The three least significant bits are the <c>SegmentIndex</c> of the corresponding - atom cache entry. An atom cache consists of 8 segments each of size - 256, i.e., an atom cache can contain 2048 entries. + atom cache entry. An atom cache consists of 8 segments, each of size + 256, that is, an atom cache can contain 2048 entries. </p> <p> After flag fields for atom cache references, another half byte flag - field is located which has the following format: + field is located with the following format: </p> <table align="left"> <row> - <cell align="center">3 bits</cell> - <cell align="center">1 bit</cell> + <cell align="center">3 bits</cell> + <cell align="center">1 bit</cell> </row> <row> - <cell align="center"><c>CurrentlyUnused</c></cell> - <cell align="center"><c>LongAtoms</c></cell> + <cell align="center"><c>CurrentlyUnused</c></cell> + <cell align="center"><c>LongAtoms</c></cell> </row> <tcaption></tcaption></table> <p> - The least significant bit in that half byte is the <c>LongAtoms</c> - flag. If it is set, 2 bytes are used for atom lengths instead of + The least significant bit in that half byte is flag <c>LongAtoms</c>. + If it is set, 2 bytes are used for atom lengths instead of 1 byte in the distribution header. </p> <p> After the <c>Flags</c> field follow the <c>AtomCacheRefs</c>. The first <c>AtomCacheRef</c> is the one corresponding to - <c>AtomCacheReferenceIndex</c> 0. Higher indices follows + <c>AtomCacheReferenceIndex</c> 0. Higher indices follow in sequence up to index <c>NumberOfAtomCacheRefs - 1</c>. </p> <p> If the <c>NewCacheEntryFlag</c> for the next <c>AtomCacheRef</c> has - been set, a <c>NewAtomCacheRef</c> on the following format will follow: + been set, a <c>NewAtomCacheRef</c> on the following format follows: </p> <table align="left"> <row> - <cell align="center">1</cell> - <cell align="center">1 | 2</cell> - <cell align="center">Length</cell> + <cell align="center">1</cell> + <cell align="center">1 | 2</cell> + <cell align="center">Length</cell> </row> <row> - <cell align="center"><c>InternalSegmentIndex</c></cell> - <cell align="center"><c>Length</c></cell> - <cell align="center"><c>AtomText</c></cell> + <cell align="center"><c>InternalSegmentIndex</c></cell> + <cell align="center"><c>Length</c></cell> + <cell align="center"><c>AtomText</c></cell> </row> <tcaption></tcaption></table> <p> <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c> completely identify the location of an atom cache entry in the - atom cache. <c>Length</c> is number of bytes that <c>AtomText</c> - consists of. Length is a two byte big endian integer - if the <c>LongAtoms</c> flag has been set, otherwise a one byte - integer. When the - <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_UTF8_ATOMS</c></seealso> - distribution flag has been exchanged between both nodes in the - <seealso marker="erl_dist_protocol#distribution_handshake">distribution handshake</seealso>, - characters in <c>AtomText</c> is encoded in UTF-8; otherwise, - encoded in Latin1. Subsequent <c>CachedAtomRef</c>s with the same + atom cache. <c>Length</c> is the number of bytes that <c>AtomText</c> + consists of. Length is a 2 byte big-endian integer + if flag <c>LongAtoms</c> has been set, otherwise a 1 byte + integer. When distribution flag + <seealso marker="erl_dist_protocol#dflags"> + <c>DFLAG_UTF8_ATOMS</c></seealso> + has been exchanged between both nodes in the + <seealso marker="erl_dist_protocol#distribution_handshake"> + distribution handshake</seealso>, + characters in <c>AtomText</c> are encoded in UTF-8, otherwise + in Latin-1. The following <c>CachedAtomRef</c>s with the same <c>SegmentIndex</c> and <c>InternalSegmentIndex</c> as this - <c>NewAtomCacheRef</c> will refer to this atom until a new + <c>NewAtomCacheRef</c> refer to this atom until a new <c>NewAtomCacheRef</c> with the same <c>SegmentIndex</c> and <c>InternalSegmentIndex</c> appear. </p> <p> - For more information on encoding of atoms, see + For more information on encoding of atoms, see the <seealso marker="#utf8_atoms">note on UTF-8 encoded atoms</seealso> - in the beginning of this document. + in the beginning of this section. </p> <p> If the <c>NewCacheEntryFlag</c> for the next <c>AtomCacheRef</c> has not been set, a <c>CachedAtomRef</c> on the following format - will follow: + follows: </p> <table align="left"> <row> - <cell align="center">1</cell> + <cell align="center">1</cell> </row> <row> - <cell align="center"><c>InternalSegmentIndex</c></cell> + <cell align="center"><c>InternalSegmentIndex</c></cell> </row> <tcaption></tcaption></table> <p> @@ -318,157 +307,125 @@ <section> <marker id="ATOM_CACHE_REF"/> <title>ATOM_CACHE_REF</title> - <table align="left"> <row> <cell align="center">1</cell> - <cell align="center">1</cell> + <cell align="center">1</cell> </row> <row> - <cell align="center"><c>82</c></cell> - <cell align="center"><c>AtomCacheReferenceIndex</c></cell> + <cell align="center"><c>82</c></cell> + <cell align="center"><c>AtomCacheReferenceIndex</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>ATOM_CACHE_REF</tcaption></table> <p> Refers to the atom with <c>AtomCacheReferenceIndex</c> in the - <seealso marker="#distribution_header">distribution header</seealso>. + <seealso marker="#distribution_header">distribution header</seealso>. </p> </section> <section> <marker id="SMALL_INTEGER_EXT"/> <title>SMALL_INTEGER_EXT</title> - <table align="left"> <row> - <cell align="center">1</cell> - <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">1</cell> </row> <row> - <cell align="center">97</cell> - <cell align="center">Int</cell> + <cell align="center"><c>97</c></cell> + <cell align="center"><c>Int</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>SMALL_INTEGER_EXT</tcaption></table> <p> - Unsigned 8 bit integer. + Unsigned 8-bit integer. </p> </section> <section> <marker id="INTEGER_EXT"/> <title>INTEGER_EXT</title> - <table align="left"> <row> - <cell align="center">1</cell> - <cell align="center">4</cell> + <cell align="center">1</cell> + <cell align="center">4</cell> </row> <row> - <cell align="center">98</cell> - <cell align="center">Int</cell> + <cell align="center"><c>98</c></cell> + <cell align="center"><c>Int</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>INTEGER_EXT</tcaption></table> <p> - Signed 32 bit integer in big-endian format (i.e. MSB first) + Signed 32-bit integer in big-endian format. </p> </section> <section> <marker id="FLOAT_EXT"/> <title>FLOAT_EXT</title> - <table align="left"> <row> - <cell align="center">1</cell> - <cell align="center">31</cell> + <cell align="center">1</cell> + <cell align="center">31</cell> </row> <row> - <cell align="center">99</cell> - <cell align="center">Float String</cell> + <cell align="center"><c>99</c></cell> + <cell align="center"><c>Float string</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>FLOAT_EXT</tcaption></table> <p> - A float is stored in string format. the format used in sprintf to - format the float is "%.20e" + A float is stored in string format. The format used in sprintf to + format the float is "%.20e" (there are more bytes allocated than necessary). - To unpack the float use sscanf with format "%lf". + To unpack the float, use sscanf with format "%lf". </p> <p> - This term is used in minor version 0 of the external format; - it has been superseded by - <seealso marker="#NEW_FLOAT_EXT"> - NEW_FLOAT_EXT - </seealso>. + This term is used in minor version 0 of the external format; + it has been superseded by + <seealso marker="#NEW_FLOAT_EXT"><c>NEW_FLOAT_EXT</c></seealso>. </p> </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></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 Latin1 characters that forms - the <c>AtomName</c>. - <em>Note</em>: The maximum allowed value for <c>Len</c> is 255. - </p> - </section> - - <section> <marker id="REFERENCE_EXT"/> <title>REFERENCE_EXT</title> - - <table align="left"> - <row> - <cell align="center">1</cell> - <cell align="center">N</cell> - <cell align="center">4</cell> - <cell align="center">1</cell> - </row> - <row> - <cell align="center"><c>101</c></cell> - <cell align="center"><c>Node</c></cell> - <cell align="center"><c>ID</c></cell> - <cell align="center"><c>Creation</c></cell> - </row> - <tcaption></tcaption></table> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">N</cell> + <cell align="center">4</cell> + <cell align="center">1</cell> + </row> + <row> + <cell align="center"><c>101</c></cell> + <cell align="center"><c>Node</c></cell> + <cell align="center"><c>ID</c></cell> + <cell align="center"><c>Creation</c></cell> + </row> + <tcaption>REFERENCE_EXT</tcaption></table> <p> - Encode a reference object (an object generated with <c>make_ref/0</c>). - The <c>Node</c> term is an encoded atom, i.e. - <seealso marker="#ATOM_EXT">ATOM_EXT</seealso>, - <seealso marker="#SMALL_ATOM_EXT">SMALL_ATOM_EXT</seealso> or - <seealso marker="#ATOM_CACHE_REF">ATOM_CACHE_REF</seealso>. - The <c>ID</c> field contains a big-endian - unsigned integer, - but <em>should be regarded as uninterpreted data</em> - since this field is node specific. - <c>Creation</c> is a byte containing a node serial number that - makes it possible to separate old (crashed) nodes from a new one. + 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_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>, + as this field is node-specific. + <c>Creation</c> is a byte containing a node serial number, which + makes it possible to separate old (crashed) nodes from a new one. </p> <p> - In <c>ID</c>, only 18 bits are significant; the rest should be 0. - In <c>Creation</c>, only 2 bits are significant; the rest should be 0. - - See <seealso marker="#NEW_REFERENCE_EXT">NEW_REFERENCE_EXT</seealso>. + In <c>ID</c>, only 18 bits are significant; the rest are to be 0. + In <c>Creation</c>, only two bits are significant; the rest are to be 0. + See <seealso marker="#NEW_REFERENCE_EXT"> + <c>NEW_REFERENCE_EXT</c></seealso>. </p> </section> <section> <marker id="PORT_EXT"/> <title>PORT_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -482,20 +439,21 @@ <cell align="center"><c>ID</c></cell> <cell align="center"><c>Creation</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>PORT_EXT</tcaption></table> <p> - Encode a port object (obtained form <c>open_port/2</c>). - The <c>ID</c> is a node specific identifier for a local port. + Encodes a port object (obtained from + <seealso marker="erlang:open_port/2"> + <c>erlang:open_port/2</c></seealso>). + The <c>ID</c> is a node-specific identifier for a local port. Port operations are not allowed across node boundaries. The <c>Creation</c> works just like in - <seealso marker="#REFERENCE_EXT">REFERENCE_EXT</seealso>. + <seealso marker="#REFERENCE_EXT"><c>REFERENCE_EXT</c></seealso>. </p> </section> <section> <marker id="PID_EXT"/> <title>PID_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -511,23 +469,20 @@ <cell align="center"><c>Serial</c></cell> <cell align="center"><c>Creation</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>PID_EXT</tcaption></table> <p> - Encode a process identifier object (obtained from <c>spawn/3</c> or - friends). - The <c>ID</c> and <c>Creation</c> fields works just like in - <seealso marker="#REFERENCE_EXT">REFERENCE_EXT</seealso>, while - the <c>Serial</c> field is used to improve safety. - - In <c>ID</c>, only 15 bits are significant; the rest should be 0. + Encodes a process identifier object (obtained from + <seealso marker="erlang:spawn/3"><c>erlang:spawn/3</c></seealso> or + friends). The <c>ID</c> and <c>Creation</c> fields works just like in + <seealso marker="#REFERENCE_EXT"><c>REFERENCE_EXT</c></seealso>, while + the <c>Serial</c> field is used to improve safety. + In <c>ID</c>, only 15 bits are significant; the rest are to be 0. </p> - </section> <section> <marker id="SMALL_TUPLE_EXT"/> <title>SMALL_TUPLE_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -535,22 +490,21 @@ <cell align="center">N</cell> </row> <row> - <cell align="center">104</cell> - <cell align="center">Arity</cell> - <cell align="center">Elements</cell> + <cell align="center"><c>104</c></cell> + <cell align="center"><c>Arity</c></cell> + <cell align="center"><c>Elements</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>SMALL_TUPLE_EXT</tcaption></table> <p> - <c>SMALL_TUPLE_EXT</c> encodes a tuple. The <c>Arity</c> - field is an unsigned byte that determines how many element - that follows in the <c>Elements</c> section. + Encodes a tuple. The <c>Arity</c> + field is an unsigned byte that determines how many elements + that follows in section <c>Elements</c>. </p> </section> <section> <marker id="LARGE_TUPLE_EXT"/> <title>LARGE_TUPLE_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -558,23 +512,22 @@ <cell align="center">N</cell> </row> <row> - <cell align="center">105</cell> - <cell align="center">Arity</cell> - <cell align="center">Elements</cell> + <cell align="center"><c>105</c></cell> + <cell align="center"><c>Arity</c></cell> + <cell align="center"><c>Elements</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>LARGE_TUPLE_EXT</tcaption></table> <p> - Same as - <seealso marker="#SMALL_TUPLE_EXT">SMALL_TUPLE_EXT</seealso> - with the exception that <c>Arity</c> is an - unsigned 4 byte integer in big endian format. + Same as + <seealso marker="#SMALL_TUPLE_EXT"><c>SMALL_TUPLE_EXT</c></seealso> + except that <c>Arity</c> is an + unsigned 4 byte integer in big-endian format. </p> </section> <section> <marker id="MAP_EXT"/> <title>MAP_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -582,43 +535,42 @@ <cell align="center">N</cell> </row> <row> - <cell align="center">116</cell> - <cell align="center">Arity</cell> - <cell align="center">Pairs</cell> + <cell align="center"><c>116</c></cell> + <cell align="center"><c>Arity</c></cell> + <cell align="center"><c>Pairs</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>MAP_EXT</tcaption></table> <p> - <c>MAP_EXT</c> encodes a map. The <c>Arity</c> field is an unsigned - 4 byte integer in big endian format that determines the number of + Encodes a map. The <c>Arity</c> field is an unsigned + 4 byte integer in big-endian format that determines the number of key-value pairs in the map. Key and value pairs (<c>Ki => Vi</c>) - are encoded in the <c>Pairs</c> section in the following order: + are encoded in section <c>Pairs</c> in the following order: <c>K1, V1, K2, V2,..., Kn, Vn</c>. Duplicate keys are <em>not allowed</em> within the same map. </p> - <p><em>Since: </em>OTP 17.0</p> + <p><em>As from </em>Erlang/OTP 17.0</p> </section> <section> <marker id="NIL_EXT"/> <title>NIL_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> </row> <row> - <cell align="center">106</cell> + <cell align="center"><c>106</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>NIL_EXT</tcaption></table> <p> - The representation for an empty list, i.e. the Erlang syntax <c>[]</c>. + The representation for an empty list, that is, the Erlang syntax + <c>[]</c>. </p> </section> <section> <marker id="STRING_EXT"/> <title>STRING_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -626,27 +578,25 @@ <cell align="center">Len</cell> </row> <row> - <cell align="center">107</cell> - <cell align="center">Length</cell> - <cell align="center">Characters</cell> + <cell align="center"><c>107</c></cell> + <cell align="center"><c>Length</c></cell> + <cell align="center"><c>Characters</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>STRING_EXT</tcaption></table> <p> - String does NOT have a corresponding Erlang representation, + String does <em>not</em> have a corresponding Erlang representation, but is an optimization for sending lists of bytes (integer in the range 0-255) more efficiently over the distribution. - Since the <c>Length</c> field is an unsigned 2 byte integer - (big endian), implementations must make sure that lists longer than - 65535 elements are encoded as - <seealso marker="#LIST_EXT">LIST_EXT</seealso>. + As field <c>Length</c> is an unsigned 2 byte integer + (big-endian), implementations must ensure that lists longer than + 65535 elements are encoded as + <seealso marker="#LIST_EXT"><c>LIST_EXT</c></seealso>. </p> - </section> <section> <marker id="LIST_EXT"/> <title>LIST_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -655,27 +605,24 @@ <cell align="center"> </cell> </row> <row> - <cell align="center">108</cell> - <cell align="center">Length</cell> - <cell align="center">Elements</cell> - <cell align="center">Tail</cell> + <cell align="center"><c>108</c></cell> + <cell align="center"><c>Length</c></cell> + <cell align="center"><c>Elements</c></cell> + <cell align="center"><c>Tail</c></cell> </row> - <tcaption></tcaption></table> - + <tcaption>LIST_EXT</tcaption></table> <p> - <c>Length</c> is the number of elements that follows in the - <c>Elements</c> section. <c>Tail</c> is the final tail of - the list; it is - <seealso marker="#NIL_EXT">NIL_EXT</seealso> - for a proper list, but may be anything type if the list is - improper (for instance <c>[a|b]</c>). + <c>Length</c> is the number of elements that follows in section + <c>Elements</c>. <c>Tail</c> is the final tail of the list; it is + <seealso marker="#NIL_EXT"><c>NIL_EXT</c></seealso> + for a proper list, but can be any type if the list is + improper (for example, <c>[a|b]</c>). </p> </section> <section> <marker id="BINARY_EXT"/> <title>BINARY_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -683,25 +630,26 @@ <cell align="center">Len</cell> </row> <row> - <cell align="center">109</cell> - <cell align="center">Len</cell> - <cell align="center">Data</cell> + <cell align="center"><c>109</c></cell> + <cell align="center"><c>Len</c></cell> + <cell align="center"><c>Data</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>BINARY_EXT</tcaption></table> <p> Binaries are generated with bit syntax expression or with - <seealso marker="erts:erlang#list_to_binary/1">list_to_binary/1</seealso>, - <seealso marker="erts:erlang#term_to_binary/1">term_to_binary/1</seealso>, + <seealso marker="erts:erlang#list_to_binary/1"> + <c>erlang:list_to_binary/1</c></seealso>, + <seealso marker="erts:erlang#term_to_binary/1"> + <c>erlang:term_to_binary/1</c></seealso>, or as input from binary ports. - The <c>Len</c> length field is an unsigned 4 byte integer - (big endian). + The <c>Len</c> length field is an unsigned 4 byte integer + (big-endian). </p> </section> <section> <marker id="SMALL_BIG_EXT"/> <title>SMALL_BIG_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -710,27 +658,26 @@ <cell align="center">n</cell> </row> <row> - <cell align="center">110</cell> - <cell align="center">n</cell> - <cell align="center">Sign</cell> - <cell align="center">d(0) ... d(n-1)</cell> + <cell align="center"><c>110</c></cell> + <cell align="center"><c>n</c></cell> + <cell align="center"><c>Sign</c></cell> + <cell align="center"><c>d(0)</c> ... <c>d(n-1)</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>SMALL_BIG_EXT</tcaption></table> <p> - Bignums are stored in unary form with a <c>Sign</c> byte - that is 0 if the binum is positive and 1 if is negative. The - digits are stored with the LSB byte stored first. To - calculate the integer the following formula can be used:<br/> - - B = 256<br/> - (d0*B^0 + d1*B^1 + d2*B^2 + ... d(N-1)*B^(n-1)) + Bignums are stored in unary form with a <c>Sign</c> byte, + that is, 0 if the binum is positive and 1 if it is negative. The + digits are stored with the least significant byte stored first. To + calculate the integer, the following formula can be used: + </p> + <p><c>B</c> = 256<br/> + <c>(d0*B^0 + d1*B^1 + d2*B^2 + ... d(N-1)*B^(n-1))</c> </p> </section> <section> <marker id="LARGE_BIG_EXT"/> <title>LARGE_BIG_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -739,24 +686,22 @@ <cell align="center">n</cell> </row> <row> - <cell align="center">111</cell> - <cell align="center">n</cell> - <cell align="center">Sign</cell> - <cell align="center">d(0) ... d(n-1)</cell> + <cell align="center"><c>111</c></cell> + <cell align="center"><c>n</c></cell> + <cell align="center"><c>Sign</c></cell> + <cell align="center"><c>d(0)</c> ... <c>d(n-1)</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>LARGE_BIG_EXT</tcaption></table> <p> - Same as <seealso marker="#SMALL_BIG_EXT">SMALL_BIG_EXT</seealso> - with the difference that the length field - is an unsigned 4 byte integer. + Same as <seealso marker="#SMALL_BIG_EXT"> + <c>SMALL_BIG_EXT</c></seealso> + except that the length field is an unsigned 4 byte integer. </p> - </section> <section> <marker id="NEW_REFERENCE_EXT"/> <title>NEW_REFERENCE_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -766,73 +711,43 @@ <cell align="center">N'</cell> </row> <row> - <cell align="center">114</cell> - <cell align="center">Len</cell> - <cell align="center">Node</cell> - <cell align="center">Creation</cell> - <cell align="center">ID ...</cell> + <cell align="center"><c>114</c></cell> + <cell align="center"><c>Len</c></cell> + <cell align="center"><c>Node</c></cell> + <cell align="center"><c>Creation</c></cell> + <cell align="center"><c>ID ...</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>NEW_REFERENCE_EXT</tcaption></table> <p> - Node and Creation are as in - <seealso marker="#REFERENCE_EXT">REFERENCE_EXT</seealso>. + <c>Node</c> and <c>Creation</c> are as in + <seealso marker="#REFERENCE_EXT"><c>REFERENCE_EXT</c></seealso>. </p> <p> - <c>ID</c> contains a sequence of big-endian unsigned integers - (4 bytes each, so <c>N'</c> is a multiple of 4), - but should be regarded as uninterpreted data. + <c>ID</c> contains a sequence of big-endian unsigned integers + (4 bytes each, so <c>N'</c> is a multiple of 4), + but is to be regarded as uninterpreted data. </p> <p> <c>N'</c> = 4 * <c>Len</c>. </p> <p> - In the first word (four bytes) of <c>ID</c>, only 18 bits are - significant, the rest should be 0. - In <c>Creation</c>, only 2 bits are significant, - the rest should be 0. + In the first word (4 bytes) of <c>ID</c>, only 18 bits are + significant, the rest are to be 0. + In <c>Creation</c>, only two bits are significant, + the rest are to be 0. </p> <p> - NEW_REFERENCE_EXT was introduced with distribution version 4. - In version 4, <c>N'</c> should be at most 12. + <c>NEW_REFERENCE_EXT</c> was introduced with distribution version 4. + In version 4, <c>N'</c> is to be at most 12. </p> <p> - See <seealso marker="#REFERENCE_EXT">REFERENCE_EXT</seealso>). + See <seealso marker="#REFERENCE_EXT"><c>REFERENCE_EXT</c></seealso>. </p> </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></tcaption></table> - <p> - An atom is stored with a 1 byte unsigned length, - followed by <c>Len</c> numbers of 8 bit Latin1 characters that - forms the <c>AtomName</c>. Longer atoms can be represented - by <seealso marker="#ATOM_EXT">ATOM_EXT</seealso>. <em>Note</em> - the <c>SMALL_ATOM_EXT</c> was introduced in erts version 5.7.2 and - require an exchange of the - <seealso marker="erl_dist_protocol#dflags"><c>DFLAG_SMALL_ATOM_TAGS</c></seealso> - distribution flag in the - <seealso marker="erl_dist_protocol#distribution_handshake">distribution handshake</seealso>. - </p> - </section> - - <section> <marker id="FUN_EXT"/> <title>FUN_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -844,48 +759,56 @@ <cell align="center">N5</cell> </row> <row> - <cell align="center">117</cell> - <cell align="center">NumFree</cell> - <cell align="center">Pid</cell> - <cell align="center">Module</cell> - <cell align="center">Index</cell> - <cell align="center">Uniq</cell> - <cell align="center">Free vars ...</cell> + <cell align="center"><c>117</c></cell> + <cell align="center"><c>NumFree</c></cell> + <cell align="center"><c>Pid</c></cell> + <cell align="center"><c>Module</c></cell> + <cell align="center"><c>Index</c></cell> + <cell align="center"><c>Uniq</c></cell> + <cell align="center"><c>Free vars ...</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>FUN_EXT</tcaption></table> <taglist> - <tag><c>Pid</c></tag> + <tag><c>Pid</c></tag> <item> - is a process identifier as in - <seealso marker="#PID_EXT">PID_EXT</seealso>. - It represents the process in which the fun was created. + <p>A process identifier as in + <seealso marker="#PID_EXT"><c>PID_EXT</c></seealso>. + Represents the process in which the fun was created. + </p> </item> <tag><c>Module</c></tag> <item> - is an encoded as an atom, using - <seealso marker="#ATOM_EXT">ATOM_EXT</seealso>, - <seealso marker="#SMALL_ATOM_EXT">SMALL_ATOM_EXT</seealso> - or <seealso marker="#ATOM_CACHE_REF">ATOM_CACHE_REF</seealso>. - This is the module that the fun is implemented in. + <p>Encoded as an atom, using + <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. + </p> </item> <tag><c>Index</c></tag> <item> - is an integer encoded using - <seealso marker="#SMALL_INTEGER_EXT">SMALL_INTEGER_EXT</seealso> - or <seealso marker="#INTEGER_EXT">INTEGER_EXT</seealso>. - It is typically a small index into the module's fun table. + <p>An integer encoded using + <seealso marker="#SMALL_INTEGER_EXT"> + <c>SMALL_INTEGER_EXT</c></seealso> + or <seealso marker="#INTEGER_EXT"><c>INTEGER_EXT</c></seealso>. + It is typically a small index into the module's fun table. + </p> </item> <tag><c>Uniq</c></tag> <item> - is an integer encoded using - <seealso marker="#SMALL_INTEGER_EXT">SMALL_INTEGER_EXT</seealso> or - <seealso marker="#INTEGER_EXT">INTEGER_EXT</seealso>. - <c>Uniq</c> is the hash value of the parse for the fun. + <p>An integer encoded using + <seealso marker="#SMALL_INTEGER_EXT"> + <c>SMALL_INTEGER_EXT</c></seealso> or + <seealso marker="#INTEGER_EXT"><c>INTEGER_EXT</c></seealso>. + <c>Uniq</c> is the hash value of the parse for the fun. + </p> </item> <tag><c>Free vars</c></tag> <item> - is <c>NumFree</c> number of terms, each one encoded according - to its type. + <p><c>NumFree</c> number of terms, each one encoded according + to its type. + </p> </item> </taglist> </section> @@ -893,7 +816,6 @@ <section> <marker id="NEW_FUN_EXT"/> <title>NEW_FUN_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -909,19 +831,19 @@ <cell align="center">N5</cell> </row> <row> - <cell align="center">112</cell> - <cell align="center">Size</cell> - <cell align="center">Arity</cell> - <cell align="center">Uniq</cell> - <cell align="center">Index</cell> - <cell align="center">NumFree</cell> - <cell align="center">Module</cell> - <cell align="center">OldIndex</cell> - <cell align="center">OldUniq</cell> - <cell align="center">Pid</cell> - <cell align="center">Free Vars</cell> + <cell align="center"><c>112</c></cell> + <cell align="center"><c>Size</c></cell> + <cell align="center"><c>Arity</c></cell> + <cell align="center"><c>Uniq</c></cell> + <cell align="center"><c>Index</c></cell> + <cell align="center"><c>NumFree</c></cell> + <cell align="center"><c>Module</c></cell> + <cell align="center"><c>OldIndex</c></cell> + <cell align="center"><c>OldUniq</c></cell> + <cell align="center"><c>Pid</c></cell> + <cell align="center"><c>Free Vars</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>NEW_FUN_EXT</tcaption></table> <p> This is the new encoding of internal funs: <c>fun F/A</c> and <c>fun(Arg1,..) -> ... end</c>. @@ -929,68 +851,73 @@ <taglist> <tag><c>Size</c></tag> <item> - is the total number of bytes, including the <c>Size</c> field. + <p>The total number of bytes, including field <c>Size</c>.</p> </item> <tag><c>Arity</c></tag> <item> - is the arity of the function implementing the fun. + <p>The arity of the function implementing the fun.</p> </item> <tag><c>Uniq</c></tag> <item> - is the 16 bytes MD5 of the significant parts of the Beam file. + <p>The 16 bytes MD5 of the significant parts of the Beam file.</p> </item> <tag><c>Index</c></tag> <item> - is an index number. Each fun within a module has an unique - index. <c>Index</c> is stored in big-endian byte order. + <p>An index number. Each fun within a module has an unique + index. <c>Index</c> is stored in big-endian byte order. + </p> </item> <tag><c>NumFree</c></tag> <item> - is the number of free variables. + <p>The number of free variables.</p> </item> <tag><c>Module</c></tag> <item> - is an encoded as an atom, using - <seealso marker="#ATOM_EXT">ATOM_EXT</seealso>, - <seealso marker="#SMALL_ATOM_EXT">SMALL_ATOM_EXT</seealso> or - <seealso marker="#ATOM_CACHE_REF">ATOM_CACHE_REF</seealso>. - This is the module that the fun is implemented in. + <p>Encoded as an atom, 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>. + Is the module that the fun is implemented in. + </p> </item> <tag><c>OldIndex</c></tag> <item> - is an integer encoded using - <seealso marker="#SMALL_INTEGER_EXT">SMALL_INTEGER_EXT</seealso> - or <seealso marker="#INTEGER_EXT">INTEGER_EXT</seealso>. - It is typically a small index into the module's fun table. + <p>An integer encoded using + <seealso marker="#SMALL_INTEGER_EXT"> + <c>SMALL_INTEGER_EXT</c></seealso> or + <seealso marker="#INTEGER_EXT"><c>INTEGER_EXT</c></seealso>. + Is typically a small index into the module's fun table. + </p> </item> <tag><c>OldUniq</c></tag> <item> - is an integer encoded using - <seealso marker="#SMALL_INTEGER_EXT">SMALL_INTEGER_EXT</seealso> - or - <seealso marker="#INTEGER_EXT">INTEGER_EXT</seealso>. - <c>Uniq</c> is the hash value of the parse tree for the fun. + <p>An integer encoded using + <seealso marker="#SMALL_INTEGER_EXT"> + <c>SMALL_INTEGER_EXT</c></seealso> or + <seealso marker="#INTEGER_EXT"><c>INTEGER_EXT</c></seealso>. + <c>Uniq</c> is the hash value of the parse tree for the fun. + </p> </item> <tag><c>Pid</c></tag> <item> - is a process identifier as in - <seealso marker="#PID_EXT">PID_EXT</seealso>. - It represents the process in which - the fun was created. + <p>A process identifier as in + <seealso marker="#PID_EXT"><c>PID_EXT</c></seealso>. + Represents the process in which the fun was created. + </p> </item> - <tag><c>Free vars</c></tag> <item> - is <c>NumFree</c> number of terms, each one encoded according - to its type. + <p><c>NumFree</c> number of terms, each one encoded according + to its type. + </p> </item> </taglist> </section> <section> <marker id="EXPORT_EXT"/> - <title>EXPORT_EXT</title> - + <title>EXPORT_EXT</title> <table align="left"> <row> <cell align="center">1</cell> @@ -999,32 +926,31 @@ <cell align="center">N3</cell> </row> <row> - <cell align="center">113</cell> - <cell align="center">Module</cell> - <cell align="center">Function</cell> - <cell align="center">Arity</cell> + <cell align="center"><c>113</c></cell> + <cell align="center"><c>Module</c></cell> + <cell align="center"><c>Function</c></cell> + <cell align="center"><c>Arity</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>EXPORT_EXT</tcaption></table> <p> This term is the encoding for external funs: <c>fun M:F/A</c>. </p> <p> - <c>Module</c> and <c>Function</c> are atoms - (encoded using <seealso marker="#ATOM_EXT">ATOM_EXT</seealso>, - <seealso marker="#SMALL_ATOM_EXT">SMALL_ATOM_EXT</seealso> or - <seealso marker="#ATOM_CACHE_REF">ATOM_CACHE_REF</seealso>). + <c>Module</c> and <c>Function</c> are atoms + (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> - <c>Arity</c> is an integer encoded using - <seealso marker="#SMALL_INTEGER_EXT">SMALL_INTEGER_EXT</seealso>. + <c>Arity</c> is an integer encoded using + <seealso marker="#SMALL_INTEGER_EXT"> + <c>SMALL_INTEGER_EXT</c></seealso>. </p> - </section> <section> <marker id="BIT_BINARY_EXT"/> <title>BIT_BINARY_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -1033,39 +959,35 @@ <cell align="center">Len</cell> </row> <row> - <cell align="center">77</cell> - <cell align="center">Len</cell> - <cell align="center">Bits</cell> - <cell align="center">Data</cell> + <cell align="center"><c>77</c></cell> + <cell align="center"><c>Len</c></cell> + <cell align="center"><c>Bits</c></cell> + <cell align="center"><c>Data</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>BIT_BINARY_EXT</tcaption></table> <p> This term represents a bitstring whose length in bits does not have to be a multiple of 8. - The <c>Len</c> field is an unsigned 4 byte integer (big endian). + The <c>Len</c> field is an unsigned 4 byte integer (big-endian). The <c>Bits</c> field is the number of bits (1-8) that are used - in the last byte in the data field, - counting from the most significant bit towards the least - significant. + in the last byte in the data field, + counting from the most significant bit to the least significant. </p> - - </section> <section> <marker id="NEW_FLOAT_EXT"/> <title>NEW_FLOAT_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> <cell align="center">8</cell> </row> <row> - <cell align="center">70</cell> - <cell align="center">IEEE float</cell> + <cell align="center"><c>70</c></cell> + <cell align="center"><c>IEEE float</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>NEW_FLOAT_EXT</tcaption></table> <p> A float is stored as 8 bytes in big-endian IEEE format. </p> @@ -1073,10 +995,10 @@ This term is used in minor version 1 of the external format. </p> </section> + <section> <marker id="ATOM_UTF8_EXT"/> <title>ATOM_UTF8_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -1088,23 +1010,22 @@ <cell align="center"><c>Len</c></cell> <cell align="center"><c>AtomName</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>ATOM_UTF8_EXT</tcaption></table> <p> An atom is stored with a 2 byte unsigned length in big-endian order, followed by <c>Len</c> bytes containing the <c>AtomName</c> encoded in UTF-8. </p> <p> - For more information on encoding of atoms, see + For more information on encoding of atoms, see the <seealso marker="#utf8_atoms">note on UTF-8 encoded atoms</seealso> - in the beginning of this document. + in the beginning of this section. </p> </section> <section> <marker id="SMALL_ATOM_UTF8_EXT"/> <title>SMALL_ATOM_UTF8_EXT</title> - <table align="left"> <row> <cell align="center">1</cell> @@ -1116,20 +1037,74 @@ <cell align="center"><c>Len</c></cell> <cell align="center"><c>AtomName</c></cell> </row> - <tcaption></tcaption></table> + <tcaption>SMALL_ATOM_UTF8_EXT</tcaption></table> <p> - An atom is stored with a 1 byte unsigned length, + An atom is stored with a 1 byte unsigned length, followed by <c>Len</c> bytes containing the <c>AtomName</c> encoded in UTF-8. Longer atoms encoded in UTF-8 can be represented using - <seealso marker="#ATOM_UTF8_EXT">ATOM_UTF8_EXT</seealso>. + <seealso marker="#ATOM_UTF8_EXT"><c>ATOM_UTF8_EXT</c></seealso>. </p> <p> - For more information on encoding of atoms, see + For more information on encoding of atoms, see the <seealso marker="#utf8_atoms">note on UTF-8 encoded atoms</seealso> - in the beginning of this document. + 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 3de94be9ff..190ec12d0e 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -4,20 +4,21 @@ <cref> <header> <copyright> - <year>2001</year><year>2013</year> + <year>2001</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -32,73 +33,54 @@ <file>erl_nif.xml</file> </header> <lib>erl_nif</lib> - <libsummary>API functions for an Erlang NIF library</libsummary> + <libsummary>API functions for an Erlang NIF library.</libsummary> <description> <p>A NIF library contains native implementation of some functions - of an Erlang module. The native implemented functions (NIFs) are - called like any other functions without any difference to the - caller. Each NIF must also have an implementation in Erlang that - will be invoked if the function is called before the NIF library - has been successfully loaded. A typical such stub implementation - is to throw an exception. But it can also be used as a fallback - implementation if the NIF library is not implemented for some - architecture.</p> - <marker id="WARNING"/> - <warning><p><em>Use this functionality with extreme care!</em></p> + of an Erlang module. The native implemented functions (NIFs) are + called like any other functions without any difference to the + caller. Each NIF must have an implementation in Erlang that + is invoked if the function is called before the NIF library + is successfully loaded. A typical such stub implementation + is to throw an exception. But it can also be used as a fallback + implementation if the NIF library is not implemented for some + architecture.</p> + + <warning> + <marker id="WARNING"/> + <p><em>Use this functionality with extreme care.</em></p> <p>A native function is executed as a direct extension of the - native code of the VM. Execution is not made in a safe environment. - The VM can <em>not</em> provide the same services as provided when - executing Erlang code, such as preemptive scheduling or memory - protection. If the native function doesn't behave well, the whole - VM will misbehave.</p> - <list> - <item><p>A native function that crash will crash the whole VM.</p></item> - <item><p>An erroneously implemented native function might cause - a VM internal state inconsistency which may cause a crash of the VM, - or miscellaneous misbehaviors of the VM at any point after the call - to the native function.</p></item> - <item><p>A native function that do <seealso marker="#lengthy_work">lengthy - work</seealso> before returning will degrade responsiveness of the VM, - and may cause miscellaneous strange behaviors. Such strange behaviors - include, but are not limited to, extreme memory usage, and bad load - balancing between schedulers. Strange behaviors that might occur due - to lengthy work may also vary between OTP releases.</p></item> + native code of the VM. Execution is not made in a safe environment. + The VM <em>cannot</em> provide the same services as provided when + executing Erlang code, such as pre-emptive scheduling or memory + protection. If the native function does not behave well, the whole + VM will misbehave.</p> + <list type="bulleted"> + <item> + <p>A native function that crash will crash the whole VM.</p> + </item> + <item> + <p>An erroneously implemented native function can cause a VM + internal state inconsistency, which can cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the + call to the native function.</p> + </item> + <item> + <p>A native function doing <seealso marker="#lengthy_work">lengthy + work</seealso> before returning degrades responsiveness of the VM, + and can cause miscellaneous strange behaviors. Such strange + behaviors include, but are not limited to, extreme memory usage, + and bad load balancing between schedulers. Strange behaviors that + can occur because of lengthy work can also vary between Erlang/OTP + releases.</p> + </item> </list> - </warning> - - <p>The NIF concept is officially supported from R14B. NIF source code - written for earlier experimental versions might need adaption to run on R14B - or later versions:</p> - <list> - <item>No incompatible changes between <em>R14B</em> and R14A.</item> - <item>Incompatible changes between <em>R14A</em> and R13B04: - <list> - <item>Environment argument removed for <c>enif_alloc</c>, - <c>enif_realloc</c>, <c>enif_free</c>, <c>enif_alloc_binary</c>, - <c>enif_realloc_binary</c>, <c>enif_release_binary</c>, - <c>enif_alloc_resource</c>, <c>enif_release_resource</c>, - <c>enif_is_identical</c> and <c>enif_compare</c>.</item> - <item>Character encoding argument added to <c>enif_get_atom</c> - and <c>enif_make_existing_atom</c>.</item> - <item>Module argument added to <c>enif_open_resource_type</c> - while changing name spaces of resource types from global to module local.</item> - </list> - </item> - <item>Incompatible changes between <em>R13B04</em> and R13B03: - <list> - <item>The function prototypes of the NIFs have changed to expect <c>argc</c> and <c>argv</c> - arguments. The arity of a NIF is by that no longer limited to 3.</item> - <item><c>enif_get_data</c> renamed as <c>enif_priv_data</c>.</item> - <item><c>enif_make_string</c> got a third argument for character encoding.</item> - </list> - </item> - </list> - - <p>A minimal example of a NIF library can look like this:</p> - <p/> - <code type="none"> + </warning> + + <p>A minimal example of a NIF library can look as follows:</p> + + <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[]) { @@ -110,13 +92,11 @@ static ErlNifFunc nif_funcs[] = {"hello", 0, hello} }; -ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL) -</code> +ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)</code> - <p>and the Erlang module would have to look something like - this:</p> - <p/> - <code type="none"> + <p>The Erlang module can look as follows:</p> + + <code type="none"> -module(niftest). -export([init/0, hello/0]). @@ -125,11 +105,11 @@ init() -> erlang:load_nif("./niftest", 0). hello() -> - "NIF library not loaded". -</code> - <p>and compile and test something like this (on Linux):</p> - <p/> - <code type="none"> + "NIF library not loaded".</code> + + <p>Compile and test can look as follows (on Linux):</p> + + <code type="none"> $> gcc -fPIC -shared -o niftest.so niftest.c -I $ERL_ROOT/usr/include/ $> erl @@ -140,1216 +120,3356 @@ $> erl 3> niftest:init(). ok 4> niftest:hello(). -"Hello world!" -</code> +"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 + <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 + loaded.</p> - <p>A better solution for a real module is to take advantage of - the new directive <seealso - marker="doc/reference_manual:code_loading#on_load">on_load</seealso> to automatically - load the NIF library when the module is loaded.</p> - <note><p>A NIF does not have to be exported, it can be local to the module. - Note however that unused local stub functions will be optimized - away by the compiler causing loading of the NIF library to fail.</p> + <note> + <p>A NIF does not have to be exported, it can be local to the module. + However, unused local stub functions will be optimized + 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 will have to load its own NIF library (or maybe choose not - to). The new code version can however choose to load the exact - same NIF library as the old code if it wants to. Sharing the same - dynamic library will mean that static data defined by the library - will be 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">enif_priv_data</seealso>.</p> - <p>There is no way to explicitly unload a NIF library. A library will be - automatically unloaded when the module code that it belongs to is purged - by the code server.</p> - - <p><marker id="lengthy_work"/> - As mentioned in the <seealso marker="#WARNING">warning</seealso> text at - the beginning of this document it is of vital importance that a native function - return relatively quickly. It is hard to give an exact maximum amount - of time that a native function is allowed to work, but as a rule of thumb - a well-behaving native function should return to its caller before a - millisecond has passed. This can be achieved using different approaches. - If you have full control over the code to execute in the native - function, the best approach is to divide the work into multiple chunks of - work and call the native function multiple times, either directly from Erlang code - or by having a native function schedule a future NIF call via the - <seealso marker="#enif_schedule_nif"> enif_schedule_nif</seealso> function. Function - <seealso marker="#enif_consume_timeslice">enif_consume_timeslice</seealso> can be - used to help with such work division. In some cases, however, this might not - be possible, e.g. when calling third-party libraries. Then you typically want - to dispatch the work to another thread, return - from the native function, and wait for the result. The thread can send - the result back to the calling thread using message passing. Information - about thread primitives can be found below. If you have built your system - with <em>the currently experimental</em> support for dirty schedulers, - you may want to try out this functionality by dispatching the work to a - <seealso marker="#dirty_nifs">dirty NIF</seealso>, - which does not have the same duration restriction as a normal NIF.</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. There are functions + <title>Functionality</title> + <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> <tag>Read and write Erlang terms</tag> - <item><p>Any Erlang terms can be passed to a NIF as function arguments and - be returned as function return values. The terms are of C-type - <seealso marker="#ERL_NIF_TERM">ERL_NIF_TERM</seealso> - and can only be read or written using API functions. Most functions to read - the content of a term are prefixed <c>enif_get_</c> and usually return - true (or false) if the term was of the expected type (or not). - The functions to write terms are all prefixed <c>enif_make_</c> and usually - return the created <c>ERL_NIF_TERM</c>. There are also some functions - to query terms, like <c>enif_is_atom</c>, <c>enif_is_identical</c> and - <c>enif_compare</c>.</p> - <p>All terms of type <c>ERL_NIF_TERM</c> belong to an environment of type - <seealso marker="#ErlNifEnv">ErlNifEnv</seealso>. The lifetime of a term is - controlled by the lifetime of its environment object. All API functions that read - or write terms has the environment, that the term belongs to, as the first - function argument.</p></item> + <item> + <p>Any Erlang terms can be passed to a NIF as function arguments and + be returned as function return values. The terms are of C-type + <seealso marker="#ERL_NIF_TERM"><c>ERL_NIF_TERM</c></seealso> and can + only be read or written using API functions. Most functions to read + the content of a term are prefixed <c>enif_get_</c> and usually return + <c>true</c> (or <c>false</c>) if the term is of the expected type (or + not). The functions to write terms are all prefixed <c>enif_make_</c> + and usually + return the created <c>ERL_NIF_TERM</c>. There are also some functions + to query terms, like <c>enif_is_atom</c>, <c>enif_is_identical</c>, + and <c>enif_compare</c>.</p> + <p>All terms of type <c>ERL_NIF_TERM</c> belong to an environment of + type <seealso marker="#ErlNifEnv"><c>ErlNifEnv</c></seealso>. The + lifetime of a term is controlled by the lifetime of its environment + object. All API functions that read or write terms has the + environment that the term belongs to as the first function + argument.</p> + </item> <tag>Binaries</tag> - <item><p>Terms of type binary are accessed with the help of the struct type - <seealso marker="#ErlNifBinary">ErlNifBinary</seealso> - that contains a pointer (<c>data</c>) to the raw binary data and the length - (<c>size</c>) of the data in bytes. Both <c>data</c> and <c>size</c> are - read-only and should only be written using calls to API functions. - Instances of <c>ErlNifBinary</c> are however always allocated by the user - (usually as local variables).</p> - <p>The raw data pointed to by <c>data</c> is only mutable after a call to - <seealso marker="#enif_alloc_binary">enif_alloc_binary</seealso> or - <seealso marker="#enif_realloc_binary">enif_realloc_binary</seealso>. - All other functions that operates on a binary will leave the data as read-only. - A mutable binary must in the end either be freed with - <seealso marker="#enif_release_binary">enif_release_binary</seealso> - or made read-only by transferring it to an Erlang term with - <seealso marker="#enif_make_binary">enif_make_binary</seealso>. - But it does not have to happen in the same NIF call. Read-only binaries - do not have to be released.</p> - <p><seealso marker="#enif_make_new_binary">enif_make_new_binary</seealso> - can be used as a shortcut to allocate and return a binary in the same NIF call.</p> - <p>Binaries are sequences of whole bytes. Bitstrings with an arbitrary - bit length have no support yet.</p> - </item> - <tag>Resource objects</tag> - <item><p>The use of resource objects is a safe way to return pointers to - native data structures from a NIF. A resource object is - just a block of memory allocated with - <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>. - A handle ("safe pointer") to this memory block can then be returned to Erlang by the use of - <seealso marker="#enif_make_resource">enif_make_resource</seealso>. - The term returned by <c>enif_make_resource</c> - is totally opaque in nature. It can be stored and passed between processes - on the same node, but the only real end usage is to pass it back as an argument to a NIF. - The NIF can then call <seealso marker="#enif_get_resource">enif_get_resource</seealso> - and get back a pointer to the memory block that is guaranteed to still be - valid. A resource object will not be deallocated until the last handle term - has been garbage collected by the VM and the resource has been - released with <seealso marker="#enif_release_resource">enif_release_resource</seealso> - (not necessarily in that order).</p> - <p>All resource objects are created as instances of some <em>resource type</em>. - This makes resources from different modules to be distinguishable. - A resource type is created by calling - <seealso marker="#enif_open_resource_type">enif_open_resource_type</seealso> - when a library is loaded. Objects of that resource type can then later be allocated - and <c>enif_get_resource</c> verifies that the resource is of the expected type. - A resource type can have a user supplied destructor function that is - automatically called when resources of that type are released (by either - the garbage collector or <c>enif_release_resource</c>). Resource types - are uniquely identified by a supplied name string and the name of the - implementing module.</p> - <marker id="enif_resource_example"/><p>Here is a template example of how to create and return a resource object.</p> - <p/> - <code type="none"> - ERL_NIF_TERM term; - MyStruct* obj = enif_alloc_resource(my_resource_type, sizeof(MyStruct)); - - /* initialize struct ... */ - - term = enif_make_resource(env, obj); - - if (keep_a_reference_of_our_own) { - /* store 'obj' in static variable, private data or other resource object */ - } - else { - enif_release_resource(obj); - /* resource now only owned by "Erlang" */ - } - return term; - </code> - <p>Note that once <c>enif_make_resource</c> creates the term to - return to Erlang, the code can choose to either keep its own - native pointer to the allocated struct and release it later, or - release it immediately and rely solely on the garbage collector - to eventually deallocate the resource object when it collects - the term.</p> - <p>Another usage of resource objects is to create binary terms with - user defined memory management. - <seealso marker="#enif_make_resource_binary">enif_make_resource_binary</seealso> - will create a binary term that is connected to a resource object. The - destructor of the resource will be called when the binary is garbage - collected, at which time the binary data can be released. An example of - this can be a binary term consisting of data from a <c>mmap</c>'ed file. - The destructor can then do <c>munmap</c> to release the memory - region.</p> - <p>Resource types support upgrade in runtime by allowing a loaded NIF - library to takeover an already existing resource type and thereby - "inherit" all existing objects of that type. The destructor of the new - library will thereafter be called for the inherited objects and the - library with the old destructor function can be safely unloaded. Existing - resource objects, of a module that is upgraded, must either be deleted - or taken over by the new NIF library. The unloading of a library will be - postponed as long as there exist resource objects with a destructor - function in the library. - </p> + <item> + <p>Terms of type binary are accessed with the help of struct type + <seealso marker="#ErlNifBinary"><c>ErlNifBinary</c></seealso>, + which contains a pointer (<c>data</c>) to the raw binary data and the + length (<c>size</c>) of the data in bytes. Both <c>data</c> and + <c>size</c> are read-only and are only to be written using calls to + API functions. Instances of <c>ErlNifBinary</c> are, however, always + allocated by the user (usually as local variables).</p> + <p>The raw data pointed to by <c>data</c> is only mutable after a call + to <seealso marker="#enif_alloc_binary"> + <c>enif_alloc_binary</c></seealso> or + <seealso marker="#enif_realloc_binary"> + <c>enif_realloc_binary</c></seealso>. All other functions that + operate on a binary leave the data as read-only. + A mutable binary must in the end either be freed with + <seealso marker="#enif_release_binary"> + <c>enif_release_binary</c></seealso> + or made read-only by transferring it to an Erlang term with + <seealso marker="#enif_make_binary"><c>enif_make_binary</c></seealso>. + However, it does not have to occur in the same NIF call. Read-only + binaries do not have to be released.</p> + <p><seealso marker="#enif_make_new_binary"> + <c>enif_make_new_binary</c></seealso> can be used as a shortcut to + allocate and return a binary in the same NIF call.</p> + <p>Binaries are sequences of whole bytes. Bitstrings with an arbitrary + bit length have no support yet.</p> + </item> + <tag><marker id="resource_objects"/>Resource objects</tag> + <item> + <p>The use of resource objects is a safe way to return pointers to + native data structures from a NIF. A resource object is + only a block of memory allocated with + <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>. + A handle ("safe pointer") to this memory block can then be returned + to Erlang by the use of + <seealso marker="#enif_make_resource"> + <c>enif_make_resource</c></seealso>. + The term returned by <c>enif_make_resource</c> is opaque in nature. + It can be stored and passed between processes, but + the only real end usage is to pass it back as an argument to a NIF. + The NIF can then call <seealso marker="#enif_get_resource"> + <c>enif_get_resource</c></seealso> and get back a pointer to the + memory block, which is guaranteed to still be valid. A resource + object is not deallocated until the last handle term + is garbage collected by the VM and the resource is released with + <seealso marker="#enif_release_resource"> + <c>enif_release_resource</c></seealso> + (not necessarily in that order).</p> + <p>All resource objects are created as instances of some <em>resource + type</em>. This makes resources from different modules to be + distinguishable. A resource type is created by calling + <seealso marker="#enif_open_resource_type"> + <c>enif_open_resource_type</c></seealso> when a library is loaded. + Objects of that resource type can then later be allocated and + <c>enif_get_resource</c> verifies that the resource is of the + expected type. A resource type can have a user-supplied destructor + function, which is automatically called when resources of that type + are released (by either the garbage collector or + <c>enif_release_resource</c>). Resource types are uniquely identified + by a supplied name string and the name of the implementing module.</p> + <marker id="enif_resource_example"/> + <p>The following is a template example of how to create and return a + resource object.</p> + <code type="none"> +ERL_NIF_TERM term; +MyStruct* obj = enif_alloc_resource(my_resource_type, sizeof(MyStruct)); + +/* initialize struct ... */ + +term = enif_make_resource(env, obj); + +if (keep_a_reference_of_our_own) { + /* store 'obj' in static variable, private data or other resource object */ +} +else { + enif_release_resource(obj); + /* resource now only owned by "Erlang" */ +} +return term;</code> + <p>Notice that once <c>enif_make_resource</c> creates the term to + return to Erlang, the code can choose to either keep its own + native pointer to the allocated struct and release it later, or + release it immediately and rely only on the garbage collector + to deallocate the resource object eventually when it collects + the term.</p> + <p>Another use of resource objects is to create binary terms with + user-defined memory management. + <seealso marker="#enif_make_resource_binary"> + <c>enif_make_resource_binary</c></seealso> + creates a binary term that is connected to a resource object. The + destructor of the resource is called when the binary is garbage + collected, at which time the binary data can be released. An example + of this can be a binary term consisting of data from a <c>mmap</c>'ed + file. The destructor can then do <c>munmap</c> to release the memory + region.</p> + <p>Resource types support upgrade in runtime by allowing a loaded NIF + library to take over an already existing resource type and by that + "inherit" all existing objects of that type. The destructor of the + new library is thereafter called for the inherited objects and the + library with the old destructor function can be safely unloaded. + Existing resource objects, of a module that is upgraded, must either + be deleted or taken over by the new NIF library. The unloading of a + 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 - long as it acts as a pure function and only reads the supplied - arguments. As soon as you write towards a shared state either through - static variables or <seealso marker="#enif_priv_data">enif_priv_data</seealso> - you need to supply your own explicit synchronization. This includes terms - in process independent environments that are shared between threads. - Resource objects will 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> + <item> + <p>A NIF is thread-safe without any explicit synchronization as + long as it acts as a pure function and only reads the supplied + arguments. When you write to a shared state either through + static variables or <seealso marker="#enif_priv_data"> + <c>enif_priv_data</c></seealso>, you need to supply your own explicit + 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> and + <c>upgrade</c> are thread-safe even for shared state data.</p> </item> - <tag><marker id="version_management"/>Version Management</tag> - <item><p> - When a NIF library is built, information about NIF API version - is compiled into the library. When a NIF library is loaded the - runtime system verifies that the library is of a compatible version. - <c>erl_nif.h</c> defines <c>ERL_NIF_MAJOR_VERSION</c>, and - <c>ERL_NIF_MINOR_VERSION</c>. <c>ERL_NIF_MAJOR_VERSION</c> will be - incremented when NIF library incompatible changes are made to the - Erlang runtime system. Normally it will suffice to recompile the NIF - library when the <c>ERL_NIF_MAJOR_VERSION</c> has changed, but it - could, under rare circumstances, mean that NIF libraries have to - be slightly modified. If so, this will of course be documented. - <c>ERL_NIF_MINOR_VERSION</c> will be incremented when - new features are added. The runtime system uses the minor version - to determine what features to use. - </p><p> - The runtime system will normally refuse to load a NIF library if - the major versions differ, or if the major versions are equal and - the minor version used by the NIF library is greater than the one - used by the runtime system. Old NIF libraries with lower major - versions will however be allowed after a bump of the major version - during a transition period of two major releases. Such old NIF - libraries might however fail if deprecated features are used. - </p></item> - - <tag>Long-running NIFs</tag> - <item><p><marker id="dirty_nifs"/>Native functions - <seealso marker="#lengthy_work"> - must normally run quickly</seealso>, as explained earlier in this document. They - generally should execute for no more than a millisecond. But not all native functions - can execute so quickly; for example, functions that encrypt large blocks of data or - perform lengthy file system operations can often run for tens of seconds or more.</p> - <p>If the functionality of a long-running NIF can be split so that its work can be - achieved through a series of shorter NIF calls, the application can either make that series - of NIF calls from the Erlang level, or it can call a NIF that first performs a chunk of the - work, then invokes the <seealso marker="#enif_schedule_nif">enif_schedule_nif</seealso> - function to schedule another NIF call to perform the next chunk. The final call scheduled - in this manner can then return the overall result. Breaking up a long-running function in - this manner enables the VM to regain control between calls to the NIFs, thereby avoiding - degraded responsiveness, scheduler load balancing problems, and other strange behaviours.</p> - <p>A NIF that cannot be split and cannot execute in a millisecond or less is called a "dirty NIF" - because it performs work that the Erlang runtime cannot handle cleanly. - <em>Note that the dirty NIF functionality described here is experimental</em> and that you have to - enable support for dirty schedulers when building OTP in order to try the functionality out. - Applications that make use of such functions must indicate to the runtime that the functions are - dirty so they can be handled specially. To schedule a dirty NIF for execution, the - appropriate flags value can be set for the NIF in its <seealso marker="#ErlNifFunc">ErlNifFunc</seealso> - entry, or the application can call <seealso marker="#enif_schedule_nif">enif_schedule_nif</seealso>, - passing to it a pointer to the dirty NIF to be executed and indicating with the <c>flags</c> - argument whether it expects the operation to be CPU-bound or I/O-bound.</p> - <note><p>Dirty NIF support is available only when the emulator is configured with dirty - schedulers enabled. This feature is currently disabled by default. To determine whether - the dirty NIF API is available, native code can check to see if the C preprocessor macro - <c>ERL_NIF_DIRTY_SCHEDULER_SUPPORT</c> is defined. Also, if the Erlang runtime was built - without threading support, dirty schedulers are disabled. 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> + <item> + <p>When a NIF library is built, information about the NIF API version + is compiled into the library. When a NIF library is loaded, the + runtime system verifies that the library is of a compatible version. + <c>erl_nif.h</c> defines the following:</p> + <taglist> + <tag><c>ERL_NIF_MAJOR_VERSION</c></tag> + <item> + <p>Incremented when NIF library incompatible changes are made to the + Erlang runtime system. Normally it suffices to recompile the NIF + library when the <c>ERL_NIF_MAJOR_VERSION</c> has changed, but it + can, under rare circumstances, mean that NIF libraries must be + slightly modified. If so, this will of course be documented.</p> + </item> + <tag><c>ERL_NIF_MINOR_VERSION</c></tag> + <item> + <p>Incremented when new features are added. The runtime system uses + the minor version to determine what features to use.</p> + </item> + </taglist> + <p>The runtime system normally refuses to load a NIF library if + the major versions differ, or if the major versions are equal and + the minor version used by the NIF library is greater than the one + used by the runtime system. Old NIF libraries with lower major + versions are, however, allowed after a bump of the major version + during a transition period of two major releases. Such old NIF + libraries can however fail if deprecated features are used.</p> + </item> + <tag><marker id="time_measurement"/>Time Measurement</tag> + <item> + <p>Support for time measurement in NIF libraries:</p> + <list type="bulleted"> + <item><seealso marker="#ErlNifTime"> + <c>ErlNifTime</c></seealso></item> + <item><seealso marker="#ErlNifTimeUnit"> + <c>ErlNifTimeUnit</c></seealso></item> + <item><seealso marker="#enif_monotonic_time"> + <c>enif_monotonic_time()</c></seealso></item> + <item><seealso marker="#enif_time_offset"> + <c>enif_time_offset()</c></seealso></item> + <item><seealso marker="#enif_convert_time_unit"> + <c>enif_convert_time_unit()</c></seealso></item> + </list> + </item> + <tag><marker id="enif_ioq"/>I/O Queues</tag> + <item> + <p>The Erlang nif library contains function for easily working + with I/O vectors as used by the unix system call <c>writev</c>. + The I/O Queue is not thread safe, so some other synchronization + mechanism has to be used.</p> + <list type="bulleted"> + <item><seealso marker="#SysIOVec"> + <c>SysIOVec</c></seealso></item> + <item><seealso marker="#ErlNifIOVec"> + <c>ErlNifIOVec</c></seealso></item> + <item><seealso marker="#enif_ioq_create"> + <c>enif_ioq_create()</c></seealso></item> + <item><seealso marker="#enif_ioq_destroy"> + <c>enif_ioq_destroy()</c></seealso></item> + <item><seealso marker="#enif_ioq_enq_binary"> + <c>enif_ioq_enq_binary()</c></seealso></item> + <item><seealso marker="#enif_ioq_enqv"> + <c>enif_ioq_enqv()</c></seealso></item> + <item><seealso marker="#enif_ioq_deq"> + <c>enif_ioq_deq()</c></seealso></item> + <item><seealso marker="#enif_ioq_peek"> + <c>enif_ioq_peek()</c></seealso></item> + <item><seealso marker="#enif_ioq_peek_head"> + <c>enif_ioq_peek_head()</c></seealso></item> + <item><seealso marker="#enif_inspect_iovec"> + <c>enif_inspect_iovec()</c></seealso></item> + <item><seealso marker="#enif_free_iovec"> + <c>enif_free_iovec()</c></seealso></item> + </list> + <p>Typical usage when writing to a file descriptor looks like this:</p> + <code type="none"><![CDATA[ +int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail, + ErlNifIOQueue *q, int fd) { + + ErlNifIOVec vec, *iovec = &vec; + SysIOVec *sysiovec; + int saved_errno; + int iovcnt, n; + + if (!enif_inspect_iovec(env, 64, term, tail, &iovec)) + return -2; + + if (enif_ioq_size(q) > 0) { + /* If the I/O queue contains data we enqueue the iovec and + then peek the data to write out of the queue. */ + if (!enif_ioq_enqv(q, iovec, 0)) + return -3; + + sysiovec = enif_ioq_peek(q, &iovcnt); + } else { + /* If the I/O queue is empty we skip the trip through it. */ + iovcnt = iovec->iovcnt; + sysiovec = iovec->iov; + } + + /* Attempt to write the data */ + n = writev(fd, sysiovec, iovcnt); + saved_errno = errno; + + if (enif_ioq_size(q) == 0) { + /* If the I/O queue was initially empty we enqueue any + remaining data into the queue for writing later. */ + if (n >= 0 && !enif_ioq_enqv(q, iovec, n)) + return -3; + } else { + /* Dequeue any data that was written from the queue. */ + if (n > 0 && !enif_ioq_deq(q, n, NULL)) + return -4; + } + + /* return n, which is either number of bytes written or -1 if + some error happened */ + errno = saved_errno; + return n; +}]]></code> + </item> + <tag><marker id="lengthy_work"/>Long-running NIFs</tag> + <item> + <p>As mentioned in the <seealso marker="#WARNING">warning</seealso> text + at the beginning of this manual page, it is of <em>vital + importance</em> that a native function returns relatively fast. It is + difficult to give an exact maximum amount of time that a native + function is allowed to work, but usually a well-behaving native + function is to return to its caller within 1 millisecond. This can be + achieved using different approaches. If you have full control over the + code to execute in the native function, the best approach is to + divide the work into multiple chunks of work and call the native + function multiple times. This is, however, not always possible, for + example when calling third-party libraries.</p> + <p>The <seealso marker="#enif_consume_timeslice"> + <c>enif_consume_timeslice()</c></seealso> function can be used to + inform the runtime system about the length of the NIF call. + It is typically always to be used unless the NIF executes very + fast.</p> + <p>If the NIF call is too lengthy, this must be handled in one of + the following ways to avoid degraded responsiveness, scheduler load + balancing problems, and other strange behaviors:</p> + <taglist> + <tag>Yielding NIF</tag> + <item> + <p>If the functionality of a long-running NIF can be split so that + its work can be achieved through a series of shorter NIF calls, + the application has two options:</p> + <list type="bulleted"> + <item> + <p>Make that series of NIF calls from the Erlang level.</p> + </item> + <item> + <p>Call a NIF that first performs a chunk of the work, then + invokes the <seealso marker="#enif_schedule_nif"> + <c>enif_schedule_nif</c></seealso> function to schedule + another NIF call to perform the next chunk. The final call + scheduled in this manner can then return the overall + result.</p> + </item> + </list> + <p>Breaking up a long-running function in this manner enables the + VM to regain control between calls to the NIFs.</p> + <p>This approach is always preferred over the other alternatives + described below. This both from a performance perspective and + a system characteristics perspective.</p> + </item> + <tag>Threaded NIF</tag> + <item> + <p>This is accomplished by dispatching the work to another thread + managed by the NIF library, return from the NIF, and wait for + the result. The thread can send the result back to the Erlang + process using <seealso marker="#enif_send"> + <c>enif_send</c></seealso>. + Information about thread primitives is provided below.</p> + </item> + <tag><marker id="dirty_nifs"/>Dirty NIF</tag> + <item> + <note> + <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 + or less is called a "dirty NIF", as it performs work that the + ordinary schedulers of the Erlang runtime system cannot handle cleanly. + Applications that make use of such functions must indicate to the + runtime that the functions are dirty so they can be handled + specially. This is handled by executing dirty jobs on a separate + set of schedulers called dirty schedulers. A dirty NIF executing + on a dirty scheduler does not have the same duration restriction + as a normal NIF. + </p> + + <p> + It is important to classify the dirty job correct. An I/O bound + job should be classified as such, and a CPU bound job should be + classified as such. If you should classify CPU bound jobs + as I/O bound jobs, dirty I/O schedulers might starve ordinary + schedulers. I/O bound jobs are expected to either block waiting + for I/O, and/or spend a limited amount of time moving data. + </p> + + <p> + To schedule a dirty NIF for execution, the application has two options:</p> + <list type="bulleted"> + <item> + <p>Set the appropriate flags value for the dirty NIF in its + <seealso marker="#ErlNifFunc"> <c>ErlNifFunc</c></seealso> + entry.</p> + </item> + <item> + <p>Call <seealso marker="#enif_schedule_nif"> + <c>enif_schedule_nif</c></seealso>, pass to it a pointer + to the dirty NIF to be executed, and indicate with argument + <c>flags</c> whether it expects the operation to be CPU-bound + or I/O-bound.</p> + </item> + </list> + <p>A job that alternates between I/O bound and CPU bound can be + reclassified and rescheduled using <c>enif_schedule_nif</c> so + that it executes on the correct type of dirty scheduler at all + times. For more information see the documentation of the + <c>erl(1)</c> command line arguments + <seealso marker="erl#+SDcpu"><c>+SDcpu</c></seealso>, + and <seealso marker="erl#+SDio"><c>+SDio</c></seealso>.</p> + <p>While a process executes a dirty NIF, some operations that + communicate with it can take a very long time to complete. + Suspend or garbage collection of a process executing a dirty + NIF cannot be done until the dirty NIF has returned. Thus, other + processes waiting for such operations to complete might + have to wait for a very long time. Blocking multi-scheduling, that + is, calling <seealso marker="erlang#system_flag_multi_scheduling"> + <c>erlang:system_flag(multi_scheduling, block)</c></seealso>, can + also take a very long time to complete. This is because all ongoing + dirty operations on all dirty schedulers must complete before + the block operation can complete.</p> + <p>Many operations communicating with a process executing a + dirty NIF can, however, complete while it executes the + dirty NIF. For example, retrieving information about it through + <seealso marker="erlang:process_info/1"> + <c>erlang:process_info</c></seealso>, setting its group leader, + register/unregister its name, and so on.</p> + <p>Termination of a process executing a dirty NIF can only be + completed up to a certain point while it executes the dirty NIF. + All Erlang resources, such as its registered name and its ETS + tables, are released. All links and monitors are triggered. The + execution of the NIF is, however, <em>not</em> stopped. The NIF + can safely continue execution, allocate heap memory, and so on, + but it is of course better to stop executing as soon as possible. + The NIF can check whether a current process is alive using + <seealso marker="#enif_is_current_process_alive"> + <c>enif_is_current_process_alive</c></seealso>. Communication + using <seealso marker="#enif_send"><c>enif_send</c></seealso> and + <seealso marker="#enif_port_command"> + <c>enif_port_command</c></seealso> is also dropped when the + sending process is not alive. Deallocation of certain internal + resources, such as process heap and process control block, is + delayed until the dirty NIF has completed.</p> + </item> + </taglist> </item> </taglist> </section> + <section> - <title>INITIALIZATION</title> + <title>Initialization</title> <taglist> - <tag><marker id="ERL_NIF_INIT"/>ERL_NIF_INIT(MODULE, ErlNifFunc funcs[], load, reload, upgrade, unload)</tag> - <item><p>This is the magic macro to initialize a NIF library. It - should be evaluated in global file scope.</p> - <p><c>MODULE</c> is the name of the Erlang module as an - identifier without string quotations. It will be stringified by - 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 - <c>upgrade</c> will be called to initialize the library. - <c>unload</c> is called to release the library. They are all - described individually below.</p> - <p>If compiling a nif for static inclusion via --enable-static-nifs you - have to define STATIC_ERLANG_NIF before the ERL_NIF_INIT declaration.</p> + <tag><marker id="ERL_NIF_INIT"/><c>ERL_NIF_INIT(MODULE, + 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> + <p><c>MODULE</c> is the name of the Erlang module as an + identifier without string quotations. It is stringified by + 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>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 deprecated <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> </item> - - <tag><marker id="load"/>int (*load)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)</tag> - <item><p><c>load</c> is called when the NIF library is loaded - and there is no previously loaded library for this module.</p> + <tag><marker id="load"/><c>int (*load)(ErlNifEnv* env, void** priv_data, + ERL_NIF_TERM load_info)</c></tag> + <item> + <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 in order to keep a state between NIF - calls. <c>enif_priv_data</c> will return this pointer. - <c>*priv_data</c> will be initialized to NULL when <c>load</c> is - called.</p> + 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> <p><c>load_info</c> is the second argument to <seealso - marker="erlang#load_nif-2">erlang:load_nif/2</seealso>.</p> - <p>The library will fail to load if <c>load</c> returns - anything other than 0. <c>load</c> can be NULL in case no - initialization is needed.</p> - </item> - - <tag><marker id="upgrade"/>int (*upgrade)(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info)</tag> - <item><p><c>upgrade</c> is called when the NIF library is loaded - and there is old code of this module with a loaded NIF library.</p> - <p>Works the same as <c>load</c>. The only difference is 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> will be initialized to NULL when <c>upgrade</c> - is called. It is allowed to write to both *priv_data and *old_priv_data.</p> - <p>The library will fail to load if <c>upgrade</c> returns - anything other than 0 or if <c>upgrade</c> is NULL.</p> + marker="erlang#load_nif-2"><c>erlang:load_nif/2</c></seealso>.</p> + <p>The library fails to load if <c>load</c> returns + anything other than <c>0</c>. <c>load</c> can be <c>NULL</c> if + initialization is not needed.</p> </item> - - <tag><marker id="unload"/>void (*unload)(ErlNifEnv* env, void* priv_data)</tag> - <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. Note that <c>unload</c> is not - called for a replaced library as a consequence of <c>reload</c>.</p> + <tag><marker id="upgrade"/><c>int (*upgrade)(ErlNifEnv* env, void** + priv_data, void** old_priv_data, ERL_NIF_TERM load_info)</c></tag> + <item> + <p><c>upgrade</c> is called when the NIF library is loaded + 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>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> + <p>The library fails to load if <c>upgrade</c> returns + anything other than <c>0</c> or if <c>upgrade</c> is <c>NULL</c>.</p> </item> - - <tag><marker id="reload"/>int (*reload)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)</tag> - <note><p>The reload mechanism is <em>deprecated</em>. It was only intended - as a development feature. Do not use it as an upgrade method for - live production systems. It might be removed in future releases. Be sure - to pass <c>reload</c> as <c>NULL</c> to <seealso marker="#ERL_NIF_INIT">ERL_NIF_INIT</seealso> - to disable it when not used.</p> - </note> - <item><p><c>reload</c> is called when the NIF library is loaded - and there is already a previously loaded library for this - module code.</p> - <p>Works the same as <c>load</c>. The only difference is 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 will fail to load if <c>reload</c> returns - anything other than 0 or if <c>reload</c> is NULL.</p> + <tag><marker id="unload"/><c>void (*unload)(ErlNifEnv* env, void* + priv_data)</c></tag> + <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.</p> </item> - </taglist> </section> <section> - <title>DATA TYPES</title> - + <title>Data Types</title> <taglist> - <tag><marker id="ERL_NIF_TERM"/>ERL_NIF_TERM</tag> - <item> + <tag><marker id="ERL_NIF_TERM"/><c>ERL_NIF_TERM</c></tag> + <item> <p>Variables of type <c>ERL_NIF_TERM</c> can refer to any Erlang term. - This is an opaque type and values of it can only by used either as - arguments to API functions or as return values from NIFs. All - <c>ERL_NIF_TERM</c>'s belong to an environment - (<seealso marker="#ErlNifEnv">ErlNifEnv</seealso>). A term can not be - destructed individually, it is valid until its environment is destructed.</p> + This is an opaque type and values of it can only by used either as + arguments to API functions or as return values from NIFs. All + <c>ERL_NIF_TERM</c>s belong to an environment + (<seealso marker="#ErlNifEnv"><c>ErlNifEnv</c></seealso>). + A term cannot be destructed individually, it is valid until its + environment is destructed.</p> </item> - <tag><marker id="ErlNifEnv"/>ErlNifEnv</tag> + <tag><marker id="ErlNifEnv"/><c>ErlNifEnv</c></tag> <item> - <p><c>ErlNifEnv</c> represents an environment that can host Erlang terms. - All terms in an environment are valid as long as the environment is valid. - <c>ErlNifEnv</c> is an opaque type and pointers to it can only be passed - on to API functions. There are two types of environments; process - bound and process independent.</p> - <p>A <em>process bound environment</em> is passed as the first argument to all NIFs. - All function arguments passed to a NIF will belong to that environment. - The return value from a NIF must also be a term belonging to the same - environment. - In addition a process bound environment contains transient information - about the calling Erlang process. The environment is only valid in the - thread where it was supplied as argument until the NIF returns. It is - thus useless and dangerous to store pointers to process bound - environments between NIF calls. </p> - <p>A <em>process independent environment</em> is created by calling - <seealso marker="#enif_alloc_env">enif_alloc_env</seealso>. It can be - used to store terms between NIF calls and to send terms with - <seealso marker="#enif_send">enif_send</seealso>. A process - independent environment with all its terms is valid until you explicitly - invalidates it with <seealso marker="#enif_free_env">enif_free_env</seealso> - or <c>enif_send</c>.</p> - <p>All elements of a list/tuple must belong to the same environment as the - list/tuple itself. Terms can be copied between environments with - <seealso marker="#enif_make_copy">enif_make_copy</seealso>.</p> + <p><c>ErlNifEnv</c> represents an environment that can host Erlang + terms. All terms in an environment are valid as long as the + environment is valid. <c>ErlNifEnv</c> is an opaque type; pointers to + it can only be passed on to API functions. Two types of environments + exist:</p> + <taglist> + <tag>Process-bound environment</tag> + <item> + <p>Passed as the first argument to all NIFs. All function arguments + passed to a NIF belong to that environment. The return value from + a NIF must also be a term belonging to the same environment.</p> + <p>A process-bound environment contains transient information + about the calling Erlang process. The environment is only valid + in the thread where it was supplied as argument until the NIF + returns. It is thus useless and dangerous to store pointers to + process-bound environments between NIF calls.</p> + </item> + <tag>Process-independent environment</tag> + <item> + <p>Created by calling <seealso marker="#enif_alloc_env"> + <c>enif_alloc_env</c></seealso>. This environment can be + used to store terms between NIF calls and to send terms with + <seealso marker="#enif_send"><c>enif_send</c></seealso>. A + process-independent environment with all its terms is valid until + you explicitly invalidate it with + <seealso marker="#enif_free_env"><c>enif_free_env</c></seealso> + or <c>enif_send</c>.</p> + </item> + </taglist> + <p>All contained terms of a list/tuple/map must belong to the same + environment as the list/tuple/map itself. Terms can be copied between + environments with + <seealso marker="#enif_make_copy"><c>enif_make_copy</c></seealso>.</p> </item> - <tag><marker id="ErlNifFunc"/>ErlNifFunc</tag> - <item> - <p/> - <code type="none"> + <tag><marker id="ErlNifFunc"/><c>ErlNifFunc</c></tag> + <item> + <code type="none"> typedef struct { - const char* <em>name</em>; - unsigned <em>arity</em>; - ERL_NIF_TERM (*<em>fptr</em>)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); + const char* name; + unsigned arity; + ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); unsigned flags; -} ErlNifFunc; -</code> - <p>Describes a NIF by its name, arity and implementation. - <c>fptr</c> is a pointer to the function that implements the - NIF. The argument <c>argv</c> of a NIF will contain the - function arguments passed to the NIF and <c>argc</c> is the - length of the array, i.e. the function arity. <c>argv[N-1]</c> - will thus denote the Nth argument to the NIF. Note that the - <c>argc</c> argument allows for the same C function to - implement several Erlang functions with different arity (but - same name probably). For a regular NIF, <c>flags</c> is 0 (and - so its value can be omitted for statically initialized <c>ErlNifFunc</c> - instances), or it can be used to indicate that the NIF is a <seealso - marker="#dirty_nifs">dirty NIF</seealso> that should be executed - on a dirty scheduler thread (<em>note that the dirty NIF functionality - described here is experimental</em> and that you have to enable - support for dirty schedulers when building OTP in order to try the - functionality out). If the dirty NIF is expected to be - CPU-bound, its <c>flags</c> field should be set to - <c>ERL_NIF_DIRTY_JOB_CPU_BOUND</c>, or for I/O-bound jobs, - <c>ERL_NIF_DIRTY_JOB_IO_BOUND</c>.</p> +} ErlNifFunc;</code> + <p>Describes a NIF by its name, arity, and implementation.</p> + <taglist> + <tag><c>fptr</c></tag> + <item> + <p>A pointer to the function that implements the NIF.</p> + </item> + <tag><c>argv</c></tag> + <item> + <p>Contains the function arguments passed to the NIF.</p> + </item> + <tag><c>argc</c></tag> + <item> + <p>The array length, that is, the function arity. <c>argv[N-1]</c> + thus denotes the Nth argument to the NIF. Notice that the argument + <c>argc</c> allows for the same C function to implement several + Erlang functions with different arity (but probably with the same + name).</p> + </item> + <tag><c>flags</c></tag> + <item> + <p>Is <c>0</c> for a regular NIF (and so its value can be omitted + for statically initialized <c>ErlNifFunc</c> instances).</p> + <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>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> + <note> + <p>If one of the <c>ERL_NIF_DIRTY_JOB_*_BOUND</c> flags is set, + and the runtime system has no support for dirty schedulers, + the runtime system refuses to load the NIF library.</p> + </note> + </item> + </taglist> </item> - <tag><marker id="ErlNifBinary"/>ErlNifBinary</tag> - <item> - <p/> - <code type="none"> + <tag><marker id="ErlNifBinary"/><c>ErlNifBinary</c></tag> + <item> + <code type="none"> typedef struct { - unsigned <em>size</em>; - unsigned char* <em>data</em>; -} ErlNifBinary; -</code> + unsigned size; + unsigned char* data; +} ErlNifBinary;</code> <p><c>ErlNifBinary</c> contains transient information about an inspected binary term. <c>data</c> is a pointer to a buffer of <c>size</c> bytes with the raw content of the binary.</p> - <p>Note that <c>ErlNifBinary</c> is a semi-opaque type and you are + <p>Notice that <c>ErlNifBinary</c> is a semi-opaque type and you are only allowed to read fields <c>size</c> and <c>data</c>.</p> </item> - <tag><marker id="ErlNifPid"/>ErlNifPid</tag> - <item> - <p><c>ErlNifPid</c> is a process identifier (pid). In contrast to - pid terms (instances of <c>ERL_NIF_TERM</c>), <c>ErlNifPid</c>'s are self - contained and not bound to any - <seealso marker="#ErlNifEnv">environment</seealso>. <c>ErlNifPid</c> - is an opaque type.</p> - </item> - - <tag><marker id="ErlNifResourceType"/>ErlNifResourceType</tag> - <item> - <p>Each instance of <c>ErlNifResourceType</c> represent a class of - memory managed resource objects that can be garbage collected. + <tag><marker id="ErlNifBinaryToTerm"/><c>ErlNifBinaryToTerm</c></tag> + <item> + <p>An enumeration of the options that can be specified to + <seealso marker="#enif_binary_to_term"> + <c>enif_binary_to_term</c></seealso>. + For default behavior, use value <c>0</c>.</p> + <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 + <c>ERL_NIF_TERM</c>), <c>ErlNifPid</c>s are self-contained and not + bound to any <seealso marker="#ErlNifEnv">environment</seealso>. + <c>ErlNifPid</c> is an opaque type.</p> + </item> + <tag><marker id="ErlNifPort"/><c>ErlNifPort</c></tag> + <item> + <p>A port identifier. In contrast to port ID terms (instances of + <c>ERL_NIF_TERM</c>), <c>ErlNifPort</c>s are self-contained and not + bound to any <seealso marker="#ErlNifEnv">environment</seealso>. + <c>ErlNifPort</c> is an opaque type.</p> + </item> + <tag><marker id="ErlNifResourceType"/><c>ErlNifResourceType</c></tag> + <item> + <p>Each instance of <c>ErlNifResourceType</c> represents a class of + memory-managed resource objects that can be garbage collected. 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="ErlNifResourceDtor"/>ErlNifResourceDtor</tag> - <item> - <p/> - <code type="none"> -typedef void ErlNifResourceDtor(ErlNifEnv* env, void* obj); -</code> - <p>The function prototype of a resource destructor function. - A destructor function is not allowed to call any term-making functions.</p> - </item> - <tag><marker id="ErlNifCharEncoding"/>ErlNifCharEncoding</tag> - <item> - <p/> - <code type="none"> + </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, ErlNifPid* pid, 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> + <code type="none"> typedef enum { ERL_NIF_LATIN1 -}ErlNifCharEncoding; -</code> - <p>The character encoding used in strings and atoms. The only - supported encoding is currently <c>ERL_NIF_LATIN1</c> for - iso-latin-1 (8-bit ascii).</p> - </item> - <tag><marker id="ErlNifSysInfo"/>ErlNifSysInfo</tag> - <item> - <p>Used by <seealso marker="#enif_system_info">enif_system_info</seealso> - to return information about the runtime system. Contains currently - the exact same content as <seealso marker="erl_driver#ErlDrvSysInfo">ErlDrvSysInfo</seealso>.</p> - </item> - <tag><marker id="ErlNifSInt64"/>ErlNifSInt64</tag> - <item><p>A native signed 64-bit integer type.</p></item> - <tag><marker id="ErlNifUInt64"/>ErlNifUInt64</tag> - <item><p>A native unsigned 64-bit integer type.</p></item> - +}ErlNifCharEncoding;</code> + <p>The character encoding used in strings and atoms. The only + supported encoding is <c>ERL_NIF_LATIN1</c> for + ISO Latin-1 (8-bit ASCII).</p> + </item> + <tag><marker id="ErlNifSysInfo"/><c>ErlNifSysInfo</c></tag> + <item> + <p>Used by <seealso marker="#enif_system_info"> + <c>enif_system_info</c></seealso> to return information about the + runtime system. Contains the same content as + <seealso marker="erl_driver#ErlDrvSysInfo"> + <c>ErlDrvSysInfo</c></seealso>.</p> + </item> + <tag><marker id="ErlNifSInt64"/><c>ErlNifSInt64</c></tag> + <item> + <p>A native signed 64-bit integer type.</p> + </item> + <tag><marker id="ErlNifUInt64"/><c>ErlNifUInt64</c></tag> + <item> + <p>A native unsigned 64-bit integer type.</p> + </item> + <tag><marker id="ErlNifTime"/><c>ErlNifTime</c></tag> + <item> + <p>A signed 64-bit integer type for representation of time.</p> + </item> + <tag><marker id="ErlNifTimeUnit"/><c>ErlNifTimeUnit</c></tag> + <item> + <p>An enumeration of time units supported by the NIF API:</p> + <taglist> + <tag><c>ERL_NIF_SEC</c></tag> + <item>Seconds</item> + <tag><c>ERL_NIF_MSEC</c></tag> + <item>Milliseconds</item> + <tag><c>ERL_NIF_USEC</c></tag> + <item>Microseconds</item> + <tag><c>ERL_NIF_NSEC</c></tag> + <item>Nanoseconds</item> + </taglist> + </item> + <tag><marker id="ErlNifUniqueInteger"/><c>ErlNifUniqueInteger</c></tag> + <item> + <p>An enumeration of the properties that can be requested from + <seealso marker="#enif_make_unique_integer"> + <c>enif_make_unique_integer</c></seealso>. + For default properties, use value <c>0</c>.</p> + <taglist> + <tag><c>ERL_NIF_UNIQUE_POSITIVE</c></tag> + <item> + <p>Return only positive integers.</p> + </item> + <tag><c>ERL_NIF_UNIQUE_MONOTONIC</c></tag> + <item> + <p>Return only <seealso + marker="time_correction#Strictly_Monotonically_Increasing"> + strictly monotonically increasing</seealso> integer corresponding + to creation time.</p> + </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> + <tag><marker id="SysIOVec"/><c>SysIOVec</c></tag> + <item> + <p>A system I/O vector, as used by <c>writev</c> on + Unix and <c>WSASend</c> on Win32. It is used in + <c>ErlNifIOVec</c> and by + <seealso marker="#enif_ioq_peek"><c>enif_ioq_peek</c></seealso>.</p> + </item> + <tag><marker id="ErlNifIOVec"/><c>ErlNifIOVec</c></tag> + <item> + <code type="none"> +typedef struct { + int iovcnt; + size_t size; + SysIOVec* iov; +} ErlNifIOVec;</code> + <p>An I/O vector containing <c>iovcnt</c> <c>SysIOVec</c>s + pointing to the data. It is used by + <seealso marker="#enif_inspect_iovec"> + <c>enif_inspect_iovec</c></seealso> and + <seealso marker="#enif_ioq_enqv"> + <c>enif_ioq_enqv</c></seealso>.</p> + </item> + <tag><marker id="ErlNifIOQueueOpts"/><c>ErlNifIOQueueOpts</c></tag> + <item> + Options to configure a <c>ErlNifIOQueue</c>. + <taglist> + <tag>ERL_NIF_IOQ_NORMAL</tag> + <item><p>Create a normal I/O Queue</p></item> + </taglist> + </item> </taglist> </section> <funcs> - <func><name><ret>void *</ret><nametext>enif_alloc(size_t size)</nametext></name> + <func> + <name><ret>void *</ret><nametext>enif_alloc(size_t size)</nametext></name> <fsummary>Allocate dynamic memory.</fsummary> - <desc><p>Allocate memory of <c>size</c> bytes. Return NULL if allocation failed.</p></desc> + <desc> + <p>Allocates memory of <c>size</c> bytes.</p> + <p>Returns <c>NULL</c> if the allocation fails.</p> + <p>The returned pointer is suitably aligned for any built-in type that + fit in the allocated memory.</p> + </desc> </func> - <func><name><ret>int</ret><nametext>enif_alloc_binary(size_t size, ErlNifBinary* bin)</nametext></name> + + <func> + <name><ret>int</ret> + <nametext>enif_alloc_binary(size_t size, ErlNifBinary* bin)</nametext> + </name> <fsummary>Create a new binary.</fsummary> - <desc><p>Allocate a new binary of size <c>size</c> - bytes. Initialize the structure pointed to by <c>bin</c> to - refer to the allocated binary. The binary must either be released by - <seealso marker="#enif_release_binary">enif_release_binary</seealso> - or ownership transferred to an Erlang term with - <seealso marker="#enif_make_binary">enif_make_binary</seealso>. - An allocated (and owned) <c>ErlNifBinary</c> can be kept between NIF - calls.</p> - <p>Return true on success or false if allocation failed.</p> - </desc> - </func> - <func><name><ret>ErlNifEnv *</ret><nametext>enif_alloc_env()</nametext></name> - <fsummary>Create a new environment</fsummary> - <desc><p>Allocate a new process independent environment. The environment can - be used to hold terms that is not bound to any process. Such terms can - later be copied to a process environment with - <seealso marker="#enif_make_copy">enif_make_copy</seealso> - or be sent to a process as a message with <seealso marker="#enif_send">enif_send</seealso>.</p> - <p>Return pointer to the new environment.</p> - </desc> - </func> - <func><name><ret>void *</ret><nametext>enif_alloc_resource(ErlNifResourceType* type, unsigned size)</nametext></name> - <fsummary>Allocate a memory managed resource object</fsummary> - <desc><p>Allocate a memory managed resource object of type <c>type</c> and size <c>size</c> bytes.</p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_clear_env(ErlNifEnv* env)</nametext></name> + <desc> + <p>Allocates a new binary of size <c>size</c> bytes. + Initializes the structure pointed to by <c>bin</c> to + refer to the allocated binary. The binary must either be released by + <seealso marker="#enif_release_binary"> + <c>enif_release_binary</c></seealso> + or ownership transferred to an Erlang term with + <seealso marker="#enif_make_binary"><c>enif_make_binary</c></seealso>. + An allocated (and owned) <c>ErlNifBinary</c> can be kept between NIF + calls.</p> + <p>If you do not need to reallocate or keep the data alive across NIF + calls, consider using <seealso marker="#enif_make_new_binary"> + <c>enif_make_new_binary</c></seealso> instead as it will allocate + small binaries on the process heap when possible.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if allocation + fails.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifEnv *</ret><nametext>enif_alloc_env()</nametext></name> + <fsummary>Create a new environment.</fsummary> + <desc> + <p>Allocates a new process-independent environment. The environment can + be used to hold terms that are not bound to any process. Such terms + can later be copied to a process environment with + <seealso marker="#enif_make_copy"><c>enif_make_copy</c></seealso> or + be sent to a process as a message with <seealso marker="#enif_send"> + <c>enif_send</c></seealso>.</p> + <p>Returns pointer to the new environment.</p> + </desc> + </func> + + <func> + <name><ret>void *</ret><nametext>enif_alloc_resource(ErlNifResourceType* + type, unsigned size)</nametext></name> + <fsummary>Allocate a memory-managed resource object.</fsummary> + <desc> + <p>Allocates a memory-managed resource object of type <c>type</c> and + size <c>size</c> bytes.</p> + </desc> + </func> + + <func> + <name><ret>size_t</ret><nametext>enif_binary_to_term(ErlNifEnv *env, + const unsigned char* data, size_t size, ERL_NIF_TERM *term, + ErlNifBinaryToTerm opts)</nametext></name> + <fsummary>Create a term from the external format.</fsummary> + <desc> + <p>Creates a term that is the result of decoding the binary data at + <c>data</c>, which must be encoded according to the Erlang external + term format. No more than <c>size</c> bytes are read from <c>data</c>. + Argument <c>opts</c> corresponds to the second argument to + <seealso marker="erlang#binary_to_term-2"> + <c>erlang:binary_to_term/2</c></seealso> and must be either <c>0</c> + or <c>ERL_NIF_BIN2TERM_SAFE</c>.</p> + <p>On success, stores the resulting term at <c>*term</c> and returns + the number of bytes read. Returns <c>0</c> if decoding fails or if + <c>opts</c> is invalid.</p> + <p>See also <seealso marker="#ErlNifBinaryToTerm"> + <c>ErlNifBinaryToTerm</c></seealso>, + <seealso marker="erlang#binary_to_term-2"> + <c>erlang:binary_to_term/2</c></seealso>, and + <seealso marker="#enif_term_to_binary"> + <c>enif_term_to_binary</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret><nametext>enif_clear_env(ErlNifEnv* env)</nametext> + </name> <fsummary>Clear an environment for reuse.</fsummary> - <desc><p>Free all terms in an environment and clear it for reuse. The environment must - have been allocated with <seealso marker="#enif_alloc_env">enif_alloc_env</seealso>. - </p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_compare(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)</nametext></name> - <fsummary>Compare two terms</fsummary> - <desc><p>Return an integer less than, equal to, or greater than - zero if <c>lhs</c> is found, respectively, to be less than, - equal, or greater than <c>rhs</c>. Corresponds to the Erlang - operators <c>==</c>, <c>/=</c>, <c>=<</c>, <c><</c>, - <c>>=</c> and <c>></c> (but <em>not</em> <c>=:=</c> or <c>=/=</c>).</p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_cond_broadcast(ErlNifCond *cnd)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_broadcast">erl_drv_cond_broadcast</seealso>. - </p></desc> - </func> - <func><name><ret>ErlNifCond *</ret><nametext>enif_cond_create(char *name)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_create">erl_drv_cond_create</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_cond_destroy(ErlNifCond *cnd)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_destroy">erl_drv_cond_destroy</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_cond_signal(ErlNifCond *cnd)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_signal">erl_drv_cond_signal</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_cond_wait(ErlNifCond *cnd, ErlNifMutex *mtx)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_cond_wait">erl_drv_cond_wait</seealso>. - </p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_consume_timeslice(ErlNifEnv *env, int percent)</nametext></name> - <fsummary></fsummary> - <desc><p>Give the runtime system a hint about how much CPU time the current NIF call has consumed - since last hint, or since the start of the NIF if no previous hint has been given. - The time is given as a <c>percent</c> of the timeslice that a process is allowed to execute Erlang - code until it may be suspended to give time for other runnable processes. - The scheduling timeslice is not an exact entity, but can usually be - approximated to about 1 millisecond.</p> - <p>Note that it is up to the runtime system to determine if and how to use this information. - Implementations on some platforms may use other means in order to determine consumed - CPU time. Lengthy NIFs should regardless of this frequently call <c>enif_consume_timeslice</c> - in order to determine if it is allowed to continue execution or not.</p> - - <p>Returns 1 if the timeslice is exhausted, or 0 otherwise. If 1 is returned the NIF should return - as soon as possible in order for the process to yield.</p> - <p>Argument <c>percent</c> must be an integer between 1 and 100. This function - must only be called from a NIF-calling thread and argument <c>env</c> must be - the environment of the calling process.</p> - <p>This function is provided to better support co-operative scheduling, improve system responsiveness, - and make it easier to prevent misbehaviors of the VM due to a NIF monopolizing a scheduler thread. - It can be used to divide <seealso marker="#lengthy_work">length work</seealso> into - a number of repeated NIF-calls without the need to create threads. - See also the <seealso marker="#WARNING">warning</seealso> text at the beginning of this document.</p> - </desc> + <desc> + <p>Frees all terms in an environment and clears it for reuse. + The environment must have been allocated with + <seealso marker="#enif_alloc_env"><c>enif_alloc_env</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_compare(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)</nametext> + </name> + <fsummary>Compare two terms.</fsummary> + <desc> + <p>Returns an integer < <c>0</c> if <c>lhs</c> < <c>rhs</c>, + <c>0</c> if <c>lhs</c> = <c>rhs</c>, and > <c>0</c> if + <c>lhs</c> > <c>rhs</c>. Corresponds to the Erlang + operators <c>==</c>, <c>/=</c>, <c>=<</c>, <c><</c>, + <c>>=</c>, and <c>></c> (but <em>not</em> <c>=:=</c> or + <c>=/=</c>).</p> + </desc> + </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> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_cond_broadcast"> + <c>erl_drv_cond_broadcast</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifCond *</ret> + <nametext>enif_cond_create(char *name)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_cond_create"> + <c>erl_drv_cond_create</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_cond_destroy(ErlNifCond *cnd)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_cond_destroy"> + <c>erl_drv_cond_destroy</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>char*</ret> + <nametext>enif_cond_name(ErlNifCond* cnd)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_cond_name"> + <c>erl_drv_cond_name</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_cond_signal(ErlNifCond *cnd)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_cond_signal"> + <c>erl_drv_cond_signal</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_cond_wait(ErlNifCond *cnd, ErlNifMutex *mtx)</nametext> + </name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_cond_wait"> + <c>erl_drv_cond_wait</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_consume_timeslice(ErlNifEnv *env, int percent)</nametext> + </name> + <fsummary></fsummary> + <desc> + <p>Gives the runtime system a hint about how much CPU time the current + NIF call has consumed since the last hint, or since the start of the + NIF if no previous hint has been specified. The time is specified as a + percent of the timeslice that a process is allowed to execute + Erlang code until it can be suspended to give time for other runnable + processes. The scheduling timeslice is not an exact entity, but can + usually be approximated to about 1 millisecond.</p> + <p>Notice that it is up to the runtime system to determine if and how + to use this information. Implementations on some platforms can use + other means to determine consumed CPU time. Lengthy NIFs should + regardless of this frequently call <c>enif_consume_timeslice</c> to + determine if it is allowed to continue execution.</p> + <p>Argument <c>percent</c> must be an integer between 1 and 100. This + function must only be called from a NIF-calling thread, and argument + <c>env</c> must be the environment of the calling process.</p> + <p>Returns <c>1</c> if the timeslice is exhausted, otherwise <c>0</c>. + If <c>1</c> is returned, the NIF is to return as soon as possible in + order for the process to yield.</p> + <p>This function is provided to better support co-operative scheduling, + improve system responsiveness, and make it easier to prevent + misbehaviors of the VM because of a NIF monopolizing a scheduler + thread. It can be used to divide <seealso marker="#lengthy_work"> + length work</seealso> into a number of repeated NIF calls without the + need to create threads.</p> + <p>See also the <seealso marker="#WARNING">warning</seealso> text at + the beginning of this manual page.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifTime</ret><nametext>enif_convert_time_unit(ErlNifTime + val, ErlNifTimeUnit from, ErlNifTimeUnit to)</nametext></name> + <fsummary>Convert time unit of a time value.</fsummary> + <desc> + <marker id="enif_convert_time_unit"></marker> + <p>Converts the <c>val</c> value of time unit <c>from</c> to + the corresponding value of time unit <c>to</c>. The result is + rounded using the floor function.</p> + <taglist> + <tag><c>val</c></tag> + <item>Value to convert time unit for.</item> + <tag><c>from</c></tag> + <item>Time unit of <c>val</c>.</item> + <tag><c>to</c></tag> + <item>Time unit of returned value.</item> + </taglist> + <p>Returns <c>ERL_NIF_TIME_ERROR</c> if called with an invalid + time unit argument.</p> + <p>See also <seealso marker="#ErlNifTime"><c>ErlNifTime</c></seealso> + and + <seealso marker="#ErlNifTimeUnit"><c>ErlNifTimeUnit</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_cpu_time(ErlNifEnv *)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Returns the CPU time in the same format as + <seealso marker="erlang#timestamp-0"> + <c>erlang:timestamp()</c></seealso>. + The CPU time is the time the current logical CPU has spent executing + since some arbitrary point in the past. If the OS does not support + fetching this value, <c>enif_cpu_time</c> invokes + <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso>.</p> + </desc> + </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> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_equal_tids"> + <c>erl_drv_equal_tids</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_fprintf(FILE *stream, const char *format, ...)</nametext></name> + <fsummary>Format strings and Erlang terms.</fsummary> + <desc> + <p>Similar to <c>fprintf</c> but this format string also accepts + <c>"%T"</c>, which formats Erlang terms of type + <seealso marker="#ERL_NIF_TERM"><c>ERL_NIF_TERM</c></seealso>.</p> + <p>This function is primarily intended for debugging purpose. It is not + recommended to print very large terms with <c>%T</c>. The function may + change <c>errno</c>, even if successful.</p> + </desc> + </func> + + <func> + <name><ret>void</ret><nametext>enif_free(void* ptr)</nametext></name> + <fsummary>Free dynamic memory.</fsummary> + <desc> + <p>Frees memory allocated by + <seealso marker="#enif_alloc"><c>enif_alloc</c></seealso>.</p> + </desc> </func> - <func><name><ret>int</ret><nametext>enif_equal_tids(ErlNifTid tid1, ErlNifTid tid2)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_equal_tids">erl_drv_equal_tids</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_free(void* ptr)</nametext></name> - <fsummary>Free dynamic memory</fsummary> - <desc><p>Free memory allocated by <c>enif_alloc</c>.</p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_free_env(ErlNifEnv* env)</nametext></name> - <fsummary>Free an environment allocated with enif_alloc_env</fsummary> - <desc><p>Free an environment allocated with <seealso marker="#enif_alloc_env">enif_alloc_env</seealso>. - All terms created in the environment will be freed as well.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_atom(ErlNifEnv* env, ERL_NIF_TERM term, char* buf, unsigned size, ErlNifCharEncoding encode)</nametext></name> - <fsummary>Get the text representation of an atom term</fsummary> - <desc><p>Write a null-terminated string, in the buffer pointed to by - <c>buf</c> of size <c>size</c>, consisting of the string - representation of the atom <c>term</c> with encoding - <seealso marker="#ErlNifCharEncoding">encode</seealso>. Return - the number of bytes written (including terminating null character) or 0 if - <c>term</c> is not an atom with maximum length of - <c>size-1</c>.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_atom_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len, ErlNifCharEncoding encode)</nametext></name> + + <func> + <name><ret>void</ret> + <nametext>enif_free_env(ErlNifEnv* env)</nametext></name> + <fsummary>Free an environment allocated with enif_alloc_env.</fsummary> + <desc> + <p>Frees an environment allocated with + <seealso marker="#enif_alloc_env"><c>enif_alloc_env</c></seealso>. + All terms created in the environment are freed as well.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_free_iovec(ErlNifIOvec* iov)</nametext></name> + <fsummary>Free an ErlIOVec</fsummary> + <desc> + <p>Frees an io vector returned from + <seealso marker="#enif_inspect_iovec"> + <c>enif_inspect_iovec</c></seealso>. + This is needed only if a <c>NULL</c> environment is passed to + <seealso marker="#enif_inspect_iovec"> + <c>enif_inspect_iovec</c></seealso>.</p> + <code type="none"><![CDATA[ +ErlNifIOVec *iovec = NULL; +size_t max_elements = 128; +ERL_NIF_TERM tail; +if (!enif_inspect_iovec(NULL, max_elements, term, &tail, &iovec)) + return 0; + +// Do things with the iovec + +/* Free the iovector, possibly in another thread or nif function call */ +enif_free_iovec(iovec);]]></code> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_atom(ErlNifEnv* env, ERL_NIF_TERM + term, char* buf, unsigned size, ErlNifCharEncoding encode)</nametext> + </name> + <fsummary>Get the text representation of an atom term.</fsummary> + <desc> + <p>Writes a <c>NULL</c>-terminated string in the buffer pointed to by + <c>buf</c> of size <c>size</c>, consisting of the string + representation of the atom <c>term</c> with encoding + <seealso marker="#ErlNifCharEncoding">encode</seealso>.</p> + <p>Returns the number of bytes written (including terminating + <c>NULL</c> character) or <c>0</c> if <c>term</c> is not an atom with + maximum length of <c>size-1</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_atom_length(ErlNifEnv* env, + ERL_NIF_TERM term, unsigned* len, ErlNifCharEncoding encode)</nametext> + </name> <fsummary>Get the length of atom <c>term</c>.</fsummary> - <desc><p>Set <c>*len</c> to the length (number of bytes excluding - terminating null character) of the atom <c>term</c> with encoding - <c>encode</c>. Return true on success or false if <c>term</c> is not an - atom.</p></desc> + <desc> + <p>Sets <c>*len</c> to the length (number of bytes excluding + terminating <c>NULL</c> character) of the atom <c>term</c> with + encoding <c>encode</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is not + an atom.</p> + </desc> </func> - <func><name><ret>int</ret><nametext>enif_get_double(ErlNifEnv* env, ERL_NIF_TERM term, double* dp)</nametext></name> + + <func> + <name><ret>int</ret><nametext>enif_get_double(ErlNifEnv* env, + ERL_NIF_TERM term, double* dp)</nametext></name> <fsummary>Read a floating-point number term.</fsummary> - <desc><p>Set <c>*dp</c> to the floating point value of - <c>term</c>. Return true on success or false if <c>term</c> is not a float.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_int(ErlNifEnv* env, ERL_NIF_TERM term, int* ip)</nametext></name> - <fsummary>Read an integer term</fsummary> - <desc><p>Set <c>*ip</c> to the integer value of - <c>term</c>. Return true on success or false if <c>term</c> is not an - integer or is outside the bounds of type <c>int</c>.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_int64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifSInt64* ip)</nametext></name> - <fsummary>Read a 64-bit integer term</fsummary> - <desc><p>Set <c>*ip</c> to the integer value of - <c>term</c>. Return true on success or false if <c>term</c> is not an - integer or is outside the bounds of a signed 64-bit integer.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_local_pid(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPid* pid)</nametext></name> - <fsummary>Read an local pid term</fsummary> - <desc><p>If <c>term</c> is the pid of a node local process, initialize the - pid variable <c>*pid</c> from it and return true. Otherwise return false. - No check if the process is alive is done.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_list_cell(ErlNifEnv* env, ERL_NIF_TERM list, ERL_NIF_TERM* head, ERL_NIF_TERM* tail)</nametext></name> - <fsummary>Get head and tail from a list</fsummary> - <desc><p>Set <c>*head</c> and <c>*tail</c> from - <c>list</c> and return true, or return false if <c>list</c> is not a - non-empty list.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_list_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len)</nametext></name> + <desc> + <p>Sets <c>*dp</c> to the floating-point value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is not + a float.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_int(ErlNifEnv* env, ERL_NIF_TERM + term, int* ip)</nametext></name> + <fsummary>Read an integer term.</fsummary> + <desc> + <p>Sets <c>*ip</c> to the integer value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is not + an integer or is outside the bounds of type <c>int</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_int64(ErlNifEnv* env, ERL_NIF_TERM + term, ErlNifSInt64* ip)</nametext></name> + <fsummary>Read a 64-bit integer term.</fsummary> + <desc> + <p>Sets <c>*ip</c> to the integer value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is not + an integer or is outside the bounds of a signed 64-bit integer.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_local_pid(ErlNifEnv* env, + ERL_NIF_TERM term, ErlNifPid* pid)</nametext></name> + <fsummary>Read a local pid term.</fsummary> + <desc> + <p>If <c>term</c> is the pid of a node local process, this function + initializes the pid variable <c>*pid</c> from it and returns + <c>true</c>. Otherwise returns <c>false</c>. No check is done to see + if the process is alive.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_local_port(ErlNifEnv* env, + ERL_NIF_TERM term, ErlNifPort* port_id)</nametext></name> + <fsummary>Read a local port term.</fsummary> + <desc> + <p>If <c>term</c> identifies a node local port, this function + initializes the port variable <c>*port_id</c> from it and returns + <c>true</c>. Otherwise returns <c>false</c>. No check is done to see + if the port is alive.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_list_cell(ErlNifEnv* env, + ERL_NIF_TERM list, ERL_NIF_TERM* head, ERL_NIF_TERM* tail)</nametext> + </name> + <fsummary>Get head and tail from a list.</fsummary> + <desc> + <p>Sets <c>*head</c> and <c>*tail</c> from list <c>list</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if it is + not a list or the list is empty.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_list_length(ErlNifEnv* env, + ERL_NIF_TERM term, unsigned* len)</nametext></name> <fsummary>Get the length of list <c>term</c>.</fsummary> - <desc><p>Set <c>*len</c> to the length of list <c>term</c> and return true, - or return false if <c>term</c> is not a list.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_long(ErlNifEnv* env, ERL_NIF_TERM term, long int* ip)</nametext></name> - <fsummary>Read an long integer term.</fsummary> - <desc><p>Set <c>*ip</c> to the long integer value of <c>term</c> and - return true, or return false if <c>term</c> is not an integer or is - outside the bounds of type <c>long int</c>.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_resource(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifResourceType* type, void** objp)</nametext></name> - <fsummary>Get the pointer to a resource object</fsummary> - <desc><p>Set <c>*objp</c> to point to the resource object referred to by <c>term</c>.</p> - <p>Return true on success or false if <c>term</c> is not a handle to a resource object - of type <c>type</c>.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_string(ErlNifEnv* env, - ERL_NIF_TERM list, char* buf, unsigned size, - ErlNifCharEncoding encode)</nametext></name> + <desc> + <p>Sets <c>*len</c> to the length of list <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is + not a proper list.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_long(ErlNifEnv* env, ERL_NIF_TERM + term, long int* ip)</nametext></name> + <fsummary>Read a long integer term.</fsummary> + <desc> + <p>Sets <c>*ip</c> to the long integer value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is + not an integer or is outside the bounds of type <c>long int</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_map_size(ErlNifEnv* env, + ERL_NIF_TERM term, size_t *size)</nametext></name> + <fsummary>Read the size of a map term.</fsummary> + <desc> + <p>Sets <c>*size</c> to the number of key-value pairs in the map + <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is + not a map.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_map_value(ErlNifEnv* env, + ERL_NIF_TERM map, ERL_NIF_TERM key, ERL_NIF_TERM* value)</nametext> + </name> + <fsummary>Get the value of a key in a map.</fsummary> + <desc> + <p>Sets <c>*value</c> to the value associated with <c>key</c> in the + map <c>map</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>map</c> is not + a map or if <c>map</c> does not contain <c>key</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_resource(ErlNifEnv* env, + ERL_NIF_TERM term, ErlNifResourceType* type, void** objp)</nametext> + </name> + <fsummary>Get the pointer to a resource object.</fsummary> + <desc> + <p>Sets <c>*objp</c> to point to the resource object referred to by + <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is + not a handle to a resource object of type <c>type</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_string(ErlNifEnv* env, + ERL_NIF_TERM list, char* buf, unsigned size, + ErlNifCharEncoding encode)</nametext></name> <fsummary>Get a C-string from a list.</fsummary> - <desc><p>Write a null-terminated string, in the buffer pointed to by - <c>buf</c> with size <c>size</c>, consisting of the characters - in the string <c>list</c>. The characters are written using encoding - <seealso marker="#ErlNifCharEncoding">encode</seealso>. - Return the number of bytes written (including terminating null - character), or <c>-size</c> if the string was truncated due to - buffer space, or 0 if <c>list</c> is not a string that can be - encoded with <c>encode</c> or if <c>size</c> was less than 1. - The written string is always null-terminated unless buffer - <c>size</c> is less than 1.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_tuple(ErlNifEnv* env, ERL_NIF_TERM term, int* arity, const ERL_NIF_TERM** array)</nametext></name> + <desc> + <p>Writes a <c>NULL</c>-terminated string in the buffer pointed to by + <c>buf</c> with size <c>size</c>, consisting of the characters + in the string <c>list</c>. The characters are written using encoding + <seealso marker="#ErlNifCharEncoding">encode</seealso>.</p> + <p>Returns one of the following:</p> + <list type="bulleted"> + <item>The number of bytes written (including terminating <c>NULL</c> + character)</item> + <item><c>-size</c> if the string was truncated because of buffer + space</item> + <item><c>0</c> if <c>list</c> is not a string that can be encoded + with <c>encode</c> or if <c>size</c> was < <c>1</c>.</item> + </list> + <p>The written string is always <c>NULL</c>-terminated, unless buffer + <c>size</c> is < <c>1</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_tuple(ErlNifEnv* env, ERL_NIF_TERM + term, int* arity, const ERL_NIF_TERM** array)</nametext></name> <fsummary>Inspect the elements of a tuple.</fsummary> - <desc><p>If <c>term</c> is a tuple, set <c>*array</c> to point - to an array containing the elements of the tuple and set - <c>*arity</c> to the number of elements. Note that the array - is read-only and <c>(*array)[N-1]</c> will be the Nth element of - the tuple. <c>*array</c> is undefined if the arity of the tuple - is zero.</p><p>Return true on success or false if <c>term</c> is not a - tuple.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_get_uint(ErlNifEnv* env, ERL_NIF_TERM term, unsigned int* ip)</nametext></name> + <desc> + <p>If <c>term</c> is a tuple, this function sets <c>*array</c> to point + to an array containing the elements of the tuple, and sets + <c>*arity</c> to the number of elements. Notice that the array + is read-only and <c>(*array)[N-1]</c> is the Nth element of + the tuple. <c>*array</c> is undefined if the arity of the tuple + is zero.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is + not a tuple.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_get_uint(ErlNifEnv* env, ERL_NIF_TERM + term, unsigned int* ip)</nametext></name> <fsummary>Read an unsigned integer term.</fsummary> - <desc><p>Set <c>*ip</c> to the unsigned integer value of <c>term</c> and - return true, or return false if <c>term</c> is not an unsigned integer or - is outside the bounds of type <c>unsigned int</c>.</p></desc> + <desc> + <p>Sets <c>*ip</c> to the unsigned integer value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is + not an unsigned integer or is outside the bounds of type + <c>unsigned int</c>.</p> + </desc> </func> - <func><name><ret>int</ret><nametext>enif_get_uint64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifUInt64* ip)</nametext></name> + + <func> + <name><ret>int</ret><nametext>enif_get_uint64(ErlNifEnv* env, + ERL_NIF_TERM term, ErlNifUInt64* ip)</nametext></name> <fsummary>Read an unsigned 64-bit integer term.</fsummary> - <desc><p>Set <c>*ip</c> to the unsigned integer value of <c>term</c> and - return true, or return false if <c>term</c> is not an unsigned integer or - is outside the bounds of an unsigned 64-bit integer.</p></desc> + <desc> + <p>Sets <c>*ip</c> to the unsigned integer value of <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is + not an unsigned integer or is outside the bounds of an unsigned + 64-bit integer.</p> + </desc> </func> - <func><name><ret>int</ret><nametext>enif_get_ulong(ErlNifEnv* env, ERL_NIF_TERM term, unsigned long* ip)</nametext></name> + + <func> + <name><ret>int</ret><nametext>enif_get_ulong(ErlNifEnv* env, ERL_NIF_TERM + term, unsigned long* ip)</nametext></name> <fsummary>Read an unsigned integer term.</fsummary> - <desc><p>Set <c>*ip</c> to the unsigned long integer value of <c>term</c> - and return true, or return false if <c>term</c> is not an unsigned integer or is - outside the bounds of type <c>unsigned long</c>.</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> - <desc><p>Initialize the structure pointed to by <c>bin</c> with - information about the binary term - <c>bin_term</c>. Return true on success or false if <c>bin_term</c> is not a binary.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_inspect_iolist_as_binary(ErlNifEnv* - env, ERL_NIF_TERM term, ErlNifBinary* bin) - </nametext></name> - <fsummary>Inspect the content of an iolist</fsummary> - <desc><p>Initialize the structure pointed to by <c>bin</c> with one - continuous buffer with the same byte content as <c>iolist</c>. As with - inspect_binary, the data pointed to by <c>bin</c> is transient and does - not need to be released. Return true on success or false if <c>iolist</c> is not an - iolist.</p> + <desc> + <p>Sets <c>*ip</c> to the unsigned long integer value of + <c>term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>term</c> is + not an unsigned integer or is outside the bounds of type + <c>unsigned long</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_getenv(const char* key, char* value, + size_t *value_size)</nametext></name> + <fsummary>Get the value of an environment variable.</fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_getenv"> + <c>erl_drv_getenv</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_has_pending_exception(ErlNifEnv* env, + ERL_NIF_TERM* reason)</nametext></name> + <fsummary>Check if an exception has been raised.</fsummary> + <desc> + <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>*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> + <p>See also <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso> and + <seealso marker="#enif_raise_exception"> + <c>enif_raise_exception</c></seealso>.</p> + </desc> + </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> + <desc> + <p>Initializes the structure pointed to by <c>bin</c> with information + about binary term <c>bin_term</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>bin_term</c> + is not a binary.</p> </desc> </func> - <func><name><ret>int</ret><nametext>enif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is an atom</fsummary> - <desc><p>Return true if <c>term</c> is an atom.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_binary(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is a binary</fsummary> - <desc><p>Return true if <c>term</c> is a binary</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_empty_list(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is an empty list</fsummary> - <desc><p>Return true if <c>term</c> is an empty list.</p></desc> - </func> - <marker id="enif_is_exception"/><func><name><ret>int</ret><nametext>enif_is_exception(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is an exception</fsummary> - <desc><p>Return true if <c>term</c> is an exception.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_number(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is a number (integer or float)</fsummary> - <desc><p>Return true if <c>term</c> is a number.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_fun(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is a fun</fsummary> - <desc><p>Return true if <c>term</c> is a fun.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_identical(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)</nametext></name> - <fsummary>Erlang operator =:=</fsummary> - <desc><p>Return true if the two terms are identical. Corresponds to the - Erlang operators <c>=:=</c> and - <c>=/=</c>.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_on_dirty_scheduler(ErlNifEnv* env)</nametext></name> - <fsummary>Check to see if executing on a dirty scheduler thread</fsummary> - <desc> - <p>Check to see if the current NIF is executing on a dirty scheduler thread. If the - emulator is built with threading support, calling <c>enif_is_on_dirty_scheduler</c> - from within a dirty NIF returns true. It returns false when the calling NIF is a regular - NIF running on a normal scheduler thread, or when the emulator is built without threading - support.</p> - <note><p>This function is available only when the emulator is configured with dirty - schedulers enabled. This feature is currently disabled by default. To determine whether - the dirty NIF API is available, native code can check to see if the C preprocessor macro - <c>ERL_NIF_DIRTY_SCHEDULER_SUPPORT</c> is defined.</p></note> - </desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is a pid</fsummary> - <desc><p>Return true if <c>term</c> is a pid.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_port(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is a port</fsummary> - <desc><p>Return true if <c>term</c> is a port.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_ref(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is a reference</fsummary> - <desc><p>Return true if <c>term</c> is a reference.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_tuple(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is a tuple</fsummary> - <desc><p>Return true if <c>term</c> is a tuple.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_is_list(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> - <fsummary>Determine if a term is a list</fsummary> - <desc><p>Return true if <c>term</c> is a list.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_keep_resource(void* obj)</nametext></name> - <fsummary>Add a reference to a resource object</fsummary> - <desc><p>Add a reference to resource object <c>obj</c> obtained from - <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>. - Each call to <c>enif_keep_resource</c> for an object must be balanced by - a call to <seealso marker="#enif_release_resource">enif_release_resource</seealso> - before the object will be destructed.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_atom(ErlNifEnv* env, const char* name)</nametext></name> - <fsummary>Create an atom term</fsummary> - <desc><p>Create an atom term from the null-terminated C-string <c>name</c> - with iso-latin-1 encoding.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_atom_len(ErlNifEnv* env, const char* name, size_t len)</nametext></name> - <fsummary>Create an atom term</fsummary> - <desc><p>Create an atom term from the string <c>name</c> with length <c>len</c>. - Null-characters are treated as any other characters.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_badarg(ErlNifEnv* env)</nametext></name> + + <func> + <name><ret>int</ret><nametext>enif_inspect_iolist_as_binary(ErlNifEnv* + env, ERL_NIF_TERM term, ErlNifBinary* bin)</nametext></name> + <fsummary>Inspect the content of an iolist.</fsummary> + <desc> + <p>Initializes the structure pointed to by <c>bin</c> with a + continuous buffer with the same byte content as <c>iolist</c>. As + with <c>inspect_binary</c>, the data pointed to by <c>bin</c> is + transient and does not need to be released.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>iolist</c> is + not an iolist.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_inspect_iovec(ErlNifEnv* + env, size_t max_elements, ERL_NIF_TERM iovec_term, ERL_NIF_TERM* tail, + ErlNifIOVec** iovec)</nametext></name> + <fsummary>Inspect a list of binaries as an ErlNifIOVec.</fsummary> + <desc> + <p>Fills <c>iovec</c> with the list of binaries provided in + <c>iovec_term</c>. The number of elements handled in the call is + limited to <c>max_elements</c>, and <c>tail</c> is set to the + remainder of the list. Note that the output may be longer than + <c>max_elements</c> on some platforms. + </p> + <p>To create a list of binaries from an arbitrary iolist, use + <seealso marker="erts:erlang#iolist_to_iovec/1"> + <c>erlang:iolist_to_iovec/1</c></seealso>.</p> + <p>When calling this function, <c>iovec</c> should contain a pointer to + <c>NULL</c> or a ErlNifIOVec structure that should be used if + possible. e.g. + </p> + <code type="none"> +/* Don't use a pre-allocated structure */ +ErlNifIOVec *iovec = NULL; +enif_inspect_iovec(env, max_elements, term, &tail, &iovec); + +/* Use a stack-allocated vector as an optimization for vectors with few elements */ +ErlNifIOVec vec, *iovec = &vec; +enif_inspect_iovec(env, max_elements, term, &tail, &iovec); +</code> + <p>The contents of the <c>iovec</c> is valid until the called nif + function returns. If the <c>iovec</c> should be valid after the nif + call returns, it is possible to call this function with a + <c>NULL</c> environment. If no environment is given the <c>iovec</c> + owns the data in the vector and it has to be explicitly freed using + <seealso marker="#enif_free_iovec"><c>enif_free_iovec</c> + </seealso>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>iovec_term</c> + not an iovec.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifIOQueue *</ret> + <nametext>enif_ioq_create(ErlNifIOQueueOpts opts)</nametext></name> + <fsummary>Create a new IO Queue</fsummary> + <desc> + <p>Create a new I/O Queue that can be used to store data. + <c>opts</c> has to be set to <c>ERL_NIF_IOQ_NORMAL</c>. + </p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_ioq_destroy(ErlNifIOQueue *q)</nametext></name> + <fsummary>Destroy an IO Queue and free it's content</fsummary> + <desc> + <p>Destroy the I/O queue and free all of it's contents</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_ioq_deq(ErlNifIOQueue *q, size_t count, size_t *size)</nametext></name> + <fsummary>Dequeue count bytes from the IO Queue</fsummary> + <desc> + <p>Dequeue <c>count</c> bytes from the I/O queue. + If <c>size</c> is not <c>NULL</c>, the new size of the queue + is placed there.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if the I/O does + not contain <c>count</c> bytes. On failure the queue is left un-altered.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_ioq_enq_binary(ErlNifIOQueue *q, ErlNifBinary *bin, size_t skip)</nametext></name> + <fsummary>Enqueue the binary into the IO Queue</fsummary> + <desc> + <p>Enqueue the <c>bin</c> into <c>q</c> skipping the first <c>skip</c> bytes.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>skip</c> is greater + than the size of <c>bin</c>. Any ownership of the binary data is transferred + to the queue and <c>bin</c> is to be considered read-only for the rest of the NIF + call and then as released.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_ioq_enqv(ErlNifIOQueue *q, ErlNifIOVec *iovec, size_t skip)</nametext></name> + <fsummary>Enqueue the iovec into the IO Queue</fsummary> + <desc> + <p>Enqueue the <c>iovec</c> into <c>q</c> skipping the first <c>skip</c> bytes.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>skip</c> is greater + than the size of <c>iovec</c>.</p> + </desc> + </func> + + <func> + <name><ret>SysIOVec *</ret> + <nametext>enif_ioq_peek(ErlNifIOQueue *q, int *iovlen)</nametext></name> + <fsummary>Peek inside the IO Queue</fsummary> + <desc> + <p>Get the I/O queue as a pointer to an array of <c>SysIOVec</c>s. + It also returns the number of elements in <c>iovlen</c>.</p> + <p>Nothing is removed from the queue by this function, that must be done + with <seealso marker="#enif_ioq_deq"><c>enif_ioq_deq</c></seealso>.</p> + <p>The returned array is suitable to use with the Unix system + call <c>writev</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_ioq_peek_head(ErlNifEnv *env, ErlNifIOQueue *q, size_t *size, ERL_NIF_TERM *bin_term)</nametext></name> + <fsummary>Peek the head of the IO Queue.</fsummary> + <desc> + <p>Get the head of the IO Queue as a binary term.</p> + <p>If <c>size</c> is not <c>NULL</c>, the size of the head is placed + there.</p> + <p>Nothing is removed from the queue by this function, that must be done + with <seealso marker="#enif_ioq_deq"><c>enif_ioq_deq</c></seealso>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if the queue is + empty.</p> + </desc> + </func> + + <func> + <name><ret>size_t</ret> + <nametext>enif_ioq_size(ErlNifIOQueue *q)</nametext></name> + <fsummary>Get the current size of the IO Queue</fsummary> + <desc> + <p>Get the size of <c>q</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term)</nametext> + </name> + <fsummary>Determine if a term is an atom.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is an atom.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_is_binary(ErlNifEnv* env, ERL_NIF_TERM term)</nametext> + </name> + <fsummary>Determine if a term is a binary.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is a binary.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_is_current_process_alive(ErlNifEnv* env)</nametext> + </name> + <fsummary>Determine if currently executing process is alive.</fsummary> + <desc> + <p>Returns <c>true</c> if the currently executing process is currently + alive, otherwise <c>false</c>.</p> + <p>This function can only be used from a NIF-calling thread, and with + an environment corresponding to currently executing processes.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_is_empty_list(ErlNifEnv* env, + ERL_NIF_TERM term)</nametext></name> + <fsummary>Determine if a term is an empty list.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is an empty list.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_is_exception(ErlNifEnv* env, + ERL_NIF_TERM term)</nametext></name> + <fsummary>Determine if a term is an exception.</fsummary> + <desc><marker id="enif_is_exception"/> + <p>Return true if <c>term</c> is an exception.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_is_fun(ErlNifEnv* env, ERL_NIF_TERM + term)</nametext></name> + <fsummary>Determine if a term is a fun.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is a fun.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_is_identical(ERL_NIF_TERM lhs, + ERL_NIF_TERM rhs)</nametext></name> + <fsummary>Erlang operator =:=.</fsummary> + <desc> + <p>Returns <c>true</c> if the two terms are identical. Corresponds to + the Erlang operators <c>=:=</c> and <c>=/=</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_is_list(ErlNifEnv* env, ERL_NIF_TERM term)</nametext> + </name> + <fsummary>Determine if a term is a list.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is a list.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_is_map(ErlNifEnv* env, ERL_NIF_TERM + term)</nametext></name> + <fsummary>Determine if a term is a map.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is a map, otherwise + <c>false</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_is_number(ErlNifEnv* env, ERL_NIF_TERM + term)</nametext></name> + <fsummary>Determine if a term is a number (integer or float).</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is a number.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term)</nametext> + </name> + <fsummary>Determine if a term is a pid.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is a pid.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_is_port(ErlNifEnv* env, ERL_NIF_TERM term)</nametext> + </name> + <fsummary>Determine if a term is a port.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is a port.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_is_port_alive(ErlNifEnv* env, + ErlNifPort *port_id)</nametext></name> + <fsummary>Determine if a local port is alive.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>port_id</c> is 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>int</ret><nametext>enif_is_process_alive(ErlNifEnv* env, + ErlNifPid *pid)</nametext></name> + <fsummary>Determine if a local process is alive.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>pid</c> is 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>int</ret> + <nametext>enif_is_ref(ErlNifEnv* env, ERL_NIF_TERM term)</nametext> + </name> + <fsummary>Determine if a term is a reference.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is a reference.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_is_tuple(ErlNifEnv* env, ERL_NIF_TERM term)</nametext> + </name> + <fsummary>Determine if a term is a tuple.</fsummary> + <desc> + <p>Returns <c>true</c> if <c>term</c> is a tuple.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_keep_resource(void* obj)</nametext> + </name> + <fsummary>Add a reference to a resource object.</fsummary> + <desc> + <p>Adds a reference to resource object <c>obj</c> obtained from + <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>. Each call to + <c>enif_keep_resource</c> for an object must be balanced by a call to + <seealso marker="#enif_release_resource"> + <c>enif_release_resource</c></seealso> + before the object is destructed.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_atom(ErlNifEnv* env, const char* name)</nametext> + </name> + <fsummary>Create an atom term.</fsummary> + <desc> + <p>Creates an atom term from the <c>NULL</c>-terminated C-string + <c>name</c> with ISO Latin-1 encoding. If the length of <c>name</c> + exceeds the maximum length allowed for an atom (255 characters), + <c>enif_make_atom</c> invokes <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_atom_len(ErlNifEnv* env, + const char* name, size_t len)</nametext></name> + <fsummary>Create an atom term.</fsummary> + <desc> + <p>Create an atom term from the string <c>name</c> with length + <c>len</c>. <c>NULL</c> characters are treated as any other + characters. If <c>len</c> exceeds the maximum length + allowed for an atom (255 characters), <c>enif_make_atom</c> invokes + <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_badarg(ErlNifEnv* env)</nametext></name> <fsummary>Make a badarg exception.</fsummary> - <desc><p>Make a badarg exception to be returned from a NIF, and set - an associated exception reason in <c>env</c>. If - <c>enif_make_badarg</c> is called, the term it returns <em>must</em> - be returned from the function that called it. No other return value - is allowed. Also, the term returned from <c>enif_make_badarg</c> may - be passed only to - <seealso marker="#enif_is_exception">enif_is_exception</seealso> and - not to any other NIF API function.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)</nametext></name> + <desc> + <p>Makes a <c>badarg</c> exception to be returned from a NIF, and + associates it with environment <c>env</c>. Once a NIF or any function + it calls invokes <c>enif_make_badarg</c>, the runtime ensures that a + <c>badarg</c> exception is raised when the NIF returns, even if the + NIF attempts to return a non-exception term instead.</p> + <p>The return value from <c>enif_make_badarg</c> can be used only as + the return value from the NIF that invoked it (directly or indirectly) + or be passed to <seealso marker="#enif_is_exception"> + <c>enif_is_exception</c></seealso>, but not to any other NIF API + function.</p> + <p>See also <seealso marker="#enif_has_pending_exception"> + <c>enif_has_pending_exception</c></seealso> and + <seealso marker="#enif_raise_exception"> + <c>enif_raise_exception</c></seealso>.</p> + <note> + <p>Before ERTS 7.0 (Erlang/OTP 18), the return value + from <c>enif_make_badarg</c> had to be returned from the NIF. This + requirement is now lifted as the return value from the NIF is + ignored if <c>enif_make_badarg</c> has been invoked.</p> + </note> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)</nametext> + </name> <fsummary>Make a binary term.</fsummary> - <desc><p>Make a binary term from <c>bin</c>. Any ownership of - the binary data will be transferred to the created term and - <c>bin</c> should be considered read-only for the rest of the NIF - call and then as released.</p></desc> + <desc> + <p>Makes a binary term from <c>bin</c>. Any ownership of + the binary data is transferred to the created term and + <c>bin</c> is to be considered read-only for the rest of the NIF + call and then as released.</p> + </desc> </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_copy(ErlNifEnv* dst_env, ERL_NIF_TERM src_term)</nametext></name> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_copy(ErlNifEnv* dst_env, + ERL_NIF_TERM src_term)</nametext></name> <fsummary>Make a copy of a term.</fsummary> - <desc><p>Make a copy of term <c>src_term</c>. The copy will be created in - environment <c>dst_env</c>. The source term may be located in any - environment.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_double(ErlNifEnv* env, double d)</nametext></name> - <fsummary>Create a floating-point term</fsummary> - <desc><p>Create a floating-point term from a <c>double</c>.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding encode)</nametext></name> - <fsummary>Create an existing atom term</fsummary> - <desc><p>Try to create the term of an already existing atom from - the null-terminated C-string <c>name</c> with encoding - <seealso marker="#ErlNifCharEncoding">encode</seealso>. If the atom - already exists store the term in <c>*atom</c> and return true, otherwise - return false.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding encoding)</nametext></name> - <fsummary>Create an existing atom term</fsummary> - <desc><p>Try to create the term of an already existing atom from the - string <c>name</c> with length <c>len</c> and encoding - <seealso marker="#ErlNifCharEncoding">encode</seealso>. Null-characters - are treated as any other characters. If the atom already exists store the term - in <c>*atom</c> and return true, otherwise return false.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_int(ErlNifEnv* env, int i)</nametext></name> - <fsummary>Create an integer term</fsummary> - <desc><p>Create an integer term.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_int64(ErlNifEnv* env, ErlNifSInt64 i)</nametext></name> - <fsummary>Create an integer term</fsummary> - <desc><p>Create an integer term from a signed 64-bit integer.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list(ErlNifEnv* env, unsigned cnt, ...)</nametext></name> + <desc> + <p>Makes a copy of term <c>src_term</c>. The copy is created in + environment <c>dst_env</c>. The source term can be located in any + environment.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_double(ErlNifEnv* env, double d)</nametext></name> + <fsummary>Create a floating-point term.</fsummary> + <desc> + <p>Creates a floating-point term from a <c>double</c>. If argument + <c>double</c> is not finite or is NaN, <c>enif_make_double</c> + invokes <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_make_existing_atom(ErlNifEnv* env, + const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding + encode)</nametext></name> + <fsummary>Create an existing atom term.</fsummary> + <desc> + <p>Tries to create the term of an already existing atom from + the <c>NULL</c>-terminated C-string <c>name</c> with encoding + <seealso marker="#ErlNifCharEncoding">encode</seealso>.</p> + <p>If the atom already exists, this function stores the term in + <c>*atom</c> and returns <c>true</c>, otherwise <c>false</c>. + Also returns <c>false</c> if the length of <c>name</c> exceeds the + maximum length allowed for an atom (255 characters).</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_make_existing_atom_len(ErlNifEnv* env, + const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding + encoding)</nametext></name> + <fsummary>Create an existing atom term.</fsummary> + <desc> + <p>Tries to create the term of an already existing atom from the + string <c>name</c> with length <c>len</c> and encoding + <seealso marker="#ErlNifCharEncoding">encode</seealso>. <c>NULL</c> + characters are treated as any other characters.</p> + <p>If the atom already exists, this function stores the term in + <c>*atom</c> and returns <c>true</c>, otherwise <c>false</c>. + Also returns <c>false</c> if <c>len</c> exceeds the maximum length + allowed for an atom (255 characters).</p> + </desc> + </func> + + <func><name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_int(ErlNifEnv* env, int i)</nametext></name> + <fsummary>Create an integer term.</fsummary> + <desc> + <p>Creates an integer term.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_int64(ErlNifEnv* env, ErlNifSInt64 i)</nametext> + </name> + <fsummary>Create an integer term.</fsummary> + <desc> + <p>Creates an integer term from a signed 64-bit integer.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_list(ErlNifEnv* env, unsigned cnt, ...)</nametext> + </name> <fsummary>Create a list term.</fsummary> - <desc><p>Create an ordinary list term of length <c>cnt</c>. Expects - <c>cnt</c> number of arguments (after <c>cnt</c>) of type ERL_NIF_TERM as the - elements of the list. An empty list is returned if <c>cnt</c> is 0.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list1(ErlNifEnv* env, ERL_NIF_TERM e1)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list2(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list3(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list4(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list5(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list6(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list7(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list8(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list9(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9)</nametext></name> + <desc> + <p>Creates an ordinary list term of length <c>cnt</c>. Expects + <c>cnt</c> number of arguments (after <c>cnt</c>) of type + <c>ERL_NIF_TERM</c> as the elements of the list.</p> + <p>Returns an empty list if <c>cnt</c> is 0.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_list1(ErlNifEnv* env, ERL_NIF_TERM e1)</nametext> + </name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list2(ErlNifEnv* env, + ERL_NIF_TERM e1, ERL_NIF_TERM e2)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list3(ErlNifEnv* env, + ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list4(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list5(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list6(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list7(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list8(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list9(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9)</nametext></name> <fsummary>Create a list term.</fsummary> - <desc><p>Create an ordinary list term with length indicated by the - function name. Prefer these functions (macros) over the variadic - <c>enif_make_list</c> to get a compile time error if the number of - arguments does not match.</p></desc> + <desc> + <p>Creates an ordinary list term with length indicated by the + function name. Prefer these functions (macros) over the variadic + <c>enif_make_list</c> to get a compile-time error if the number of + arguments does not match.</p> + </desc> </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list_cell(ErlNifEnv* env, ERL_NIF_TERM head, ERL_NIF_TERM tail)</nametext></name> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list_cell(ErlNifEnv* + env, ERL_NIF_TERM head, ERL_NIF_TERM tail)</nametext></name> <fsummary>Create a list cell.</fsummary> - <desc><p>Create a list cell <c>[head | tail]</c>.</p></desc> + <desc> + <p>Creates a list cell <c>[head | tail]</c>.</p> + </desc> </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_list_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt)</nametext></name> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_list_from_array(ErlNifEnv* env, const ERL_NIF_TERM + arr[], unsigned cnt)</nametext></name> <fsummary>Create a list term from an array.</fsummary> - <desc><p>Create an ordinary list containing the elements of array <c>arr</c> - of length <c>cnt</c>. An empty list is returned if <c>cnt</c> is 0.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM term, ERL_NIF_TERM *list)</nametext></name> - <fsummary>Create the reverse list of the list <c>term</c>.</fsummary> - <desc><p>Set <c>*list</c> to the reverse list of the list <c>term</c> and return true, - or return false if <c>term</c> is not a list. This function should only be used on - short lists as a copy will be created of the list which will not be released until after the - nif returns.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_long(ErlNifEnv* env, long int i)</nametext></name> - <fsummary>Create an integer term from a long int</fsummary> - <desc><p>Create an integer term from a <c>long int</c>.</p></desc> - </func> - <func><name><ret>unsigned char *</ret><nametext>enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp)</nametext></name> - <fsummary>Allocate and create a new binary term</fsummary> - <desc><p>Allocate a binary of size <c>size</c> bytes and create an owning - term. The binary data is mutable until the calling NIF returns. This is a - quick way to create a new binary without having to use - <seealso marker="#ErlNifBinary">ErlNifBinary</seealso>. The drawbacks are - that the binary can not be kept between NIF calls and it can not be - reallocated.</p><p>Return a pointer to the raw binary data and set - <c>*termp</c> to the binary term.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_pid(ErlNifEnv* env, const ErlNifPid* pid)</nametext></name> - <fsummary>Make a pid term</fsummary> - <desc><p>Make a pid term from <c>*pid</c>.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_ref(ErlNifEnv* env)</nametext></name> + <desc> + <p>Creates an ordinary list containing the elements of array <c>arr</c> + of length <c>cnt</c>.</p> + <p>Returns an empty list if <c>cnt</c> is 0.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_long(ErlNifEnv* env, long int i)</nametext></name> + <fsummary>Create an integer term from a long int.</fsummary> + <desc> + <p>Creates an integer term from a <c>long int</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_make_map_put(ErlNifEnv* env, + ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM value, + ERL_NIF_TERM* map_out)</nametext></name> + <fsummary>Insert key-value pair in map.</fsummary> + <desc> + <p>Makes a copy of map <c>map_in</c> and inserts <c>key</c> with + <c>value</c>. If <c>key</c> already exists in <c>map_in</c>, the old + associated value is replaced by <c>value</c>.</p> + <p>If successful, this function sets <c>*map_out</c> to the new map and + returns <c>true</c>. Returns <c>false</c> if <c>map_in</c> is not a + map.</p> + <p>The <c>map_in</c> term must belong to environment <c>env</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_make_map_remove(ErlNifEnv* env, + ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM* map_out)</nametext> + </name> + <fsummary>Remove key from map.</fsummary> + <desc> + <p>If map <c>map_in</c> contains <c>key</c>, this function makes a copy + of <c>map_in</c> in <c>*map_out</c>, and removes <c>key</c> and the + associated value. If map <c>map_in</c> does not contain <c>key</c>, + <c>*map_out</c> is set to <c>map_in</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if <c>map_in</c> is + not a map.</p> + <p>The <c>map_in</c> term must belong to environment <c>env</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_make_map_update(ErlNifEnv* env, + ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM new_value, + ERL_NIF_TERM* map_out)</nametext></name> + <fsummary>Replace value for key in map.</fsummary> + <desc> + <p>Makes a copy of map <c>map_in</c> and replace the old associated + value for <c>key</c> with <c>new_value</c>.</p> + <p>If successful, this function sets <c>*map_out</c> to the new map and + returns <c>true</c>. Returns <c>false</c> if <c>map_in</c> is not a + map or if it does not contain <c>key</c>.</p> + <p>The <c>map_in</c> term must belong to environment <c>env</c>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_make_map_from_arrays(ErlNifEnv* env, ERL_NIF_TERM keys[], + ERL_NIF_TERM values[], size_t cnt, ERL_NIF_TERM *map_out)</nametext></name> + <fsummary>Make map term from the given keys and values.</fsummary> + <desc> + <p>Makes a map term from the given keys and values.</p> + <p>If successful, this function sets <c>*map_out</c> to the new map and + returns <c>true</c>. Returns <c>false</c> there are any duplicate + keys.</p> + <p>All keys and values must belong to <c>env</c>.</p> + </desc> + </func> + + <func> + <name><ret>unsigned char *</ret><nametext>enif_make_new_binary(ErlNifEnv* + env, size_t size, ERL_NIF_TERM* termp)</nametext></name> + <fsummary>Allocate and create a new binary term.</fsummary> + <desc> + <p>Allocates a binary of size <c>size</c> bytes and creates an owning + term. The binary data is mutable until the calling NIF returns. + This is a quick way to create a new binary without having to use + <seealso marker="#ErlNifBinary"><c>ErlNifBinary</c></seealso>. + The drawbacks are that the binary cannot be kept between NIF calls + and it cannot be reallocated.</p> + <p>Returns a pointer to the raw binary data and sets + <c>*termp</c> to the binary term.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_new_map(ErlNifEnv* env)</nametext></name> + <fsummary>Make an empty map term.</fsummary> + <desc> + <p>Makes an empty map term.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_pid(ErlNifEnv* env, const ErlNifPid* pid)</nametext> + </name> + <fsummary>Make a pid term.</fsummary> + <desc> + <p>Makes a pid term from <c>*pid</c>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_ref(ErlNifEnv* env)</nametext></name> <fsummary>Create a reference.</fsummary> - <desc><p>Create a reference like <seealso marker="erlang#make_ref-0">erlang:make_ref/0</seealso>.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_resource(ErlNifEnv* env, void* obj)</nametext></name> - <fsummary>Create an opaque handle to a resource object</fsummary> - <desc><p>Create an opaque handle to a memory managed resource object - obtained by <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>. - No ownership transfer is done, as the resource object still needs to be released by - <seealso marker="#enif_release_resource">enif_release_resource</seealso>, - but note that the call to <c>enif_release_resource</c> can occur - immediately after obtaining the term from <c>enif_make_resource</c>, - in which case the resource object will be deallocated when the - term is garbage collected. See the - <seealso marker="#enif_resource_example">example of creating and - returning a resource object</seealso> for more details.</p> - <p>Note that the only defined behaviour of using a resource term in - an Erlang program is to store it and send it between processes on the - same node. Other operations such as matching or <c>term_to_binary</c> - will have unpredictable (but harmless) results.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_resource_binary(ErlNifEnv* env, void* obj, const void* data, size_t size)</nametext></name> - <fsummary>Create a custom binary term</fsummary> - <desc><p>Create a binary term that is memory managed by a resource object - <c>obj</c> obtained by <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>. - The returned binary term will consist of <c>size</c> bytes pointed to - by <c>data</c>. This raw binary data must be kept readable and unchanged - until the destructor of the resource is called. The binary data may be - stored external to the resource object in which case it is the responsibility - of the destructor to release the data.</p> - <p>Several binary terms may be managed by the same resource object. The - destructor will not be called until the last binary is garbage collected. - This can be useful as a way to return different parts of a larger binary - buffer.</p> - <p>As with <seealso marker="#enif_make_resource">enif_make_resource</seealso>, - no ownership transfer is done. The resource still needs to be released with - <seealso marker="#enif_release_resource">enif_release_resource</seealso>.</p> - </desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_string(ErlNifEnv* env, const char* string, ErlNifCharEncoding encoding)</nametext></name> + <desc> + <p>Creates a reference like <seealso marker="erlang#make_ref-0"> + <c>erlang:make_ref/0</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_resource(ErlNifEnv* env, void* obj)</nametext> + </name> + <fsummary>Create an opaque handle to a resource object.</fsummary> + <desc> + <p>Creates an opaque handle to a memory-managed resource object + obtained by <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>. No ownership transfer is done, + as the resource object still needs to be released by + <seealso marker="#enif_release_resource"> + <c>enif_release_resource</c></seealso>. However, notice that the call + to <c>enif_release_resource</c> can occur immediately after obtaining + the term from <c>enif_make_resource</c>, in which case the resource + object is deallocated when the term is garbage collected. For more + details, see the <seealso marker="#enif_resource_example">example of + creating and returning a resource object</seealso> in the User's + Guide.</p> + <note> + <p>Since ERTS 9.0 (OTP-20.0), resource terms have a defined behavior + when compared and serialized through <c>term_to_binary</c> or passed + between nodes.</p> + <list type="bulleted"> + <item> + <p>Two resource terms will compare equal iff they + would yield the same resource object pointer when passed to + <seealso marker="#enif_get_resource"><c>enif_get_resource</c></seealso>.</p> + </item> + <item> + <p>A resource term can be serialized with <c>term_to_binary</c> and later + be fully recreated if the resource object is still alive when + <c>binary_to_term</c> is called. A <em>stale</em> resource term will be + returned from <c>binary_to_term</c> if the resource object has + been deallocated. <seealso marker="#enif_get_resource"><c>enif_get_resource</c></seealso> + will return false for stale resource terms.</p> + <p>The same principles of serialization apply when passing + resource terms in messages to remote nodes and back again. A + resource term will act stale on all nodes except the node where + its resource object is still alive in memory.</p> + </item> + </list> + <p>Before ERTS 9.0 (OTP-20.0), all resource terms did + compare equal to each other and to empty binaries (<c><<>></c>). + If serialized, they would be recreated as plain empty binaries.</p> + </note> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_resource_binary(ErlNifEnv* env, void* obj, const + void* data, size_t size)</nametext></name> + <fsummary>Create a custom binary term.</fsummary> + <desc> + <p>Creates a binary term that is memory-managed by a resource object + <c>obj</c> obtained by <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>. The returned binary term + consists of <c>size</c> bytes pointed to by <c>data</c>. This raw + binary data must be kept readable and unchanged until the destructor + of the resource is called. The binary data can be stored external to + the resource object, in which case the destructor is responsible + for releasing the data.</p> + <p>Several binary terms can be managed by the same resource object. The + destructor is not called until the last binary is garbage collected. + This can be useful to return different parts of a larger binary + buffer.</p> + <p>As with <seealso marker="#enif_make_resource"> + <c>enif_make_resource</c></seealso>, no ownership transfer is done. + The resource still needs to be released with + <seealso marker="#enif_release_resource"> + <c>enif_release_resource</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM list_in, + ERL_NIF_TERM *list_out)</nametext></name> + <fsummary>Create the reverse of a list.</fsummary> + <desc> + <p>Sets <c>*list_out</c> to the reverse list of the list <c>list_in</c> + and returns <c>true</c>, or returns <c>false</c> if <c>list_in</c> is + not a list.</p> + <p>This function is only to be used on short lists, as a copy is + created of the list, which is not released until after the NIF + returns.</p> + <p>The <c>list_in</c> term must belong to environment <c>env</c>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_string(ErlNifEnv* env, + const char* string, ErlNifCharEncoding encoding)</nametext></name> <fsummary>Create a string.</fsummary> - <desc><p>Create a list containing the characters of the - null-terminated string <c>string</c> with encoding <seealso marker="#ErlNifCharEncoding">encoding</seealso>.</p></desc> + <desc> + <p>Creates a list containing the characters of the + <c>NULL</c>-terminated string <c>string</c> with encoding + <seealso marker="#ErlNifCharEncoding">encoding</seealso>.</p> + </desc> </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_string_len(ErlNifEnv* env, const char* string, size_t len, ErlNifCharEncoding encoding)</nametext></name> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_string_len(ErlNifEnv* + env, const char* string, size_t len, ErlNifCharEncoding + encoding)</nametext></name> <fsummary>Create a string.</fsummary> - <desc><p>Create a list containing the characters of the string <c>string</c> with - length <c>len</c> and encoding <seealso marker="#ErlNifCharEncoding">encoding</seealso>. - Null-characters are treated as any other characters.</p></desc> + <desc> + <p>Creates a list containing the characters of the string <c>string</c> + with length <c>len</c> and encoding + <seealso marker="#ErlNifCharEncoding">encoding</seealso>. + <c>NULL</c> characters are treated as any other characters.</p> + </desc> </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_sub_binary(ErlNifEnv* - env, ERL_NIF_TERM bin_term, size_t pos, size_t size)</nametext></name> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_sub_binary(ErlNifEnv* + env, ERL_NIF_TERM bin_term, size_t pos, size_t size)</nametext></name> <fsummary>Make a subbinary term.</fsummary> - <desc><p>Make a subbinary of binary <c>bin_term</c>, starting at - zero-based position <c>pos</c> with a length of <c>size</c> bytes. - <c>bin_term</c> must be a binary or bitstring and - <c>pos+size</c> must be less or equal to the number of whole - bytes in <c>bin_term</c>.</p></desc> + <desc> + <p>Makes a subbinary of binary <c>bin_term</c>, starting at + zero-based position <c>pos</c> with a length of <c>size</c> bytes. + <c>bin_term</c> must be a binary or bitstring. <c>pos+size</c> must + be less or equal to the number of whole bytes in <c>bin_term</c>.</p> + </desc> </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple(ErlNifEnv* env, unsigned cnt, ...)</nametext></name> - <fsummary>Create a tuple term.</fsummary> - <desc><p>Create a tuple term of arity <c>cnt</c>. Expects - <c>cnt</c> number of arguments (after <c>cnt</c>) of type ERL_NIF_TERM as the - elements of the tuple.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple1(ErlNifEnv* env, ERL_NIF_TERM e1)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple2(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple3(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple4(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple5(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple6(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple7(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple8(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8)</nametext></name> - <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple9(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9)</nametext></name> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple(ErlNifEnv* env, + unsigned cnt, ...)</nametext></name> + <fsummary>Creates a tuple term.</fsummary> + <desc> + <p>Creates a tuple term of arity <c>cnt</c>. Expects <c>cnt</c> number + of arguments (after <c>cnt</c>) of type <c>ERL_NIF_TERM</c> as the + elements of the tuple.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple1(ErlNifEnv* env, + ERL_NIF_TERM e1)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple2(ErlNifEnv* env, + ERL_NIF_TERM e1, ERL_NIF_TERM e2)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple3(ErlNifEnv* env, + ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple4(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple5(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple6(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple7(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple8(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8)</nametext></name> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple9(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9)</nametext></name> <fsummary>Create a tuple term.</fsummary> - <desc><p>Create a tuple term with length indicated by the - function name. Prefer these functions (macros) over the variadic - <c>enif_make_tuple</c> to get a compile time error if the number of - arguments does not match.</p></desc> + <desc> + <p>Creates a tuple term with length indicated by the + function name. Prefer these functions (macros) over the variadic + <c>enif_make_tuple</c> to get a compile-time error if the number of + arguments does not match.</p> + </desc> </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_tuple_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt)</nametext></name> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_tuple_from_array(ErlNifEnv* env, const ERL_NIF_TERM + arr[], unsigned cnt)</nametext></name> <fsummary>Create a tuple term from an array.</fsummary> - <desc><p>Create a tuple containing the elements of array <c>arr</c> - of length <c>cnt</c>.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_uint(ErlNifEnv* env, unsigned int i)</nametext></name> - <fsummary>Create an unsigned integer term</fsummary> - <desc><p>Create an integer term from an <c>unsigned int</c>.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_uint64(ErlNifEnv* env, ErlNifUInt64 i)</nametext></name> - <fsummary>Create an unsigned integer term</fsummary> - <desc><p>Create an integer term from an unsigned 64-bit integer.</p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_ulong(ErlNifEnv* env, unsigned long i)</nametext></name> - <fsummary>Create an integer term from an unsigned long int</fsummary> - <desc><p>Create an integer term from an <c>unsigned long int</c>.</p></desc> - </func> - <func><name><ret>ErlNifMutex *</ret><nametext>enif_mutex_create(char *name)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_create">erl_drv_mutex_create</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_mutex_destroy(ErlNifMutex *mtx)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_destroy">erl_drv_mutex_destroy</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_mutex_lock(ErlNifMutex *mtx)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_lock">erl_drv_mutex_lock</seealso>. - </p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_mutex_trylock(ErlNifMutex *mtx)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_trylock">erl_drv_mutex_trylock</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_mutex_unlock(ErlNifMutex *mtx)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_mutex_unlock">erl_drv_mutex_unlock</seealso>. - </p></desc> - </func> - <func><name><ret>ErlNifResourceType *</ret><nametext>enif_open_resource_type(ErlNifEnv* env, - const char* module_str, const char* name, - ErlNifResourceDtor* dtor, ErlNifResourceFlags flags, ErlNifResourceFlags* tried)</nametext></name> - <fsummary>Create or takeover a resource type</fsummary> - <desc><p>Create or takeover a resource type identified by the string - <c>name</c> and give it the destructor function pointed to by <seealso marker="#ErlNifResourceDtor">dtor</seealso>. - Argument <c>flags</c> can have the following values:</p> - <taglist> - <tag><c>ERL_NIF_RT_CREATE</c></tag> - <item>Create a new resource type that does not already exist.</item> - <tag><c>ERL_NIF_RT_TAKEOVER</c></tag> - <item>Open an existing resource type and take over ownership of all its instances. - The supplied destructor <c>dtor</c> will be called both for existing instances - as well as new instances not yet created by the calling NIF library.</item> - </taglist> - <p>The two flag values can be combined with bitwise-or. The name of the - resource type is local to the calling module. Argument <c>module_str</c> - is not (yet) used and must be NULL. The <c>dtor</c> may be <c>NULL</c> - in case no destructor is needed.</p> - <p>On success, return a pointer to the resource type and <c>*tried</c> - will be set to either <c>ERL_NIF_RT_CREATE</c> or - <c>ERL_NIF_RT_TAKEOVER</c> to indicate what was actually done. - On failure, return <c>NULL</c> and set <c>*tried</c> to <c>flags</c>. - It is allowed to set <c>tried</c> to <c>NULL</c>.</p> - <p>Note that <c>enif_open_resource_type</c> is only allowed to be called in the three callbacks - <seealso marker="#load">load</seealso>, <seealso marker="#reload">reload</seealso> - and <seealso marker="#upgrade">upgrade</seealso>.</p> - </desc> - </func> - <func><name><ret>void *</ret><nametext>enif_priv_data(ErlNifEnv* env)</nametext></name> - <fsummary>Get the private data of a NIF library</fsummary> - <desc><p>Return the pointer to the private data that was set by <c>load</c>, - <c>reload</c> or <c>upgrade</c>.</p> - <p>Was previously named <c>enif_get_data</c>.</p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_realloc_binary(ErlNifBinary* bin, size_t size)</nametext></name> + <desc> + <p>Creates a tuple containing the elements of array <c>arr</c> + of length <c>cnt</c>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_uint(ErlNifEnv* env, unsigned int i)</nametext> + </name> + <fsummary>Create an unsigned integer term.</fsummary> + <desc> + <p>Creates an integer term from an <c>unsigned int</c>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_uint64(ErlNifEnv* env, ErlNifUInt64 i)</nametext> + </name> + <fsummary>Create an unsigned integer term.</fsummary> + <desc> + <p>Creates an integer term from an unsigned 64-bit integer.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_make_ulong(ErlNifEnv* env, unsigned long i)</nametext> + </name> + <fsummary>Create an integer term from an unsigned long int.</fsummary> + <desc> + <p>Creates an integer term from an <c>unsigned long int</c>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_make_unique_integer(ErlNifEnv + *env, ErlNifUniqueInteger properties)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Returns a unique integer with the same properties as specified by + <seealso marker="erlang#unique_integer-1"> + <c>erlang:unique_integer/1</c></seealso>.</p> + <p><c>env</c> is the environment to create the integer in.</p> + <p><c>ERL_NIF_UNIQUE_POSITIVE</c> and <c>ERL_NIF_UNIQUE_MONOTONIC</c> + can be passed as the second argument to change the properties of the + integer returned. They can be combined by OR:ing the two values + together.</p> + <p>See also <seealso marker="#ErlNifUniqueInteger"> + <c>ErlNifUniqueInteger</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_map_iterator_create(ErlNifEnv *env, + ERL_NIF_TERM map, ErlNifMapIterator *iter, ErlNifMapIteratorEntry + entry)</nametext></name> + <fsummary>Create a map iterator.</fsummary> + <desc> + <p>Creates an iterator for the map <c>map</c> by initializing the + structure pointed to by <c>iter</c>. Argument <c>entry</c> determines + the start position of the iterator: <c>ERL_NIF_MAP_ITERATOR_FIRST</c> + or <c>ERL_NIF_MAP_ITERATOR_LAST</c>.</p> + <p>Returns <c>true</c> on success, or false if <c>map</c> is not a + map.</p> + <p>A map iterator is only useful during the lifetime of environment + <c>env</c> that the <c>map</c> belongs to. The iterator must be + destroyed by calling <seealso marker="#enif_map_iterator_destroy"> + <c>enif_map_iterator_destroy</c></seealso>:</p> + <code type="none"> +ERL_NIF_TERM key, value; +ErlNifMapIterator iter; +enif_map_iterator_create(env, my_map, &iter, ERL_NIF_MAP_ITERATOR_FIRST); + +while (enif_map_iterator_get_pair(env, &iter, &key, &value)) { + do_something(key,value); + enif_map_iterator_next(env, &iter); +} +enif_map_iterator_destroy(env, &iter);</code> + <note> + <p>The key-value pairs of a map have no defined iteration order. + The only guarantee is that the iteration order of a single map + instance is preserved during the lifetime of the environment that + the map belongs to.</p> + </note> + </desc> + </func> + + <func> + <name><ret>void</ret><nametext>enif_map_iterator_destroy(ErlNifEnv *env, + ErlNifMapIterator *iter)</nametext></name> + <fsummary>Destroy a map iterator.</fsummary> + <desc> + <p>Destroys a map iterator created by + <seealso marker="#enif_map_iterator_create"> + <c>enif_map_iterator_create</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_map_iterator_get_pair(ErlNifEnv *env, + ErlNifMapIterator *iter, ERL_NIF_TERM *key, ERL_NIF_TERM + *value)</nametext></name> + <fsummary>Get key and value at current map iterator position.</fsummary> + <desc> + <p>Gets key and value terms at the current map iterator position.</p> + <p>On success, sets <c>*key</c> and <c>*value</c> and returns + <c>true</c>. Returns <c>false</c> if the iterator is positioned at + head (before first entry) or tail (beyond last entry).</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_map_iterator_is_head(ErlNifEnv *env, + ErlNifMapIterator *iter)</nametext></name> + <fsummary>Check if map iterator is positioned before first.</fsummary> + <desc> + <p>Returns <c>true</c> if map iterator <c>iter</c> is positioned + before the first entry.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_map_iterator_is_tail(ErlNifEnv *env, + ErlNifMapIterator *iter)</nametext></name> + <fsummary>Check if map iterator is positioned after last.</fsummary> + <desc> + <p>Returns <c>true</c> if map iterator <c>iter</c> is positioned + after the last entry.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_map_iterator_next(ErlNifEnv *env, + ErlNifMapIterator *iter)</nametext></name> + <fsummary>Increment map iterator to point to next entry.</fsummary> + <desc> + <p>Increments map iterator to point to the next key-value entry.</p> + <p>Returns <c>true</c> if the iterator is now positioned at a valid + key-value entry, or <c>false</c> if the iterator is positioned at + the tail (beyond the last entry).</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_map_iterator_prev(ErlNifEnv *env, + ErlNifMapIterator *iter)</nametext></name> + <fsummary>Decrement map iterator to point to previous entry.</fsummary> + <desc> + <p>Decrements map iterator to point to the previous key-value entry.</p> + <p>Returns <c>true</c> if the iterator is now positioned at a valid + key-value entry, or <c>false</c> if the iterator is positioned at + the head (before the first entry).</p> + </desc> + </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> + <fsummary>Get Erlang monotonic time.</fsummary> + <desc> + <marker id="enif_monotonic_time"></marker> + <p>Returns the current + <seealso marker="time_correction#Erlang_Monotonic_Time"> + Erlang monotonic time</seealso>. Notice that it is not uncommon with + negative values.</p> + <p><c>time_unit</c> is the time unit of the returned value.</p> + <p>Returns <c>ERL_NIF_TIME_ERROR</c> if called with an invalid time + unit argument, or if called from a thread that is not a scheduler + thread.</p> + <p>See also <seealso marker="#ErlNifTime"><c>ErlNifTime</c></seealso> + and <seealso marker="#ErlNifTimeUnit"><c>ErlNifTimeUnit</c></seealso>. + </p> + </desc> + </func> + + <func> + <name><ret>ErlNifMutex *</ret> + <nametext>enif_mutex_create(char *name)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_mutex_create"> + <c>erl_drv_mutex_create</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_mutex_destroy(ErlNifMutex *mtx)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_mutex_destroy"> + <c>erl_drv_mutex_destroy</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_mutex_lock(ErlNifMutex *mtx)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_mutex_lock"> + <c>erl_drv_mutex_lock</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>char*</ret> + <nametext>enif_mutex_name(ErlNifMutex* mtx)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_mutex_name"> + <c>erl_drv_mutex_name</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_mutex_trylock(ErlNifMutex *mtx)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_mutex_trylock"> + <c>erl_drv_mutex_trylock</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_mutex_unlock(ErlNifMutex *mtx)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_mutex_unlock"> + <c>erl_drv_mutex_unlock</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret> + <nametext>enif_now_time(ErlNifEnv *env)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Returns an <seealso marker="erlang#now-0"> + <c>erlang:now()</c></seealso> time stamp.</p> + <p><em>This function is deprecated.</em></p> + </desc> + </func> + + <func> + <name><ret>ErlNifResourceType *</ret> + <nametext>enif_open_resource_type(ErlNifEnv* env, const char* + module_str, const char* name, ErlNifResourceDtor* dtor, + ErlNifResourceFlags flags, ErlNifResourceFlags* tried)</nametext> + </name> + <fsummary>Create or takeover a resource type.</fsummary> + <desc> + <p>Creates or takes over a resource type identified by the string + <c>name</c> and gives it the destructor function pointed to by + <seealso marker="#ErlNifResourceDtor"><c>dtor</c></seealso>. + Argument <c>flags</c> can have the following values:</p> + <taglist> + <tag><c>ERL_NIF_RT_CREATE</c></tag> + <item>Creates a new resource type that does not already exist.</item> + <tag><c>ERL_NIF_RT_TAKEOVER</c></tag> + <item>Opens an existing resource type and takes over ownership of all + its instances. The supplied destructor <c>dtor</c> is called both + for existing instances and new instances not yet created by the + calling NIF library.</item> + </taglist> + <p>The two flag values can be combined with bitwise OR. The resource + type name is local to the calling module. Argument <c>module_str</c> + is not (yet) used and must be <c>NULL</c>. <c>dtor</c> can be + <c>NULL</c> if no destructor is needed.</p> + <p>On success, the function returns a pointer to the resource type and + <c>*tried</c> is set to either <c>ERL_NIF_RT_CREATE</c> or + <c>ERL_NIF_RT_TAKEOVER</c> to indicate what was done. On failure, + 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 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> + + <func> + <name><ret>int</ret><nametext>enif_port_command(ErlNifEnv* env, const + ErlNifPort* to_port, ErlNifEnv *msg_env, ERL_NIF_TERM msg)</nametext> + </name> + <fsummary>Send a port_command to to_port.</fsummary> + <desc> + <p>Works as <seealso marker="erlang#port_command-2"> + <c>erlang:port_command/2</c></seealso>, + except that it is always completely asynchronous.</p> + <taglist> + <tag><c>env</c></tag> + <item>The environment of the calling process. Must not be + <c>NULL</c>.</item> + <tag><c>*to_port</c></tag> + <item>The port ID of the receiving port. The port ID is to refer to a + port on the local node.</item> + <tag><c>msg_env</c></tag> + <item>The environment of the message term. Can be a process-independent + environment allocated with <seealso marker="#enif_alloc_env"> + <c>enif_alloc_env</c></seealso> or <c>NULL</c>.</item> + <tag><c>msg</c></tag> + <item>The message term to send. The same limitations apply as on the + payload to <seealso marker="erlang#port_command-2"> + <c>erlang:port_command/2</c></seealso>.</item> + </taglist> + <p>Using a <c>msg_env</c> of <c>NULL</c> is an optimization, which + groups together calls to <c>enif_alloc_env</c>, <c>enif_make_copy</c>, + <c>enif_port_command</c>, and <c>enif_free_env</c> into one call. + This optimization is only useful when a majority of the terms are to + be copied from <c>env</c> to <c>msg_env</c>.</p> + <p>Returns <c>true</c> if the command is successfully sent. Returns + <c>false</c> if the command fails, for example:</p> + <list type="bulleted"> + <item><c>*to_port</c> does not refer to a local port.</item> + <item>The currently executing process (that is, the sender) is not + alive.</item> + <item><c>msg</c> is invalid.</item> + </list> + <p>See also <seealso marker="#enif_get_local_port"> + <c>enif_get_local_port</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void *</ret> + <nametext>enif_priv_data(ErlNifEnv* env)</nametext></name> + <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> or + <seealso marker="#upgrade"><c>upgrade</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_raise_exception(ErlNifEnv* + env, ERL_NIF_TERM reason)</nametext></name> + <fsummary>Raise a NIF error exception.</fsummary> + <desc> + <p>Creates an error exception with the term <c>reason</c> to be + returned from a NIF, and associates it with environment <c>env</c>. + Once a NIF or any function it calls invokes + <c>enif_raise_exception</c>, the runtime ensures that the exception + it creates is raised when the NIF returns, even if the NIF attempts + to return a non-exception term instead.</p> + <p>The return value from <c>enif_raise_exception</c> can only be used + as the return value from the NIF that invoked it (directly or + indirectly) or be passed to <seealso marker="#enif_is_exception"> + <c>enif_is_exception</c></seealso>, but not to any other NIF API + function.</p> + <p>See also <seealso marker="#enif_has_pending_exception"> + <c>enif_has_pending_exception</c></seealso> and + <seealso marker="#enif_make_badarg"> + <c>enif_make_badarg</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void *</ret> + <nametext>enif_realloc(void* ptr, size_t size)</nametext></name> + <fsummary>Reallocate dynamic memory.</fsummary> + <desc> + <p>Reallocates memory allocated by + <seealso marker="#enif_alloc"><c>enif_alloc</c></seealso> to + <c>size</c> bytes.</p> + <p>Returns <c>NULL</c> if the reallocation fails.</p> + <p>The returned pointer is suitably aligned for any built-in type that + fit in the allocated memory.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_realloc_binary(ErlNifBinary* bin, size_t size)</nametext> + </name> <fsummary>Change the size of a binary.</fsummary> - <desc><p>Change the size of a binary <c>bin</c>. The source binary - may be read-only, in which case it will be left untouched and - a mutable copy is allocated and assigned to <c>*bin</c>. Return true on success, - false if memory allocation failed.</p></desc> + <desc> + <p>Changes the size of a binary <c>bin</c>. The source binary + can be read-only, in which case it is left untouched and + a mutable copy is allocated and assigned to <c>*bin</c>.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if memory allocation + failed.</p> + </desc> </func> - <func><name><ret>void</ret><nametext>enif_release_binary(ErlNifBinary* bin)</nametext></name> + + <func> + <name><ret>void</ret> + <nametext>enif_release_binary(ErlNifBinary* bin)</nametext></name> <fsummary>Release a binary.</fsummary> - <desc><p>Release a binary obtained from <c>enif_alloc_binary</c>.</p></desc> + <desc> + <p>Releases a binary obtained from + <seealso marker="#enif_alloc_binary"> + <c>enif_alloc_binary</c></seealso>.</p> + </desc> </func> - <func><name><ret>void</ret><nametext>enif_release_resource(void* obj)</nametext></name> + + <func> + <name><ret>void</ret> + <nametext>enif_release_resource(void* obj)</nametext></name> <fsummary>Release a resource object.</fsummary> - <desc><p>Remove a reference to resource object <c>obj</c>obtained from - <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>. - The resource object will be destructed when the last reference is removed. - Each call to <c>enif_release_resource</c> must correspond to a previous - call to <c>enif_alloc_resource</c> or - <seealso marker="#enif_keep_resource">enif_keep_resource</seealso>. - References made by <seealso marker="#enif_make_resource">enif_make_resource</seealso> - can only be removed by the garbage collector.</p></desc> - </func> - <func><name><ret>ErlNifRWLock *</ret><nametext>enif_rwlock_create(char *name)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_create">erl_drv_rwlock_create</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_rwlock_destroy(ErlNifRWLock *rwlck)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_destroy">erl_drv_rwlock_destroy</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_rwlock_rlock(ErlNifRWLock *rwlck)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rlock">erl_drv_rwlock_rlock</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_rwlock_runlock(ErlNifRWLock *rwlck)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_runlock">erl_drv_rwlock_runlock</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_rwlock_rwlock(ErlNifRWLock *rwlck)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rwlock">erl_drv_rwlock_rwlock</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_rwlock_rwunlock(ErlNifRWLock *rwlck)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rwunlock">erl_drv_rwlock_rwunlock</seealso>. - </p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_rwlock_tryrlock(ErlNifRWLock *rwlck)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_tryrlock">erl_drv_rwlock_tryrlock</seealso>. - </p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_rwlock_tryrwlock(ErlNifRWLock *rwlck)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_rwlock_tryrwlock">erl_drv_rwlock_tryrwlock</seealso>. - </p></desc> - </func> - <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_schedule_nif(ErlNifEnv* env, const char* fun_name, int flags, ERL_NIF_TERM (*fp)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]), int argc, const ERL_NIF_TERM argv[])</nametext></name> - <fsummary>Schedule a NIF for execution</fsummary> - <desc> - <p>Schedule NIF <c>fp</c> to execute. This function allows an 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 (<em>note that the dirty NIF functionality described here is - experimental</em> and that you have to enable support for dirty schedulers when building OTP in - order to try the functionality out).</p> - <p>The <c>fun_name</c> argument provides a name for the NIF being scheduled for execution. If it cannot - be converted to an atom, <c>enif_schedule_nif</c> returns a <c>badarg</c> exception.</p> - <p>The <c>flags</c> argument must be set to 0 for a regular NIF, or if the emulator was built the - experimental 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 primarily 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, a try to schedule such a job - will result in a <c>badarg</c> exception.</p> - - <p>The <c>argc</c> and <c>argv</c> arguments can either be the originals passed into the calling NIF, or - they can be values created by the calling NIF.</p> - <p>The calling NIF must use the return value of <c>enif_schedule_nif</c> as its own return value.</p> - <p>Be aware that <c>enif_schedule_nif</c>, as its name implies, only schedules the - NIF for future execution. The calling NIF does not block waiting for the scheduled NIF to - execute and return, which means that the calling NIF can't expect to receive the scheduled NIF + <desc> + <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. + Each call to <c>enif_release_resource</c> must correspond to a + previous call to <c>enif_alloc_resource</c> or + <seealso marker="#enif_keep_resource"> + <c>enif_keep_resource</c></seealso>. + References made by <seealso marker="#enif_make_resource"> + <c>enif_make_resource</c></seealso> + can only be removed by the garbage collector.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifRWLock *</ret> + <nametext>enif_rwlock_create(char *name)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_create"> + <c>erl_drv_rwlock_create</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_rwlock_destroy(ErlNifRWLock *rwlck)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_destroy"> + <c>erl_drv_rwlock_destroy</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>char*</ret> + <nametext>enif_rwlock_name(ErlNifRWLock* rwlck)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_name"> + <c>erl_drv_rwlock_name</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_rwlock_rlock(ErlNifRWLock *rwlck)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rlock"> + <c>erl_drv_rwlock_rlock</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_rwlock_runlock(ErlNifRWLock *rwlck)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_runlock"> + <c>erl_drv_rwlock_runlock</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_rwlock_rwlock(ErlNifRWLock *rwlck)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rwlock"> + <c>erl_drv_rwlock_rwlock</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_rwlock_rwunlock(ErlNifRWLock *rwlck)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_rwunlock"> + <c>erl_drv_rwlock_rwunlock</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_rwlock_tryrlock(ErlNifRWLock *rwlck)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_tryrlock"> + <c>erl_drv_rwlock_tryrlock</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_rwlock_tryrwlock(ErlNifRWLock *rwlck)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_rwlock_tryrwlock"> + <c>erl_drv_rwlock_tryrwlock</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ERL_NIF_TERM</ret><nametext>enif_schedule_nif(ErlNifEnv* env, + const char* fun_name, int flags, ERL_NIF_TERM (*fp)(ErlNifEnv* env, int + argc, const ERL_NIF_TERM argv[]), int argc, const ERL_NIF_TERM + argv[])</nametext></name> + <fsummary>Schedule a NIF for execution.</fsummary> + <desc> + <p>Schedules NIF <c>fp</c> to execute. This function allows an + 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> + <taglist> + <tag><c>fun_name</c></tag> + <item> + <p>Provides a name for the NIF that is scheduled for execution. + If it cannot be converted to an atom, <c>enif_schedule_nif</c> + returns a <c>badarg</c> exception.</p> + </item> + <tag><c>flags</c></tag> + <item> + <p>Must be set to <c>0</c> for a regular NIF. If the emulator was + 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>notsup</c> exception.</p> + </item> + <tag><c>argc</c> and <c>argv</c></tag> + <item> + <p>Can either be the originals passed into the calling NIF, + or can be values created by the calling NIF.</p> + </item> + </taglist> + <p>The calling NIF must use the return value of + <c>enif_schedule_nif</c> as its own return value.</p> + <p>Be aware that <c>enif_schedule_nif</c>, as its name implies, only + schedules the NIF for future execution. The calling NIF does not + block waiting for the scheduled NIF to execute and return. This means + that the calling NIF cannot expect to receive the scheduled NIF return value and use it for further operations.</p> </desc> </func> - <func><name><ret>ErlNifPid *</ret><nametext>enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)</nametext></name> + + <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 triggered, + a notification message like this is sent to the process identified by + <c>pid</c>:</p> + <code type="none">{select, Obj, Ref, ready_input | ready_output}</code> + <p><c>ready_input</c> or <c>ready_output</c> indicates if the event object + is ready for reading or writing.</p> + <p>Argument <c>pid</c> may be <c>NULL</c> to indicate the calling process.</p> + <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 following 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 value. + New significant bits may be added in future releases to give more detailed + information for both failed and successful calls. Do NOT use equality 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> <fsummary>Get the pid of the calling process.</fsummary> - <desc><p>Initialize the pid variable <c>*pid</c> to represent the - calling process. Return <c>pid</c>.</p></desc> + <desc> + <p>Initializes the <seealso marker="#ErlNifPid"><c>ErlNifPid</c></seealso> + variable at <c>*pid</c> to represent the calling process.</p> + <p>Returns <c>pid</c> if successful, or NULL if <c>caller_env</c> is not + a <seealso marker="#ErlNifEnv">process-bound environment</seealso>.</p> + </desc> </func> - <func><name><ret>int</ret><nametext>enif_send(ErlNifEnv* env, ErlNifPid* to_pid, ErlNifEnv* msg_env, ERL_NIF_TERM msg)</nametext></name> + + <func> + <name><ret>int</ret><nametext>enif_send(ErlNifEnv* env, ErlNifPid* to_pid, + ErlNifEnv* msg_env, ERL_NIF_TERM msg)</nametext></name> <fsummary>Send a message to a process.</fsummary> - <desc><p>Send a message to a process.</p> - <taglist> - <tag><c>env</c></tag> - <item>The environment of the calling process. Must be NULL if and - only if calling from a created thread.</item> - <tag><c>*to_pid</c></tag> - <item>The pid of the receiving process. The pid should refer to a process on the local node.</item> - <tag><c>msg_env</c></tag> - <item>The environment of the message term. Must be a process - independent environment allocated with - <seealso marker="#enif_alloc_env">enif_alloc_env</seealso>.</item> - <tag><c>msg</c></tag> - <item>The message term to send.</item> - </taglist> - <p>Return true on success, or false if <c>*to_pid</c> does not refer to an alive local process.</p> - <p>The message environment <c>msg_env</c> with all its terms (including - <c>msg</c>) will be invalidated by a successful call to <c>enif_send</c>. The environment - should either be freed with <seealso marker="#enif_free_env">enif_free_env</seealso> - of cleared for reuse with <seealso marker="#enif_clear_env">enif_clear_env</seealso>.</p> - <p>This function is only thread-safe when the emulator with SMP support is used. - It can only be used in a non-SMP emulator from a NIF-calling thread.</p> - </desc> - </func> - <func><name><ret>unsigned</ret><nametext>enif_sizeof_resource(void* obj)</nametext></name> - <fsummary>Get the byte size of a resource object</fsummary> - <desc><p>Get the byte size of a resource object <c>obj</c> obtained by - <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>.</p></desc> - </func> - <func> - <name><ret>void</ret><nametext>enif_system_info(ErlNifSysInfo *sys_info_ptr, size_t size)</nametext></name> - <fsummary>Get information about the Erlang runtime system</fsummary> - <desc><p>Same as <seealso marker="erl_driver#driver_system_info">driver_system_info</seealso>. - </p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_thread_create(char *name,ErlNifTid *tid,void * (*func)(void *),void *args,ErlNifThreadOpts *opts)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_create">erl_drv_thread_create</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_thread_exit(void *resp)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_exit">erl_drv_thread_exit</seealso>. - </p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_thread_join(ErlNifTid, void **respp)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_join">erl_drv_thread_join </seealso>. - </p></desc> - </func> - <func><name><ret>ErlNifThreadOpts *</ret><nametext>enif_thread_opts_create(char *name)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_opts_create">erl_drv_thread_opts_create</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_thread_opts_destroy(ErlNifThreadOpts *opts)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_opts_destroy">erl_drv_thread_opts_destroy</seealso>. - </p></desc> - </func> - <func><name><ret>ErlNifTid</ret><nametext>enif_thread_self(void)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_thread_self">erl_drv_thread_self</seealso>. - </p></desc> - </func> - <func><name><ret>int</ret><nametext>enif_tsd_key_create(char *name, ErlNifTSDKey *key)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_key_create">erl_drv_tsd_key_create</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_tsd_key_destroy(ErlNifTSDKey key)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_key_destroy">erl_drv_tsd_key_destroy</seealso>. - </p></desc> - </func> - <func><name><ret>void *</ret><nametext>enif_tsd_get(ErlNifTSDKey key)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_get">erl_drv_tsd_get</seealso>. - </p></desc> - </func> - <func><name><ret>void</ret><nametext>enif_tsd_set(ErlNifTSDKey key, void *data)</nametext></name> - <fsummary></fsummary> - <desc><p>Same as <seealso marker="erl_driver#erl_drv_tsd_set">erl_drv_tsd_set</seealso>. - </p></desc> + <desc> + <p>Sends a message to a process.</p> + <taglist> + <tag><c>env</c></tag> + <item>The environment of the calling process. Must be <c>NULL</c> + only if calling from a created thread.</item> + <tag><c>*to_pid</c></tag> + <item>The pid of the receiving process. The pid is to refer to a + process on the local node.</item> + <tag><c>msg_env</c></tag> + <item>The environment of the message term. Must be a + process-independent environment allocated with + <seealso marker="#enif_alloc_env"><c>enif_alloc_env</c></seealso> + or NULL.</item> + <tag><c>msg</c></tag> + <item>The message term to send.</item> + </taglist> + <p>Returns <c>true</c> if the message is successfully sent. Returns + <c>false</c> if the send operation fails, that is:</p> + <list type="bulleted"> + <item><c>*to_pid</c> does not refer to an alive local process.</item> + <item>The currently executing process (that is, the sender) is not + alive.</item> + </list> + <p>The message environment <c>msg_env</c> with all its terms (including + <c>msg</c>) is invalidated by a successful call to <c>enif_send</c>. + The environment is to either be freed with + <seealso marker="#enif_free_env"> + <c>enif_free_env</c></seealso> of cleared for reuse with + <seealso marker="#enif_clear_env"><c>enif_clear_env</c></seealso>.</p> + <p>If <c>msg_env</c> is set to <c>NULL</c>, the <c>msg</c> term is + copied and the original term and its environment is still valid after + the call.</p> + <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> + <note> + <p>Passing <c>msg_env</c> as <c>NULL</c> is only supported as from + ERTS 8.0 (Erlang/OTP 19).</p> + </note> + </desc> + </func> + + <func> + <name><ret>unsigned</ret> + <nametext>enif_sizeof_resource(void* obj)</nametext></name> + <fsummary>Get the byte size of a resource object.</fsummary> + <desc> + <p>Gets the byte size of resource object <c>obj</c> obtained by + <seealso marker="#enif_alloc_resource"> + <c>enif_alloc_resource</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_snprintf(char *str, size_t size, const + char *format, ...)</nametext></name> + <fsummary>Format strings and Erlang terms.</fsummary> + <desc> + <p>Similar to <c>snprintf</c> but this format string also accepts + <c>"%T"</c>, which formats Erlang terms of type + <seealso marker="#ERL_NIF_TERM"><c>ERL_NIF_TERM</c></seealso>.</p> + <p>This function is primarily intended for debugging purpose. It is not + recommended to print very large terms with <c>%T</c>. The function may + change <c>errno</c>, even if successful.</p> + </desc> + </func> + + <func> + <name><ret>void</ret><nametext>enif_system_info(ErlNifSysInfo + *sys_info_ptr, size_t size)</nametext></name> + <fsummary>Get information about the Erlang runtime system.</fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#driver_system_info"> + <c>driver_system_info</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret><nametext>enif_term_to_binary(ErlNifEnv *env, + ERL_NIF_TERM term, ErlNifBinary *bin)</nametext></name> + <fsummary>Convert a term to the external format.</fsummary> + <desc> + <p>Allocates a new binary with <seealso marker="#enif_alloc_binary"> + <c>enif_alloc_binary</c></seealso> and stores the result of encoding + <c>term</c> according to the Erlang external term format.</p> + <p>Returns <c>true</c> on success, or <c>false</c> if the allocation + fails.</p> + <p>See also <seealso marker="erlang#term_to_binary-1"> + <c>erlang:term_to_binary/1</c></seealso> and + <seealso marker="#enif_binary_to_term"> + <c>enif_binary_to_term</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_thread_create(char *name,ErlNifTid + *tid,void * (*func)(void *),void *args,ErlNifThreadOpts + *opts)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_thread_create"> + <c>erl_drv_thread_create</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_thread_exit(void *resp)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_thread_exit"> + <c>erl_drv_thread_exit</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_thread_join(ErlNifTid, void **respp)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_thread_join"> + <c>erl_drv_thread_join</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>char*</ret> + <nametext>enif_thread_name(ErlNifTid tid)</nametext></name> + <fsummary>Thread name</fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_thread_name"> + <c>erl_drv_thread_name</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifThreadOpts *</ret> + <nametext>enif_thread_opts_create(char *name)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_thread_opts_create"> + <c>erl_drv_thread_opts_create</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_thread_opts_destroy(ErlNifThreadOpts *opts)</nametext> + </name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_thread_opts_destroy"> + <c>erl_drv_thread_opts_destroy</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>ErlNifTid</ret> + <nametext>enif_thread_self(void)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_thread_self"> + <c>erl_drv_thread_self</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_thread_type(void)</nametext></name> + <fsummary>Determine type of current thread</fsummary> + <desc> + <p>Determine the type of currently executing thread. A positive value + indicates a scheduler thread while a negative value or zero indicates + another type of thread. Currently the following specific types exist + (which may be extended in the future):</p> + <taglist> + <tag><c>ERL_NIF_THR_UNDEFINED</c></tag> + <item><p>Undefined thread that is not a scheduler thread.</p></item> + <tag><c>ERL_NIF_THR_NORMAL_SCHEDULER</c></tag> + <item><p>A normal scheduler thread.</p></item> + <tag><c>ERL_NIF_THR_DIRTY_CPU_SCHEDULER</c></tag> + <item><p>A dirty CPU scheduler thread.</p></item> + <tag><c>ERL_NIF_THR_DIRTY_IO_SCHEDULER</c></tag> + <item><p>A dirty I/O scheduler thread.</p></item> + </taglist> + </desc> + </func> + + <func> + <name><ret>ErlNifTime</ret> + <nametext>enif_time_offset(ErlNifTimeUnit time_unit)</nametext></name> + <fsummary>Get current time offset.</fsummary> + <desc> + <marker id="enif_time_offset"></marker> + <p>Returns the current time offset between + <seealso marker="time_correction#Erlang_Monotonic_Time"> + Erlang monotonic time</seealso> and + <seealso marker="time_correction#Erlang_System_Time"> + Erlang system time</seealso> + converted into the <c>time_unit</c> passed as argument.</p> + <p><c>time_unit</c> is the time unit of the returned value.</p> + <p>Returns <c>ERL_NIF_TIME_ERROR</c> if called with an invalid + time unit argument or if called from a thread that is not a + scheduler thread.</p> + <p>See also <seealso marker="#ErlNifTime"><c>ErlNifTime</c></seealso> + and + <seealso marker="#ErlNifTimeUnit"><c>ErlNifTimeUnit</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void *</ret> + <nametext>enif_tsd_get(ErlNifTSDKey key)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_tsd_get"> + <c>erl_drv_tsd_get</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_tsd_key_create(char *name, ErlNifTSDKey *key)</nametext> + </name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_tsd_key_create"> + <c>erl_drv_tsd_key_create</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_tsd_key_destroy(ErlNifTSDKey key)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_tsd_key_destroy"> + <c>erl_drv_tsd_key_destroy</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>void</ret> + <nametext>enif_tsd_set(ErlNifTSDKey key, void *data)</nametext></name> + <fsummary></fsummary> + <desc> + <p>Same as <seealso marker="erl_driver#erl_drv_tsd_set"> + <c>erl_drv_tsd_set</c></seealso>.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_vfprintf(FILE *stream, const char *format, va_list ap) + </nametext></name> + <fsummary>Format strings and Erlang terms.</fsummary> + <desc> + <p>Equivalent to <seealso marker="#enif_fprintf"><c>enif_fprintf</c></seealso> + except that its called with a <c>va_list</c> instead of a variable number of + arguments.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_vsnprintf(char *str, size_t size, const char *format, va_list ap) + </nametext></name> + <fsummary>Format strings and Erlang terms.</fsummary> + <desc> + <p>Equivalent to <seealso marker="#enif_snprintf"><c>enif_snprintf</c></seealso> + except that its called with a <c>va_list</c> instead of a variable number of + arguments.</p> + </desc> + </func> + + <func> + <name><ret>int</ret> + <nametext>enif_whereis_pid(ErlNifEnv *env, + ERL_NIF_TERM name, ErlNifPid *pid)</nametext></name> + <fsummary>Looks up a process by its registered name.</fsummary> + <desc> + <p>Looks up a process by its registered name.</p> + <taglist> + <tag><c>env</c></tag> + <item>The environment of the calling process. Must be <c>NULL</c> + only if calling from a created thread.</item> + <tag><c>name</c></tag> + <item>The name of a registered process, as an atom.</item> + <tag><c>*pid</c></tag> + <item>The <seealso marker="#ErlNifPid"><c>ErlNifPid</c></seealso> + in which the resolved process id is stored.</item> + </taglist> + <p>On success, sets <c>*pid</c> to the local process registered with + <c>name</c> and returns <c>true</c>. If <c>name</c> is not a + registered process, or is not an atom, <c>false</c> is returned and + <c>*pid</c> is unchanged.</p> + <p>Works as <seealso marker="erlang#whereis-1"> + <c>erlang:whereis/1</c></seealso>, but restricted to processes. See + <seealso marker="#enif_whereis_port"><c>enif_whereis_port</c></seealso> + to resolve registered ports.</p> + </desc> </func> + + <func> + <name><ret>int</ret> + <nametext>enif_whereis_port(ErlNifEnv *env, + ERL_NIF_TERM name, ErlNifPort *port)</nametext></name> + <fsummary>Looks up a port by its registered name.</fsummary> + <desc> + <p>Looks up a port by its registered name.</p> + <taglist> + <tag><c>env</c></tag> + <item>The environment of the calling process. Must be <c>NULL</c> + only if calling from a created thread.</item> + <tag><c>name</c></tag> + <item>The name of a registered port, as an atom.</item> + <tag><c>*port</c></tag> + <item>The <seealso marker="#ErlNifPort"><c>ErlNifPort</c></seealso> + in which the resolved port id is stored.</item> + </taglist> + <p>On success, sets <c>*port</c> to the port registered with + <c>name</c> and returns <c>true</c>. If <c>name</c> is not a + registered port, or is not an atom, <c>false</c> is returned and + <c>*port</c> is unchanged.</p> + <p>Works as <seealso marker="erlang#whereis-1"> + <c>erlang:whereis/1</c></seealso>, but restricted to ports. See + <seealso marker="#enif_whereis_pid"><c>enif_whereis_pid</c></seealso> + to resolve registered processes.</p> + </desc> + </func> + </funcs> + <section> - <title>SEE ALSO</title> - <p><seealso marker="erlang#load_nif-2">erlang:load_nif/2</seealso></p> + <title>See Also</title> + <p><seealso marker="erlang#load_nif-2"> + <c>erlang:load_nif/2</c></seealso></p> </section> </cref> diff --git a/erts/doc/src/erl_prim_loader.xml b/erts/doc/src/erl_prim_loader.xml index 171f84decc..286bac6c93 100644 --- a/erts/doc/src/erl_prim_loader.xml +++ b/erts/doc/src/erl_prim_loader.xml @@ -4,20 +4,21 @@ <erlref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -29,108 +30,70 @@ <file>erl_prim_loader.xml</file> </header> <module>erl_prim_loader</module> - <modulesummary>Low Level Erlang Loader</modulesummary> + <modulesummary>Low-level Erlang loader.</modulesummary> <description> - <p><c>erl_prim_loader</c> is used to load all Erlang modules into - the system. The start script is also fetched with this low level + <p>This module is used to load all Erlang modules into + the system. The start script is also fetched with this low-level loader.</p> - <p><c>erl_prim_loader</c> knows about the environment and how to - fetch modules. The loader could, for example, fetch files using - the file system (with absolute file names as input), or a - database (where the binary format of a module is stored).</p> - <p>The <c>-loader Loader</c> command line flag can be used to - choose the method used by the <c>erl_prim_loader</c>. Two - <c>Loader</c> methods are supported by the Erlang runtime system: - <c>efile</c> and <c>inet</c>. If another loader is required, then - it has to be implemented by the user. The <c>Loader</c> provided - by the user must fulfill the protocol defined below, and it is - started with the <c>erl_prim_loader</c> by evaluating - <c>open_port({spawn,Loader},[binary])</c>.</p> - <warning><p>The support for loading of code from archive files is - experimental. The sole purpose of releasing it before it is ready - is to obtain early feedback. The file format, semantics, - interfaces etc. may be changed in a future release. The functions - <c>list_dir/1</c> and <c>read_file_info/1</c> as well as the flag - <c>-loader_debug</c> are also experimental</p></warning> + <p><c>erl_prim_loader</c> knows about the environment and how to + fetch modules.</p> + <p>Command-line flag <c>-loader Loader</c> can be used to + choose the method used by <c>erl_prim_loader</c>. Two + <c>Loader</c> methods are supported by the Erlang runtime system: + <c>efile</c> and <c>inet</c>.</p> </description> - <datatypes> - <datatype> - <name name="host"/> - </datatype> - </datatypes> <funcs> <func> - <name name="start" arity="3"/> - <fsummary>Start the Erlang low level loader</fsummary> - <desc> - <p>Starts the Erlang low level loader. This function is called - by the <c>init</c> process (and module). The <c>init</c> - process reads the command line flags <c>-id <anno>Id</anno></c>, - <c>-loader <anno>Loader</anno></c>, and <c>-hosts <anno>Hosts</anno></c>. These are - the arguments supplied to the <c>start/3</c> function.</p> - <p>If <c>-loader</c> is not given, the default loader is - <c>efile</c> which tells the system to read from the file - system.</p> - <p>If <c>-loader</c> is <c>inet</c>, the <c>-id <anno>Id</anno></c>, - <c>-hosts <anno>Hosts</anno></c>, and <c>-setcookie Cookie</c> flags must - also be supplied. <c><anno>Hosts</anno></c> identifies hosts which this - node can contact in order to load modules. One Erlang - runtime system with a <c>erl_boot_server</c> process must be - started on each of hosts given in <c><anno>Hosts</anno></c> in order to - answer the requests. See <seealso - marker="kernel:erl_boot_server">erl_boot_server(3)</seealso>.</p> - <p>If <c>-loader</c> is something else, the given port program - is started. The port program is supposed to follow - the protocol specified below.</p> - </desc> - </func> - <func> <name name="get_file" arity="1"/> - <fsummary>Get a file</fsummary> + <fsummary>Get a file.</fsummary> <desc> - <p>This function fetches a file using the low level loader. - <c><anno>Filename</anno></c> is either an absolute file name or just the name - of the file, for example <c>"lists.beam"</c>. If an internal + <p>Fetches a file using the low-level loader. + <c><anno>Filename</anno></c> is either an absolute filename or only + the name of the file, for example, <c>"lists.beam"</c>. If an internal path is set to the loader, this path is used to find the file. - If a user supplied loader is used, the path can be stripped - off if it is obsolete, and the loader does not use a path. <c><anno>FullName</anno></c> is the complete name of the fetched file. <c><anno>Bin</anno></c> is the contents of the file as a binary.</p> - - <p>The <c><anno>Filename</anno></c> can also be a file in an archive. For example + <p><c><anno>Filename</anno></c> can also be a file in an archive, + for example, <c>$OTPROOT/lib/</c><c>mnesia-4.4.7.ez/mnesia-4.4.7/ebin/</c><c>mnesia.beam</c>. - See <seealso marker="kernel:code">code(3)</seealso> about archive files.</p> + For information about archive files, see + <seealso marker="kernel:code"><c>code(3)</c></seealso>.</p> </desc> </func> + <func> <name name="get_path" arity="0"/> - <fsummary>Get the path set in the loader</fsummary> + <fsummary>Get the path set in the loader.</fsummary> <desc> - <p>This function gets the path set in the loader. The path is - set by the <c>init</c> process according to information found - in the start script.</p> + <p>Gets the path set in the loader. The path is + set by the <seealso marker="init"><c>init(3)</c></seealso> + process according to information found in the start script.</p> </desc> </func> + <func> <name name="list_dir" arity="1"/> - <fsummary>List files in a directory</fsummary> + <fsummary>List files in a directory.</fsummary> <desc> <p>Lists all the files in a directory. Returns - <c>{ok, <anno>Filenames</anno>}</c> if successful. Otherwise, it returns + <c>{ok, <anno>Filenames</anno>}</c> if successful, otherwise <c>error</c>. <c><anno>Filenames</anno></c> is a list of the names of all the files in the directory. The names are not sorted.</p> - <p>The <c><anno>Dir</anno></c> can also be a directory in an archive. For example + <p><c><anno>Dir</anno></c> can also be a directory in an archive, + for example, <c>$OTPROOT/lib/</c><c>mnesia-4.4.7.ez/mnesia-4.4.7/ebin</c>. - See <seealso marker="kernel:code">code(3)</seealso> about archive files.</p> + For information about archive files, see + <seealso marker="kernel:code"><c>code(3)</c></seealso>.</p> </desc> </func> + <func> <name name="read_file_info" arity="1"/> - <fsummary>Get information about a file</fsummary> + <fsummary>Get information about a file.</fsummary> <desc> <p>Retrieves information about a file. Returns <c>{ok, <anno>FileInfo</anno>}</c> if successful, otherwise @@ -140,22 +103,25 @@ from which the function is called:</p> <code type="none"> -include_lib("kernel/include/file.hrl").</code> - <p>See <seealso marker="kernel:file">file(3)</seealso> for more info about - the record <c>file_info</c>.</p> - <p>The <c><anno>Filename</anno></c> can also be a file in an archive. For example + <p>For more information about the record <c>file_info</c>, see + <seealso marker="kernel:file"><c>file(3)</c></seealso>.</p> + <p><c><anno>Filename</anno></c> can also be a file in an archive, + for example, <c>$OTPROOT/lib/</c><c>mnesia-4.4.7.ez/mnesia-4.4.7/ebin/</c><c>mnesia</c>. - See <seealso marker="kernel:code">code(3)</seealso> about archive files.</p> + For information about archive files, see + <seealso marker="kernel:code"><c>code(3)</c></seealso>.</p> </desc> </func> + <func> <name name="read_link_info" arity="1"/> - <fsummary>Get information about a link or file</fsummary> + <fsummary>Get information about a link or file.</fsummary> <desc> - <p>This function works like - <seealso marker="#read_file_info/1">read_file_info/1</seealso> + <p>Works like + <seealso marker="#read_file_info/1"><c>read_file_info/1</c></seealso> except that if <c><anno>Filename</anno></c> is a symbolic link, - information about the link will be returned in the <c>file_info</c> - record and the <c>type</c> field of the record will be set to + information about the link is returned in the <c>file_info</c> + record and the <c>type</c> field of the record is set to <c>symlink</c>.</p> <p>If <c><anno>Filename</anno></c> is not a symbolic link, this function returns exactly the same result as <c>read_file_info/1</c>. @@ -163,81 +129,62 @@ is always equivalent to <c>read_file_info/1</c>.</p> </desc> </func> + <func> <name name="set_path" arity="1"/> - <fsummary>Set the path of the loader</fsummary> + <fsummary>Set the path of the loader.</fsummary> <desc> - <p>This function sets the path of the loader if <c>init</c> + <p>Sets the path of the loader if + <seealso marker="init"><c>init(3)</c></seealso> interprets a <c>path</c> command in the start script.</p> </desc> </func> </funcs> <section> - <title>Protocol</title> - <p>The following protocol must be followed if a user provided - loader port program is used. The <c>Loader</c> port program is - started with the command - <c>open_port({spawn,Loader},[binary])</c>. The protocol is as - follows:</p> - <pre> -Function Send Receive -------------------------------------------------------------- -get_file [102 | FileName] [121 | BinaryFile] (on success) - [122] (failure) - -stop eof terminate</pre> - </section> - - <section> - <title>Command Line Flags</title> + <title>Command-Line Flags</title> <p>The <c>erl_prim_loader</c> module interprets the following - command line flags:</p> + command-line flags:</p> + <taglist> <tag><c>-loader Loader</c></tag> <item> <p>Specifies the name of the loader used by <c>erl_prim_loader</c>. <c>Loader</c> can be <c>efile</c> - (use the local file system), or <c>inet</c> (load using - the <c>boot_server</c> on another Erlang node). If - <c>Loader</c> is user defined, the defined <c>Loader</c> port - program is started.</p> - <p>If the <c>-loader</c> flag is omitted, it defaults to + (use the local file system) or <c>inet</c> (load using + the <c>boot_server</c> on another Erlang node).</p> + <p>If flag <c>-loader</c> is omitted, it defaults to <c>efile</c>.</p> </item> <tag><c>-loader_debug</c></tag> <item> <p>Makes the <c>efile</c> loader write some debug information, - such as the reason for failures, while it handles files.</p> + such as the reason for failures, while it handles files.</p> </item> <tag><c>-hosts Hosts</c></tag> <item> <p>Specifies which other Erlang nodes the <c>inet</c> loader - can use. This flag is mandatory if the <c>-loader inet</c> - flag is present. On each host, there must be on Erlang node - with the <c>erl_boot_server</c> which handles the load - requests. <c>Hosts</c> is a list of IP addresses (hostnames + can use. This flag is mandatory if flag <c>-loader inet</c> + is present. On each host, there must be on Erlang node + with the <seealso marker="kernel:erl_boot_server"> + <c>erl_boot_server(3)</c></seealso>, + which handles the load requests. + <c>Hosts</c> is a list of IP addresses (hostnames are not acceptable).</p> </item> - <tag><c>-id Id</c></tag> - <item> - <p>Specifies the identity of the Erlang runtime system. If - the system runs as a distributed node, <c>Id</c> must be - identical to the name supplied with the <c>-sname</c> or - <c>-name</c> distribution flags.</p> - </item> <tag><c>-setcookie Cookie</c></tag> <item> <p>Specifies the cookie of the Erlang runtime system. This flag - is mandatory if the <c>-loader inet</c> flag is present.</p> + is mandatory if flag <c>-loader inet</c> is present.</p> </item> </taglist> </section> <section> - <title>SEE ALSO</title> - <p><seealso marker="init">init(3)</seealso>, - <seealso marker="kernel:erl_boot_server">erl_boot_server(3)</seealso></p> + <title>See Also</title> + <p><seealso marker="init"><c>init(3)</c></seealso>, + <seealso marker="kernel:erl_boot_server"> + <c>erl_boot_server(3)</c></seealso></p> </section> </erlref> diff --git a/erts/doc/src/erl_tracer.xml b/erts/doc/src/erl_tracer.xml new file mode 100644 index 0000000000..fd3c17f337 --- /dev/null +++ b/erts/doc/src/erl_tracer.xml @@ -0,0 +1,781 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2016</year><year>2017</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + </legalnotice> + + <title>erl_tracer</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + </header> + <module>erl_tracer</module> + <modulesummary>Erlang tracer behavior.</modulesummary> + <description> + <p>This behavior module implements the back end of the Erlang + tracing system. The functions in this module are called whenever + a trace probe is triggered. Both the <c>enabled</c> and <c>trace</c> + functions are called in the context of the entity that triggered the + trace probe. + This means that the overhead by having the tracing enabled is + greatly effected by how much time is spent in these functions. So, do as + little work as possible in these functions.</p> + + <note> + <p>All functions in this behavior must be implemented as NIFs. + This limitation can be removed in a future releases. + An <seealso marker="#example">example tracer module NIF</seealso> + implementation is provided at the end of this page.</p> + </note> + + <warning> + <p>Do not send messages or issue port commands to the <c>Tracee</c> + in any of the callbacks. This is not allowed and can cause all + sorts of strange behavior, including, but not limited to, infinite + recursions.</p> + </warning> + </description> + + <datatypes> + <datatype> + <name name="trace_tag_call"/> + </datatype> + <datatype> + <name name="trace_tag_gc"/> + </datatype> + <datatype> + <name name="trace_tag_ports"/> + </datatype> + <datatype> + <name name="trace_tag_procs"/> + </datatype> + <datatype> + <name name="trace_tag_receive"/> + </datatype> + <datatype> + <name name="trace_tag_running_ports"/> + </datatype> + <datatype> + <name name="trace_tag_running_procs"/> + </datatype> + <datatype> + <name name="trace_tag_send"/> + </datatype> + <datatype> + <name name="trace_tag"/> + <desc> + <p>The different trace tags that the tracer is called with. + Each trace tag is described in detail in + <seealso marker="#Module:trace/5"><c>Module:trace/5</c></seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="tracee"/> + <desc> + <p>The process or port that the trace belongs to.</p> + </desc> + </datatype> + <datatype> + <name name="trace_opts"/> + <desc> + <p>The options for the tracee:</p> + <taglist> + <tag><c>timestamp</c></tag> + <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 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 + <seealso marker="erlang#trace_3_trace_messages"> + erlang:trace/3</seealso>.</item> + <tag><c>match_spec_result</c></tag> + <item>If set the tracer has been requested to include the output + of a match specification that was run.</item> + <tag><c>scheduler_id</c></tag> + <item>If set the scheduler id is to be included by the tracer.</item> + </taglist> + </desc> + </datatype> + <datatype> + <name name="tracer_state"/> + <desc> + <p>The state specified when calling + <seealso marker="erlang#trace-3"> + <c>erlang:trace(PidPortSpec,true,[{tracer,Module,TracerState}])</c></seealso>. + The tracer state is an immutable value that is passed to + <c>erl_tracer</c> callbacks and is to + contain all the data that is needed to generate the trace event.</p> + </desc> + </datatype> + </datatypes> + + <section> + <title>Callback Functions</title> + <p>The following functions are to be exported from an <c>erl_tracer</c> + callback module:</p> + + <taglist> + <tag><seealso marker="#Module:enabled/3"> + <c>Module:enabled/3</c></seealso></tag> + <item>Mandatory</item> + <tag><seealso marker="#Module:trace/5"> + <c>Module:trace/5</c></seealso></tag> + <item>Mandatory</item> + <tag><seealso marker="#Module:enabled_call/3"> + <c>Module:enabled_call/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_call/5"> + <c>Module:trace_call/5</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:enabled_garbage_collection/3"> + <c>Module:enabled_garbage_collection/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_garbage_collection/5"> + <c>Module:trace_garbage_collection/5</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:enabled_ports/3"> + <c>Module:enabled_ports/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_ports/5"> + <c>Module:trace_ports/5</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:enabled_procs/3"> + <c>Module:enabled_procs/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_procs/5"> + <c>Module:trace_procs/5</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:enabled_receive/3"> + <c>Module:enabled_receive/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_receive/5"> + <c>Module:trace_receive/5</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:enabled_running_ports/3"> + <c>Module:enabled_running_ports/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_running_ports/5"> + <c>Module:trace_running_ports/5</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:enabled_running_procs/3"> + <c>Module:enabled_running_procs/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_running_procs/5"> + <c>Module:trace_running_procs/5</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:enabled_send/3"> + <c>Module:enabled_send/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_send/5"> + <c>Module:trace_send/5</c></seealso></tag> + <item>Optional</item> + </taglist> + </section> + + <funcs> + <func> + <name>Module:enabled(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag"> + trace_tag()</seealso> | trace_status</v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback is called whenever a tracepoint is triggered. It + allows the tracer to decide whether a trace is to be generated or not. + This check is made as early as possible to limit the amount of + overhead associated with tracing. If <c>trace</c> is returned, the + necessary trace data is created and the trace callback of the tracer + is called. If <c>discard</c> is returned, this trace call is + discarded and no call to trace is done.</p> + <p><c>trace_status</c> is a special type of <c>TraceTag</c>, which is + used to check if the tracer is still to be active. It is called in + multiple scenarios, but most significantly it is used when tracing + is started using this tracer. If <c>remove</c> is returned when the + <c>trace_status</c> is checked, the tracer is removed from the + tracee.</p> + <p>This function can be called multiple times per tracepoint, so it + is important that it is both fast and without side effects.</p> + </desc> + </func> + + <func> + <name>Module:enabled_call(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_call"> + trace_tag_call()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback is called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>call | return_to</c></seealso> + is triggered.</p> + <p>If <c>enabled_call/3</c> is undefined, + <seealso marker="#Module:enabled/3"><c>Module:enabled/3</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_garbage_collection(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_gc"> + trace_tag_gc()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback is called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>garbage_collection</c></seealso> + is triggered.</p> + <p>If <c>enabled_garbage_collection/3</c> is undefined, + <seealso marker="#Module:enabled/3"><c>Module:enabled/3</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_ports(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_ports"> + trace_tag_ports()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback is called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>ports</c></seealso> + is triggered.</p> + <p>If <c>enabled_ports/3</c> is undefined, + <seealso marker="#Module:enabled/3"><c>Module:enabled/3</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_procs(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_procs"> + trace_tag_procs()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback is called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>procs</c></seealso> + is triggered.</p> + <p>If <c>enabled_procs/3</c> is undefined, + <seealso marker="#Module:enabled/3"><c>Module:enabled/3</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_receive(TraceTag, TracerState, Tracee) -> Result + </name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_receive"> + trace_tag_receive()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback is called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>'receive'</c></seealso> + is triggered.</p> + <p>If <c>enabled_receive/3</c> is undefined, + <seealso marker="#Module:enabled/3"><c>Module:enabled/3</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_running_ports(TraceTag, TracerState, Tracee) -> + Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_running_ports"> + trace_tag_running_ports()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback is called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>running_ports</c></seealso> + is triggered.</p> + <p>If <c>enabled_running_ports/3</c> is undefined, + <seealso marker="#Module:enabled/3"><c>Module:enabled/3</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_running_procs(TraceTag, TracerState, Tracee) -> + Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_running_procs"> + trace_tag_running_procs()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback is called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"> + <c>running_procs | running</c></seealso> + is triggered.</p> + <p>If <c>enabled_running_procs/3</c> is undefined, + <seealso marker="#Module:enabled/3"><c>Module:enabled/3</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_send(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_send"> + trace_tag_send()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback is called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>send</c></seealso> + is triggered.</p> + <p>If <c>enabled_send/3</c> is undefined, + <seealso marker="#Module:enabled/3"><c>Module:enabled/3</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag"> + trace_tag()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>TraceTerm = term()</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback is called when a tracepoint is triggered and the + <seealso marker="#Module:enabled/3"><c>Module:enabled/3</c></seealso> + callback returned <c>trace</c>. In it any side effects needed by + the tracer are to be done. The tracepoint payload is located in + the <c>TraceTerm</c>. The content of the <c>TraceTerm</c> + depends on which <c>TraceTag</c> is triggered. + <c>TraceTerm</c> corresponds to the + fourth element in the trace tuples described in + <seealso marker="erlang#trace_3_trace_messages"> + <c>erlang:trace/3</c></seealso>.</p> + <p>If the trace tuple has five elements, the fifth element + will be sent as the <c>extra</c> value in the <c>Opts</c> maps.</p> + </desc> + </func> + + <func> + <name name="trace">Module:trace(seq_trace, TracerState, Label, + SeqTraceInfo, Opts) -> Result</name> + <fsummary>Check if a sequence trace event is to be generated.</fsummary> + <type> + <v>TracerState = term()</v> + <v>Label = term()</v> + <v>SeqTraceInfo = term()</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>The <c>TraceTag</c> <c>seq_trace</c> is handled slightly + differently. There is no <c>Tracee</c> for <c>seq_trace</c>, instead + the <c>Label</c> associated with the <c>seq_trace</c> event is + specified.</p> + <p>For more information on what <c>Label</c> and <c>SeqTraceInfo</c> + can be, see <seealso marker="kernel:seq_trace"> + <c>seq_trace(3)</c></seealso>.</p> + </desc> + </func> + + <func> + <name>Module:trace_call(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_call"> + trace_tag_call()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>TraceTerm = term()</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback is called when a tracepoint is triggered and the + <seealso marker="#Module:enabled_call/3"> + <c>Module:enabled_call/3</c></seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_call/5</c> is undefined, + <seealso marker="#Module:trace/5"><c>Module:trace/5</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_garbage_collection(TraceTag, TracerState, Tracee, + TraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_gc"> + trace_tag_gc()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>TraceTerm = term()</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback is called when a tracepoint is triggered and the + <seealso marker="#Module:enabled_garbage_collection/3"> + <c>Module:enabled_garbage_collection/3</c></seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_garbage_collection/5</c> is undefined, + <seealso marker="#Module:trace/5"><c>Module:trace/5</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_ports(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_ports"> + trace_tag()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>TraceTerm = term()</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback is called when a tracepoint is triggered and the + <seealso marker="#Module:enabled_ports/3"> + <c>Module:enabled_ports/3</c></seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_ports/5</c> is undefined, + <seealso marker="#Module:trace/5"><c>Module:trace/5</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_procs(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_procs"> + trace_tag()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>TraceTerm = term()</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback is called when a tracepoint is triggered and the + <seealso marker="#Module:enabled_procs/3"> + <c>Module:enabled_procs/3</c></seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_procs/5</c> is undefined, + <seealso marker="#Module:trace/5"><c>Module:trace/5</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_receive(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_receive"> + trace_tag_receive()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>TraceTerm = term()</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback is called when a tracepoint is triggered and the + <seealso marker="#Module:enabled_receive/3"> + <c>Module:enabled_receive/3</c></seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_receive/5</c> is undefined, + <seealso marker="#Module:trace/5"><c>Module:trace/5</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_running_ports(TraceTag, TracerState, Tracee, + TraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_running_ports"> + trace_tag_running_ports()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>TraceTerm = term()</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback is called when a tracepoint is triggered and the + <seealso marker="#Module:enabled_running_ports/3"> + <c>Module:enabled_running_ports/3</c></seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_running_ports/5</c> is undefined, + <seealso marker="#Module:trace/5"><c>Module:trace/5</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_running_procs(TraceTag, TracerState, Tracee, + TraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_running_procs"> + trace_tag_running_procs()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>TraceTerm = term()</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback is called when a tracepoint is triggered and the + <seealso marker="#Module:enabled_running_procs/3"> + <c>Module:enabled_running_procs/3</c></seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_running_procs/5</c> is undefined, + <seealso marker="#Module:trace/5"><c>Module:trace/5</c></seealso> + is called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_send(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result</name> + <fsummary>Check if a trace event is to be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_send"> + trace_tag_send()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>TraceTerm = term()</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback is called when a tracepoint is triggered and the + <seealso marker="#Module:enabled_send/3"> + <c>Module:enabled_send/3</c></seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_send/5</c> is undefined, + <seealso marker="#Module:trace/5"><c>Module:trace/5</c></seealso> + is called instead.</p> + </desc> + </func> + </funcs> + + <section> + <marker id="example"></marker> + <title>Erl Tracer Module Example</title> + <p>In this example, a tracer module with a NIF back end sends a + message for each <c>send</c> trace tag containing only the sender and + receiver. Using this tracer module, a much more lightweight message + tracer is used, which only records who sent messages to who.</p> + + <p>The following is an example session using it on Linux:</p> + + <pre> +$ gcc -I erts-8.0/include/ -fPIC -shared -o erl_msg_tracer.so erl_msg_tracer.c +$ erl +Erlang/OTP 19 [DEVELOPMENT] [erts-8.0] [source-ed2b56b] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] + +Eshell V8.0 (abort with ^G) +1> c(erl_msg_tracer), erl_msg_tracer:load(). +ok +2> Tracer = spawn(fun F() -> receive M -> io:format("~p~n",[M]), F() end end). +<0.37.0> +3> erlang:trace(new, true, [send,{tracer, erl_msg_tracer, Tracer}]). +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>} +{trace,#Port<0.487>,<0.4.0>} +{trace,#Port<0.488>,<0.4.0>} +{trace,#Port<0.489>,<0.4.0>} +{trace,#Port<0.490>,<0.4.0>} +{ok,<0.40.0>} +{trace,<0.41.0>,<0.27.0>} +5></pre> + + <p><c>erl_msg_tracer.erl</c>:</p> + + <pre> +-module(erl_msg_tracer). + +-export([enabled/3, trace/5, load/0]). + +load() -> + erlang:load_nif("erl_msg_tracer", []). + +enabled(_, _, _) -> + error. + +trace(_, _, _, _, _) -> + error.</pre> + + <p><c>erl_msg_tracer.c</c>:</p> + + <pre> +#include <erl_nif.h> + +/* NIF interface declarations */ +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info); +static void unload(ErlNifEnv* env, void* priv_data); + +/* The NIFs: */ +static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); + +static ErlNifFunc nif_funcs[] = { + {"enabled", 3, enabled}, + {"trace", 5, trace} +}; + +ERL_NIF_INIT(erl_msg_tracer, nif_funcs, load, NULL, upgrade, unload) + +static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) +{ + *priv_data = NULL; + return 0; +} + +static void unload(ErlNifEnv* env, void* priv_data) +{ + +} + +static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, + ERL_NIF_TERM load_info) +{ + if (*old_priv_data != NULL || *priv_data != NULL) { + return -1; /* Don't know how to do that */ + } + if (load(env, priv_data, load_info)) { + return -1; + } + return 0; +} + +/* + * argv[0]: TraceTag + * argv[1]: TracerState + * argv[2]: Tracee + */ +static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + ErlNifPid to_pid; + if (enif_get_local_pid(env, argv[1], &to_pid)) + if (!enif_is_process_alive(env, &to_pid)) + if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0])) + /* tracer is dead so we should remove this tracepoint */ + return enif_make_atom(env, "remove"); + else + return enif_make_atom(env, "discard"); + + /* Only generate trace for when tracer != tracee */ + if (enif_is_identical(argv[1], argv[2])) + return enif_make_atom(env, "discard"); + + /* Only trigger trace messages on 'send' */ + if (enif_is_identical(enif_make_atom(env, "send"), argv[0])) + return enif_make_atom(env, "trace"); + + /* Have to answer trace_status */ + if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0])) + return enif_make_atom(env, "trace"); + + return enif_make_atom(env, "discard"); +} + +/* + * argv[0]: TraceTag, should only be 'send' + * argv[1]: TracerState, process to send {Tracee, Recipient} to + * argv[2]: Tracee + * 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)) { + 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"); +}</pre> + </section> +</erlref> diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 0e5909a52d..8e014c3010 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -4,20 +4,21 @@ <erlref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -29,50 +30,193 @@ <file>erlang.xml</file> </header> <module>erlang</module> - <modulesummary>The Erlang BIFs</modulesummary> + <modulesummary>The Erlang BIFs.</modulesummary> <description> - <p>By convention, most built-in functions (BIFs) are seen as being - in the module <c>erlang</c>. A number of the BIFs are viewed more + <p>By convention, most Built-In Functions (BIFs) are included + in this module. Some of the BIFs are viewed more or less as part of the Erlang programming language and are - <em>auto-imported</em>. Thus, it is not necessary to specify - the module name and both the calls <c>atom_to_list(Erlang)</c> and - <c>erlang:atom_to_list(Erlang)</c> are identical.</p> - <p>In the text, auto-imported BIFs are listed without module prefix. + <em>auto-imported</em>. Thus, it is not necessary to specify the + module name. For example, the calls <c>atom_to_list(erlang)</c> + and <c>erlang:atom_to_list(erlang)</c> are identical.</p> + + <p>Auto-imported BIFs are listed without module prefix. BIFs listed with module prefix are not auto-imported.</p> - <p>BIFs may fail for a variety of reasons. All BIFs fail with + + <p>BIFs can fail for various reasons. All BIFs fail with reason <c>badarg</c> if they are called with arguments of an - incorrect type. The other reasons that may make BIFs fail are - described in connection with the description of each individual - BIF.</p> - <p>Some BIFs may be used in guard tests, these are marked with + incorrect type. The other reasons are described in the + description of each individual BIF.</p> + + <p>Some BIFs can be used in guard tests and are marked with "Allowed in guard tests".</p> </description> <datatypes> <datatype> - <name><marker id="type-ext_binary">ext_binary()</marker></name> + <name name="ext_binary"/> <desc> <p>A binary data object, structured according to - the Erlang external term format.</p> + the Erlang external term format.</p> + </desc> + </datatype> + <datatype> + <name name="iovec"/> + <desc> + <p>A list of binaries. This datatype is useful to use + together with <seealso marker="erl_nif#enif_inspect_iovec"> + <c>enif_inspect_iovec</c></seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="message_queue_data"></name> + <desc> + <p>See <seealso marker="#process_flag_message_queue_data"> + <c>process_flag(message_queue_data, MQD)</c></seealso>.</p> </desc> </datatype> <datatype> <name name="timestamp"></name> - <desc><p>See <seealso marker="#now/0">now/0</seealso>.</p> + <desc> + <p>See <seealso marker="#timestamp/0"> + <c>erlang:timestamp/0</c></seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="time_unit"></name> + <desc> + <marker id="type_time_unit"/> + <p>Supported time unit representations:</p> + <taglist> + <tag><c>PartsPerSecond :: integer() >= 1</c></tag> + <item> + <p>Time unit expressed in parts per second. That is, + the time unit equals <c>1/PartsPerSecond</c> second.</p> + </item> + <tag><c>second</c></tag> + <item> + <p>Symbolic representation of the time unit + represented by the integer <c>1</c>.</p> + </item> + <tag><c>millisecond</c></tag> + <item> + <p>Symbolic representation of the time unit + represented by the integer <c>1000</c>.</p> + </item> + <tag><c>microsecond</c></tag> + <item> + <p>Symbolic representation of the time unit + represented by the integer <c>1000000</c>.</p> + </item> + <tag><c>nanosecond</c></tag> + <item> + <p>Symbolic representation of the time unit + represented by the integer <c>1000000000</c>.</p> + </item> + <tag><c>native</c></tag> + <item> + <p>Symbolic representation of the native time unit + used by the Erlang runtime system.</p> + <p>The <c>native</c> time unit is determined at + runtime system start, and remains the same until + the runtime system terminates. If a runtime system + is stopped and then started again (even on the same + machine), the <c>native</c> time unit of the new + runtime system instance can differ from the + <c>native</c> time unit of the old runtime system + instance.</p> + <p>One can get an approximation of the <c>native</c> + time unit by calling + <seealso marker="erlang:convert_time_unit/3"> + <c>erlang:convert_time_unit(1, second, native)</c></seealso>. + The result equals the number + of whole <c>native</c> time units per second. If + the number of <c>native</c> time units per second does not + add up to a whole number, the result is rounded downwards.</p> + <note> + <p>The value of the <c>native</c> time unit gives + you more or less no information about the + quality of time values. It sets a limit for the + <seealso marker="time_correction#Time_Resolution"> + resolution</seealso> and for the + <seealso marker="time_correction#Time_Precision"> + precision</seealso> of time values, + but it gives no information about the + <seealso marker="time_correction#Time_Accuracy"> + accuracy</seealso> of time values. The resolution of + the <c>native</c> time unit and the resolution of time + values can differ significantly.</p> + </note> + </item> + <tag><c>perf_counter</c></tag> + <item> + <p>Symbolic representation of the performance counter + time unit used by the Erlang runtime system.</p> + <p>The <c>perf_counter</c> time unit behaves much in the same way + as the <c>native</c> time unit. That is, it can differ between + runtime restarts. To get values of this type, call + <seealso marker="kernel:os#perf_counter/0"> + <c>os:perf_counter/0</c></seealso>.</p> + </item> + <tag><seealso marker="#type_deprecated_time_unit"><c>deprecated_time_unit()</c></seealso></tag> + <item><p> + Deprecated symbolic representations kept for backwards-compatibility. + </p></item> + </taglist> + <p>The <c>time_unit/0</c> type can be extended. + To convert time values between time units, use + <seealso marker="#convert_time_unit/3"> + <c>erlang:convert_time_unit/3</c></seealso>.</p> + </desc> + </datatype> + <datatype> + <name name="deprecated_time_unit"></name> + <desc><marker id="type_deprecated_time_unit"/> + <p>The <seealso marker="#type_time_unit"><c>time_unit()</c></seealso> + type also consist of the following <em>deprecated</em> symbolic + time units:</p> + <taglist> + <tag><c>seconds</c></tag> + <item><p>Same as <seealso marker="#type_time_unit"><c>second</c></seealso>.</p></item> + + <tag><c>milli_seconds</c></tag> + <item><p>Same as <seealso marker="#type_time_unit"><c>millisecond</c></seealso>.</p></item> + + <tag><c>micro_seconds</c></tag> + <item><p>Same as <seealso marker="#type_time_unit"><c>microsecond</c></seealso>.</p></item> + + <tag><c>nano_seconds</c></tag> + <item><p>Same as <seealso marker="#type_time_unit"><c>nanosecond</c></seealso>.</p></item> + </taglist> </desc> </datatype> + + <datatype> + <name name="dist_handle"></name> + <desc> + <p>An opaque handle identifing a distribution channel.</p> + </desc> + </datatype> + + <datatype> + <name name="nif_resource"></name> + <desc> + <p>An opaque handle identifing a + <seealso marker="erl_nif#resource_objects">NIF resource object + </seealso>.</p> + </desc> + </datatype> + </datatypes> <funcs> <func> <name name="abs" arity="1" clause_i="1"/> <name name="abs" arity="1" clause_i="2"/> - <type variable="Float" name_i="1"/> - <type variable="Int" name_i="2"/> - <fsummary>Arithmetical absolute value</fsummary> + <fsummary>Arithmetical absolute value.</fsummary> <desc> - <p>Returns an integer or float which is the arithmetical - absolute value of <c><anno>Float</anno></c> or <c><anno>Int</anno></c>.</p> + <p>Returns an integer or float that is the arithmetical + absolute value of <c><anno>Float</anno></c> or + <c><anno>Int</anno></c>, for example:</p> <pre> > <input>abs(-3.33).</input> 3.33 @@ -81,229 +225,245 @@ <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="adler32" arity="1"/> - <fsummary>Compute adler32 checksum</fsummary> + <fsummary>Compute adler32 checksum.</fsummary> <desc> - <p>Computes and returns the adler32 checksum for <c><anno>Data</anno></c>.</p> + <p>Computes and returns the adler32 checksum for + <c><anno>Data</anno></c>.</p> </desc> </func> + <func> <name name="adler32" arity="2"/> - <fsummary>Compute adler32 checksum</fsummary> + <fsummary>Compute adler32 checksum.</fsummary> <desc> - <p>Continue computing the adler32 checksum by combining - the previous checksum, <c><anno>OldAdler</anno></c>, with the checksum of - <c><anno>Data</anno></c>.</p> - <p>The following code:</p> - <code> - X = erlang:adler32(Data1), - Y = erlang:adler32(X,Data2). - </code> - <p>- would assign the same value to <c>Y</c> as this would:</p> - <code> - Y = erlang:adler32([Data1,Data2]). - </code> + <p>Continues computing the adler32 checksum by combining + the previous checksum, <c><anno>OldAdler</anno></c>, with + the checksum of <c><anno>Data</anno></c>.</p> + <p>The following code:</p> + <code> +X = erlang:adler32(Data1), +Y = erlang:adler32(X,Data2).</code> + <p>assigns the same value to <c>Y</c> as this:</p> + <code> +Y = erlang:adler32([Data1,Data2]).</code> </desc> </func> + <func> <name name="adler32_combine" arity="3"/> - <fsummary>Combine two adler32 checksums</fsummary> - <desc> - <p>Combines two previously computed adler32 checksums. - This computation requires the size of the data object for - the second checksum to be known.</p> - <p>The following code:</p> - <code> - Y = erlang:adler32(Data1), - Z = erlang:adler32(Y,Data2). - </code> - <p>- would assign the same value to <c>Z</c> as this would:</p> - <code> - X = erlang:adler32(Data1), - Y = erlang:adler32(Data2), - Z = erlang:adler32_combine(X,Y,iolist_size(Data2)). - </code> + <fsummary>Combine two adler32 checksums.</fsummary> + <desc> + <p>Combines two previously computed adler32 checksums. + This computation requires the size of the data object for + the second checksum to be known.</p> + <p>The following code:</p> + <code> +Y = erlang:adler32(Data1), +Z = erlang:adler32(Y,Data2).</code> + <p>assigns the same value to <c>Z</c> as this:</p> + <code> +X = erlang:adler32(Data1), +Y = erlang:adler32(Data2), +Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).</code> </desc> </func> + <func> <name name="append_element" arity="2"/> - <fsummary>Append an extra element to a tuple</fsummary> - <desc> - <p>Returns a new tuple which has one element more than - <c><anno>Tuple1</anno></c>, and contains the elements in <c><anno>Tuple1</anno></c> - followed by <c><anno>Term</anno></c> as the last element. Semantically - equivalent to - <c>list_to_tuple(tuple_to_list(<anno>Tuple1</anno>) ++ [<anno>Term</anno>])</c>, but much - faster.</p> + <fsummary>Append an extra element to a tuple.</fsummary> + <desc> + <p>Returns a new tuple that has one element more than + <c><anno>Tuple1</anno></c>, and contains the elements in + <c><anno>Tuple1</anno></c> + followed by <c><anno>Term</anno></c> as the last element. + Semantically equivalent to + <c>list_to_tuple(tuple_to_list(<anno>Tuple1</anno>) ++ + [<anno>Term</anno>])</c>, but much faster. Example:</p> <pre> > <input>erlang:append_element({one, two}, three).</input> {one,two,three}</pre> </desc> </func> + <func> <name name="apply" arity="2"/> - <fsummary>Apply a function to an argument list</fsummary> + <fsummary>Apply a function to an argument list.</fsummary> <desc> - <p>Call a fun, passing the elements in <c><anno>Args</anno></c> as - arguments.</p> - <p>Note: If the number of elements in the arguments are known at - compile-time, the call is better written as + <p>Calls a fun, passing the elements in <c><anno>Args</anno></c> + as arguments.</p> + <p>If the number of elements in the arguments are known at + compile time, the call is better written as <c><anno>Fun</anno>(Arg1, Arg2, ... ArgN)</c>.</p> <warning> - <p>Earlier, <c><anno>Fun</anno></c> could also be given as + <p>Earlier, <c><anno>Fun</anno></c> could also be specified as <c>{Module, Function}</c>, equivalent to - <c>apply(Module, Function, Args)</c>. This usage is - deprecated and will stop working in a future release of - Erlang/OTP.</p> + <c>apply(Module, Function, Args)</c>. <em>This use is + deprecated and will stop working in a future release.</em></p> </warning> </desc> </func> + <func> <name name="apply" arity="3"/> - <fsummary>Apply a function to an argument list</fsummary> + <fsummary>Apply a function to an argument list.</fsummary> <desc> <p>Returns the result of applying <c>Function</c> in - <c><anno>Module</anno></c> to <c><anno>Args</anno></c>. The applied function must + <c><anno>Module</anno></c> to <c><anno>Args</anno></c>. + The applied function must be exported from <c>Module</c>. The arity of the function is - the length of <c>Args</c>.</p> + the length of <c>Args</c>. Example:</p> <pre> > <input>apply(lists, reverse, [[a, b, c]]).</input> -[c,b,a]</pre> - <p><c>apply</c> can be used to evaluate BIFs by using - the module name <c>erlang</c>.</p> - <pre> +[c,b,a] > <input>apply(erlang, atom_to_list, ['Erlang']).</input> "Erlang"</pre> - <p>Note: If the number of arguments are known at compile-time, + <p>If the number of arguments are known at compile time, the call is better written as - <c><anno>Module</anno>:<anno>Function</anno>(Arg1, Arg2, ..., ArgN)</c>.</p> - <p>Failure: <c>error_handler:undefined_function/3</c> is called + <c><anno>Module</anno>:<anno>Function</anno>(Arg1, Arg2, ..., + ArgN)</c>.</p> + <p>Failure: <seealso marker="kernel:error_handler#undefined_function/3"> + <c>error_handler:undefined_function/3</c></seealso> is called if the applied function is not exported. The error handler can be redefined (see - <seealso marker="#process_flag/2">process_flag/2</seealso>). - If the <c>error_handler</c> is undefined, or if the user has + <seealso marker="#process_flag/2"><c>process_flag/2</c></seealso>). + If <c>error_handler</c> is undefined, or if the user has redefined the default <c>error_handler</c> so the replacement - module is undefined, an error with the reason <c>undef</c> + module is undefined, an error with reason <c>undef</c> is generated.</p> </desc> </func> + <func> <name name="atom_to_binary" arity="2"/> - <fsummary>Return the binary representation of an atom</fsummary> - <desc> - <p>Returns a binary which corresponds to the text - representation of <c><anno>Atom</anno></c>. If <c><anno>Encoding</anno></c> - is <c>latin1</c>, there will be one byte for each character - in the text representation. If <c><anno>Encoding</anno></c> is - <c>utf8</c> or - <c>unicode</c>, the characters will be encoded using UTF-8 - (meaning that characters from 16#80 up to 0xFF will be - encoded in two bytes).</p> - - <note><p>Currently, <c>atom_to_binary(<anno>Atom</anno>, latin1)</c> can - never fail because the text representation of an atom can only contain - characters from 0 to 16#FF. In a future release, the text representation - of atoms might be allowed to contain any Unicode character - and <c>atom_to_binary(<anno>Atom</anno>, latin1)</c> will fail if the - text representation for the <c><anno>Atom</anno></c> contains a Unicode - character greater than 16#FF.</p></note> - + <fsummary>Return the binary representation of an atom.</fsummary> + <desc> + <p>Returns a binary corresponding to the text + representation of <c><anno>Atom</anno></c>. + If <c><anno>Encoding</anno></c> + 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 where + characters may require multiple bytes.</p> + <note> + <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> + <p>Example:</p> <pre> > <input>atom_to_binary('Erlang', latin1).</input> <<"Erlang">></pre> </desc> </func> + <func> <name name="atom_to_list" arity="1"/> - <fsummary>Text representation of an atom</fsummary> + <fsummary>Text representation of an atom.</fsummary> <desc> - <p>Returns a string which corresponds to the text - representation of <c><anno>Atom</anno></c>.</p> + <p>Returns a string corresponding to the text + representation of <c><anno>Atom</anno></c>, for example:</p> <pre> > <input>atom_to_list('Erlang').</input> "Erlang"</pre> </desc> </func> + <func> <name name="binary_part" arity="2"/> - <fsummary>Extracts a part of a binary</fsummary> + <fsummary>Extract a part of a binary.</fsummary> <desc> - <p>Extracts the part of the binary described by <c><anno>PosLen</anno></c>.</p> - - <p>Negative length can be used to extract bytes at the end of a binary:</p> - + <p>Extracts the part of the binary described by + <c><anno>PosLen</anno></c>.</p> + <p>Negative length can be used to extract bytes at the end + of a binary, for example:</p> <code> 1> Bin = <<1,2,3,4,5,6,7,8,9,10>>. 2> binary_part(Bin,{byte_size(Bin), -5}). -<<6,7,8,9,10>> -</code> - - <p>If <c><anno>PosLen</anno></c> in any way references outside the binary, a <c>badarg</c> exception is raised.</p> - - <p><c><anno>Start</anno></c> is zero-based, i.e.:</p> +<<6,7,8,9,10>></code> + <p>Failure: <c>badarg</c> if <c><anno>PosLen</anno></c> in any way + references outside the binary.</p> + <p><c><anno>Start</anno></c> is zero-based, that is:</p> <code> 1> Bin = <<1,2,3>> 2> binary_part(Bin,{0,2}). -<<1,2>> -</code> - - <p>See the STDLIB module <c>binary</c> for details about the <c><anno>PosLen</anno></c> semantics.</p> - +<<1,2>></code> + <p>For details about the <c><anno>PosLen</anno></c> semantics, see + <seealso marker="stdlib:binary"><c>binary(3)</c></seealso>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="binary_part" arity="3"/> - <fsummary>Extracts a part of a binary</fsummary> + <fsummary>Extract a part of a binary.</fsummary> <desc> - <p>The same as <c>binary_part(<anno>Subject</anno>, {<anno>Start</anno>, <anno>Length</anno>})</c>.</p> - + <p>The same as <c>binary_part(<anno>Subject</anno>, + {<anno>Start</anno>, <anno>Length</anno>})</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="binary_to_atom" arity="2"/> - <fsummary>Convert from text representation to an atom</fsummary> + <fsummary>Convert from text representation to an atom.</fsummary> <desc> <p>Returns the atom whose text representation is - <c><anno>Binary</anno></c>. If <c><anno>Encoding</anno></c> is <c>latin1</c>, no - 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; furthermore, only Unicode characters up - to 0xFF are allowed.</p> - - <note><p><c>binary_to_atom(<anno>Binary</anno>, utf8)</c> will fail if - the binary contains Unicode characters greater than 16#FF. - In a future release, such Unicode characters might be allowed - and <c>binary_to_atom(<anno>Binary</anno>, utf8)</c> - will not fail in that case. For more information on Unicode support in atoms - see <seealso marker="erl_ext_dist#utf8_atoms">note on UTF-8 encoded atoms</seealso> - in the chapter about the external term format in the ERTS User's Guide.</p></note> - + <c><anno>Binary</anno></c>. + If <c><anno>Encoding</anno></c> is <c>latin1</c>, no + 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.</p> + <note> + <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> + in section "External Term Format" in the User's Guide.</p> + </note> + <p>Examples:</p> <pre> > <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> + <func> <name name="binary_to_existing_atom" arity="2"/> - <fsummary>Convert from text representation to an atom</fsummary> + <fsummary>Convert from text representation to an atom.</fsummary> <desc> - <p>Works like <seealso marker="#binary_to_atom/2">binary_to_atom/2</seealso>, - but the atom must already exist.</p> - <p>Failure: <c>badarg</c> if the atom does not already exist.</p> + <p>As + <seealso marker="#binary_to_atom/2"><c>binary_to_atom/2</c></seealso>, + but the atom must exist.</p> + <p>Failure: <c>badarg</c> if the atom does not exist.</p> + <note> + <p>Note that the compiler may optimize away atoms. For + example, the compiler will rewrite + <c>atom_to_list(some_atom)</c> to <c>"some_atom"</c>. If + that expression is the only mention of the atom + <c>some_atom</c> in the containing module, the atom will not + be created when the module is loaded, and a subsequent call + to <c>binary_to_existing_atom(<<"some_atom">>, utf8)</c> + will fail.</p> + </note> </desc> </func> + <func> <name name="binary_to_float" arity="1"/> - <fsummary>Convert from text representation to a float</fsummary> + <fsummary>Convert from text representation to a float.</fsummary> <desc> - <p>Returns the float whose text representation is <c><anno>Binary</anno></c>.</p> + <p>Returns the float whose text representation is + <c><anno>Binary</anno></c>, for example:</p> <pre> > <input>binary_to_float(<<"2.2017764e+0">>).</input> 2.2017764</pre> @@ -311,12 +471,13 @@ representation of a float.</p> </desc> </func> + <func> <name name="binary_to_integer" arity="1"/> - <fsummary>Convert from text representation to an integer</fsummary> + <fsummary>Convert from text representation to an integer.</fsummary> <desc> <p>Returns an integer whose text representation is - <c><anno>Binary</anno></c>.</p> + <c><anno>Binary</anno></c>, for example:</p> <pre> > <input>binary_to_integer(<<"123">>).</input> 123</pre> @@ -324,12 +485,14 @@ representation of an integer.</p> </desc> </func> + <func> <name name="binary_to_integer" arity="2"/> - <fsummary>Convert from text representation to an integer</fsummary> + <fsummary>Convert from text representation to an integer.</fsummary> <desc> <p>Returns an integer whose text representation in base - <c><anno>Base</anno></c> is <c><anno>Binary</anno></c>.</p> + <c><anno>Base</anno></c> is <c><anno>Binary</anno></c>, for + example:</p> <pre> > <input>binary_to_integer(<<"3FF">>, 16).</input> 1023</pre> @@ -337,93 +500,124 @@ representation of an integer.</p> </desc> </func> + <func> <name name="binary_to_list" arity="1"/> - <fsummary>Convert a binary to a list</fsummary> + <fsummary>Convert a binary to a list.</fsummary> <desc> - <p>Returns a list of integers which correspond to the bytes of + <p>Returns a list of integers corresponding to the bytes of <c><anno>Binary</anno></c>.</p> </desc> </func> + <func> <name name="binary_to_list" arity="3"/> - <fsummary>Convert part of a binary to a list</fsummary> - <type_desc variable="Start">1..byte_size(<anno>Binary</anno>)</type_desc> + <fsummary>Convert part of a binary to a list.</fsummary> + <type_desc variable="Start">1..byte_size(<c><anno>Binary</anno></c>) + </type_desc> <desc> <p>As <c>binary_to_list/1</c>, but returns a list of integers corresponding to the bytes from position <c><anno>Start</anno></c> to - position <c><anno>Stop</anno></c> in <c><anno>Binary</anno></c>. Positions in the + position <c><anno>Stop</anno></c> in <c><anno>Binary</anno></c>. + The positions in the binary are numbered starting from 1.</p> - - <note><p>This function's indexing style of using one-based indices for - binaries is deprecated. New code should use the functions in - the STDLIB module <c>binary</c> instead. They consequently - use the same (zero-based) style of indexing.</p></note> - </desc> - </func> - <func> - <name name="bitstring_to_list" arity="1"/> - <fsummary>Convert a bitstring to a list</fsummary> - <desc> - <p>Returns a list of integers which correspond to the bytes of - <c><anno>Bitstring</anno></c>. If the number of bits in the binary is not - divisible by 8, the last element of the list will be a bitstring - containing the remaining bits (1 up to 7 bits).</p> + <note> + <p><em>The one-based indexing for binaries used by + this function is deprecated.</em> New code is to use + <seealso marker="stdlib:binary#bin_to_list/3"> + <c>binary:bin_to_list/3</c></seealso> + in STDLIB instead. All functions in module + <c>binary</c> consistently use zero-based indexing.</p> + </note> </desc> </func> + <func> <name name="binary_to_term" arity="1"/> - <fsummary>Decode an Erlang external term format binary</fsummary> + <fsummary>Decode an Erlang external term format binary.</fsummary> <desc> - <p>Returns an Erlang term which is the result of decoding - the binary object <c><anno>Binary</anno></c>, which must be encoded - according to the Erlang external term format.</p> + <p>Returns an Erlang term that is the result of decoding + binary object <c><anno>Binary</anno></c>, which must be encoded + according to the <seealso marker="erts:erl_ext_dist"> + Erlang external term format</seealso>.</p> + <pre> +> <input>Bin = term_to_binary(hello).</input> +<<131,100,0,5,104,101,108,108,111>> +> <input>hello = binary_to_term(Bin).</input> +hello +</pre> <warning> - <p>When decoding binaries from untrusted sources, consider using - <c>binary_to_term/2</c> to prevent denial of service attacks.</p> + <p>When decoding binaries from untrusted sources, + consider using <c>binary_to_term/2</c> to prevent Denial + of Service attacks.</p> </warning> - <p>See also - <seealso marker="#term_to_binary/1">term_to_binary/1</seealso> - and - <seealso marker="#binary_to_term/2">binary_to_term/2</seealso>.</p> + <p>See also + <seealso marker="#term_to_binary/1"><c>term_to_binary/1</c></seealso> + and <seealso marker="#binary_to_term/2"> + <c>binary_to_term/2</c></seealso>.</p> </desc> </func> + <func> <name name="binary_to_term" arity="2"/> - <fsummary>Decode an Erlang external term format binary</fsummary> + <fsummary>Decode an Erlang external term format binary.</fsummary> <desc> - <p>As <c>binary_to_term/1</c>, but takes options that affect decoding - of the binary.</p> + <p>As <c>binary_to_term/1</c>, but takes these options:</p> <taglist> <tag><c>safe</c></tag> <item> - <p>Use this option when receiving binaries from an untrusted - source.</p> - <p>When enabled, it prevents decoding data that may be used to - attack the Erlang system. In the event of receiving unsafe - data, decoding fails with a badarg error.</p> - <p>Currently, this prevents creation of new atoms directly, - creation of new atoms indirectly (as they are embedded in - certain structures like pids, refs, funs, etc.), and creation of - new external function references. None of those resources are - currently garbage collected, so unchecked creation of them can - exhaust available memory.</p> + <p>Use this option when receiving binaries from an untrusted + source.</p> + <p>When enabled, it prevents decoding data that can be used to + attack the Erlang system. In the event of receiving unsafe + data, decoding fails with a <c>badarg</c> error.</p> + <p>This prevents creation of new atoms directly, + creation of new atoms indirectly (as they are embedded in + certain structures, such as process identifiers, + refs, and funs), and + creation of new external function references. + None of those resources are garbage collected, so unchecked + creation of them can exhaust available memory.</p> + <pre> +> <input>binary_to_term(<<131,100,0,5,"hello">>, [safe]).</input> +** exception error: bad argument +> <input>hello.</input> +hello +> <input>binary_to_term(<<131,100,0,5,"hello">>, [safe]).</input> +hello +</pre> + </item> + <tag><c>used</c></tag> + <item> + <p>Changes the return value to <c>{Term, Used}</c> where <c>Used</c> + is the number of bytes actually read from <c>Binary</c>.</p> + <pre> +> <input>Input = <<131,100,0,5,"hello","world">>.</input> +<<131,100,0,5,104,101,108,108,111,119,111,114,108,100>> +> <input>{Term, Used} = binary_to_term(Input, [used]).</input> +{hello, 9} +> <input>split_binary(Input, Used).</input> +{<<131,100,0,5,104,101,108,108,111>>, <<"world">>} +</pre> </item> </taglist> - <p>Failure: <c>badarg</c> if <c>safe</c> is specified and unsafe data - is decoded.</p> + <p>Failure: <c>badarg</c> if <c>safe</c> is specified and unsafe + data is decoded.</p> <p>See also - <seealso marker="#term_to_binary/1">term_to_binary/1</seealso>, - <seealso marker="#binary_to_term/1">binary_to_term/1</seealso>, - and <seealso marker="#list_to_existing_atom/1"> - list_to_existing_atom/1</seealso>.</p> + <seealso marker="#term_to_binary/1"><c>term_to_binary/1</c></seealso>, + <seealso marker="#binary_to_term/1"> + <c>binary_to_term/1</c></seealso>, and + <seealso marker="#list_to_existing_atom/1"> + <c>list_to_existing_atom/1</c></seealso>.</p> </desc> </func> + <func> <name name="bit_size" arity="1"/> - <fsummary>Return the size of a bitstring</fsummary> + <fsummary>Return the size of a bitstring.</fsummary> <desc> - <p>Returns an integer which is the size in bits of <c><anno>Bitstring</anno></c>.</p> + <p>Returns an integer that is the size in bits of + <c><anno>Bitstring</anno></c>, for example:</p> <pre> > <input>bit_size(<<433:16,3:3>>).</input> 19 @@ -432,30 +626,44 @@ <p>Allowed in guard tests.</p> </desc> </func> + + <func> + <name name="bitstring_to_list" arity="1"/> + <fsummary>Convert a bitstring to a list.</fsummary> + <desc> + <p>Returns a list of integers corresponding to the bytes of + <c><anno>Bitstring</anno></c>. If the number of bits in the binary + is not divisible by 8, the last element of the list is a bitstring + containing the remaining 1-7 bits.</p> + </desc> + </func> + <func> <name name="bump_reductions" arity="1"/> - <fsummary>Increment the reduction counter</fsummary> + <fsummary>Increment the reduction counter.</fsummary> <desc> <p>This implementation-dependent function increments the reduction counter for the calling process. In the Beam emulator, the reduction counter is normally incremented by - one for each function and BIF call, and a context switch is - forced when the counter reaches the maximum number of reductions - for a process (2000 reductions in R12B).</p> + one for each function and BIF call. A context switch is + forced when the counter reaches the maximum number of + reductions for a process (2000 reductions in Erlang/OTP R12B).</p> <warning> - <p>This BIF might be removed in a future version of the Beam + <p>This BIF can be removed in a future version of the Beam machine without prior warning. It is unlikely to be implemented in other Erlang implementations.</p> </warning> </desc> </func> + <func> <name name="byte_size" arity="1"/> - <fsummary>Return the size of a bitstring (or binary)</fsummary> + <fsummary>Return the size of a bitstring (or binary).</fsummary> <desc> - <p>Returns an integer which is the number of bytes needed to contain - <c><anno>Bitstring</anno></c>. (That is, if the number of bits in <c><anno>Bitstring</anno></c> is not - divisible by 8, the resulting number of bytes will be rounded <em>up</em>.)</p> + <p>Returns an integer that is the number of bytes needed to + contain <c><anno>Bitstring</anno></c>. That is, if the number of bits + in <c><anno>Bitstring</anno></c> is not divisible by 8, the resulting + number of bytes is rounded <em>up</em>. Examples:</p> <pre> > <input>byte_size(<<433:16,3:3>>).</input> 3 @@ -464,222 +672,353 @@ <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="cancel_timer" arity="1"/> - <fsummary>Cancel a timer</fsummary> - <desc> - <p>Cancels a timer, where <c><anno>TimerRef</anno></c> was returned by - either - <seealso marker="#send_after/3">erlang:send_after/3</seealso> - or - <seealso marker="#start_timer/3">erlang:start_timer/3</seealso>. - If the timer is there to be removed, the function returns - the time in milliseconds left until the timer would have expired, - otherwise <c>false</c> (which means that <c><anno>TimerRef</anno></c> was - never a timer, that it has already been cancelled, or that it - has already delivered its message).</p> - <p>See also - <seealso marker="#send_after/3">erlang:send_after/3</seealso>, - <seealso marker="#start_timer/3">erlang:start_timer/3</seealso>, - and - <seealso marker="#read_timer/1">erlang:read_timer/1</seealso>.</p> - <p>Note: Cancelling a timer does not guarantee that the message - has not already been delivered to the message queue.</p> + <fsummary>Cancel a timer.</fsummary> + <desc> + <p>Cancels a timer. The same as calling + <seealso marker="#cancel_timer/2"> + <c>erlang:cancel_timer(TimerRef, [])</c></seealso>.</p> </desc> </func> <func> + <name name="cancel_timer" arity="2"/> + <fsummary>Cancel a timer.</fsummary> + <desc> + <p>Cancels a timer that has been created by + <seealso marker="#start_timer/4"> + <c>erlang:start_timer</c></seealso> or + <seealso marker="#send_after/4"><c>erlang:send_after</c></seealso>. + <c><anno>TimerRef</anno></c> identifies the timer, and + was returned by the BIF that created the timer.</p> + <p><c><anno>Option</anno></c>s:</p> + <taglist> + <tag><c>{async, Async}</c></tag> + <item> + <p>Asynchronous request for cancellation. <c>Async</c> + defaults to <c>false</c>, which causes the + cancellation to be performed synchronously. When + <c>Async</c> is set to <c>true</c>, the cancel + operation is performed asynchronously. That is, + <c>cancel_timer()</c> sends an asynchronous + request for cancellation to the timer service that + manages the timer, and then returns <c>ok</c>.</p> + </item> + <tag><c>{info, Info}</c></tag> + <item> + <p>Requests information about the <c><anno>Result</anno></c> + of the cancellation. <c>Info</c> defaults to <c>true</c>, + which means the <c><anno>Result</anno></c> is + given. When <c>Info</c> is set to <c>false</c>, no + information about the result of the cancellation + is given.</p> + <list type="bulleted"> + <item> + <p>When <c>Async</c> is <c>false</c>: + if <c>Info</c> is <c>true</c>, the <c>Result</c> is + returned by <c>erlang:cancel_timer()</c>. otherwise + <c>ok</c> is returned.</p> + </item> + <item> + <p>When <c>Async</c> is <c>true</c>: + if <c>Info</c> is <c>true</c>, a message on the form + <c>{cancel_timer, <anno>TimerRef</anno>, + <anno>Result</anno>}</c> is sent to the + caller of <c>erlang:cancel_timer()</c> when the + cancellation operation has been performed, otherwise + no message is sent.</p> + </item> + </list> + </item> + </taglist> + <p>More <c><anno>Option</anno></c>s may be added in the future.</p> + <p>If <c><anno>Result</anno></c> is an integer, it represents + the time in milliseconds left until the canceled timer would + have expired.</p> + <p>If <c><anno>Result</anno></c> is <c>false</c>, a + timer corresponding to <c><anno>TimerRef</anno></c> could not + be found. This can be either because the timer had expired, + already had been canceled, or because <c><anno>TimerRef</anno></c> + never corresponded to a timer. Even if the timer had expired, + it does not tell you if the time-out message has + arrived at its destination yet.</p> + <note> + <p>The timer service that manages the timer can be co-located + with another scheduler than the scheduler that the calling + process is executing on. If so, communication + with the timer service takes much longer time than if it + is located locally. If the calling process is in critical + path, and can do other things while waiting for the result + of this operation, or is not interested in the result of + the operation, you want to use option <c>{async, true}</c>. + If using option <c>{async, false}</c>, the calling + process blocks until the operation has been performed.</p> + </note> + <p>See also + <seealso marker="#send_after/4"><c>erlang:send_after/4</c></seealso>, + <seealso marker="#start_timer/4"> + <c>erlang:start_timer/4</c></seealso>, and + <seealso marker="#read_timer/2"> + <c>erlang:read_timer/2</c></seealso>.</p> + </desc> + </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> + <fsummary>Check if a module has old code.</fsummary> <desc> - <p>Returns <c>true</c> if the <c><anno>Module</anno></c> has old code, - and <c>false</c> otherwise.</p> - <p>See also <seealso marker="kernel:code">code(3)</seealso>.</p> + <p>Returns <c>true</c> if <c><anno>Module</anno></c> has old code, + otherwise <c>false</c>.</p> + <p>See also <seealso marker="kernel:code"> + <c>code(3)</c></seealso>.</p> </desc> </func> + <func> <name name="check_process_code" arity="2"/> - <fsummary>Check if a process is executing old code for a module</fsummary> + <fsummary>Check if a process executes old code for a module.</fsummary> <desc> <p>The same as - <seealso marker="#check_process_code/3"><c>erlang:check_process_code(<anno>Pid</anno>, - <anno>Module</anno>, [])</c></seealso>.</p> + <seealso marker="#check_process_code/3"> + <c>check_process_code(<anno>Pid</anno>, <anno>Module</anno>, [])</c> + </seealso>.</p> </desc> </func> + <func> <name name="check_process_code" arity="3"/> - <fsummary>Check if a process is executing old code for a module</fsummary> + <fsummary>Check if a process executes old code for a module.</fsummary> <desc> - <p>Check if the node local process identified by <c><anno>Pid</anno></c> - is executing old code for <c><anno>Module</anno></c>.</p> - <p>Currently available <c><anno>Option</anno>s</c>:</p> + <p>Checks if the node local process identified by + <c><anno>Pid</anno></c> + executes old code for <c><anno>Module</anno></c>.</p> + <p><c><anno>Option</anno></c>s:</p> <taglist> <tag><c>{allow_gc, boolean()}</c></tag> <item> - Determines if garbage collection is allowed when performing - the operation. If <c>{allow_gc, false}</c> is passed, and - a garbage collection is needed in order to determine the - result of the operation, the operation will be aborted - (see information on <c><anno>CheckResult</anno></c> below). - The default is to allow garbage collection, i.e., - <c>{allow_gc, true}</c>. - </item> + <p>Determines if garbage collection is allowed when performing + the operation. If <c>{allow_gc, false}</c> is passed, and + a garbage collection is needed to determine the + result of the operation, the operation is aborted (see + information on <c><anno>CheckResult</anno></c> below). + The default is to allow garbage collection, that is, + <c>{allow_gc, true}</c>.</p> + </item> <tag><c>{async, RequestId}</c></tag> <item> - The <c>check_process_code/3</c> function will return - the value <c>async</c> immediately after the request - has been sent. When the request has been processed, the - process that called this function will be passed a - message on the form:<br/> - <c>{check_process_code, <anno>RequestId</anno>, <anno>CheckResult</anno>}</c>. - </item> + <p>The function <c>check_process_code/3</c> returns + the value <c>async</c> immediately after the request + has been sent. When the request has been processed, the + process that called this function is passed a + message on the form <c>{check_process_code, <anno>RequestId</anno>, + <anno>CheckResult</anno>}</c>.</p> + </item> </taglist> - <p>If <c><anno>Pid</anno></c> equals <c>self()</c>, and - no <c>async</c> option has been passed, the operation will - be performed at once. In all other cases a request for - the operation will be sent to the process identified by - <c><anno>Pid</anno></c>, and will be handled when - appropriate. If no <c>async</c> option has been passed, - the caller will block until <c><anno>CheckResult</anno></c> - is available and can be returned.</p> - <p><c><anno>CheckResult</anno></c> informs about the result of - the request:</p> + <p>If <c><anno>Pid</anno></c> equals <c>self()</c>, and + no <c>async</c> option has been passed, the operation + is performed at once. Otherwise a request for + the operation is sent to the process identified by + <c><anno>Pid</anno></c>, and is handled when + appropriate. If no <c>async</c> option has been passed, + the caller blocks until <c><anno>CheckResult</anno></c> + is available and can be returned.</p> + <p><c><anno>CheckResult</anno></c> informs about the result of + the request as follows:</p> <taglist> <tag><c>true</c></tag> <item> - The process identified by <c><anno>Pid</anno></c> is - executing old code for <c><anno>Module</anno></c>. - That is, the current call of the process executes old - code for this module, or the process has references - to old code for this module, or the process contains - funs that references old code for this module. - </item> + <p>The process identified by <c><anno>Pid</anno></c> + executes old code for <c><anno>Module</anno></c>. + That is, the current call of the process executes old + code for this module, or the process has references + to old code for this module, or the process contains + funs that references old code for this module.</p> + </item> <tag><c>false</c></tag> <item> - The process identified by <c><anno>Pid</anno></c> is - not executing old code for <c><anno>Module</anno></c>. - </item> + <p>The process identified by <c><anno>Pid</anno></c> does + not execute old code for <c><anno>Module</anno></c>.</p> + </item> <tag><c>aborted</c></tag> <item> - The operation was aborted since the process needed to - be garbage collected in order to determine the result - of the operation, and the operation was requested - by passing the <c>{allow_gc, false}</c> option.</item> + <p>The operation was aborted, as the process needed to + be garbage collected to determine the operation result, + and the operation was requested + by passing option <c>{allow_gc, false}</c>.</p> + </item> </taglist> - <p>See also <seealso marker="kernel:code">code(3)</seealso>.</p> + <note> + <p> + Up until ERTS version 8.*, the check process code operation + checks for all types of references to the old code. That is, + direct references (e.g. return addresses on the process + stack), indirect references (<c>fun</c>s in process + context), and references to literals in the code. + </p> + <p> + As of ERTS version 9.0, the check process code operation + only checks for direct references to the code. Indirect + references via <c>fun</c>s will be ignored. If such + <c>fun</c>s exist and are used after a purge of the old + code, an exception will be raised upon usage (same as + the case when the <c>fun</c> is received by the process + after the purge). Literals will be taken care of (copied) + at a later stage. This behavior can as of ERTS version + 8.1 be enabled when + <seealso marker="doc/installation_guide:INSTALL#Advanced-configuration-and-build-of-ErlangOTP_Configuring">building OTP</seealso>, + and will automatically be enabled if dirty scheduler + support is enabled. + </p> + </note> + <p>See also <seealso marker="kernel:code"> + <c>code(3)</c></seealso>.</p> <p>Failures:</p> <taglist> <tag><c>badarg</c></tag> - <item> - If <c><anno>Pid</anno></c> is not a node local process identifier. - </item> + <item>If <c><anno>Pid</anno></c> is not a node local process + identifier. + </item> <tag><c>badarg</c></tag> - <item> - If <c><anno>Module</anno></c> is not an atom. - </item> + <item>If <c><anno>Module</anno></c> is not an atom. + </item> <tag><c>badarg</c></tag> - <item> - If <c><anno>OptionList</anno></c> is not a valid list of options. - </item> + <item>If <c><anno>OptionList</anno></c> is an invalid list of options. + </item> </taglist> </desc> </func> + + <func> + <name name="convert_time_unit" arity="3"/> + <fsummary>Convert time unit of a time value.</fsummary> + <desc> + <p>Converts the <c><anno>Time</anno></c> value of time unit + <c><anno>FromUnit</anno></c> to the corresponding + <c><anno>ConvertedTime</anno></c> value of time unit + <c><anno>ToUnit</anno></c>. The result is rounded + using the floor function.</p> + <warning> + <p>You can lose accuracy and precision when converting + between time units. To minimize such loss, collect all + data at <c>native</c> time unit and do the conversion on the end + result.</p> + </warning> + </desc> + </func> + <func> <name name="crc32" arity="1"/> - <fsummary>Compute crc32 (IEEE 802.3) checksum</fsummary> + <fsummary>Compute crc32 (IEEE 802.3) checksum.</fsummary> <desc> - <p>Computes and returns the crc32 (IEEE 802.3 style) checksum for <c><anno>Data</anno></c>.</p> + <p>Computes and returns the crc32 (IEEE 802.3 style) checksum + for <c><anno>Data</anno></c>.</p> </desc> </func> + <func> <name name="crc32" arity="2"/> - <fsummary>Compute crc32 (IEEE 802.3) checksum</fsummary> + <fsummary>Compute crc32 (IEEE 802.3) checksum.</fsummary> <desc> - <p>Continue computing the crc32 checksum by combining - the previous checksum, <c><anno>OldCrc</anno></c>, with the checksum of - <c><anno>Data</anno></c>.</p> - <p>The following code:</p> - <code> - X = erlang:crc32(Data1), - Y = erlang:crc32(X,Data2). - </code> - <p>- would assign the same value to <c>Y</c> as this would:</p> - <code> - Y = erlang:crc32([Data1,Data2]). - </code> + <p>Continues computing the crc32 checksum by combining + the previous checksum, <c><anno>OldCrc</anno></c>, with the checksum + of <c><anno>Data</anno></c>.</p> + <p>The following code:</p> + <code> +X = erlang:crc32(Data1), +Y = erlang:crc32(X,Data2).</code> + <p>assigns the same value to <c>Y</c> as this:</p> + <code> +Y = erlang:crc32([Data1,Data2]).</code> </desc> </func> + <func> <name name="crc32_combine" arity="3"/> - <fsummary>Combine two crc32 (IEEE 802.3) checksums</fsummary> - <desc> - <p>Combines two previously computed crc32 checksums. - This computation requires the size of the data object for - the second checksum to be known.</p> - <p>The following code:</p> + <fsummary>Combine two crc32 (IEEE 802.3) checksums.</fsummary> + <desc> + <p>Combines two previously computed crc32 checksums. + This computation requires the size of the data object for + the second checksum to be known.</p> + <p>The following code:</p> + <code> +Y = erlang:crc32(Data1), +Z = erlang:crc32(Y,Data2).</code> + <p>assigns the same value to <c>Z</c> as this:</p> <code> - Y = erlang:crc32(Data1), - Z = erlang:crc32(Y,Data2). - </code> - <p>- would assign the same value to <c>Z</c> as this would:</p> - <code> - X = erlang:crc32(Data1), - Y = erlang:crc32(Data2), - Z = erlang:crc32_combine(X,Y,iolist_size(Data2)). - </code> +X = erlang:crc32(Data1), +Y = erlang:crc32(Data2), +Z = erlang:crc32_combine(X,Y,iolist_size(Data2)).</code> </desc> </func> + <func> <name name="date" arity="0"/> - <fsummary>Current date</fsummary> + <fsummary>Current date.</fsummary> <desc> <p>Returns the current date as <c>{Year, Month, Day}</c>.</p> - <p>The time zone and daylight saving time correction depend on - the underlying OS.</p> + <p>The time zone and Daylight Saving Time correction depend on + the underlying OS. Example:</p> <pre> > <input>date().</input> {1995,2,19}</pre> </desc> </func> + <func> <name name="decode_packet" arity="3"/> - <fsummary>Extracts a protocol packet from a binary</fsummary> + <fsummary>Extract a protocol packet from a binary.</fsummary> <desc> - <p>Decodes the binary <c><anno>Bin</anno></c> according to the packet - protocol specified by <c><anno>Type</anno></c>. Very similar to the packet - handling done by sockets with the option {packet,<anno>Type</anno>}.</p> - <p>If an entire packet is contained in <c><anno>Bin</anno></c> it is - returned together with the remainder of the binary as - <c>{ok,<anno>Packet</anno>,<anno>Rest</anno>}</c>.</p> + protocol specified by <c><anno>Type</anno></c>. Similar to the packet + handling done by sockets with option + <c>{packet,<anno>Type</anno>}.</c></p> + <p>If an entire packet is contained in <c><anno>Bin</anno></c>, it is + returned together with the remainder of the binary as + <c>{ok,<anno>Packet</anno>,<anno>Rest</anno>}</c>.</p> <p>If <c><anno>Bin</anno></c> does not contain the entire packet, - <c>{more,<anno>Length</anno>}</c> is returned. <c><anno>Length</anno></c> is either the - expected <em>total size</em> of the packet or <c>undefined</c> - if the expected packet size is not known. <c>decode_packet</c> - can then be called again with more data added.</p> - <p>If the packet does not conform to the protocol format - <c>{error,<anno>Reason</anno>}</c> is returned.</p> - <p>The following values of <c><anno>Type</anno></c> are valid:</p> + <c>{more,<anno>Length</anno>}</c> is returned. + <c><anno>Length</anno></c> is either the + expected <em>total size</em> of the packet, or <c>undefined</c> + if the expected packet size is unknown. <c>decode_packet</c> + can then be called again with more data added.</p> + <p>If the packet does not conform to the protocol format, + <c>{error,<anno>Reason</anno>}</c> is returned.</p> + <p><c>Type</c>s:</p> <taglist> <tag><c>raw | 0</c></tag> <item> - <p>No packet handling is done. Entire binary is - returned unless it is empty.</p> + <p>No packet handling is done. The entire binary is + returned unless it is empty.</p> </item> <tag><c>1 | 2 | 4</c></tag> <item> <p>Packets consist of a header specifying the number of bytes in the packet, followed by that number of bytes. - The length of header can be one, two, or four bytes; + The length of the header can be one, two, or four bytes; the order of the bytes is big-endian. The header - will be stripped off when the packet is returned.</p> + is stripped off when the packet is returned.</p> </item> <tag><c>line</c></tag> <item> - <p>A packet is a line terminated with newline. The - newline character is included in the returned packet - unless the line was truncated according to the option - <c>line_length</c>.</p> + <p>A packet is a line-terminated by a delimiter byte, + default is the latin-1 newline character. The delimiter + byte is included in the returned packet unless the line + was truncated according to option <c>line_length</c>.</p> </item> <tag><c>asn1 | cdr | sunrm | fcgi | tpkt</c></tag> <item> @@ -696,42 +1035,52 @@ <tag><c>http | httph | http_bin | httph_bin</c></tag> <item> <p>The Hypertext Transfer Protocol. The packets - are returned with the format according to - <c><anno>HttpPacket</anno></c> described above. A packet is either a - request, a response, a header or an end of header - mark. Invalid lines are returned as <c><anno>HttpError</anno></c>.</p> - <p>Recognized request methods and header fields are returned as atoms. - Others are returned as strings. Strings of unrecognized header fields - are formatted with only capital letters first and after hyphen characters - (like <c>"Sec-Websocket-Key"</c>).</p> - <p>The protocol type <c>http</c> should only be used for - the first line when a <c><anno>HttpRequest</anno></c> or a - <c><anno>HttpResponse</anno></c> is expected. The following calls - should use <c>httph</c> to get <c><anno>HttpHeader</anno></c>'s until - <c>http_eoh</c> is returned that marks the end of the - headers and the beginning of any following message body.</p> - <p>The variants <c>http_bin</c> and <c>httph_bin</c> will return - strings (<c>HttpString</c>) as binaries instead of lists.</p> + are returned with the format according to + <c><anno>HttpPacket</anno></c> described earlier. + A packet is either a + request, a response, a header, or an end of header + mark. Invalid lines are returned as + <c><anno>HttpError</anno></c>.</p> + <p>Recognized request methods and header fields are returned + as atoms. Others are returned as strings. Strings of + unrecognized header fields are formatted with only + capital letters first and after hyphen characters, for + example, <c>"Sec-Websocket-Key"</c>.</p> + <p>The protocol type <c>http</c> is only to be used for + the first line when an <c><anno>HttpRequest</anno></c> or an + <c><anno>HttpResponse</anno></c> is expected. + The following calls are to use <c>httph</c> to get + <c><anno>HttpHeader</anno></c>s until + <c>http_eoh</c> is returned, which marks the end of the + headers and the beginning of any following message body.</p> + <p>The variants <c>http_bin</c> and <c>httph_bin</c> return + strings (<c>HttpString</c>) as binaries instead of lists.</p> </item> </taglist> - <p>The following options are available:</p> - <taglist> - <tag><c>{packet_size, integer() >= 0}</c></tag> - <item><p>Sets the max allowed size of the packet body. If - the packet header indicates that the length of the - packet is longer than the max allowed length, the packet - is considered invalid. Default is 0 which means no - size limit.</p> - </item> - <tag><c>{line_length, integer() >= 0}</c></tag> - <item><p>For packet type <c>line</c>, truncate lines longer - than the indicated length.</p> - <p>Option <c>line_length</c> also applies to <c>http*</c> - packet types as an alias for option <c>packet_size</c> in the - case when <c>packet_size</c> itself is not set. This usage is - only intended for backward compatibility.</p> - </item> - </taglist> + <p>Options:</p> + <taglist> + <tag><c>{packet_size, integer() >= 0}</c></tag> + <item><p>Sets the maximum allowed size of the packet body. + If the packet header indicates that the length of the + packet is longer than the maximum allowed length, the + packet is considered invalid. Defaults to 0, which means + no size limit.</p> + </item> + <tag><c>{line_length, integer() >= 0}</c></tag> + <item> + <p>For packet type <c>line</c>, lines longer than + the indicated length are truncated.</p> + <p>Option <c>line_length</c> also applies to <c>http*</c> + packet types as an alias for option <c>packet_size</c> + if <c>packet_size</c> itself is not set. This use is + only intended for backward compatibility.</p> + </item> + <tag><c>{line_delimiter, 0 =< byte() =< 255}</c></tag> + <item><p>For packet type <c>line</c>, sets the delimiting byte. + Default is the latin-1 character <c>$\n</c>.</p> + </item> + </taglist> + <p>Examples:</p> <pre> > <input>erlang:decode_packet(1,<<3,"abcd">>,[]).</input> {ok,<<"abc">>,<<"d">>} @@ -742,13 +1091,11 @@ <func> <name name="delete_element" arity="2"/> - <fsummary>Delete element at index in a tuple</fsummary> + <fsummary>Delete element at index in a tuple.</fsummary> <type_desc variable="Index">1..tuple_size(<anno>Tuple1</anno>)</type_desc> <desc> - <p> - Returns a new tuple with element at <c><anno>Index</anno></c> removed from - tuple <c><anno>Tuple1</anno></c>. - </p> + <p>Returns a new tuple with element at <c><anno>Index</anno></c> + removed from tuple <c><anno>Tuple1</anno></c>, for example:</p> <pre> > <input>erlang:delete_element(2, {one, two, three}).</input> {one,three}</pre> @@ -757,160 +1104,313 @@ <func> <name name="delete_module" arity="1"/> - <fsummary>Make the current code for a module old</fsummary> + <fsummary>Make the current code for a module old.</fsummary> <desc> - <p>Makes the current code for <c><anno>Module</anno></c> become old code, and - deletes all references for this module from the export table. + <p>Makes the current code for <c><anno>Module</anno></c> become old + code and deletes all references for this module from the export table. Returns <c>undefined</c> if the module does not exist, otherwise <c>true</c>.</p> <warning> <p>This BIF is intended for the code server (see - <seealso marker="kernel:code">code(3)</seealso>) and should not be - used elsewhere.</p> + <seealso marker="kernel:code"><c>code(3)</c></seealso>) + and is not to be used elsewhere.</p> </warning> - <p>Failure: <c>badarg</c> if there is already an old version of + <p>Failure: <c>badarg</c> if there already is an old version of <c>Module</c>.</p> </desc> </func> + <func> <name name="demonitor" arity="1"/> - <fsummary>Stop monitoring</fsummary> + <fsummary>Stop monitoring.</fsummary> <desc> - <p>If <c><anno>MonitorRef</anno></c> is a reference which the calling process - obtained by calling - <seealso marker="#monitor/2">monitor/2</seealso>, + <p>If <c><anno>MonitorRef</anno></c> is a reference that the + calling process obtained by calling + <seealso marker="#monitor/2"><c>monitor/2</c></seealso>, this monitoring is turned off. If the monitoring is already turned off, nothing happens.</p> - <p>Once <c>demonitor(<anno>MonitorRef</anno>)</c> has returned it is - guaranteed that no <c>{'DOWN', <anno>MonitorRef</anno>, _, _, _}</c> message - due to the monitor will be placed in the caller's message queue - in the future. A <c>{'DOWN', <anno>MonitorRef</anno>, _, _, _}</c> message - might have been placed in the caller's message queue prior to - the call, though. Therefore, in most cases, it is advisable + <p>Once <c>demonitor(<anno>MonitorRef</anno>)</c> has returned, it is + guaranteed that no <c>{'DOWN', + <anno>MonitorRef</anno>, _, _, _}</c> message, + because of the monitor, will be placed in the caller message queue + in the future. However, a <c>{'DOWN', + <anno>MonitorRef</anno>, _, _, _}</c> message + can have been placed in the caller message queue before + the call. It is therefore usually advisable to remove such a <c>'DOWN'</c> message from the message queue - after monitoring has been stopped. - <seealso marker="#demonitor/2">demonitor(<anno>MonitorRef</anno>, [flush])</seealso> can be used instead of - <c>demonitor(<anno>MonitorRef</anno>)</c> if this cleanup is wanted.</p> + after monitoring has been stopped. + <seealso marker="#demonitor/2"> + <c>demonitor(<anno>MonitorRef</anno>, [flush])</c></seealso> + can be used instead of <c>demonitor(<anno>MonitorRef</anno>)</c> + if this cleanup is wanted.</p> <note> - <p>Prior to OTP release R11B (erts version 5.5) <c>demonitor/1</c> - behaved completely asynchronous, i.e., the monitor was active + <p>Before Erlang/OTP R11B (ERTS 5.5) <c>demonitor/1</c> + behaved completely asynchronously, that is, the monitor was active until the "demonitor signal" reached the monitored entity. This - had one undesirable effect, though. You could never know when + had one undesirable effect. You could never know when you were guaranteed <em>not</em> to receive a <c>DOWN</c> message - due to the monitor.</p> - <p>Current behavior can be viewed as two combined operations: + because of the monitor.</p> + <p>The current behavior can be viewed as two combined operations: asynchronously send a "demonitor signal" to the monitored entity - and ignore any future results of the monitor. </p> + and ignore any future results of the monitor.</p> </note> <p>Failure: It is an error if <c><anno>MonitorRef</anno></c> refers to a monitoring started by another process. Not all such cases are - cheap to check; if checking is cheap, the call fails with - <c>badarg</c> (for example if <c><anno>MonitorRef</anno></c> is a remote - reference).</p> + cheap to check. If checking is cheap, the call fails with + <c>badarg</c>, for example if <c><anno>MonitorRef</anno></c> is a + remote reference.</p> </desc> </func> + <func> <name name="demonitor" arity="2"/> - <fsummary>Stop monitoring</fsummary> + <fsummary>Stop monitoring.</fsummary> <desc> <p>The returned value is <c>true</c> unless <c>info</c> is part - of <c><anno>OptionList</anno></c>. - </p> + of <c><anno>OptionList</anno></c>.</p> <p><c>demonitor(<anno>MonitorRef</anno>, [])</c> is equivalent to - <seealso marker="#demonitor/1">demonitor(<anno>MonitorRef</anno>)</seealso>.</p> - <p>Currently the following <c><anno>Option</anno></c>s are valid:</p> + <seealso marker="#demonitor/1"> + <c>demonitor(<anno>MonitorRef</anno>)</c></seealso>.</p> + <p><c><anno>Option</anno></c>s:</p> <taglist> <tag><c>flush</c></tag> <item> - <p>Remove (one) <c>{_, <anno>MonitorRef</anno>, _, _, _}</c> message, - if there is one, from the caller's message queue after + <p>Removes (one) <c>{_, + <anno>MonitorRef</anno>, _, _, _}</c> message, + if there is one, from the caller message queue after monitoring has been stopped.</p> <p>Calling <c>demonitor(<anno>MonitorRef</anno>, [flush])</c> is equivalent to the following, but more efficient:</p> <code type="none"> - - demonitor(MonitorRef), - receive - {_, MonitorRef, _, _, _} -> - true - after 0 -> - true - end</code> +demonitor(MonitorRef), +receive + {_, MonitorRef, _, _, _} -> + true +after 0 -> + true +end</code> </item> <tag><c>info</c></tag> <item> - <p>The returned value is one of the following:</p> - <taglist> - <tag><c>true</c></tag> - <item><p>The monitor was found and removed. In this case - no <c>'DOWN'</c> message due to this monitor have - been nor will be placed in the message queue - of the caller. - </p> - </item> - <tag><c>false</c></tag> - <item><p>The monitor was not found and could not be removed. - This probably because someone already has placed a - <c>'DOWN'</c> message corresponding to this monitor - in the caller's message queue. - </p> - </item> - </taglist> - <p>If the <c>info</c> option is combined with the <c>flush</c> - option, <c>false</c> will be returned if a flush was needed; - otherwise, <c>true</c>. - </p> + <p>The returned value is one of the following:</p> + <taglist> + <tag><c>true</c></tag> + <item><p>The monitor was found and removed. In this case, + no <c>'DOWN'</c> message corresponding to this + monitor has been delivered and will not be delivered.</p> + </item> + <tag><c>false</c></tag> + <item><p>The monitor was not found and could not be removed. + This probably because someone already has placed a + <c>'DOWN'</c> message corresponding to this monitor + in the caller message queue.</p> + </item> + </taglist> + <p>If option <c>info</c> is combined with option <c>flush</c>, + <c>false</c> is returned if a flush was needed, + otherwise <c>true</c>.</p> </item> </taglist> <note> - <p>More options may be added in the future.</p> + <p>More options can be added in a future release.</p> </note> - <p>Failure: <c>badarg</c> if <c><anno>OptionList</anno></c> is not a list, or - if <c><anno>Option</anno></c> is not a valid option, or the same failure as for - <seealso marker="#demonitor/1">demonitor/1</seealso></p> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item>If <c><anno>OptionList</anno></c> is not a list. + </item> + <tag><c>badarg</c></tag> + <item>If <c><anno>Option</anno></c> is an invalid option. + </item> + <tag><c>badarg</c></tag> + <item>The same failure as for + <seealso marker="#demonitor/1"><c>demonitor/1</c></seealso>. + </item> + </taglist> </desc> </func> + <func> <name name="disconnect_node" arity="1"/> - <fsummary>Force the disconnection of a node</fsummary> + <fsummary>Force the disconnection of a node.</fsummary> <desc> - <p>Forces the disconnection of a node. This will appear to - the node <c><anno>Node</anno></c> as if the local node has crashed. This - BIF is mainly used in the Erlang network authentication - protocols. Returns <c>true</c> if disconnection succeeds, + <p>Forces the disconnection of a node. This appears to + the node <c><anno>Node</anno></c> as if the local node has crashed. + This BIF is mainly used in the Erlang network authentication + protocols.</p> + <p>Returns <c>true</c> if disconnection succeeds, otherwise <c>false</c>. If the local node is not alive, - the function returns <c>ignored</c>.</p> + <c>ignored</c> is returned.</p> </desc> </func> + <func> <name name="display" arity="1"/> - <fsummary>Print a term on standard output</fsummary> + <fsummary>Print a term on standard output.</fsummary> <desc> - <p>Prints a text representation of <c><anno>Term</anno></c> on the standard - output. On OSE the term is printed to the ramlog.</p> + <p>Prints a text representation of <c><anno>Term</anno></c> on the + standard output.</p> <warning> <p>This BIF is intended for debugging only.</p> </warning> </desc> </func> + + <func> + <name name="dist_ctrl_get_data" arity="1"/> + <fsummary>Get distribution channel data to pass to another node.</fsummary> + <desc> + <p> + Get distribution channel data from the local node that is + to be passed to the remote node. The distribution channel + is identified by <c><anno>DHandle</anno></c>. If no data + is available, the atom <c>none</c> is returned. One + can request to be informed by a message when more + data is available by calling + <seealso marker="erlang#dist_ctrl_get_data_notification/1"><c>erlang:dist_ctrl_get_data_notification(DHandle)</c></seealso>. + </p> + <note><p> + Only the process registered as distribution + controller for the distribution channel identified by + <c><anno>DHandle</anno></c> is allowed to call this + function. + </p></note> + <p> + This function is used when implementing an alternative + distribution carrier using processes as distribution + controllers. <c><anno>DHandle</anno></c> is retrived + via the callback + <seealso marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seealso>. + More information can be found in the documentation of + <seealso marker="erts:alt_dist#distribution_module">ERTS + User's Guide âžœ How to implement an Alternative Carrier + for the Erlang Distribution âžœ Distribution Module</seealso>. + </p> + </desc> + </func> + + <func> + <name name="dist_ctrl_get_data_notification" arity="1"/> + <fsummary>Request notification about available outgoing distribution channel data.</fsummary> + <desc> + <p> + Request notification when more data is available to + fetch using + <seealso marker="erlang#dist_ctrl_get_data/1"><c>erlang:dist_ctrl_get_data(DHandle)</c></seealso> + for the distribution channel identified by + <c><anno>DHandle</anno></c>. When more data is present, + the caller will be sent the message <c>dist_data</c>. + Once a <c>dist_data</c> messages has been sent, no + more <c>dist_data</c> messages will be sent until + the <c>dist_ctrl_get_data_notification/1</c> function has been called + again. + </p> + <note><p> + Only the process registered as distribution + controller for the distribution channel identified by + <c><anno>DHandle</anno></c> is allowed to call this + function. + </p></note> + <p> + This function is used when implementing an alternative + distribution carrier using processes as distribution + controllers. <c><anno>DHandle</anno></c> is retrived + via the callback + <seealso marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seealso>. + More information can be found in the documentation of + <seealso marker="erts:alt_dist#distribution_module">ERTS + User's Guide âžœ How to implement an Alternative Carrier + for the Erlang Distribution âžœ Distribution Module</seealso>. + </p> + </desc> + </func> + + <func> + <name name="dist_ctrl_input_handler" arity="2"/> + <fsummary>Register distribution channel input handler process.</fsummary> + <desc> + <p> + Register an alternate input handler process for the + distribution channel identified by <c><anno>DHandle</anno></c>. + Once this function has been called, <c><anno>InputHandler</anno></c> + is the only process allowed to call + <seealso marker="erlang#dist_ctrl_put_data/2"><c>erlang:dist_ctrl_put_data(DHandle, Data)</c></seealso> + with the <c><anno>DHandle</anno></c> identifing this distribution + channel. + </p> + <note><p> + Only the process registered as distribution + controller for the distribution channel identified by + <c><anno>DHandle</anno></c> is allowed to call this + function. + </p></note> + <p> + This function is used when implementing an alternative + distribution carrier using processes as distribution + controllers. <c><anno>DHandle</anno></c> is retrived + via the callback + <seealso marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seealso>. + More information can be found in the documentation of + <seealso marker="erts:alt_dist#distribution_module">ERTS + User's Guide âžœ How to implement an Alternative Carrier + for the Erlang Distribution âžœ Distribution Module</seealso>. + </p> + </desc> + </func> + + <func> + <name name="dist_ctrl_put_data" arity="2"/> + <fsummary>Pass data into the VM from a distribution channel.</fsummary> + <desc> + <p> + Deliver distribution channel data from a remote node to the + local node. + </p> + <note><p> + Only the process registered as distribution + controller for the distribution channel identified by + <c><anno>DHandle</anno></c> is allowed to call this + function unless an alternate input handler process + has been registered using + <seealso marker="erlang#dist_ctrl_input_handler/2"><c>erlang:dist_ctrl_input_handler(DHandle, InputHandler)</c></seealso>. + If an alternate input handler has been registered, only + the registered input handler process is allowed to call + this function. + </p></note> + <p> + This function is used when implementing an alternative + distribution carrier using processes as distribution + controllers. <c><anno>DHandle</anno></c> is retrived + via the callback + <seealso marker="erts:alt_dist#hs_data_f_handshake_complete"><c>f_handshake_complete</c></seealso>. + More information can be found in the documentation of + <seealso marker="erts:alt_dist#distribution_module">ERTS + User's Guide âžœ How to implement an Alternative Carrier + for the Erlang Distribution âžœ Distribution Module</seealso>. + </p> + </desc> + </func> + <func> <name name="element" arity="2"/> + <fsummary>Return the Nth element of a tuple.</fsummary> <type_desc variable="N">1..tuple_size(<anno>Tuple</anno>)</type_desc> - <fsummary>Get Nth element of a tuple</fsummary> <desc> <p>Returns the <c><anno>N</anno></c>th element (numbering from 1) of - <c><anno>Tuple</anno></c>.</p> + <c><anno>Tuple</anno></c>, for example:</p> <pre> > <input>element(2, {a, b, c}).</input> b</pre> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="erase" arity="0"/> - <fsummary>Return and delete the process dictionary</fsummary> + <fsummary>Return and delete the process dictionary.</fsummary> <desc> - <p>Returns the process dictionary and deletes it.</p> + <p>Returns the process dictionary and deletes it, for + example:</p> <pre> > <input>put(key1, {1, 2, 3}),</input> <input>put(key2, [a, b, c]),</input> @@ -918,13 +1418,16 @@ b</pre> [{key1,{1,2,3}},{key2,[a,b,c]}]</pre> </desc> </func> + <func> <name name="erase" arity="1"/> - <fsummary>Return and delete a value from the process dictionary</fsummary> + <fsummary>Return and delete a value from the process dictionary. + </fsummary> <desc> - <p>Returns the value <c><anno>Val</anno></c> associated with <c><anno>Key</anno></c> and - deletes it from the process dictionary. Returns - <c>undefined</c> if no value is associated with <c><anno>Key</anno></c>.</p> + <p>Returns the value <c><anno>Val</anno></c> associated with + <c><anno>Key</anno></c> and deletes it from the process dictionary. + Returns <c>undefined</c> if no value is associated with + <c><anno>Key</anno></c>. Example:</p> <pre> > <input>put(key1, {merry, lambs, are, playing}),</input> <input>X = erase(key1),</input> @@ -932,48 +1435,57 @@ b</pre> {{merry,lambs,are,playing},undefined}</pre> </desc> </func> + <func> <name name="error" arity="1"/> - <fsummary>Stop execution with a given reason</fsummary> + <fsummary>Stop execution with a specified reason.</fsummary> <desc> <p>Stops the execution of the calling process with the reason - <c><anno>Reason</anno></c>, where <c><anno>Reason</anno></c> is any term. The actual - exit reason will be <c>{<anno>Reason</anno>, Where}</c>, where <c>Where</c> + <c><anno>Reason</anno></c>, where <c><anno>Reason</anno></c> + is any term. The exit reason is + <c>{<anno>Reason</anno>, Where}</c>, where <c>Where</c> is a list of the functions most recently called (the current - function first). Since evaluating this function causes - the process to terminate, it has no return value.</p> + function first). As evaluating this function causes + the process to terminate, it has no return value. Example:</p> <pre> > <input>catch error(foobar).</input> -{'EXIT',{foobar,[{erl_eval,do_apply,5}, - {erl_eval,expr,5}, - {shell,exprs,6}, - {shell,eval_exprs,6}, - {shell,eval_loop,3}]}}</pre> +{'EXIT',{foobar,[{shell,apply_fun,3, + [{file,"shell.erl"},{line,906}]}, + {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,677}]}, + {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,430}]}, + {shell,exprs,7,[{file,"shell.erl"},{line,687}]}, + {shell,eval_exprs,7,[{file,"shell.erl"},{line,642}]}, + {shell,eval_loop,3,[{file,"shell.erl"},{line,627}]}]}} +</pre> </desc> </func> + <func> <name name="error" arity="2"/> - <fsummary>Stop execution with a given reason</fsummary> + <fsummary>Stop execution with a specified reason.</fsummary> <desc> <p>Stops the execution of the calling process with the reason - <c><anno>Reason</anno></c>, where <c><anno>Reason</anno></c> is any term. The actual - exit reason will be <c>{<anno>Reason</anno>, Where}</c>, where <c>Where</c> + <c><anno>Reason</anno></c>, where <c><anno>Reason</anno></c> + is any term. The exit reason is + <c>{<anno>Reason</anno>, Where}</c>, where <c>Where</c> is a list of the functions most recently called (the current - function first). <c><anno>Args</anno></c> is expected to be the list of - arguments for the current function; in Beam it will be used - to provide the actual arguments for the current function in - the <c>Where</c> term. Since evaluating this function causes + function first). <c><anno>Args</anno></c> is expected to be the + list of arguments for the current function; in Beam it is used + to provide the arguments for the current function in + the term <c>Where</c>. As evaluating this function causes the process to terminate, it has no return value.</p> </desc> </func> + <func> <name name="exit" arity="1"/> - <fsummary>Stop execution with a given reason</fsummary> + <fsummary>Stop execution with a specified reason.</fsummary> <desc> - <p>Stops the execution of the calling process with the exit - reason <c><anno>Reason</anno></c>, where <c><anno>Reason</anno></c> is any term. Since + <p>Stops the execution of the calling process with exit reason + <c><anno>Reason</anno></c>, where <c><anno>Reason</anno></c> + is any term. As evaluating this function causes the process to terminate, it - has no return value.</p> + has no return value. Example:</p> <pre> > <input>exit(foobar).</input> ** exception exit: foobar @@ -981,110 +1493,123 @@ b</pre> {'EXIT',foobar}</pre> </desc> </func> + <func> <name name="exit" arity="2"/> - <fsummary>Send an exit signal to a process or a port</fsummary> + <fsummary>Send an exit signal to a process or a port.</fsummary> <desc> <p>Sends an exit signal with exit reason <c><anno>Reason</anno></c> to the process or port identified by <c><anno>Pid</anno></c>.</p> - <p>The following behavior apply if <c><anno>Reason</anno></c> is any term - except <c>normal</c> or <c>kill</c>:</p> - <p>If <c><anno>Pid</anno></c> is not trapping exits, <c><anno>Pid</anno></c> itself will - exit with exit reason <c><anno>Reason</anno></c>. If <c><anno>Pid</anno></c> is trapping - exits, the exit signal is transformed into a message - <c>{'EXIT', From, <anno>Reason</anno>}</c> and delivered to the message - queue of <c><anno>Pid</anno></c>. <c>From</c> is the pid of the process - which sent the exit signal. See also - <seealso marker="#process_flag/2">process_flag/2</seealso>.</p> - <p>If <c><anno>Reason</anno></c> is the atom <c>normal</c>, <c><anno>Pid</anno></c> will - not exit. If it is trapping exits, the exit signal is + <p>The following behavior applies if <c><anno>Reason</anno></c> + is any term, except <c>normal</c> or <c>kill</c>:</p> + <list type="bulleted"> + <item><p>If <c><anno>Pid</anno></c> is not trapping exits, + <c><anno>Pid</anno></c> + itself exits with exit reason <c><anno>Reason</anno></c>.</p> + </item> + <item><p>If <c><anno>Pid</anno></c> is trapping exits, the exit + signal is transformed into a message + <c>{'EXIT', From, <anno>Reason</anno>}</c> + and delivered to the message queue of <c><anno>Pid</anno></c>.</p> + </item> + <item><p><c>From</c> is the process identifier of the process + that sent the exit signal. See also + <seealso marker="#process_flag/2"> + <c>process_flag/2</c></seealso>.</p> + </item> + </list> + <p>If <c><anno>Reason</anno></c> is the atom <c>normal</c>, + <c><anno>Pid</anno></c> + does not exit. If it is trapping exits, the exit signal is transformed into a message <c>{'EXIT', From, normal}</c> and delivered to its message queue.</p> - <p>If <c><anno>Reason</anno></c> is the atom <c>kill</c>, that is if - <c>exit(<anno>Pid</anno>, kill)</c> is called, an untrappable exit signal - is sent to <c><anno>Pid</anno></c> which will unconditionally exit with - exit reason <c>killed</c>.</p> + <p>If <c><anno>Reason</anno></c> is the atom <c>kill</c>, + that is, if <c>exit(<anno>Pid</anno>, kill)</c> is called, + an untrappable exit signal is sent to <c><anno>Pid</anno></c>, + which unconditionally exits with exit reason <c>killed</c>.</p> </desc> </func> + <func> <name name="external_size" arity="1"/> <fsummary>Calculate the maximum size for a term encoded in the Erlang - external term format</fsummary> + external term format.</fsummary> <desc> <p>Calculates, without doing the encoding, the maximum byte size for a term encoded in the Erlang external term format. The following condition applies always:</p> - <p> <pre> > <input>Size1 = byte_size(term_to_binary(<anno>Term</anno>)),</input> > <input>Size2 = erlang:external_size(<anno>Term</anno>),</input> > <input>true = Size1 =< Size2.</input> -true - </pre> - </p> - <p>This is equivalent to a call to: <code>erlang:external_size(<anno>Term</anno>, []) - </code></p> +true</pre> + <p>This is equivalent to a call to:</p> +<code> +erlang:external_size(<anno>Term</anno>, [])</code> </desc> </func> + <func> <name name="external_size" arity="2"/> <fsummary>Calculate the maximum size for a term encoded in the Erlang - external term format</fsummary> + external term format.</fsummary> <desc> <p>Calculates, without doing the encoding, the maximum byte size for a term encoded in the Erlang external term format. The following condition applies always:</p> - <p> <pre> > <input>Size1 = byte_size(term_to_binary(<anno>Term</anno>, <anno>Options</anno>)),</input> > <input>Size2 = erlang:external_size(<anno>Term</anno>, <anno>Options</anno>),</input> > <input>true = Size1 =< Size2.</input> -true - </pre> - </p> - <p>The option <c>{minor_version, <anno>Version</anno>}</c> specifies how floats - are encoded. See - <seealso marker="#term_to_binary/2">term_to_binary/2</seealso> for - a more detailed description. - </p> +true</pre> + <p>Option <c>{minor_version, <anno>Version</anno>}</c> specifies how + floats are encoded. For a detailed description, see + <seealso marker="#term_to_binary/2"> + <c>term_to_binary/2</c></seealso>.</p> </desc> </func> + <func> <name name="float" arity="1"/> - <fsummary>Convert a number to a float</fsummary> + <fsummary>Convert a number to a float.</fsummary> <desc> - <p>Returns a float by converting <c><anno>Number</anno></c> to a float.</p> + <p>Returns a float by converting <c><anno>Number</anno></c> to a float, + for example:</p> <pre> > <input>float(55).</input> 55.0</pre> <p>Allowed in guard tests.</p> <note> - <p>Note that if used on the top-level in a guard, it will - test whether the argument is a floating point number; for - clarity, use - <seealso marker="#is_float/1">is_float/1</seealso> instead.</p> + <p>If used on the top level in a guard, it tests whether the + argument is a floating point number; for clarity, use + <seealso marker="#is_float/1"><c>is_float/1</c></seealso> + instead.</p> <p>When <c>float/1</c> is used in an expression in a guard, such as '<c>float(A) == 4.0</c>', it converts a number as - described above.</p> + described earlier.</p> </note> </desc> </func> + <func> <name name="float_to_binary" arity="1"/> - <fsummary>Text representation of a float</fsummary> + <fsummary>Text representation of a float.</fsummary> <desc> - <p>The same as <c>float_to_binary(<anno>Float</anno>,[{scientific,20}])</c>.</p> + <p>The same as + <c>float_to_binary(<anno>Float</anno>,[{scientific,20}])</c>.</p> </desc> </func> + <func> <name name="float_to_binary" arity="2"/> - <fsummary>Text representation of a float formatted using given options</fsummary> + <fsummary>Text representation of a float formatted using specified + options.</fsummary> <desc> - <p>Returns a binary which corresponds to the text + <p>Returns a binary corresponding to the text representation of <c><anno>Float</anno></c> using fixed decimal - point formatting. The <c><anno>Options</anno></c> behave in the same - way as <seealso marker="#float_to_list/2">float_to_list/2</seealso>. - </p> + point formatting. <c><anno>Options</anno></c> behaves in the same + way as <seealso marker="#float_to_list/2"> + <c>float_to_list/2</c></seealso>. Examples:</p> <pre> > <input>float_to_binary(7.12, [{decimals, 4}]).</input> <<"7.1200">> @@ -1092,31 +1617,44 @@ true <<"7.12">></pre> </desc> </func> + <func> <name name="float_to_list" arity="1"/> - <fsummary>Text representation of a float</fsummary> + <fsummary>Text representation of a float.</fsummary> <desc> - <p>The same as <c>float_to_list(<anno>Float</anno>,[{scientific,20}])</c>.</p> + <p>The same as + <c>float_to_list(<anno>Float</anno>,[{scientific,20}])</c>.</p> </desc> </func> + <func> <name name="float_to_list" arity="2"/> - <fsummary>Text representation of a float formatted using given options</fsummary> - <desc> - <p>Returns a string which corresponds to the text - representation of <c>Float</c> using fixed decimal point formatting. - When <c>decimals</c> option is specified - the returned value will contain at most <c>Decimals</c> number of - digits past the decimal point. If the number doesn't fit in the - internal static buffer of 256 bytes, the function throws <c>badarg</c>. - When <c>compact</c> option is provided - the trailing zeros at the end of the list are truncated (this option is - only meaningful together with the <c>decimals</c> option). When - <c>scientific</c> option is provided, the float will be formatted using - scientific notation with <c>Decimals</c> digits of precision. If - <c>Options</c> is <c>[]</c> the function behaves like - <c><seealso marker="#float_to_list/1">float_to_list/1</seealso></c>. - </p> + <fsummary>Text representation of a float formatted using specified + options.</fsummary> + <desc> + <p>Returns a string corresponding to the text representation + of <c>Float</c> using fixed decimal point formatting.</p> + <p>Available options:</p> + <list type="bulleted"> + <item><p>If option <c>decimals</c> is specified, the returned value + contains at most <c>Decimals</c> number of digits past the + decimal point. If the number does not fit in the internal + static buffer of 256 bytes, the function throws <c>badarg</c>.</p> + </item> + <item><p>If option <c>compact</c> is specified, the trailing zeros + at the end of the list are truncated. This option is only + meaningful together with option <c>decimals</c>.</p> + </item> + <item><p>If option <c>scientific</c> is specified, the float is + formatted using scientific notation with <c>Decimals</c> + digits of precision.</p> + </item> + <item><p>If <c>Options</c> is <c>[]</c>, the function behaves as + <seealso marker="#float_to_list/1"> + <c>float_to_list/1</c></seealso>.</p> + </item> + </list> + <p>Examples:</p> <pre> > <input>float_to_list(7.12, [{decimals, 4}]).</input> "7.1200" @@ -1124,36 +1662,54 @@ true "7.12"</pre> </desc> </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> + <fsummary>Information about a fun.</fsummary> <desc> - <p>Returns a list containing information about the fun - <c><anno>Fun</anno></c>. Each element of the list is a tuple. The order of - the tuples is not defined, and more tuples may be added in a + <p>Returns a list with information about the fun + <c><anno>Fun</anno></c>. Each list element is a tuple. The order + of the tuples is undefined, and more tuples can be added in a future release.</p> <warning> <p>This BIF is mainly intended for debugging, but it can - occasionally be useful in library functions that might need - to verify, for instance, the arity of a fun.</p> + sometimes be useful in library functions that need + to verify, for example, the arity of a fun.</p> </warning> - <p>There are two types of funs with slightly different - semantics:</p> - <p>A fun created by <c>fun M:F/A</c> is called an - <em>external</em> fun. Calling it will always call the - function <c>F</c> with arity <c>A</c> in the latest code for - module <c>M</c>. Note that module <c>M</c> does not even need - to be loaded when the fun <c>fun M:F/A</c> is created.</p> - <p>All other funs are called <em>local</em>. When a local fun - is called, the same version of the code that created the fun - will be called (even if newer version of the module has been - loaded).</p> - <p>The following elements will always be present in the list + <p>Two types of funs have slightly different semantics:</p> + <list type="bulleted"> + <item><p>A fun created by <c>fun M:F/A</c> is called an + <em>external</em> fun. Calling it will always call the + function <c>F</c> with arity <c>A</c> in the latest code for + module <c>M</c>. Notice that module <c>M</c> does not even + need to be loaded when the fun <c>fun M:F/A</c> is created.</p> + </item> + <item><p>All other funs are called <em>local</em>. When a local fun + is called, the same version of the code that created the fun + is called (even if a newer version of the module has been + loaded).</p> + </item> + </list> + <p>The following elements are always present in the list for both local and external funs:</p> <taglist> <tag><c>{type, Type}</c></tag> <item> - <p><c>Type</c> is either <c>local</c> or <c>external</c>.</p> + <p><c>Type</c> is <c>local</c> or <c>external</c>.</p> </item> <tag><c>{module, Module}</c></tag> <item> @@ -1168,182 +1724,202 @@ true <p><c>Name</c> (an atom) is a function name.</p> <p>If <c>Fun</c> is a local fun, <c>Name</c> is the name of the local function that implements the fun. - (This name was generated by the compiler, and is generally + (This name was generated by the compiler, and is only of informational use. As it is a local function, it - is not possible to call it directly.) + cannot be called directly.) If no code is currently loaded for the fun, <c>[]</c> - will be returned instead of an atom.</p> + is returned instead of an atom.</p> <p>If <c>Fun</c> is an external fun, <c>Name</c> is the name of the exported function that the fun refers to.</p> </item> <tag><c>{arity, Arity}</c></tag> <item> <p><c>Arity</c> is the number of arguments that the fun - should be called with.</p> + is to be called with.</p> </item> <tag><c>{env, Env}</c></tag> <item> <p><c>Env</c> (a list) is the environment or free variables - for the fun. (For external funs, the returned list is - always empty.)</p> + for the fun. For external funs, the returned list is + always empty.</p> </item> </taglist> - <p>The following elements will only be present in the list if + <p>The following elements are only present in the list if <c>Fun</c> is local:</p> <taglist> <tag><c>{pid, Pid}</c></tag> <item> - <p><c>Pid</c> is the pid of the process that originally - created the fun.</p> + <p><c>Pid</c> is the process identifier of the process + that originally created the fun.</p> </item> <tag><c>{index, Index}</c></tag> <item> - <p><c>Index</c> (an integer) is an index into the module's + <p><c>Index</c> (an integer) is an index into the module fun table.</p> </item> <tag><c>{new_index, Index}</c></tag> <item> - <p><c>Index</c> (an integer) is an index into the module's + <p><c>Index</c> (an integer) is an index into the module fun table.</p> </item> <tag><c>{new_uniq, Uniq}</c></tag> <item> - <p><c>Uniq</c> (a binary) is a unique value for this fun. - It is calculated from the compiled code for the entire module.</p> + <p><c>Uniq</c> (a binary) is a unique value for this fun. It + is calculated from the compiled code for the entire module.</p> </item> <tag><c>{uniq, Uniq}</c></tag> <item> <p><c>Uniq</c> (an integer) is a unique value for this fun. - Starting in the R15 release, this integer is calculated from - the compiled code for the entire module. Before R15, this - integer was based on only the body of the fun. - </p> + As from Erlang/OTP R15, this integer is calculated from the + compiled code for the entire module. Before Erlang/OTP R15, this + integer was based on only the body of the fun.</p> </item> </taglist> </desc> </func> + <func> <name name="fun_info" arity="2"/> + <fsummary>Information about a fun.</fsummary> <type name="fun_info_item"/> - <fsummary>Information about a fun</fsummary> <desc> <p>Returns information about <c><anno>Fun</anno></c> as specified by - <c><anno>Item</anno></c>, in the form <c>{<anno>Item</anno>,<anno>Info</anno>}</c>.</p> + <c><anno>Item</anno></c>, in the form + <c>{<anno>Item</anno>,<anno>Info</anno>}</c>.</p> <p>For any fun, <c><anno>Item</anno></c> can be any of the atoms - <c>module</c>, <c>name</c>, <c>arity</c>, <c>env</c>, or <c>type</c>.</p> - <p>For a local fun, <c><anno>Item</anno></c> can also be any of the atoms - <c>index</c>, <c>new_index</c>, <c>new_uniq</c>, + <c>module</c>, <c>name</c>, <c>arity</c>, <c>env</c>, or + <c>type</c>.</p> + <p>For a local fun, <c><anno>Item</anno></c> can also be any of the + atoms <c>index</c>, <c>new_index</c>, <c>new_uniq</c>, <c>uniq</c>, and <c>pid</c>. For an external fun, the value of any of these items is always the atom <c>undefined</c>.</p> <p>See - <seealso marker="#fun_info/1">erlang:fun_info/1</seealso>.</p> + <seealso marker="#fun_info/1"><c>erlang:fun_info/1</c></seealso>.</p> </desc> </func> + <func> <name name="fun_to_list" arity="1"/> - <fsummary>Text representation of a fun</fsummary> + <fsummary>Text representation of a fun.</fsummary> <desc> - <p>Returns a string which corresponds to the text + <p>Returns a string corresponding to the text representation of <c><anno>Fun</anno></c>.</p> </desc> </func> + <func> <name name="function_exported" arity="3"/> - <fsummary>Check if a function is exported and loaded</fsummary> + <fsummary>Check if a function is exported and loaded.</fsummary> <desc> - <p>Returns <c>true</c> if the module <c><anno>Module</anno></c> is loaded - and contains an exported function <c><anno>Function</anno>/<anno>Arity</anno></c>; - otherwise <c>false</c>.</p> - <p>Returns <c>false</c> for any BIF (functions implemented in C - rather than in Erlang).</p> + <p>Returns <c>true</c> if the module <c><anno>Module</anno></c> is + loaded and contains an exported function + <c><anno>Function</anno>/<anno>Arity</anno></c>, + or if there is a BIF (a built-in function implemented in C) + with the specified name, otherwise returns <c>false</c>.</p> + <note> + <p>This function used to return <c>false</c> for BIFs + before Erlang/OTP 18.0.</p> + </note> </desc> </func> + <func> <name name="garbage_collect" arity="0"/> - <fsummary>Force an immediate garbage collection of the calling process</fsummary> + <fsummary>Force an immediate garbage collection of the calling process. + </fsummary> <desc> - <p>Forces an immediate garbage collection of the currently - executing process. The function should not be used, unless - it has been noticed -- or there are good reasons to suspect -- + <p>Forces an immediate garbage collection of the + executing process. The function is not to be used unless + it has been noticed (or there are good reasons to suspect) that the spontaneous garbage collection will occur too late - or not at all. Improper use may seriously degrade system - performance.</p> + or not at all.</p> + <warning> + <p>Improper use can seriously degrade system performance.</p> + </warning> </desc> </func> + <func> <name name="garbage_collect" arity="1"/> - <fsummary>Garbage collect a process</fsummary> + <fsummary>Garbage collect a process.</fsummary> <desc> <p>The same as - <seealso marker="#garbage_collect/2"><c>garbage_collect(<anno>Pid</anno>, [])</c></seealso>.</p> + <seealso marker="#garbage_collect/2"> + <c>garbage_collect(<anno>Pid</anno>, [])</c></seealso>.</p> </desc> </func> + <func> <name name="garbage_collect" arity="2"/> - <fsummary>Garbage collect a process</fsummary> + <fsummary>Garbage collect a process.</fsummary> <desc> - <p>Garbage collect the node local process identified by - <c><anno>Pid</anno></c>.</p> - <p>Currently available <c><anno>Option</anno></c>s:</p> + <p>Garbage collects the node local process identified by + <c><anno>Pid</anno></c>.</p> + <p><c><anno>Option</anno></c>:</p> <taglist> <tag><c>{async, RequestId}</c></tag> - <item> - The <c>garbage_collect/2</c> function will return - the value <c>async</c> immediately after the request - has been sent. When the request has been processed, the - process that called this function will be passed a - message on the form:<br/> - <c>{garbage_collect, <anno>RequestId</anno>, <anno>GCResult</anno>}</c>. - </item> + <item>The function <c>garbage_collect/2</c> returns + the value <c>async</c> immediately after the request + has been sent. When the request has been processed, the + process that called this function is passed a message on + 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 - collection will be performed at once, i.e. the same as - calling - <seealso marker="#garbage_collect/0">garbage_collect/0</seealso>. - In all other cases a request for garbage collection will - be sent to the process identified by <c><anno>Pid</anno></c>, - and will be handled when appropriate. If no <c>async</c> - option has been passed, the caller will block until - <c><anno>GCResult</anno></c> is available and can be - returned.</p> - <p><c><anno>GCResult</anno></c> informs about the result of - the garbage collection request:</p> + <p>If <c><anno>Pid</anno></c> equals <c>self()</c>, and + no <c>async</c> option has been passed, the garbage + collection is performed at once, that is, the same as calling + <seealso marker="#garbage_collect/0"> + <c>garbage_collect/0</c></seealso>. + Otherwise a request for garbage collection + is sent to the process identified by <c><anno>Pid</anno></c>, + and will be handled when appropriate. If no <c>async</c> + option has been passed, the caller blocks until + <c><anno>GCResult</anno></c> is available and can be returned.</p> + <p><c><anno>GCResult</anno></c> informs about the result of + the garbage collection request as follows:</p> <taglist> <tag><c>true</c></tag> <item> - The process identified by <c><anno>Pid</anno></c> has - been garbage collected. - </item> + The process identified by <c><anno>Pid</anno></c> has + been garbage collected. + </item> <tag><c>false</c></tag> <item> - No garbage collection was performed. This since the - the process identified by <c><anno>Pid</anno></c> - terminated before the request could be satisfied. - </item> + No garbage collection was performed, as + the process identified by <c><anno>Pid</anno></c> + terminated before the request could be satisfied. + </item> </taglist> - <p>Note that the same caveats as for - <seealso marker="#garbage_collect/0">garbage_collect/0</seealso> - apply.</p> + <p>Notice that the same caveats apply as for + <seealso marker="#garbage_collect/0"> + <c>garbage_collect/0</c></seealso>.</p> <p>Failures:</p> <taglist> <tag><c>badarg</c></tag> <item> - If <c><anno>Pid</anno></c> is not a node local process identifier. - </item> + If <c><anno>Pid</anno></c> is not a node local process identifier. + </item> <tag><c>badarg</c></tag> <item> - If <c><anno>OptionList</anno></c> is not a valid list of options. - </item> + If <c><anno>OptionList</anno></c> is an invalid list of options. + </item> </taglist> </desc> </func> + <func> <name name="get" arity="0"/> - <fsummary>Return the process dictionary</fsummary> + <fsummary>Return the process dictionary.</fsummary> <desc> <p>Returns the process dictionary as a list of - <c>{<anno>Key</anno>, <anno>Val</anno>}</c> tuples.</p> + <c>{<anno>Key</anno>, <anno>Val</anno>}</c> tuples, for example:</p> <pre> > <input>put(key1, merry),</input> <input>put(key2, lambs),</input> @@ -1352,13 +1928,14 @@ true [{key1,merry},{key2,lambs},{key3,{are,playing}}]</pre> </desc> </func> + <func> <name name="get" arity="1"/> - <fsummary>Return a value from the process dictionary</fsummary> + <fsummary>Return a value from the process dictionary.</fsummary> <desc> - <p>Returns the value <c><anno>Val</anno></c> associated with <c><anno>Key</anno></c> in - the process dictionary, or <c>undefined</c> if <c><anno>Key</anno></c> - does not exist.</p> + <p>Returns the value <c><anno>Val</anno></c> associated with + <c><anno>Key</anno></c> in the process dictionary, or <c>undefined</c> + if <c><anno>Key</anno></c> does not exist. Example:</p> <pre> > <input>put(key1, merry),</input> <input>put(key2, lambs),</input> @@ -1367,20 +1944,38 @@ true {are,playing}</pre> </desc> </func> + <func> <name name="get_cookie" arity="0"/> - <fsummary>Get the magic cookie of the local node</fsummary> + <fsummary>Get the magic cookie of the local node.</fsummary> + <desc> + <p>Returns the magic cookie of the local node if the node is + alive, otherwise the atom <c>nocookie</c>.</p> + </desc> + </func> + + <func> + <name name="get_keys" arity="0"/> + <fsummary>Return a list of all keys from the process dictionary. + </fsummary> <desc> - <p>Returns the magic cookie of the local node, if the node is - alive; otherwise the atom <c>nocookie</c>.</p> + <p>Returns a list of all keys present in the process dictionary, + for example:</p> + <pre> +> <input>put(dog, {animal,1}),</input> +<input>put(cow, {animal,2}),</input> +<input>put(lamb, {animal,3}),</input> +<input>get_keys().</input> +[dog,cow,lamb]</pre> </desc> </func> + <func> <name name="get_keys" arity="1"/> - <fsummary>Return a list of keys from the process dictionary</fsummary> + <fsummary>Return a list of keys from the process dictionary.</fsummary> <desc> - <p>Returns a list of keys which are associated with the value - <c><anno>Val</anno></c> in the process dictionary.</p> + <p>Returns a list of keys that are associated with the value + <c><anno>Val</anno></c> in the process dictionary, for example:</p> <pre> > <input>put(mary, {1, 2}),</input> <input>put(had, {1, 2}),</input> @@ -1392,269 +1987,320 @@ true [mary,had,a,little,lamb]</pre> </desc> </func> + <func> <name name="get_stacktrace" arity="0"/> - <fsummary>Get the call stack back-trace of the last exception</fsummary> + <fsummary>Get the call stack back-trace of the last exception.</fsummary> <type name="stack_item"/> <desc> - <p>Get the call stack back-trace (<em>stacktrace</em>) of the last - exception in the calling process as a list of - <c>{<anno>Module</anno>,<anno>Function</anno>,<anno>Arity</anno>,<anno>Location</anno>}</c> tuples. - The <c><anno>Arity</anno></c> field in the first tuple may be the argument - list of that function call instead of an arity integer, - depending on the exception.</p> + <warning><p><c>erlang:get_stacktrace/0</c> is deprecated and will stop working + in a future release.</p></warning> + <p>Instead of using <c>erlang:get_stacktrace/0</c> to retrieve + the call stack back-trace, use the following syntax:</p> +<pre> +try Expr +catch + Class:Reason:Stacktrace -> + {Class,Reason,Stacktrace} +end</pre> + <p><c>erlang:get_stacktrace/0</c> retrieves the call stack back-trace + (<em>stacktrace</em>) for an exception that has just been + caught in the calling process as a list of + <c>{<anno>Module</anno>,<anno>Function</anno>,<anno>Arity</anno>,<anno>Location</anno>}</c> + tuples. Field <c><anno>Arity</anno></c> in the first tuple can + be the argument list of that function call instead of an arity + integer, depending on the exception.</p> <p>If there has not been any exceptions in a process, the stacktrace is <c>[]</c>. After a code change for the process, - the stacktrace may also be reset to [].</p> - <p>The stacktrace is the same data as the <c>catch</c> operator + the stacktrace can also be reset to <c>[]</c>.</p> + <p>The stacktrace is the same data as operator <c>catch</c> returns, for example:</p> - <p><c>{'EXIT',{badarg,Stacktrace}} = catch abs(x)</c></p> - <p><c><anno>Location</anno></c> is a (possibly empty) list of two-tuples that - may indicate the location in the source code of the function. - The first element is an atom that describes the type of - information in the second element. Currently the following - items may occur:</p> - <taglist> - <tag><c>file</c></tag> - <item> - <p>The second element of the tuple is a string (list of - characters) representing the filename of the source file - of the function.</p> - </item> - <tag><c>line</c></tag> - <item> - <p>The second element of the tuple is the line number - (an integer greater than zero) in the source file - where the exception occurred or the function was called.</p> - </item> - </taglist> + <pre> +{'EXIT',{badarg,Stacktrace}} = catch abs(x)</pre> + <p><c><anno>Location</anno></c> is a (possibly empty) list + of two-tuples that + can indicate the location in the source code of the function. + The first element is an atom describing the type of + information in the second element. The following + items can occur:</p> + <taglist> + <tag><c>file</c></tag> + <item>The second element of the tuple is a string (list of + characters) representing the filename of the source file + of the function. + </item> + <tag><c>line</c></tag> + <item>The second element of the tuple is the line number + (an integer > 0) in the source file + where the exception occurred or the function was called. + </item> + </taglist> + <warning><p>Developers should rely on stacktrace entries only for + debugging purposes.</p> + <p>The VM performs tail call optimization, which + does not add new entries to the stacktrace, and also limits stacktraces + to a certain depth. Furthermore, compiler options, optimizations and + future changes may add or remove stacktrace entries, causing any code + that expects the stacktrace to be in a certain order or contain specific + items to fail.</p> + <p>The only exception to this rule is <c>error:undef</c> which + guarantees to include the <anno>Module</anno>, <anno>Function</anno> and <anno>Arity</anno> + of the attempted function as the first stacktrace entry.</p> + </warning> <p>See also - <seealso marker="#error/1">erlang:error/1</seealso> and - <seealso marker="#error/2">erlang:error/2</seealso>.</p> + <seealso marker="#error/1"><c>error/1</c></seealso> and + <seealso marker="#error/2"><c>error/2</c></seealso>.</p> </desc> </func> + <func> <name name="group_leader" arity="0"/> - <fsummary>Get the group leader for the calling process</fsummary> + <fsummary>Get the group leader for the calling process.</fsummary> <desc> - <p>Returns the pid of the group leader for the process which - evaluates the function.</p> + <p>Returns the process identifier of the group leader for the + process evaluating the function.</p> <p>Every process is a member of some process group and all - groups have a <em>group leader</em>. All IO from the group + groups have a <em>group leader</em>. All I/O from the group is channeled to the group leader. When a new process is spawned, it gets the same group leader as the spawning - process. Initially, at system start-up, <c>init</c> is both + process. Initially, at system startup, <c>init</c> is both its own group leader and the group leader of all processes.</p> </desc> </func> + <func> <name name="group_leader" arity="2"/> - <fsummary>Set the group leader for a process</fsummary> + <fsummary>Set the group leader for a process.</fsummary> <desc> - <p>Sets the group leader of <c><anno>Pid</anno></c> to <c><anno>GroupLeader</anno></c>. - Typically, this is used when a processes started from a - certain shell should have another group leader than + <p>Sets the group leader of <c><anno>Pid</anno></c> + to <c><anno>GroupLeader</anno></c>. + Typically, this is used when a process started from a + certain shell is to have another group leader than <c>init</c>.</p> + <p>The group leader should be rarely changed in + applications with a supervision tree, because OTP + assumes the group leader of their processes is + their application master.</p> <p>See also - <seealso marker="#group_leader/0">group_leader/0</seealso>.</p> + <seealso marker="#group_leader/0"><c>group_leader/0</c></seealso> + and <seealso marker="doc/design_principles:applications#stopping">OTP + design principles</seealso> related to starting and stopping + applications.</p> </desc> </func> + <func> <name name="halt" arity="0"/> - <fsummary>Halt the Erlang runtime system and indicate normal exit to the calling environment</fsummary> + <fsummary>Halt the Erlang runtime system and indicate normal exit to + the calling environment.</fsummary> <desc> - <p>The same as - <seealso marker="#halt/2"><c>halt(0, [])</c></seealso>.</p> + <p>The same as + <seealso marker="#halt/2"><c>halt(0, [])</c></seealso>. Example:</p> <pre> > <input>halt().</input> -os_prompt% </pre> +os_prompt%</pre> </desc> </func> + <func> <name name="halt" arity="1"/> - <fsummary>Halt the Erlang runtime system</fsummary> + <fsummary>Halt the Erlang runtime system.</fsummary> <desc> - <p>The same as - <seealso marker="#halt/2"><c>halt(<anno>Status</anno>, [])</c></seealso>.</p> + <p>The same as <seealso marker="#halt/2"> + <c>halt(<anno>Status</anno>, [])</c></seealso>. Example:</p> <pre> > <input>halt(17).</input> os_prompt% <input>echo $?</input> 17 -os_prompt% </pre> +os_prompt%</pre> </desc> </func> + <func> <name name="halt" arity="2"/> - <fsummary>Halt the Erlang runtime system</fsummary> + <fsummary>Halt the Erlang runtime system.</fsummary> <desc> <p><c><anno>Status</anno></c> must be a non-negative integer, a string, - or the atom <c>abort</c>. - Halts the Erlang runtime system. Has no return value. - Depending on <c><anno>Status</anno></c>: - </p> - <taglist> - <tag>integer()</tag> - <item>The runtime system exits with the integer value <c><anno>Status</anno></c> - as status code to the calling environment (operating system). - </item> - <tag>string()</tag> - <item>An erlang crash dump is produced with <c><anno>Status</anno></c> as slogan, - and then the runtime system exits with status code <c>1</c>. - </item> - <tag><c>abort</c></tag> - <item> - The runtime system aborts producing a core dump, if that is - enabled in the operating system. - </item> - </taglist> - <p>Note that on many platforms, only the status codes 0-255 are - supported by the operating system. - </p> - <p>For integer <c><anno>Status</anno></c> the Erlang runtime system closes all ports - and allows async threads to finish their operations before exiting. - To exit without such flushing use - <c><anno>Option</anno></c> as <c>{flush,false}</c>. - </p> - <p>For statuses <c>string()</c> and <c>abort</c> the <c>flush</c> - option is ignored and flushing is <em>not</em> done. - </p> - </desc> - </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 allowed range is 1..2^27-1.</p> - <warning> - <p>This BIF is deprecated as the hash value may differ on - different architectures. Also the hash values for integer - terms larger than 2^27 as well as large binaries are very - poor. The BIF is retained for backward compatibility - reasons (it may have been used to hash records into a file), - but all new code should use one of the BIFs - <c>erlang:phash/2</c> or <c>erlang:phash2/1,2</c> instead.</p> - </warning> + or the atom <c>abort</c>. + Halts the Erlang runtime system. Has no return value. + Depending on <c><anno>Status</anno></c>, the following occurs:</p> + <taglist> + <tag>integer()</tag> + <item>The runtime system exits with integer value + <c><anno>Status</anno></c> + as status code to the calling environment (OS). + <note> + <p>On many platforms, the OS supports only status + codes 0-255. A too large status code is truncated by clearing + the high bits.</p> + </note> + </item> + <tag>string()</tag> + <item>An Erlang crash dump is produced with <c><anno>Status</anno></c> + as slogan. Then the runtime system exits with status code <c>1</c>. + The string will be truncated if longer than 200 characters. + <note> + <p>Before ERTS 9.1 (OTP-20.1) only code points in the range 0-255 + was accepted in the string. Now any unicode string is valid.</p> + </note> + </item> + <tag><c>abort</c></tag> + <item>The runtime system aborts producing a core dump, if that is + enabled in the OS. + </item> + </taglist> + <p>For integer <c><anno>Status</anno></c>, the Erlang runtime system + closes all ports and allows async threads to finish their + operations before exiting. To exit without such flushing, use + <c><anno>Option</anno></c> as <c>{flush,false}</c>.</p> + <p>For statuses <c>string()</c> and <c>abort</c>, option + <c>flush</c> is ignored and flushing is <em>not</em> done.</p> </desc> </func> + <func> <name name="hd" arity="1"/> - <fsummary>Head of a list</fsummary> + <fsummary>Head of a list.</fsummary> <desc> - <p>Returns the head of <c><anno>List</anno></c>, that is, the first element.</p> + <p>Returns the head of <c><anno>List</anno></c>, that is, + the first element, for example:</p> <pre> > <input>hd([1,2,3,4,5]).</input> 1</pre> <p>Allowed in guard tests.</p> - <p>Failure: <c>badarg</c> if <c><anno>List</anno></c> is the empty list [].</p> + <p>Failure: <c>badarg</c> if <c><anno>List</anno></c> is the empty + list <c>[]</c>.</p> </desc> </func> + <func> <name name="hibernate" arity="3"/> - <fsummary>Hibernate a process until a message is sent to it</fsummary> + <fsummary>Hibernate a process until a message is sent to it.</fsummary> <desc> <p>Puts the calling process into a wait state where its memory - allocation has been reduced as much as possible, which is + allocation has been reduced as much as possible. This is useful if the process does not expect to receive any messages - in the near future.</p> - <p>The process will be awaken when a message is sent to it, and - control will resume in <c><anno>Module</anno>:<anno>Function</anno></c> with - the arguments given by <c><anno>Args</anno></c> with the call stack - emptied, meaning that the process will terminate when that - function returns. Thus <c>erlang:hibernate/3</c> will never - return to its caller.</p> + soon.</p> + <p>The process is awaken when a message is sent to it, and control + resumes in <c><anno>Module</anno>:<anno>Function</anno></c> with + the arguments specified by <c><anno>Args</anno></c> with the call + stack emptied, meaning that the process terminates when that + function returns. Thus <c>erlang:hibernate/3</c> never + returns to its caller.</p> <p>If the process has any message in its message queue, - the process will be awaken immediately in the same way as - described above.</p> - <p>In more technical terms, what <c>erlang:hibernate/3</c> does - is the following. It discards the call stack for the process. - Then it garbage collects the process. After the garbage - collection, all live data is in one continuous heap. The heap + the process is awakened immediately in the same way as + described earlier.</p> + <p>In more technical terms, <c>erlang:hibernate/3</c> + discards the call stack for the process, + and then garbage collects the process. After this, + all live data is in one continuous heap. The heap is then shrunken to the exact same size as the live data - which it holds (even if that size is less than the minimum + that it holds (even if that size is less than the minimum heap size for the process).</p> <p>If the size of the live data in the process is less than the minimum heap size, the first garbage collection occurring - after the process has been awaken will ensure that the heap + after the process is awakened ensures that the heap size is changed to a size not smaller than the minimum heap size.</p> - <p>Note that emptying the call stack means that any surrounding - <c>catch</c> is removed and has to be re-inserted after + <p>Notice that emptying the call stack means that any surrounding + <c>catch</c> is removed and must be re-inserted after hibernation. One effect of this is that processes started using <c>proc_lib</c> (also indirectly, such as - <c>gen_server</c> processes), should use - <seealso marker="stdlib:proc_lib#hibernate/3">proc_lib:hibernate/3</seealso> - instead to ensure that the exception handler continues to work + <c>gen_server</c> processes), are to use + <seealso marker="stdlib:proc_lib#hibernate/3"> + <c>proc_lib:hibernate/3</c></seealso> + instead, to ensure that the exception handler continues to work when the process wakes up.</p> </desc> </func> <func> <name name="insert_element" arity="3"/> - <fsummary>Insert an element at index in a tuple</fsummary> - <type_desc variable="Index">1..tuple_size(<anno>Tuple1</anno>) + 1</type_desc> - <desc> - <p> - Returns a new tuple with element <c><anno>Term</anno></c> insert at position - <c><anno>Index</anno></c> in tuple <c><anno>Tuple1</anno></c>. - All elements from position <c><anno>Index</anno></c> and upwards are subsequently - pushed one step higher in the new tuple <c><anno>Tuple2</anno></c>. - </p> + <fsummary>Insert an element at index in a tuple.</fsummary> + <type_desc variable="Index">1..tuple_size(<anno>Tuple1</anno>) + + 1</type_desc> + <desc> + <p>Returns a new tuple with element <c><anno>Term</anno></c> + inserted at position + <c><anno>Index</anno></c> in tuple <c><anno>Tuple1</anno></c>. + All elements from position <c><anno>Index</anno></c> and upwards are + pushed one step higher in the new tuple <c><anno>Tuple2</anno></c>. + Example:</p> <pre> > <input>erlang:insert_element(2, {one, two, three}, new).</input> {one,new,two,three}</pre> </desc> </func> + <func> <name name="integer_to_binary" arity="1"/> - <fsummary>Text representation of an integer</fsummary> + <fsummary>Text representation of an integer.</fsummary> <desc> - <p>Returns a binary which corresponds to the text - representation of <c><anno>Integer</anno></c>.</p> + <p>Returns a binary corresponding to the text + representation of <c><anno>Integer</anno></c>, for example:</p> <pre> > <input>integer_to_binary(77).</input> <<"77">></pre> </desc> </func> + <func> <name name="integer_to_binary" arity="2"/> - <fsummary>Text representation of an integer</fsummary> + <fsummary>Text representation of an integer.</fsummary> <desc> - <p>Returns a binary which corresponds to the text - representation of <c><anno>Integer</anno></c> in base <c><anno>Base</anno></c>.</p> + <p>Returns a binary corresponding to the text + representation of <c><anno>Integer</anno></c> in base + <c><anno>Base</anno></c>, for example:</p> <pre> > <input>integer_to_binary(1023, 16).</input> <<"3FF">></pre> </desc> </func> + <func> <name name="integer_to_list" arity="1"/> - <fsummary>Text representation of an integer</fsummary> + <fsummary>Text representation of an integer.</fsummary> <desc> - <p>Returns a string which corresponds to the text - representation of <c><anno>Integer</anno></c>.</p> + <p>Returns a string corresponding to the text + representation of <c><anno>Integer</anno></c>, for example:</p> <pre> > <input>integer_to_list(77).</input> "77"</pre> </desc> </func> + <func> <name name="integer_to_list" arity="2"/> - <fsummary>Text representation of an integer</fsummary> + <fsummary>Text representation of an integer.</fsummary> <desc> - <p>Returns a string which corresponds to the text - representation of <c><anno>Integer</anno></c> in base <c><anno>Base</anno></c>.</p> + <p>Returns a string corresponding to the text + representation of <c><anno>Integer</anno></c> in base + <c><anno>Base</anno></c>, for example:</p> <pre> > <input>integer_to_list(1023, 16).</input> "3FF"</pre> </desc> </func> + + <func> + <name name="iolist_size" arity="1"/> + <fsummary>Size of an iolist.</fsummary> + <desc> + <p>Returns an integer, that is the size in bytes, + of the binary that would be the result of + <c>iolist_to_binary(<anno>Item</anno>)</c>, for example:</p> + <pre> +> <input>iolist_size([1,2|<<3,4>>]).</input> +4</pre> + </desc> + </func> + <func> <name name="iolist_to_binary" arity="1"/> - <fsummary>Convert an iolist to a binary</fsummary> + <fsummary>Convert an iolist to a binary.</fsummary> <desc> - <p>Returns a binary which is made from the integers and - binaries in <c><anno>IoListOrBinary</anno></c>.</p> + <p>Returns a binary that is made from the integers and + binaries in <c><anno>IoListOrBinary</anno></c>, for example:</p> <pre> > <input>Bin1 = <<1,2,3>>.</input> <<1,2,3>> @@ -1666,278 +2312,328 @@ os_prompt% </pre> <<1,2,3,1,2,3,4,5,4,6>></pre> </desc> </func> + <func> - <name name="iolist_size" arity="1"/> - <fsummary>Size of an iolist</fsummary> + <name name="iolist_to_iovec" arity="1"/> + <fsummary>Converts an iolist to a iovec.</fsummary> <desc> - <p>Returns an integer which is the size in bytes - of the binary that would be the result of - <c>iolist_to_binary(<anno>Item</anno>)</c>.</p> - <pre> -> <input>iolist_size([1,2|<<3,4>>]).</input> -4</pre> + <p>Returns an iovec that is made from the integers and binaries in + <c><anno>IoListOrBinary</anno></c>.</p> </desc> </func> + <func> <name name="is_alive" arity="0"/> - <fsummary>Check whether the local node is alive</fsummary> + <fsummary>Check whether the local node is alive.</fsummary> <desc> - <p>Returns <c>true</c> if the local node is alive; that is, if - the node can be part of a distributed system. Otherwise, it - returns <c>false</c>.</p> + <p>Returns <c>true</c> if the local node is alive (that is, if + the node can be part of a distributed system), otherwise + <c>false</c>.</p> </desc> </func> + <func> <name name="is_atom" arity="1"/> - <fsummary>Check whether a term is an atom</fsummary> + <fsummary>Check whether a term is an atom.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is an atom; - otherwise returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is an atom, + otherwise <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_binary" arity="1"/> - <fsummary>Check whether a term is a binary</fsummary> + <fsummary>Check whether a term is a binary.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a binary; - otherwise returns <c>false</c>.</p> - - <p>A binary always contains a complete number of bytes.</p> - + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a binary, + otherwise <c>false</c>.</p> + <p>A binary always contains a complete number of bytes.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_bitstring" arity="1"/> - <fsummary>Check whether a term is a bitstring</fsummary> + <fsummary>Check whether a term is a bitstring.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a bitstring (including a binary); - otherwise returns <c>false</c>.</p> - + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a + bitstring (including a binary), otherwise <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_boolean" arity="1"/> - <fsummary>Check whether a term is a boolean</fsummary> + <fsummary>Check whether a term is a boolean.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is - either the atom <c>true</c> or the atom <c>false</c> - (i.e. a boolean); otherwise returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is the + atom <c>true</c> or the atom <c>false</c> (that is, a boolean). + Otherwise returns <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_builtin" arity="3"/> - <fsummary>Check if a function is a BIF implemented in C</fsummary> + <fsummary>Check if a function is a BIF implemented in C.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Module</anno>:<anno>Function</anno>/<anno>Arity</anno></c> is - a BIF implemented in C; otherwise returns <c>false</c>. - This BIF is useful for builders of cross reference tools.</p> + <p>This BIF is useful for builders of cross-reference tools.</p> + <p>Returns <c>true</c> if + <c><anno>Module</anno>:<anno>Function</anno>/<anno>Arity</anno></c> + is a BIF implemented in C, otherwise <c>false</c>.</p> </desc> </func> + <func> <name name="is_float" arity="1"/> - <fsummary>Check whether a term is a float</fsummary> + <fsummary>Check whether a term is a float.</fsummary> <desc> <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a floating point - number; otherwise returns <c>false</c>.</p> + number, otherwise <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_function" arity="1"/> - <fsummary>Check whether a term is a fun</fsummary> + <fsummary>Check whether a term is a fun.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a fun; otherwise - returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a fun, otherwise + <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_function" arity="2"/> - <fsummary>Check whether a term is a fun with a given arity</fsummary> + <fsummary>Check whether a term is a fun with a specified given arity. + </fsummary> <desc> <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a fun that can be - applied with <c><anno>Arity</anno></c> number of arguments; otherwise - returns <c>false</c>.</p> + applied with <c><anno>Arity</anno></c> number of arguments, otherwise + <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_integer" arity="1"/> - <fsummary>Check whether a term is an integer</fsummary> + <fsummary>Check whether a term is an integer.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is an integer; - otherwise returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is an integer, + otherwise <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_list" arity="1"/> - <fsummary>Check whether a term is a list</fsummary> + <fsummary>Check whether a term is a list.</fsummary> <desc> <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a list with - zero or more elements; otherwise returns <c>false</c>.</p> + zero or more elements, otherwise <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_map" arity="1"/> - <fsummary>Check whether a term is a map</fsummary> + <fsummary>Check whether a term is a map.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a map; - otherwise returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a map, + otherwise <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + + <func> + <name name="is_map_key" arity="2"/> + <fsummary></fsummary> + <desc> + <p>Returns <c>true</c> if map <c><anno>Map</anno></c> contains + <c><anno>Key</anno></c> and returns <c>false</c> if it does not + contain the <c><anno>Key</anno></c>.</p> + <p>The call fails with a <c>{badmap,Map}</c> exception if + <c><anno>Map</anno></c> is not a map.</p> + <p><em>Example:</em></p> + <code type="none"> +> Map = #{"42" => value}. +#{"42" => value} +> is_map_key("42",Map). +true +> is_map_key(value,Map). +false</code> + </desc> + </func> + <func> <name name="is_number" arity="1"/> - <fsummary>Check whether a term is a number</fsummary> + <fsummary>Check whether a term is a number.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is either an integer or a - floating point number; otherwise returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is an integer or a + floating point number. Otherwise returns <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_pid" arity="1"/> - <fsummary>Check whether a term is a pid</fsummary> + <fsummary>Check whether a term is a process identifier.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a pid (process - identifier); otherwise returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a process + identifier, otherwise <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_port" arity="1"/> - <fsummary>Check whether a term is a port</fsummary> + <fsummary>Check whether a term is a port.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a port identifier; - otherwise returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a port identifier, + otherwise <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_process_alive" arity="1"/> - <fsummary>Check whether a process is alive</fsummary> + <fsummary>Check whether a process is alive.</fsummary> <desc> - <p> - <c><anno>Pid</anno></c> must refer to a process at the local node. - Returns <c>true</c> if the process exists and is alive, that - is, is not exiting and has not exited. Otherwise, returns - <c>false</c>. - </p> + <p><c><anno>Pid</anno></c> must refer to a process at the local + node.</p> + <p>Returns <c>true</c> if the process exists and is alive, that + is, is not exiting and has not exited. Otherwise returns + <c>false</c>.</p> </desc> </func> + <func> <name name="is_record" arity="2"/> - <fsummary>Check whether a term appears to be a record</fsummary> + <fsummary>Check whether a term appears to be a record.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a tuple and its first - element is <c><anno>RecordTag</anno></c>. Otherwise, returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a tuple and its + first element is <c><anno>RecordTag</anno></c>. + Otherwise returns <c>false</c>.</p> <note> <p>Normally the compiler treats calls to <c>is_record/2</c> - specially. It emits code to verify that <c><anno>Term</anno></c> is a - tuple, that its first element is <c><anno>RecordTag</anno></c>, and that - the size is correct. However, if the <c><anno>RecordTag</anno></c> is - not a literal atom, the <c>is_record/2</c> BIF will be - called instead and the size of the tuple will not be - verified.</p> + especially. It emits code to verify that <c><anno>Term</anno></c> + is a tuple, that its first element is + <c><anno>RecordTag</anno></c>, and that the + size is correct. However, if <c><anno>RecordTag</anno></c> is + not a literal atom, the BIF <c>is_record/2</c> is called + instead and the size of the tuple is not verified.</p> </note> - <p>Allowed in guard tests, if <c><anno>RecordTag</anno></c> is a literal - atom.</p> + <p>Allowed in guard tests, if <c><anno>RecordTag</anno></c> is + a literal atom.</p> </desc> </func> + <func> <name name="is_record" arity="3"/> - <fsummary>Check whether a term appears to be a record</fsummary> - <desc> - <p><c><anno>RecordTag</anno></c> must be an atom. Returns <c>true</c> if - <c><anno>Term</anno></c> is a tuple, its first element is <c><anno>RecordTag</anno></c>, - and its size is <c><anno>Size</anno></c>. Otherwise, returns <c>false</c>.</p> - <p>Allowed in guard tests, provided that <c><anno>RecordTag</anno></c> is + <fsummary>Check whether a term appears to be a record.</fsummary> + <desc> + <p><c><anno>RecordTag</anno></c> must be an atom.</p> + <p>Returns <c>true</c> if + <c><anno>Term</anno></c> is a tuple, + its first element is <c><anno>RecordTag</anno></c>, + and its size is <c><anno>Size</anno></c>. + Otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests if <c><anno>RecordTag</anno></c> is a literal atom and <c>Size</c> is a literal integer.</p> <note> - <p>This BIF is documented for completeness. In most cases - <c>is_record/2</c> should be used.</p> + <p>This BIF is documented for completeness. Usually + <c>is_record/2</c> is to be used.</p> </note> </desc> </func> + <func> <name name="is_reference" arity="1"/> - <fsummary>Check whether a term is a reference</fsummary> + <fsummary>Check whether a term is a reference.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a reference; - otherwise returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a reference, + otherwise <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="is_tuple" arity="1"/> - <fsummary>Check whether a term is a tuple</fsummary> + <fsummary>Check whether a term is a tuple.</fsummary> <desc> - <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a tuple; - otherwise returns <c>false</c>.</p> + <p>Returns <c>true</c> if <c><anno>Term</anno></c> is a tuple, + otherwise <c>false</c>.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="length" arity="1"/> - <fsummary>Length of a list</fsummary> + <fsummary>Length of a list.</fsummary> <desc> - <p>Returns the length of <c><anno>List</anno></c>.</p> + <p>Returns the length of <c><anno>List</anno></c>, for example:</p> <pre> > <input>length([1,2,3,4,5,6,7,8,9]).</input> 9</pre> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="link" arity="1"/> - <fsummary>Create a link to another process (or port)</fsummary> + <fsummary>Create a link to another process (or port).</fsummary> <desc> <p>Creates a link between the calling process and another - process (or port) <c><anno>PidOrPort</anno></c>, if there is not such a link + process (or port) <c><anno>PidOrPort</anno></c>, if there is + not such a link already. If a process attempts to create a link to itself, nothing is done. Returns <c>true</c>.</p> - <p>If <c><anno>PidOrPort</anno></c> does not exist, the behavior of the BIF depends - on if the calling process is trapping exits or not (see - <seealso marker="#process_flag/2">process_flag/2</seealso>):</p> + <p>If <c><anno>PidOrPort</anno></c> does not exist, the behavior + of the BIF + depends on if the calling process is trapping exits or not (see + <seealso marker="#process_flag/2"> + <c>process_flag/2</c></seealso>):</p> <list type="bulleted"> - <item>If the calling process is not trapping exits, and - checking <c><anno>PidOrPort</anno></c> is cheap -- that is, if <c><anno>PidOrPort</anno></c> is - local -- <c>link/1</c> fails with reason <c>noproc</c>.</item> - <item>Otherwise, if the calling process is trapping exits, - and/or <c><anno>PidOrPort</anno></c> is remote, <c>link/1</c> returns - <c>true</c>, but an exit signal with reason <c>noproc</c> - is sent to the calling process.</item> + <item><p>If the calling process is not trapping exits, and + checking <c><anno>PidOrPort</anno></c> is cheap + (that is, if <c><anno>PidOrPort</anno></c> + is local), <c>link/1</c> fails with reason <c>noproc</c>.</p></item> + <item><p>Otherwise, if the calling process is trapping exits, + and/or <c><anno>PidOrPort</anno></c> is remote, <c>link/1</c> + returns <c>true</c>, but an exit signal with reason <c>noproc</c> + is sent to the calling process.</p></item> </list> </desc> </func> + <func> <name name="list_to_atom" arity="1"/> - <fsummary>Convert from text representation to an atom</fsummary> - <desc> - <p>Returns the atom whose text representation is <c><anno>String</anno></c>.</p> - <p><c><anno>String</anno></c> may only contain ISO-latin-1 - characters (i.e. numbers below 256) as the current - implementation does not allow unicode characters >= 256 in - atoms. For more information on Unicode support in atoms - see <seealso marker="erl_ext_dist#utf8_atoms">note on UTF-8 encoded atoms</seealso> - in the chapter about the external term format in the ERTS User's Guide.</p> + <fsummary>Convert from text representation to an atom.</fsummary> + <desc> + <p>Returns the atom whose text representation is + <c><anno>String</anno></c>.</p> + <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> + <p>Example:</p> <pre> > <input>list_to_atom("Erlang").</input> 'Erlang'</pre> </desc> </func> + <func> <name name="list_to_binary" arity="1"/> - <fsummary>Convert a list to a binary</fsummary> + <fsummary>Convert a list to a binary.</fsummary> <desc> - <p>Returns a binary which is made from the integers and - binaries in <c><anno>IoList</anno></c>.</p> + <p>Returns a binary that is made from the integers and + binaries in <c><anno>IoList</anno></c>, for example:</p> <pre> > <input>Bin1 = <<1,2,3>>.</input> <<1,2,3>> @@ -1949,40 +2645,55 @@ os_prompt% </pre> <<1,2,3,1,2,3,4,5,4,6>></pre> </desc> </func> + <func> <name name="list_to_bitstring" arity="1"/> + <fsummary>Convert a list to a bitstring.</fsummary> <type name="bitstring_list"/> - <fsummary>Convert a list to a bitstring</fsummary> <desc> - <p>Returns a bitstring which is made from the integers and - bitstrings in <c><anno>BitstringList</anno></c>. (The last tail in <c><anno>BitstringList</anno></c> - is allowed to be a bitstring.)</p> + <p>Returns a bitstring that is made from the integers and + bitstrings in <c><anno>BitstringList</anno></c>. (The last tail in + <c><anno>BitstringList</anno></c> is allowed to be a bitstring.) + Example:</p> <pre> > <input>Bin1 = <<1,2,3>>.</input> <<1,2,3>> > <input>Bin2 = <<4,5>>.</input> <<4,5>> -> <input>Bin3 = <<6,7:4,>>.</input> -<<6>> +> <input>Bin3 = <<6,7:4>>.</input> +<<6,7:4>> > <input>list_to_bitstring([Bin1,1,[2,3,Bin2],4|Bin3]).</input> -<<1,2,3,1,2,3,4,5,4,6,7:46>></pre> +<<1,2,3,1,2,3,4,5,4,6,7:4>></pre> </desc> </func> + <func> <name name="list_to_existing_atom" arity="1"/> - <fsummary>Convert from text representation to an atom</fsummary> + <fsummary>Convert from text representation to an atom.</fsummary> <desc> - <p>Returns the atom whose text representation is <c><anno>String</anno></c>, + <p>Returns the atom whose text representation is + <c><anno>String</anno></c>, but only if there already exists such atom.</p> <p>Failure: <c>badarg</c> if there does not already exist an atom whose text representation is <c><anno>String</anno></c>.</p> + <note> + <p>Note that the compiler may optimize away atoms. For + example, the compiler will rewrite + <c>atom_to_list(some_atom)</c> to <c>"some_atom"</c>. If + that expression is the only mention of the atom + <c>some_atom</c> in the containing module, the atom will not + be created when the module is loaded, and a subsequent call + to <c>list_to_existing_atom("some_atom")</c> will fail.</p> + </note> </desc> </func> + <func> <name name="list_to_float" arity="1"/> - <fsummary>Convert from text representation to a float</fsummary> + <fsummary>Convert from text representation to a float.</fsummary> <desc> - <p>Returns the float whose text representation is <c><anno>String</anno></c>.</p> + <p>Returns the float whose text representation is + <c><anno>String</anno></c>, for example:</p> <pre> > <input>list_to_float("2.2017764e+0").</input> 2.2017764</pre> @@ -1990,12 +2701,13 @@ os_prompt% </pre> representation of a float.</p> </desc> </func> + <func> <name name="list_to_integer" arity="1"/> - <fsummary>Convert from text representation to an integer</fsummary> + <fsummary>Convert from text representation to an integer.</fsummary> <desc> <p>Returns an integer whose text representation is - <c><anno>String</anno></c>.</p> + <c><anno>String</anno></c>, for example:</p> <pre> > <input>list_to_integer("123").</input> 123</pre> @@ -2003,12 +2715,14 @@ os_prompt% </pre> representation of an integer.</p> </desc> </func> + <func> <name name="list_to_integer" arity="2"/> - <fsummary>Convert from text representation to an integer</fsummary> + <fsummary>Convert from text representation to an integer.</fsummary> <desc> <p>Returns an integer whose text representation in base - <c><anno>Base</anno></c> is <c><anno>String</anno></c>.</p> + <c><anno>Base</anno></c> is <c><anno>String</anno></c>, + for example:</p> <pre> > <input>list_to_integer("3FF", 16).</input> 1023</pre> @@ -2016,168 +2730,217 @@ os_prompt% </pre> representation of an integer.</p> </desc> </func> + <func> <name name="list_to_pid" arity="1"/> - <fsummary>Convert from text representation to a pid</fsummary> + <fsummary>Convert from text representation to a pid.</fsummary> <desc> - <p>Returns a pid whose text representation is <c><anno>String</anno></c>.</p> - <warning> - <p>This BIF is intended for debugging and for use in - the Erlang operating system. It should not be used in - application programs.</p> - </warning> + <p>Returns a process identifier whose text representation is a + <c><anno>String</anno></c>, for example:</p> <pre> > <input>list_to_pid("<0.4.1>").</input> <0.4.1></pre> <p>Failure: <c>badarg</c> if <c><anno>String</anno></c> contains a bad - representation of a pid.</p> + representation of a process 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_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> + <fsummary>Convert a list to a tuple.</fsummary> <desc> - <p>Returns a tuple which corresponds to <c><anno>List</anno></c>. <c><anno>List</anno></c> - can contain any Erlang terms.</p> + <p>Returns a tuple corresponding to <c><anno>List</anno></c>, + for example</p> <pre> > <input>list_to_tuple([share, ['Ericsson_B', 163]]).</input> {share, ['Ericsson_B', 163]}</pre> + <p><c><anno>List</anno></c> can contain any Erlang terms.</p> </desc> </func> + <func> <name name="load_module" arity="2"/> - <fsummary>Load object code for a module</fsummary> + <fsummary>Load object code for a module.</fsummary> <desc> - <p>If <c><anno>Binary</anno></c> contains the object code for the module - <c><anno>Module</anno></c>, this BIF loads that object code. Also, if - the code for the module <c><anno>Module</anno></c> already exists, all + <p>If <c><anno>Binary</anno></c> contains the object code for module + <c><anno>Module</anno></c>, this BIF loads that object code. If + the code for module <c><anno>Module</anno></c> already exists, all export references are replaced so they point to the newly loaded code. The previously loaded code is kept in the system - as old code, as there may still be processes which are - executing that code. It returns either - <c>{module, <anno>Module</anno>}</c>, or <c>{error, <anno>Reason</anno>}</c> if loading - fails. <c><anno>Reason</anno></c> is one of the following:</p> + as old code, as there can still be processes executing + that code.</p> + <p>Returns either <c>{module, <anno>Module</anno>}</c>, or + <c>{error, <anno>Reason</anno>}</c> if loading fails. + <c><anno>Reason</anno></c> is one of the following:</p> <taglist> <tag><c>badfile</c></tag> - <item> - <p>The object code in <c><anno>Binary</anno></c> has an - incorrect format <em>or</em> the object code contains code - for another module than <c><anno>Module</anno></c>.</p> + <item>The object code in <c><anno>Binary</anno></c> has an + incorrect format <em>or</em> the object code contains code + for another module than <c><anno>Module</anno></c>. </item> <tag><c>not_purged</c></tag> - <item> - <p><c><anno>Binary</anno></c> contains a module which cannot be loaded - because old code for this module already exists.</p> + <item><c><anno>Binary</anno></c> contains a module that cannot be + loaded because old code for this module already exists. </item> </taglist> <warning> <p>This BIF is intended for the code server (see - <seealso marker="kernel:code">code(3)</seealso>) and should not be - used elsewhere.</p> + <seealso marker="kernel:code"><c>code(3)</c></seealso>) + and is not to be used elsewhere.</p> </warning> </desc> </func> + <func> <name name="load_nif" arity="2"/> - <fsummary>Load NIF library</fsummary> + <fsummary>Load NIF library.</fsummary> <desc> - <note> - <p>In releases older than OTP R14B, NIFs were an - experimental feature. Versions of OTP older than R14B might - have different and possibly incompatible NIF semantics and - interfaces. For example, in 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 sharable object/dynamic library file minus - the OS-dependent file extension (.so for Unix and .dll for - Windows). See <seealso marker="erl_nif">erl_nif</seealso> - on how to implement a NIF library.</p> - <p><c><anno>LoadInfo</anno></c> can be any term. It will be passed on to - the library as part of the initialization. A good practice is - to include a module version number to support future code - upgrade scenarios.</p> + implemented functions (NIFs) for a module. <c><anno>Path</anno></c> + is a file path to the shareable object/dynamic library file minus + the OS-dependent file extension (<c>.so</c> for Unix and + <c>.dll</c> for Windows). Notice that on most OSs the library has + to have a different name on disc when an upgrade of the nif is + done. If the name is the same, but the contents differ, the + old library may be loaded instead. For information on how to + implement a NIF library, see + <seealso marker="erl_nif"><c>erl_nif(3)</c></seealso>.</p> + <p><c><anno>LoadInfo</anno></c> can be any term. It is passed on to + the library as part of the initialization. A good practice is + to include a module version number to support future code + upgrade scenarios.</p> <p>The call to <c>load_nif/2</c> must be made - <em>directly</em> from the Erlang code of the module that the - NIF library belongs to.</p> - <p>It returns either <c>ok</c>, or <c>{error,{<anno>Reason</anno>,Text}}</c> - if loading fails. <c><anno>Reason</anno></c> is one of the atoms below, - while <c><anno>Text</anno></c> is a human readable string that may give - some more information about the failure.</p> + <em>directly</em> from the Erlang code of the module that the + NIF library belongs to. It returns either <c>ok</c>, or + <c>{error,{<anno>Reason</anno>,Text}}</c> if loading fails. + <c><anno>Reason</anno></c> is one of the following atoms + while <c><anno>Text</anno></c> is a human readable string that + can give more information about the failure:</p> <taglist> <tag><c>load_failed</c></tag> - <item> - <p>The OS failed to load the NIF library.</p> + <item>The OS failed to load the NIF library. </item> <tag><c>bad_lib</c></tag> - <item> - <p>The library did not fulfil the requirements as a NIF - library of the calling module.</p> + <item>The library did not fulfill the requirements as a NIF + library of the calling module. </item> - <tag><c>load | reload | upgrade</c></tag> - <item> - <p>The corresponding library callback was not successful.</p> + <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> - <p>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.</p> + <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> + <func> <name name="loaded" arity="0"/> - <fsummary>List of all loaded modules</fsummary> + <fsummary>List all loaded modules.</fsummary> <desc> - <p>Returns a list of all loaded Erlang modules (current and/or + <p>Returns a list of all loaded Erlang modules (current and old code), including preloaded modules.</p> - <p>See also <seealso marker="kernel:code">code(3)</seealso>.</p> + <p>See also <seealso marker="kernel:code"> + <c>code(3)</c></seealso>.</p> </desc> </func> + <func> <name name="localtime" arity="0"/> - <fsummary>Current local date and time</fsummary> + <fsummary>Current local date and time.</fsummary> <desc> - <p>Returns the current local date and time - <c>{{Year, Month, Day}, {Hour, Minute, Second}}</c>.</p> - <p>The time zone and daylight saving time correction depend - on the underlying OS.</p> + <p>Returns the current local date and time, + <c>{{Year, Month, Day}, {Hour, Minute, Second}}</c>, + for example:</p> <pre> > <input>erlang:localtime().</input> {{1996,11,6},{14,45,17}}</pre> + <p>The time zone and Daylight Saving Time correction depend + on the underlying OS.</p> </desc> </func> + <func> <name name="localtime_to_universaltime" arity="1"/> - <fsummary>Convert from local to Universal Time Coordinated (UTC) date and time</fsummary> + <fsummary>Convert from local to Universal Time Coordinated (UTC) date + and time.</fsummary> <desc> <p>Converts local date and time to Universal Time Coordinated - (UTC), if this is supported by the underlying OS. Otherwise, - no conversion is done and <c><anno>Localtime</anno></c> is returned.</p> + (UTC), if supported by the underlying OS. Otherwise + no conversion is done and <c><anno>Localtime</anno></c> + is returned. Example:</p> <pre> > <input>erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}).</input> {{1996,11,6},{13,45,17}}</pre> - <p>Failure: <c>badarg</c> if <c><anno>Localtime</anno></c> does not denote - a valid date and time.</p> + <p>Failure: <c>badarg</c> if <c><anno>Localtime</anno></c> denotes an + invalid date and time.</p> </desc> </func> + <func> <name name="localtime_to_universaltime" arity="2"/> - <fsummary>Convert from local to Universal Time Coordinated (UTC) date and time</fsummary> + <fsummary>Convert from local to Universal Time Coordinated (UTC) date + and time.</fsummary> <desc> <p>Converts local date and time to Universal Time Coordinated - (UTC) just like <c>erlang:localtime_to_universaltime/1</c>, - but the caller decides if daylight saving time is active or - not.</p> - <p>If <c><anno>IsDst</anno> == true</c> the <c><anno>Localtime</anno></c> is during - daylight saving time, if <c><anno>IsDst</anno> == false</c> it is not, - and if <c><anno>IsDst</anno> == undefined</c> the underlying OS may - guess, which is the same as calling + (UTC) as <c>erlang:localtime_to_universaltime/1</c>, + but the caller decides if Daylight Saving Time is active.</p> + <p>If <c><anno>IsDst</anno> == true</c>, <c><anno>Localtime</anno></c> + is during Daylight Saving Time, if <c><anno>IsDst</anno> == false</c> + it is not. If <c><anno>IsDst</anno> == undefined</c>, the underlying + OS can guess, which is the same as calling <c>erlang:localtime_to_universaltime(<anno>Localtime</anno>)</c>.</p> + <p>Examples:</p> <pre> > <input>erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}, true).</input> {{1996,11,6},{12,45,17}} @@ -2185,519 +2948,737 @@ os_prompt% </pre> {{1996,11,6},{13,45,17}} > <input>erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}, undefined).</input> {{1996,11,6},{13,45,17}}</pre> - <p>Failure: <c>badarg</c> if <c><anno>Localtime</anno></c> does not denote - a valid date and time.</p> + <p>Failure: <c>badarg</c> if <c><anno>Localtime</anno></c> denotes an + invalid date and time.</p> </desc> </func> + <func> <name name="make_ref" arity="0"/> - <fsummary>Return an almost unique reference</fsummary> + <fsummary>Return a unique reference.</fsummary> <desc> - <p>Returns an almost unique reference.</p> - <p>The returned reference will re-occur after approximately 2^82 - calls; therefore it is unique enough for practical purposes.</p> - <pre> -> <input>make_ref().</input> -#Ref<0.0.0.135></pre> + <p>Returns a + <seealso marker="doc/efficiency_guide:advanced#unique_references"> + unique reference</seealso>. The reference is unique among + connected nodes.</p> + <warning> + <p>Known issue: When a node is restarted multiple + times with the same node name, references created + on a newer node can be mistaken for a reference + created on an older node with the same node name.</p> + </warning> </desc> </func> + <func> <name name="make_tuple" arity="2"/> - <fsummary>Create a new tuple of a given arity</fsummary> + <fsummary>Create a new tuple of a specified arity.</fsummary> <desc> - <p>Returns a new tuple of the given <c><anno>Arity</anno></c>, where all - elements are <c><anno>InitialValue</anno></c>.</p> + <p>Creates a new tuple of the specified <c><anno>Arity</anno></c>, where + all elements are <c><anno>InitialValue</anno></c>, for example:</p> <pre> > <input>erlang:make_tuple(4, []).</input> {[],[],[],[]}</pre> </desc> </func> + <func> <name name="make_tuple" arity="3"/> - <fsummary>Create a new tuple with given arity and contents</fsummary> - <desc> - <p><c>erlang:make_tuple</c> first creates a tuple of size <c><anno>Arity</anno></c> - where each element has the value <c><anno>DefaultValue</anno></c>. It then fills - in values from <c><anno>InitList</anno></c>. Each list element in <c><anno>InitList</anno></c> - must be a two-tuple where the first element is a position in the - newly created tuple and the second element is any term. If a position - occurs more than once in the list, the term corresponding to - last occurrence will be used.</p> + <fsummary>Create a new tuple with specifed arity and contents.</fsummary> + <desc> + <p>Creates a tuple of size <c><anno>Arity</anno></c>, where each element + has value <c><anno>DefaultValue</anno></c>, and then fills in + values from <c><anno>InitList</anno></c>. + Each list element in <c><anno>InitList</anno></c> + must be a two-tuple, where the first element is a position in the + newly created tuple and the second element is any term. If a + position occurs more than once in the list, the term corresponding + to the last occurrence is used. Example:</p> <pre> > <input>erlang:make_tuple(5, [], [{2,ignored},{5,zz},{2,aa}]).</input> -{{[],aa,[],[],zz}</pre> +{[],aa,[],[],zz}</pre> </desc> </func> + + <func> + <name name="map_get" arity="2" /> + <fsummary>Extract a value from a map</fsummary> + <desc> + <p>Returns value <c><anno>Value</anno></c> associated with + <c><anno>Key</anno></c> if <c><anno>Map</anno></c> contains + <c><anno>Key</anno></c>.</p> + <p>The call fails with a <c>{badmap,Map}</c> exception if + <c><anno>Map</anno></c> is not a map, or with a <c>{badkey,Key}</c> + exception if no value is associated with <c><anno>Key</anno></c>.</p> + <p><em>Example:</em></p> + <code type="none"> +> Key = 1337, + Map = #{42 => value_two,1337 => "value one","a" => 1}, + map_get(Key,Map). +"value one"</code> + </desc> + </func> + <func> <name name="map_size" arity="1"/> - <fsummary>Return the size of a map</fsummary> + <fsummary>Return the size of a map.</fsummary> <desc> - <p>Returns an integer which is the number of key-value pairs in <c><anno>Map</anno></c>.</p> + <p>Returns an integer, which is the number of key-value pairs + in <c><anno>Map</anno></c>, for example:</p> <pre> > <input>map_size(#{a=>1, b=>2, c=>3}).</input> 3</pre> <p>Allowed in guard tests.</p> </desc> </func> + + <func> + <name name="match_spec_test" arity="3"/> + <fsummary>Test that a match specification works.</fsummary> + <desc> + <p>Tests a match specification used in calls to + <seealso marker="stdlib:ets#select/2"><c>ets:select/2</c></seealso> + and <seealso marker="#trace_pattern/3"> + <c>erlang:trace_pattern/3</c></seealso>. + The function tests both a match specification for "syntactic" + correctness and runs the match specification against the object. If + the match specification contains errors, the tuple <c>{error, + Errors}</c> is returned, where <c>Errors</c> is a list of natural + language descriptions of what was wrong with the match + specification.</p> + <p>If <c><anno>Type</anno></c> is <c>table</c>, the object to match + against is to be a tuple. The function then returns + <c>{ok,Result,[],Warnings}</c>, where <c>Result</c> is what would + have been the result in a real <c>ets:select/2</c> call, or + <c>false</c> if the match specification does not match the object + tuple.</p> + <p>If <c><anno>Type</anno></c> is <c>trace</c>, the object to match + against is to be a list. The function returns + <c>{ok, Result, Flags, Warnings}</c>, where <c>Result</c> is one of + the following:</p> + <list type="bulleted"> + <item><c>true</c> if a trace message is to be emitted</item> + <item><c>false</c> if a trace message is not to be emitted</item> + <item>The message term to be appended to the trace message</item> + </list> + <p><c>Flags</c> is a list containing all the trace flags to be enabled, + currently this is only <c>return_trace</c>.</p> + <p>This is a useful debugging and test tool, especially when writing + complicated match specifications.</p> + <p>See also + <seealso marker="stdlib:ets#test_ms/2"><c>ets:test_ms/2</c></seealso>.</p> + </desc> + </func> + <func> <name name="max" arity="2"/> - <fsummary>Return the largest of two term</fsummary> + <fsummary>Return the largest of two terms.</fsummary> <desc> - <p>Return the largest of <c><anno>Term1</anno></c> and <c><anno>Term2</anno></c>; - if the terms compare equal, <c><anno>Term1</anno></c> will be returned.</p> + <p>Returns the largest of <c><anno>Term1</anno></c> and + <c><anno>Term2</anno></c>. + If the terms are equal, <c><anno>Term1</anno></c> is returned.</p> </desc> </func> + <func> <name name="md5" arity="1"/> - <fsummary>Compute an MD5 message digest</fsummary> + <fsummary>Compute an MD5 message digest.</fsummary> <desc> - <p>Computes an <c>MD5</c> message digest from <c><anno>Data</anno></c>, where - the length of the digest is 128 bits (16 bytes). <c><anno>Data</anno></c> + <p>Computes an MD5 message digest from <c><anno>Data</anno></c>, where + the length of the digest is 128 bits (16 bytes). + <c><anno>Data</anno></c> is a binary or a list of small integers and binaries.</p> - <p>See The MD5 Message Digest Algorithm (RFC 1321) for more - information about MD5.</p> - <warning><p>The MD5 Message Digest Algorithm is <em>not</em> considered - safe for code-signing or software integrity purposes.</p></warning> + <p>For more information about MD5, see + <url href="https://www.ietf.org/rfc/rfc1321.txt"> + RFC 1321 - The MD5 Message-Digest Algorithm</url>.</p> + <warning> + <p>The MD5 Message-Digest Algorithm is <em>not</em> considered + safe for code-signing or software-integrity purposes.</p> + </warning> </desc> </func> + <func> <name name="md5_final" arity="1"/> - <fsummary>Finish the update of an MD5 context and return the computed MD5 message digest</fsummary> + <fsummary>Finish the update of an MD5 context and return the computed + MD5 message digest.</fsummary> <desc> <p>Finishes the update of an MD5 <c><anno>Context</anno></c> and returns the computed <c>MD5</c> message digest.</p> </desc> </func> + <func> <name name="md5_init" arity="0"/> - <fsummary>Create an MD5 context</fsummary> + <fsummary>Create an MD5 context.</fsummary> <desc> - <p>Creates an MD5 context, to be used in subsequent calls to + <p>Creates an MD5 context, to be used in the following calls to <c>md5_update/2</c>.</p> </desc> </func> + <func> <name name="md5_update" arity="2"/> - <fsummary>Update an MD5 context with data, and return a new context</fsummary> + <fsummary>Update an MD5 context with data and return a new context. + </fsummary> <desc> - <p>Updates an MD5 <c><anno>Context</anno></c> with <c><anno>Data</anno></c>, and returns - a <c><anno>NewContext</anno></c>.</p> + <p>Update an MD5 <c><anno>Context</anno></c> with + <c><anno>Data</anno></c> and returns a + <c><anno>NewContext</anno></c>.</p> </desc> </func> + <func> <name name="memory" arity="0"/> + <fsummary>Information about dynamically allocated memory.</fsummary> <type name="memory_type"/> - <fsummary>Information about dynamically allocated memory</fsummary> - <desc> - <p>Returns a list containing information about memory - dynamically allocated by the Erlang emulator. Each element of - the list is a tuple <c>{Type, Size}</c>. The first element - <c><anno>Type</anno></c>is an atom describing memory type. The second - element <c><anno>Size</anno></c>is memory size in bytes. A description of - each memory type follows:</p> + <desc> + <p>Returns a list with information about memory + dynamically allocated by the Erlang emulator. Each list + element is a tuple <c>{Type, Size}</c>. The first element + <c><anno>Type</anno></c> is an atom describing memory type. The second + element <c><anno>Size</anno></c> is the memory size in bytes.</p> + <p>Memory types:</p> <taglist> <tag><c>total</c></tag> <item> - <p>The total amount of memory currently allocated, which is - the same as the sum of memory size for <c>processes</c> + <p>The total amount of memory currently allocated. This is + the same as the sum of the memory size for <c>processes</c> and <c>system</c>.</p> </item> <tag><c>processes</c></tag> <item> - <p>The total amount of memory currently allocated by + <p>The total amount of memory currently allocated for the Erlang processes.</p> </item> <tag><c>processes_used</c></tag> <item> <p>The total amount of memory currently used by the Erlang - processes.</p> - <p>This memory is part of the memory presented as + processes. This is part of the memory presented as <c>processes</c> memory.</p> </item> <tag><c>system</c></tag> <item> - <p>The total amount of memory currently allocated by + <p>The total amount of memory currently allocated for the emulator that is not directly related to any Erlang - process.</p> - <p>Memory presented as <c>processes</c> is not included in - this memory.</p> + process. Memory presented as <c>processes</c> is not + included in this memory. <seealso marker="tools:instrument"> + <c>instrument(3)</c></seealso> can be used to + get a more detailed breakdown of what memory is part + of this type.</p> </item> <tag><c>atom</c></tag> <item> - <p>The total amount of memory currently allocated for atoms.</p> - <p>This memory is part of the memory presented as + <p>The total amount of memory currently allocated for atoms. + This memory is part of the memory presented as <c>system</c> memory.</p> </item> <tag><c>atom_used</c></tag> <item> - <p>The total amount of memory currently used for atoms.</p> - <p>This memory is part of the memory presented as + <p>The total amount of memory currently used for atoms. + This memory is part of the memory presented as <c>atom</c> memory.</p> </item> <tag><c>binary</c></tag> <item> <p>The total amount of memory currently allocated for - binaries.</p> - <p>This memory is part of the memory presented as - <c>system</c> memory.</p> + binaries. This memory is part of the memory presented + as <c>system</c> memory.</p> </item> <tag><c>code</c></tag> <item> <p>The total amount of memory currently allocated for - Erlang code.</p> - <p>This memory is part of the memory presented as - <c>system</c> memory.</p> + Erlang code. This memory is part of the memory presented + as <c>system</c> memory.</p> </item> <tag><c>ets</c></tag> <item> - <p>The total amount of memory currently allocated for ets - tables.</p> - <p>This memory is part of the memory presented as + <p>The total amount of memory currently allocated for ETS + tables. This memory is part of the memory presented as <c>system</c> memory.</p> </item> <tag><c>low</c></tag> <item> - <p>Only on 64-bit halfword emulator.</p> - <p>The total amount of memory allocated in low memory areas - that are restricted to less than 4 Gb even though - the system may have more physical memory.</p> - <p>May be removed in future releases of halfword emulator.</p> + <p>Only on 64-bit halfword emulator. + The total amount of memory allocated in low memory areas + that are restricted to < 4 GB, although + the system can have more memory.</p> + <p>Can be removed in a future release of the halfword + emulator.</p> </item> <tag><c>maximum</c></tag> <item> <p>The maximum total amount of memory allocated since - the emulator was started.</p> - <p>This tuple is only present when the emulator is run with - instrumentation.</p> + the emulator was started. This tuple is only present + when the emulator is run with instrumentation.</p> <p>For information on how to run the emulator with - instrumentation see - <seealso marker="tools:instrument">instrument(3)</seealso> - and/or <seealso marker="erts:erl">erl(1)</seealso>.</p> + instrumentation, see + <seealso marker="tools:instrument"> + <c>instrument(3)</c></seealso> + and/or <seealso marker="erl"><c>erl(1)</c></seealso>.</p> </item> </taglist> <note> <p>The <c>system</c> value is not complete. Some allocated - memory that should be part of the <c>system</c> value are - not.</p> + memory that is to be part of this value is not.</p> <p>When the emulator is run with instrumentation, the <c>system</c> value is more accurate, but memory - directly allocated by <c>malloc</c> (and friends) are still + directly allocated for <c>malloc</c> (and friends) is still not part of the <c>system</c> value. Direct calls to - <c>malloc</c> are only done from OS specific runtime - libraries and perhaps from user implemented Erlang drivers + <c>malloc</c> are only done from OS-specific runtime + libraries and perhaps from user-implemented Erlang drivers that do not use the memory allocation functions in the driver interface.</p> - <p>Since the <c>total</c> value is the sum of <c>processes</c> - and <c>system</c> the error in <c>system</c> will propagate + <p>As the <c>total</c> value is the sum of <c>processes</c> + and <c>system</c>, the error in <c>system</c> propagates to the <c>total</c> value.</p> - <p>The different amounts of memory that are summed are - <em>not</em> gathered atomically which also introduce - an error in the result.</p> + <p>The different amounts of memory that are summed are + <em>not</em> gathered atomically, which introduces + an error in the result.</p> </note> - <p>The different values has the following relation to each + <p>The different values have the following relation to each other. Values beginning with an uppercase letter is not part of the result.</p> <code type="none"> - total = processes + system - processes = processes_used + ProcessesNotUsed - system = atom + binary + code + ets + OtherSystem - atom = atom_used + AtomNotUsed - - RealTotal = processes + RealSystem - RealSystem = system + MissedSystem</code> - <p>More tuples in the returned list may be added in the future.</p> +total = processes + system +processes = processes_used + ProcessesNotUsed +system = atom + binary + code + ets + OtherSystem +atom = atom_used + AtomNotUsed +RealTotal = processes + RealSystem +RealSystem = system + MissedSystem</code> + <p>More tuples in the returned list can be added in a + future release.</p> <note> <p>The <c>total</c> value is supposed to be the total amount of memory dynamically allocated by the emulator. Shared libraries, the code of the emulator itself, and - the emulator stack(s) are not supposed to be included. That + the emulator stacks are not supposed to be included. That is, the <c>total</c> value is <em>not</em> supposed to be - equal to the total size of all pages mapped to the emulator. - Furthermore, due to fragmentation and pre-reservation of - memory areas, the size of the memory segments which contain - the dynamically allocated memory blocks can be substantially + equal to the total size of all pages mapped to the emulator.</p> + <p>Also, because of fragmentation and prereservation of + memory areas, the size of the memory segments containing + the dynamically allocated memory blocks can be much larger than the total size of the dynamically allocated memory blocks.</p> </note> - <note> - <p> - Since erts version 5.6.4 <c>erlang:memory/0</c> requires that - all <seealso marker="erts:erts_alloc">erts_alloc(3)</seealso> - allocators are enabled (default behaviour). - </p> - </note> - <p>Failure:</p> - <taglist> - <tag><c>notsup</c></tag> - <item> - If an <seealso marker="erts:erts_alloc">erts_alloc(3)</seealso> - allocator has been disabled. - </item> - </taglist> + <note> + <p>As from ERTS 5.6.4, <c>erlang:memory/0</c> requires that + all <seealso marker="erts:erts_alloc"><c>erts_alloc(3)</c></seealso> + allocators are enabled (default behavior).</p> + </note> + <p>Failure: <c>notsup</c> if an + <seealso marker="erts:erts_alloc"><c>erts_alloc(3)</c></seealso> + allocator has been disabled.</p> </desc> </func> + <func> <name name="memory" arity="1" clause_i="1"/> <name name="memory" arity="1" clause_i="2"/> + <fsummary>Information about dynamically allocated memory.</fsummary> <type name="memory_type"/> - <fsummary>Information about dynamically allocated memory</fsummary> <desc> - <p>Returns the memory size in bytes allocated for memory of - type <c><anno>Type</anno></c>. The argument can also be given as a list + <p>Returns the memory size in bytes allocated for memory of type + <c><anno>Type</anno></c>. The argument can also be specified as a list of <c>memory_type()</c> atoms, in which case a corresponding list of <c>{memory_type(), Size :: integer >= 0}</c> tuples is returned.</p> - <note> - <p> - Since erts version 5.6.4 <c>erlang:memory/1</c> requires that - all <seealso marker="erts:erts_alloc">erts_alloc(3)</seealso> - allocators are enabled (default behaviour). - </p> - </note> + <note> + <p>As from ERTS 5.6.4, + <c>erlang:memory/1</c> requires that + all <seealso marker="erts_alloc"><c>erts_alloc(3)</c></seealso> + allocators are enabled (default behavior).</p> + </note> <p>Failures:</p> <taglist> <tag><c>badarg</c></tag> <item> - If <c><anno>Type</anno></c> is not one of the memory types listed in the - documentation of - <seealso marker="#memory/0">erlang:memory/0</seealso>. - </item> + If <c><anno>Type</anno></c> is not one of the memory types + listed in the description of + <seealso marker="#memory/0"><c>erlang:memory/0</c></seealso>. + </item> <tag><c>badarg</c></tag> <item> - If <c>maximum</c> is passed as <c><anno>Type</anno></c> and the emulator - is not run in instrumented mode. - </item> + If <c>maximum</c> is passed as <c><anno>Type</anno></c> and + the emulator is not run in instrumented mode. + </item> <tag><c>notsup</c></tag> <item> - If an <seealso marker="erts:erts_alloc">erts_alloc(3)</seealso> - allocator has been disabled. - </item> - </taglist> + If an <seealso marker="erts_alloc"><c>erts_alloc(3)</c></seealso> + allocator has been disabled. + </item> + </taglist> <p>See also - <seealso marker="#memory/0">erlang:memory/0</seealso>.</p> + <seealso marker="#memory/0"><c>erlang:memory/0</c></seealso>.</p> </desc> </func> + <func> <name name="min" arity="2"/> - <fsummary>Return the smallest of two term</fsummary> + <fsummary>Return the smallest of two terms.</fsummary> <desc> - <p>Return the smallest of <c><anno>Term1</anno></c> and <c><anno>Term2</anno></c>; - if the terms compare equal, <c><anno>Term1</anno></c> will be returned.</p> + <p>Returns the smallest of <c><anno>Term1</anno></c> and + <c><anno>Term2</anno></c>. + If the terms are equal, <c><anno>Term1</anno></c> is returned.</p> </desc> </func> + <func> <name name="module_loaded" arity="1"/> - <fsummary>Check if a module is loaded</fsummary> + <fsummary>Check if a module is loaded.</fsummary> <desc> - <p>Returns <c>true</c> if the module <c><anno>Module</anno></c> is loaded, - otherwise returns <c>false</c>. It does not attempt to load + <p>Returns <c>true</c> if the module <c><anno>Module</anno></c> + is loaded, otherwise <c>false</c>. It does not attempt to load the module.</p> <warning> <p>This BIF is intended for the code server (see - <seealso marker="kernel:code">code(3)</seealso>) and should not be - used elsewhere.</p> + <seealso marker="kernel:code"><c>code(3)</c></seealso>) + and is not to be used elsewhere.</p> </warning> </desc> </func> + <func> - <name name="monitor" arity="2"/> - <fsummary>Start monitoring</fsummary> - <desc> - <p>The calling process starts monitoring <c><anno>Item</anno></c> which is - an object of type <c><anno>Type</anno></c>.</p> - <p>Currently only processes can be monitored, i.e. the only - allowed <c><anno>Type</anno></c> is <c>process</c>, but other types may be - allowed in the future.</p> - <p><c><anno>Item</anno></c> can be:</p> - <taglist> - <tag><c>pid()</c></tag> - <item> - <p>The pid of the process to monitor.</p> - </item> - <tag><c>{RegName, Node}</c></tag> - <item> - <p>A tuple consisting of a registered name of a process and - a node name. The process residing on the node <c>Node</c> - with the registered name <c>RegName</c> will be monitored.</p> - </item> - <tag><c>RegName</c></tag> - <item> - <p>The process locally registered as <c>RegName</c> will be - monitored.</p> - </item> - </taglist> - <note> - <p>When a process is monitored by registered name, the process - that has the registered name at the time when - <c>monitor/2</c> is called will be monitored. - The monitor will not be effected, if the registered name is - unregistered.</p> - </note> - <p>A <c>'DOWN'</c> message will be sent to the monitoring - process if <c><anno>Item</anno></c> dies, if <c><anno>Item</anno></c> does not exist, - or if the connection is lost to the node which <c><anno>Item</anno></c> - resides on. A <c>'DOWN'</c> message has the following pattern:</p> + <name name="monitor" arity="2" clause_i="1"/> + <name name="monitor" arity="2" clause_i="2"/> + <name name="monitor" arity="2" clause_i="3"/> + <fsummary>Start monitoring.</fsummary> + <type name="registered_name"/> + <type name="registered_process_identifier"/> + <type name="monitor_process_identifier"/> + <type name="monitor_port_identifier"/> + <desc> + <p>Sends a monitor request of type <c><anno>Type</anno></c> to the + entity identified by <c><anno>Item</anno></c>. If the monitored entity + does not exist or it changes monitored state, the caller of + <c>monitor/2</c> is notified by a message on the following format:</p> <code type="none"> +{Tag, <anno>MonitorRef</anno>, <anno>Type</anno>, Object, Info}</code> + <note> + <p>The monitor request is an asynchronous signal. That is, it + takes time before the signal reaches its destination.</p> + </note> + + <p><c><anno>Type</anno></c> can be one of the following atoms: + <c>process</c>, <c>port</c> or <c>time_offset</c>.</p> + + <p>A <c>process</c> or <c>port</c> monitor is triggered only once, + after that it is removed from both monitoring process and + the monitored entity. Monitors are fired when the monitored process + or port terminates, does not exist at the moment of creation, + or if the connection to it is lost. If the connection to it is lost, + we do not know if it still exists. The monitoring is also turned off + when <seealso marker="#demonitor/1">demonitor/1</seealso> is + called.</p> + + <p>A <c>process</c> or <c>port</c> monitor by name + resolves the <c>RegisteredName</c> to <c>pid()</c> or <c>port()</c> + only once at the moment of monitor instantiation, later changes to + the name registration will not affect the existing monitor.</p> + + <p>When a <c>process</c> or <c>port</c> monitor is triggered, + a <c>'DOWN'</c> message is sent that has the following pattern:</p> + <code type="none"> {'DOWN', MonitorRef, Type, Object, Info}</code> - <p>where <c>MonitorRef</c> and <c>Type</c> are the same as - described above, and:</p> + + <p>In the monitor message <c>MonitorRef</c> and <c>Type</c> are the + same as described earlier, and:</p> <taglist> <tag><c>Object</c></tag> <item> - <p>A reference to the monitored object:</p> - <list type="bulleted"> - <item>the pid of the monitored process, if <c><anno>Item</anno></c> was - specified as a pid.</item> - <item><c>{RegName, Node}</c>, if <c><anno>Item</anno></c> was specified as - <c>{RegName, Node}</c>.</item> - <item><c>{RegName, Node}</c>, if <c><anno>Item</anno></c> was specified as - <c>RegName</c>. <c>Node</c> will in this case be the - name of the local node (<c>node()</c>).</item> - </list> + <p>The monitored entity, which triggered the event. When monitoring + a local process or port, <c>Object</c> will be equal to the + <c>pid()</c> or <c>port()</c> that was being monitored. When + monitoring process or port by name, <c>Object</c> will have format + <c>{RegisteredName, Node}</c> where <c>RegisteredName</c> is the + name which has been used with <c>monitor/2</c> call and + <c>Node</c> is local or remote node name (for ports monitored by + name, <c>Node</c> is always local node name).</p> </item> <tag><c>Info</c></tag> <item> <p>Either the exit reason of the process, <c>noproc</c> - (non-existing process), or <c>noconnection</c> (no - connection to <c><anno>Node</anno></c>).</p> - </item> + (process or port did not exist at the time of monitor creation), + or <c>noconnection</c> (no connection to the node where the + monitored process resides). </p></item> </taglist> + + <taglist> + <tag>Monitoring a <marker id="monitor_process"/><c>process</c></tag> + <item> + <p>Creates monitor between the current process and another + process identified by <c><anno>Item</anno></c>, which can be a + <c>pid()</c> (local or remote), an atom <c>RegisteredName</c> or + a tuple <c>{RegisteredName, Node}</c> for a registered process, + located elsewhere.</p> + + <note><p>Before ERTS 10.0 (OTP 21.0), monitoring a process could fail with + <c>badarg</c> if the monitored process resided on a primitive node + (such as erl_interface or jinterface), where remote process monitoring + is not implemented.</p> + <p>Now, such a call to <c>monitor</c> will instead succeed and a + monitor is created. But the monitor will only supervise the + connection. That is, a <c>{'DOWN', _, process, _, noconnection}</c> is + the only message that may be received, as the primitive node have no + way of reporting the status of the monitored process.</p> + </note> + + </item> + + <tag>Monitoring a <marker id="monitor_port"/><c>port</c></tag> + <item> + <p>Creates monitor between the current process and a port + identified by <c><anno>Item</anno></c>, which can be a + <c>port()</c> (only local), an atom <c>RegisteredName</c> or + a tuple <c>{RegisteredName, Node}</c> for a registered port, + located on this node. Note, that attempt to monitor a remote port + will result in <c>badarg</c>.</p> + </item> + + <tag>Monitoring a + <marker id="monitor_time_offset"/><c>time_offset</c></tag> + <item> + <p>Monitors changes in + <seealso marker="#time_offset/0"><c>time offset</c></seealso> + between + <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang + monotonic time</seealso> and + <seealso marker="time_correction#Erlang_System_Time">Erlang + system time</seealso>. One valid <c><anno>Item</anno></c> + exists in combination with the + <c>time_offset <anno>Type</anno></c>, namely the atom + <c>clock_service</c>. Notice that the atom <c>clock_service</c> is + <em>not</em> the registered name of a process. In this + case it serves as an identifier of the runtime system internal + clock service at current runtime system instance.</p> + + <p>The monitor is triggered when the time offset is changed. + This either if the time offset value is changed, or if the + offset is changed from preliminary to final during + <seealso marker="#system_flag_time_offset">finalization + of the time offset</seealso> when the + <seealso marker="time_correction#Single_Time_Warp_Mode">single + time warp mode</seealso> is used. When a change from preliminary + to final time offset is made, the monitor is triggered once + regardless of whether the time offset value was changed + or not.</p> + + <p>If the runtime system is in + <seealso marker="time_correction#Multi_Time_Warp_Mode">multi + time warp mode</seealso>, the time offset is changed when + the runtime system detects that the + <seealso marker="time_correction#OS_System_Time">OS system + time</seealso> has changed. The runtime system does, however, + not detect this immediately when it occurs. A task checking + the time offset is scheduled to execute at least once a minute, + so under normal operation this is to be detected within a + minute, but during heavy load it can take longer time.</p> + + <p>The monitor is <em>not</em> automatically removed + after it has been triggered. That is, repeated changes of + the time offset trigger the monitor repeatedly.</p> + + <p>When the monitor is triggered a <c>'CHANGE'</c> message is + sent to the monitoring process. A <c>'CHANGE'</c> message has + the following pattern:</p> + <code type="none"> +{'CHANGE', MonitorRef, Type, Item, NewTimeOffset}</code> + <p>where <c>MonitorRef</c>, <c><anno>Type</anno></c>, and + <c><anno>Item</anno></c> are the same as described above, and + <c>NewTimeOffset</c> is the new time offset.</p> + + <p>When the <c>'CHANGE'</c> message has been received you are + guaranteed not to retrieve the old time offset when calling + <seealso marker="#time_offset/0"> + <c>erlang:time_offset()</c></seealso>. + Notice that you can observe the change of the time offset + when calling <c>erlang:time_offset()</c> before you + get the <c>'CHANGE'</c> message.</p> + </item> + </taglist> + + <p>Making several calls to <c>monitor/2</c> for the same + <c><anno>Item</anno></c> and/or <c><anno>Type</anno></c> is not + an error; it results in as many independent monitoring instances.</p> + + <p>The monitor functionality is expected to be extended. That is, + other <c><anno>Type</anno></c>s and <c><anno>Item</anno></c>s + are expected to be supported in a future release.</p> <note> - <p>If/when <c>monitor/2</c> is extended (e.g. to - handle other item types than <c>process</c>), other - possible values for <c>Object</c>, and <c>Info</c> in the - <c>'DOWN'</c> message will be introduced.</p> - </note> - <p>The monitoring is turned off either when the <c>'DOWN'</c> - message is sent, or when - <seealso marker="#demonitor/1">demonitor/1</seealso> - is called.</p> - <p>If an attempt is made to monitor a process on an older node - (where remote process monitoring is not implemented or one - where remote process monitoring by registered name is not - implemented), the call fails with <c>badarg</c>.</p> - <p>Making several calls to <c>monitor/2</c> for the same - <c><anno>Item</anno></c> is not an error; it results in as many, completely - independent, monitorings.</p> - <note> - <p>The format of the <c>'DOWN'</c> message changed in the 5.2 - version of the emulator (OTP release R9B) for monitor <em>by registered name</em>. The <c>Object</c> element of - the <c>'DOWN'</c> message could in earlier versions - sometimes be the pid of the monitored process and sometimes - be the registered name. Now the <c>Object</c> element is - always a tuple consisting of the registered name and - the node name. Processes on new nodes (emulator version 5.2 - or greater) will always get <c>'DOWN'</c> messages on - the new format even if they are monitoring processes on old - nodes. Processes on old nodes will always get <c>'DOWN'</c> - messages on the old format.</p> + <p>If or when <c>monitor/2</c> is extended, other + possible values for <c>Tag</c>, <c>Object</c>, and + <c>Info</c> in the monitor message will be introduced.</p> </note> </desc> </func> + <func> <name name="monitor_node" arity="2"/> - <fsummary>Monitor the status of a node</fsummary> + <fsummary>Monitor the status of a node.</fsummary> <desc> - <p>Monitors the status of the node <c><anno>Node</anno></c>. If <c><anno>Flag</anno></c> - is <c>true</c>, monitoring is turned on; if <c><anno>Flag</anno></c> is - <c>false</c>, monitoring is turned off.</p> + <p>Monitor the status of the node <c><anno>Node</anno></c>. + If <c><anno>Flag</anno></c> + is <c>true</c>, monitoring is turned on. If <c><anno>Flag</anno></c> + is <c>false</c>, monitoring is turned off.</p> <p>Making several calls to <c>monitor_node(Node, true)</c> for - the same <c><anno>Node</anno></c> is not an error; it results in as many, - completely independent, monitorings.</p> + the same <c><anno>Node</anno></c> is not an error; it results + in as many independent monitoring instances.</p> <p>If <c><anno>Node</anno></c> fails or does not exist, the message <c>{nodedown, Node}</c> is delivered to the process. If a process has made two calls to <c>monitor_node(Node, true)</c> - and <c><anno>Node</anno></c> terminates, two <c>nodedown</c> messages are - delivered to the process. If there is no connection to - <c><anno>Node</anno></c>, there will be an attempt to create one. If this - fails, a <c>nodedown</c> message is delivered.</p> + and <c><anno>Node</anno></c> terminates, two <c>nodedown</c> messages + are delivered to the process. If there is no connection to + <c><anno>Node</anno></c>, an attempt is made to create one. + If this fails, a <c>nodedown</c> message is delivered.</p> <p>Nodes connected through hidden connections can be monitored - as any other node.</p> + as any other nodes.</p> <p>Failure: <c>badarg</c> if the local node is not alive.</p> </desc> </func> + <func> <name name="monitor_node" arity="3"/> - <fsummary>Monitor the status of a node</fsummary> - <desc> - <p>Behaves as <c>monitor_node/2</c> except that it allows an - extra option to be given, namely <c>allow_passive_connect</c>. - The option allows the BIF to wait the normal net connection - timeout for the <em>monitored node</em> to connect itself, + <fsummary>Monitor the status of a node.</fsummary> + <desc> + <p>Behaves as + <seealso marker="#monitor_node/2"><c>monitor_node/2</c></seealso> + except that it allows an + extra option to be specified, namely <c>allow_passive_connect</c>. + This option allows the BIF to wait the normal network connection + time-out for the <em>monitored node</em> to connect itself, even if it cannot be actively connected from this node - (i.e. it is blocked). The state where this might be useful can - only be achieved by using the kernel option - <c>dist_auto_connect once</c>. If that kernel option is not - used, the <c>allow_passive_connect</c> option has no - effect.</p> + (that is, it is blocked). The state where this can be useful + can only be achieved by using the Kernel option + <c>dist_auto_connect once</c>. If that option is not + used, option <c>allow_passive_connect</c> has no effect.</p> <note> - <p>The <c>allow_passive_connect</c> option is used + <p>Option <c>allow_passive_connect</c> is used internally and is seldom needed in applications where the - network topology and the kernel options in effect is known in - advance.</p> + network topology and the Kernel options in effect + are known in advance.</p> </note> <p>Failure: <c>badarg</c> if the local node is not alive or the option list is malformed.</p> </desc> </func> + + <func> + <name name="monotonic_time" arity="0"/> + <fsummary>Current Erlang monotonic time.</fsummary> + <desc> + <p>Returns the current + <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang + monotonic time</seealso> in <c>native</c> + <seealso marker="#type_time_unit">time unit</seealso>. This + is a monotonically increasing time since some unspecified point in + time.</p> + <note> + <p>This is a + <seealso marker="time_correction#Monotonically_Increasing"> + monotonically increasing</seealso> time, but <em>not</em> a + <seealso marker="time_correction#Strictly_Monotonically_Increasing"> + strictly monotonically increasing</seealso> + time. That is, consecutive calls to + <c>erlang:monotonic_time/0</c> can produce the same result.</p> + <p>Different runtime system instances will use different unspecified + points in time as base for their Erlang monotonic clocks. + That is, it is <em>pointless</em> comparing monotonic times from + different runtime system instances. Different runtime system + instances can also place this unspecified point in time different + relative runtime system start. It can be placed in the future (time + at start is a negative value), the past (time at start is a + positive value), or the runtime system start (time at start is + zero). The monotonic time at runtime system start can be + retrieved by calling + <seealso marker="#system_info_start_time"> + <c>erlang:system_info(start_time)</c></seealso>.</p> + </note> + </desc> + </func> + + <func> + <name name="monotonic_time" arity="1"/> + <fsummary>Current Erlang monotonic time.</fsummary> + <desc> + <p>Returns the current + <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang + monotonic time</seealso> converted + into the <c><anno>Unit</anno></c> passed as argument.</p> + <p>Same as calling + <seealso marker="#convert_time_unit/3"> + <c>erlang:convert_time_unit</c></seealso><c>(</c><seealso + marker="#monotonic_time/0"> + <c>erlang:monotonic_time()</c></seealso><c>, + native, <anno>Unit</anno>)</c>, + however optimized for commonly used <c><anno>Unit</anno></c>s.</p> + </desc> + </func> + <func> <name name="nif_error" arity="1"/> - <fsummary>Stop execution with a given reason</fsummary> + <fsummary>Stop execution with a specified reason.</fsummary> <desc> <p>Works exactly like - <seealso marker="#error/1">erlang:error/1</seealso>, - but Dialyzer thinks that this BIF will return an arbitrary term. - When used in a stub function for a NIF to generate an - exception when the NIF library is not loaded, Dialyzer - will not generate false warnings.</p> + <seealso marker="#error/1"><c>error/1</c></seealso>, but + Dialyzer thinks that this BIF will return an arbitrary + term. When used in a stub function for a NIF to generate an + exception when the NIF library is not loaded, Dialyzer + does not generate false warnings.</p> </desc> </func> + <func> <name name="nif_error" arity="2"/> - <fsummary>Stop execution with a given reason</fsummary> + <fsummary>Stop execution with a specified reason.</fsummary> <desc> <p>Works exactly like - <seealso marker="#error/2">erlang:error/2</seealso>, - but Dialyzer thinks that this BIF will return an arbitrary term. - When used in a stub function for a NIF to generate an - exception when the NIF library is not loaded, Dialyzer - will not generate false warnings.</p> + <seealso marker="#error/2"><c>error/2</c></seealso>, but + Dialyzer thinks that this BIF will return an arbitrary + term. When used in a stub function for a NIF to generate an + exception when the NIF library is not loaded, Dialyzer + does not generate false warnings.</p> </desc> </func> + <func> <name name="node" arity="0"/> - <fsummary>Name of the local node</fsummary> + <fsummary>Name of the local node.</fsummary> <desc> <p>Returns the name of the local node. If the node is not alive, <c>nonode@nohost</c> is returned instead.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="node" arity="1"/> - <fsummary>At which node is a pid, port or reference located</fsummary> + <fsummary>At which node a pid, port, or reference originates.</fsummary> <desc> - <p>Returns the node where <c><anno>Arg</anno></c> is located. <c><anno>Arg</anno></c> can - be a pid, a reference, or a port. If the local node is not + <p>Returns the node where <c><anno>Arg</anno></c> originates. + <c><anno>Arg</anno></c> can + be a process identifier, a reference, or a port. + If the local node is not alive, <c>nonode@nohost</c> is returned.</p> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="nodes" arity="0"/> - <fsummary>All visible nodes in the system</fsummary> + <fsummary>All visible nodes in the system.</fsummary> <desc> - <p>Returns a list of all visible nodes in the system, excluding + <p>Returns a list of all visible nodes in the system, except the local node. Same as <c>nodes(visible)</c>.</p> </desc> </func> + <func> <name name="nodes" arity="1"/> - <fsummary>All nodes of a certain type in the system</fsummary> + <fsummary>All nodes of a certain type in the system.</fsummary> <desc> - <p>Returns a list of nodes according to argument given. - The result returned when the argument is a list, is the list + <p>Returns a list of nodes according to the argument specified. + The returned result, when the argument is a list, is the list of nodes satisfying the disjunction(s) of the list elements.</p> - <p><c><anno>NodeType</anno></c> can be any of the following:</p> + <p><c><anno>NodeType</anno></c>s:</p> <taglist> <tag><c>visible</c></tag> <item> @@ -2717,151 +3698,152 @@ os_prompt% </pre> </item> <tag><c>known</c></tag> <item> - <p>Nodes which are known to this node, i.e., connected, - previously connected, etc.</p> + <p>Nodes that are known to this node. That is, connected + nodes and nodes referred to by process identifiers, port + identifiers, and references located on this node. + The set of known nodes is garbage collected. Notice that + this garbage collection can be delayed. For more + information, see + <seealso marker="erlang#system_info_delayed_node_table_gc"> + <c>erlang:system_info(delayed_node_table_gc)</c></seealso>.</p> </item> </taglist> <p>Some equalities: <c>[node()] = nodes(this)</c>, <c>nodes(connected) = nodes([visible, hidden])</c>, and <c>nodes() = nodes(visible)</c>.</p> - <p>If the local node is not alive, - <c>nodes(this) == nodes(known) == [nonode@nohost]</c>, for - any other <c><anno>Arg</anno></c> the empty list [] is returned.</p> </desc> </func> + <func> <name name="now" arity="0"/> + <fsummary>Elapsed time since 00:00 GMT.</fsummary> <type name="timestamp"/> - <fsummary>Elapsed time since 00:00 GMT</fsummary> <desc> - <p>Returns the tuple <c>{MegaSecs, Secs, MicroSecs}</c> which is - the elapsed time since 00:00 GMT, January 1, 1970 (zero hour) - on the assumption that the underlying OS supports this. - Otherwise, some other point in time is chosen. It is also - guaranteed that subsequent calls to this BIF returns + <warning> + <p><em>This function is deprecated. Do not use it.</em></p> + <p>For more information, see section + <seealso marker="time_correction">Time and Time Correction</seealso> + in the User's Guide. Specifically, section + <seealso marker="time_correction#Dos_and_Donts"> + Dos and Dont's</seealso> describes what to use instead of + <c>erlang:now/0</c>.</p> + </warning> + <p>Returns the tuple <c>{MegaSecs, Secs, MicroSecs}</c>, which is + the elapsed time since 00:00 GMT, January 1, 1970 (zero hour), + if provided by the underlying OS. + Otherwise some other point in time is chosen. It is also + guaranteed that the following calls to this BIF return continuously increasing values. Hence, the return value from - <c>now()</c> can be used to generate unique time-stamps, - and if it is called in a tight loop on a fast machine + <c>erlang:now/0</c> can be used to generate unique time stamps. + If it is called in a tight loop on a fast machine, the time of the node can become skewed.</p> - <p>It can only be used to check the local time of day if - the time-zone info of the underlying operating system is + <p>Can only be used to check the local time of day if + the time-zone information of the underlying OS is properly configured.</p> - <p>If you do not need the return value to be unique and - monotonically increasing, use - <seealso marker="kernel:os#timestamp/0">os:timestamp/0</seealso> - instead to avoid some overhead.</p> </desc> </func> + <func> <name name="open_port" arity="2"/> - <fsummary>Open a port</fsummary> + <fsummary>Open a port.</fsummary> <desc> <p>Returns a port identifier as the result of opening a new Erlang port. A port can be seen as an external Erlang - process. - </p> - <p>The name of the executable as well as the arguments - given in <c>cd</c>, <c>env</c>, <c>args</c> and <c>arg0</c> is subject to - Unicode file name translation if the system is running - in Unicode file name mode. To avoid - translation or force i.e. UTF-8, supply the executable - and/or arguments as a binary in the correct - encoding. See the <seealso - marker="kernel:file">file</seealso> module, the - <seealso marker="kernel:file#native_name_encoding/0"> - file:native_name_encoding/0</seealso> function and the - <seealso marker="stdlib:unicode_usage">stdlib users guide - </seealso> for details.</p> - - <note><p>The characters in the name (if given as a list) - can only be > 255 if the Erlang VM is started in - Unicode file name translation mode, otherwise the name - of the executable is limited to the ISO-latin-1 - character set.</p></note> - - <p><c><anno>PortName</anno></c> is one of the following:</p> + process.</p> + <p>The name of the executable as well as the arguments + specifed in <c>cd</c>, <c>env</c>, <c>args</c>, and <c>arg0</c> are + subject to Unicode filename translation if the system is running + in Unicode filename mode. To avoid + translation or to force, for example UTF-8, supply the executable + and/or arguments as a binary in the correct + encoding. For details, see the module + <seealso marker="kernel:file"><c>file(3)</c></seealso>, the + function <seealso marker="kernel:file#native_name_encoding/0"> + <c>file:native_name_encoding/0</c></seealso> in Kernel, and + the <seealso marker="stdlib:unicode_usage"> + <c>Using Unicode in Erlang</c></seealso> User's Guide.</p> + <note> + <p>The characters in the name (if specified as a list) can + only be > 255 if the Erlang virtual machine is started + in Unicode filename translation mode. Otherwise the name + of the executable is limited to the ISO Latin-1 + character set.</p> + </note> + <p><c><anno>PortName</anno></c>s:</p> <taglist> <tag><c>{spawn, <anno>Command</anno>}</c></tag> <item> - <p>Starts an external program. <c><anno>Command</anno></c> is the name - of the external program which will be run. <c><anno>Command</anno></c> + <p>Starts an external program. <c><anno>Command</anno></c> + is the name of the external program to be run. + <c><anno>Command</anno></c> runs outside the Erlang work space unless an Erlang - driver with the name <c><anno>Command</anno></c> is found. If found, - that driver will be started. A driver runs in the Erlang - workspace, which means that it is linked with the Erlang + driver with the name <c><anno>Command</anno></c> is found. + If found, that driver is started. A driver runs in the Erlang + work space, which means that it is linked with the Erlang runtime system.</p> - <p>When starting external programs on Solaris, the system - call <c>vfork</c> is used in preference to <c>fork</c> - for performance reasons, although it has a history of - being less robust. If there are problems with using - <c>vfork</c>, setting the environment variable - <c>ERL_NO_VFORK</c> to any value will cause <c>fork</c> - to be used instead.</p> - - <p>For external programs, the <c>PATH</c> is searched - (or an equivalent method is used to find programs, - depending on operating system). This is done by invoking - the shell on certain platforms. The first space - separated token of the command will be considered as the - name of the executable (or driver). This (among other - things) makes this option unsuitable for running - programs having spaces in file or directory names. Use - {spawn_executable, <anno>Command</anno>} instead if spaces in executable - file names is desired.</p> + <p>For external programs, <c>PATH</c> is searched + (or an equivalent method is used to find programs, + depending on the OS). This is done by invoking + the shell on certain platforms. The first space-separated + token of the command is considered as the + name of the executable (or driver). This (among other + things) makes this option unsuitable for running + programs with spaces in filenames or directory names. + If spaces in executable filenames are desired, use + <c>{spawn_executable, <anno>Command</anno>}</c> instead.</p> </item> <tag><c>{spawn_driver, <anno>Command</anno>}</c></tag> <item> - <p>Works like <c>{spawn, <anno>Command</anno>}</c>, but demands the - first (space separated) token of the command to be the name of a - loaded driver. If no driver with that name is loaded, a - <c>badarg</c> error is raised.</p> + <p>Works like <c>{spawn, <anno>Command</anno>}</c>, but demands + the first (space-separated) token of the command to be the name + of a loaded driver. If no driver with that name is loaded, a + <c>badarg</c> error is raised.</p> </item> <tag><c>{spawn_executable, <anno>FileName</anno>}</c></tag> <item> - - <p>Works like <c>{spawn, <anno>FileName</anno>}</c>, but only runs - external executables. The <c><anno>FileName</anno></c> in its whole - is used as the name of the executable, including any - spaces. If arguments are to be passed, the - <c>args</c> and <c>arg0</c> <c><anno>PortSettings</anno></c> can be used.</p> - - <p>The shell is not usually invoked to start the - program, it's executed directly. Neither is the - <c>PATH</c> (or equivalent) searched. To find a program - in the PATH to execute, use <seealso - marker="kernel:os#find_executable/1">os:find_executable/1</seealso>.</p> - <p>Only if a shell script or <c>.bat</c> file is - executed, the appropriate command interpreter will - implicitly be invoked, but there will still be no - command argument expansion or implicit PATH search.</p> - - <p>If the <c><anno>FileName</anno></c> cannot be run, an error - exception, with the posix error code as the reason, is - raised. The error reason may differ between operating - systems. Typically the error <c>enoent</c> is raised - when one tries to run a program that is not found and - <c>eacces</c> is raised when the given file is not - executable.</p> + <p>Works like <c>{spawn, <anno>FileName</anno>}</c>, but only runs + external executables. <c><anno>FileName</anno></c> in its whole + is used as the name of the executable, including any spaces. + If arguments are to be passed, the + <c><anno>PortSettings</anno></c> + <c>args</c> and <c>arg0</c> can be used.</p> + <p>The shell is usually not invoked to start the + program, it is executed directly. <c>PATH</c> (or + equivalent) is not searched. To find a program + in <c>PATH</c> to execute, use + <seealso marker="kernel:os#find_executable/1"> + <c>os:find_executable/1</c></seealso>.</p> + <p>Only if a shell script or <c>.bat</c> file is + executed, the appropriate command interpreter is + invoked implicitly, but there is still no + command-argument expansion or implicit <c>PATH</c> search.</p> + <p>If <c><anno>FileName</anno></c> cannot be run, an error + exception is raised, with the POSIX error code as the reason. + The error reason can differ between OSs. + Typically the error <c>enoent</c> is raised when an + attempt is made to run a program that is not found and + <c>eacces</c> is raised when the specified file is not + executable.</p> </item> <tag><c>{fd, <anno>In</anno>, <anno>Out</anno>}</c></tag> <item> <p>Allows an Erlang process to access any currently opened file descriptors used by Erlang. The file descriptor - <c><anno>In</anno></c> can be used for standard input, and the file - descriptor <c><anno>Out</anno></c> for standard output. It is only - used for various servers in the Erlang operating system - (<c>shell</c> and <c>user</c>). Hence, its use is very - limited.</p> + <c><anno>In</anno></c> can be used for standard input, and the + file descriptor <c><anno>Out</anno></c> for standard output. + It is only used for various servers in the Erlang OS (<c>shell</c> + and <c>user</c>). Hence, its use is limited.</p> </item> </taglist> <p><c><anno>PortSettings</anno></c> is a list of settings for the port. - Valid settings are:</p> + The valid settings are as follows:</p> <taglist> <tag><c>{packet, <anno>N</anno>}</c></tag> <item> - <p>Messages are preceded by their length, sent in <c><anno>N</anno></c> - bytes, with the most significant byte first. Valid values - for <c>N</c> are 1, 2, or 4.</p> + <p>Messages are preceded by their length, sent in + <c><anno>N</anno></c> + bytes, with the most significant byte first. The valid values + for <c>N</c> are 1, 2, and 4.</p> </item> <tag><c>stream</c></tag> <item> @@ -2873,115 +3855,121 @@ os_prompt% </pre> <item> <p>Messages are delivered on a per line basis. Each line (delimited by the OS-dependent newline sequence) is - delivered in one single message. The message data format - is <c>{Flag, Line}</c>, where <c>Flag</c> is either - <c>eol</c> or <c>noeol</c> and <c>Line</c> is the actual + delivered in a single message. The message data format + is <c>{Flag, Line}</c>, where <c>Flag</c> is + <c>eol</c> or <c>noeol</c>, and <c>Line</c> is the data delivered (without the newline sequence).</p> <p><c><anno>L</anno></c> specifies the maximum line length in bytes. - Lines longer than this will be delivered in more than one - message, with the <c>Flag</c> set to <c>noeol</c> for all + Lines longer than this are delivered in more than one + message, with <c>Flag</c> set to <c>noeol</c> for all but the last message. If end of file is encountered anywhere else than immediately following a newline - sequence, the last line will also be delivered with - the <c>Flag</c> set to <c>noeol</c>. In all other cases, + sequence, the last line is also delivered with + <c>Flag</c> set to <c>noeol</c>. Otherwise lines are delivered with <c>Flag</c> set to <c>eol</c>.</p> - <p>The <c>{packet, <anno>N</anno>}</c> and <c>{line, <anno>L</anno>}</c> settings are - mutually exclusive.</p> + <p>The <c>{packet, <anno>N</anno>}</c> and <c>{line, + <anno>L</anno>}</c> settings are mutually exclusive.</p> </item> <tag><c>{cd, <anno>Dir</anno>}</c></tag> <item> - <p>This is only valid for <c>{spawn, <anno>Command</anno>}</c> and - <c>{spawn_executable, <anno>FileName</anno>}</c>. + <p>Only valid for <c>{spawn, <anno>Command</anno>}</c> and + <c>{spawn_executable, <anno>FileName</anno>}</c>. The external program starts using <c><anno>Dir</anno></c> as its - working directory. <c><anno>Dir</anno></c> must be a string. - </p> + working directory. <c><anno>Dir</anno></c> must be a string.</p> </item> <tag><c>{env, <anno>Env</anno>}</c></tag> <item> - <p>This is only valid for <c>{spawn, <anno>Command</anno>}</c> and - <c>{spawn_executable, <anno>FileName</anno>}</c>. + <p> + Types:<br/> + <c><anno>Name</anno> = </c><seealso marker="kernel:os#type-env_var_name"><c>os:env_var_name()</c></seealso><br/> + <c><anno>Val</anno> = </c><seealso marker="kernel:os#type-env_var_value"><c>os:env_var_value()</c></seealso><c> | false</c><br/> + <c>Env = [{<anno>Name</anno>, <anno>Val</anno>}]</c> + </p> + <p>Only valid for <c>{spawn, <anno>Command</anno>}</c>, and + <c>{spawn_executable, <anno>FileName</anno>}</c>. The environment of the started process is extended using the environment specifications in <c><anno>Env</anno></c>.</p> - <p><c><anno>Env</anno></c> should be a list of tuples <c>{<anno>Name</anno>, <anno>Val</anno>}</c>, - where <c><anno>Name</anno></c> is the name of an environment variable, - and <c><anno>Val</anno></c> is the value it is to have in the spawned - port process. Both <c><anno>Name</anno></c> and <c><anno>Val</anno></c> must be - strings. The one exception is <c><anno>Val</anno></c> being the atom - <c>false</c> (in analogy with <c>os:getenv/1</c>), which - removes the environment variable. + <p><c><anno>Env</anno></c> is to be a list of tuples + <c>{<anno>Name</anno>, <anno>Val</anno>}</c>, + where <c><anno>Name</anno></c> is the name of an + environment variable, and <c><anno>Val</anno></c> is the + value it is to have in the spawned + port process. Both <c><anno>Name</anno></c> and + <c><anno>Val</anno></c> must be strings. The one + exception is <c><anno>Val</anno></c> being the atom + <c>false</c> (in analogy with + <seealso marker="kernel:os#getenv/1"><c>os:getenv/1</c></seealso>, + which removes the environment variable. + </p> + <p> + For information about encoding requirements, see documentation + of the types for <c><anno>Name</anno></c> and + <c><anno>Val</anno></c>. </p> </item> - <tag><c>{args, [ string() | binary() ]}</c></tag> - <item> - - <p>This option is only valid for <c>{spawn_executable, <anno>FileName</anno>}</c> - and specifies arguments to the executable. Each argument - is given as a separate string and (on Unix) eventually - ends up as one element each in the argument vector. On - other platforms, similar behavior is mimicked.</p> - - <p>The arguments are not expanded by the shell prior to - being supplied to the executable, most notably this - means that file wildcard expansion will not happen. Use - <seealso - marker="stdlib:filelib#wildcard/1">filelib:wildcard/1</seealso> - to expand wildcards for the arguments. Note that even if - the program is a Unix shell script, meaning that the - shell will ultimately be invoked, wildcard expansion - will not happen and the script will be provided with the - untouched arguments. On Windows®, wildcard expansion - is always up to the program itself, why this isn't an - issue.</p> - - <p>Note also that the actual executable name (a.k.a. <c>argv[0]</c>) - should not be given in this list. The proper executable name will - automatically be used as argv[0] where applicable.</p> - - <p>If one, for any reason, wants to explicitly set the - program name in the argument vector, the <c>arg0</c> - option can be used.</p> - - </item> - <tag><c>{arg0, string() | binary()}</c></tag> - <item> - - <p>This option is only valid for <c>{spawn_executable, <anno>FileName</anno>}</c> - and explicitly specifies the program name argument when - running an executable. This might in some circumstances, - on some operating systems, be desirable. How the program - responds to this is highly system dependent and no specific - effect is guaranteed.</p> - - </item> - + <tag><c>{args, [ string() | binary() ]}</c></tag> + <item> + <p>Only valid for <c>{spawn_executable, <anno>FileName</anno>}</c> + and specifies arguments to the executable. Each argument + is specified as a separate string and (on Unix) eventually + ends up as one element each in the argument vector. On + other platforms, a similar behavior is mimicked.</p> + <p>The arguments are not expanded by the shell before + they are supplied to the executable. Most notably this + means that file wildcard expansion does not occur. + To expand wildcards for the arguments, use + <seealso marker="stdlib:filelib#wildcard/1"> + <c>filelib:wildcard/1</c></seealso>. + Notice that even if + the program is a Unix shell script, meaning that the + shell ultimately is invoked, wildcard expansion + does not occur, and the script is provided with the + untouched arguments. On Windows, wildcard expansion + is always up to the program itself, therefore this is + not an issue.</p> + <p>The executable name (also known as <c>argv[0]</c>) + is not to be specified in this list. The proper executable name + is automatically used as <c>argv[0]</c>, where applicable.</p> + <p>If you explicitly want to set the + program name in the argument vector, option <c>arg0</c> + can be used.</p> + </item> + <tag><c>{arg0, string() | binary()}</c></tag> + <item> + <p>Only valid for <c>{spawn_executable, <anno>FileName</anno>}</c> + and explicitly specifies the program name argument when + running an executable. This can in some circumstances, + on some OSs, be desirable. How the program + responds to this is highly system-dependent and no specific + effect is guaranteed.</p> + </item> <tag><c>exit_status</c></tag> <item> - <p>This is only valid for <c>{spawn, <anno>Command</anno>}</c> where - <c><anno>Command</anno></c> refers to an external program, and for - <c>{spawn_executable, <anno>FileName</anno>}</c>.</p> + <p>Only valid for <c>{spawn, <anno>Command</anno>}</c>, where + <c><anno>Command</anno></c> refers to an external program, and + for <c>{spawn_executable, <anno>FileName</anno>}</c>.</p> <p>When the external process connected to the port exits, a message of the form <c>{Port,{exit_status,Status}}</c> is sent to the connected process, where <c>Status</c> is the exit status of the external process. If the program - aborts, on Unix the same convention is used as the shells - do (i.e., 128+signal).</p> - <p>If the <c>eof</c> option has been given as well, - the <c>eof</c> message and the <c>exit_status</c> message - appear in an unspecified order.</p> - <p>If the port program closes its stdout without exiting, - the <c>exit_status</c> option will not work.</p> + aborts on Unix, the same convention is used as the shells + do (that is, 128+signal).</p> + <p>If option <c>eof</c> is specified also, the messages <c>eof</c> + and <c>exit_status</c> appear in an unspecified order.</p> + <p>If the port program closes its <c>stdout</c> without exiting, + option <c>exit_status</c> does not work.</p> </item> <tag><c>use_stdio</c></tag> <item> - <p>This is only valid for <c>{spawn, <anno>Command</anno>}</c> and - <c>{spawn_executable, <anno>FileName</anno>}</c>. It + <p>Only valid for <c>{spawn, <anno>Command</anno>}</c> and + <c>{spawn_executable, <anno>FileName</anno>}</c>. It allows the standard input and output (file descriptors 0 - and 1) of the spawned (UNIX) process for communication + and 1) of the spawned (Unix) process for communication with Erlang.</p> </item> <tag><c>nouse_stdio</c></tag> <item> - <p>The opposite of <c>use_stdio</c>. Uses file descriptors + <p>The opposite of <c>use_stdio</c>. It uses file descriptors 3 and 4 for communication with Erlang.</p> </item> <tag><c>stderr_to_stdout</c></tag> @@ -2993,14 +3981,15 @@ os_prompt% </pre> </item> <tag><c>overlapped_io</c></tag> <item> - <p>Affects ports to external programs on Windows® only. - The standard input and standard output handles of the port program - will, if this option is supplied, be opened with the flag - FILE_FLAG_OVERLAPPED, so that the port program can (and has to) do - overlapped I/O on its standard handles. This is not normally - the case for simple port programs, but an option of value for the - experienced Windows programmer. <em>On all other platforms, this - option is silently discarded</em>.</p> + <p>Affects ports to external programs on Windows only. The + standard input and standard output handles of the port program + are, if this option is supplied, opened with flag + <c>FILE_FLAG_OVERLAPPED</c>, so that the port program can + (and must) do + overlapped I/O on its standard handles. This is not normally + the case for simple port programs, but an option of value for the + experienced Windows programmer. <em>On all other platforms, this + option is silently discarded.</em></p> </item> <tag><c>in</c></tag> <item> @@ -3012,294 +4001,336 @@ os_prompt% </pre> </item> <tag><c>binary</c></tag> <item> - <p>All IO from the port are binary data objects as opposed + <p>All I/O from the port is binary data objects as opposed to lists of bytes.</p> </item> <tag><c>eof</c></tag> <item> - <p>The port will not be closed at the end of the file and - produce an exit signal. Instead, it will remain open and - a <c>{Port, eof}</c> message will be sent to the process + <p>The port is not closed at the end of the file and does not + produce an exit signal. Instead, it remains open and + a <c>{Port, eof}</c> message is sent to the process holding the port.</p> </item> <tag><c>hide</c></tag> <item> - <p>When running on Windows, suppress creation of a new - console window when spawning the port program. - (This option has no effect on other platforms.)</p> + <p>When running on Windows, suppresses creation of a new + console window when spawning the port program. + (This option has no effect on other platforms.)</p> </item> - <tag><marker id="open_port_parallelism"><c>{parallelism, Boolean}</c></marker></tag> + <tag><c>{parallelism, Boolean}</c></tag> <item> - <p>Set scheduler hint for port parallelism. If set to <c>true</c>, - the VM will schedule port tasks when doing so will improve - parallelism in the system. If set to <c>false</c>, the VM will - try to perform port tasks immediately, improving latency at the - expense of parallelism. The default can be set on system startup - by passing the - <seealso marker="erl#+spp">+spp</seealso> command line argument - to <seealso marker="erl">erl(1)</seealso>. - </p> + <marker id="open_port_parallelism"></marker> + <p>Sets scheduler hint for port parallelism. If set to + <c>true</c>, the virtual machine schedules port tasks; + when doing so, it improves parallelism in the system. If set + to <c>false</c>, the virtual machine tries to + perform port tasks immediately, improving latency at the + expense of parallelism. The default can be set at system startup + by passing command-line argument + <seealso marker="erl#+spp"><c>+spp</c></seealso> to + <c>erl(1)</c>.</p> </item> </taglist> - <p>The default is <c>stream</c> for all types of port and + <p>Default is <c>stream</c> for all port types and <c>use_stdio</c> for spawned ports.</p> - <p>Failure: If the port cannot be opened, the exit reason is - <c>badarg</c>, <c>system_limit</c>, or the Posix error code which - most closely describes the error, or <c>einval</c> if no Posix code - is appropriate:</p> + <p>Failure: if the port cannot be opened, the exit reason is + <c>badarg</c>, <c>system_limit</c>, or the POSIX error code that + most closely describes the error, or <c>einval</c> if no POSIX + code is appropriate:</p> <taglist> <tag><c>badarg</c></tag> - <item> - <p>Bad input arguments to <c>open_port</c>.</p> + <item>Bad input arguments to <c>open_port</c>. </item> <tag><c>system_limit</c></tag> - <item> - <p>All available ports in the Erlang emulator are in use.</p> + <item>All available ports in the Erlang emulator are in use. </item> <tag><c>enomem</c></tag> - <item> - <p>There was not enough memory to create the port.</p> + <item>Not enough memory to create the port. </item> <tag><c>eagain</c></tag> - <item> - <p>There are no more available operating system processes.</p> + <item>No more available OS processes. </item> <tag><c>enametoolong</c></tag> - <item> - <p>The external command given was too long.</p> + <item>Too long external command. </item> <tag><c>emfile</c></tag> - <item> - <p>There are no more available file descriptors (for the operating system process - that the Erlang emulator runs in).</p> + <item>No more available file descriptors (for the + OS process that the Erlang emulator runs in). </item> <tag><c>enfile</c></tag> - <item> - <p>The file table is full (for the entire operating system).</p> + <item>Full file table (for the entire OS). </item> <tag><c>eacces</c></tag> - <item> - <p>The <c>Command</c> given in <c>{spawn_executable, Command}</c> does not point out an executable file.</p> + <item><c>Command</c> specified in <c>{spawn_executable, Command}</c> + does not point out an executable file. </item> <tag><c>enoent</c></tag> - <item> - <p>The <c><anno>FileName</anno></c> given in <c>{spawn_executable, <anno>FileName</anno>}</c> does not point out an existing file.</p> + <item><c><anno>FileName</anno></c> specified in + <c>{spawn_executable, <anno>FileName</anno>}</c> + does not point out an existing file. </item> </taglist> <p>During use of a port opened using <c>{spawn, Name}</c>, - <c>{spawn_driver, Name}</c> or <c>{spawn_executable, Name}</c>, + <c>{spawn_driver, Name}</c>, or <c>{spawn_executable, Name}</c>, errors arising when sending messages to it are reported to the owning process using signals of the form - <c>{'EXIT', Port, PosixCode}</c>. See <c>file(3)</c> for - possible values of <c>PosixCode</c>.</p> - <p>The maximum number of ports that can be open at the same - time can be configured by passing the - <seealso marker="erl#max_ports"><c>+Q</c></seealso> - command line flag to - <seealso marker="erl"><c>erl(1)</c></seealso>.</p> + <c>{'EXIT', Port, PosixCode}</c>. For the possible values of + <c>PosixCode</c>, see + <seealso marker="kernel:file"><c>file(3)</c></seealso>.</p> + <p>The maximum number of ports that can be open at the same + time can be configured by passing command-line flag + <seealso marker="erl#max_ports"><c>+Q</c></seealso> to + <c>erl(1)</c>.</p> </desc> </func> + <func> <name name="phash" arity="2"/> + <fsummary>Portable hash function.</fsummary> <type_desc variable="Range">Range = 1..2^32, Hash = 1..Range</type_desc> - <fsummary>Portable hash function</fsummary> <desc> - <p>Portable hash function that will give the same hash for + <p>Portable hash function that gives the same hash for the same Erlang term regardless of machine architecture and - ERTS version (the BIF was introduced in ERTS 4.9.1.1). Range - can be between 1 and 2^32, the function returns a hash value - for <c><anno>Term</anno></c> within the range <c>1..<anno>Range</anno></c>.</p> - <p>This BIF could be used instead of the old deprecated - <c>erlang:hash/2</c> BIF, as it calculates better hashes for - all data-types, but consider using <c>phash2/1,2</c> instead.</p> + ERTS version (the BIF was introduced in ERTS 4.9.1.1). + The function returns a hash value for + <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> </desc> </func> + <func> <name name="phash2" arity="1"/> <name name="phash2" arity="2"/> + <fsummary>Portable hash function.</fsummary> <type_desc variable="Range">1..2^32</type_desc> <type_desc variable="Hash">0..Range-1</type_desc> - <fsummary>Portable hash function</fsummary> <desc> - <p>Portable hash function that will give the same hash for + <p>Portable hash function that gives the same hash for the same Erlang term regardless of machine architecture and - ERTS version (the BIF was introduced in ERTS 5.2). Range can - be between 1 and 2^32, the function returns a hash value for - <c><anno>Term</anno></c> within the range <c>0..<anno>Range</anno>-1</c>. When called - without the <c><anno>Range</anno></c> argument, a value in the range - <c>0..2^27-1</c> is returned.</p> - <p>This BIF should always be used for hashing terms. It + ERTS version (the BIF was introduced in ERTS 5.2). + The function returns a hash value for + <c><anno>Term</anno></c> within the range + <c>0..<anno>Range</anno>-1</c>. The maximum value for + <c><anno>Range</anno></c> is 2^32. When without argument + <c><anno>Range</anno></c>, a value in the range + 0..2^27-1 is returned.</p> + <p>This BIF is always to be used for hashing terms. It distributes small integers better than <c>phash/2</c>, and it is faster for bignums and binaries.</p> - <p>Note that the range <c>0..<anno>Range</anno>-1</c> is different from - the range of <c>phash/2</c> (<c>1..<anno>Range</anno></c>).</p> + <p>Notice that the range <c>0..<anno>Range</anno>-1</c> is + different from the range of <c>phash/2</c>, which is + <c>1..<anno>Range</anno></c>.</p> </desc> </func> + <func> <name name="pid_to_list" arity="1"/> - <fsummary>Text representation of a pid</fsummary> + <fsummary>Text representation of a pid.</fsummary> <desc> - <p>Returns a string which corresponds to the text + <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 for use in - the Erlang operating system. It should not be used in - application programs.</p> - </warning> </desc> </func> + + <func> + <name name="port_call" arity="3"/> + <fsummary>Perform a synchronous call to a port with term data.</fsummary> + <desc> + <p>Performs a synchronous call to a port. The meaning of + <c><anno>Operation</anno></c> and <c><anno>Data</anno></c> + depends on the port, that is, + on the port driver. Not all port drivers support this feature.</p> + <p><c><anno>Port</anno></c> is a port identifier, + referring to a driver.</p> + <p><c><anno>Operation</anno></c> is an integer, which is passed on to + the driver.</p> + <p><c><anno>Data</anno></c> is any Erlang term. This data is converted + to binary term format and sent to the port.</p> + <p>Returns a term from the driver. The meaning of the returned + data also depends on the port driver.</p> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item> + If <c><anno>Port</anno></c> is not an identifier of an open port, + or the registered name of an open port. If the calling + process was previously linked to the closed port, + identified by <c><anno>Port</anno></c>, the exit signal + from the port is guaranteed to be delivered before this + <c>badarg</c> exception occurs. + </item> + <tag><c>badarg</c></tag> + <item> + If <c><anno>Operation</anno></c> does not fit in a 32-bit integer. + </item> + <tag><c>badarg</c></tag> + <item> + If the port driver does not support synchronous control operations. + </item> + <tag><c>badarg</c></tag> + <item> + If the port driver so decides for any reason (probably + something wrong with <c><anno>Operation</anno></c> + or <c><anno>Data</anno></c>). + </item> + </taglist> + </desc> + </func> + <func> <name name="port_close" arity="1"/> - <fsummary>Close an open port</fsummary> + <fsummary>Close an open port.</fsummary> <desc> - <p>Closes an open port. Roughly the same as - <c><anno>Port</anno> ! {self(), close}</c> except for the error behaviour + <p>Closes an open port. Roughly the same as <c><anno>Port</anno> ! + {self(), close}</c> except for the error behavior (see below), being synchronous, and that the port does - <em>not</em> reply with <c>{Port, closed}</c>. Any process may - close a port with <c>port_close/1</c>, not only the port owner - (the connected process). If the calling process is linked to - port identified by <c><anno>Port</anno></c>, an exit signal due - to that link will be received by the process prior to the return - from <c>port_close/1</c>.</p> - <p>For comparison: <c><anno>Port</anno> ! {self(), close}</c> fails with - <c>badarg</c> if <c><anno>Port</anno></c> cannot be sent to (i.e., - <c><anno>Port</anno></c> refers neither to a port nor to a process). If - <c><anno>Port</anno></c> is a closed port nothing happens. If <c><anno>Port</anno></c> + <em>not</em> reply with <c>{Port, closed}</c>. Any process can + close a port with <c>port_close/1</c>, not only the port owner + (the connected process). If the calling process is linked to + the port identified by <c><anno>Port</anno></c>, the exit + signal from the port is guaranteed to be delivered before + <c>port_close/1</c> returns.</p> + <p>For comparison: <c><anno>Port</anno> ! {self(), close}</c> + only fails with <c>badarg</c> if <c><anno>Port</anno></c> does + not refer to a port or a process. If <c><anno>Port</anno></c> + is a closed port, nothing happens. If <c><anno>Port</anno></c> is an open port and the calling process is the port owner, the port replies with <c>{Port, closed}</c> when all buffers - have been flushed and the port really closes, but if - the calling process is not the port owner the <em>port owner</em> fails with <c>badsig</c>.</p> - - <p>Note that any process can close a port using - <c><anno>Port</anno> ! {PortOwner, close}</c> just as if it itself was + have been flushed and the port really closes. If the calling + process is not the port owner, the <em>port owner</em> fails + with <c>badsig</c>.</p> + <p>Notice that any process can close a port using + <c><anno>Port</anno> ! {PortOwner, close}</c> as if it itself was the port owner, but the reply always goes to the port owner.</p> - <p>As of OTP-R16 <c><anno>Port</anno> ! {PortOwner, close}</c> is truly - asynchronous. Note that this operation has always been - documented as an asynchronous operation, while the underlying - implementation has been synchronous. <c>port_close/1</c> is - however still fully synchronous. This due to its error - behavior.</p> - <p>Failure:</p> - <taglist> - <tag><c>badarg</c></tag> - <item> - If <c><anno>Port</anno></c> is not an identifier of an open - port, or the registered name of an open port. If the calling - process was linked to the previously open port identified by - <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to this exception. - </item> - </taglist> + <p>As from Erlang/OTP R16, + <c><anno>Port</anno> ! {PortOwner, close}</c> is truly + asynchronous. Notice that this operation has always been + documented as an asynchronous operation, while the underlying + implementation has been synchronous. <c>port_close/1</c> is + however still fully synchronous because of its error behavior.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not an + identifier of an open port, or the registered name of an open port. + If the calling process was previously linked to the closed + port, identified by <c><anno>Port</anno></c>, the exit + signal from the port is guaranteed to be delivered before + this <c>badarg</c> exception occurs.</p> </desc> </func> + <func> <name name="port_command" arity="2"/> - <fsummary>Send data to a port</fsummary> + <fsummary>Send data to a port.</fsummary> <desc> <p>Sends data to a port. Same as - <c><anno>Port</anno> ! {PortOwner, {command, Data}}</c> except for the error - behaviour and being synchronous (see below). Any process may - send data to a port with <c>port_command/2</c>, not only the - port owner (the connected process).</p> - <p>For comparison: <c><anno>Port</anno> ! {PortOwner, {command, Data}}</c> - fails with <c>badarg</c> if <c><anno>Port</anno></c> cannot be sent to - (i.e., <c><anno>Port</anno></c> refers neither to a port nor to a process). - If <c><anno>Port</anno></c> is a closed port the data message disappears + <c><anno>Port</anno> ! {PortOwner, {command, Data}}</c> except for + the error behavior and being synchronous (see below). Any process + can send data to a port with <c>port_command/2</c>, not only the + port owner (the connected process).</p> + <p>For comparison: <c><anno>Port</anno> ! {PortOwner, {command, + Data}}</c> only fails with <c>badarg</c> if <c><anno>Port</anno></c> + does not refer to a port or a process. If <c><anno>Port</anno></c> is + a closed port, the data message disappears without a sound. If <c><anno>Port</anno></c> is open and the calling process is not the port owner, the <em>port owner</em> fails with <c>badsig</c>. The port owner fails with <c>badsig</c> - also if <c><anno>Data</anno></c> is not a valid IO list.</p> - <p>Note that any process can send to a port using - <c><anno>Port</anno> ! {PortOwner, {command, <anno>Data</anno>}}</c> just as if it - itself was the port owner.</p> - <p>If the port is busy, the calling process will be suspended - until the port is not busy anymore.</p> - <p>As of OTP-R16 <c><anno>Port</anno> ! {PortOwner, {command, Data}}</c> is - truly asynchronous. Note that this operation has always been - documented as an asynchronous operation, while the underlying - implementation has been synchronous. <c>port_command/2</c> is - however still fully synchronous. This due to its error - behavior.</p> + also if <c><anno>Data</anno></c> is an invalid I/O list.</p> + <p>Notice that any process can send to a port using + <c><anno>Port</anno> ! {PortOwner, {command, <anno>Data</anno>}}</c> + as if it itself was the port owner.</p> + <p>If the port is busy, the calling process is suspended + until the port is not busy any more.</p> + <p>As from Erlang/OTP R16, + <c><anno>Port</anno> ! {PortOwner, {command, Data}}</c> + is truly asynchronous. Notice that this operation has always been + documented as an asynchronous operation, while the underlying + implementation has been synchronous. <c>port_command/2</c> is + however still fully synchronous because of its error behavior.</p> <p>Failures:</p> <taglist> <tag><c>badarg</c></tag> <item> - If <c><anno>Port</anno></c> is not an identifier of an open - port, or the registered name of an open port. If the calling - process was linked to the previously open port identified by - <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to this exception. - </item> + <p>If <c><anno>Port</anno></c> is not an identifier of an open + port, or the registered name of an open port. If the + calling process was previously linked to the closed port, + identified by <c><anno>Port</anno></c>, the exit signal + from the port is guaranteed to be delivered before this + <c>badarg</c> exception occurs.</p> + </item> <tag><c>badarg</c></tag> <item> - If <c><anno>Data</anno></c> is not a valid io list. - </item> - </taglist> + <p>If <c><anno>Data</anno></c> is an invalid I/O list.</p> + </item> + </taglist> </desc> </func> + <func> <name name="port_command" arity="3"/> - <fsummary>Send data to a port</fsummary> + <fsummary>Send data to a port.</fsummary> <desc> <p>Sends data to a port. <c>port_command(Port, Data, [])</c> - equals <c>port_command(Port, Data)</c>.</p> - <p>If the port command is aborted <c>false</c> is returned; - otherwise, <c>true</c> is returned.</p> - <p>If the port is busy, the calling process will be suspended - until the port is not busy anymore.</p> - <p>Currently the following <c><anno>Option</anno></c>s are valid:</p> + equals <c>port_command(Port, Data)</c>.</p> + <p>If the port command is aborted, <c>false</c> is returned, + otherwise <c>true</c>.</p> + <p>If the port is busy, the calling process is suspended + until the port is not busy anymore.</p> + <p><c><anno>Option</anno></c>s:</p> <taglist> <tag><c>force</c></tag> - <item>The calling process will not be suspended if the port is - busy; instead, the port command is forced through. The - call will fail with a <c>notsup</c> exception if the - driver of the port does not support this. For more - information see the - <seealso marker="driver_entry#driver_flags"><![CDATA[ERL_DRV_FLAG_SOFT_BUSY]]></seealso> - driver flag. + <item>The calling process is not suspended if the port is + busy, instead the port command is forced through. The + call fails with a <c>notsup</c> exception if the + driver of the port does not support this. For more + information, see driver flag + <seealso marker="driver_entry#driver_flags"> + <c>![CDATA[ERL_DRV_FLAG_SOFT_BUSY]]</c></seealso>. </item> <tag><c>nosuspend</c></tag> - <item>The calling process will not be suspended if the port is - busy; instead, the port command is aborted and - <c>false</c> is returned. + <item>The calling process is not suspended if the port is + busy, instead the port command is aborted and + <c>false</c> is returned. </item> </taglist> <note> - <p>More options may be added in the future.</p> + <p>More options can be added in a future release.</p> </note> <p>Failures:</p> <taglist> <tag><c>badarg</c></tag> <item> - If <c><anno>Port</anno></c> is not an identifier of an open - port, or the registered name of an open port. If the calling - process was linked to the previously open port identified by - <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to this exception. - </item> + If <c><anno>Port</anno></c> is not an identifier of an open + port, or the registered name of an open port. If the + calling process was previously linked to the closed port, + identified by <c><anno>Port</anno></c>, the exit signal + from the port is guaranteed to be delivered before this + <c>badarg</c> exception occurs. + </item> <tag><c>badarg</c></tag> <item> - If <c><anno>Data</anno></c> is not a valid io list. - </item> + If <c><anno>Data</anno></c> is an invalid I/O list. + </item> <tag><c>badarg</c></tag> <item> - If <c><anno>OptionList</anno></c> is not a valid option list. - </item> + If <c><anno>OptionList</anno></c> is an invalid option list. + </item> <tag><c>notsup</c></tag> <item> - If the <c>force</c> option has been passed, but the - driver of the port does not allow forcing through - a busy port. - </item> - </taglist> + If option <c>force</c> has been passed, but the + driver of the port does not allow forcing through + a busy port. + </item> + </taglist> </desc> </func> + <func> <name name="port_connect" arity="2"/> - <fsummary>Set the owner of a port</fsummary> + <fsummary>Set the owner of a port.</fsummary> <desc> <p>Sets the port owner (the connected port) to <c><anno>Pid</anno></c>. - Roughly the same as <c><anno>Port</anno> ! {Owner, {connect, <anno>Pid</anno>}}</c> + Roughly the same as + <c><anno>Port</anno> ! {Owner, {connect, <anno>Pid</anno>}}</c> except for the following:</p> <list type="bulleted"> <item> @@ -3316,702 +4347,869 @@ os_prompt% </pre> <p>The new port owner gets linked to the port.</p> </item> </list> - <p>The old port owner stays linked to the port and have to call - <c>unlink(Port)</c> if this is not desired. Any process may + <p>The old port owner stays linked to the port and must call + <c>unlink(Port)</c> if this is not desired. Any process can set the port owner to be any process with <c>port_connect/2</c>.</p> - <p>For comparison: <c><anno>Port</anno> ! {self(), {connect, <anno>Pid</anno>}}</c> fails - with <c>badarg</c> if <c><anno>Port</anno></c> cannot be sent to (i.e., - <c><anno>Port</anno></c> refers neither to a port nor to a process). If - <c><anno>Port</anno></c> is a closed port nothing happens. If <c><anno>Port</anno></c> + <p>For comparison: + <c><anno>Port</anno> ! {self(), {connect, <anno>Pid</anno>}}</c> + only fails with <c>badarg</c> if <c><anno>Port</anno></c> + does not refer to a port or a process. If + <c><anno>Port</anno></c> is a closed port, nothing happens. + If <c><anno>Port</anno></c> is an open port and the calling process is the port owner, the port replies with <c>{Port, connected}</c> to the old - port owner. Note that the old port owner is still linked to - the port, and that the new is not. If <c><anno>Port</anno></c> is an open + port owner. Notice that the old port owner is still linked to + the port, while the new is not. If <c><anno>Port</anno></c> is an open port and the calling process is not the port owner, the <em>port owner</em> fails with <c>badsig</c>. The port - owner fails with <c>badsig</c> also if <c><anno>Pid</anno></c> is not an - existing local pid.</p> - <p>Note that any process can set the port owner using - <c><anno>Port</anno> ! {PortOwner, {connect, <anno>Pid</anno>}}</c> just as if it - itself was the port owner, but the reply always goes to + owner fails with <c>badsig</c> also if <c><anno>Pid</anno></c> is not + an existing local process identifier.</p> + <p>Notice that any process can set the port owner using + <c><anno>Port</anno> ! {PortOwner, {connect, <anno>Pid</anno>}}</c> + as if it itself was the port owner, but the reply always goes to the port owner.</p> - <p>As of OTP-R16 <c><anno>Port</anno> ! {PortOwner, {connect, <anno>Pid</anno>}}</c> is - truly asynchronous. Note that this operation has always been - documented as an asynchronous operation, while the underlying - implementation has been synchronous. <c>port_connect/2</c> is - however still fully synchronous. This due to its error - behavior.</p> + <p>As from Erlang/OTP R16, + <c><anno>Port</anno> ! {PortOwner, {connect, <anno>Pid</anno>}}</c> + is truly asynchronous. Notice that this operation has always been + documented as an asynchronous operation, while the underlying + implementation has been synchronous. <c>port_connect/2</c> is + however still fully synchronous because of its error behavior.</p> <p>Failures:</p> <taglist> <tag><c>badarg</c></tag> <item> - If <c><anno>Port</anno></c> is not an identifier of an open - port, or the registered name of an open port. If the calling - process was linked to the previously open port identified by - <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to this exception. - </item> + If <c><anno>Port</anno></c> is not an identifier of an open port, + or the registered name of an open port. If the calling + process was previously linked to the closed port, + identified by <c><anno>Port</anno></c>, the exit signal + from the port is guaranteed to be delivered before this + <c>badarg</c> exception occurs. + </item> <tag><c>badarg</c></tag> - <item>If process identified by <c>Pid</c> is not an existing - local process.</item> - </taglist> + <item>If the process identified by <c>Pid</c> is not an existing + local process.</item> + </taglist> </desc> </func> + <func> <name name="port_control" arity="3"/> - <fsummary>Perform a synchronous control operation on a port</fsummary> + <fsummary>Perform a synchronous control operation on a port.</fsummary> <desc> <p>Performs a synchronous control operation on a port. - The meaning of <c><anno>Operation</anno></c> and <c><anno>Data</anno></c> depends on - the port, i.e., on the port driver. Not all port drivers + The meaning of <c><anno>Operation</anno></c> and + <c><anno>Data</anno></c> depends on + the port, that is, on the port driver. Not all port drivers support this control feature.</p> - <p>Returns: a list of integers in the range 0 through 255, or a + <p>Returns a list of integers in the range 0..255, or a binary, depending on the port driver. The meaning of the returned data also depends on the port driver.</p> - <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not an open port or - the registered name of an open port, if <c><anno>Operation</anno></c> - cannot fit in a 32-bit integer, if the port driver does not - support synchronous control operations, or if the port driver - so decides for any reason (probably something wrong with - <c><anno>Operation</anno></c> or <c><anno>Data</anno></c>).</p> - </desc> - </func> - <func> - <name name="port_call" arity="3"/> - <fsummary>Synchronous call to a port with term data</fsummary> - <desc> - <p>Performs a synchronous call to a port. The meaning of - <c><anno>Operation</anno></c> and <c><anno>Data</anno></c> depends on the port, i.e., - on the port driver. Not all port drivers support this feature.</p> - <p><c><anno>Port</anno></c> is a port identifier, referring to a driver.</p> - <p><c><anno>Operation</anno></c> is an integer, which is passed on to - the driver.</p> - <p><c><anno>Data</anno></c> is any Erlang term. This data is converted to - binary term format and sent to the port.</p> - <p>Returns: a term from the driver. The meaning of the returned - data also depends on the port driver.</p> <p>Failures:</p> <taglist> <tag><c>badarg</c></tag> <item> - If <c><anno>Port</anno></c> is not an identifier of an open - port, or the registered name of an open port. If the calling - process was linked to the previously open port identified by - <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to this exception. - </item> + If <c><anno>Port</anno></c> is not an open port or the registered + name of an open port. + </item> <tag><c>badarg</c></tag> - <item> - If <c><anno>Operation</anno></c> does not fit in a - 32-bit integer. - </item> + <item> + If <c><anno>Operation</anno></c> cannot fit in a 32-bit integer. + </item> <tag><c>badarg</c></tag> - <item> - If the port driver does not support synchronous control - operations. - </item> + <item> + If the port driver does not support synchronous control operations. + </item> <tag><c>badarg</c></tag> - <item> - If the port driver so decides for any reason (probably - something wrong with <c><anno>Operation</anno></c>, or - <c><anno>Data</anno></c>). - </item> - </taglist> + <item> + If the port driver so decides for any reason (probably + something wrong with <c><anno>Operation</anno></c> or + <c><anno>Data</anno></c>). + </item> + </taglist> </desc> </func> + <func> <name name="port_info" arity="1"/> - <fsummary>Information about a port</fsummary> + <fsummary>Information about a port.</fsummary> <desc> <p>Returns a list containing tuples with information about - the <c><anno>Port</anno></c>, or <c>undefined</c> if the port is not open. - The order of the tuples is not defined, nor are all the - tuples mandatory. - If <c>undefined</c> is returned and the calling process - was linked to a previously open port identified by - <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/1</c>.</p> - <p>Currently the result will containt information about the - following <c>Item</c>s: <c>registered_name</c> (if the port has - a registered name), <c>id</c>, <c>connected</c>, <c>links</c>, - <c>name</c>, <c>input</c>, and <c>output</c>. For more information - about the different <c>Item</c>s, see - <seealso marker="#port_info/2">port_info/2</seealso>.</p> + <c><anno>Port</anno></c>, or <c>undefined</c> if the port is not open. + The order of the tuples is undefined, and all the + tuples are not mandatory. + If the port is closed and the calling process + was previously linked to the port, the exit signal from the + port is guaranteed to be delivered before <c>port_info/1</c> + returns <c>undefined</c>.</p> + <p>The result contains information about the following + <c>Item</c>s:</p> + <list type="bulleted"> + <item><c>registered_name</c> (if the port has a registered + name)</item> + <item><c>id</c></item> + <item><c>connected</c></item> + <item><c>links</c></item> + <item><c>name</c></item> + <item><c>input</c></item> + <item><c>output</c></item> + </list> + <p>For more information about the different <c>Item</c>s, see + <seealso marker="#port_info/2"><c>port_info/2</c></seealso>.</p> <p>Failure: <c>badarg</c> if <c>Port</c> is not a local port - identifier, or an atom.</p> + identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="1"/> - <fsummary>Information about the connected process of a port</fsummary> - <desc> - <p><c><anno>Pid</anno></c> is the process identifier of the process - connected to the port.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Information about the connected process of a port.</fsummary> + <desc> + <p><c><anno>Pid</anno></c> is the process identifier of the process + connected to the port.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="2"/> - <fsummary>Information about the internal index of a port</fsummary> - <desc> - <p><c><anno>Index</anno></c> is the internal index of the port. This - index may be used to separate ports.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Information about the internal index of a port.</fsummary> + <desc> + <p><c><anno>Index</anno></c> is the internal index of the port. This + index can be used to separate ports.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="3"/> - <fsummary>Information about the input of a port</fsummary> - <desc> - <p><c><anno>Bytes</anno></c> is the total number of bytes - read from the port.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Information about the input of a port.</fsummary> + <desc> + <p><c><anno>Bytes</anno></c> is the total number of bytes + read from the port.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="4"/> - <fsummary>Information about the links of a port</fsummary> - <desc> - <p><c><anno>Pids</anno></c> is a list of the process identifiers - of the processes that the port is linked to.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Information about the links of a port.</fsummary> + <desc> + <p><c><anno>Pids</anno></c> is a list of the process identifiers + of the processes that the port is linked to.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="5"/> - <fsummary>Information about the locking of a port</fsummary> - <desc> - <p><c><anno>Locking</anno></c> is currently either <c>false</c> - (emulator without SMP support), <c>port_level</c> (port specific - locking), or <c>driver_level</c> (driver specific locking). Note - that these results are highly implementation specific and might - change in the future.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Information about the locking of a port.</fsummary> + <desc> + <p><c><anno>Locking</anno></c> is one of the following:</p> + <list type="bulleted"> + <item><c>port_level</c> (port-specific locking)</item> + <item><c>driver_level</c> (driver-specific locking)</item> + </list> + <p>Notice that these results are highly implementation-specific + and can change in a future release.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="6"/> - <fsummary>Information about the memory size of a port</fsummary> - <desc> - <p><c><anno>Bytes</anno></c> is the total amount of memory, - in bytes, allocated for this port by the runtime system. Note - that the port itself might have allocated memory which is not - included in <c><anno>Bytes</anno></c>.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Information about the memory size of a port.</fsummary> + <desc> + <p><c><anno>Bytes</anno></c> is the total number of + bytes allocated for this port by the runtime system. The + port itself can have allocated memory that is not + included in <c><anno>Bytes</anno></c>.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="7"/> - <fsummary>Information about the monitors of a port</fsummary> - <desc> - <p><c><anno>Monitors</anno></c> represent processes that this port - is monitoring.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Information about the monitors of a port.</fsummary> + <desc> + <p><c><anno>Monitors</anno></c> represent processes monitored by + this port.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="8"/> - <fsummary>Information about the name of a port</fsummary> - <desc> - <p><c><anno>Name</anno></c> is the command name set by - <seealso marker="#open_port/2">open_port/2</seealso>.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Which processes are monitoring this port.</fsummary> + <desc> + <p>Returns list of pids that are monitoring given port at the + moment.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="9"/> - <fsummary>Information about the OS pid of a port</fsummary> - <desc> - <p><c><anno>OsPid</anno></c> is the process identifier (or equivalent) - of an OS process created with - <seealso marker="#open_port/2">open_port({spawn | spawn_executable, - Command}, Options)</seealso>. If the port is not the result of spawning - an OS process, the value is <c>undefined</c>.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Information about the name of a port.</fsummary> + <desc> + <p><c><anno>Name</anno></c> is the command name set by + <seealso marker="#open_port/2"><c>open_port/2</c></seealso>.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="10"/> - <fsummary>Information about the output of a port</fsummary> - <desc> - <p><c><anno>Bytes</anno></c> is the total number of bytes written - to the port from Erlang processes using either - <seealso marker="#port_command/2">port_command/2</seealso>, - <seealso marker="#port_command/3">port_command/3</seealso>, - or <c><anno>Port</anno> ! {Owner, {command, Data}</c>. - </p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Information about the OS pid of a port.</fsummary> + <desc> + <p><c><anno>OsPid</anno></c> is the process identifier (or equivalent) + of an OS process created with + <seealso marker="#open_port/2"><c>open_port({spawn | spawn_executable, + Command}, Options)</c></seealso>. If the port is not the result of + spawning an OS process, the value is <c>undefined</c>.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="11"/> - <fsummary>Information about the parallelism hint of a port</fsummary> - <desc> - <p><c><anno>Boolean</anno></c> corresponds to the port parallelism - hint being used by this port. For more information see - the <seealso marker="#open_port_parallelism">parallelism</seealso> - option of <seealso marker="#open_port/2">open_port/2</seealso>.</p> + <fsummary>Information about the output of a port.</fsummary> + <desc> + <p><c><anno>Bytes</anno></c> is the total number of bytes written + to the port from Erlang processes using + <seealso marker="#port_command/2"><c>port_command/2</c></seealso>, + <seealso marker="#port_command/3"><c>port_command/3</c></seealso>, + or <c><anno>Port</anno> ! {Owner, {command, Data}</c>.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="12"/> - <fsummary>Information about the queue size of a port</fsummary> - <desc> - <p><c><anno>Bytes</anno></c> is the total amount of data, - in bytes, queued by the port using the ERTS driver queue - implementation.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> - <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + <fsummary>Information about the parallelism hint of a port.</fsummary> + <desc> + <p><c><anno>Boolean</anno></c> corresponds to the port parallelism + hint used by this port. For more information, see option + <seealso marker="#open_port_parallelism"><c>parallelism</c></seealso> + of <seealso marker="#open_port/2"><c>open_port/2</c></seealso>.</p> </desc> </func> + <func> <name name="port_info" arity="2" clause_i="13"/> - <fsummary>Information about the registered name of a port</fsummary> - <desc> - <p><c><anno>RegisteredName</anno></c> is the registered name of - the port. If the port has no registered name, <c>[]</c> is returned.</p> - <p>If the port identified by <c><anno>Port</anno></c> is not open, - <c>undefined</c> is returned. If <c>undefined</c> is returned and - the calling process was linked to a previously open port identified - by <c><anno>Port</anno></c>, an exit signal due to this link - was received by the process prior to the return from - <c>port_info/2</c>.</p> + <fsummary>Information about the queue size of a port.</fsummary> + <desc> + <p><c><anno>Bytes</anno></c> is the total number + of bytes queued by the port using the ERTS driver queue + implementation.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local - port identifier, or an atom.</p> + port identifier, or an atom.</p> </desc> </func> + + <func> + <name name="port_info" arity="2" clause_i="14"/> + <fsummary>Information about the registered name of a port.</fsummary> + <desc> + <p><c><anno>RegisteredName</anno></c> is the registered name of + the port. If the port has no registered name, <c>[]</c> is + returned.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + <c>port_info/2</c> returns <c>undefined</c>.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> <name name="port_to_list" arity="1"/> - <fsummary>Text representation of a port identifier</fsummary> + <fsummary>Text representation of a port identifier.</fsummary> <desc> - <p>Returns a string which corresponds to the text + <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 and for use in - the Erlang operating system. It should not be used in - application programs.</p> - </warning> </desc> </func> + <func> <name name="ports" arity="0"/> - <fsummary>All open ports</fsummary> + <fsummary>List all existing ports.</fsummary> <desc> - <p>Returns a list of port identifiers corresponding to all the - ports currently existing on the local node.</p> - - <p>Note that a port that is exiting, exists but is not open.</p> + <p>Returns a list of port identifiers corresponding to all the + ports existing on the local node.</p> + <p>Notice that an exiting port exists, but is not open.</p> </desc> </func> + <func> <name name="pre_loaded" arity="0"/> - <fsummary>List of all pre-loaded modules</fsummary> + <fsummary>List all preloaded modules.</fsummary> <desc> - <p>Returns a list of Erlang modules which are pre-loaded in + <p>Returns a list of Erlang modules that are preloaded in the system. As all loading of code is done through the file system, the file system must have been loaded previously. - Hence, at least the module <c>init</c> must be pre-loaded.</p> + Hence, at least the module <c>init</c> must be preloaded.</p> </desc> </func> + <func> <name name="process_display" arity="2"/> - <fsummary>Write information about a local process on standard error</fsummary> + <fsummary>Write information about a local process on standard error. + </fsummary> <desc> <p>Writes information about the local process <c><anno>Pid</anno></c> on - standard error. The currently allowed value for the atom - <c><anno>Type</anno></c> is <c>backtrace</c>, which shows the contents of - the call stack, including information about the call chain, with + standard error. The only allowed value for the atom + <c><anno>Type</anno></c> is <c>backtrace</c>, which shows the contents + of the call stack, including information about the call chain, with the current function printed first. The format of the output is not further defined.</p> </desc> </func> + <func> <name name="process_flag" arity="2" clause_i="1"/> - <fsummary>Set process flag trap_exit for the calling process</fsummary> + <fsummary>Set process flag trap_exit for the calling process.</fsummary> <desc> <p>When <c>trap_exit</c> is set to <c>true</c>, exit signals - arriving to a process are converted to <c>{'EXIT', From, Reason}</c> messages, which can be received as ordinary + arriving to a process are converted to <c>{'EXIT', From, Reason}</c> + messages, which can be received as ordinary messages. If <c>trap_exit</c> is set to <c>false</c>, the process exits if it receives an exit signal other than <c>normal</c> and the exit signal is propagated to its - linked processes. Application processes should normally - not trap exits.</p> + linked processes. Application processes are normally + not to trap exits.</p> <p>Returns the old value of the flag.</p> - <p>See also <seealso marker="#exit/2">exit/2</seealso>.</p> + <p>See also <seealso marker="#exit/2"><c>exit/2</c></seealso>.</p> </desc> </func> + <func> <name name="process_flag" arity="2" clause_i="2"/> - <fsummary>Set process flag error_handler for the calling process</fsummary> + <fsummary>Set process flag error_handler for the calling process. + </fsummary> <desc> - <p>This is used by a process to redefine the error handler + <p>Used by a process to redefine the error handler for undefined function calls and undefined registered - processes. Inexperienced users should not use this flag - since code auto-loading is dependent on the correct + processes. Inexperienced users are not to use this flag, + as code auto-loading depends on the correct operation of the error handling module.</p> <p>Returns the old value of the flag.</p> </desc> </func> + <func> - <name name="process_flag" arity="2" clause_i="3"/> - <fsummary>Set process flag min_heap_size for the calling process</fsummary> + <name name="process_flag" arity="2" clause_i="3" + anchor="process_flag_min_heap_size"/> + <fsummary>Set process flag min_heap_size for the calling process. + </fsummary> <desc> - <p>This changes the minimum heap size for the calling - process.</p> + <p>Changes the minimum heap size for the calling process.</p> <p>Returns the old value of the flag.</p> </desc> </func> + <func> <name name="process_flag" arity="2" clause_i="4"/> - <fsummary>Set process flag min_bin_vheap_size for the calling process</fsummary> + <fsummary>Set process flag min_bin_vheap_size for the calling process. + </fsummary> <desc> - <p>This changes the minimum binary virtual heap size for the calling + <p>Changes the minimum binary virtual heap size for the calling process.</p> - <p>Returns the old value of the flag.</p> </desc> + <p>Returns the old value of the flag.</p> + </desc> </func> + <func> - <name name="process_flag" arity="2" clause_i="5"/> - <type name="priority_level"/> - <fsummary>Set process flag priority for the calling process</fsummary> - <desc> - <p><marker id="process_flag_priority"></marker> - This sets the process priority. <c><anno>Level</anno></c> is an atom. - There are currently four priority levels: <c>low</c>, - <c>normal</c>, <c>high</c>, and <c>max</c>. The default - priority level is <c>normal</c>. <em>NOTE</em>: The - <c>max</c> priority level is reserved for internal use in - the Erlang runtime system, and should <em>not</em> be used - by others. + <name name="process_flag" arity="2" clause_i="5" + anchor="process_flag_max_heap_size"/> + <fsummary>Set process flag max_heap_size for the calling process. + </fsummary> + <type name="max_heap_size"/> + <desc> + <p>This flag sets the maximum heap size for the calling process. + If <c><anno>MaxHeapSize</anno></c> is an integer, the system default + values for <c>kill</c> and <c>error_logger</c> are used. </p> - <p>Internally in each priority level processes are scheduled - in a round robin fashion. + <taglist> + <tag><c>size</c></tag> + <item> + <p>The maximum size in words of the process. If set to zero, the + heap size limit is disabled. <c>badarg</c> is be thrown if the + value is smaller than <seealso marker="#process_flag_min_heap_size"> + <c>min_heap_size</c></seealso>. The size check is only done when + a garbage collection is triggered.</p> + <p><c>size</c> is the entire heap of the process when garbage collection + is triggered. This includes all generational heaps, the process stack, + any <seealso marker="#process_flag_message_queue_data"> + messages that are considered to be part of the heap</seealso>, and any + extra memory that the garbage collector needs during collection.</p> + <p><c>size</c> is the same as can be retrieved using + <seealso marker="#process_info_total_heap_size"> + <c>erlang:process_info(Pid, total_heap_size)</c></seealso>, + or by adding <c>heap_block_size</c>, <c>old_heap_block_size</c> + and <c>mbuf_size</c> from <seealso marker="#process_info_garbage_collection_info"> + <c>erlang:process_info(Pid, garbage_collection_info)</c></seealso>.</p> + </item> + <tag><c>kill</c></tag> + <item> + <p>When set to <c>true</c>, the runtime system sends an + untrappable exit signal with reason <c>kill</c> to the process + if the maximum heap size is reached. The garbage collection + that triggered the <c>kill</c> is not completed, instead the + process exits as soon as possible. When set to <c>false</c>, + no exit signal is sent to the process, instead it continues + executing.</p> + <p>If <c>kill</c> is not defined in the map, + the system default will be used. The default system default + is <c>true</c>. It can be changed by either option + <seealso marker="erl#+hmaxk">+hmaxk</seealso> in <c>erl(1)</c>, + or <seealso marker="#system_flag_max_heap_size"> + <c>erlang:system_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> + </item> + <tag><c>error_logger</c></tag> + <item> + <p>When set to <c>true</c>, the runtime system logs an + error event via <seealso marker="kernel:logger"> + <c>logger</c></seealso>, + containing details about the process when the maximum + heap size is reached. One log event is sent + each time the limit is reached.</p> + <p>If <c>error_logger</c> is not defined in the map, the system + default is used. The default system default is <c>true</c>. + It can be changed by either the option + <seealso marker="erl#+hmaxel">+hmaxel</seealso> int <c>erl(1)</c>, + or <seealso marker="#system_flag_max_heap_size"> + <c>erlang:system_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> + </item> + </taglist> + <p>The heap size of a process is quite hard to predict, especially the + amount of memory that is used during the garbage collection. When + contemplating using this option, it is recommended to first run + it in production with <c>kill</c> set to <c>false</c> and inspect + the log events to see what the normal peak sizes + of the processes in the system is and then tune the value + accordingly. </p> + </desc> + </func> + + <func> + <name name="process_flag" arity="2" clause_i="6" + anchor="process_flag_message_queue_data"/> + <fsummary>Set process flag message_queue_data for the calling process. + </fsummary> + <type name="message_queue_data"/> + <desc> + <p>This flag determines how messages in the message queue + are stored, as follows:</p> + <taglist> + <tag><c>off_heap</c></tag> + <item> + <p><em>All</em> messages in the message queue will be stored + outside of the process heap. This implies that <em>no</em> + messages in the message queue will be part of a garbage + collection of the process.</p> + </item> + <tag><c>on_heap</c></tag> + <item> + <p>All messages in the message queue will eventually be + placed on heap. They can however temporarily be stored + off heap. This is how messages always have been stored + up until ERTS 8.0.</p> + </item> + </taglist> + <p>The default <c>message_queue_data</c> process flag is determined + by command-line argument <seealso marker="erl#+hmqd"> + <c>+hmqd</c></seealso> in <c>erl(1)</c>.</p> + <p>If the process potentially can get many messages in its queue, + 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 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> + <p>When changing this flag messages will be moved. This work + has been initiated but not completed when this function + call returns.</p> + <p>Returns the old value of the flag.</p> + </desc> + </func> + + <func> + <name name="process_flag" arity="2" clause_i="7" + anchor="process_flag_priority"/> + <fsummary>Set process flag priority for the calling process.</fsummary> + <type name="priority_level"/> + <desc> + <p> + Sets the process priority. <c><anno>Level</anno></c> is an atom. + Four priority levels exist: <c>low</c>, + <c>normal</c>, <c>high</c>, and <c>max</c>. Default + is <c>normal</c>.</p> + <note> + <p>Priority level <c>max</c> is reserved for internal use in + the Erlang runtime system, and is <em>not</em> to be used + by others.</p> + </note> + <p>Internally in each priority level, processes are scheduled + in a round robin fashion.</p> <p>Execution of processes on priority <c>normal</c> and - priority <c>low</c> will be interleaved. Processes on - priority <c>low</c> will be selected for execution less - frequently than processes on priority <c>normal</c>. - </p> - <p>When there are runnable processes on priority <c>high</c> - no processes on priority <c>low</c>, or <c>normal</c> will - be selected for execution. Note, however, that this does - <em>not</em> mean that no processes on priority <c>low</c>, - or <c>normal</c> will be able to run when there are - processes on priority <c>high</c> running. On the runtime - system with SMP support there might be more processes running - in parallel than processes on priority <c>high</c>, i.e., - a <c>low</c>, and a <c>high</c> priority process might - execute at the same time. - </p> - <p>When there are runnable processes on priority <c>max</c> + <c>low</c> are interleaved. Processes on priority + <c>low</c> are selected for execution less + frequently than processes on priority <c>normal</c>.</p> + <p>When runnable processes on priority <c>high</c> exist, + no processes on priority <c>low</c> or <c>normal</c> are + selected for execution. Notice however that this does + <em>not</em> mean that no processes on priority <c>low</c> + or <c>normal</c> can run when processes + are running on priority <c>high</c>. When using multiple + schedulers, more processes can be running + in parallel than processes on priority <c>high</c>. That is, + a <c>low</c> and a <c>high</c> priority process can + execute at the same time.</p> + <p>When runnable processes on priority <c>max</c> exist, no processes on priority <c>low</c>, <c>normal</c>, or - <c>high</c> will be selected for execution. As with the - <c>high</c> priority, processes on lower priorities might - execute in parallel with processes on priority <c>max</c>. - </p> - <p>Scheduling is preemptive. Regardless of priority, a process - is preempted when it has consumed more than a certain amount + <c>high</c> are selected for execution. As with priority + <c>high</c>, processes on lower priorities can + execute in parallel with processes on priority <c>max</c>.</p> + <p>Scheduling is pre-emptive. Regardless of priority, a process + is pre-empted when it has consumed more than a certain number of reductions since the last time it was selected for - execution. - </p> - <p><em>NOTE</em>: You should not depend on the scheduling - to remain exactly as it is today. Scheduling, at least on - the runtime system with SMP support, is very likely to be - modified in the future in order to better utilize available - processor cores. - </p> - <p>There is currently <em>no</em> automatic mechanism for - avoiding priority inversion, such as priority inheritance, - or priority ceilings. When using priorities you have - to take this into account and handle such scenarios by - yourself. - </p> + execution.</p> + <note> + <p>Do not depend on the scheduling + to remain exactly as it is today. Scheduling is likely to be + changed in a future release to use available processor cores better.</p> + </note> + <p>There is <em>no</em> automatic mechanism for + avoiding priority inversion, such as priority inheritance + or priority ceilings. When using priorities, + take this into account and handle such scenarios by + yourself.</p> <p>Making calls from a <c>high</c> priority process into code - that you don't have control over may cause the <c>high</c> - priority process to wait for a processes with lower - priority, i.e., effectively decreasing the priority of the + that you has no control over can cause the <c>high</c> + priority process to wait for a process with lower + priority. That is, effectively decreasing the priority of the <c>high</c> priority process during the call. Even if this - isn't the case with one version of the code that you don't - have under your control, it might be the case in a future - version of it. This might, for example, happen if a - <c>high</c> priority process triggers code loading, since - the code server runs on priority <c>normal</c>. - </p> + is not the case with one version of the code that you have no + control over, it can be the case in a future + version of it. This can, for example, occur if a + <c>high</c> priority process triggers code loading, as + the code server runs on priority <c>normal</c>.</p> <p>Other priorities than <c>normal</c> are normally not needed. - When other priorities are used, they need to be used - with care, especially the <c>high</c> priority <em>must</em> - be used with care. A process on <c>high</c> priority should - only perform work for short periods of time. Busy looping for - long periods of time in a <c>high</c> priority process will - most likely cause problems, since there are important servers - in OTP running on priority <c>normal</c>. - </p> + When other priorities are used, use them with care, + <em>especially</em> priority <c>high</c>. A + process on priority <c>high</c> is only + to perform work for short periods. Busy looping for + long periods in a <c>high</c> priority process causes + most likely problems, as important OTP servers + run on priority <c>normal</c>.</p> <p>Returns the old value of the flag.</p> </desc> </func> + <func> - <name name="process_flag" arity="2" clause_i="6"/> - <fsummary>Set process flag save_calls for the calling process</fsummary> + <name name="process_flag" arity="2" clause_i="8"/> + <fsummary>Set process flag save_calls for the calling process.</fsummary> <desc> <p><c><anno>N</anno></c> must be an integer in the interval 0..10000. - If <c><anno>N</anno></c> > 0, call saving is made active for the - process, which means that information about the <c><anno>N</anno></c> - most recent global function calls, BIF calls, sends and + If <c><anno>N</anno></c> > 0, call saving is made + active for the + process. This means that information about the <c><anno>N</anno></c> + most recent global function calls, BIF calls, sends, and receives made by the process are saved in a list, which can be retrieved with <c>process_info(Pid, last_calls)</c>. A global function call is one in which the module of the function is explicitly mentioned. Only a fixed amount of information - is saved: a tuple <c>{Module, Function, Arity}</c> for - function calls, and the mere atoms <c>send</c>, - <c>'receive'</c> and <c>timeout</c> for sends and receives - (<c>'receive'</c> when a message is received and - <c>timeout</c> when a receive times out). If <c>N</c> = 0, + is saved, as follows:</p> + <list type="bulleted"> + <item><p>A tuple <c>{Module, Function, Arity}</c> for + function calls</p></item> + <item><p>The atoms <c>send</c>, <c>'receive'</c>, and + <c>timeout</c> for sends and receives (<c>'receive'</c> + when a message is received and <c>timeout</c> when a + receive times out)</p></item> + </list> + <p>If <c>N</c> = 0, call saving is disabled for the process, which is the default. Whenever the size of the call saving list is set, its contents are reset.</p> <p>Returns the old value of the flag.</p> </desc> </func> + <func> - <name name="process_flag" arity="2" clause_i="7"/> - <fsummary>Set process flag sensitive for the calling process</fsummary> + <name name="process_flag" arity="2" clause_i="9"/> + <fsummary>Set process flag sensitive for the calling process.</fsummary> <desc> - <p>Set or clear the <c>sensitive</c> flag for the current process. + <p>Sets or clears flag <c>sensitive</c> for the current process. When a process has been marked as sensitive by calling - <c>process_flag(sensitive, true)</c>, features in the run-time - system that can be used for examining the data and/or inner working + <c>process_flag(sensitive, true)</c>, features in the runtime + system that can be used for examining the data or inner working of the process are silently disabled.</p> <p>Features that are disabled include (but are not limited to) the following:</p> - <p>Tracing: Trace flags can still be set for the process, but no - trace messages of any kind will be generated. - (If the <c>sensitive</c> flag is turned off, trace messages will - again be generated if there are any trace flags set.)</p> - <p>Sequential tracing: The sequential trace token will be propagated - as usual, but no sequential trace messages will be generated.</p> - <p><c>process_info/1,2</c> cannot be used to read out the message - queue or the process dictionary (both will be returned as empty lists).</p> + <list type="bulleted"> + <item><p>Tracing. Trace flags can still be set for the process, + but no trace messages of any kind are generated. (If flag + <c>sensitive</c> is turned off, trace messages are again + generated if any trace flags are set.)</p></item> + <item><p>Sequential tracing. The sequential trace token is + propagated as usual, but no sequential trace messages are + generated.</p></item> + </list> + <p><c>process_info/1,2</c> cannot be used to read out the + message queue or the process dictionary (both are returned + as empty lists).</p> <p>Stack back-traces cannot be displayed for the process.</p> <p>In crash dumps, the stack, messages, and the process dictionary - will be omitted.</p> + are omitted.</p> <p>If <c>{save_calls,N}</c> has been set for the process, no - function calls will be saved to the call saving list. - (The call saving list will not be cleared; furthermore, send, receive, - and timeout events will still be added to the list.)</p> + function calls are saved to the call saving list. + (The call saving list is not cleared. Also, send, receive, + and time-out events are still added to the list.)</p> <p>Returns the old value of the flag.</p> </desc> </func> + <func> <name name="process_flag" arity="3"/> - <fsummary>Set process flags for a process</fsummary> + <fsummary>Set process flags for a process.</fsummary> <desc> - <p>Sets certain flags for the process <c><anno>Pid</anno></c>, in the same - manner as - <seealso marker="#process_flag/2">process_flag/2</seealso>. - Returns the old value of the flag. The allowed values for + <p>Sets certain flags for the process <c><anno>Pid</anno></c>, + in the same manner as + <seealso marker="#process_flag/2"><c>process_flag/2</c></seealso>. + Returns the old value of the flag. The valid values for <c><anno>Flag</anno></c> are only a subset of those allowed in - <c>process_flag/2</c>, namely: <c>save_calls</c>.</p> - <p>Failure: <c>badarg</c> if <c><anno>Pid</anno></c> is not a local process.</p> + <c>process_flag/2</c>, namely <c>save_calls</c>.</p> + <p>Failure: <c>badarg</c> if <c><anno>Pid</anno></c> + is not a local process.</p> </desc> </func> + <func> <name name="process_info" arity="1"/> + <fsummary>Information about a process.</fsummary> <type name="process_info_result_item"/> <type name="priority_level"/> <type name="stack_item"/> - <fsummary>Information about a process</fsummary> + <type name="max_heap_size"/> + <type name="message_queue_data"/> <desc> <p>Returns a list containing <c><anno>InfoTuple</anno></c>s with - miscellaneous information about the process identified by - <c>Pid</c>, or <c>undefined</c> if the process is not alive. - </p> - <p> - The order of the <c><anno>InfoTuple</anno></c>s is not defined, nor - are all the <c><anno>InfoTuple</anno></c>s mandatory. The <c><anno>InfoTuple</anno></c>s - part of the result may be changed without prior notice. - Currently <c><anno>InfoTuple</anno></c>s with the following items - are part of the result: - <c>current_function</c>, <c>initial_call</c>, <c>status</c>, - <c>message_queue_len</c>, <c>messages</c>, <c>links</c>, - <c>dictionary</c>, <c>trap_exit</c>, <c>error_handler</c>, - <c>priority</c>, <c>group_leader</c>, <c>total_heap_size</c>, - <c>heap_size</c>, <c>stack_size</c>, <c>reductions</c>, and - <c>garbage_collection</c>. - If the process identified by <c><anno>Pid</anno></c> has a registered name - also an <c><anno>InfoTuple</anno></c> with the item <c>registered_name</c> - will appear. - </p> - <p>See <seealso marker="#process_info/2">process_info/2</seealso> - for information about specific <c><anno>InfoTuple</anno></c>s.</p> + miscellaneous information about the process identified by + <c>Pid</c>, or <c>undefined</c> if the process is not alive.</p> + <p>The order of the <c><anno>InfoTuple</anno></c>s is undefined and + all <c><anno>InfoTuple</anno></c>s are not mandatory. + The <c><anno>InfoTuple</anno></c>s + part of the result can be changed without prior notice.</p> + <p>The <c><anno>InfoTuple</anno></c>s with the following items + are part of the result:</p> + <list type="bulleted"> + <item><c>current_function</c></item> + <item><c>initial_call</c></item> + <item><c>status</c></item> + <item><c>message_queue_len</c></item> + <item><c>links</c></item> + <item><c>dictionary</c></item> + <item><c>trap_exit</c></item> + <item><c>error_handler</c></item> + <item><c>priority</c></item> + <item><c>group_leader</c></item> + <item><c>total_heap_size</c></item> + <item><c>heap_size</c></item> + <item><c>stack_size</c></item> + <item><c>reductions</c></item> + <item><c>garbage_collection</c></item> + </list> + <p>If the process identified by <c><anno>Pid</anno></c> has a + registered name, + also an <c><anno>InfoTuple</anno></c> with item <c>registered_name</c> + is included.</p> + <p>For information about specific <c><anno>InfoTuple</anno></c>s, see + <seealso marker="#process_info/2"><c>process_info/2</c></seealso>.</p> <warning> - <p>This BIF is intended for <em>debugging only</em>, use - <seealso marker="#process_info/2">process_info/2</seealso> - for all other purposes. - </p> + <p>This BIF is intended for <em>debugging only</em>. For + all other purposes, use <seealso marker="#process_info/2"> + <c>process_info/2</c></seealso>.</p> </warning> - <p>Failure: <c>badarg</c> if <c>Pid</c> is not a local process.</p> + <p>Failure: <c>badarg</c> if <c><anno>Pid</anno></c> is not a + local process.</p> </desc> </func> + <func> <name name="process_info" arity="2" clause_i="1"/> <name name="process_info" arity="2" clause_i="2"/> + <fsummary>Information about a process.</fsummary> <type name="process_info_item"/> <type name="process_info_result_item"/> <type name="stack_item"/> <type name="priority_level"/> - <fsummary>Information about a process</fsummary> - <desc> - <p>Returns information about the process identified by <c><anno>Pid</anno></c> - as specified by the <c><anno>Item</anno></c> or the <c><anno>ItemList</anno></c>, or <c>undefined</c> if the - process is not alive. - </p> - <p>If the process is alive and a single <c><anno>Item</anno></c> is given, - the returned value is the corresponding - <c><anno>InfoTuple</anno></c> unless <c>Item =:= registered_name</c> - and the process has no registered name. In this case - <c>[]</c> is returned. This strange behavior is due to - historical reasons, and is kept for backward compatibility. - </p> - <p>If an <c>ItemList</c> is given, the result is an - <c><anno>InfoTupleList</anno></c>. The <c><anno>InfoTuple</anno></c>s in the - <c><anno>InfoTupleList</anno></c> will appear with the corresponding - <c><anno>Item</anno></c>s in the same order as the <c><anno>Item</anno></c>s appeared - in the <c><anno>ItemList</anno></c>. Valid <c><anno>Item</anno></c>s may appear multiple - times in the <c><anno>ItemList</anno></c>. - </p> - <note><p>If <c>registered_name</c> is part of an <c><anno>ItemList</anno></c> - and the process has no name registered a - <c>{registered_name, []}</c> <c><anno>InfoTuple</anno></c> <em>will</em> - appear in the resulting <c><anno>InfoTupleList</anno></c>. This - behavior is different than when a single - <c>Item =:= registered_name</c> is given, and than when - <c>process_info/1</c> is used. - </p></note> - <p>Currently the following <c><anno>InfoTuple</anno></c>s with corresponding - <c><anno>Item</anno></c>s are valid:</p> + <type name="max_heap_size"/> + <type name="message_queue_data"/> + <desc> + <p>Returns information about the process identified by + <c><anno>Pid</anno></c>, as specified by + <c><anno>Item</anno></c> or <c><anno>ItemList</anno></c>. + Returns <c>undefined</c> if the process is not alive.</p> + <p>If the process is alive and a single <c><anno>Item</anno></c> + is specified, the returned value is the corresponding + <c><anno>InfoTuple</anno></c>, unless <c>Item =:= registered_name</c> + and the process has no registered name. In this case, + <c>[]</c> is returned. This strange behavior is because of + historical reasons, and is kept for backward compatibility.</p> + <p>If <c><anno>ItemList</anno></c> is specified, the result is + <c><anno>InfoTupleList</anno></c>. + The <c><anno>InfoTuple</anno></c>s in + <c><anno>InfoTupleList</anno></c> are included with the corresponding + <c><anno>Item</anno></c>s in the same order as the + <c><anno>Item</anno></c>s were included + in <c><anno>ItemList</anno></c>. Valid <c><anno>Item</anno></c>s can + be included multiple times in <c><anno>ItemList</anno></c>.</p> + <note> + <p>If <c>registered_name</c> is part of <c><anno>ItemList</anno></c> + and the process has no name registered, a + <c>{registered_name, []}</c>, <c><anno>InfoTuple</anno></c> + <em>will</em> be included in the resulting + <c><anno>InfoTupleList</anno></c>. This + behavior is different when a single + <c>Item =:= registered_name</c> is specified, and when + <c>process_info/1</c> is used.</p> + </note> + <p>Valid <c><anno>InfoTuple</anno></c>s with corresponding + <c><anno>Item</anno></c>s:</p> <taglist> <tag><c>{backtrace, <anno>Bin</anno>}</c></tag> <item> - <p>The binary <c><anno>Bin</anno></c> contains the same information as - the output from + <p>Binary <c><anno>Bin</anno></c> contains the same information + as the output from <c>erlang:process_display(<anno>Pid</anno>, backtrace)</c>. Use <c>binary_to_list/1</c> to obtain the string of characters from the binary.</p> </item> <tag><c>{binary, <anno>BinInfo</anno>}</c></tag> <item> - <p><c><anno>BinInfo</anno></c> is a list containing miscellaneous information - about binaries currently being referred to by this process. - This <c><anno>InfoTuple</anno></c> may be changed or removed without prior - notice.</p> + <p><c><anno>BinInfo</anno></c> is a list containing miscellaneous + information about binaries on the heap of this + process. + This <c><anno>InfoTuple</anno></c> can be changed or + removed without prior notice. In the current implementation + <c><anno>BinInfo</anno></c> is a list of tuples. The tuples + contain; <c>BinaryId</c>, <c>BinarySize</c>, <c>BinaryRefcCount</c>.</p> + <p>The message queue is on the heap depending on the + process flag <seealso marker="#process_flag_message_queue_data"> + <c>message_queue_data</c></seealso>.</p> </item> <tag><c>{catchlevel, <anno>CatchLevel</anno>}</c></tag> <item> <p><c><anno>CatchLevel</anno></c> is the number of currently active - catches in this process. This <c><anno>InfoTuple</anno></c> may be - changed or removed without prior notice.</p> + catches in this process. This <c><anno>InfoTuple</anno></c> can be + changed or removed without prior notice.</p> </item> - <tag><c>{current_function, {<anno>Module</anno>, <anno>Function</anno>, <anno>Arity</anno>}}</c></tag> + <tag><c>{current_function, {<anno>Module</anno>, + <anno>Function</anno>, Arity}}</c></tag> <item> - <p><c><anno>Module</anno></c>, <c><anno>Function</anno></c>, <c><anno>Arity</anno></c> is + <p><c><anno>Module</anno></c>, <c><anno>Function</anno></c>, + <c><anno>Arity</anno></c> is the current function call of the process.</p> </item> - <tag><c>{current_location, {<anno>Module</anno>, <anno>Function</anno>, <anno>Arity</anno>, <anno>Location</anno>}}</c></tag> + <tag><c>{current_location, {<anno>Module</anno>, + <anno>Function</anno>, <anno>Arity</anno>, + <anno>Location</anno>}}</c></tag> <item> - <p><c><anno>Module</anno></c>, <c><anno>Function</anno></c>, <c><anno>Arity</anno></c> is + <p><c><anno>Module</anno></c>, <c><anno>Function</anno></c>, + <c><anno>Arity</anno></c> is the current function call of the process. - <c><anno>Location</anno></c> is a list of two-tuples that describes the - location in the source code. - </p> + <c><anno>Location</anno></c> is a list of two-tuples describing + the location in the source code.</p> </item> <tag><c>{current_stacktrace, <anno>Stack</anno>}</c></tag> <item> - <p>Return the current call stack back-trace (<em>stacktrace</em>) + <p>Returns the current call stack back-trace (<em>stacktrace</em>) of the process. The stack has the same format as returned by - <seealso marker="#get_stacktrace/0">erlang:get_stacktrace/0</seealso>. - </p> + <seealso marker="#get_stacktrace/0"> + <c>erlang:get_stacktrace/0</c></seealso>. The depth of the + stacktrace is truncated according to the <c>backtrace_depth</c> + system flag setting.</p> </item> <tag><c>{dictionary, <anno>Dictionary</anno>}</c></tag> <item> - <p><c><anno>Dictionary</anno></c> is the dictionary of the process.</p> + <p><c><anno>Dictionary</anno></c> is the process dictionary.</p> </item> <tag><c>{error_handler, <anno>Module</anno>}</c></tag> <item> @@ -4020,55 +5218,69 @@ os_prompt% </pre> </item> <tag><c>{garbage_collection, <anno>GCInfo</anno>}</c></tag> <item> - <p><c><anno>GCInfo</anno></c> is a list which contains miscellaneous - information about garbage collection for this process. - The content of <c><anno>GCInfo</anno></c> may be changed without - prior notice.</p> + <p><c><anno>GCInfo</anno></c> is a list containing miscellaneous + information about garbage collection for this process. + The content of <c><anno>GCInfo</anno></c> can be changed without + prior notice.</p> + </item> + <tag> + <marker id="process_info_garbage_collection_info"/> + <c>{garbage_collection_info, <anno>GCInfo</anno>}</c> + </tag> + <item> + <p><c><anno>GCInfo</anno></c> is a list containing miscellaneous + detailed information about garbage collection for this process. + The content of <c><anno>GCInfo</anno></c> can be changed without + prior notice. For details about the meaning of each item, see + <seealso marker="#gc_minor_start"><c>gc_minor_start</c></seealso> + in <seealso marker="#trace/3"><c>erlang:trace/3</c></seealso>.</p> </item> <tag><c>{group_leader, <anno>GroupLeader</anno>}</c></tag> <item> - <p><c><anno>GroupLeader</anno></c> is group leader for the IO of - the process.</p> + <p><c><anno>GroupLeader</anno></c> is the group leader for the I/O + of the process.</p> </item> <tag><c>{heap_size, <anno>Size</anno>}</c></tag> <item> - <p><c><anno>Size</anno></c> is the size in words of youngest heap generation - of the process. This generation currently include the stack - of the process. This information is highly implementation - dependent, and may change if the implementation change. - </p> + <p><c><anno>Size</anno></c> is the size in words of the youngest + heap generation of the process. This generation includes + the process stack. This information is highly + implementation-dependent, and can change if the + implementation changes.</p> </item> - <tag><c>{initial_call, {Module, Function, Arity}}</c></tag> + <tag><c>{initial_call, {<anno>Module</anno>, <anno>Function</anno>, + <anno>Arity</anno>}}</c></tag> <item> - <p><c>Module</c>, <c>Function</c>, <c>Arity</c> is + <p><c><anno>Module</anno></c>, <c><anno>Function</anno></c>, + <c><anno>Arity</anno></c> is the initial function call with which the process was spawned.</p> </item> <tag><c>{links, <anno>PidsAndPorts</anno>}</c></tag> <item> - <p><c><anno>PidsAndPorts</anno></c> is a list of pids and - port identifiers, with processes or ports to which the process - has a link.</p> + <p><c><anno>PidsAndPorts</anno></c> is a list of process identifiers + and port identifiers, with processes or ports to which the process + has a link.</p> </item> <tag><c>{last_calls, false|Calls}</c></tag> <item> <p>The value is <c>false</c> if call saving is not active - for the process (see - <seealso marker="#process_flag/3">process_flag/3</seealso>). + for the process (see <seealso marker="#process_flag/3"> + <c>process_flag/3</c></seealso>). If call saving is active, a list is returned, in which the last element is the most recent called.</p> </item> <tag><c>{memory, <anno>Size</anno>}</c></tag> <item> - <p><c><anno>Size</anno></c> is the size in bytes of the process. This - includes call stack, heap and internal structures.</p> + <p><c><anno>Size</anno></c> is the size in bytes of the process. + This includes call stack, heap, and internal structures.</p> </item> <tag><c>{message_queue_len, <anno>MessageQueueLen</anno>}</c></tag> <item> <p><c><anno>MessageQueueLen</anno></c> is the number of messages - currently in the message queue of the process. This is - the length of the list <c><anno>MessageQueue</anno></c> returned as - the info item <c>messages</c> (see below).</p> + currently in the message queue of the process. This is the + length of the list <c><anno>MessageQueue</anno></c> returned as + the information item <c>messages</c> (see below).</p> </item> <tag><c>{messages, <anno>MessageQueue</anno>}</c></tag> <item> @@ -4077,279 +5289,404 @@ os_prompt% </pre> </item> <tag><c>{min_heap_size, <anno>MinHeapSize</anno>}</c></tag> <item> - <p><c><anno>MinHeapSize</anno></c> is the minimum heap size for the process.</p> + <p><c><anno>MinHeapSize</anno></c> is the minimum heap size + for the process.</p> </item> <tag><c>{min_bin_vheap_size, <anno>MinBinVHeapSize</anno>}</c></tag> <item> - <p><c><anno>MinBinVHeapSize</anno></c> is the minimum binary virtual heap size for the process.</p> + <p><c><anno>MinBinVHeapSize</anno></c> is the minimum binary virtual + heap size for the process.</p> </item> - <tag><c>{monitored_by, <anno>Pids</anno>}</c></tag> + <tag><c>{monitored_by, <anno>MonitoredBy</anno>}</c></tag> <item> - <p>A list of pids that are monitoring the process (with - <c>monitor/2</c>).</p> + <p>A list of identifiers for all the processes, ports and NIF + resources, that are monitoring the process.</p> </item> <tag><c>{monitors, <anno>Monitors</anno>}</c></tag> <item> <p>A list of monitors (started by <c>monitor/2</c>) that are active for the process. For a local process - monitor or a remote process monitor by pid, the list item - is <c>{process, <anno>Pid</anno>}</c>, and for a remote process - monitor by name, the list item is - <c>{process, {<anno>RegName</anno>, <anno>Node</anno>}}</c>.</p> + monitor or a remote process monitor by a process + identifier, the list consists of:</p> + <taglist> + <tag><c>{process, <anno>Pid</anno>}</c></tag> + <item>Process is monitored by pid.</item> + <tag><c>{process, {<anno>RegName</anno>, <anno>Node</anno>}}</c></tag> + <item>Local or remote process is monitored by name.</item> + <tag><c>{port, PortId}</c></tag> + <item>Local port is monitored by port id.</item> + <tag><c>{port, {<anno>RegName</anno>, <anno>Node</anno>}}</c></tag> + <item>Local port is monitored by name. Please note, that + remote port monitors are not supported, so <c>Node</c> will + always be the local node name.</item> + </taglist> + </item> + <tag><c>{message_queue_data, <anno>MQD</anno>}</c></tag> + <item> + <p>Returns the current state of process flag + <c>message_queue_data</c>. <c><anno>MQD</anno></c> is either + <c>off_heap</c> or <c>on_heap</c>. For more + information, see the documentation of + <seealso marker="#process_flag_message_queue_data"> + <c>process_flag(message_queue_data, MQD)</c></seealso>.</p> </item> - <tag><c>{priority, Level}</c></tag> + <tag><c>{priority, <anno>Level</anno>}</c></tag> <item> <p><c><anno>Level</anno></c> is the current priority level for - the process. For more information on priorities see - <seealso marker="#process_flag_priority">process_flag(priority, Level)</seealso>.</p> + the process. For more information on priorities, see + <seealso marker="#process_flag_priority"> + <c>process_flag(priority, Level)</c></seealso>.</p> </item> <tag><c>{reductions, <anno>Number</anno>}</c></tag> <item> - <p><c><anno>Number</anno></c> is the number of reductions executed by - the process.</p> + <p><c><anno>Number</anno></c> is the number of reductions executed + by the process.</p> </item> <tag><c>{registered_name, <anno>Atom</anno>}</c></tag> <item> - <p><c><anno>Atom</anno></c> is the registered name of the process. If - the process has no registered name, this tuple is not + <p><c><anno>Atom</anno></c> is the registered process name. + If the process has no registered name, this tuple is not present in the list.</p> </item> - <tag><c>{sequential_trace_token, [] | <anno>SequentialTraceToken</anno>}</c></tag> + <tag><c>{sequential_trace_token, [] | + <anno>SequentialTraceToken</anno>}</c></tag> <item> - <p><c><anno>SequentialTraceToken</anno></c> the sequential trace token for - the process. This <c><anno>InfoTuple</anno></c> may be changed or removed - without prior notice.</p> + <p><c><anno>SequentialTraceToken</anno></c> is the sequential trace + token for the process. This <c><anno>InfoTuple</anno></c> can be + changed or removed without prior notice.</p> </item> <tag><c>{stack_size, <anno>Size</anno>}</c></tag> <item> - <p><c><anno>Size</anno></c> is the stack size of the process in words.</p> + <p><c><anno>Size</anno></c> is the stack size, in words, + of the process.</p> </item> <tag><c>{status, <anno>Status</anno>}</c></tag> <item> - <p><c><anno>Status</anno></c> is the status of the process. <c><anno>Status</anno></c> - is <c>exiting</c>, <c>garbage_collecting</c>, - <c>waiting</c> (for a message), <c>running</c>, - <c>runnable</c> (ready to run, but another process is - running), or <c>suspended</c> (suspended on a "busy" port - or by the <c>erlang:suspend_process/[1,2]</c> BIF).</p> + <p><c><anno>Status</anno></c> is the status of the process and is + one of the following:</p> + <list type="bulleted"> + <item><c>exiting</c></item> + <item><c>garbage_collecting</c></item> + <item><c>waiting</c> (for a message)</item> + <item><c>running</c></item> + <item><c>runnable</c> (ready to run, but another process is + running)</item> + <item><c>suspended</c> (suspended on a "busy" port + or by the BIF <c>erlang:suspend_process/1,2</c>)</item> + </list> </item> <tag><c>{suspending, <anno>SuspendeeList</anno>}</c></tag> <item> - <p><c><anno>SuspendeeList</anno></c> is a list of <c>{<anno>Suspendee</anno>, - <anno>ActiveSuspendCount</anno>, <anno>OutstandingSuspendCount</anno>}</c> tuples. - <c><anno>Suspendee</anno></c> is the pid of a process that have been or is to - be suspended by the process identified by <c><anno>Pid</anno></c> via the - <seealso marker="#suspend_process/2">erlang:suspend_process/2</seealso> - BIF, or the - <seealso marker="#suspend_process/1">erlang:suspend_process/1</seealso> - BIF. <c><anno>ActiveSuspendCount</anno></c> is the number of times the - <c><anno>Suspendee</anno></c> has been suspended by <c><anno>Pid</anno></c>. - <c><anno>OutstandingSuspendCount</anno></c> is the number of not yet - completed suspend requests sent by <c><anno>Pid</anno></c>. That is, - if <c><anno>ActiveSuspendCount</anno> =/= 0</c>, <c><anno>Suspendee</anno></c> is - currently in the suspended state, and if - <c><anno>OutstandingSuspendCount</anno> =/= 0</c> the <c>asynchronous</c> - option of <c>erlang:suspend_process/2</c> has been used and - the suspendee has not yet been suspended by <c><anno>Pid</anno></c>. - Note that the <c><anno>ActiveSuspendCount</anno></c> and - <c><anno>OutstandingSuspendCount</anno></c> are not the total suspend count - on <c><anno>Suspendee</anno></c>, only the parts contributed by <c>Pid</c>. - </p> + <p><c><anno>SuspendeeList</anno></c> is a list of + <c>{<anno>Suspendee</anno>, <anno>ActiveSuspendCount</anno>, + <anno>OutstandingSuspendCount</anno>}</c> tuples. + <c><anno>Suspendee</anno></c> is the process identifier of a + process that has been, or is to be, + suspended by the process identified by <c><anno>Pid</anno></c> + through the BIF <seealso marker="#suspend_process/2"> + <c>erlang:suspend_process/2</c></seealso> or + <seealso marker="#suspend_process/1"> + <c>erlang:suspend_process/1</c></seealso>.</p> + <p><c><anno>ActiveSuspendCount</anno></c> is the number of + times <c><anno>Suspendee</anno></c> has been suspended by + <c><anno>Pid</anno></c>. + <c><anno>OutstandingSuspendCount</anno></c> is the number of not + yet completed suspend requests sent by <c><anno>Pid</anno></c>, + that is:</p> + <list type="bulleted"> + <item> + <p>If <c><anno>ActiveSuspendCount</anno> =/= 0</c>, + <c><anno>Suspendee</anno></c> is + currently in the suspended state.</p> + </item> + <item> + <p>If <c><anno>OutstandingSuspendCount</anno> =/= 0</c>, + option <c>asynchronous</c> of <c>erlang:suspend_process/2</c> + has been used and the suspendee has not yet been + suspended by <c><anno>Pid</anno></c>.</p> + </item> + </list> + <p>Notice that <c><anno>ActiveSuspendCount</anno></c> and + <c><anno>OutstandingSuspendCount</anno></c> are not the + total suspend count on <c><anno>Suspendee</anno></c>, + only the parts contributed by <c><anno>Pid</anno></c>.</p> </item> - <tag><c>{total_heap_size, <anno>Size</anno>}</c></tag> + <tag> + <marker id="process_info_total_heap_size"/> + <c>{total_heap_size, <anno>Size</anno>}</c> + </tag> <item> - <p><c><anno>Size</anno></c> is the total size in words of all heap - fragments of the process. This currently include the stack - of the process. - </p> + <p><c><anno>Size</anno></c> is the total size, in words, of all heap + fragments of the process. This includes the process stack and + any unreceived messages that are considered to be part of the + heap.</p> </item> <tag><c>{trace, <anno>InternalTraceFlags</anno>}</c></tag> <item> - <p><c><anno>InternalTraceFlags</anno></c> is an integer representing - internal trace flag for this process. This <c><anno>InfoTuple</anno></c> - may be changed or removed without prior notice.</p> + <p><c><anno>InternalTraceFlags</anno></c> is an integer + representing the internal trace flag for this process. + This <c><anno>InfoTuple</anno></c> + can be changed or removed without prior notice.</p> </item> <tag><c>{trap_exit, <anno>Boolean</anno>}</c></tag> <item> - <p><c><anno>Boolean</anno></c> is <c>true</c> if the process is trapping - exits, otherwise it is <c>false</c>.</p> + <p><c><anno>Boolean</anno></c> is <c>true</c> if the process + is trapping exits, otherwise <c>false</c>.</p> </item> </taglist> - <p>Note however, that not all implementations support every one - of the above <c><anno>Item</anno></c>s.</p> - <p>Failure: <c>badarg</c> if <c><anno>Pid</anno></c> is not a local process, - or if <c><anno>Item</anno></c> is not a valid <c><anno>Item</anno></c>.</p> + <p>Notice that not all implementations support all + these <c><anno>Item</anno></c>s.</p> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item>If <c><anno>Pid</anno></c> is not a local process.</item> + <tag><c>badarg</c></tag> + <item>If <c><anno>Item</anno></c> is an invalid item.</item> + </taglist> </desc> </func> + <func> <name name="processes" arity="0"/> - <fsummary>All processes</fsummary> + <fsummary>All processes.</fsummary> <desc> <p>Returns a list of process identifiers corresponding to - all the processes currently existing on the local node. - </p> - <p>Note that a process that is exiting, exists but is not alive, i.e., - <c>is_process_alive/1</c> will return <c>false</c> for a process - that is exiting, but its process identifier will be part - of the result returned from <c>processes/0</c>. - </p> + all the processes currently existing on the local node.</p> + <p>Notice that an exiting process exists, but is not alive. + That is, <c>is_process_alive/1</c> returns <c>false</c> + for an exiting process, but its process identifier is part + of the result returned from <c>processes/0</c>.</p> + <p>Example:</p> <pre> > <input>processes().</input> [<0.0.0>,<0.2.0>,<0.4.0>,<0.5.0>,<0.7.0>,<0.8.0>]</pre> </desc> </func> + <func> <name name="purge_module" arity="1"/> - <fsummary>Remove old code for a module</fsummary> + <fsummary>Remove old code for a module.</fsummary> <desc> - <p>Removes old code for <c><anno>Module</anno></c>. Before this BIF is used, - <c>erlang:check_process_code/2</c> should be called to check - that no processes are executing old code in the module.</p> + <p>Removes old code for <c><anno>Module</anno></c>. + Before this BIF is used, + <seealso marker="#check_process_code/2"> + <c>check_process_code/2</c></seealso>is to be called to check + that no processes execute old code in the module.</p> <warning> <p>This BIF is intended for the code server (see - <seealso marker="kernel:code">code(3)</seealso>) and should not be - used elsewhere.</p> + <seealso marker="kernel:code"><c>code(3)</c></seealso>) + and is not to be used elsewhere.</p> </warning> + <note> + <p>As from ERTS 8.0 (Erlang/OTP 19), any lingering processes + that still execute the old code is killed by this function. + In earlier versions, such incorrect use could cause much + more fatal failures, like emulator crash.</p> + </note> <p>Failure: <c>badarg</c> if there is no old code for <c><anno>Module</anno></c>.</p> </desc> </func> + <func> <name name="put" arity="2"/> - <fsummary>Add a new value to the process dictionary</fsummary> + <fsummary>Add a new value to the process dictionary.</fsummary> <desc> - <p>Adds a new <c><anno>Key</anno></c> to the process dictionary, associated - with the value <c><anno>Val</anno></c>, and returns <c>undefined</c>. If - <c><anno>Key</anno></c> already exists, the old value is deleted and - replaced by <c><anno>Val</anno></c> and the function returns the old value.</p> - <note> - <p>The values stored when <c>put</c> is evaluated within - the scope of a <c>catch</c> will not be retracted if a - <c>throw</c> is evaluated, or if an error occurs.</p> - </note> + <p>Adds a new <c><anno>Key</anno></c> to the process dictionary, + associated with the value <c><anno>Val</anno></c>, and returns + <c>undefined</c>. If <c><anno>Key</anno></c> exists, the old + value is deleted and replaced by <c><anno>Val</anno></c>, and + the function returns the old value. Example:</p> <pre> > <input>X = put(name, walrus), Y = put(name, carpenter),</input> <input>Z = get(name),</input> <input>{X, Y, Z}.</input> {undefined,walrus,carpenter}</pre> + <note> + <p>The values stored when <c>put</c> is evaluated within + the scope of a <c>catch</c> are not retracted if a + <c>throw</c> is evaluated, or if an error occurs.</p> + </note> </desc> </func> + <func> <name name="raise" arity="3"/> + <fsummary>Stop execution with an exception of specified class, reason, + and call stack backtrace.</fsummary> <type name="raise_stacktrace"/> - <fsummary>Stop execution with an exception of given class, reason and call stack backtrace</fsummary> <desc> <p>Stops the execution of the calling process with an - exception of given class, reason and call stack backtrace + exception of the specified class, reason, and call stack backtrace (<em>stacktrace</em>).</p> - <warning> - <p>This BIF is intended for debugging and for use in - the Erlang operating system. In general, it should - be avoided in applications, unless you know - very well what you are doing.</p> - </warning> - <p><c><anno>Class</anno></c> is one of <c>error</c>, <c>exit</c> or - <c>throw</c>, so if it were not for the stacktrace - <c>erlang:raise(<anno>Class</anno>, <anno>Reason</anno>, <anno>Stacktrace</anno>)</c> is - equivalent to <c>erlang:<anno>Class</anno>(<anno>Reason</anno>)</c>. - <c><anno>Reason</anno></c> is any term and <c><anno>Stacktrace</anno></c> is a list as - returned from <c>get_stacktrace()</c>, that is a list of - 4-tuples <c>{Module, Function, Arity | Args, - Location}</c> where <c>Module</c> and <c>Function</c> - are atoms and the third element is an integer arity or an - argument list. The stacktrace may also contain <c>{Fun, - Args, Location}</c> tuples where - <c>Fun</c> is a local fun and <c>Args</c> is an argument list.</p> - <p>The <c>Location</c> element at the end is optional. - Omitting it is equivalent to specifying an empty list.</p> + <p><c><anno>Class</anno></c> is <c>error</c>, <c>exit</c>, or + <c>throw</c>. So, if it were not for the stacktrace, + <c>erlang:raise(<anno>Class</anno>, <anno>Reason</anno>, + <anno>Stacktrace</anno>)</c> is equivalent to + <c>erlang:<anno>Class</anno>(<anno>Reason</anno>)</c>.</p> + <p><c><anno>Reason</anno></c> is any term. + <c><anno>Stacktrace</anno></c> is a list as + returned from <c>get_stacktrace()</c>, that is, a list of + four-tuples <c>{Module, Function, Arity | Args, + Location}</c>, where <c>Module</c> and <c>Function</c> + are atoms, and the third element is an integer arity or an + argument list. The stacktrace can also contain <c>{Fun, + Args, Location}</c> tuples, where <c>Fun</c> is a local + fun and <c>Args</c> is an argument list.</p> + <p>Element <c>Location</c> at the end is optional. + Omitting it is equivalent to specifying an empty list.</p> <p>The stacktrace is used as the exception stacktrace for the - calling process; it will be truncated to the current + calling process; it is truncated to the current maximum stacktrace depth.</p> - <p>Because evaluating this function causes the process to - terminate, it has no return value - unless the arguments are - invalid, in which case the function <em>returns the error reason</em>, that is <c>badarg</c>. If you want to be - really sure not to return you can call - <c>error(erlang:raise(<anno>Class</anno>, <anno>Reason</anno>, <anno>Stacktrace</anno>))</c> + <p>As evaluating this function causes the process to + terminate, it has no return value unless the arguments are + invalid, in which case the function <em>returns the error + reason</em> <c>badarg</c>. If you want to be + sure not to return, you can call + <c>error(erlang:raise(<anno>Class</anno>, <anno>Reason</anno>, + <anno>Stacktrace</anno>))</c> and hope to distinguish exceptions later.</p> </desc> </func> + <func> <name name="read_timer" arity="1"/> - <fsummary>Number of milliseconds remaining for a timer</fsummary> - <desc> - <p><c><anno>TimerRef</anno></c> is a timer reference returned by - <seealso marker="#send_after/3">erlang:send_after/3</seealso> - or - <seealso marker="#start_timer/3">erlang:start_timer/3</seealso>. - If the timer is active, the function returns the time in - milliseconds left until the timer will expire, otherwise - <c>false</c> (which means that <c><anno>TimerRef</anno></c> was never a - timer, that it has been cancelled, or that it has already - delivered its message).</p> + <fsummary>Read the state of a timer.</fsummary> + <desc> + <p>Reads the state of a timer. The same as calling + <seealso marker="#read_timer/2"><c>erlang:read_timer(TimerRef, + [])</c></seealso>.</p> + </desc> + </func> + + <func> + <name name="read_timer" arity="2"/> + <fsummary>Read the state of a timer.</fsummary> + <desc> + <p>Reads the state of a timer that has been created by either + <seealso marker="#start_timer/4"><c>erlang:start_timer</c></seealso> + or <seealso marker="#send_after/4"><c>erlang:send_after</c></seealso>. + <c><anno>TimerRef</anno></c> identifies the timer, and + was returned by the BIF that created the timer.</p> + <p><c><anno>Option</anno>s</c>:</p> + <taglist> + <tag><c>{async, Async}</c></tag> + <item> + <p>Asynchronous request for state information. <c>Async</c> + defaults to <c>false</c>, which causes the operation + to be performed synchronously. In this case, the <c>Result</c> + is returned by <c>erlang:read_timer</c>. When + <c>Async</c> is <c>true</c>, <c>erlang:read_timer</c> + sends an asynchronous request for the state information + to the timer service that manages the timer, and then returns + <c>ok</c>. A message on the format <c>{read_timer, + <anno>TimerRef</anno>, <anno>Result</anno>}</c> is + sent to the caller of <c>erlang:read_timer</c> when the + operation has been processed.</p> + </item> + </taglist> + <p>More <c><anno>Option</anno></c>s can be added in the future.</p> + <p>If <c><anno>Result</anno></c> is an integer, it represents the + time in milliseconds left until the timer expires.</p> + <p>If <c><anno>Result</anno></c> is <c>false</c>, a + timer corresponding to <c><anno>TimerRef</anno></c> could not + be found. This because the timer had expired, + or been canceled, or because <c><anno>TimerRef</anno></c> + never has corresponded to a timer. Even if the timer has expired, + it does not tell you whether or not the time-out message has + arrived at its destination yet.</p> + <note> + <p>The timer service that manages the timer can be co-located + with another scheduler than the scheduler that the calling + process is executing on. If so, communication + with the timer service takes much longer time than if it + is located locally. If the calling process is in a critical + path, and can do other things while waiting for the result + of this operation, you want to use option <c>{async, true}</c>. + If using option <c>{async, false}</c>, the calling + process is blocked until the operation has been performed.</p> + </note> <p>See also - <seealso marker="#send_after/3">erlang:send_after/3</seealso>, - <seealso marker="#start_timer/3">erlang:start_timer/3</seealso>, - and - <seealso marker="#cancel_timer/1">erlang:cancel_timer/1</seealso>.</p> + <seealso marker="#send_after/4"><c>erlang:send_after/4</c></seealso>, + <seealso marker="#start_timer/4"> + <c>erlang:start_timer/4</c></seealso>, and + <seealso marker="#cancel_timer/2"> + <c>erlang:cancel_timer/2</c></seealso>.</p> </desc> </func> + <func> <name name="ref_to_list" arity="1"/> - <fsummary>Text representation of a reference</fsummary> + <fsummary>Text representation of a reference.</fsummary> <desc> - <p>Returns a string which corresponds to the text + <p>Returns a string corresponding to the text representation of <c><anno>Ref</anno></c>.</p> <warning> - <p>This BIF is intended for debugging and for use in - the Erlang operating system. It should not be used in - application programs.</p> + <p>This BIF is intended for debugging and is not to be used + in application programs.</p> </warning> </desc> </func> + <func> <name name="register" arity="2"/> - <fsummary>Register a name for a pid (or port)</fsummary> + <fsummary>Register a name for a pid (or port).</fsummary> <desc> - <p>Associates the name <c><anno>RegName</anno></c> with a pid or a port - identifier. <c><anno>RegName</anno></c>, which must be an atom, can be used - instead of the pid / port identifier in the send operator - (<c><anno>RegName</anno> ! Message</c>).</p> + <p>Associates the name <c><anno>RegName</anno></c> with a process + identifier (pid) or a port identifier. + <c><anno>RegName</anno></c>, which must be an atom, can be used + instead of the pid or port identifier in send operator + (<c><anno>RegName</anno> ! Message</c>). Example:</p> <pre> > <input>register(db, Pid).</input> true</pre> - <p>Failure: <c>badarg</c> if <c><anno>PidOrPort</anno></c> is not an existing, - local process or port, if <c><anno>RegName</anno></c> is already in use, - if the process or port is already registered (already has a - name), or if <c><anno>RegName</anno></c> is the atom <c>undefined</c>.</p> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item>If <c><anno>PidOrPort</anno></c> is not an existing local + process or port.</item> + <tag><c>badarg</c></tag> + <item>If <c><anno>RegName</anno></c> is already in use.</item> + <tag><c>badarg</c></tag> + <item>If the process or port is already registered + (already has a name).</item> + <tag><c>badarg</c></tag> + <item>If <c><anno>RegName</anno></c> is the atom + <c>undefined</c>.</item> + </taglist> </desc> </func> + <func> <name name="registered" arity="0"/> - <fsummary>All registered names</fsummary> + <fsummary>All registered names.</fsummary> <desc> - <p>Returns a list of names which have been registered using - <seealso marker="#register/2">register/2</seealso>.</p> + <p>Returns a list of names that have been registered using + <seealso marker="#register/2"><c>register/2</c></seealso>, for + example:</p> <pre> > <input>registered().</input> [code_server, file_server, init, user, my_db]</pre> </desc> </func> + <func> <name name="resume_process" arity="1"/> - <fsummary>Resume a suspended process</fsummary> + <fsummary>Resume a suspended process.</fsummary> <desc> <p>Decreases the suspend count on the process identified by - <c><anno>Suspendee</anno></c>. <c><anno>Suspendee</anno></c> should previously have been - suspended via - <seealso marker="#suspend_process/2">erlang:suspend_process/2</seealso>, - or - <seealso marker="#suspend_process/1">erlang:suspend_process/1</seealso> - by the process calling <c>erlang:resume_process(<anno>Suspendee</anno>)</c>. When - the suspend count on <c><anno>Suspendee</anno></c> reach zero, <c><anno>Suspendee</anno></c> - will be resumed, i.e., the state of the <c>Suspendee</c> is changed - from suspended into the state <c><anno>Suspendee</anno></c> was in before it was - suspended. - </p> + <c><anno>Suspendee</anno></c>. <c><anno>Suspendee</anno></c> + is previously to have been suspended through + <seealso marker="#suspend_process/2"> + <c>erlang:suspend_process/2</c></seealso> or + <seealso marker="#suspend_process/1"> + <c>erlang:suspend_process/1</c></seealso> + by the process calling + <c>erlang:resume_process(<anno>Suspendee</anno>)</c>. When the + suspend count on <c><anno>Suspendee</anno></c> reaches zero, + <c><anno>Suspendee</anno></c> is resumed, that is, its state + is changed from suspended into the state it had before it was + suspended.</p> <warning> <p>This BIF is intended for debugging only.</p> </warning> @@ -4357,504 +5694,626 @@ true</pre> <taglist> <tag><c>badarg</c></tag> <item> - If <c><anno>Suspendee</anno></c> isn't a process identifier. - </item> + If <c><anno>Suspendee</anno></c> is not a process identifier. + </item> <tag><c>badarg</c></tag> <item> - If the process calling <c>erlang:resume_process/1</c> had - not previously increased the suspend count on the process - identified by <c><anno>Suspendee</anno></c>. - </item> + If the process calling <c>erlang:resume_process/1</c> had + not previously increased the suspend count on the process + identified by <c><anno>Suspendee</anno></c>. + </item> <tag><c>badarg</c></tag> <item> - If the process identified by <c><anno>Suspendee</anno></c> is not alive. - </item> + If the process identified by <c><anno>Suspendee</anno></c> + is not alive. + </item> </taglist> </desc> </func> + <func> <name name="round" arity="1"/> - <fsummary>Return an integer by rounding a number</fsummary> + <fsummary>Return an integer by rounding a number.</fsummary> <desc> - <p>Returns an integer by rounding <c><anno>Number</anno></c>.</p> + <p>Returns an integer by rounding <c><anno>Number</anno></c>, + for example:</p> <pre> -> <input>round(5.5).</input> +<input>round(5.5).</input> 6</pre> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="self" arity="0"/> - <fsummary>Pid of the calling process</fsummary> + <fsummary>Return pid of the calling process.</fsummary> <desc> - <p>Returns the pid (process identifier) of the calling process.</p> + <p>Returns the process identifier of the calling process, for + example:</p> <pre> > <input>self().</input> <0.26.0></pre> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="send" arity="2"/> - <fsummary>Send a message</fsummary> + <fsummary>Send a message.</fsummary> <type name="dst"/> <desc> - <p>Sends a message and returns <c><anno>Msg</anno></c>. This is the same as - <c><anno>Dest</anno> ! <anno>Msg</anno></c>.</p> - <p><c><anno>Dest</anno></c> may be a remote or local pid, a (local) port, a - locally registered name, or a tuple <c>{<anno>RegName</anno>, <anno>Node</anno>}</c> - for a registered name at another node.</p> + <p>Sends a message and returns <c><anno>Msg</anno></c>. This + is the same as using the <seealso marker="doc/reference_manual:expressions#send"> + send operator</seealso>: + <c><anno>Dest</anno> ! <anno>Msg</anno></c>.</p> + <p><c><anno>Dest</anno></c> can be a remote or local process identifier, + a (local) port, a locally registered name, or a tuple + <c>{<anno>RegName</anno>, <anno>Node</anno>}</c> + for a registered name at another node.</p> + <p>The function fails with a <c>badarg</c> run-time error if + <c><anno>Dest</anno></c> is an atom name, but this name is not + registered. This is the only case when <c>send</c> fails for an + unreachable destination <c><anno>Dest</anno></c> (of correct type).</p> </desc> </func> + <func> <name name="send" arity="3"/> + <fsummary>Send a message conditionally.</fsummary> <type name="dst"/> - <fsummary>Send a message conditionally</fsummary> - <desc> - <p>Sends a message and returns <c>ok</c>, or does not send - the message but returns something else (see below). Otherwise - the same as - <seealso marker="#send/2">erlang:send/2</seealso>. See - also - <seealso marker="#send_nosuspend/2">erlang:send_nosuspend/2,3</seealso>. - for more detailed explanation and warnings.</p> - <p>The possible options are:</p> + <desc> + <p>Either sends a message and returns <c>ok</c>, or does not send + the message but returns something else (see below). + Otherwise the same as + <seealso marker="#send/2"><c>erlang:send/2</c></seealso>. + For more detailed explanation and warnings, see + <seealso marker="#send_nosuspend/2"> + <c>erlang:send_nosuspend/2,3</c></seealso>.</p> + <p>Options:</p> <taglist> <tag><c>nosuspend</c></tag> - <item> - <p>If the sender would have to be suspended to do the send, - <c>nosuspend</c> is returned instead.</p> + <item>If the sender would have to be suspended to do the send, + <c>nosuspend</c> is returned instead. </item> <tag><c>noconnect</c></tag> <item> - <p>If the destination node would have to be auto-connected - before doing the send, <c>noconnect</c> is returned - instead.</p> + If the destination node would have to be auto-connected + to do the send, <c>noconnect</c> is returned + instead. </item> </taglist> <warning> - <p>As with <c>erlang:send_nosuspend/2,3</c>: Use with extreme - care!</p> + <p>As with <c>erlang:send_nosuspend/2,3</c>: use with extreme + care.</p> </warning> </desc> </func> + <func> <name name="send_after" arity="3"/> - <type_desc variable="Time">0 <= Time <= 4294967295</type_desc> - <fsummary>Start a timer</fsummary> - <desc> - <p>Starts a timer which will send the message <c>Msg</c> - to <c><anno>Dest</anno></c> after <c><anno>Time</anno></c> milliseconds.</p> - <p>If <c><anno>Dest</anno></c> is a <c>pid()</c> it has to be a <c>pid()</c> of a local process, dead or alive.</p> - <p>The <c><anno>Time</anno></c> value can, in the current implementation, not be greater than 4294967295.</p> - <p>If <c><anno>Dest</anno></c> is an <c>atom()</c>, it is supposed to be the name of - a registered process. The process referred to by the name is - looked up at the time of delivery. No error is given if - the name does not refer to a process.</p> - - <p>If <c><anno>Dest</anno></c> is a <c>pid()</c>, the timer will be automatically - canceled if the process referred to by the <c>pid()</c> is not alive, - or when the process exits. This feature was introduced in - erts version 5.4.11. Note that timers will not be - automatically canceled when <c><anno>Dest</anno></c> is an <c>atom</c>.</p> - <p>See also - <seealso marker="#start_timer/3">erlang:start_timer/3</seealso>, - <seealso marker="#cancel_timer/1">erlang:cancel_timer/1</seealso>, - and - <seealso marker="#read_timer/1">erlang:read_timer/1</seealso>.</p> - <p>Failure: <c>badarg</c> if the arguments does not satisfy - the requirements specified above.</p> + <fsummary>Start a timer.</fsummary> + <desc> + <p>Starts a timer. The same as calling + <seealso marker="#send_after/4"> + <c>erlang:send_after(<anno>Time</anno>, <anno>Dest</anno>, + <anno>Msg</anno>, [])</c></seealso>.</p> + </desc> + </func> + + <func> + <name name="send_after" arity="4"/> + <fsummary>Start a timer.</fsummary> + <desc> + <p>Starts a timer. When the timer expires, the message + <c><anno>Msg</anno></c> is sent to the process + identified by <c><anno>Dest</anno></c>. Apart from + the format of the time-out message, this function works exactly as + <seealso marker="#start_timer/4"> + <c>erlang:start_timer/4</c></seealso>.</p> </desc> </func> + <func> <name name="send_nosuspend" arity="2"/> - <fsummary>Try to send a message without ever blocking</fsummary> + <fsummary>Try to send a message without ever blocking.</fsummary> <type name="dst"/> <desc> <p>The same as - <seealso marker="#send/3">erlang:send(<anno>Dest</anno>, <anno>Msg</anno>, [nosuspend])</seealso>, but returns <c>true</c> if + <seealso marker="#send/3"><c>erlang:send(<anno>Dest</anno>, + <anno>Msg</anno>, [nosuspend])</c></seealso>, + but returns <c>true</c> if the message was sent and <c>false</c> if the message was not sent because the sender would have had to be suspended.</p> - <p>This function is intended for send operations towards an + <p>This function is intended for send operations to an unreliable remote node without ever blocking the sending (Erlang) process. If the connection to the remote node (usually not a real Erlang node, but a node written in C or - Java) is overloaded, this function <em>will not send the message</em> but return <c>false</c> instead.</p> - <p>The same happens, if <c><anno>Dest</anno></c> refers to a local port that - is busy. For all other destinations (allowed for the ordinary - send operator <c>'!'</c>) this function sends the message and + Java) is overloaded, this function <em>does not send the message</em> + and returns <c>false</c>.</p> + <p>The same occurs if <c><anno>Dest</anno></c> refers to a local port + that is busy. For all other destinations (allowed for the ordinary + send operator <c>'!'</c>), this function sends the message and returns <c>true</c>.</p> - <p>This function is only to be used in very rare circumstances + <p>This function is only to be used in rare circumstances where a process communicates with Erlang nodes that can - disappear without any trace causing the TCP buffers and - the drivers queue to be over-full before the node will actually - be shut down (due to tick timeouts) by <c>net_kernel</c>. The - normal reaction to take when this happens is some kind of + disappear without any trace, causing the TCP buffers and + the drivers queue to be over-full before the node is + shut down (because of tick time-outs) by <c>net_kernel</c>. + The normal reaction to take when this occurs is some kind of premature shutdown of the other node.</p> - <p>Note that ignoring the return value from this function would - result in <em>unreliable</em> message passing, which is + <p>Notice that ignoring the return value from this function would + result in an <em>unreliable</em> message passing, which is contradictory to the Erlang programming model. The message is <em>not</em> sent if this function returns <c>false</c>.</p> - <p>Note also that in many systems, transient states of - overloaded queues are normal. The fact that this function - returns <c>false</c> does not in any way mean that the other + <p>In many systems, transient states of + overloaded queues are normal. Although this function + returns <c>false</c> does not mean that the other node is guaranteed to be non-responsive, it could be a - temporary overload. Also a return value of <c>true</c> does - only mean that the message could be sent on the (TCP) channel - without blocking, the message is not guaranteed to have - arrived at the remote node. Also in the case of a disconnected + temporary overload. Also, a return value of <c>true</c> does + only mean that the message can be sent on the (TCP) channel + without blocking; the message is not guaranteed to + arrive at the remote node. For a disconnected non-responsive node, the return value is <c>true</c> (mimics - the behaviour of the <c>!</c> operator). The expected - behaviour as well as the actions to take when the function - returns <c>false</c> are application and hardware specific.</p> + the behavior of operator <c>!</c>). The expected + behavior and the actions to take when the function + returns <c>false</c> are application- and hardware-specific.</p> <warning> - <p>Use with extreme care!</p> + <p>Use with extreme care.</p> </warning> </desc> </func> + <func> <name name="send_nosuspend" arity="3"/> - <fsummary>Try to send a message without ever blocking</fsummary> + <fsummary>Try to send a message without ever blocking.</fsummary> <type name="dst"/> <desc> <p>The same as - <seealso marker="#send/3">erlang:send(<anno>Dest</anno>, <anno>Msg</anno>, [nosuspend | <anno>Options</anno>])</seealso>, - but with boolean return value.</p> + <seealso marker="#send/3"><c>erlang:send(<anno>Dest</anno>, + <anno>Msg</anno>, [nosuspend | <anno>Options</anno>])</c></seealso>, + but with a Boolean return value.</p> <p>This function behaves like - <seealso marker="#send_nosuspend/2">erlang:send_nosuspend/2)</seealso>, - but takes a third parameter, a list of options. The only - currently implemented option is <c>noconnect</c>. The option - <c>noconnect</c> makes the function return <c>false</c> if + <seealso marker="#send_nosuspend/2"> + <c>erlang:send_nosuspend/2</c></seealso>, + but takes a third parameter, a list of options. + The only option is <c>noconnect</c>, which + makes the function return <c>false</c> if the remote node is not currently reachable by the local - node. The normal behaviour is to try to connect to the node, - which may stall the process for a shorter period. The use of - the <c>noconnect</c> option makes it possible to be - absolutely sure not to get even the slightest delay when + node. The normal behavior is to try to connect to the node, + which can stall the process during a short period. The use of + option <c>noconnect</c> makes it possible to be + sure not to get the slightest delay when sending to a remote process. This is especially useful when - communicating with nodes who expect to always be - the connecting part (i.e. nodes written in C or Java).</p> + communicating with nodes that expect to always be + the connecting part (that is, nodes written in C or Java).</p> <p>Whenever the function returns <c>false</c> (either when a suspend would occur or when <c>noconnect</c> was specified and the node was not already connected), the message is guaranteed <em>not</em> to have been sent.</p> <warning> - <p>Use with extreme care!</p> + <p>Use with extreme care.</p> </warning> </desc> </func> + <func> <name name="set_cookie" arity="2"/> - <fsummary>Set the magic cookie of a node</fsummary> + <fsummary>Set the magic cookie of a node.</fsummary> <desc> <p>Sets the magic cookie of <c><anno>Node</anno></c> to the atom - <c><anno>Cookie</anno></c>. If <c><anno>Node</anno></c> is the local node, the function + <c><anno>Cookie</anno></c>. If <c><anno>Node</anno></c> is the + local node, the function also sets the cookie of all other unknown nodes to - <c><anno>Cookie</anno></c> (see - <seealso marker="doc/reference_manual:distributed">Distributed Erlang</seealso> in the Erlang Reference Manual).</p> + <c><anno>Cookie</anno></c> (see section + <seealso marker="doc/reference_manual:distributed"> + Distributed Erlang</seealso> + in the Erlang Reference Manual in System Documentation).</p> <p>Failure: <c>function_clause</c> if the local node is not alive.</p> </desc> </func> + <func> <name name="setelement" arity="3"/> - <type_desc variable="Index">1..tuple_size(<anno>Tuple1</anno>)</type_desc> - <fsummary>Set Nth element of a tuple</fsummary> + <fsummary>Set the Nth element of a tuple.</fsummary> + <type_desc variable="Index">1..tuple_size(<anno>Tuple1</anno></type_desc> <desc> - <p>Returns a tuple which is a copy of the argument <c><anno>Tuple1</anno></c> - with the element given by the integer argument <c><anno>Index</anno></c> + <p>Returns a tuple that is a copy of argument + <c><anno>Tuple1</anno></c> + with the element specified by integer argument + <c><anno>Index</anno></c> (the first element is the element with index 1) replaced by - the argument <c><anno>Value</anno></c>.</p> + argument <c><anno>Value</anno></c>, for example:</p> <pre> > <input>setelement(2, {10, green, bottles}, red).</input> {10,red,bottles}</pre> </desc> </func> + <func> <name name="size" arity="1"/> - <fsummary>Size of a tuple or binary</fsummary> + <fsummary>Size of a tuple or binary.</fsummary> <desc> - <p>Returns an integer which is the size of the argument - <c><anno>Item</anno></c>, which must be either a tuple or a binary.</p> + <p>Returns the number of elements in a tuple or the number of + bytes in a binary or bitstring, for example:</p> <pre> > <input>size({morni, mulle, bwange}).</input> +3 +> <input>size(<<11, 22, 33>>).</input> 3</pre> + <p>For bitstrings, the number of whole bytes is returned. + That is, if the number of bits + in the bitstring is not divisible by 8, the resulting + number of bytes is rounded <em>down</em>.</p> <p>Allowed in guard tests.</p> + <p>See also + <seealso marker="#tuple_size/1"><c>tuple_size/1</c></seealso>, + <seealso marker="#byte_size/1"><c>byte_size/1</c></seealso>, and + <seealso marker="#bit_size/1"><c>bit_size/1</c></seealso>.</p> </desc> </func> + <func> <name name="spawn" arity="1"/> - <fsummary>Create a new process with a fun as entry point</fsummary> + <fsummary>Create a new process with a fun as entry point.</fsummary> <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Fun</anno></c> to the empty list <c>[]</c>. Otherwise works - like <seealso marker="#spawn/3">spawn/3</seealso>.</p> + <p>Returns the process identifier of a new process started by the + application of <c><anno>Fun</anno></c> to the empty list + <c>[]</c>. Otherwise + works like <seealso marker="#spawn/3"><c>spawn/3</c></seealso>.</p> </desc> </func> + <func> <name name="spawn" arity="2"/> - <fsummary>Create a new process with a fun as entry point on a given node</fsummary> + <fsummary>Create a new process with a fun as entry point on a specified + node.</fsummary> <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Fun</anno></c> to the empty list <c>[]</c> on <c><anno>Node</anno></c>. If - <c><anno>Node</anno></c> does not exist, a useless pid is returned. - Otherwise works like - <seealso marker="#spawn/3">spawn/3</seealso>.</p> + <p>Returns the process identifier of a new process started + by the application of <c><anno>Fun</anno></c> to the + empty list <c>[]</c> on <c><anno>Node</anno></c>. If + <c><anno>Node</anno></c> does not exist, a useless pid is + returned. Otherwise works like + <seealso marker="#spawn/3"><c>spawn/3</c></seealso>.</p> </desc> </func> + <func> <name name="spawn" arity="3"/> - <fsummary>Create a new process with a function as entry point</fsummary> - <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Module</anno>:<anno>Function</anno></c> to <c><anno>Args</anno></c>. The new process - created will be placed in the system scheduler queue and be - run some time later.</p> - <p><c>error_handler:undefined_function(<anno>Module</anno>, <anno>Function</anno>, <anno>Args</anno>)</c> is evaluated by the new process if - <c><anno>Module</anno>:<anno>Function</anno>/Arity</c> does not exist (where - <c>Arity</c> is the length of <c><anno>Args</anno></c>). The error handler + <fsummary>Create a new process with a function as entry point.</fsummary> + <desc> + <p>Returns the process identifier of a new process started by + the application of <c><anno>Module</anno>:<anno>Function</anno></c> + to <c><anno>Args</anno></c>.</p> + <p><c>error_handler:undefined_function(<anno>Module</anno>, + <anno>Function</anno>, <anno>Args</anno>)</c> + is evaluated by the new process if + <c><anno>Module</anno>:<anno>Function</anno>/Arity</c> + does not exist (where <c>Arity</c> is the length of + <c><anno>Args</anno></c>). The error handler can be redefined (see - <seealso marker="#process_flag/2">process_flag/2</seealso>). + <seealso marker="#process_flag/2"><c>process_flag/2</c></seealso>). If <c>error_handler</c> is undefined, or the user has - redefined the default <c>error_handler</c> its replacement is - undefined, a failure with the reason <c>undef</c> will occur.</p> + redefined the default <c>error_handler</c> and its replacement is + undefined, a failure with reason <c>undef</c> occurs.</p> + <p>Example:</p> <pre> > <input>spawn(speed, regulator, [high_speed, thin_cut]).</input> <0.13.1></pre> </desc> </func> + <func> <name name="spawn" arity="4"/> - <fsummary>Create a new process with a function as entry point on a given node</fsummary> + <fsummary>Create a new process with a function as entry point on a + specified node.</fsummary> <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Module</anno>:<anno>Function</anno></c> to <c><anno>Args</anno></c> on <c>Node</c>. If - <c><anno>Node</anno></c> does not exists, a useless pid is returned. + <p>Returns the process identifier (pid) of a new process started + by the application + of <c><anno>Module</anno>:<anno>Function</anno></c> + to <c><anno>Args</anno></c> on <c><anno>Node</anno></c>. If + <c><anno>Node</anno></c> does not exist, a useless pid is returned. Otherwise works like - <seealso marker="#spawn/3">spawn/3</seealso>.</p> + <seealso marker="#spawn/3"><c>spawn/3</c></seealso>.</p> </desc> </func> + <func> <name name="spawn_link" arity="1"/> - <fsummary>Create and link to a new process with a fun as entry point</fsummary> + <fsummary>Create and link to a new process with a fun as entry point. + </fsummary> <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Fun</anno></c> to the empty list []. A link is created between + <p>Returns the process identifier of a new process started by + the application of <c><anno>Fun</anno></c> to the empty list + <c>[]</c>. A link is created between the calling process and the new process, atomically. Otherwise works like - <seealso marker="#spawn/3">spawn/3</seealso>.</p> + <seealso marker="#spawn/3"><c>spawn/3</c></seealso>.</p> </desc> </func> + <func> <name name="spawn_link" arity="2"/> - <fsummary>Create and link to a new process with a fun as entry point on a specified node</fsummary> + <fsummary>Create and link to a new process with a fun as entry point on + a specified node.</fsummary> <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Fun</anno></c> to the empty list [] on <c><anno>Node</anno></c>. A link is + <p>Returns the process identifier (pid) of a new process started + by the application of <c><anno>Fun</anno></c> to the empty + list <c>[]</c> on <c><anno>Node</anno></c>. A link is created between the calling process and the new process, - atomically. If <c><anno>Node</anno></c> does not exist, a useless pid is - returned (and due to the link, an exit signal with exit - reason <c>noconnection</c> will be received). Otherwise works - like <seealso marker="#spawn/3">spawn/3</seealso>.</p> + atomically. If <c><anno>Node</anno></c> does not exist, + a useless pid is returned and an exit signal with + reason <c>noconnection</c> is sent to the calling + process. Otherwise works like <seealso marker="#spawn/3"> + <c>spawn/3</c></seealso>.</p> </desc> </func> + <func> <name name="spawn_link" arity="3"/> - <fsummary>Create and link to a new process with a function as entry point</fsummary> + <fsummary>Create and link to a new process with a function as entry point. + </fsummary> <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Module</anno>:<anno>Function</anno></c> to <c><anno>Args</anno></c>. A link is created + <p>Returns the process identifier of a new process started by + the application of <c><anno>Module</anno>:<anno>Function</anno></c> + to <c><anno>Args</anno></c>. A link is created between the calling process and the new process, atomically. Otherwise works like - <seealso marker="#spawn/3">spawn/3</seealso>.</p> + <seealso marker="#spawn/3"><c>spawn/3</c></seealso>.</p> </desc> </func> + <func> <name name="spawn_link" arity="4"/> - <fsummary>Create and link to a new process with a function as entry point on a given node</fsummary> + <fsummary>Create and link to a new process with a function as entry point + on a specified node.</fsummary> <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Module</anno>:<anno>Function</anno></c> to <c><anno>Args</anno></c> on <c>Node</c>. A + <p>Returns the process identifier (pid) of a new process + started by the application + of <c><anno>Module</anno>:<anno>Function</anno></c> + to <c><anno>Args</anno></c> on <c><anno>Node</anno></c>. A link is created between the calling process and the new - process, atomically. If <c><anno>Node</anno></c> does not exist, a useless - pid is returned (and due to the link, an exit signal with exit - reason <c>noconnection</c> will be received). Otherwise works - like <seealso marker="#spawn/3">spawn/3</seealso>.</p> + process, atomically. If <c><anno>Node</anno></c> does + not exist, a useless pid is returned and an exit signal with + reason <c>noconnection</c> is sent to the calling + process. Otherwise works like <seealso marker="#spawn/3"> + <c>spawn/3</c></seealso>.</p> </desc> </func> + <func> <name name="spawn_monitor" arity="1"/> - <fsummary>Create and monitor a new process with a fun as entry point</fsummary> + <fsummary>Create and monitor a new process with a fun as entry point. + </fsummary> <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Fun</anno></c> to the empty list [] and reference for a monitor - created to the new process. + <p>Returns the process identifier of a new process, started by + the application of <c><anno>Fun</anno></c> to the empty list + <c>[]</c>, + and a reference for a monitor created to the new process. Otherwise works like - <seealso marker="#spawn/3">spawn/3</seealso>.</p> + <seealso marker="#spawn/3"><c>spawn/3</c></seealso>.</p> </desc> </func> + <func> <name name="spawn_monitor" arity="3"/> - <fsummary>Create and monitor a new process with a function as entry point</fsummary> + <fsummary>Create and monitor a new process with a function as entry point. + </fsummary> <desc> <p>A new process is started by the application - of <c><anno>Module</anno>:<anno>Function</anno></c> to <c><anno>Args</anno></c>, and the process is - monitored at the same time. Returns the pid and a reference - for the monitor. - Otherwise works like - <seealso marker="#spawn/3">spawn/3</seealso>.</p> + of <c><anno>Module</anno>:<anno>Function</anno></c> + to <c><anno>Args</anno></c>. The process is + monitored at the same time. Returns the process identifier + and a reference for the monitor. Otherwise works like + <seealso marker="#spawn/3"><c>spawn/3</c></seealso>.</p> </desc> </func> + <func> <name name="spawn_opt" arity="2"/> - <type name="priority_level" /> - <fsummary>Create a new process with a fun as entry point</fsummary> + <fsummary>Create a new process with a fun as entry point.</fsummary> + <type name="priority_level"/> + <type name="max_heap_size"/> + <type name="message_queue_data"/> + <type name="spawn_opt_option"/> <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Fun</anno></c> to the empty list <c>[]</c>. Otherwise - works like - <seealso marker="#spawn_opt/4">spawn_opt/4</seealso>.</p> - <p>If the option <c>monitor</c> is given, the newly created - process will be monitored and both the pid and reference for - the monitor will be returned.</p> + <p>Returns the process identifier (pid) of a new process + started by the application of <c><anno>Fun</anno></c> + to the empty list <c>[]</c>. Otherwise works like + <seealso marker="#spawn_opt/4"><c>spawn_opt/4</c></seealso>.</p> + <p>If option <c>monitor</c> is specified, the newly created + process is monitored, and both the pid and reference for + the monitor are returned.</p> </desc> </func> + <func> <name name="spawn_opt" arity="3"/> - <type name="priority_level" /> - <fsummary>Create a new process with a fun as entry point on a given node</fsummary> + <fsummary>Create a new process with a fun as entry point on a specified + node.</fsummary> + <type name="priority_level"/> + <type name="max_heap_size"/> + <type name="message_queue_data"/> + <type name="spawn_opt_option"/> <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Fun</anno></c> to the empty list <c>[]</c> on <c><anno>Node</anno></c>. If - <c><anno>Node</anno></c> does not exist, a useless pid is returned. - Otherwise works like - <seealso marker="#spawn_opt/4">spawn_opt/4</seealso>.</p> + <p>Returns the process identifier (pid) of a new process started + by the application of <c><anno>Fun</anno></c> to the + empty list <c>[]</c> on <c><anno>Node</anno></c>. If + <c><anno>Node</anno></c> does not exist, a useless pid is + returned. Otherwise works like + <seealso marker="#spawn_opt/4"><c>spawn_opt/4</c></seealso>.</p> </desc> </func> + <func> <name name="spawn_opt" arity="4"/> - <type name="priority_level" /> - <fsummary>Create a new process with a function as entry point</fsummary> - <desc> - <p>Works exactly like - <seealso marker="#spawn/3">spawn/3</seealso>, except that an - extra option list is given when creating the process.</p> - <p>If the option <c>monitor</c> is given, the newly created - process will be monitored and both the pid and reference for - the monitor will be returned.</p> + <fsummary>Create a new process with a function as entry point.</fsummary> + <type name="priority_level"/> + <type name="max_heap_size"/> + <type name="message_queue_data"/> + <type name="spawn_opt_option"/> + <desc> + <p>Works as + <seealso marker="#spawn/3"><c>spawn/3</c></seealso>, except that an + extra option list is specified when creating the process.</p> + <p>If option <c>monitor</c> is specified, the newly created + process is monitored, and both the pid and reference for + the monitor are returned.</p> + <p>Options:</p> <taglist> <tag><c>link</c></tag> <item> <p>Sets a link to the parent process (like - <c>spawn_link/3</c> does).</p> + <seealso marker="#spawn_link/3"><c>spawn_link/3</c></seealso> + does).</p> </item> <tag><c>monitor</c></tag> <item> - <p>Monitor the new process (just like - <seealso marker="#monitor/2">monitor/2</seealso> does).</p> + <p>Monitors the new process (like + <seealso marker="#monitor/2"><c>monitor/2</c></seealso> does).</p> </item> <tag><c>{priority, <anno>Level</anno>}</c></tag> <item> <p>Sets the priority of the new process. Equivalent to - executing - <seealso marker="#process_flag_priority">process_flag(priority, <anno>Level</anno>)</seealso> in the start function of the new process, - except that the priority will be set before the process is - selected for execution for the first time. For more information - on priorities see - <seealso marker="#process_flag_priority">process_flag(priority, Level)</seealso>.</p> + executing <seealso marker="#process_flag_priority"> + <c>process_flag(priority, <anno>Level</anno>)</c></seealso> + in the start function of the new process, + except that the priority is set before the process is + selected for execution for the first time. For more + information on priorities, see + <seealso marker="#process_flag_priority"> + <c>process_flag(priority, <anno>Level</anno>)</c></seealso>.</p> </item> <tag><c>{fullsweep_after, <anno>Number</anno>}</c></tag> <item> - <p>This option is only useful for performance tuning. - In general, you should not use this option unless you - know that there is problem with execution times and/or - memory consumption, and you should measure to make sure - that the option improved matters. - </p> + <p>Useful only for performance tuning. Do not use this + option unless you + know that there is problem with execution times or + memory consumption, and ensure + that the option improves matters.</p> <p>The Erlang runtime system uses a generational garbage collection scheme, using an "old heap" for data that has survived at least one garbage collection. When there is no more room on the old heap, a fullsweep garbage - collection will be done.</p> - <p>The <c>fullsweep_after</c> option makes it possible to + collection is done.</p> + <p>Option <c>fullsweep_after</c> makes it possible to specify the maximum number of generational collections - before forcing a fullsweep even if there is still room on - the old heap. Setting the number to zero effectively - disables the general collection algorithm, meaning that + before forcing a fullsweep, even if there is room on + the old heap. Setting the number to zero + disables the general collection algorithm, that is, all live data is copied at every garbage collection.</p> - <p>Here are a few cases when it could be useful to change - <c>fullsweep_after</c>. Firstly, if binaries that are no - longer used should be thrown away as soon as possible. - (Set <c><anno>Number</anno></c> to zero.) Secondly, a process that - mostly have short-lived data will be fullsweeped seldom - or never, meaning that the old heap will contain mostly - garbage. To ensure a fullsweep once in a while, set - <c><anno>Number</anno></c> to a suitable value such as 10 or 20. - Thirdly, in embedded systems with limited amount of RAM - and no virtual memory, one might want to preserve memory - by setting <c><anno>Number</anno></c> to zero. (The value may be set - globally, see - <seealso marker="#system_flag/2">erlang:system_flag/2</seealso>.)</p> + <p>A few cases when it can be useful to change + <c>fullsweep_after</c>:</p> + <list type="bulleted"> + <item><p>If binaries that are no longer used are to be + thrown away as soon as possible. (Set + <c><anno>Number</anno></c> to zero.)</p> + </item> + <item><p>A process that mostly have short-lived data is + fullsweeped seldom or never, that is, the old heap + contains mostly garbage. To ensure a fullsweep + occasionally, set <c><anno>Number</anno></c> to a + suitable value, such as 10 or 20.</p> + </item> + <item>In embedded systems with a limited amount of RAM + and no virtual memory, you might want to preserve memory + by setting <c><anno>Number</anno></c> to zero. + (The value can be set globally, see + <seealso marker="#system_flag/2"> + <c>erlang:system_flag/2</c></seealso>.) + </item> + </list> </item> <tag><c>{min_heap_size, <anno>Size</anno>}</c></tag> <item> - <p>This option is only useful for performance tuning. - In general, you should not use this option unless you - know that there is problem with execution times and/or - memory consumption, and you should measure to make sure - that the option improved matters. - </p> - <p>Gives a minimum heap size in words. Setting this value - higher than the system default might speed up some + <p>Useful only for performance tuning. Do not use this + option unless you know that there is problem with + execution times or memory consumption, and + ensure that the option improves matters.</p> + <p>Gives a minimum heap size, in words. Setting this value + higher than the system default can speed up some processes because less garbage collection is done. - Setting too high value, however, might waste memory and - slow down the system due to worse data locality. - Therefore, it is recommended to use this option only for + However, setting a too high value can waste memory and + slow down the system because of worse data locality. + Therefore, use this option only for fine-tuning an application and to measure the execution time with various <c><anno>Size</anno></c> values.</p> </item> <tag><c>{min_bin_vheap_size, <anno>VSize</anno>}</c></tag> <item> - <p>This option is only useful for performance tuning. - In general, you should not use this option unless you - know that there is problem with execution times and/or - memory consumption, and you should measure to make sure - that the option improved matters. - </p> - <p>Gives a minimum binary virtual heap size in words. Setting this value - higher than the system default might speed up some + <p>Useful only for performance tuning. Do not use this + option unless you know that there is problem with + execution times or memory consumption, and + ensure that the option improves matters.</p> + <p>Gives a minimum binary virtual heap size, in words. + Setting this value + higher than the system default can speed up some processes because less garbage collection is done. - Setting too high value, however, might waste memory. - Therefore, it is recommended to use this option only for + However, setting a too high value can waste memory. + Therefore, use this option only for fine-tuning an application and to measure the execution time with various <c><anno>VSize</anno></c> values.</p> </item> - + <tag><c>{max_heap_size, <anno>Size</anno>}</c></tag> + <item> + <p>Sets the <c>max_heap_size</c> process flag. The default + <c>max_heap_size</c> is determined by command-line argument + <seealso marker="erl#+hmax"><c>+hmax</c></seealso> + in <c>erl(1)</c>. For more information, see the + documentation of <seealso marker="#process_flag_max_heap_size"> + <c>process_flag(max_heap_size, <anno>Size</anno>)</c></seealso>. + </p> + </item> + <tag><c>{message_queue_data, <anno>MQD</anno>}</c></tag> + <item> + <p>Sets the state of the <c>message_queue_data</c> process + flag. <c><anno>MQD</anno></c> is to be either <c>off_heap</c> + or <c>on_heap</c>. The default + <c>message_queue_data</c> process flag is determined by + command-line argument <seealso marker="erl#+hmqd"> + <c>+hmqd</c></seealso> in <c>erl(1)</c>. + For more information, see the documentation of + <seealso marker="#process_flag_message_queue_data"> + <c>process_flag(message_queue_data, + <anno>MQD</anno>)</c></seealso>.</p> + </item> </taglist> </desc> </func> + <func> <name name="spawn_opt" arity="5"/> - <type name="priority_level" /> - <fsummary>Create a new process with a function as entry point on a given node</fsummary> - <desc> - <p>Returns the pid of a new process started by the application - of <c><anno>Module</anno>:<anno>Function</anno></c> to <c><anno>Args</anno></c> on <c>Node</c>. If + <fsummary>Create a new process with a function as entry point on a + specified node.</fsummary> + <type name="priority_level"/> + <type name="max_heap_size"/> + <type name="message_queue_data"/> + <type name="spawn_opt_option"/> + <desc> + <p>Returns the process identifier (pid) of a new process started + by the application + of <c><anno>Module</anno>:<anno>Function</anno></c> to + <c><anno>Args</anno></c> on <c><anno>Node</anno></c>. If <c><anno>Node</anno></c> does not exist, a useless pid is returned. Otherwise works like - <seealso marker="#spawn_opt/4">spawn_opt/4</seealso>.</p> - <note><p>The <c>monitor</c> option is currently not supported by - <c>spawn_opt/5</c>.</p></note> + <seealso marker="#spawn_opt/4"><c>spawn_opt/4</c></seealso>.</p> + <note> + <p>Option <c>monitor</c> is not supported by + <c>spawn_opt/5</c>.</p> + </note> </desc> </func> + <func> <name name="split_binary" arity="2"/> + <fsummary>Split a binary into two.</fsummary> <type_desc variable="Pos">0..byte_size(Bin)</type_desc> - <fsummary>Split a binary into two</fsummary> <desc> - <p>Returns a tuple containing the binaries which are the result - of splitting <c><anno>Bin</anno></c> into two parts at position <c><anno>Pos</anno></c>. + <p>Returns a tuple containing the binaries that are the result + of splitting <c><anno>Bin</anno></c> into two parts at + position <c><anno>Pos</anno></c>. This is not a destructive operation. After the operation, - there will be three binaries altogether.</p> + there are three binaries altogether. Example:</p> <pre> > <input>B = list_to_binary("0123456789").</input> <<"0123456789">> @@ -4868,157 +6327,512 @@ true</pre> 7</pre> </desc> </func> + <func> <name name="start_timer" arity="3"/> - <type_desc variable="Time">0 <= Time <= 4294967295</type_desc> - <fsummary>Start a timer</fsummary> - <desc> - <p>Starts a timer which will send the message - <c>{timeout, <anno>TimerRef</anno>, <anno>Msg</anno>}</c> to <c><anno>Dest</anno></c> - after <c><anno>Time</anno></c> milliseconds.</p> - <p>If <c><anno>Dest</anno></c> is a <c>pid()</c> it has to be a <c>pid()</c> of a local process, dead or alive.</p> - <p>The <c><anno>Time</anno></c> value can, in the current implementation, not be greater than 4294967295.</p> - <p>If <c><anno>Dest</anno></c> is an <c>atom()</c>, it is supposed to be the name of - a registered process. The process referred to by the name is - looked up at the time of delivery. No error is given if - the name does not refer to a process.</p> - <p>If <c><anno>Dest</anno></c> is a <c>pid()</c>, the timer will be automatically - canceled if the process referred to by the <c>pid()</c> is not alive, - or when the process exits. This feature was introduced in - erts version 5.4.11. Note that timers will not be - automatically canceled when <c><anno>Dest</anno></c> is an <c>atom()</c>.</p> - <p>See also - <seealso marker="#send_after/3">erlang:send_after/3</seealso>, - <seealso marker="#cancel_timer/1">erlang:cancel_timer/1</seealso>, - and - <seealso marker="#read_timer/1">erlang:read_timer/1</seealso>.</p> - <p>Failure: <c>badarg</c> if the arguments does not satisfy - the requirements specified above.</p> + <fsummary>Start a timer.</fsummary> + <desc> + <p>Starts a timer. The same as calling + <seealso marker="#start_timer/4"> + <c>erlang:start_timer(<anno>Time</anno>, + <anno>Dest</anno>, <anno>Msg</anno>, [])</c></seealso>.</p> </desc> </func> + <func> - <name name="statistics" arity="1" clause_i="1"/> - <fsummary>Information about context switches</fsummary> + <name name="start_timer" arity="4"/> + <fsummary>Start a timer.</fsummary> <desc> - <p><c><anno>ContextSwitches</anno></c> is the total number of context - switches since the system started.</p> + <p>Starts a timer. When the timer expires, the message + <c>{timeout, <anno>TimerRef</anno>, <anno>Msg</anno>}</c> + is sent to the process identified by <c><anno>Dest</anno></c>.</p> + <p><c><anno>Option</anno></c>s:</p> + <taglist> + <tag><c>{abs, false}</c></tag> + <item> + <p>This is the default. It means the + <c><anno>Time</anno></c> value is interpreted + as a time in milliseconds <em>relative</em> current + <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang + monotonic time</seealso>.</p> + </item> + <tag><c>{abs, true}</c></tag> + <item> + <p>Absolute <c><anno>Time</anno></c> value. The + <c><anno>Time</anno></c> value is interpreted as an + absolute Erlang monotonic time in milliseconds.</p> + </item> + </taglist> + <p>More <c><anno>Option</anno></c>s can be added in the future.</p> + <p>The absolute point in time, the timer is set to expire on, + must be in the interval + <c>[</c><seealso marker="#system_info_start_time"> + <c>erlang:system_info(start_time)</c></seealso><c>, + </c><seealso marker="#system_info_end_time"> + <c>erlang:system_info(end_time)</c></seealso><c>]</c>. + If a relative time is specified, the <c><anno>Time</anno></c> + value is not allowed to be negative.</p> + <p>If <c><anno>Dest</anno></c> is a <c>pid()</c>, it must + be a <c>pid()</c> of a process created on the current + runtime system instance. This process has either terminated + or not. If <c><anno>Dest</anno></c> is an + <c>atom()</c>, it is interpreted as the name of a + locally registered process. The process referred to by the + name is looked up at the time of timer expiration. No error + is returned if the name does not refer to a process.</p> + <p>If <c><anno>Dest</anno></c> is a <c>pid()</c>, the timer is + automatically canceled if the process referred to by the + <c>pid()</c> is not alive, or if the process exits. This + feature was introduced in ERTS 5.4.11. Notice that + timers are not automatically canceled when + <c><anno>Dest</anno></c> is an <c>atom()</c>.</p> + <p>See also + <seealso marker="#send_after/4"><c>erlang:send_after/4</c></seealso>, + <seealso marker="#cancel_timer/2"> + <c>erlang:cancel_timer/2</c></seealso>, and + <seealso marker="#read_timer/2"> + <c>erlang:read_timer/2</c></seealso>.</p> + <p>Failure: <c>badarg</c> if the arguments do not satisfy + the requirements specified here.</p> </desc> </func> + <func> - <name name="statistics" arity="1" clause_i="2"/> - <fsummary>Information about exact reductions</fsummary> + <name name="statistics" arity="1" clause_i="1" + anchor="statistics_active_tasks"/> + <fsummary>Information about active processes and ports.</fsummary> <desc> - <marker id="statistics_exact_reductions"></marker> - <note><p><c>statistics(exact_reductions)</c> is - a more expensive operation than - <seealso marker="#statistics_reductions">statistics(reductions)</seealso> - especially on an Erlang machine with SMP support.</p> - </note> + <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" + anchor="statistics_active_tasks_all"/> + <fsummary>Information about active processes and ports.</fsummary> + <desc> + <p>Returns a list where each element represents the amount + of active processes and ports on each run queue and its + associated schedulers. That is, the number of processes and + 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>, + <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>, 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="3"/> - <fsummary>Information about garbage collection</fsummary> + <fsummary>Information about context switches.</fsummary> <desc> - <p>This information may not be valid for all implementations.</p> - <pre> -> <input>statistics(garbage_collection).</input> -{85,23961,0} -</pre> + <p>Returns the total number of context switches since the + system started.</p> </desc> </func> + <func> - <name name="statistics" arity="1" clause_i="4"/> - <fsummary>Information about io</fsummary> + <name name="statistics" arity="1" clause_i="4" + anchor="statistics_exact_reductions"/> + <fsummary>Information about exact reductions.</fsummary> <desc> - <p><c><anno>Input</anno></c> is the total number of bytes received - through ports, and <c><anno>Output</anno></c> is the total number of - bytes output to ports.</p> + <p>Returns the number of exact reductions.</p> + <note> + <p><c>statistics(exact_reductions)</c> is + a more expensive operation than + <seealso marker="#statistics_reductions"> + statistics(reductions)</seealso>.</p> + </note> </desc> </func> + <func> <name name="statistics" arity="1" clause_i="5"/> - <fsummary>Information about reductions</fsummary> - <desc> - <marker id="statistics_reductions"></marker> - <note> - <p>Since erts-5.5 (OTP release R11B) - this value does not include reductions performed in current - time slices of currently scheduled processes. If an - exact value is wanted, use - <seealso marker="#statistics_exact_reductions">statistics(exact_reductions)</seealso>.</p> - </note> + <fsummary>Information about garbage collection.</fsummary> + <desc> + <p>Returns information about garbage collection, for example:</p> <pre> -> <input>statistics(reductions).</input> -{2046,11} -</pre> +> <input>statistics(garbage_collection).</input> +{85,23961,0}</pre> + <p>This information can be invalid for some implementations.</p> </desc> </func> + <func> <name name="statistics" arity="1" clause_i="6"/> - <fsummary>Information about the run-queue</fsummary> + <fsummary>Information about I/O.</fsummary> <desc> - <p>Returns the total length of the run queues, that is, the number - of processes that are ready to run on all available run queues.</p> + <p>Returns <c><anno>Input</anno></c>, + which is the total number of bytes + received through ports, and <c><anno>Output</anno></c>, + which is the total number of bytes output to ports.</p> </desc> </func> + <func> - <name name="statistics" arity="1" clause_i="7"/> - <fsummary>Information about run-time</fsummary> + <name name="statistics" arity="1" clause_i="7" + anchor="statistics_microstate_accounting"/> + <fsummary>Information about microstate accounting.</fsummary> + <desc> + <p>Microstate accounting can be used to measure how much time the Erlang + runtime system spends doing various tasks. It is designed to be as + lightweight as possible, but some overhead exists when this + is enabled. Microstate accounting is meant to be a profiling tool + to help finding performance bottlenecks. + To <c>start</c>/<c>stop</c>/<c>reset</c> microstate accounting, use + system flag <seealso marker="#system_flag_microstate_accounting"> + <c>microstate_accounting</c></seealso>.</p> + <p><c>statistics(microstate_accounting)</c> returns a list of maps + representing some of the OS threads within ERTS. Each map + contains <c>type</c> and <c>id</c> fields that can be used to + identify what + thread it is, and also a counters field that contains data about how + much time has been spent in the various states.</p> + <p>Example:</p> + <pre> +> <input>erlang:statistics(microstate_accounting).</input> +[#{counters => #{aux => 1899182914, + check_io => 2605863602, + emulator => 45731880463, + gc => 1512206910, + other => 5421338456, + port => 221631, + sleep => 5150294100}, + id => 1, + type => scheduler}|...]</pre> + <p>The time unit is the same as returned by + <seealso marker="kernel:os#perf_counter/0"> + <c>os:perf_counter/0</c></seealso>. + So, to convert it to milliseconds, you can do something like this:</p> + <pre> +lists:map( + fun(#{ counters := Cnt } = M) -> + MsCnt = maps:map(fun(_K, PerfCount) -> + erlang:convert_time_unit(PerfCount, perf_counter, 1000) + end, Cnt), + M#{ counters := MsCnt } + end, erlang:statistics(microstate_accounting)).</pre> + <p>Notice that these values are not guaranteed to be + the exact time spent in each state. This is because of various + optimisation done to keep the overhead as small as possible.</p> + <p><c><anno>MSAcc_Thread_Type</anno></c>s:</p> + <taglist> + <tag><c>scheduler</c></tag> + <item>The main execution threads that do most of the work. See + <seealso marker="erts:erl#+S">erl +S</seealso> for more details.</item> + <tag><c>dirty_cpu_scheduler</c></tag> + <item>The threads for long running cpu intensive work. See + <seealso marker="erts:erl#+SDcpu">erl +SDcpu</seealso> for more details.</item> + <tag><c>dirty_io_scheduler</c></tag> + <item>The threads for long running I/O work. See + <seealso marker="erts:erl#+SDio">erl +SDio</seealso> for more details.</item> + <tag><c>async</c></tag> + <item>Async threads are used by various linked-in drivers (mainly the + file drivers) do offload non-CPU intensive work. See + <seealso marker="erts:erl#+async_thread_pool_size">erl +A</seealso> for more details.</item> + <tag><c>aux</c></tag> + <item>Takes care of any work that is not + specifically assigned to a scheduler.</item> + <tag><c>poll</c></tag> + <item>Does the IO polling for the emulator. See + <seealso marker="erts:erl#+IOt">erl +IOt</seealso> for more details.</item> + </taglist> + <p>The following <c><anno>MSAcc_Thread_State</anno></c>s are available. + All states are exclusive, meaning that a thread cannot be in two + states at once. So, if you add the numbers of all counters in a + thread, you get the total runtime for that thread.</p> + <taglist> + <tag><c>aux</c></tag> + <item>Time spent handling auxiliary jobs.</item> + <tag><c>check_io</c></tag> + <item>Time spent checking for new I/O events.</item> + <tag><c>emulator</c></tag> + <item>Time spent executing Erlang processes.</item> + <tag><c>gc</c></tag> + <item>Time spent doing garbage collection. When extra states are + enabled this is the time spent doing non-fullsweep garbage + collections.</item> + <tag><c>other</c></tag> + <item>Time spent doing unaccounted things.</item> + <tag><c>port</c></tag> + <item>Time spent executing ports.</item> + <tag><c>sleep</c></tag> + <item>Time spent sleeping.</item> + </taglist> + <p>More fine-grained <c><anno>MSAcc_Thread_State</anno></c>s can + be added through configure (such as + <c>./configure --with-microstate-accounting=extra</c>). + Enabling these states causes performance degradation when + microstate accounting is turned off and increases the overhead when + it is turned on.</p> + <taglist> + <tag><c>alloc</c></tag> + <item>Time spent managing memory. Without extra states this time is + spread out over all other states.</item> + <tag><c>bif</c></tag> + <item>Time spent in BIFs. Without extra states this time is part of + the <c>emulator</c> state.</item> + <tag><c>busy_wait</c></tag> + <item>Time spent busy waiting. This is also the state where a + scheduler no longer reports that it is active when using + <seealso marker="#statistics_scheduler_wall_time"> + <c>statistics(scheduler_wall_time)</c></seealso>. So, if you add + all other states but this and sleep, and then divide that by all + time in the thread, you should get something very similar to the + <c>scheduler_wall_time</c> fraction. Without extra states this + time is part of the <c>other</c> state.</item> + <tag><c>ets</c></tag> + <item>Time spent executing ETS BIFs. Without extra states + this time is part of the <c>emulator</c> state.</item> + <tag><c>gc_full</c></tag> + <item>Time spent doing fullsweep garbage collection. Without extra + states this time is part of the <c>gc</c> state.</item> + <tag><c>nif</c></tag> + <item>Time spent in NIFs. Without extra states this time is part of + the <c>emulator</c> state.</item> + <tag><c>send</c></tag> + <item>Time spent sending messages (processes only). Without extra + states this time is part of the <c>emulator</c> state.</item> + <tag><c>timers</c></tag> + <item>Time spent managing timers. Without extra states this time is + part of the <c>other</c> state.</item> + </taglist> + <p>The utility module + <seealso marker="runtime_tools:msacc"><c>msacc(3)</c></seealso> + can be used to more easily analyse these statistics.</p> + <p>Returns <c>undefined</c> if system flag + <seealso marker="#system_flag_microstate_accounting"> + <c>microstate_accounting</c></seealso> is turned off.</p> + <p>The list of thread information is unsorted and can appear in + different order between calls.</p> + <note> + <p>The threads and states are subject to change without any + prior notice.</p> + </note> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="8" + anchor="statistics_reductions"/> + <fsummary>Information about reductions.</fsummary> <desc> - <p>Note that the run-time is the sum of the run-time for all - threads in the Erlang run-time system and may therefore be greater - than the wall-clock time. The time is returned in milliseconds.</p> + <p>Returns information about reductions, for example:</p> <pre> -> <input>statistics(runtime).</input> -{1690,1620} -</pre> +> <input>statistics(reductions).</input> +{2046,11}</pre> + <note><p>As from ERTS 5.5 (Erlang/OTP R11B), + this value does not include reductions performed in current + time slices of currently scheduled processes. If an + exact value is wanted, use + <seealso marker="#statistics_exact_reductions"> + <c>statistics(exact_reductions)</c></seealso>.</p> + </note> </desc> </func> + <func> - <name name="statistics" arity="1" clause_i="8"/> - <fsummary>Information about each schedulers work time</fsummary> + <name name="statistics" arity="1" clause_i="9" + anchor="statistics_run_queue"/> + <fsummary>Information about the run-queues.</fsummary> <desc> - <marker id="statistics_scheduler_wall_time"></marker> - <p> - Returns a list of tuples with <c>{<anno>SchedulerId</anno>, - <anno>ActiveTime</anno>, <anno>TotalTime</anno>}</c>, where - <c>SchedulerId</c> is an integer id of the scheduler, <c>ActiveTime</c> is - the duration the scheduler has been busy, <c>TotalTime</c> is the total time duration since - <seealso marker="#system_flag_scheduler_wall_time">scheduler_wall_time</seealso> - activation. The time unit is not defined and may be subject to change - between releases, operating systems and system restarts. - <c>scheduler_wall_time</c> should only be used to calculate relative - values for scheduler-utilization. <c>ActiveTime</c> can never exceed <c>TotalTime</c>. - </p> + <p>Returns the total length of all normal run-queues. That is, the number + of processes and ports that are ready to run on all available + normal run-queues. Dirty run queues are not part of the + 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"> + <c>statistics(total_run_queue_lengths)</c></seealso>, + especially when a large amount of schedulers is used.</p> + </desc> + </func> - <p>The definition of a busy scheduler is when it is not idle or not - scheduling (selecting) a process or port, meaning; executing process - code, executing linked-in-driver or NIF code, executing - built-in-functions or any other runtime handling, garbage collecting - or handling any other memory management. Note, a scheduler may also be - busy even if the operating system has scheduled out the scheduler - thread. - </p> + <func> + <name name="statistics" arity="1" clause_i="10" + anchor="statistics_run_queue_lengths"/> + <fsummary>Information about the run-queue lengths.</fsummary> + <desc> + <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> - <p> - Returns <c>undefined</c> if the system flag - <seealso marker="#system_flag_scheduler_wall_time">scheduler_wall_time</seealso> - is turned off. - </p> + <func> + <name name="statistics" arity="1" clause_i="11" + anchor="statistics_run_queue_lengths_all"/> + <fsummary>Information about the run-queue lengths.</fsummary> + <desc> + <p>Returns a list where each element represents the amount + of processes and ports ready to run for each run queue. + Values for normal run queues are located first in the + 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>, + <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>, + <seealso marker="#statistics_total_active_tasks_all"> + <c>statistics(total_active_tasks_all)</c></seealso>.</p> + </desc> + </func> - <p>The list of scheduler information is unsorted and may appear in different order - between calls. - </p> - <p>Using <c>scheduler_wall_time</c> to calculate scheduler utilization.</p> -<pre> + <func> + <name name="statistics" arity="1" clause_i="12"/> + <fsummary>Information about runtime.</fsummary> + <desc> + <p>Returns information about runtime, in milliseconds.</p> + <p>This is the sum of the runtime for all threads + in the Erlang runtime system and can therefore be greater + than the wall clock time.</p> + <warning><p>This value might wrap due to limitations in the + underlying functionality provided by the operating system + that is used.</p></warning> + <p>Example:</p> + <pre> +> <input>statistics(runtime).</input> +{1690,1620}</pre> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="13" + anchor="statistics_scheduler_wall_time"/> + <fsummary>Information about each schedulers work time.</fsummary> + <desc> + <p>Returns a list of tuples with + <c>{<anno>SchedulerId</anno>, <anno>ActiveTime</anno>, + <anno>TotalTime</anno>}</c>, where + <c><anno>SchedulerId</anno></c> is an integer ID of the scheduler, + <c><anno>ActiveTime</anno></c> is + the duration the scheduler has been busy, and + <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 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> + <list type="bulleted"> + <item>Executing process code</item> + <item>Executing linked-in driver or NIF code</item> + <item>Executing BIFs, or any other runtime handling</item> + <item>Garbage collecting</item> + <item>Handling any other memory management</item> + </list> + <p>Notice that a scheduler can also be busy even if the + OS has scheduled out the scheduler thread.</p> + <p>Returns <c>undefined</c> if system flag + <seealso marker="#system_flag_scheduler_wall_time"> + <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> + <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 we will take another snapshot and calculate scheduler-utilization per scheduler.</p> -<pre> +ok</pre> + <p>Some time later the user takes another snapshot and calculates + scheduler utilization per scheduler, for example:</p> + <pre> > <input>Ts1 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.</input> ok > <input>lists:map(fun({{I, A0, T0}, {I, A1, T1}}) -> @@ -5030,1483 +6844,2402 @@ ok {5,0.9717956667018103}, {6,0.9739235846420741}, {7,0.973237033077876}, - {8,0.9741297293248656}] -</pre> - <p>Using the same snapshots to calculate a total scheduler-utilization.</p> -<pre> + {8,0.9741297293248656}]</pre> + <p>Using the same snapshots to calculate a total + 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> -0.9769136803764825 -</pre> + {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 + 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. Use <c>erlang:system_flag(scheduler_wall_time, true)</c> to enable it. </p> + <p><c>scheduler_wall_time</c> is by default disabled. To + enable it, use + <c>erlang:system_flag(scheduler_wall_time, true)</c>.</p> </note> </desc> </func> + + <func> + <name name="statistics" arity="1" clause_i="14" + anchor="statistics_scheduler_wall_time_all"/> + <fsummary>Information about each schedulers work time.</fsummary> + <desc> + <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" + anchor="statistics_total_active_tasks"/> + <fsummary>Information about active processes and ports.</fsummary> + <desc> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_active_tasks"><c>statistics(active_tasks)</c></seealso><c>)</c>, + but more efficient.</p> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="16" + anchor="statistics_total_active_tasks_all"/> + <fsummary>Information about active processes and ports.</fsummary> + <desc> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_active_tasks_all"><c>statistics(active_tasks_all)</c></seealso><c>)</c>, + but more efficient.</p> + </desc> + </func> + + <func> + <name name="statistics" arity="1" clause_i="17" + anchor="statistics_total_run_queue_lengths"/> + <fsummary>Information about the run-queue lengths.</fsummary> + <desc> + <p>The same as calling + <c>lists:sum(</c><seealso marker="#statistics_run_queue_lengths"><c>statistics(run_queue_lengths)</c></seealso><c>)</c>, + but more efficient.</p> + </desc> + </func> + <func> - <name name="statistics" arity="1" clause_i="9"/> - <fsummary>Information about wall-clock</fsummary> + <name name="statistics" arity="1" clause_i="18" + anchor="statistics_total_run_queue_lengths_all"/> + <fsummary>Information about the run-queue lengths.</fsummary> <desc> - <p><c>wall_clock</c> can be used in the same manner as + <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 + be used in the same manner as <c>runtime</c>, except that real time is measured as opposed to runtime or CPU time.</p> </desc> </func> + + <func> + <name name="suspend_process" arity="1"/> + <fsummary>Suspend a process.</fsummary> + <desc> + <p>Suspends the process identified by + <c><anno>Suspendee</anno></c>. The same as calling + <seealso marker="#suspend_process/2"> + <c>erlang:suspend_process(<anno>Suspendee</anno>, + [])</c></seealso>.</p> + <warning> + <p>This BIF is intended for debugging only.</p> + </warning> + </desc> + </func> + <func> <name name="suspend_process" arity="2"/> - <fsummary>Suspend a process</fsummary> + <fsummary>Suspend a process.</fsummary> <desc> <p>Increases the suspend count on the process identified by - <c><anno>Suspendee</anno></c> and puts it in the suspended state if it isn't - already in the suspended state. A suspended process will not be - scheduled for execution until the process has been resumed. - </p> - - <p>A process can be suspended by multiple processes and can - be suspended multiple times by a single process. A suspended - process will not leave the suspended state until its suspend - count reach zero. The suspend count of <c><anno>Suspendee</anno></c> - is decreased when - <seealso marker="#resume_process/1">erlang:resume_process(<anno>Suspendee</anno>)</seealso> - is called by the same process that called - <c>erlang:suspend_process(<anno>Suspendee</anno>)</c>. All increased suspend - counts on other processes acquired by a process will automatically be - decreased when the process terminates.</p> - - <p>Currently the following options (<c><anno>Opt</anno></c>s) are available:</p> + <c><anno>Suspendee</anno></c> and puts it in the suspended + state if it is not + already in that state. A suspended process is not + scheduled for execution until the process has been resumed.</p> + <p>A process can be suspended by multiple processes and can + be suspended multiple times by a single process. A suspended + process does not leave the suspended state until its suspend + count reaches zero. The suspend count of + <c><anno>Suspendee</anno></c> is decreased when + <seealso marker="#resume_process/1"> + <c>erlang:resume_process(<anno>Suspendee</anno>)</c></seealso> + is called by the same process that called + <c>erlang:suspend_process(<anno>Suspendee</anno>)</c>. + All increased suspend + counts on other processes acquired by a process are automatically + decreased when the process terminates.</p> + <p>Options (<c><anno>Opt</anno></c>s):</p> <taglist> <tag><c>asynchronous</c></tag> <item> - A suspend request is sent to the process identified by - <c><anno>Suspendee</anno></c>. <c><anno>Suspendee</anno></c> will eventually suspend - unless it is resumed before it was able to suspend. The caller - of <c>erlang:suspend_process/2</c> will return immediately, - regardless of whether the <c><anno>Suspendee</anno></c> has suspended yet - or not. Note that the point in time when the <c><anno>Suspendee</anno></c> - will actually suspend cannot be deduced from other events - in the system. The only guarantee given is that the - <c><anno>Suspendee</anno></c> will <em>eventually</em> suspend (unless it - is resumed). If the <c>asynchronous</c> option has <em>not</em> - been passed, the caller of <c>erlang:suspend_process/2</c> will - be blocked until the <c><anno>Suspendee</anno></c> has actually suspended. - </item> + <p>A suspend request is sent to the process identified by + <c><anno>Suspendee</anno></c>. <c><anno>Suspendee</anno></c> + eventually suspends + unless it is resumed before it could suspend. The caller + of <c>erlang:suspend_process/2</c> returns immediately, + regardless of whether <c><anno>Suspendee</anno></c> has + suspended yet or not. The point in time when + <c><anno>Suspendee</anno></c> suspends cannot be deduced + from other events in the system. It is only guaranteed that + <c><anno>Suspendee</anno></c> <em>eventually</em> suspends + (unless it + is resumed). If no <c>asynchronous</c> options has + been passed, the caller of <c>erlang:suspend_process/2</c> is + blocked until <c><anno>Suspendee</anno></c> has suspended.</p> + </item> + <tag><c>{asynchronous, ReplyTag}</c></tag> + <item> + <p>A suspend request is sent to the process identified by + <c><anno>Suspendee</anno></c>. When the suspend request + has been processed, a reply message is sent to the caller + of this function. The reply is on the form <c>{ReplyTag, + State}</c> where <c>State</c> is either:</p> + <taglist> + <tag><c>exited</c></tag> + <item> + <p> + <c><anno>Suspendee</anno></c> has exited. + </p> + </item> + <tag><c>suspended</c></tag> + <item> + <p> + <c><anno>Suspendee</anno></c> is now suspended. + </p> + </item> + <tag><c>not_suspended</c></tag> + <item> + <p> + <c><anno>Suspendee</anno></c> is not suspended. + This can only happen when the process that + issued this request, have called + <c>resume_process(<anno>Suspendee</anno>)</c> + before getting the reply. + </p> + </item> + </taglist> + <p> + Appart from the reply message, the <c>{asynchronous, + ReplyTag}</c> option behaves exactly the same as the + <c>asynchronous</c> option without reply tag. + </p> + </item> <tag><c>unless_suspending</c></tag> <item> - The process identified by <c><anno>Suspendee</anno></c> will be suspended - unless the calling process already is suspending the - <c><anno>Suspendee</anno></c>. If <c>unless_suspending</c> is combined - with the <c>asynchronous</c> option, a suspend request will be - sent unless the calling process already is suspending the - <c><anno>Suspendee</anno></c> or if a suspend request already has been sent - and is in transit. If the calling process already is suspending - the <c><anno>Suspendee</anno></c>, or if combined with the <c>asynchronous</c> - option and a send request already is in transit, - <c>false</c> is returned and the suspend count on <c><anno>Suspendee</anno></c> - will remain unchanged. - </item> + <p>The process identified by <c><anno>Suspendee</anno></c> is + suspended unless the calling process already is suspending + <c><anno>Suspendee</anno></c>. + If <c>unless_suspending</c> is combined + with option <c>asynchronous</c>, a suspend request is + sent unless the calling process already is suspending + <c><anno>Suspendee</anno></c> or if a suspend request + already has been sent and is in transit. If the calling + process already is suspending <c><anno>Suspendee</anno></c>, + or if combined with option <c>asynchronous</c> + and a send request already is in transit, + <c>false</c> is returned and the suspend count on + <c><anno>Suspendee</anno></c> remains unchanged.</p> + </item> </taglist> - - <p>If the suspend count on the process identified by - <c><anno>Suspendee</anno></c> was increased, <c>true</c> is returned; otherwise, - <c>false</c> is returned.</p> - + <p>If the suspend count on the process identified by + <c><anno>Suspendee</anno></c> is increased, <c>true</c> + is returned, otherwise <c>false</c>.</p> <warning> <p>This BIF is intended for debugging only.</p> </warning> + <warning> + <p>You can easily create deadlocks if processes suspends + each other (directly or in circles). In ERTS versions prior + to ERTS version 10.0, the runtime system prevented such + deadlocks, but this prevention has now been removed due + to performance reasons.</p> + </warning> <p>Failures:</p> <taglist> <tag><c>badarg</c></tag> <item> - If <c><anno>Suspendee</anno></c> isn't a process identifier. - </item> + If <c><anno>Suspendee</anno></c> is not a process identifier. + </item> <tag><c>badarg</c></tag> <item> - If the process identified by <c><anno>Suspendee</anno></c> is same the process as - the process calling <c>erlang:suspend_process/2</c>. - </item> + If the process identified by <c><anno>Suspendee</anno></c> + is the same process + as the process calling <c>erlang:suspend_process/2</c>. + </item> <tag><c>badarg</c></tag> <item> - If the process identified by <c><anno>Suspendee</anno></c> is not alive. - </item> + If the process identified by <c><anno>Suspendee</anno></c> + is not alive. + </item> <tag><c>badarg</c></tag> <item> - If the process identified by <c><anno>Suspendee</anno></c> resides on another node. - </item> + If the process identified by <c><anno>Suspendee</anno></c> + resides on another node. + </item> <tag><c>badarg</c></tag> <item> - If <c><anno>OptList</anno></c> isn't a proper list of valid <c><anno>Opt</anno></c>s. - </item> + If <c><anno>OptList</anno></c> is not a proper list of valid + <c><anno>Opt</anno></c>s. + </item> <tag><c>system_limit</c></tag> <item> - If the process identified by <c><anno>Suspendee</anno></c> has been suspended more - times by the calling process than can be represented by the - currently used internal data structures. The current system limit - is larger than 2 000 000 000 suspends, and it will never be less - than that. - </item> + If the process identified by <c><anno>Suspendee</anno></c> + has been suspended + more times by the calling process than can be represented by the + currently used internal data structures. The system limit is + > 2,000,000,000 suspends and will never be lower. + </item> </taglist> </desc> </func> - <func> - <name name="suspend_process" arity="1"/> - <fsummary>Suspend a process</fsummary> - <desc> - <p>Suspends the process identified by <c><anno>Suspendee</anno></c>. The - same as calling - <seealso marker="#suspend_process/2">erlang:suspend_process(<anno>Suspendee</anno>, [])</seealso>. For more information see the documentation of <seealso marker="#suspend_process/2">erlang:suspend_process/2</seealso>. - </p> - <warning> - <p>This BIF is intended for debugging only.</p> - </warning> - </desc> - </func> + <func> <name name="system_flag" arity="2" clause_i="1"/> - <fsummary>Set system flag backtrace_depth</fsummary> + <fsummary>Set system flag <c>backtrace_depth</c>.</fsummary> <desc> <p>Sets the maximum depth of call stack back-traces in the - exit reason element of <c>'EXIT'</c> tuples.</p> + exit reason element of <c>'EXIT'</c> tuples. The flag + also limits the stacktrace depth returned by <c>process_info</c> + item <c>current_stacktrace.</c></p> <p>Returns the old value of the flag.</p> </desc> </func> + <func> - <name name="system_flag" arity="2" clause_i="2"/> + <name name="system_flag" arity="2" clause_i="2" + anchor="system_flag_cpu_topology"/> + <fsummary>Set system flag <c>cpu_topology</c>.</fsummary> <type name="cpu_topology"/> <type name="level_entry"/> <type name="level_tag"/> <type name="sub_level"/> <type name="info_list"/> - <fsummary>Set system flag cpu_topology</fsummary> <desc> <warning> - <p><marker id="system_flag_cpu_topology"></marker> - This argument is <em>deprecated</em> and - scheduled for removal in erts-5.10/OTP-R16. Instead of using - this argument you are advised to use the <c>erl</c> command - line argument <seealso marker="erts:erl#+sct">+sct</seealso>. - When this argument has been removed a final CPU topology to use - will be determined at emulator boot time.</p> + <p> + <em>This argument is deprecated.</em> + Instead of using this argument, use command-line argument + <seealso marker="erts:erl#+sct"><c>+sct</c></seealso> in + <c>erl(1)</c>.</p> + <p>When this argument is removed, a final CPU topology + to use is determined at emulator boot time.</p> </warning> - <p>Sets the user defined <c><anno>CpuTopology</anno></c>. The user defined - CPU topology will override any automatically detected - CPU topology. By passing <c>undefined</c> as <c><anno>CpuTopology</anno></c> - the system will revert back to the CPU topology automatically - detected. The returned value equals the value returned - from <c>erlang:system_info(cpu_topology)</c> before the - change was made. - </p> + <p>Sets the user-defined <c><anno>CpuTopology</anno></c>. + The user-defined + CPU topology overrides any automatically detected + CPU topology. By passing <c>undefined</c> as + <c><anno>CpuTopology</anno></c>, + the system reverts to the CPU topology automatically + detected. The returned value equals the value returned + from <c>erlang:system_info(cpu_topology)</c> before the + change was made.</p> <p>Returns the old value of the flag.</p> <p>The CPU topology is used when binding schedulers to logical - processors. If schedulers are already bound when the CPU - topology is changed, the schedulers will be sent a request - to rebind according to the new CPU topology. - </p> - <p>The user defined CPU topology can also be set by passing - the <seealso marker="erts:erl#+sct">+sct</seealso> command - line argument to <c>erl</c>. - </p> - <p>For information on the <c><anno>CpuTopology</anno></c> type - and more, see the documentation of - <seealso marker="#system_info_cpu_topology">erlang:system_info(cpu_topology)</seealso>, - and the <c>erl</c> <seealso marker="erts:erl#+sct">+sct</seealso> - and <seealso marker="erts:erl#+sbt">+sbt</seealso> - command line flags. - </p> + processors. If schedulers are already bound when the CPU + topology is changed, the schedulers are sent a request + to rebind according to the new CPU topology.</p> + <p>The user-defined CPU topology can also be set by passing + command-line argument + <seealso marker="erts:erl#+sct"><c>+sct</c></seealso> to + <c>erl(1)</c>.</p> + <p>For information on type <c><anno>CpuTopology</anno></c> + and more, see + <seealso marker="#system_info_cpu_topology"> + <c>erlang:system_info(cpu_topology)</c></seealso> + as well as command-line flags + <seealso marker="erts:erl#+sct"><c>+sct</c></seealso> and + <seealso marker="erts:erl#+sbt"><c>+sbt</c></seealso> in + <c>erl(1)</c>.</p> </desc> </func> + <func> - <name name="system_flag" arity="2" clause_i="3"/> - <fsummary>Set system flag dirty CPU schedulers online</fsummary> + <name name="system_flag" arity="2" clause_i="3" + anchor="system_flag_dirty_cpu_schedulers_online"/> + <fsummary>Set system_flag_dirty_cpu_schedulers_online.</fsummary> <desc> - <p><marker id="system_flag_dirty_cpu_schedulers_online"></marker> - Sets the amount of dirty CPU schedulers online. Valid range is - <![CDATA[1 <= DirtyCPUSchedulersOnline <= N]]> where <c>N</c> is the - lesser of the return values of <c>erlang:system_info(dirty_cpu_schedulers)</c> and - <c>erlang:system_info(schedulers_online)</c>. - </p> + <p> + Sets the number of dirty CPU schedulers online. Range is + <c><![CDATA[1 <= DirtyCPUSchedulersOnline <= N]]></c>, where <c>N</c> + is the smallest of the return values of + <c>erlang:system_info(dirty_cpu_schedulers)</c> and + <c>erlang:system_info(schedulers_online)</c>.</p> <p>Returns the old value of the flag.</p> - <p>Note that the number of dirty CPU schedulers online may change if the number of - schedulers online changes. For example, if there are 12 schedulers and all are - online, and 6 dirty CPU schedulers, all online as well, and <c>system_flag/2</c> - is used to set the number of schedulers online to 6, then the number of dirty - CPU schedulers online is automatically decreased by half as well, down to 3. - Similarly, the number of dirty CPU schedulers online increases proportionally - to increases in the number of schedulers online.</p> - <p><em>Note that the dirty schedulers functionality is experimental</em>, and - that you have to enable support for dirty schedulers when building OTP in order - to try out the functionality.</p> - <p>For more information see - <seealso marker="#system_info_dirty_cpu_schedulers">erlang:system_info(dirty_cpu_schedulers)</seealso> - and - <seealso marker="#system_info_dirty_cpu_schedulers_online">erlang:system_info(dirty_cpu_schedulers_online)</seealso>. - </p> + <p>The number of dirty CPU schedulers online can change if the + number of schedulers online changes. For example, if 12 + schedulers and 6 dirty CPU schedulers are online, and + <c>system_flag/2</c> is used to set the number of + schedulers online to 6, then the number of dirty CPU + schedulers online is automatically decreased by half as well, + down to 3. Similarly, the number of dirty CPU schedulers + online increases proportionally to increases in the number of + schedulers online.</p> + <p>For more information, see + <seealso marker="#system_info_dirty_cpu_schedulers"> + <c>erlang:system_info(dirty_cpu_schedulers)</c></seealso> and + <seealso marker="#system_info_dirty_cpu_schedulers_online"> + <c>erlang:system_info(dirty_cpu_schedulers_online)</c></seealso>.</p> </desc> </func> + <func> <name name="system_flag" arity="2" clause_i="4"/> - <fsummary>Set system flag fullsweep_after</fsummary> + <fsummary>Set system flag for erts_alloc.</fsummary> <desc> - <p><c><anno>Number</anno></c> is a non-negative integer which indicates + <p>Sets system flags for + <seealso marker="erts:erts_alloc"><c>erts_alloc(3)</c></seealso>. + <c><anno>Alloc</anno></c> is the allocator to affect, for example + <c>binary_alloc</c>. <c><anno>F</anno></c> is the flag to change and + <c><anno>V</anno></c> is the new value.</p> + <p>Only a subset of all <c>erts_alloc</c> flags can be changed + at run time. This subset is currently only the flag + <seealso marker="erts:erts_alloc#M_sbct"><c>sbct</c></seealso>.</p> + <p>Returns <c>ok</c> if the flag was set or <c>notsup</c> if not + supported by <c>erts_alloc</c>.</p> + </desc> + </func> + + <func> + <name name="system_flag" arity="2" clause_i="5"/> + <fsummary>Set system flag fullsweep_after.</fsummary> + <desc> + <p>Sets system flag <c>fullsweep_after</c>. + <c><anno>Number</anno></c> is a non-negative integer indicating how many times generational garbage collections can be done without forcing a fullsweep collection. The value - applies to new processes; processes already running are + applies to new processes, while processes already running are not affected.</p> <p>Returns the old value of the flag.</p> <p>In low-memory systems (especially without virtual - memory), setting the value to 0 can help to conserve + memory), setting the value to <c>0</c> can help to conserve memory.</p> - <p>An alternative way to set this value is through the - (operating system) environment variable - <c>ERL_FULLSWEEP_AFTER</c>.</p> + <p>This value can also be set through (OS) + environment variable <c>ERL_FULLSWEEP_AFTER</c>.</p> </desc> </func> + <func> - <name name="system_flag" arity="2" clause_i="5"/> - <fsummary>Set system flag min_heap_size</fsummary> - <desc> - <p>Sets the default minimum heap size for processes. The - size is given in words. The new <c>min_heap_size</c> only - effects processes spawned after the change of - <c>min_heap_size</c> has been made. - The <c>min_heap_size</c> can be set for individual - processes by use of - <seealso marker="#spawn_opt/4">spawn_opt/N</seealso> or - <seealso marker="#process_flag/2">process_flag/2</seealso>. </p> + <name name="system_flag" arity="2" clause_i="6" + anchor="system_flag_microstate_accounting"/> + <fsummary>Set system flag microstate_accounting.</fsummary> + <desc> + <p> + Turns on/off microstate accounting measurements. When passing reset, + all counters are reset to 0.</p> + <p>For more information see + <seealso marker="#statistics_microstate_accounting"> + <c>statistics(microstate_accounting)</c></seealso>.</p> + </desc> + </func> + + <func> + <name name="system_flag" arity="2" clause_i="7"/> + <fsummary>Set system flag min_heap_size.</fsummary> + <desc> + <p>Sets the default minimum heap size for processes. The size + is specified in words. The new <c>min_heap_size</c> effects + only processes spawned after the change of + <c>min_heap_size</c> has been made. <c>min_heap_size</c> + can be set for individual processes by using + <seealso marker="#spawn_opt/4"><c>spawn_opt/4</c></seealso> or + <seealso marker="#process_flag/2"><c>process_flag/2</c></seealso>.</p> + <p>Returns the old value of the flag.</p> + </desc> + </func> + + <func> + <name name="system_flag" arity="2" clause_i="8"/> + <fsummary>Set system flag min_bin_vheap_size.</fsummary> + <desc> + <p>Sets the default minimum binary virtual heap size for + processes. The size is specified in words. + The new <c>min_bin_vhheap_size</c> effects only + processes spawned after the change of + <c>min_bin_vheap_size</c> has been made. + <c>min_bin_vheap_size</c> can be set for individual + processes by using + <seealso marker="#spawn_opt/4"><c>spawn_opt/2,3,4</c></seealso> or + <seealso marker="#process_flag/2"><c>process_flag/2</c></seealso>.</p> <p>Returns the old value of the flag.</p> </desc> </func> + <func> - <name name="system_flag" arity="2" clause_i="6"/> - <fsummary>Set system flag min_bin_vheap_size</fsummary> + <name name="system_flag" arity="2" clause_i="9" + anchor="system_flag_max_heap_size"/> + <fsummary>Set system flag max_heap_size.</fsummary> + <type name="max_heap_size"/> <desc> - <p>Sets the default minimum binary virtual heap size for processes. The - size is given in words. The new <c>min_bin_vhheap_size</c> only - effects processes spawned after the change of - <c>min_bin_vhheap_size</c> has been made. - The <c>min_bin_vheap_size</c> can be set for individual - processes by use of - <seealso marker="#spawn_opt/4">spawn_opt/N</seealso> or - <seealso marker="#process_flag/2">process_flag/2</seealso>. </p> + <p> + Sets the default maximum heap size settings for processes. + The size is specified in words. The new <c>max_heap_size</c> + effects only processes spawned efter the change has been made. + <c>max_heap_size</c> can be set for individual processes using + <seealso marker="#spawn_opt/4"><c>spawn_opt/2,3,4</c></seealso> or + <seealso marker="#process_flag_max_heap_size"> + <c>process_flag/2</c></seealso>.</p> <p>Returns the old value of the flag.</p> </desc> </func> + <func> - <name name="system_flag" arity="2" clause_i="7"/> - <fsummary>Set system flag multi_scheduling</fsummary> + <name name="system_flag" arity="2" clause_i="10" + anchor="system_flag_multi_scheduling"/> + <fsummary>Set system flag multi_scheduling.</fsummary> <desc> - <p><marker id="system_flag_multi_scheduling"></marker> + <p> If multi-scheduling is enabled, more than one scheduler thread is used by the emulator. Multi-scheduling can be - blocked. When multi-scheduling has been blocked, only - one scheduler thread will schedule Erlang processes.</p> - <p>If <c><anno>BlockState</anno> =:= block</c>, multi-scheduling will - be blocked. If <c><anno>BlockState</anno> =:= unblock</c> and no-one - else is blocking multi-scheduling and this process has - only blocked one time, multi-scheduling will be unblocked. - One process can block multi-scheduling multiple times. - If a process has blocked multiple times, it has to - unblock exactly as many times as it has blocked before it - has released its multi-scheduling block. If a process that - has blocked multi-scheduling exits, it will release its - blocking of multi-scheduling.</p> + blocked in two different ways. Either all schedulers but + one is blocked, or all <em>normal</em> schedulers but + one is blocked. When only normal schedulers are blocked, + dirty schedulers are free to continue to schedule + processes.</p> + <p>If <c><anno>BlockState</anno> =:= block</c>, multi-scheduling is + blocked. That is, one and only one scheduler thread will + execute. If <c><anno>BlockState</anno> =:= unblock</c> and no one + else blocks multi-scheduling, and this process has + blocked only once, multi-scheduling is unblocked.</p> + <p>If <c><anno>BlockState</anno> =:= block_normal</c>, normal + multi-scheduling is blocked. That is, only one normal scheduler + thread will execute, but multiple dirty schedulers can execute. + If <c><anno>BlockState</anno> =:= unblock_normal</c> and no one + else blocks normal multi-scheduling, and this process has + blocked only once, normal multi-scheduling is unblocked.</p> + <p>One process can block multi-scheduling and normal + multi-scheduling multiple times. If a process has blocked + multiple times, it must unblock exactly as many times as it + has blocked before it has released its multi-scheduling + block. If a process that has blocked multi-scheduling or normal + multi-scheduling exits, it automatically releases its blocking + of multi-scheduling and normal multi-scheduling.</p> <p>The return values are <c>disabled</c>, <c>blocked</c>, - or <c>enabled</c>. The returned value describes the - state just after the call to + <c>blocked_normal</c>, or <c>enabled</c>. The returned value + describes the state just after the call to <c>erlang:system_flag(multi_scheduling, <anno>BlockState</anno>)</c> - has been made. The return values are described in the - documentation of <seealso marker="#system_info_multi_scheduling">erlang:system_info(multi_scheduling)</seealso>.</p> - <p><em>NOTE</em>: Blocking of multi-scheduling should normally - not be needed. If you feel that you need to - block multi-scheduling, think through the - problem at least a couple of times again. - Blocking multi-scheduling should only be used - as a last resort since it will most likely be - a <em>very inefficient</em> way to solve the - problem.</p> - <p>See also <seealso marker="#system_info_multi_scheduling">erlang:system_info(multi_scheduling)</seealso>, - <seealso marker="#system_info_multi_scheduling_blockers">erlang:system_info(multi_scheduling_blockers)</seealso>, and - <seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>.</p> + has been made. For information about the return values, see + <seealso marker="#system_info_multi_scheduling"> + <c>erlang:system_info(multi_scheduling)</c></seealso>.</p> + <note><p>Blocking of multi-scheduling and normal multi-scheduling + is normally not needed. If you feel that you need to use these + features, consider it a few more times again. Blocking + multi-scheduling is only to be used as a last resort, as it is + most likely a <em>very inefficient</em> way to solve the problem.</p> + </note> + <p>See also + <seealso marker="#system_info_multi_scheduling"> + <c>erlang:system_info(multi_scheduling)</c></seealso>, + <seealso marker="#system_info_normal_multi_scheduling_blockers"> + <c>erlang:system_info(normal_multi_scheduling_blockers)</c></seealso>, + <seealso marker="#system_info_multi_scheduling_blockers"> + <c>erlang:system_info(multi_scheduling_blockers)</c></seealso>, and + <seealso marker="#system_info_schedulers"> + <c>erlang:system_info(schedulers)</c></seealso>.</p> </desc> </func> + <func> - <name name="system_flag" arity="2" clause_i="8"/> + <name name="system_flag" arity="2" clause_i="11" + anchor="system_flag_scheduler_bind_type"/> + <fsummary>Set system flag scheduler_bind_type.</fsummary> <type name="scheduler_bind_type"/> - <fsummary>Set system flag scheduler_bind_type</fsummary> <desc> <warning> - <p><marker id="system_flag_scheduler_bind_type"></marker> - This argument is <em>deprecated</em> and - scheduled for removal in erts-5.10/OTP-R16. Instead of using - this argument you are advised to use the <c>erl</c> command - line argument <seealso marker="erts:erl#+sbt">+sbt</seealso>. - When this argument has been removed a final scheduler bind type - to use will be determined at emulator boot time.</p> + <p> + <em>This argument is deprecated.</em> + Instead of using this argument, use command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt</c></seealso> in + <c>erl(1)</c>. When this argument is removed, a final scheduler bind + type to use is determined at emulator boot time.</p> </warning> <p>Controls if and how schedulers are bound to logical - processors.</p> - <p>When <c>erlang:system_flag(scheduler_bind_type, <anno>How</anno>)</c> is - called, an asynchronous signal is sent to all schedulers - online which causes them to try to bind or unbind as requested. - <em>NOTE:</em> If a scheduler fails to bind, this - will often be silently ignored. This since it isn't always - possible to verify valid logical processor identifiers. If - an error is reported, it will be reported to the - <c>error_logger</c>. If you want to verify that the - schedulers actually have bound as requested, call - <seealso marker="#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>. - </p> - <p>Schedulers can currently only be bound on newer Linux, - Solaris, FreeBSD, and Windows systems, but more systems will be - supported in the future. - </p> + processors.</p> + <p>When <c>erlang:system_flag(scheduler_bind_type, <anno>How</anno>)</c> + is called, an asynchronous signal is sent to all schedulers + online, causing them to try to bind or unbind as requested.</p> + <note><p>If a scheduler fails to bind, this is often silently + ignored, as it is not always possible to verify valid + logical processor identifiers. If an error is reported, + an error event is logged. To verify that the + schedulers have bound as requested, call + <seealso marker="#system_info_scheduler_bindings"> + <c>erlang:system_info(scheduler_bindings)</c></seealso>.</p> + </note> + <p>Schedulers can be bound on newer Linux, + Solaris, FreeBSD, and Windows systems, but more systems will be + supported in future releases.</p> <p>In order for the runtime system to be able to bind schedulers, - the CPU topology needs to be known. If the runtime system fails - to automatically detect the CPU topology, it can be defined. - For more information on how to define the CPU topology, see - the <c>erl</c> <seealso marker="erts:erl#+sct">+sct</seealso> command - line flag. - </p> - <p>The runtime system will by default <em>not</em> bind schedulers - to logical processors. - </p> - <p><em>NOTE:</em> If the Erlang runtime system is the only - operating system process that binds threads to logical processors, - this improves the performance of the runtime system. However, - if other operating system processes (as for example another Erlang - runtime system) also bind threads to logical processors, there - might be a performance penalty instead. In some cases this - performance penalty might be severe. If this is the case, you - are advised to not bind the schedulers.</p> - <p>Schedulers can be bound in different ways. The <c><anno>How</anno></c> - argument determines how schedulers are bound. <c><anno>How</anno></c> can - currently be one of:</p> + the CPU topology must be known. If the runtime system fails + to detect the CPU topology automatically, it can be defined. + For more information on how to define the CPU topology, see + command-line flag <seealso marker="erts:erl#+sct"> + <c>+sct</c></seealso> in <c>erl(1)</c>.</p> + <p>The runtime system does by default <em>not</em> bind schedulers + to logical processors.</p> + <note><p>If the Erlang runtime system is the only OS + process binding threads to logical processors, this + improves the performance of the runtime system. However, + if other OS processes (for example, another Erlang + runtime system) also bind threads to logical processors, + there can be a performance penalty instead. Sometimes this + performance penalty can be severe. If so, it is recommended + to not bind the schedulers.</p> + </note> + <p>Schedulers can be bound in different ways. Argument + <c><anno>How</anno></c> determines how schedulers are + bound and can be any of the following:</p> <taglist> <tag><c>unbound</c></tag> - <item><p>Same as the <c>erl</c> command line argument - <seealso marker="erts:erl#+sbt">+sbt u</seealso>. - </p></item> + <item>Same as command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt u</c></seealso> in + <c>erl(1)</c>. + </item> <tag><c>no_spread</c></tag> - <item><p>Same as the <c>erl</c> command line argument - <seealso marker="erts:erl#+sbt">+sbt ns</seealso>. - </p></item> + <item>Same as command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt ns</c></seealso> + in <c>erl(1)</c>. + </item> <tag><c>thread_spread</c></tag> - <item><p>Same as the <c>erl</c> command line argument - <seealso marker="erts:erl#+sbt">+sbt ts</seealso>. - </p></item> + <item>Same as command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt ts</c></seealso> + in <c>erl(1)</c>. + </item> <tag><c>processor_spread</c></tag> - <item><p>Same as the <c>erl</c> command line argument - <seealso marker="erts:erl#+sbt">+sbt ps</seealso>. - </p></item> + <item>Same as command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt ps</c></seealso> + in <c>erl(1)</c>. + </item> <tag><c>spread</c></tag> - <item><p>Same as the <c>erl</c> command line argument - <seealso marker="erts:erl#+sbt">+sbt s</seealso>. - </p></item> + <item>Same as command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt s</c></seealso> + in <c>erl(1)</c>. + </item> <tag><c>no_node_thread_spread</c></tag> - <item><p>Same as the <c>erl</c> command line argument - <seealso marker="erts:erl#+sbt">+sbt nnts</seealso>. - </p></item> + <item>Same as command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt nnts</c></seealso> + in <c>erl(1)</c>. + </item> <tag><c>no_node_processor_spread</c></tag> - <item><p>Same as the <c>erl</c> command line argument - <seealso marker="erts:erl#+sbt">+sbt nnps</seealso>. - </p></item> + <item>Same as command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt nnps</c></seealso> + in <c>erl(1)</c>. + </item> <tag><c>thread_no_node_processor_spread</c></tag> - <item><p>Same as the <c>erl</c> command line argument - <seealso marker="erts:erl#+sbt">+sbt tnnps</seealso>. - </p></item> + <item>Same as command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt tnnps</c></seealso> + in <c>erl(1)</c>. + </item> <tag><c>default_bind</c></tag> - <item><p>Same as the <c>erl</c> command line argument - <seealso marker="erts:erl#+sbt">+sbt db</seealso>. - </p></item> + <item>Same as command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt db</c></seealso> + in <c>erl(1)</c>. + </item> </taglist> - <p>The value returned equals <c><anno>How</anno></c> before the - <c>scheduler_bind_type</c> flag was changed.</p> - <p>Failure:</p> + <p>The returned value equals <c><anno>How</anno></c> before flag + <c>scheduler_bind_type</c> was changed.</p> + <p>Failures:</p> <taglist> <tag><c>notsup</c></tag> - <item> - <p>If binding of schedulers is not supported.</p> + <item>If binding of schedulers is not supported. </item> <tag><c>badarg</c></tag> - <item> - <p>If <c>How</c> isn't one of the documented alternatives.</p> + <item>If <c><anno>How</anno></c> is not one of the documented + alternatives. </item> <tag><c>badarg</c></tag> - <item> - <p>If no CPU topology information is available.</p> + <item>If CPU topology information is unavailable. </item> </taglist> - <p>The scheduler bind type can also be set by passing - the <seealso marker="erts:erl#+sbt">+sbt</seealso> command - line argument to <c>erl</c>. - </p> + <p>The scheduler bind type can also be set by passing command-line + argument <seealso marker="erts:erl#+sbt"> + <c>+sbt</c></seealso> to <c>erl(1)</c>.</p> <p>For more information, see - <seealso marker="#system_info_scheduler_bind_type">erlang:system_info(scheduler_bind_type)</seealso>, - <seealso marker="#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>, - the <c>erl</c> <seealso marker="erts:erl#+sbt">+sbt</seealso> - and <seealso marker="erts:erl#+sct">+sct</seealso> command line - flags. - </p> + <seealso marker="#system_info_scheduler_bind_type"> + <c>erlang:system_info(scheduler_bind_type)</c></seealso>, + <seealso marker="#system_info_scheduler_bindings"> + <c>erlang:system_info(scheduler_bindings)</c></seealso>, + as well as command-line flags + <seealso marker="erts:erl#+sbt"><c>+sbt</c></seealso> + and <seealso marker="erts:erl#+sct"><c>+sct</c></seealso> + in <c>erl(1)</c>.</p> </desc> </func> + <func> - <name name="system_flag" arity="2" clause_i="9"/> - <fsummary>Set system flag scheduler_wall_time</fsummary> - <desc><p><marker id="system_flag_scheduler_wall_time"></marker> - Turns on/off scheduler wall time measurements. </p> - <p>For more information see, - <seealso marker="#statistics_scheduler_wall_time">erlang:statistics(scheduler_wall_time)</seealso>. - </p> + <name name="system_flag" arity="2" clause_i="12" + anchor="system_flag_scheduler_wall_time"/> + <fsummary>Set system flag scheduler_wall_time.</fsummary> + <desc> + <p> + Turns on or off scheduler wall time measurements.</p> + <p>For more information, see + <seealso marker="#statistics_scheduler_wall_time"> + <c>statistics(scheduler_wall_time)</c></seealso>.</p> </desc> </func> + <func> - <name name="system_flag" arity="2" clause_i="10"/> - <fsummary>Set system flag schedulers_online</fsummary> + <name name="system_flag" arity="2" clause_i="13" + anchor="system_flag_schedulers_online"/> + <fsummary>Set system flag schedulers_online.</fsummary> <desc> - <p><marker id="system_flag_schedulers_online"></marker> - Sets the amount of schedulers online. Valid range is - <![CDATA[1 <= SchedulersOnline <= erlang:system_info(schedulers)]]>. - </p> + <p> + Sets the number of schedulers online. Range is + <c><![CDATA[1 <= SchedulersOnline <= + erlang:system_info(schedulers)]]></c>.</p> <p>Returns the old value of the flag.</p> - <p>Note that if the emulator was built with support for <seealso - marker="#system_flag_dirty_cpu_schedulers_online">dirty schedulers</seealso>, - changing the number of schedulers online can also change the number of dirty - CPU schedulers online. For example, if there are 12 schedulers and all are - online, and 6 dirty CPU schedulers, all online as well, and <c>system_flag/2</c> - is used to set the number of schedulers online to 6, then the number of dirty - CPU schedulers online is automatically decreased by half as well, down to 3. - Similarly, the number of dirty CPU schedulers online increases proportionally - to increases in the number of schedulers online.</p> - <p>For more information see, - <seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>, - and - <seealso marker="#system_info_schedulers_online">erlang:system_info(schedulers_online)</seealso>. - </p> + <p>If the emulator was built with support for + <seealso marker="#system_flag_dirty_cpu_schedulers_online"> + dirty schedulers</seealso>, + changing the number of schedulers online can also change the + number of dirty CPU schedulers online. For example, if 12 + schedulers and 6 dirty CPU schedulers are online, and + <c>system_flag/2</c> is used to set the number of schedulers + online to 6, then the number of dirty CPU schedulers online + is automatically decreased by half as well, down to 3. + Similarly, the number of dirty CPU schedulers online increases + proportionally to increases in the number of schedulers online.</p> + <p>For more information, see + <seealso marker="#system_info_schedulers"> + <c>erlang:system_info(schedulers)</c></seealso> and + <seealso marker="#system_info_schedulers_online"> + <c>erlang:system_info(schedulers_online)</c></seealso>.</p> </desc> </func> + <func> - <name name="system_flag" arity="2" clause_i="11"/> - <fsummary>Set system flag trace_control_word</fsummary> + <name name="system_flag" arity="2" clause_i="14"/> + <fsummary>Set system flag trace_control_word.</fsummary> <desc> - <p>Sets the value of the node's trace control word to - <c><anno>TCW</anno></c>. <c><anno>TCW</anno></c> should be an unsigned integer. For - more information see documentation of the - <seealso marker="erts:match_spec#set_tcw">set_tcw</seealso> - function in the match specification documentation in the - ERTS User's Guide.</p> + <p>Sets the value of the node trace control word to + <c><anno>TCW</anno></c>, which is to be an unsigned integer. + For more information, see function + <seealso marker="erts:match_spec#set_tcw"><c>set_tcw</c></seealso> + in section "Match Specifications in Erlang" in the + User's Guide.</p> <p>Returns the old value of the flag.</p> </desc> </func> + + <func> + <name name="system_flag" arity="2" clause_i="15" + anchor="system_flag_time_offset"/> + <fsummary>Finalize the time offset.</fsummary> + <desc> + <p> + Finalizes the <seealso marker="#time_offset/0">time offset</seealso> + when <seealso marker="time_correction#Single_Time_Warp_Mode">single + time warp mode</seealso> is used. If another time warp mode + is used, the time offset state is left unchanged.</p> + <p>Returns the old state identifier, that is:</p> + <list> + <item><p>If <c>preliminary</c> is returned, finalization was + performed and the time offset is now final.</p> + </item> + <item><p>If <c>final</c> is returned, the time offset was + already in the final state. This either because another + <c>erlang:system_flag(time_offset, finalize)</c> call or + because <seealso marker="time_correction#No_Time_Warp_Mode">no + time warp mode</seealso> is used.</p> + </item> + <item><p>If <c>volatile</c> is returned, the time offset + cannot be finalized because + <seealso marker="time_correction#Multi_Time_Warp_Mode">multi-time + warp mode</seealso> is used.</p> + </item> + </list> + </desc> + </func> + + <func> + <name name="system_info" arity="1" clause_i="76"/> + <fsummary>System info overview.</fsummary> + <desc> + <p>Returns information about the current system. + The documentation of this function is broken into the following + sections in order to make it easier to navigate.</p> + <taglist> + <tag><seealso marker="#system_info_allocator"> + <c>Memory Allocation</c></seealso></tag> + <item> + <p> + <seealso marker="#system_info_allocated_areas"><c>allocated_areas</c></seealso>, + <seealso marker="#system_info_allocator"><c>allocator</c></seealso>, + <seealso marker="#system_info_alloc_util_allocators"><c>alloc_util_allocators</c></seealso>, + <seealso marker="#system_info_allocator_sizes"><c>allocator_sizes</c></seealso>, + <seealso marker="#system_info_elib_malloc"><c>elib_malloc</c></seealso> + </p> + </item> + <tag><seealso marker="#system_info_cpu_topology"> + <c>CPU Topology</c></seealso></tag> + <item> + <p> + <seealso marker="#system_info_cpu_topology"><c>cpu_topology</c></seealso>, + <seealso marker="#system_info_logical_processors"><c>logical_processors</c></seealso>, + <seealso marker="#system_info_update_cpu_info"><c>update_cpu_info</c></seealso> + </p> + </item> + <tag><seealso marker="#system_info_process"> + <c>Process Information</c></seealso></tag> + <item> + <p> + <seealso marker="#system_info_fullsweep_after"><c>fullsweep_after</c></seealso>, + <seealso marker="#system_info_garbage_collection"><c>garbage_collection</c></seealso>, + <seealso marker="#system_info_heap_sizes"><c>heap_sizes</c></seealso>, + <seealso marker="#system_info_heap_type"><c>heap_type</c></seealso>, + <seealso marker="#system_info_max_heap_size"><c>max_heap_size</c></seealso>, + <seealso marker="#system_info_message_queue_data"><c>message_queue_data</c></seealso>, + <seealso marker="#system_info_min_heap_size"><c>min_heap_size</c></seealso>, + <seealso marker="#system_info_min_bin_vheap_size"><c>min_bin_vheap_size</c></seealso>, + <seealso marker="#system_info_procs"><c>procs</c></seealso> + </p> + </item> + <tag><seealso marker="#system_info_limits"> + <c>System Limits</c></seealso></tag> + <item> + <p> + <seealso marker="#system_info_atom_count"><c>atom_count</c></seealso>, + <seealso marker="#system_info_atom_limit"><c>atom_limit</c></seealso>, + <seealso marker="#system_info_ets_count"><c>ets_count</c></seealso>, + <seealso marker="#system_info_ets_limit"><c>ets_limit</c></seealso>, + <seealso marker="#system_info_port_count"><c>port_count</c></seealso>, + <seealso marker="#system_info_port_limit"><c>port_limit</c></seealso>, + <seealso marker="#system_info_process_count"><c>process_count</c></seealso>, + <seealso marker="#system_info_process_limit"><c>process_limit</c></seealso> + </p> + </item> + <tag><seealso marker="#system_info_time"> + <c>System Time</c></seealso></tag> + <item> + <p> + <seealso marker="#system_info_end_time"><c>end_time</c></seealso>, + <seealso marker="#system_info_os_monotonic_time_source"><c>os_monotonic_time_source</c></seealso>, + <seealso marker="#system_info_os_system_time_source"><c>os_system_time_source</c></seealso>, + <seealso marker="#system_info_start_time"><c>start_time</c></seealso>, + <seealso marker="#system_info_time_correction"><c>time_correction</c></seealso>, + <seealso marker="#system_info_time_offset"><c>time_offset</c></seealso>, + <seealso marker="#system_info_time_warp_mode"><c>time_warp_mode</c></seealso>, + <seealso marker="#system_info_tolerant_timeofday"><c>tolerant_timeofday</c></seealso> + </p> + </item> + <tag><seealso marker="#system_info_scheduler"> + <c>Scheduler Information</c></seealso></tag> + <item> + <p> + <seealso marker="#system_info_dirty_cpu_schedulers"><c>dirty_cpu_schedulers</c></seealso>, + <seealso marker="#system_info_dirty_cpu_schedulers_online"><c>dirty_cpu_schedulers_online</c></seealso>, + <seealso marker="#system_info_dirty_io_schedulers"><c>dirty_io_schedulers</c></seealso>, + <seealso marker="#system_info_multi_scheduling"><c>multi_scheduling</c></seealso>, + <seealso marker="#system_info_multi_scheduling_blockers"><c>multi_scheduling_blockers</c></seealso>, + <seealso marker="#system_info_normal_multi_scheduling_blockers"><c>normal_multi_scheduling_blockers</c></seealso>, + <seealso marker="#system_info_scheduler_bind_type"><c>scheduler_bind_type</c></seealso>, + <seealso marker="#system_info_scheduler_bindings"><c>scheduler_bindings</c></seealso>, + <seealso marker="#system_info_scheduler_id"><c>scheduler_id</c></seealso>, + <seealso marker="#system_info_schedulers"><c>schedulers</c></seealso>, + <seealso marker="#system_info_smp_support"><c>smp_support</c></seealso>, + <seealso marker="#system_info_threads"><c>threads</c></seealso>, + <seealso marker="#system_info_thread_pool_size"><c>thread_pool_size</c></seealso> + </p> + </item> + <tag><seealso marker="#system_info_dist"> + <c>Distribution Information</c></seealso></tag> + <item> + <p> + <seealso marker="#system_info_creation"><c>creation</c></seealso>, + <seealso marker="#system_info_delayed_node_table_gc"><c>delayed_node_table_gc</c></seealso>, + <seealso marker="#system_info_dist"><c>dist</c></seealso>, + <seealso marker="#system_info_dist_buf_busy_limit"><c>dist_buf_busy_limit</c></seealso>, + <seealso marker="#system_info_dist_ctrl"><c>dist_ctrl</c></seealso> + </p> + </item> + <tag><seealso marker="#system_info_misc"> + <c>System Information</c></seealso></tag> + <item> + <p> + <seealso marker="#system_info_build_type"><c>build_type</c></seealso>, + <seealso marker="#system_info_c_compiler_used"><c>c_compiler_used</c></seealso>, + <seealso marker="#system_info_check_io"><c>check_io</c></seealso>, + <seealso marker="#system_info_compat_rel"><c>compat_rel</c></seealso>, + <seealso marker="#system_info_debug_compiled"><c>debug_compiled</c></seealso>, + <seealso marker="#system_info_driver_version"><c>driver_version</c></seealso>, + <seealso marker="#system_info_dynamic_trace"><c>dynamic_trace</c></seealso>, + <seealso marker="#system_info_dynamic_trace_probes"><c>dynamic_trace_probes</c></seealso>, + <seealso marker="#system_info_info"><c>info</c></seealso>, + <seealso marker="#system_info_kernel_poll"><c>kernel_poll</c></seealso>, + <seealso marker="#system_info_loaded"><c>loaded</c></seealso>, + <seealso marker="#system_info_machine"><c>machine</c></seealso>, + <seealso marker="#system_info_modified_timing_level"><c>modified_timing_level</c></seealso>, + <seealso marker="#system_info_nif_version"><c>nif_version</c></seealso>, + <seealso marker="#system_info_otp_release"><c>otp_release</c></seealso>, + <seealso marker="#system_info_port_parallelism"><c>port_parallelism</c></seealso>, + <seealso marker="#system_info_system_version"><c>system_version</c></seealso>, + <seealso marker="#system_info_system_architecture"><c>system_architecture</c></seealso>, + <seealso marker="#system_info_trace_control_word"><c>trace_control_word</c></seealso>, + <seealso marker="#system_info_version"><c>version</c></seealso>, + <seealso marker="#system_info_wordsize"><c>wordsize</c></seealso> + </p> + </item> + </taglist> + </desc> + </func> + <func> - <name name="system_info" arity="1" clause_i="1"/> - <name name="system_info" arity="1" clause_i="2"/> - <name name="system_info" arity="1" clause_i="3"/> - <name name="system_info" arity="1" clause_i="4"/> - <name name="system_info" arity="1" clause_i="5"/> + <name name="system_info" arity="1" clause_i="1" + anchor="system_info_allocator"/> <!-- allocated_areas --> + <name name="system_info" arity="1" clause_i="2"/> <!-- allocator --> + <name name="system_info" arity="1" clause_i="3"/> <!-- {allocator, _} --> + <name name="system_info" arity="1" clause_i="4"/> <!-- alloc_util_allocators --> + <name name="system_info" arity="1" clause_i="5"/> <!-- {allocator_sizes, _} --> + <name name="system_info" arity="1" clause_i="27"/> <!-- elib_malloc --> + <fsummary>Information about the system allocators.</fsummary> <type variable="Allocator" name_i="2"/> <type variable="Version" name_i="2"/> <type variable="Features" name_i="2"/> <type variable="Settings" name_i="2"/> <type variable="Alloc" name_i="3"/> - <fsummary>Information about the allocators of the system</fsummary> <desc> - <p> - Returns various information about the - <marker id="system_info_allocator_tags">allocators</marker> of the - current system (emulator) as specified by + <marker id="system_info_allocator_tags"></marker> + <p>Returns various information about the memory allocators + of the current system (emulator) as specified by <c><anno>Item</anno></c>:</p> + <marker id="system_info_allocated_areas"></marker> <taglist> - <tag><marker id="system_info_allocated_areas"><c>allocated_areas</c></marker></tag> + <tag><marker id="system_info_allocated_areas"/> + <c>allocated_areas</c></tag> <item> <p>Returns a list of tuples with information about miscellaneous allocated memory areas.</p> - <p>Each tuple contains an atom describing type of memory as - first element and amount of allocated memory in bytes as - second element. In those cases when there is information - present about allocated and used memory, a third element - is present. This third element contains the amount of + <p>Each tuple contains an atom describing the type of + memory as first element and the amount of allocated + memory in bytes as second element. When information + about allocated and used memory is present, also a + third element is present, containing the amount of used memory in bytes.</p> <p><c>erlang:system_info(allocated_areas)</c> is intended - for debugging, and the content is highly implementation - dependent. The content of the results will therefore - change when needed without prior notice.</p> - <p><em>Note:</em> The sum of these values is <em>not</em> + for debugging, and the content is highly + implementation-dependent. The content of the results + therefore changes when needed without prior notice.</p> + <p>Notice that the sum of these values is <em>not</em> the total amount of memory allocated by the emulator. Some values are part of other values, and some memory - areas are not part of the result. If you are interested - in the total amount of memory allocated by the emulator - see <seealso marker="#memory/0">erlang:memory/0,1</seealso>.</p> + areas are not part of the result. For information about + the total amount of memory allocated by the emulator, see + <seealso marker="#memory/0"> + <c>erlang:memory/0,1</c></seealso>.</p> </item> - <tag><marker id="system_info_allocator"><c>allocator</c></marker></tag> + <tag><marker id="system_info_allocator"/> + <c>allocator</c></tag> <item> - <p>Returns <c>{<anno>Allocator</anno>, <anno>Version</anno>, <anno>Features</anno>, <anno>Settings</anno>}.</c></p> - <p>Explanation:</p> + <p>Returns <c>{<anno>Allocator</anno>, <anno>Version</anno>, + <anno>Features</anno>, <anno>Settings</anno></c>, where:</p> <list type="bulleted"> <item> - <p><c><anno>Allocator</anno></c> corresponds to the <c>malloc()</c> - implementation used. If <c><anno>Allocator</anno></c> equals + <p><c><anno>Allocator</anno></c> corresponds to the + <c>malloc()</c> implementation used. If + <c><anno>Allocator</anno></c> equals <c>undefined</c>, the <c>malloc()</c> implementation - used could not be identified. Currently - <c>glibc</c> can be identified.</p> + used cannot be identified. <c>glibc</c> can be + identified.</p> </item> <item> - <p><c><anno>Version</anno></c> is a list of integers (but not a - string) representing the version of + <p><c><anno>Version</anno></c> is a list of integers + (but not a string) representing the version of the <c>malloc()</c> implementation used.</p> </item> <item> - <p><c><anno>Features</anno></c> is a list of atoms representing - allocation features used.</p> + <p><c><anno>Features</anno></c> is a list of atoms + representing the allocation features used.</p> </item> <item> - <p><c><anno>Settings</anno></c> is a list of subsystems, their - configurable parameters, and used values. Settings - may differ between different combinations of + <p><c><anno>Settings</anno></c> is a list of subsystems, + their configurable parameters, and used values. Settings + can differ between different combinations of platforms, allocators, and allocation features. Memory sizes are given in bytes.</p> </item> </list> <p>See also "System Flags Effecting erts_alloc" in - <seealso marker="erts:erts_alloc#flags">erts_alloc(3)</seealso>.</p> - </item> - <tag><marker id="system_info_alloc_util_allocators"><c>alloc_util_allocators</c></marker></tag> - <item> - <p>Returns a list of the names of all allocators - using the ERTS internal <c>alloc_util</c> framework - as atoms. For more information see the - <seealso marker="erts:erts_alloc#alloc_util">"the - alloc_util framework" section in the - erts_alloc(3)</seealso> documentation. - </p> + <seealso marker="erts:erts_alloc#flags"> + <c>erts_alloc(3)</c></seealso>.</p> </item> - <tag><marker id="system_info_allocator_tuple"><c>{allocator, <anno>Alloc</anno>}</c></marker></tag> + <tag><marker id="system_info_allocator_tuple"></marker> + <c>{allocator, <anno>Alloc</anno>}</c></tag> <item> <p>Returns information about the specified allocator. - As of erts version 5.6.1 the return value is a list - of <c>{instance, InstanceNo, InstanceInfo}</c> tuples - where <c>InstanceInfo</c> contains information about - a specific instance of the allocator. As of erts version - 5.10.4 the returned list when calling - <c>erlang:system_info({allocator, mseg_alloc})</c> also - include an <c>{erts_mmap, _}</c> tuple as one element - in the list. - If <c><anno>Alloc</anno></c> is not a recognized allocator, - <c>undefined</c> is returned. If <c><anno>Alloc</anno></c> is disabled, + As from ERTS 5.6.1, the return value is a list + of <c>{instance, InstanceNo, InstanceInfo}</c> tuples, + where <c>InstanceInfo</c> contains information about + a specific instance of the allocator. + If <c><anno>Alloc</anno></c> is not a + recognized allocator, <c>undefined</c> is returned. + If <c><anno>Alloc</anno></c> is disabled, <c>false</c> is returned.</p> - <p><em>Note:</em> The information returned is highly - implementation dependent and may be changed, or removed + <p>Notice that the information returned is highly + implementation-dependent and can be changed or removed at any time without prior notice. It was initially intended as a tool when developing new allocators, but - since it might be of interest for others it has been + as it can be of interest for others it has been briefly documented.</p> <p>The recognized allocators are listed in - <seealso marker="erts:erts_alloc">erts_alloc(3)</seealso>. - After reading the <c>erts_alloc(3)</c> documentation, - the returned information - should more or less speak for itself. But it can be worth + <seealso marker="erts:erts_alloc"><c>erts_alloc(3)</c></seealso>. + Information about super carriers can be obtained from + ERTS 8.0 with <c>{allocator, erts_mmap}</c> or from + ERTS 5.10.4; the returned list when calling with + <c>{allocator, mseg_alloc}</c> also includes an + <c>{erts_mmap, _}</c> tuple as one element in the list.</p> + <p>After reading the <c>erts_alloc(3)</c> documentation, + the returned information + more or less speaks for itself, but it can be worth explaining some things. Call counts are presented by two - values. The first value is giga calls, and the second - value is calls. <c>mbcs</c>, and <c>sbcs</c> are - abbreviations for, respectively, multi-block carriers, and - single-block carriers. Sizes are presented in bytes. When - it is not a size that is presented, it is the amount of - something. Sizes and amounts are often presented by three - values, the first is current value, the second is maximum - value since the last call to - <c>erlang:system_info({allocator, Alloc})</c>, and - the third is maximum value since the emulator was started. - If only one value is present, it is the current value. + values, the first value is giga calls, and the second + value is calls. <c>mbcs</c> and <c>sbcs</c> denote + multi-block carriers, and single-block carriers, + respectively. Sizes are presented in bytes. When a + size is not presented, it is the amount of something. + Sizes and amounts are often presented by three values:</p> + <list type="bulleted"> + <item>The first is the current value.</item> + <item>The second is the maximum value since the last call + to <c>erlang:system_info({allocator, Alloc})</c>.</item> + <item>The third is the maximum value since the emulator + was started.</item> + </list> + <p>If only one value is present, it is the current value. <c>fix_alloc</c> memory block types are presented by two - values. The first value is memory pool size and - the second value used memory size.</p> + values. The first value is the memory pool size and + the second value is the used memory size.</p> </item> - <tag><marker id="system_info_allocator_sizes"><c>{allocator_sizes, <anno>Alloc</anno>}</c></marker></tag> + <tag><marker id="system_info_alloc_util_allocators"/> + <c>alloc_util_allocators</c></tag> <item> - <p>Returns various size information for the specified - allocator. The information returned is a subset of the - information returned by - <seealso marker="#system_info_allocator_tuple">erlang:system_info({allocator, <anno>Alloc</anno>})</seealso>. - </p> + <p>Returns a list of the names of all allocators using + the ERTS internal <c>alloc_util</c> framework + as atoms. For more information, see section + <seealso marker="erts:erts_alloc#alloc_util">The + alloc_util framework</seealso> + in <c>erts_alloc(3)</c>.</p> + </item> + <tag><marker id="system_info_allocator_sizes"/> + <c>{allocator_sizes, <anno>Alloc</anno>}</c></tag> + <item> + <p>Returns various size information for the specified + allocator. The information returned is a subset of the + information returned by + <seealso marker="#system_info_allocator_tuple"> + <c>erlang:system_info({allocator, + <anno>Alloc</anno>})</c></seealso>.</p> + </item> + <tag><marker id="system_info_elib_malloc"/> + <c>elib_malloc</c></tag> + <item> + <p>This option will be removed in a future release. + The return value will always be <c>false</c>, as the + <c>elib_malloc</c> allocator has been removed.</p> </item> </taglist> </desc> </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" + anchor="system_info_cpu_topology"/> <!-- cpu_topology --> + <name name="system_info" arity="1" clause_i="13"/> <!-- {cpu_topology, _} --> + <name name="system_info" arity="1" clause_i="38"/> <!-- logical_processors --> + <name name="system_info" arity="1" clause_i="73"/> <!-- update_cpu_info --> + <fsummary>Information about the CPU topology of the system.</fsummary> <type name="cpu_topology"/> <type name="level_entry"/> <type_desc name="cpu_topology"> - <marker id="system_info_cpu_topology"></marker> All <c><anno>LevelEntry</anno></c>s of a list must contain the same <c><anno>LevelTag</anno></c>, except on the top level where both <c>node</c> and - <c>processor</c> <c><anno>LevelTag</anno></c>s may co-exist. + <c>processor</c> <c><anno>LevelTag</anno></c>s can coexist. </type_desc> <type_desc name="level_entry"> - <c>{<anno>LevelTag</anno>, <anno>SubLevel</anno>} == {<anno>LevelTag</anno>, [], <anno>SubLevel</anno>}</c> + <c>{<anno>LevelTag</anno>, + <anno>SubLevel</anno>} == {<anno>LevelTag</anno>, [], + <anno>SubLevel</anno>}</c> </type_desc> <type name="level_tag"/> <type_desc name="level_tag"> - More <c><anno>LevelTag</anno></c>s may be introduced in the future. + More <c><anno>LevelTag</anno></c>s can be introduced in a + future release. </type_desc> <type name="sub_level"/> <type name="info_list"/> <type_desc name="info_list"> - The <c>info_list()</c> may be extended in the future. + The <c>info_list()</c> can be extended in a future release. </type_desc> - <fsummary>Information about the CPU topology of the system</fsummary> <desc> - <p>Returns various information about the - <marker id="system_info_cpu_topology_tags">CPU topology</marker> - of the current system - (emulator) as specified by <c><anno>Item</anno></c>:</p> + <marker id="system_info_cpu_topology_tags"></marker> + <p>Returns various information about the CPU topology of + the current system (emulator) as specified by + <c><anno>Item</anno></c>:</p> <taglist> - <tag><c>cpu_topology</c></tag> - <item> - <p>Returns the <c><anno>CpuTopology</anno></c> which currently is used by the - emulator. The CPU topology is used when binding schedulers - to logical processors. The CPU topology used is the - <seealso marker="erlang#system_info_cpu_topology_defined">user - defined CPU topology</seealso> if such exists; otherwise, the - <seealso marker="erlang#system_info_cpu_topology_detected">automatically - detected CPU topology</seealso> if such exists. If no CPU topology - exists, <c>undefined</c> is returned.</p> - <p><c>node</c> refers to NUMA (non-uniform memory access) - nodes, and <c>thread</c> refers to hardware threads - (e.g. Intels hyper-threads).</p> - <p>A level in the <c><anno>CpuTopology</anno></c> term can be omitted if - only one entry exists and the <c><anno>InfoList</anno></c> is empty. - </p> - <p><c>thread</c> can only be a sub level to <c>core</c>. - <c>core</c> can be a sub level to either <c>processor</c> - or <c>node</c>. <c>processor</c> can either be on the - top level or a sub level to <c>node</c>. <c>node</c> - can either be on the top level or a sub level to - <c>processor</c>. That is, NUMA nodes can be processor - internal or processor external. A CPU topology can - consist of a mix of processor internal and external - NUMA nodes, as long as each logical CPU belongs to one - and only one NUMA node. Cache hierarchy is not part of - the <c><anno>CpuTopology</anno></c> type yet, but will be in the - future. Other things may also make it into the CPU - topology in the future. In other words, expect the - <c><anno>CpuTopology</anno></c> type to change. - </p> + <tag><marker id="system_info_cpu_topology"/> + <c>cpu_topology</c></tag> + <item> + <p>Returns the <c><anno>CpuTopology</anno></c> currently used by + the emulator. The CPU topology is used when binding schedulers + to logical processors. The CPU topology used is the + <seealso marker="erlang#system_info_cpu_topology_defined"> + user-defined CPU topology</seealso>, + if such exists, otherwise the + <seealso marker="erlang#system_info_cpu_topology_detected"> + automatically detected CPU topology</seealso>, + if such exists. If no CPU topology + exists, <c>undefined</c> is returned.</p> + <p><c>node</c> refers to Non-Uniform Memory Access (NUMA) + nodes. <c>thread</c> refers to hardware threads + (for example, Intel hyper-threads).</p> + <p>A level in term <c><anno>CpuTopology</anno></c> can be + omitted if only one entry exists and + <c><anno>InfoList</anno></c> is empty.</p> + <p><c>thread</c> can only be a sublevel to <c>core</c>. + <c>core</c> can be a sublevel to <c>processor</c> + or <c>node</c>. <c>processor</c> can be on the + top level or a sublevel to <c>node</c>. <c>node</c> + can be on the top level or a sublevel to + <c>processor</c>. That is, NUMA nodes can be processor + internal or processor external. A CPU topology can + consist of a mix of processor internal and external + NUMA nodes, as long as each logical CPU belongs to + <em>one</em> NUMA node. Cache hierarchy is not part of + the <c><anno>CpuTopology</anno></c> type, but will be in a + future release. Other things can also make it into the CPU + topology in a future release. So, expect the + <c><anno>CpuTopology</anno></c> type to change.</p> + </item> + <tag><c>{cpu_topology, defined}</c></tag> + <item> + <marker id="system_info_cpu_topology_defined"></marker> + <p>Returns the user-defined <c><anno>CpuTopology</anno></c>. + For more information, see command-line flag + <seealso marker="erts:erl#+sct"><c>+sct</c></seealso> in + <c>erl(1)</c> and argument + <seealso marker="#system_info_cpu_topology"> + <c>cpu_topology</c></seealso>.</p> + </item> + <tag><c>{cpu_topology, detected}</c></tag> + <item> + <marker id="system_info_cpu_topology_detected"></marker> + <p>Returns the automatically detected + <c><anno>CpuTopology</anno>y</c>. The + emulator detects the CPU topology on some newer + Linux, Solaris, FreeBSD, and Windows systems. + On Windows system with more than 32 logical processors, + the CPU topology is not detected.</p> + <p>For more information, see argument + <seealso marker="#system_info_cpu_topology"> + <c>cpu_topology</c></seealso>.</p> </item> - <tag><marker id="system_info_cpu_topology_defined"><c>{cpu_topology, defined}</c></marker></tag> + <tag><c>{cpu_topology, used}</c></tag> <item> - <p>Returns the user defined <c><anno>CpuTopology</anno></c>. For more - information see the documentation of - the <c>erl</c> <seealso marker="erts:erl#+sct">+sct</seealso> command - line flag, and the documentation of the - <seealso marker="#system_info_cpu_topology">cpu_topology</seealso> - argument. - </p> + <p>Returns <c><anno>CpuTopology</anno></c> used by the emulator. + For more information, see argument + <seealso marker="#system_info_cpu_topology"> + <c>cpu_topology</c></seealso>.</p> </item> - <tag><marker id="system_info_cpu_topology_detected"><c>{cpu_topology, detected}</c></marker></tag> + <tag><marker id="system_info_logical_processors"/> + <c>logical_processors</c></tag> <item> - <p>Returns the automatically detected <c><anno>CpuTopology</anno></c>. The - emulator currently only detects the CPU topology on some newer - Linux, Solaris, FreeBSD, and Windows systems. On Windows system with - more than 32 logical processors the CPU topology is not detected. - </p> - <p>For more information see the documentation of the - <seealso marker="#system_info_cpu_topology">cpu_topology</seealso> - argument. - </p> + <p>Returns the detected number of logical processors configured + in the system. The return value is either an integer, or + the atom <c>unknown</c> if the emulator cannot + detect the configured logical processors.</p> </item> - <tag><c>{cpu_topology, used}</c></tag> + <tag><marker id="system_info_logical_processors_available"/> + <c>logical_processors_available</c></tag> <item> - <p>Returns the <c><anno>CpuTopology</anno></c> which is used by the - emulator. For more information see the - documentation of the - <seealso marker="#system_info_cpu_topology">cpu_topology</seealso> - argument. - </p> + <p>Returns the detected number of logical processors available + to the Erlang runtime system. The return value is either an + integer, or the atom <c>unknown</c> if the emulator + cannot detect the available logical processors. The number + of available logical processors is less than or equal to + the number of <seealso marker="#system_info_logical_processors_online"> + logical processors online</seealso>.</p> + </item> + <tag><marker id="system_info_logical_processors_online"/> + <c>logical_processors_online</c></tag> + <item> + <p>Returns the detected number of logical processors online on + the system. The return value is either an integer, + or the atom <c>unknown</c> if the emulator cannot + detect logical processors online. The number of logical + processors online is less than or equal to the number of + <seealso marker="#system_info_logical_processors">logical processors + configured</seealso>.</p> + </item> + <tag><marker id="system_info_update_cpu_info"/> + <c>update_cpu_info</c></tag> + <item> + <p>The runtime system rereads the CPU information available + and updates its internally stored information about the + <seealso marker="#system_info_cpu_topology_detected">detected + CPU topology</seealso> and the number of logical processors + <seealso marker="#system_info_logical_processors">configured</seealso>, + <seealso marker="#system_info_logical_processors_online">online</seealso>, + and <seealso marker="#system_info_logical_processors_available"> + available</seealso>.</p> + <p>If the CPU information has changed since the last time + it was read, the atom <c>changed</c> is returned, otherwise + the atom <c>unchanged</c>. If the CPU information has changed, + you probably want to + <seealso marker="#system_flag_schedulers_online">adjust the + number of schedulers online</seealso>. You typically want + to have as many schedulers online as + <seealso marker="#system_info_logical_processors_available">logical + processors available</seealso>.</p> </item> </taglist> </desc> </func> + <func> - <name name="system_info" arity="1" clause_i="6"/> - <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="14"/> - <name name="system_info" arity="1" clause_i="15"/> - <name name="system_info" arity="1" clause_i="16"/> - <name name="system_info" arity="1" clause_i="17"/> - <name name="system_info" arity="1" clause_i="18"/> - <name name="system_info" arity="1" clause_i="19"/> - <name name="system_info" arity="1" clause_i="20"/> - <name name="system_info" arity="1" clause_i="21"/> - <name name="system_info" arity="1" clause_i="22"/> - <name name="system_info" arity="1" clause_i="23"/> - <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="27"/> - <name name="system_info" arity="1" clause_i="28"/> - <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="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="36"/> - <name name="system_info" arity="1" clause_i="37"/> - <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"/> - <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"/> - <name name="system_info" arity="1" clause_i="45"/> - <name name="system_info" arity="1" clause_i="46"/> - <name name="system_info" arity="1" clause_i="47"/> - <name name="system_info" arity="1" clause_i="48"/> - <name name="system_info" arity="1" clause_i="49"/> - <name name="system_info" arity="1" clause_i="50"/> - <name name="system_info" arity="1" clause_i="51"/> - <name name="system_info" arity="1" clause_i="52"/> - <name name="system_info" arity="1" clause_i="53"/> - <name name="system_info" arity="1" clause_i="54"/> - <name name="system_info" arity="1" clause_i="55"/> - <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> + <name name="system_info" arity="1" clause_i="31" + anchor="system_info_process"/> <!-- fullsweep_after --> + <name name="system_info" arity="1" clause_i="32"/> <!-- garbage_collection --> + <name name="system_info" arity="1" clause_i="33"/> <!-- heap_sizes --> + <name name="system_info" arity="1" clause_i="34"/> <!-- heap_type --> + <name name="system_info" arity="1" clause_i="40"/> <!-- max_heap_size --> + <name name="system_info" arity="1" clause_i="41"/> <!-- message_queue_data --> + <name name="system_info" arity="1" clause_i="42"/> <!-- min_heap_size --> + <name name="system_info" arity="1" clause_i="43"/> <!-- min_bin_vheap_size --> + <name name="system_info" arity="1" clause_i="57"/> <!-- procs --> + <fsummary>Information about the default process heap settings.</fsummary> + <type name="message_queue_data"/> + <type name="max_heap_size"/> + <desc> + <marker id="system_info_process_tags"/> + <p>Returns information about the default process heap settings:</p> <taglist> - <tag><c>allocated_areas</c>, <c>allocator</c>, - <c>alloc_util_allocators</c>, <c>allocator_sizes</c></tag> + <tag><marker id="system_info_fullsweep_after"/> + <c>fullsweep_after</c></tag> <item> - <p>See <seealso marker="#system_info_allocator_tags">above</seealso>.</p> + <p>Returns <c>{fullsweep_after, integer() >= 0}</c>, which is + the <c>fullsweep_after</c> garbage collection setting used + by default. For more information, see + <c>garbage_collection</c> described below.</p> </item> - <tag><c>build_type</c></tag> + <tag><marker id="system_info_garbage_collection"/> + <c>garbage_collection</c></tag> <item> - <p>Returns an atom describing the build type of the runtime - system. This is normally the atom <c>opt</c> for optimized. - Other possible return values are <c>debug</c>, <c>purify</c>, - <c>quantify</c>, <c>purecov</c>, <c>gcov</c>, <c>valgrind</c>, - <c>gprof</c>, and <c>lcnt</c>. Possible return values - may be added and/or removed at any time without prior notice. - </p> + <p>Returns a list describing the default garbage collection + settings. A process spawned on the local node by a + <c>spawn</c> or <c>spawn_link</c> uses these + garbage collection settings. The default settings can be + changed by using + <seealso marker="#system_flag/2"> + <c>erlang:system_flag/2</c></seealso>. + <seealso marker="#spawn_opt/4"><c>spawn_opt/2,3,4</c></seealso> + can spawn a process that does not use the default + settings.</p> </item> - <tag><c>c_compiler_used</c></tag> + <tag><marker id="system_info_heap_sizes"/> + <c>heap_sizes</c></tag> <item> - <p>Returns a two-tuple describing the C compiler used when - compiling the runtime system. The first element is an - atom describing the name of the compiler, or <c>undefined</c> - if unknown. The second element is a term describing the - version of the compiler, or <c>undefined</c> if unknown. - </p> + <p>Returns a list of integers representing valid heap sizes + in words. All Erlang heaps are sized from sizes in this + list.</p> </item> - <tag><c>check_io</c></tag> + <tag><marker id="system_info_heap_type"/> + <c>heap_type</c></tag> <item> - <p>Returns a list containing miscellaneous information - regarding the emulators internal I/O checking. Note, - the content of the returned list may vary between - platforms and over time. The only thing guaranteed is - that a list is returned.</p> + <p>Returns the heap type used by the current emulator. One + heap type exists:</p> + <taglist> + <tag><c>private</c></tag> + <item> + Each process has a heap reserved for its use and no + references between heaps of different processes are + allowed. Messages passed between processes are copied + between heaps. + </item> + </taglist> </item> - <tag><c>compat_rel</c></tag> + <tag><marker id="system_info_max_heap_size"/> + <c>max_heap_size</c></tag> + <item> + <p>Returns <c>{max_heap_size, <anno>MaxHeapSize</anno>}</c>, + where <c><anno>MaxHeapSize</anno></c> is the current + system-wide maximum heap size settings for spawned processes. + This setting can be set using the command-line flags + <seealso marker="erl#+hmax"><c>+hmax</c></seealso>, + <seealso marker="erl#+hmaxk"><c>+hmaxk</c></seealso> and + <seealso marker="erl#+hmaxel"><c>+hmaxel</c></seealso> in + <c>erl(1)</c>. It can also be changed at runtime using + <seealso marker="#system_flag_max_heap_size"> + <c>erlang:system_flag(max_heap_size, MaxHeapSize)</c></seealso>. + For more details about the <c>max_heap_size</c> process flag, + see <seealso marker="#process_flag_max_heap_size"> + <c>process_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> + </item> + <tag><marker id="system_info_message_queue_data"/> + <c>message_queue_data</c></tag> + <item> + <p>Returns the default value of the <c>message_queue_data</c> + process flag, which is either <c>off_heap</c> or <c>on_heap</c>. + This default is set by command-line argument + <seealso marker="erl#+hmqd"><c>+hmqd</c></seealso> in + <c>erl(1)</c>. For more information on the + <c>message_queue_data</c> process flag, see documentation of + <seealso marker="#process_flag_message_queue_data"> + <c>process_flag(message_queue_data, MQD)</c></seealso>.</p> + </item> + <tag><marker id="system_info_min_heap_size"/> + <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_min_bin_vheap_size"/> + <c>min_bin_vheap_size</c></tag> + <item> + <p>Returns <c>{min_bin_vheap_size, + <anno>MinBinVHeapSize</anno>}</c>, where + <c><anno>MinBinVHeapSize</anno></c> is the current system-wide + minimum binary virtual heap size for spawned processes.</p> + </item> + <tag><marker id="system_info_procs"/> + <c>procs</c></tag> <item> - <p>Returns the compatibility mode of the local node as - an integer. The integer returned represents the - Erlang/OTP release which the current emulator has been - set to be backward compatible with. The compatibility - mode can be configured at startup by using the command - line flag <c>+R</c>, see - <seealso marker="erts:erl#compat_rel">erl(1)</seealso>.</p> + <p>Returns a binary containing a string of process and port + information formatted as in Erlang crash dumps. For more + information, see section <seealso marker="erts:crash_dump"> + How to interpret the Erlang crash dumps</seealso> + in the User's Guide.</p> </item> - <tag><c>cpu_topology</c></tag> + </taglist> + </desc> + </func> + + <func> + <name name="system_info" arity="1" clause_i="6" anchor="system_info_limits"/> <!-- atom_count --> + <name name="system_info" arity="1" clause_i="7"/> <!-- atom_limit --> + <name name="system_info" arity="1" clause_i="29"/> <!-- ets_count --> + <name name="system_info" arity="1" clause_i="30"/> <!-- ets_limit --> + <name name="system_info" arity="1" clause_i="53"/> <!-- port_count --> + <name name="system_info" arity="1" clause_i="54"/> <!-- port_limit --> + <name name="system_info" arity="1" clause_i="55"/> <!-- process_count --> + <name name="system_info" arity="1" clause_i="56"/> <!-- process_limit --> + <fsummary>Information about various system limits.</fsummary> + <desc> + <marker id="system_info_limits"/> + <p>Returns information about the current system + (emulator) limits as specified by <c><anno>Item</anno></c>:</p> + <taglist> + <tag><marker id="system_info_atom_count"/> + <c>atom_count</c></tag> <item> - <p>See <seealso marker="#system_info_cpu_topology_tags">above</seealso>.</p> + <p>Returns the number of atoms currently existing at the + local node. The value is given as an integer.</p> </item> - <tag><c>creation</c></tag> + <tag><marker id="system_info_atom_limit"/> + <c>atom_limit</c></tag> <item> - <p>Returns the creation of the local node as an integer. - The creation is changed when a node is restarted. The - creation of a node is stored in process identifiers, port - identifiers, and references. This makes it (to some - extent) possible to distinguish between identifiers from - different incarnations of a node. Currently valid - creations are integers in the range 1..3, but this may - (probably will) change in the future. If the node is not - alive, 0 is returned.</p> + <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>debug_compiled</c></tag> + <tag><marker id="system_info_ets_count"/> + <c>ets_count</c></tag> <item> - <p>Returns <c>true</c> if the emulator has been debug - compiled; otherwise, <c>false</c>. - </p> + <p>Returns the number of ETS tables currently existing at the + local node.</p> </item> - <tag><marker id="system_info_dirty_cpu_schedulers"><c>dirty_cpu_schedulers</c></marker></tag> + <tag><marker id="system_info_ets_limit"/> + <c>ets_limit</c></tag> <item> - <p>Returns the number of dirty CPU scheduler threads used by - the emulator. Dirty CPU schedulers execute CPU-bound - native functions such as NIFs, linked-in driver code, and BIFs - that cannot be managed cleanly by the emulator's normal schedulers. - </p> - <p>The number of dirty CPU scheduler threads is determined at emulator - boot time and cannot be changed after that. The number of dirty CPU - scheduler threads online can however be changed at any time. The number of - dirty CPU schedulers can be set on startup by passing - the <seealso marker="erts:erl#+SDcpu">+SDcpu</seealso> or - <seealso marker="erts:erl#+SDPcpu">+SDPcpu</seealso> command line flags, - see <seealso marker="erts:erl#+SDcpu">erl(1)</seealso>. - </p> - <p><em>Note that the dirty schedulers functionality is experimental</em>, and - that you have to enable support for dirty schedulers when building OTP in - order to try out the functionality.</p> - <p>See also <seealso marker="#system_flag_dirty_cpu_schedulers_online">erlang:system_flag(dirty_cpu_schedulers_online, DirtyCPUSchedulersOnline)</seealso>, - <seealso marker="#system_info_dirty_cpu_schedulers_online">erlang:system_info(dirty_cpu_schedulers_online)</seealso>, - <seealso marker="#system_info_dirty_io_schedulers">erlang:system_info(dirty_io_schedulers)</seealso>, - <seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>, - <seealso marker="#system_info_schedulers_online">erlang:system_info(schedulers_online)</seealso>, and - <seealso marker="#system_flag_schedulers_online">erlang:system_flag(schedulers_online, SchedulersOnline)</seealso>.</p> - </item> - <tag><marker id="system_info_dirty_cpu_schedulers_online"><c>dirty_cpu_schedulers_online</c></marker></tag> - <item> - <p>Returns the number of dirty CPU schedulers online. The return value - satisfies the following relationship: - <c><![CDATA[1 <= DirtyCPUSchedulersOnline <= N]]></c>, where <c>N</c> is - the lesser of the return values of <c>erlang:system_info(dirty_cpu_schedulers)</c> and - <c>erlang:system_info(schedulers_online)</c>. - </p> - <p>The number of dirty CPU schedulers online can be set on startup by passing - the <seealso marker="erts:erl#+SDcpu">+SDcpu</seealso> command line flag, see - <seealso marker="erts:erl#+SDcpu">erl(1)</seealso>. - </p> - <p><em>Note that the dirty schedulers functionality is experimental</em>, and - that you have to enable support for dirty schedulers when building OTP in - order to try out the functionality.</p> - <p>For more information, see - <seealso marker="#system_info_dirty_cpu_schedulers">erlang:system_info(dirty_cpu_schedulers)</seealso>, - <seealso marker="#system_info_dirty_io_schedulers">erlang:system_info(dirty_io_schedulers)</seealso>, - <seealso marker="#system_info_schedulers_online">erlang:system_info(schedulers_online)</seealso>, and - <seealso marker="#system_flag_dirty_cpu_schedulers_online">erlang:system_flag(dirty_cpu_schedulers_online, DirtyCPUSchedulersOnline)</seealso>. - </p> + <p>Returns the limit for number of ETS tables. This limit is + <seealso marker="stdlib:ets#max_ets_tables">partially obsolete</seealso> + and number of tables are only limited by available memory.</p> </item> - <tag><marker id="system_info_dirty_io_schedulers"><c>dirty_io_schedulers</c></marker></tag> + <tag><marker id="system_info_port_count"/><c>port_count</c></tag> <item> - <p>Returns the number of dirty I/O schedulers as an integer. Dirty I/O schedulers - execute I/O-bound native functions such as NIFs and linked-in driver code that - cannot be managed cleanly by the emulator's normal schedulers. - </p> - <p>This value can be set on startup by passing - the <seealso marker="erts:erl#+SDio">+SDio</seealso> command line flag, see - <seealso marker="erts:erl#+SDio">erl(1)</seealso>. - </p> - <p><em>Note that the dirty schedulers functionality is experimental</em>, and - that you have to enable support for dirty schedulers when building OTP in - order to try out the functionality.</p> - <p>For more information, see - <seealso marker="#system_info_dirty_cpu_schedulers">erlang:system_info(dirty_cpu_schedulers)</seealso>, - <seealso marker="#system_info_dirty_cpu_schedulers_online">erlang:system_info(dirty_cpu_schedulers_online)</seealso>, and - <seealso marker="#system_flag_dirty_cpu_schedulers_online">erlang:system_flag(dirty_cpu_schedulers_online, DirtyCPUSchedulersOnline)</seealso>. - </p> + <p>Returns the number of ports currently existing at the + local node. The value is given as an integer. This is + the same value as returned by + <c>length(erlang:ports())</c>, but more efficient.</p> </item> - <tag><c>dist</c></tag> + <tag><marker id="system_info_port_limit"/> + <c>port_limit</c></tag> <item> - <p>Returns a binary containing a string of distribution - information formatted as in Erlang crash dumps. For more - information see the <seealso marker="erts:crash_dump">"How to interpret the Erlang crash dumps"</seealso> - chapter in the ERTS User's Guide.</p> + <p>Returns the maximum number of simultaneously existing + ports at the local node as an integer. This limit can be + configured at startup by using command-line flag + <seealso marker="erl#+Q"><c>+Q</c></seealso> in <c>erl(1)</c>.</p> </item> - <tag><marker id="system_info_dist_buf_busy_limit"><c>dist_buf_busy_limit</c></marker></tag> + <tag><marker id="system_info_process_count"/> + <c>process_count</c></tag> <item> - <p>Returns the value of the distribution buffer busy limit - in bytes. This limit can be set on startup by passing the - <seealso marker="erts:erl#+zdbbl">+zdbbl</seealso> command line - flag to <c>erl</c>.</p> + <p>Returns the number of processes currently existing at the + local node. The value is given as an integer. This is + the same value as returned by + <c>length(processes())</c>, but more efficient.</p> </item> - <tag><c>dist_ctrl</c></tag> + <tag><marker id="system_info_process_limit"/> + <c>process_limit</c></tag> <item> - <p>Returns a list of tuples - <c>{Node, ControllingEntity}</c>, one entry for each - connected remote node. The <c><anno>Node</anno></c> is the name of the - node and the <c><anno>ControllingEntity</anno></c> is the port or pid - responsible for the communication to that node. More - specifically, the <c><anno>ControllingEntity</anno></c> for nodes - connected via TCP/IP (the normal case) is the socket - actually used in communication with the specific node.</p> + <p>Returns the maximum number of simultaneously existing + processes at the local node. The value is given as an + integer. This limit can be configured at startup by using + command-line flag <seealso marker="erl#+P"><c>+P</c></seealso> + in <c>erl(1)</c>.</p> </item> - <tag><c>driver_version</c></tag> - <item> - <p>Returns a string containing the erlang driver version - used by the runtime system. It will be on the form - <seealso marker="erts:erl_driver#version_management">"<major ver>.<minor ver>"</seealso>.</p> + </taglist> + </desc> + </func> + + <func> + <name name="system_info" arity="1" clause_i="26" + anchor="system_info_time"/> <!-- end_time --> + <name name="system_info" arity="1" clause_i="50"/> <!-- os_monotonic_time_source --> + <name name="system_info" arity="1" clause_i="51"/> <!-- os_system_time_source --> + <name name="system_info" arity="1" clause_i="63"/> <!-- start_time --> + <name name="system_info" arity="1" clause_i="68"/> <!-- time_correction --> + <name name="system_info" arity="1" clause_i="69"/> <!-- time_offset --> + <name name="system_info" arity="1" clause_i="70"/> <!-- time_warp_mode --> + <name name="system_info" arity="1" clause_i="71"/> <!-- tolerant_timeofday --> + <fsummary>Information about system time.</fsummary> + <desc> + <marker id="system_info_time_tags"/> + <p>Returns information about the current system + (emulator) time as specified by <c><anno>Item</anno></c>:</p> + <taglist> + <tag><marker id="system_info_end_time"/><c>end_time</c></tag> + <item> + <p>The last <seealso marker="#monotonic_time/0">Erlang monotonic + time</seealso> in <c>native</c> + <seealso marker="#type_time_unit">time unit</seealso> that + can be represented internally in the current Erlang runtime system + instance. The time between the + <seealso marker="#system_info_start_time">start time</seealso> and + the end time is at least a quarter of a millennium.</p> + </item> + <tag><marker id="system_info_os_monotonic_time_source"/> + <c>os_monotonic_time_source</c></tag> + <item> + <p>Returns a list containing information about the source of + <seealso marker="erts:time_correction#OS_Monotonic_Time">OS + monotonic time</seealso> that is used by the runtime system.</p> + <p>If <c>[]</c> is returned, no OS monotonic time is + available. The list contains two-tuples with <c>Key</c>s + as first element, and <c>Value</c>s as second element. The + order of these tuples is undefined. The following + tuples can be part of the list, but more tuples can be + introduced in the future:</p> + <taglist> + <tag><c>{function, Function}</c></tag> + <item><p><c>Function</c> is the name of the function + used. This tuple always exists if OS monotonic time is + available to the runtime system.</p> + </item> + <tag><c>{clock_id, ClockId}</c></tag> + <item><p>This tuple only exists if <c>Function</c> + can be used with different clocks. <c>ClockId</c> + corresponds to the clock identifier used when calling + <c>Function</c>.</p> + </item> + <tag><c>{resolution, OsMonotonicTimeResolution}</c></tag> + <item><p>Highest possible + <seealso marker="time_correction#Time_Resolution"> + resolution</seealso> + of current OS monotonic time source as parts per + second. If no resolution information can be retrieved + from the OS, <c>OsMonotonicTimeResolution</c> is + set to the resolution of the time unit of + <c>Function</c>s return value. That is, the actual + resolution can be lower than + <c>OsMonotonicTimeResolution</c>. Notice that + the resolution does not say anything about the + <seealso marker="time_correction#Time_Accuracy"> + accuracy</seealso> or whether the + <seealso marker="time_correction#Time_Precision"> + precision</seealso> aligns with the resolution. You do, + however, know that the precision is not better than + <c>OsMonotonicTimeResolution</c>.</p> + </item> + <tag><c>{extended, Extended}</c></tag> + <item><p><c>Extended</c> equals <c>yes</c> if + the range of time values has been extended; + otherwise <c>Extended</c> equals <c>no</c>. The + range must be extended if <c>Function</c> + returns values that wrap fast. This typically + is the case when the return value is a 32-bit value.</p> + </item> + <tag><c>{parallel, Parallel}</c></tag> + <item><p><c>Parallel</c> equals <c>yes</c> if + <c>Function</c> is called in parallel from multiple + threads. If it is not called in parallel, because + calls must be serialized, <c>Parallel</c> equals + <c>no</c>.</p> + </item> + <tag><c>{time, OsMonotonicTime}</c></tag> + <item><p><c>OsMonotonicTime</c> equals current OS + monotonic time in <c>native</c> + <seealso marker="#type_time_unit">time unit</seealso>.</p> + </item> + </taglist> </item> - <tag><c>dynamic_trace</c></tag> - <item> - <p>Returns an atom describing the dynamic trace framework - compiled into the virtual machine. It can currently be either - <c>dtrace</c>, <c>systemtap</c> or <c>none</c>. For a - commercial or standard build, this is always <c>none</c>, - the other return values indicate a custom configuration - (e.g. <c>./configure --with-dynamic-trace=dtrace</c>). See - the <seealso marker="runtime_tools:dyntrace">dyntrace - </seealso> manual page and the - <c>README.dtrace</c>/<c>README.systemtap</c> files in the - Erlang source code top directory for more information - about dynamic tracing.</p> - </item> - <tag><c>dynamic_trace_probes</c></tag> - <item> - <p>Returns a <c>boolean()</c> indicating if dynamic trace probes - (either dtrace or systemtap) are built into the - emulator. This can only be <c>true</c> if the virtual - machine was built for dynamic tracing - (i.e. <c>system_info(dynamic_trace)</c> returns - <c>dtrace</c> or <c>systemtap</c>).</p> - </item> - <tag><c>elib_malloc</c></tag> - <item> - <p>This option will be removed in a future release. - The return value will always be <c>false</c> since - the elib_malloc allocator has been removed.</p> + <tag><marker id="system_info_os_system_time_source"/> + <c>os_system_time_source</c></tag> + <item> + <p>Returns a list containing information about the source of + <seealso marker="erts:time_correction#OS_System_Time">OS + system time</seealso> that is used by the runtime system.</p> + <p>The list contains two-tuples with <c>Key</c>s + as first element, and <c>Value</c>s as second element. The + order if these tuples is undefined. The following + tuples can be part of the list, but more tuples can be + introduced in the future:</p> + <taglist> + <tag><c>{function, Function}</c></tag> + <item><p><c>Function</c> is the name of the funcion used.</p> + </item> + <tag><c>{clock_id, ClockId}</c></tag> + <item><p>Exists only if <c>Function</c> + can be used with different clocks. <c>ClockId</c> + corresponds to the clock identifier used when calling + <c>Function</c>.</p> + </item> + <tag><c>{resolution, OsSystemTimeResolution}</c></tag> + <item><p>Highest possible + <seealso marker="time_correction#Time_Resolution"> + resolution</seealso> + of current OS system time source as parts per + second. If no resolution information can be retrieved + from the OS, <c>OsSystemTimeResolution</c> is + set to the resolution of the time unit of + <c>Function</c>s return value. That is, the actual + resolution can be lower than + <c>OsSystemTimeResolution</c>. Notice that + the resolution does not say anything about the + <seealso marker="time_correction#Time_Accuracy"> + accuracy</seealso> or whether the + <seealso marker="time_correction#Time_Precision"> + precision</seealso> do align with the resolution. You do, + however, know that the precision is not better than + <c>OsSystemTimeResolution</c>.</p> + </item> + <tag><c>{parallel, Parallel}</c></tag> + <item><p><c>Parallel</c> equals <c>yes</c> if + <c>Function</c> is called in parallel from multiple + threads. If it is not called in parallel, because + calls needs to be serialized, <c>Parallel</c> equals + <c>no</c>.</p> + </item> + <tag><c>{time, OsSystemTime}</c></tag> + <item><p><c>OsSystemTime</c> equals current OS + system time in <c>native</c> + <seealso marker="#type_time_unit">time unit</seealso>.</p> + </item> + </taglist> </item> - <tag><marker id="system_info_eager_check_io"><c>eager_check_io</c></marker></tag> + <tag><marker id="system_info_start_time"/><c>start_time</c></tag> <item> - <p> - Returns the value of the <c>erl</c> - <seealso marker="erl#+secio">+secio</seealso> command line - flag which is either <c>true</c> or <c>false</c>. See the - documentation of the command line flag for information about - the different values. - </p> + <p>The <seealso marker="#monotonic_time/0">Erlang monotonic + time</seealso> in <c>native</c> + <seealso marker="#type_time_unit">time unit</seealso> at the + time when current Erlang runtime system instance started.</p> + <p>See also <seealso marker="#system_info_end_time"> + <c>erlang:system_info(end_time)</c></seealso>.</p> </item> - <tag><c>ets_limit</c></tag> + <tag><marker id="system_info_time_correction"/> + <c>time_correction</c></tag> <item> - <p>Returns the maximum number of ETS tables allowed. This limit - can be increased on startup by passing the <seealso - marker="erts:erl#+e">+e</seealso> command line flag to - <c>erl</c> or by setting the environment variable - <c>ERL_MAX_ETS_TABLES</c> before starting the Erlang runtime - system.</p> + <p>Returns a boolean value indicating whether + <seealso marker="time_correction#Time_Correction"> + time correction</seealso> is enabled or not.</p> </item> - <tag><c>fullsweep_after</c></tag> + <tag><marker id="system_info_time_offset"/> + <c>time_offset</c></tag> <item> - <p>Returns <c>{fullsweep_after, integer() >= 0}</c> which is the - <c>fullsweep_after</c> garbage collection setting used - by default. For more information see - <c>garbage_collection</c> described below.</p> + <p>Returns the state of the time offset:</p> + <taglist> + <tag><c>preliminary</c></tag> + <item> + <p>The time offset is preliminary, and will be changed + and finalized later. The preliminary time offset + is used during the preliminary phase of the + <seealso marker="time_correction#Single_Time_Warp_Mode"> + single time warp mode</seealso>.</p> + </item> + <tag><c>final</c></tag> + <item> + <p>The time offset is final. This either because + <seealso marker="time_correction#No_Time_Warp_Mode"> + no time warp mode</seealso> is used, or because the time + offset have been finalized when + <seealso marker="time_correction#Single_Time_Warp_Mode"> + single time warp mode</seealso> is used.</p> + </item> + <tag><c>volatile</c></tag> + <item> + <p>The time offset is volatile. That is, it can + change at any time. This is because + <seealso marker="time_correction#Multi_Time_Warp_Mode"> + multi-time warp mode</seealso> is used.</p> + </item> + </taglist> </item> - <tag><c>garbage_collection</c></tag> + <tag><marker id="system_info_time_warp_mode"/> + <c>time_warp_mode</c></tag> <item> - <p>Returns a list describing the default garbage collection - settings. A process spawned on the local node by a - <c>spawn</c> or <c>spawn_link</c> will use these - garbage collection settings. The default settings can be - changed by use of - <seealso marker="#system_flag/2">system_flag/2</seealso>. - <seealso marker="#spawn_opt/4">spawn_opt/4</seealso> - can spawn a process that does not use the default - settings.</p> + <p>Returns a value identifying the + <seealso marker="time_correction#Time_Warp_Modes"> + time warp mode</seealso> that is used:</p> + <taglist> + <tag><c>no_time_warp</c></tag> + <item>The <seealso marker="time_correction#No_Time_Warp_Mode"> + no time warp mode</seealso> is used. + </item> + <tag><c>single_time_warp</c></tag> + <item>The <seealso marker="time_correction#Single_Time_Warp_Mode"> + single time warp mode</seealso> is used. + </item> + <tag><c>multi_time_warp</c></tag> + <item>The <seealso marker="time_correction#Multi_Time_Warp_Mode"> + multi-time warp mode</seealso> is used. + </item> + </taglist> </item> - <tag><c>heap_sizes</c></tag> + <tag><marker id="system_info_tolerant_timeofday"/> + <c>tolerant_timeofday</c></tag> <item> - <p>Returns a list of integers representing valid heap sizes - in words. All Erlang heaps are sized from sizes in this - list.</p> + <p>Returns whether a pre ERTS 7.0 backwards compatible + compensation for sudden changes of system time is <c>enabled</c> + or <c>disabled</c>. Such compensation is <c>enabled</c> when the + <seealso marker="#system_info_time_offset">time offset</seealso> + is <c>final</c>, and + <seealso marker="#system_info_time_correction"> + time correction</seealso> is enabled.</p> </item> - <tag><c>heap_type</c></tag> + </taglist> + </desc> + </func> + + <func> + <name name="system_info" arity="1" clause_i="17" + anchor="system_info_scheduler"/> <!-- dirty_cpu_schedulers --> + <name name="system_info" arity="1" clause_i="18"/> <!-- dirty_cpu_schedulers_online --> + <name name="system_info" arity="1" clause_i="19"/> <!-- dirty_io_schedulers --> + <name name="system_info" arity="1" clause_i="45"/> <!-- multi_scheduling --> + <name name="system_info" arity="1" clause_i="46"/> <!-- multi_scheduling_blockers --> + <name name="system_info" arity="1" clause_i="49"/> <!-- normal_multi_scheduling_blockers --> + <name name="system_info" arity="1" clause_i="58"/> <!-- scheduler_bind_type --> + <name name="system_info" arity="1" clause_i="59"/> <!-- scheduler_bindings --> + <name name="system_info" arity="1" clause_i="60"/> <!-- scheduler_id --> + <name name="system_info" arity="1" clause_i="61"/> <!-- schedulers --> + <name name="system_info" arity="1" clause_i="62"/> <!-- smp_support --> + <name name="system_info" arity="1" clause_i="66"/> <!-- threads --> + <name name="system_info" arity="1" clause_i="67"/> <!-- thread_pool_size --> + <fsummary>Information about system schedulers.</fsummary> + <desc> + <marker id="system_info_scheduler_tags"/> + <p>Returns information about schedulers, scheduling and threads in the + current system as specified by <c><anno>Item</anno></c>:</p> + <taglist> + <tag><marker id="system_info_dirty_cpu_schedulers"/> + <c>dirty_cpu_schedulers</c></tag> <item> - <p>Returns the heap type used by the current emulator. - Currently only the following heap type exists:</p> + <p>Returns the number of dirty CPU scheduler threads used by + the emulator. Dirty CPU schedulers execute CPU-bound + native functions, such as NIFs, linked-in driver code, + and BIFs that cannot be managed cleanly by the normal + emulator schedulers.</p> + <p>The number of dirty CPU scheduler threads is determined + at emulator boot time and cannot be changed after that. + However, the number of dirty CPU scheduler threads online + can be changed at any time. The number of dirty CPU + schedulers can be set at startup by passing + command-line flag + <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>See also + <seealso marker="#system_flag_dirty_cpu_schedulers_online"> + <c>erlang:system_flag(dirty_cpu_schedulers_online, + DirtyCPUSchedulersOnline)</c></seealso>, + <seealso marker="#system_info_dirty_cpu_schedulers_online"> + <c>erlang:system_info(dirty_cpu_schedulers_online)</c></seealso>, + <seealso marker="#system_info_dirty_io_schedulers"> + <c>erlang:system_info(dirty_io_schedulers)</c></seealso>, + <seealso marker="#system_info_schedulers"> + <c>erlang:system_info(schedulers)</c></seealso>, + <seealso marker="#system_info_schedulers_online"> + <c>erlang:system_info(schedulers_online)</c></seealso>, and + <seealso marker="#system_flag_schedulers_online"> + <c>erlang:system_flag(schedulers_online, + SchedulersOnline)</c></seealso>.</p> + </item> + <tag><marker id="system_info_dirty_cpu_schedulers_online"/> + <c>dirty_cpu_schedulers_online</c></tag> + <item> + <p>Returns the number of dirty CPU schedulers online. + The return value satisfies + <c><![CDATA[1 <= DirtyCPUSchedulersOnline <= N]]></c>, + where <c>N</c> is the smallest of the return values of + <c>erlang:system_info(dirty_cpu_schedulers)</c> and + <c>erlang:system_info(schedulers_online)</c>.</p> + <p>The number of dirty CPU schedulers online can be set at + startup by passing command-line flag + <seealso marker="erts:erl#+SDcpu"><c>+SDcpu</c></seealso> in + <c>erl(1)</c>.</p> + <p>For more information, see + <seealso marker="#system_info_dirty_cpu_schedulers"> + <c>erlang:system_info(dirty_cpu_schedulers)</c></seealso>, + <seealso marker="#system_info_dirty_io_schedulers"> + <c>erlang:system_info(dirty_io_schedulers)</c></seealso>, + <seealso marker="#system_info_schedulers_online"> + <c>erlang:system_info(schedulers_online)</c></seealso>, and + <seealso marker="#system_flag_dirty_cpu_schedulers_online"> + <c>erlang:system_flag(dirty_cpu_schedulers_online, + DirtyCPUSchedulersOnline)</c></seealso>.</p> + </item> + <tag><marker id="system_info_dirty_io_schedulers"/> + <c>dirty_io_schedulers</c></tag> + <item> + <p>Returns the number of dirty I/O schedulers as an integer. + Dirty I/O schedulers execute I/O-bound native functions, + such as NIFs and linked-in driver code, which cannot be + managed cleanly by the normal emulator schedulers.</p> + <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>For more information, see + <seealso marker="#system_info_dirty_cpu_schedulers"> + <c>erlang:system_info(dirty_cpu_schedulers)</c></seealso>, + <seealso marker="#system_info_dirty_cpu_schedulers_online"> + <c>erlang:system_info(dirty_cpu_schedulers_online)</c></seealso>, + and <seealso marker="#system_flag_dirty_cpu_schedulers_online"> + <c>erlang:system_flag(dirty_cpu_schedulers_online, + DirtyCPUSchedulersOnline)</c></seealso>.</p> + </item> + <tag><marker id="system_info_multi_scheduling"/> + <c>multi_scheduling</c></tag> + <item> + <p>Returns one of the following:</p> <taglist> - <tag><c>private</c></tag> + <tag><c>disabled</c></tag> + <item> + <p>The emulator has been started with only one scheduler thread.</p> + </item> + <tag><c>blocked</c></tag> + <item> + <p>The emulator has more than one scheduler thread, + but all scheduler threads except one are blocked. + That is, only one scheduler thread schedules + Erlang processes and executes Erlang code.</p> + </item> + <tag><c>blocked_normal</c></tag> + <item> + <p>The emulator has more than one scheduler thread, + but all normal scheduler threads except one are + blocked. Notice that dirty schedulers are not + blocked, and can schedule Erlang processes and + execute native code.</p> + </item> + <tag><c>enabled</c></tag> <item> - <p>Each process has a heap reserved for its use and no - references between heaps of different processes are - allowed. Messages passed between processes are copied - between heaps.</p> + <p>The emulator has more than one scheduler thread, + and no scheduler threads are blocked. That is, + all available scheduler threads schedule + Erlang processes and execute Erlang code.</p> </item> </taglist> + <p>See also + <seealso marker="#system_flag_multi_scheduling"> + <c>erlang:system_flag(multi_scheduling, BlockState)</c></seealso>, + <seealso marker="#system_info_multi_scheduling_blockers"> + <c>erlang:system_info(multi_scheduling_blockers)</c></seealso>, + <seealso marker="#system_info_normal_multi_scheduling_blockers"> + <c>erlang:system_info(normal_multi_scheduling_blockers)</c></seealso>, + and <seealso marker="#system_info_schedulers"> + <c>erlang:system_info(schedulers)</c></seealso>.</p> + </item> + <tag><marker id="system_info_multi_scheduling_blockers"/> + <c>multi_scheduling_blockers</c></tag> + <item> + <p>Returns a list of <c><anno>Pid</anno></c>s when + multi-scheduling is blocked, otherwise the empty list is + returned. The <c><anno>Pid</anno></c>s in the list + represent all the processes currently + blocking multi-scheduling. A <c><anno>Pid</anno></c> occurs + only once in the list, even if the corresponding + process has blocked multiple times.</p> + <p>See also + <seealso marker="#system_flag_multi_scheduling"> + <c>erlang:system_flag(multi_scheduling, BlockState)</c></seealso>, + <seealso marker="#system_info_multi_scheduling"> + <c>erlang:system_info(multi_scheduling)</c></seealso>, + <seealso marker="#system_info_normal_multi_scheduling_blockers"> + <c>erlang:system_info(normal_multi_scheduling_blockers)</c></seealso>, + and <seealso marker="#system_info_schedulers"> + <c>erlang:system_info(schedulers)</c></seealso>.</p> + </item> + <tag><marker id="system_info_normal_multi_scheduling_blockers"/> + <c>normal_multi_scheduling_blockers</c></tag> + <item> + <p>Returns a list of <c><anno>Pid</anno></c>s when + normal multi-scheduling is blocked (that is, all normal schedulers + but one is blocked), otherwise the empty list is returned. + The <c><anno>Pid</anno></c>s in the list represent all the + processes currently blocking normal multi-scheduling. + A <c><anno>Pid</anno></c> occurs only once in the list, even if + the corresponding process has blocked multiple times.</p> + <p>See also + <seealso marker="#system_flag_multi_scheduling"> + <c>erlang:system_flag(multi_scheduling, BlockState)</c></seealso>, + <seealso marker="#system_info_multi_scheduling"> + <c>erlang:system_info(multi_scheduling)</c></seealso>, + <seealso marker="#system_info_multi_scheduling_blockers"> + <c>erlang:system_info(multi_scheduling_blockers)</c></seealso>, + and <seealso marker="#system_info_schedulers"> + <c>erlang:system_info(schedulers)</c></seealso>.</p> + </item> + <tag><marker id="system_info_scheduler_bind_type"/> + <c>scheduler_bind_type</c></tag> + <item> + <p>Returns information about how the user has requested + schedulers to be bound or not bound.</p> + <p>Notice that although a user has requested + schedulers to be bound, they can silently have failed + to bind. To inspect the scheduler bindings, call + <seealso marker="#system_info_scheduler_bindings"> + <c>erlang:system_info(scheduler_bindings)</c></seealso>.</p> + <p>For more information, see command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt</c></seealso> + in <c>erl(1)</c> and + <seealso marker="#system_info_scheduler_bindings"> + <c>erlang:system_info(scheduler_bindings)</c></seealso>.</p> + </item> + <tag><marker id="system_info_scheduler_bindings"/> + <c>scheduler_bindings</c></tag> + <item> + <p>Returns information about the currently used scheduler + bindings.</p> + <p>A tuple of a size equal to + <seealso marker="#system_info_schedulers"> + <c>erlang:system_info(schedulers)</c></seealso> + is returned. The tuple elements are integers + or the atom <c>unbound</c>. Logical processor identifiers + are represented as integers. The <c>N</c>th + element of the tuple equals the current binding for + the scheduler with the scheduler identifier equal to + <c>N</c>. For example, if the schedulers are bound, + <c>element(erlang:system_info(scheduler_id), + erlang:system_info(scheduler_bindings))</c> returns + the identifier of the logical processor that the calling + process is executing on.</p> + <p>Notice that only schedulers online can be bound to logical + processors.</p> + <p>For more information, see command-line argument + <seealso marker="erts:erl#+sbt"><c>+sbt</c></seealso> + in <c>erl(1)</c> and + <seealso marker="#system_info_schedulers_online"> + <c>erlang:system_info(schedulers_online)</c></seealso>.</p> + </item> + <tag><marker id="system_info_scheduler_id"/> + <c>scheduler_id</c></tag> + <item> + <p>Returns the scheduler ID (<c>SchedulerId</c>) of the + scheduler thread that the calling process is executing + on. <c><anno>SchedulerId</anno></c> is a positive integer, + where <c><![CDATA[1 <= SchedulerId <= + erlang:system_info(schedulers)]]></c>.</p> + <p>See also + <seealso marker="#system_info_schedulers"> + <c>erlang:system_info(schedulers)</c></seealso>.</p> </item> - <tag><c>info</c></tag> + <tag><marker id="system_info_schedulers"/> + <c>schedulers</c></tag> <item> - <p>Returns a binary containing a string of miscellaneous - system information formatted as in Erlang crash dumps. - For more information see the - <seealso marker="erts:crash_dump">"How to interpret the Erlang crash dumps"</seealso> chapter in the ERTS - User's Guide.</p> + <p>Returns the number of scheduler threads used by + the emulator. Scheduler threads online schedules Erlang + processes and Erlang ports, and execute Erlang code + and Erlang linked-in driver code.</p> + <p>The number of scheduler threads is determined at + emulator boot time and cannot be changed later. + However, the number of schedulers online can + be changed at any time.</p> + <p>See also + <seealso marker="#system_flag_schedulers_online"> + <c>erlang:system_flag(schedulers_online, + SchedulersOnline)</c></seealso>, + <seealso marker="#system_info_schedulers_online"> + <c>erlang:system_info(schedulers_online)</c></seealso>, + <seealso marker="#system_info_scheduler_id"> + <c>erlang:system_info(scheduler_id)</c></seealso>, + <seealso marker="#system_flag_multi_scheduling"> + <c>erlang:system_flag(multi_scheduling, BlockState)</c></seealso>, + <seealso marker="#system_info_multi_scheduling"> + <c>erlang:system_info(multi_scheduling)</c></seealso>, + <seealso marker="#system_info_normal_multi_scheduling_blockers"> + <c>erlang:system_info(normal_multi_scheduling_blockers)</c></seealso> + and <seealso marker="#system_info_multi_scheduling_blockers"> + <c>erlang:system_info(multi_scheduling_blockers)</c></seealso>. + </p> </item> - <tag><c>kernel_poll</c></tag> + <tag><marker id="system_info_schedulers_online"/> + <c>schedulers_online</c></tag> <item> - <p>Returns <c>true</c> if the emulator uses some kind of - kernel-poll implementation; otherwise, <c>false</c>.</p> + <p>Returns the number of schedulers online. The scheduler + identifiers of schedulers online satisfy the relationship + <c><![CDATA[1 <= SchedulerId <= + erlang:system_info(schedulers_online)]]></c>.</p> + <p>For more information, see + <seealso marker="#system_info_schedulers"> + <c>erlang:system_info(schedulers)</c></seealso> and + <seealso marker="#system_flag_schedulers_online"> + <c>erlang:system_flag(schedulers_online, + SchedulersOnline)</c></seealso>.</p> </item> - <tag><c>loaded</c></tag> + <tag><marker id="system_info_smp_support"/> + <c>smp_support</c></tag> <item> - <p>Returns a binary containing a string of loaded module - information formatted as in Erlang crash dumps. For more - information see the <seealso marker="erts:crash_dump">"How to interpret the Erlang crash dumps"</seealso> chapter - in the ERTS User's Guide.</p> + <p>Returns <c>true</c>.</p> </item> - <tag><marker id="logical_processors"><c>logical_processors</c></marker></tag> + <tag><marker id="system_info_threads"/> + <c>threads</c></tag> <item> - <p>Returns the detected number of logical processors configured - on the system. The return value is either an integer, or - the atom <c>unknown</c> if the emulator wasn't able to - detect logical processors configured. - </p> + <p>Returns <c>true</c>.</p> </item> - <tag><marker id="logical_processors_available"><c>logical_processors_available</c></marker></tag> + <tag><marker id="system_info_thread_pool_size"/> + <c>thread_pool_size</c></tag> <item> - <p>Returns the detected number of logical processors available to - the Erlang runtime system. The return value is either an - integer, or the atom <c>unknown</c> if the emulator wasn't - able to detect logical processors available. The number - of logical processors available is less than or equal to - the number of <seealso marker="#logical_processors_online">logical - processors online</seealso>. - </p> + <marker id="system_info_thread_pool_size"></marker> + <p>Returns the number of async threads in the async thread + pool used for asynchronous driver calls + (<seealso marker="erts:erl_driver#driver_async"> + <c>erl_driver:driver_async()</c></seealso>). + The value is given as an integer.</p> </item> - <tag><marker id="logical_processors_online"><c>logical_processors_online</c></marker></tag> + </taglist> + </desc> + </func> + + <func> + <name name="system_info" arity="1" clause_i="14" + anchor="system_info_dist"/> <!-- creation --> + <name name="system_info" arity="1" clause_i="16"/> <!-- delayed_node_table_gc --> + <name name="system_info" arity="1" clause_i="20"/> <!-- dist --> + <name name="system_info" arity="1" clause_i="21"/> <!-- dist_buf_busy_limit --> + <name name="system_info" arity="1" clause_i="22"/> <!-- dist_ctrl --> + <fsummary>Information about erlang distribution.</fsummary> + <desc> + <marker id="system_info_dist_tags"/> + <p>Returns information about Erlang Distribution in the + current system as specified by <c><anno>Item</anno></c>:</p> + <taglist> + <tag><marker id="system_info_creation"/> + <c>creation</c></tag> <item> - <p>Returns the detected number of logical processors online on - the system. The return value is either an integer, - or the atom <c>unknown</c> if the emulator wasn't able to - detect logical processors online. The number of logical - processors online is less than or equal to the number of - <seealso marker="#logical_processors">logical processors - configured</seealso>. - </p> + <p>Returns the creation of the local node as an integer. + The creation is changed when a node is restarted. The + creation of a node is stored in process identifiers, port + identifiers, and references. This makes it (to some + extent) possible to distinguish between identifiers from + different incarnations of a node. The valid + creations are integers in the range 1..3, but this will + probably change in a future release. If the node is not + alive, <c>0</c> is returned.</p> </item> - <tag><c>machine</c></tag> + <tag><marker id="system_info_delayed_node_table_gc"/> + <c>delayed_node_table_gc</c></tag> <item> - <p>Returns a string containing the Erlang machine name.</p> + <p>Returns the amount of time in seconds garbage collection + of an entry in a node table is delayed. This limit can be set + on startup by passing command-line flag + <seealso marker="erts:erl#+zdntgc"><c>+zdntgc</c></seealso> + to <c>erl(1)</c>. For more information, see the documentation of + the command-line flag.</p> </item> - <tag><c>min_heap_size</c></tag> + <tag><marker id="system_info_dist"/> + <c>dist</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> + <p>Returns a binary containing a string of distribution + information formatted as in Erlang crash dumps. For more + information, see section <seealso marker="erts:crash_dump"> + How to interpret the Erlang crash dumps</seealso> + in the User's Guide.</p> </item> - <tag><c>min_bin_vheap_size</c></tag> + <tag><marker id="system_info_dist_buf_busy_limit"/> + <c>dist_buf_busy_limit</c></tag> <item> - <p>Returns <c>{min_bin_vheap_size, <anno>MinBinVHeapSize</anno>}</c> where <c><anno>MinBinVHeapSize</anno></c> is the current system wide - minimum binary virtual heap size for spawned processes.</p> + <p>Returns the value of the distribution buffer busy limit + in bytes. This limit can be set at startup by passing + command-line flag + <seealso marker="erts:erl#+zdbbl"><c>+zdbbl</c></seealso> + to <c>erl(1)</c>.</p> </item> - <tag><c>modified_timing_level</c></tag> + <tag><marker id="system_info_dist_ctrl"/> + <c>dist_ctrl</c></tag> <item> - <p>Returns the modified timing level (an integer) if - modified timing has been enabled; otherwise, - <c>undefined</c>. See the <c>+T</c> command line flag - in the documentation of the - <seealso marker="erts:erl#+T">erl(1)</seealso> - command for more information on modified timing.</p> + <p>Returns a list of tuples + <c>{<anno>Node</anno>, <anno>ControllingEntity</anno>}</c>, + one entry for each connected remote node. + <c><anno>Node</anno></c> is the node name + and <c><anno>ControllingEntity</anno></c> is the port or process + identifier responsible for the communication to that node. + More specifically, <c><anno>ControllingEntity</anno></c> for + nodes connected through TCP/IP (the normal case) is the socket + used in communication with the specific node.</p> </item> - <tag><marker id="system_info_multi_scheduling"><c>multi_scheduling</c></marker></tag> + </taglist> + </desc> + </func> + + <func> + <!-- <name name="system_info" arity="1" clause_i="1"/> allocated_areas --> + <!-- <name name="system_info" arity="1" clause_i="2"/> allocated --> + <!-- <name name="system_info" arity="1" clause_i="3"/> {allocator, _} --> + <!-- <name name="system_info" arity="1" clause_i="4"/> alloc_util_allocators --> + <!-- <name name="system_info" arity="1" clause_i="5"/> {allocator_sizes, _} --> + <!-- <name name="system_info" arity="1" clause_i="6"/> atom_count --> + <!-- <name name="system_info" arity="1" clause_i="7"/> atom_limit --> + <name name="system_info" arity="1" clause_i="8" + anchor="system_info_misc"/> <!-- build_type --> + <name name="system_info" arity="1" clause_i="9"/> <!-- c_compiler_used --> + <name name="system_info" arity="1" clause_i="10"/> <!-- check_io --> + <name name="system_info" arity="1" clause_i="11"/> <!-- compat_rel --> + <!-- <name name="system_info" arity="1" clause_i="12"/> cpu_topology --> + <!-- <name name="system_info" arity="1" clause_i="13"/> {cpu_topology, _} --> + <!-- <name name="system_info" arity="1" clause_i="14"/> creation --> + <name name="system_info" arity="1" clause_i="15"/> <!-- debug_compiled --> + <!-- <name name="system_info" arity="1" clause_i="16"/> delayed_node_table_gc --> + <!-- <name name="system_info" arity="1" clause_i="17"/> dirty_cpu_schedulers --> + <!-- <name name="system_info" arity="1" clause_i="18"/> dirty_cpu_schedulers_online --> + <!-- <name name="system_info" arity="1" clause_i="19"/> dirty_io_schedulers --> + <!-- <name name="system_info" arity="1" clause_i="20"/> dist --> + <!-- <name name="system_info" arity="1" clause_i="21"/> dist_buf_busy_limit --> + <!-- <name name="system_info" arity="1" clause_i="22"/> dist_ctrl --> + <name name="system_info" arity="1" clause_i="23"/> <!-- driver_version --> + <name name="system_info" arity="1" clause_i="24"/> <!-- dynamic_trace --> + <name name="system_info" arity="1" clause_i="25"/> <!-- dynamic_trace_probes --> + <!-- <name name="system_info" arity="1" clause_i="26"/> end_time --> + <!-- <name name="system_info" arity="1" clause_i="27"/> elib_malloc --> + <!-- <name name="system_info" arity="1" clause_i="28"/> eager_check_io, removed --> + <!-- <name name="system_info" arity="1" clause_i="29"/> ets_count --> + <!-- <name name="system_info" arity="1" clause_i="30"/> ets_limit --> + <!-- <name name="system_info" arity="1" clause_i="31"/> fullsweep_after --> + <!-- <name name="system_info" arity="1" clause_i="32"/> garbage_collection --> + <!-- <name name="system_info" arity="1" clause_i="33"/> heap_sizes --> + <!-- <name name="system_info" arity="1" clause_i="34"/> heap_type --> + <name name="system_info" arity="1" clause_i="35"/> <!-- info --> + <name name="system_info" arity="1" clause_i="36"/> <!-- kernel_poll --> + <name name="system_info" arity="1" clause_i="37"/> <!-- loaded --> + <!-- <name name="system_info" arity="1" clause_i="38"/> logical_processors --> + <name name="system_info" arity="1" clause_i="39"/> <!-- machine --> + <!-- <name name="system_info" arity="1" clause_i="40"/> max_heap_size --> + <!-- <name name="system_info" arity="1" clause_i="41"/> message_queue_data --> + <!-- <name name="system_info" arity="1" clause_i="42"/> min_heap_size --> + <!-- <name name="system_info" arity="1" clause_i="43"/> min_bin_vheap_size --> + <name name="system_info" arity="1" clause_i="44"/> <!-- modified_timing_level --> + <!-- <name name="system_info" arity="1" clause_i="45"/> multi_scheduling --> + <!-- <name name="system_info" arity="1" clause_i="46"/> multi_scheduling_blockers --> + <name name="system_info" arity="1" clause_i="47"/> <!-- nif_version --> + <!-- n<name name="system_info" arity="1" clause_i="48"/> ormal_multi_scheduling_blockers --> + <name name="system_info" arity="1" clause_i="49"/> <!-- otp_release --> + <!-- <name name="system_info" arity="1" clause_i="50"/> os_monotonic_time_source --> + <!-- <name name="system_info" arity="1" clause_i="51"/> os_system_time_source --> + <name name="system_info" arity="1" clause_i="52"/> <!-- port_parallelism --> + <!-- <name name="system_info" arity="1" clause_i="53"/> port_count --> + <!-- <name name="system_info" arity="1" clause_i="54"/> port_limit --> + <!-- <name name="system_info" arity="1" clause_i="55"/> process_count --> + <!-- <name name="system_info" arity="1" clause_i="56"/> process_limit --> + <!-- <name name="system_info" arity="1" clause_i="57"/> procs --> + <!-- <name name="system_info" arity="1" clause_i="58"/> scheduler_bind_type --> + <!-- <name name="system_info" arity="1" clause_i="59"/> scheduler_bindings --> + <!-- <name name="system_info" arity="1" clause_i="60"/> scheduler_id --> + <!-- <name name="system_info" arity="1" clause_i="61"/> schedulers --> + <!-- <name name="system_info" arity="1" clause_i="62"/> smp_support --> + <!-- <name name="system_info" arity="1" clause_i="63"/> start_time --> + <name name="system_info" arity="1" clause_i="64"/> <!-- system_version --> + <name name="system_info" arity="1" clause_i="65"/> <!-- system_architecture --> + <!-- <name name="system_info" arity="1" clause_i="66"/> threads --> + <!-- <name name="system_info" arity="1" clause_i="67"/> thread_pool_size --> + <!-- <name name="system_info" arity="1" clause_i="68"/> time_correction --> + <!-- <name name="system_info" arity="1" clause_i="69"/> time_offset --> + <!-- <name name="system_info" arity="1" clause_i="70"/> time_warp_mode --> + <!-- <name name="system_info" arity="1" clause_i="71"/> tolerant_timeofday --> + <name name="system_info" arity="1" clause_i="72"/> <!-- trace_control_word --> + <!-- <name name="system_info" arity="1" clause_i="73"/> update_cpu_info --> + <name name="system_info" arity="1" clause_i="74"/> <!-- version --> + <name name="system_info" arity="1" clause_i="75"/> <!-- wordsize --> + <!-- <name name="system_info" arity="1" clause_i="76"/> overview --> + <fsummary>Information about the system.</fsummary> + <desc> + <marker id="system_info_misc_tags"/> + <p>Returns various information about the current system + (emulator) as specified by <c><anno>Item</anno></c>:</p> + <taglist> + <tag><marker id="system_info_build_type"/> + <c>build_type</c></tag> <item> - <p>Returns <c>disabled</c>, <c>blocked</c>, or <c>enabled</c>. - A description of the return values:</p> - <taglist> - <tag><c>disabled</c></tag> - <item> - <p>The emulator has only one scheduler thread. The - emulator does not have SMP support, or have been - started with only one scheduler thread.</p> - </item> - <tag><c>blocked</c></tag> - <item> - <p>The emulator has more than one scheduler thread, - but all scheduler threads but one have been blocked, - i.e., only one scheduler thread will schedule - Erlang processes and execute Erlang code.</p> - </item> - <tag><c>enabled</c></tag> - <item> - <p>The emulator has more than one scheduler thread, - and no scheduler threads have been blocked, i.e., - all available scheduler threads will schedule - Erlang processes and execute Erlang code.</p> - </item> - </taglist> - <p>See also <seealso marker="#system_flag_multi_scheduling">erlang:system_flag(multi_scheduling, BlockState)</seealso>, - <seealso marker="#system_info_multi_scheduling_blockers">erlang:system_info(multi_scheduling_blockers)</seealso>, and - <seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>.</p> + <p>Returns an atom describing the build type of the runtime + system. This is normally the atom <c>opt</c> for optimized. + Other possible return values are <c>debug</c>, <c>purify</c>, + <c>quantify</c>, <c>purecov</c>, <c>gcov</c>, <c>valgrind</c>, + <c>gprof</c>, and <c>lcnt</c>. Possible return values + can be added or removed at any time without prior notice.</p> </item> - <tag><marker id="system_info_multi_scheduling_blockers"><c>multi_scheduling_blockers</c></marker></tag> + <tag><marker id="system_info_c_compiler_used"/> + <c>c_compiler_used</c></tag> <item> - <p>Returns a list of <c><anno>PID</anno></c>s when multi-scheduling - is blocked; otherwise, the empty list. The <c><anno>PID</anno></c>s - in the list is <c><anno>PID</anno></c>s of the processes currently - blocking multi-scheduling. A <c><anno>PID</anno></c> will only be - present once in the list, even if the corresponding - process has blocked multiple times.</p> - <p>See also <seealso marker="#system_flag_multi_scheduling">erlang:system_flag(multi_scheduling, BlockState)</seealso>, - <seealso marker="#system_info_multi_scheduling">erlang:system_info(multi_scheduling)</seealso>, and - <seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>.</p> + <p>Returns a two-tuple describing the C compiler used when + compiling the runtime system. The first element is an + atom describing the name of the compiler, or <c>undefined</c> + if unknown. The second element is a term describing the + version of the compiler, or <c>undefined</c> if unknown.</p> </item> - <tag><c>nif_version</c></tag> + <tag><marker id="system_info_check_io"/> + <c>check_io</c></tag> <item> - <p>Returns a string containing the erlang NIF version - used by the runtime system. It will be on the form "<major ver>.<minor ver>".</p> + <p>Returns a list containing miscellaneous information + about the emulators internal I/O checking. Notice that + the content of the returned list can vary between + platforms and over time. It is only guaranteed + that a list is returned.</p> </item> - <tag><marker id="system_info_otp_release"><c>otp_release</c></marker></tag> + <tag><marker id="system_info_compat_rel"/> + <c>compat_rel</c></tag> <item> - <p>Returns a string containing the OTP release number of the - OTP release that the currently executing ERTS application is - part of.</p> - <p>As of OTP release 17, the OTP release number corresponds to - the major OTP version number. There is no - <c>erlang:system_info()</c> argument giving the exact OTP - version. This since the exact OTP version in the general case - is hard to determine. For more information see - <seealso marker="doc/system_principles:versions">the - documentation of versions in the system principles - guide</seealso>.</p> - </item> - <tag><marker id="system_info_port_parallelism"><c>port_parallelism</c></marker></tag> - <item><p>Returns the default port parallelism scheduling hint used. - For more information see the - <seealso marker="erl#+spp">+spp</seealso> command line argument - of <seealso marker="erl">erl(1)</seealso>.</p></item> - <tag><marker id="system_info_port_count"/><c>port_count</c></tag> + <p>Returns the compatibility mode of the local node as + an integer. The integer returned represents the + Erlang/OTP release that the current emulator has been + set to be backward compatible with. The compatibility + mode can be configured at startup by using command-line flag + <seealso marker="erts:erl#compat_rel"><c>+R</c></seealso> in + <c>erl(1)</c>.</p> + </item> + <tag><marker id="system_info_debug_compiled"/> + <c>debug_compiled</c></tag> <item> - <p>Returns the number of ports currently existing at - the local node as an integer. The same value as - <c>length(erlang:ports())</c> returns, but more efficient.</p> + <p>Returns <c>true</c> if the emulator has been + debug-compiled, otherwise <c>false</c>.</p> </item> - <tag><marker id="system_info_port_limit"><c>port_limit</c></marker></tag> + <tag><marker id="system_info_driver_version"/> + <c>driver_version</c></tag> <item> - <p>Returns the maximum number of simultaneously existing - ports at the local node as an integer. This limit - can be configured at startup by using the - <seealso marker="erl#+Q">+Q</seealso> - command line flag of - <seealso marker="erl">erl(1)</seealso>.</p> + <p>Returns a string containing the Erlang driver version + used by the runtime system. It has the form + <seealso marker="erts:erl_driver#version_management"> + "<major ver>.<minor ver>"</seealso>.</p> </item> - <tag><marker id="system_info_process_count"/><c>process_count</c></tag> + <tag><marker id="system_info_dynamic_trace"/> + <c>dynamic_trace</c></tag> + <item> + <p>Returns an atom describing the dynamic trace framework + compiled into the virtual machine. It can be + <c>dtrace</c>, <c>systemtap</c>, or <c>none</c>. For a + commercial or standard build, it is always <c>none</c>. + The other return values indicate a custom configuration + (for example, <c>./configure --with-dynamic-trace=dtrace</c>). + For more information about dynamic tracing, see + <seealso marker="runtime_tools:dyntrace"> + <c>dyntrace(3)</c></seealso> manual page and the + <c>README.dtrace</c>/<c>README.systemtap</c> files in the + Erlang source code top directory.</p> + </item> + <tag><marker id="system_info_dynamic_trace_probes"/> + <c>dynamic_trace_probes</c></tag> + <item> + <p>Returns a <c>boolean()</c> indicating if dynamic trace + probes (<c>dtrace</c> or <c>systemtap</c>) are built into + the emulator. This can only be <c>true</c> if the virtual + machine was built for dynamic tracing (that is, + <c>system_info(dynamic_trace)</c> returns + <c>dtrace</c> or <c>systemtap</c>).</p> + </item> + <tag><marker id="system_info_info"/> + <c>info</c></tag> <item> - <p>Returns the number of processes currently existing at - the local node as an integer. The same value as - <c>length(processes())</c> returns, but more efficient.</p> + <p>Returns a binary containing a string of miscellaneous + system information formatted as in Erlang crash dumps. + For more information, see section + <seealso marker="erts:crash_dump"> + How to interpret the Erlang crash dumps</seealso> + in the User's Guide.</p> </item> - <tag><marker id="system_info_process_limit"><c>process_limit</c></marker></tag> + <tag><marker id="system_info_kernel_poll"/> + <c>kernel_poll</c></tag> <item> - <p>Returns the maximum number of simultaneously existing - processes at the local node as an integer. This limit - can be configured at startup by using the - <seealso marker="erl#+P">+P</seealso> - command line flag of - <seealso marker="erl">erl(1)</seealso>.</p> + <p>Returns <c>true</c> if the emulator uses some kind of + kernel-poll implementation, otherwise <c>false</c>.</p> </item> - <tag><c>procs</c></tag> + <tag><marker id="system_info_loaded"/> + <c>loaded</c></tag> <item> - <p>Returns a binary containing a string of process and port + <p>Returns a binary containing a string of loaded module information formatted as in Erlang crash dumps. For more - information see the <seealso marker="erts:crash_dump">"How to interpret the Erlang crash dumps"</seealso> chapter - in the ERTS User's Guide.</p> + information, see section + <seealso marker="erts:crash_dump">How to interpret the Erlang + crash dumps</seealso> in the User's Guide.</p> </item> - <tag><marker id="system_info_scheduler_bind_type"><c>scheduler_bind_type</c></marker></tag> + <tag><marker id="system_info_machine"/> + <c>machine</c></tag> <item> - <p>Returns information on how user has requested - schedulers to be bound or not bound.</p> - <p><em>NOTE:</em> Even though user has requested - schedulers to be bound, they might have silently failed - to bind. In order to inspect actual scheduler bindings call - <seealso marker="#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>. - </p> - <p>For more information, see - the <c>erl</c> <seealso marker="erts:erl#+sbt">+sbt</seealso> - command line argument, and - <seealso marker="#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>. - </p> - </item> - <tag><marker id="system_info_scheduler_bindings"><c>scheduler_bindings</c></marker></tag> - <item> - <p>Returns information on currently used scheduler - bindings.</p> - <p>A tuple of a size equal to - <seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso> is returned. The elements of the tuple are integers - or the atom <c>unbound</c>. Logical processor identifiers - are represented as integers. The <c>N</c>th - element of the tuple equals the current binding for - the scheduler with the scheduler identifier equal to - <c>N</c>. E.g., if the schedulers have been bound, - <c>element(erlang:system_info(scheduler_id), - erlang:system_info(scheduler_bindings))</c> will return - the identifier of the logical processor that the calling - process is executing on. - </p> - <p>Note that only schedulers online can be bound to logical - processors.</p> - <p>For more information, see - the <c>erl</c> <seealso marker="erts:erl#+sbt">+sbt</seealso> - command line argument, - <seealso marker="#system_info_schedulers_online">erlang:system_info(schedulers_online)</seealso>. - </p> + <p>Returns a string containing the Erlang machine name.</p> </item> - <tag><marker id="system_info_scheduler_id"><c>scheduler_id</c></marker></tag> + <tag><marker id="system_info_modified_timing_level"/> + <c>modified_timing_level</c></tag> <item> - <p>Returns the scheduler id (<c>SchedulerId</c>) of the - scheduler thread that the calling process is executing - on. <c><anno>SchedulerId</anno></c> is a positive integer; where - <c><![CDATA[1 <= SchedulerId <= erlang:system_info(schedulers)]]></c>. See also - <seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>.</p> + <p>Returns the modified timing-level (an integer) if + modified timing is enabled, otherwise <c>undefined</c>. + For more information about modified timing, see + command-line flag + <seealso marker="erts:erl#+T"><c>+T</c></seealso> + in <c>erl(1)</c></p> </item> - <tag><marker id="system_info_schedulers"><c>schedulers</c></marker></tag> + <tag><marker id="system_info_nif_version"/> + <c>nif_version</c></tag> <item> - <p>Returns the number of scheduler threads used by - the emulator. Scheduler threads online schedules Erlang - processes and Erlang ports, and execute Erlang code - and Erlang linked in driver code.</p> - <p>The number of scheduler threads is determined at - emulator boot time and cannot be changed after - that. The amount of schedulers online can - however be changed at any time.</p> - <p>See also <seealso marker="#system_flag_schedulers_online">erlang:system_flag(schedulers_online, SchedulersOnline)</seealso>, - <seealso marker="#system_info_schedulers_online">erlang:system_info(schedulers_online)</seealso>, - <seealso marker="#system_info_scheduler_id">erlang:system_info(scheduler_id)</seealso>, - <seealso marker="#system_flag_multi_scheduling">erlang:system_flag(multi_scheduling, BlockState)</seealso>, - <seealso marker="#system_info_multi_scheduling">erlang:system_info(multi_scheduling)</seealso>, and - and <seealso marker="#system_info_multi_scheduling_blockers">erlang:system_info(multi_scheduling_blockers)</seealso>.</p> - </item> - <tag><marker id="system_info_schedulers_online"><c>schedulers_online</c></marker></tag> - <item> - <p>Returns the amount of schedulers online. The scheduler - identifiers of schedulers online satisfy the following - relationship: - <c><![CDATA[1 <= SchedulerId <= erlang:system_info(schedulers_online)]]></c>. - </p> - <p>For more information, see - <seealso marker="#system_info_schedulers">erlang:system_info(schedulers)</seealso>, - and - <seealso marker="#system_flag_schedulers_online">erlang:system_flag(schedulers_online, SchedulersOnline)</seealso>. - </p> <name name="system_info" arity="1" clause_i="49"/> - + <p>Returns a string containing the version of the Erlang NIF + interface used by the runtime system. It is on the form + "<major ver>.<minor ver>".</p> </item> - <tag><c>smp_support</c></tag> + <tag><marker id="system_info_otp_release"/> + <c>otp_release</c></tag> <item> - <p>Returns <c>true</c> if the emulator has been compiled - with smp support; otherwise, <c>false</c>.</p> - </item> - <tag><c>system_version</c></tag> + <marker id="system_info_otp_release"></marker> + <p>Returns a string containing the OTP release number of the + OTP release that the currently executing ERTS application + is part of.</p> + <p>As from Erlang/OTP 17, the OTP release number corresponds to + the major OTP version number. No + <c>erlang:system_info()</c> argument gives the exact OTP + version. This is because the exact OTP version in the general case + is difficult to determine. For more information, see the + description of versions in + <seealso marker="doc/system_principles:versions"> + System principles</seealso> in System Documentation.</p> + </item> + <tag><marker id="system_info_port_parallelism"/> + <c>port_parallelism</c></tag> + <item> + <p>Returns the default port parallelism scheduling hint used. + For more information, see command-line argument + <seealso marker="erl#+spp"><c>+spp</c></seealso> + in <c>erl(1)</c>.</p> + </item> + <tag><marker id="system_info_system_version"/> + <c>system_version</c></tag> <item> <p>Returns a string containing version number and - some important properties such as the number of schedulers.</p> + some important properties, such as the number of schedulers.</p> </item> - <tag><c>system_architecture</c></tag> + <tag><marker id="system_info_system_architecture"/> + <c>system_architecture</c></tag> <item> <p>Returns a string containing the processor and OS architecture the emulator is built for.</p> </item> - <tag><c>threads</c></tag> - <item> - <p>Returns <c>true</c> if the emulator has been compiled - with thread support; otherwise, <c>false</c> is - returned.</p> - </item> - <tag><marker id="system_info_thread_pool_size"><c>thread_pool_size</c></marker></tag> + <tag><marker id="system_info_trace_control_word"/> + <c>trace_control_word</c></tag> <item> - <p>Returns the number of async threads in the async thread - pool used for asynchronous driver calls - (<seealso marker="erts:erl_driver#driver_async">driver_async()</seealso>) - as an integer.</p> - </item> - <tag><marker id="system_info_tolerant_timeofday"><c>tolerant_timeofday</c></marker></tag> - <item> - <p>Returns whether compensation for sudden changes of system - time is <c>enabled</c> or <c>disabled</c>.</p> - <p>See also <seealso marker="erts:erl#+c">+c</seealso> - command line flag.</p> - </item> - <tag><c>trace_control_word</c></tag> - <item> - <p>Returns the value of the node's trace control word. - For more information see documentation of the function - <c>get_tcw</c> in "Match Specifications in Erlang", - <seealso marker="erts:match_spec#get_tcw">ERTS User's Guide</seealso>.</p> - </item> - <tag><marker id="update_cpu_info"><c>update_cpu_info</c></marker></tag> - <item> - <p>The runtime system rereads the CPU information available and - updates its internally stored information about the - <seealso marker="#system_info_cpu_topology_detected">detected CPU - topology</seealso> and the amount of logical processors - <seealso marker="#logical_processors">configured</seealso>, - <seealso marker="#logical_processors_online">online</seealso>, and - <seealso marker="#logical_processors_available">available</seealso>. - If the CPU information has changed since the last time it was read, - the atom <c>changed</c> is returned; otherwise, the atom - <c>unchanged</c> is returned. If the CPU information has changed - you probably want to - <seealso marker="#system_flag_schedulers_online">adjust the amount - of schedulers online</seealso>. You typically want to have as - many schedulers online as - <seealso marker="#logical_processors_available">logical processors - available</seealso>. - </p> + <p>Returns the value of the node trace control word. For + more information, see function <c>get_tcw</c> in section + <seealso marker="erts:match_spec#get_tcw"> + Match Specifications in Erlang</seealso> in the User's Guide.</p> </item> - <tag><marker id="system_info_version"><c>version</c></marker></tag> + <tag><marker id="system_info_version"/> + <c>version</c></tag> <item> <p>Returns a string containing the version number of the emulator.</p> </item> - <tag><c>wordsize</c></tag> + <tag><marker id="system_info_wordsize"/> + <c>wordsize</c></tag> <item> - <p>Same as <c>{wordsize, internal}.</c></p> + <p>Same as <c>{wordsize, internal}</c>.</p> </item> <tag><c>{wordsize, internal}</c></tag> <item> <p>Returns the size of Erlang term words in bytes as an - integer, i.e. on a 32-bit architecture 4 is returned, - and on a pure 64-bit architecture 8 is returned. On a + integer, that is, 4 is returned on a 32-bit architecture, + and 8 is returned on a pure 64-bit architecture. On a halfword 64-bit emulator, 4 is returned, as the Erlang - terms are stored using a virtual wordsize of half the - system's wordsize.</p> + terms are stored using a virtual word size of half the + system word size.</p> </item> <tag><c>{wordsize, external}</c></tag> <item> - <p>Returns the true wordsize of the emulator, i.e. the size - of a pointer, in bytes as an integer. On a pure 32-bit - architecture 4 is returned, on both a halfword and pure - 64-bit architecture, 8 is returned.</p> + <p>Returns the true word size of the emulator, that is, + the size of a pointer. The value is given in bytes + as an integer. On a pure 32-bit architecture, 4 is + returned. On both a half word and on a pure + 64-bit architecture, 8 is returned.</p> </item> </taglist> - <note> - <p>The <c>scheduler</c> argument has changed name to - <c>scheduler_id</c>. This in order to avoid mixup with - the <c>schedulers</c> argument. The <c>scheduler</c> - argument was introduced in ERTS version 5.5 and renamed - in ERTS version 5.5.1.</p> - </note> </desc> </func> <func> <name name="system_monitor" arity="0"/> + <fsummary>Current system performance monitoring settings.</fsummary> <type name="system_monitor_option"/> - <fsummary>Current system performance monitoring settings</fsummary> <desc> <p>Returns the current system monitoring settings set by - <seealso marker="#system_monitor/2">erlang:system_monitor/2</seealso> - as <c>{<anno>MonitorPid</anno>, <anno>Options</anno>}</c>, or <c>undefined</c> if there - are no settings. The order of the options may be different - from the one that was set.</p> + <seealso marker="#system_monitor/2"> + <c>erlang:system_monitor/2</c></seealso> + as <c>{<anno>MonitorPid</anno>, <anno>Options</anno>}</c>, + or <c>undefined</c> if no settings exist. The order of the + options can be different from the one that was set.</p> </desc> </func> <func> <name name="system_monitor" arity="1"/> + <fsummary>Set or clear system performance monitoring options.</fsummary> <type name="system_monitor_option"/> - <fsummary>Set or clear system performance monitoring options</fsummary> <desc> - <p>When called with the argument <c>undefined</c>, all + <p>When called with argument <c>undefined</c>, all system performance monitoring settings are cleared.</p> - <p>Calling the function with <c>{<anno>MonitorPid</anno>, <anno>Options</anno>}</c> as - argument, is the same as calling - <seealso marker="#system_monitor/2">erlang:system_monitor(<anno>MonitorPid</anno>, <anno>Options</anno>)</seealso>.</p> + <p>Calling the function with <c>{<anno>MonitorPid</anno>, + <anno>Options</anno>}</c> as argument is the same as calling + <seealso marker="#system_monitor/2"> + <c>erlang:system_monitor(<anno>MonitorPid</anno>, + <anno>Options</anno>)</c></seealso>.</p> <p>Returns the previous system monitor settings just like - <seealso marker="#system_monitor/0">erlang:system_monitor/0</seealso>.</p> + <seealso marker="#system_monitor/0"> + <c>erlang:system_monitor/0</c></seealso>.</p> </desc> </func> <func> <name name="system_monitor" arity="2"/> + <fsummary>Set system performance monitoring options.</fsummary> <type name="system_monitor_option"/> - <fsummary>Set system performance monitoring options</fsummary> <desc> - <p>Sets system performance monitoring options. <c><anno>MonitorPid</anno></c> - is a local pid that will receive system monitor messages, and - the second argument is a list of monitoring options:</p> + <p>Sets the system performance monitoring options. + <c><anno>MonitorPid</anno></c> is a local process identifier (pid) + receiving system monitor messages. The + second argument is a list of monitoring options:</p> <taglist> <tag><c>{long_gc, Time}</c></tag> <item> <p>If a garbage collection in the system takes at least - <c>Time</c> wallclock milliseconds, a message + <c>Time</c> wall clock milliseconds, a message <c>{monitor, GcPid, long_gc, Info}</c> is sent to - <c><anno>MonitorPid</anno></c>. <c>GcPid</c> is the pid that was - garbage collected and <c>Info</c> is a list of two-element - tuples describing the result of the garbage collection. - One of the tuples is <c>{timeout, GcTime}</c> where - <c>GcTime</c> is the actual time for the garbage + <c><anno>MonitorPid</anno></c>. <c>GcPid</c> is the pid that + was garbage collected. <c>Info</c> is a list of two-element + tuples describing the result of the garbage collection.</p> + <p>One of the tuples is <c>{timeout, GcTime}</c>, where + <c>GcTime</c> is the time for the garbage collection in milliseconds. The other tuples are tagged with <c>heap_size</c>, <c>heap_block_size</c>, - <c>stack_size</c>, <c>mbuf_size</c>, <c>old_heap_size</c>, - and <c>old_heap_block_size</c>. These tuples are - explained in the documentation of the - <seealso marker="#gc_start">gc_start</seealso> - trace message (see - <seealso marker="#trace/3">erlang:trace/3</seealso>). - New tuples may be added, and the order of the tuples in - the <c>Info</c> list may be changed at any time without prior - notice. - </p> + <c>stack_size</c>, <c>mbuf_size</c>, <c>old_heap_size</c>, + and <c>old_heap_block_size</c>. These tuples are + explained in the description of trace message + <seealso marker="#gc_minor_start"><c>gc_minor_start</c></seealso> + (see <seealso marker="#trace/3"><c>erlang:trace/3</c></seealso>). + New tuples can be added, and the order of the tuples in + the <c>Info</c> list can be changed at any time without + prior notice.</p> </item> <tag><c>{long_schedule, Time}</c></tag> <item> - <p>If a process or port in the system runs uninterrupted + <p>If a process or port in the system runs uninterrupted for at least <c>Time</c> wall clock milliseconds, a message <c>{monitor, PidOrPort, long_schedule, Info}</c> is sent to <c>MonitorPid</c>. <c>PidOrPort</c> is the - process or port that was running and <c>Info</c> is a - list of two-element tuples describing the event. In case - of a <c>pid()</c>, the tuples <c>{timeout, Millis}</c>, - <c>{in, Location}</c> and <c>{out, Location}</c> will be + process or port that was running. <c>Info</c> is a + list of two-element tuples describing the event.</p> + <p>If a <c>pid()</c>, the tuples <c>{timeout, Millis}</c>, + <c>{in, Location}</c>, and <c>{out, Location}</c> are present, where <c>Location</c> is either an MFA (<c>{Module, Function, Arity}</c>) describing the function where the process was scheduled in/out, or the - atom <c>undefined</c>. In case of a <c>port()</c>, the + atom <c>undefined</c>.</p> + <p>If a <c>port()</c>, the tuples <c>{timeout, Millis}</c> and <c>{port_op,Op}</c> - will be present. <c>Op</c> will be one of <c>proc_sig</c>, + are present. <c>Op</c> is one of <c>proc_sig</c>, <c>timeout</c>, <c>input</c>, <c>output</c>, - <c>event</c> or <c>dist_cmd</c>, depending on which - driver callback was executing. <c>proc_sig</c> is an - internal operation and should never appear, while the + <c>event</c>, or <c>dist_cmd</c>, depending on which + driver callback was executing.</p> + <p><c>proc_sig</c> is an + internal operation and is never to appear, while the others represent the corresponding driver callbacks <c>timeout</c>, <c>ready_input</c>, <c>ready_output</c>, - <c>event</c> and finally <c>outputv</c> (when the port - is used by distribution). The <c>Millis</c> value in - the <c>timeout</c> tuple will tell you the actual - uninterrupted execution time of the process or port, - which will always be <c>>=</c> the <c>Time</c> value - supplied when starting the trace. New tuples may be - added to the <c>Info</c> list in the future, and the - order of the tuples in the list may be changed at any - time without prior notice. - </p> - <p>This can be used to detect problems with NIF's or - drivers that take too long to execute. Generally, 1 ms - is considered a good maximum time for a driver callback - or a NIF. However, a time sharing system should usually - consider everything below 100 ms as "possible" and - fairly "normal". Schedule times above that might however - indicate swapping or a NIF/driver that is - misbehaving. Misbehaving NIF's and drivers could cause - bad resource utilization and bad overall performance of - the system.</p> + <c>event</c>, and <c>outputv</c> (when the port + is used by distribution). Value <c>Millis</c> in + tuple <c>timeout</c> informs about the + uninterrupted execution time of the process or port, which + always is equal to or higher than the <c>Time</c> value + supplied when starting the trace. New tuples can be + added to the <c>Info</c> list in a future release. The + order of the tuples in the list can be changed at any + time without prior notice.</p> + <p>This can be used to detect problems with NIFs or + drivers that take too long to execute. 1 ms is + considered a good maximum time for a driver callback + or a NIF. However, a time-sharing system is usually to + consider everything < 100 ms as "possible" and + fairly "normal". However, longer schedule times can + indicate swapping or a misbehaving NIF/driver. + Misbehaving NIFs and drivers can cause bad resource + utilization and bad overall system performance.</p> </item> <tag><c>{large_heap, Size}</c></tag> <item> <p>If a garbage collection in the system results in the allocated size of a heap being at least <c>Size</c> words, a message <c>{monitor, GcPid, large_heap, Info}</c> - is sent to <c><anno>MonitorPid</anno></c>. <c>GcPid</c> and <c>Info</c> - are the same as for <c>long_gc</c> above, except that - the tuple tagged with <c>timeout</c> is not present. - <em>Note</em>: As of erts version 5.6 the monitor message - is sent if the sum of the sizes of all memory blocks allocated - for all heap generations is equal to or larger than <c>Size</c>. - Previously the monitor message was sent if the memory block - allocated for the youngest generation was equal to or larger - than <c>Size</c>. - </p> + is sent to <c><anno>MonitorPid</anno></c>. + <c>GcPid</c> and <c>Info</c> + are the same as for <c>long_gc</c> earlier, except that + the tuple tagged with <c>timeout</c> is not present.</p> + <p>The monitor message is sent if the sum of the sizes of + all memory blocks allocated for all heap generations after + a garbage collection is equal to or higher than <c>Size</c>.</p> + <p>When a process is killed by + <seealso marker="#process_flag_max_heap_size"> + <c>max_heap_size</c></seealso>, it is killed before the + garbage collection is complete and thus no large heap message + is sent.</p> </item> <tag><c>busy_port</c></tag> <item> <p>If a process in the system gets suspended because it sends to a busy port, a message <c>{monitor, SusPid, busy_port, Port}</c> is sent to - <c><anno>MonitorPid</anno></c>. <c>SusPid</c> is the pid that got - suspended when sending to <c>Port</c>.</p> + <c><anno>MonitorPid</anno></c>. <c>SusPid</c> is the pid + that got suspended when sending to <c>Port</c>.</p> </item> <tag><c>busy_dist_port</c></tag> <item> @@ -6514,973 +9247,1812 @@ ok sends to a process on a remote node whose inter-node communication was handled by a busy port, a message <c>{monitor, SusPid, busy_dist_port, Port}</c> is sent to - <c><anno>MonitorPid</anno></c>. <c>SusPid</c> is the pid that got - suspended when sending through the inter-node + <c><anno>MonitorPid</anno></c>. <c>SusPid</c> is the pid + that got suspended when sending through the inter-node communication port <c>Port</c>.</p> </item> </taglist> <p>Returns the previous system monitor settings just like - <seealso marker="#system_monitor/0">erlang:system_monitor/0</seealso>.</p> + <seealso marker="#system_monitor/0"> + <c>erlang:system_monitor/0</c></seealso>.</p> <note> <p>If a monitoring process gets so large that it itself starts to cause system monitor messages when garbage - collecting, the messages will enlarge the process's + collecting, the messages enlarge the process message queue and probably make the problem worse.</p> <p>Keep the monitoring process neat and do not set the system monitor limits too tight.</p> </note> - <p>Failure: <c>badarg</c> if <c><anno>MonitorPid</anno></c> does not exist or is not a local process.</p> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item>If <c><anno>MonitorPid</anno></c> does not exist.</item> + <tag><c>badarg</c></tag> + <item>If <c><anno>MonitorPid</anno></c> is not a local process.</item> + </taglist> </desc> </func> <func> <name name="system_profile" arity="0"/> + <fsummary>Current system profiling settings.</fsummary> <type name="system_profile_option"/> - <fsummary>Current system profiling settings</fsummary> <desc> <p>Returns the current system profiling settings set by - <seealso marker="#system_profile/2">erlang:system_profile/2</seealso> - as <c>{<anno>ProfilerPid</anno>, <anno>Options</anno>}</c>, or <c>undefined</c> if there - are no settings. The order of the options may be different + <seealso marker="#system_profile/2"> + <c>erlang:system_profile/2</c></seealso> + as <c>{<anno>ProfilerPid</anno>, <anno>Options</anno>}</c>, + or <c>undefined</c> if there + are no settings. The order of the options can be different from the one that was set.</p> </desc> </func> <func> <name name="system_profile" arity="2"/> + <fsummary>Current system profiling settings.</fsummary> <type name="system_profile_option"/> - <fsummary>Current system profiling settings</fsummary> <desc> <p>Sets system profiler options. <c><anno>ProfilerPid</anno></c> - is a local pid or port that will receive profiling messages. The - receiver is excluded from all profiling. + is a local process identifier (pid) or port receiving profiling + messages. The receiver is excluded from all profiling. The second argument is a list of profiling options:</p> <taglist> <tag><c>exclusive</c></tag> <item> - <p> - If a synchronous call to a port from a process is done, the - calling process is considered not runnable during the call - runtime to the port. The calling process is notified as - <c>inactive</c> and subsequently <c>active</c> when the port - callback returns. - </p> + <p>If a synchronous call to a port from a process is done, the + calling process is considered not runnable during the call + runtime to the port. The calling process is notified as + <c>inactive</c>, and later <c>active</c> when the port + callback returns.</p> + </item> + <tag><c>monotonic_timestamp</c></tag> + <item> + <p>Time stamps in profile messages use + <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang + monotonic time</seealso>. The time stamp (Ts) has the same + format and value as produced by + <c>erlang:monotonic_time(nanosecond)</c>.</p> </item> <tag><c>runnable_procs</c></tag> <item> - <p>If a process is put into or removed from the run queue a message, - <c>{profile, Pid, State, Mfa, Ts}</c>, is sent to - <c><anno>ProfilerPid</anno></c>. Running processes that is reinserted into the - run queue after having been preemptively scheduled out will not trigger this - message. - </p> + <p>If a process is put into or removed from the run queue, a + message, <c>{profile, Pid, State, Mfa, Ts}</c>, is sent to + <c><anno>ProfilerPid</anno></c>. Running processes that + are reinserted into the run queue after having been + pre-empted do not trigger this message.</p> </item> <tag><c>runnable_ports</c></tag> <item> - <p>If a port is put into or removed from the run queue a message, - <c>{profile, Port, State, 0, Ts}</c>, is sent to - <c><anno>ProfilerPid</anno></c>. - </p> + <p>If a port is put into or removed from the run queue, a + message, <c>{profile, Port, State, 0, Ts}</c>, is sent to + <c><anno>ProfilerPid</anno></c>.</p> </item> <tag><c>scheduler</c></tag> <item> - <p>If a scheduler is put to sleep or awoken a message, - <c>{profile, scheduler, Id, State, NoScheds, Ts}</c>, is sent - to <c><anno>ProfilerPid</anno></c>. - </p> + <p>If a scheduler is put to sleep or awoken, a message, + <c>{profile, scheduler, Id, State, NoScheds, Ts}</c>, is + sent to <c><anno>ProfilerPid</anno></c>.</p> + </item> + <tag><c>strict_monotonic_timestamp</c></tag> + <item> + <p>Time stamps in profile messages consist of + <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang + monotonic time</seealso> and a monotonically increasing + integer. The time stamp (Ts) has the same format and value + as produced by <c>{erlang:monotonic_time(nanosecond), + erlang:unique_integer([monotonic])}</c>.</p> + </item> + <tag><c>timestamp</c></tag> + <item> + <p>Time stamps in profile messages include a + time stamp (Ts) that has the same form as returned by + <c>erlang:now()</c>. This is also the default if no + time stamp flag is specified. If <c>cpu_timestamp</c> has + been enabled through + <seealso marker="#trace/3"><c>erlang:trace/3</c></seealso>, + this also effects the time stamp produced in profiling messages + when flag <c>timestamp</c> is enabled.</p> </item> </taglist> - <note><p><c>erlang:system_profile</c> is considered experimental and - its behaviour may change in the future.</p> + <note> + <p><c>erlang:system_profile</c> behavior can change + in a future release.</p> + </note> + </desc> + </func> + + <func> + <name name="system_time" arity="0"/> + <fsummary>Current Erlang system time.</fsummary> + <desc> + <p>Returns current + <seealso marker="time_correction#Erlang_System_Time"> + Erlang system time</seealso> in <c>native</c> + <seealso marker="#type_time_unit">time unit</seealso>.</p> + <p>Calling <c>erlang:system_time()</c> is equivalent to + <seealso marker="#monotonic_time/0"> + <c>erlang:monotonic_time()</c></seealso><c> + + </c><seealso marker="#time_offset/0"> + <c>erlang:time_offset()</c></seealso>.</p> + <note> + <p>This time is <em>not</em> a monotonically increasing time + in the general case. For more information, see the documentation of + <seealso marker="time_correction#Time_Warp_Modes"> + time warp modes</seealso> in the User's Guide.</p> + </note> + </desc> + </func> + + <func> + <name name="system_time" arity="1"/> + <fsummary>Current Erlang system time.</fsummary> + <desc> + <p>Returns current + <seealso marker="time_correction#Erlang_System_Time"> + Erlang system time</seealso> + converted into the <c><anno>Unit</anno></c> passed as argument.</p> + <p>Calling <c>erlang:system_time(<anno>Unit</anno>)</c> is equivalent + to <seealso marker="#convert_time_unit/3"> + <c>erlang:convert_time_unit</c></seealso><c>(</c><seealso + marker="#system_time/0"><c>erlang:system_time()</c></seealso><c>, + native, <anno>Unit</anno>)</c>.</p> + <note> + <p>This time is <em>not</em> a monotonically increasing time + in the general case. For more information, see the documentation of + <seealso marker="time_correction#Time_Warp_Modes"> + time warp modes</seealso> in the User's Guide.</p> </note> </desc> </func> <func> <name name="term_to_binary" arity="1"/> - <fsummary>Encode a term to an Erlang external term format binary</fsummary> - <desc> - <p>Returns a binary data object which is the result of encoding - <c><anno>Term</anno></c> according to the Erlang external term format.</p> - <p>This can be used for a variety of purposes, for example + <fsummary>Encode a term to an Erlang external term format binary. + </fsummary> + <desc> + <p>Returns a binary data object that is the result of encoding + <c><anno>Term</anno></c> according to the + <seealso marker="erts:erl_ext_dist">Erlang external + term format.</seealso></p> + <p>This can be used for various purposes, for example, writing a term to a file in an efficient way, or sending an Erlang term to some type of communications channel not supported by distributed Erlang.</p> - <p>See also - <seealso marker="#binary_to_term/1">binary_to_term/1</seealso>.</p> + <pre> +> <input>Bin = term_to_binary(hello).</input> +<<131,100,0,5,104,101,108,108,111>> +> <input>hello = binary_to_term(Bin).</input> +hello +</pre> + <p>See also <seealso marker="#binary_to_term/1"> + <c>binary_to_term/1</c></seealso>.</p> + <note> + <p>There is no guarantee that this function will return + the same encoded representation for the same term.</p> + </note> </desc> </func> + <func> <name name="term_to_binary" arity="2"/> - <fsummary>Encode a term to en Erlang external term format binary</fsummary> - <desc> - <p>Returns a binary data object which is the result of encoding - <c><anno>Term</anno></c> according to the Erlang external term format.</p> - <p>If the option <c>compressed</c> is provided, the external - term format will be compressed. The compressed format is - automatically recognized by <c>binary_to_term/1</c> in R7B and later.</p> - <p>It is also possible to specify a compression level by giving - the option <c>{compressed, <anno>Level</anno>}</c>, where <c><anno>Level</anno></c> is an - integer from 0 through 9. <c>0</c> means that no compression - will be done (it is the same as not giving any <c>compressed</c> option); - <c>1</c> will take the least time but may not compress as well as - the higher levels; <c>9</c> will take the most time and may produce - a smaller result. Note the "mays" in the preceding sentence; depending - on the input term, level 9 compression may or may not produce a smaller - result than level 1 compression.</p> - <p>Currently, <c>compressed</c> gives the same result as - <c>{compressed, 6}</c>.</p> - <p>The option <c>{minor_version, <anno>Version</anno>}</c> can be use to control - some details of the encoding. This option was - introduced in R11B-4. Currently, the allowed values for <c><anno>Version</anno></c> - are <c>0</c> and <c>1</c>.</p> - <p><c>{minor_version, 1}</c> is since 17.0 the default, it forces any floats in - the term to be encoded - in a more space-efficient and exact way (namely in the 64-bit IEEE format, - rather than converted to a textual representation). <c>binary_to_term/1</c> - in R11B-4 and later is able decode this representation.</p> - <p><c>{minor_version, 0}</c> meaning that floats - will be encoded using a textual representation; this option is useful if - you want to ensure that releases prior to R11B-4 can decode resulting - binary.</p> - <p>See also - <seealso marker="#binary_to_term/1">binary_to_term/1</seealso>.</p> + <fsummary>Encode a term to en Erlang external term format binary. + </fsummary> + <desc> + <p>Returns a binary data object that is the result of encoding + <c><anno>Term</anno></c> according to the Erlang external + term format.</p> + <p>If option <c>compressed</c> is provided, the external term + format is compressed. The compressed format is automatically + recognized by <c>binary_to_term/1</c> as from Erlang/OTP R7B.</p> + <p>A compression level can be specified by giving option + <c>{compressed, <anno>Level</anno>}</c>. + <c><anno>Level</anno></c> is an integer + with range 0..9, where:</p> + <list type="bulleted"> + <item><p><c>0</c> - No compression is done (it is the same as + giving no <c>compressed</c> option).</p></item> + <item><p><c>1</c> - Takes least time but may not compress + as well as the higher levels.</p></item> + <item><p><c>6</c> - Default level when option <c>compressed</c> + is provided.</p></item> + <item><p><c>9</c> - Takes most time and tries to produce a smaller + result. Notice "tries" in the preceding sentence; depending + on the input term, level 9 compression either does or does + not produce a smaller result than level 1 compression.</p></item> + </list> + <p>Option <c>{minor_version, <anno>Version</anno>}</c> + can be used to control some + encoding details. This option was introduced in Erlang/OTP R11B-4. + The valid values for <c><anno>Version</anno></c> are:</p> + <taglist> + <tag><c>0</c></tag> + <item> + <p>Floats are encoded using a textual representation. + This option is useful to ensure that releases before Erlang/OTP + R11B-4 can decode resulting binary.</p> + <p>This version encode atoms that can be represented by a + latin1 string using latin1 encoding while only atoms that + cannot be represented by latin1 are encoded using utf8.</p> + </item> + <tag><c>1</c></tag> + <item> + <p>This is as of Erlang/OTP 17.0 the default. It forces any floats + in the term to be encoded in a more space-efficient and exact way + (namely in the 64-bit IEEE format, rather than converted to a + textual representation). As from Erlang/OTP R11B-4, + <c>binary_to_term/1</c> can decode this representation.</p> + <p>This version encode atoms that can be represented by a + latin1 string using latin1 encoding while only atoms that + cannot be represented by latin1 are encoded using utf8.</p> + </item> + <tag><c>2</c></tag> + <item> + <p>Drops usage of the latin1 atom encoding and unconditionally + use utf8 encoding for all atoms. This will be changed to the + default in a future major release of Erlang/OTP. Erlang/OTP + systems as of R16B can decode this representation.</p> + </item> + </taglist> + <p>See also <seealso marker="#binary_to_term/1"> + <c>binary_to_term/1</c></seealso>.</p> </desc> </func> + <func> <name name="throw" arity="1"/> - <fsummary>Throw an exception</fsummary> + <fsummary>Throw an exception.</fsummary> <desc> <p>A non-local return from a function. If evaluated within a - <c>catch</c>, <c>catch</c> will return the value <c><anno>Any</anno></c>.</p> + <c>catch</c>, <c>catch</c> returns value <c><anno>Any</anno></c>. + Example:</p> <pre> > <input>catch throw({hello, there}).</input> {hello,there}</pre> <p>Failure: <c>nocatch</c> if not evaluated within a catch.</p> </desc> </func> + <func> <name name="time" arity="0"/> - <fsummary>Current time</fsummary> + <fsummary>Current time.</fsummary> <desc> <p>Returns the current time as <c>{Hour, Minute, Second}</c>.</p> - <p>The time zone and daylight saving time correction depend on - the underlying OS.</p> + <p>The time zone and Daylight Saving Time correction depend on + the underlying OS. Example:</p> <pre> > <input>time().</input> {9,42,44}</pre> </desc> </func> + + <func> + <name name="time_offset" arity="0"/> + <fsummary>Current time offset.</fsummary> + <desc> + <p>Returns the current time offset between + <seealso marker="time_correction#Erlang_Monotonic_Time"> + Erlang monotonic time</seealso> and + <seealso marker="time_correction#Erlang_System_Time"> + Erlang system time</seealso> in + <c>native</c> <seealso marker="#type_time_unit">time unit</seealso>. + Current time offset added to an Erlang monotonic time gives + corresponding Erlang system time.</p> + <p>The time offset may or may not change during operation depending + on the <seealso marker="time_correction#Time_Warp_Modes">time + warp mode</seealso> used.</p> + <note> + <p>A change in time offset can be observed at slightly + different points in time by different processes.</p> + <p>If the runtime system is in + <seealso marker="time_correction#Multi_Time_Warp_Mode">multi-time + warp mode</seealso>, the time offset is changed when + the runtime system detects that the + <seealso marker="time_correction#OS_System_Time">OS system + time</seealso> has changed. The runtime system will, however, + not detect this immediately when it occurs. A task checking + the time offset is scheduled to execute at least once a minute; + so, under normal operation this is to be detected within a + minute, but during heavy load it can take longer time.</p> + </note> + </desc> + </func> + + <func> + <name name="time_offset" arity="1"/> + <fsummary>Current time offset.</fsummary> + <desc> + <p>Returns the current time offset between + <seealso marker="time_correction#Erlang_Monotonic_Time"> + Erlang monotonic time</seealso> and + <seealso marker="time_correction#Erlang_System_Time"> + Erlang system time</seealso> + converted into the <c><anno>Unit</anno></c> passed as argument.</p> + <p>Same as calling + <seealso marker="#convert_time_unit/3"> + <c>erlang:convert_time_unit</c></seealso><c>(</c><seealso marker="#time_offset/0"> + <c>erlang:time_offset()</c></seealso><c>, native, + <anno>Unit</anno>)</c> + however optimized for commonly used <c><anno>Unit</anno></c>s.</p> + </desc> + </func> + + <func> + <name name="timestamp" arity="0"/> + <fsummary>Current Erlang System time.</fsummary> + <type name="timestamp"/> + <desc> + <p>Returns current + <seealso marker="time_correction#Erlang_System_Time"> + Erlang system time</seealso> + on the format <c>{MegaSecs, Secs, MicroSecs}</c>. This format is + the same as <seealso marker="kernel:os#timestamp/0"> + <c>os:timestamp/0</c></seealso> + and the deprecated <seealso marker="#now/0"> + <c>erlang:now/0</c></seealso> + use. The reason for the existence of <c>erlang:timestamp()</c> is + purely to simplify use for existing code that assumes this time stamp + format. Current Erlang system time can more efficiently be retrieved + in the time unit of your choice using + <seealso marker="#system_time/1"> + <c>erlang:system_time/1</c></seealso>.</p> + <p>The <c>erlang:timestamp()</c> BIF is equivalent to:</p> +<code type="none"> +timestamp() -> + ErlangSystemTime = erlang:system_time(microsecond), + MegaSecs = ErlangSystemTime div 1000000000000, + Secs = ErlangSystemTime div 1000000 - MegaSecs*1000000, + MicroSecs = ErlangSystemTime rem 1000000, + {MegaSecs, Secs, MicroSecs}.</code> + <p>It, however, uses a native implementation that does + not build garbage on the heap and with slightly better + performance.</p> + <note> + <p>This time is <em>not</em> a monotonically increasing time + in the general case. For more information, see the documentation of + <seealso marker="time_correction#Time_Warp_Modes"> + time warp modes</seealso> in the User's Guide.</p> + </note> + </desc> + </func> + <func> <name name="tl" arity="1"/> - <fsummary>Tail of a list</fsummary> + <fsummary>Tail of a list.</fsummary> <desc> - <p>Returns the tail of <c><anno>List</anno></c>, that is, the list minus - the first element.</p> + <p>Returns the tail of <c><anno>List</anno></c>, that is, + the list minus the first element, for example:</p> <pre> > <input>tl([geesties, guilies, beasties]).</input> [guilies, beasties]</pre> <p>Allowed in guard tests.</p> - <p>Failure: <c>badarg</c> if <c><anno>List</anno></c> is the empty list [].</p> + <p>Failure: <c>badarg</c> if <c><anno>List</anno></c> + is the empty list <c>[]</c>.</p> </desc> </func> + <func> <name name="trace" arity="3"/> + <fsummary>Set trace flags for a process or processes.</fsummary> <type name="trace_flag"/> - <fsummary>Set trace flags for a process or processes</fsummary> <desc> <p>Turns on (if <c><anno>How</anno> == true</c>) or off (if - <c><anno>How</anno> == false</c>) the trace flags in <c><anno>FlagList</anno></c> for - the process or processes represented by <c><anno>PidSpec</anno></c>.</p> - <p><c><anno>PidSpec</anno></c> is either a pid for a local process, or one of - the following atoms:</p> + <c><anno>How</anno> == false</c>) the trace flags in + <c><anno>FlagList</anno></c> for + the process or processes represented by + <c><anno>PidPortSpec</anno></c>.</p> + <p><c><anno>PidPortSpec</anno></c> is either a process identifier + (pid) for a local process, a port identifier, + or one of the following atoms:</p> <taglist> + <tag><c>all</c></tag> + <item>All currently existing processes and ports and all that + will be created in the future. + </item> + <tag><c>processes</c></tag> + <item>All currently existing processes and all that will be created + in the future. + </item> + <tag><c>ports</c></tag> + <item>All currently existing ports and all that will be created in + the future. + </item> <tag><c>existing</c></tag> - <item> - <p>All processes currently existing.</p> + <item>All currently existing processes and ports. + </item> + <tag><c>existing_processes</c></tag> + <item>All currently existing processes. + </item> + <tag><c>existing_ports</c></tag> + <item>All currently existing ports. </item> <tag><c>new</c></tag> - <item> - <p>All processes that will be created in the future.</p> + <item>All processes and ports that will be created in the future. </item> - <tag><c>all</c></tag> - <item> - <p>All currently existing processes and all processes that - will be created in the future.</p> + <tag><c>new_processes</c></tag> + <item>All processes that will be created in the future. + </item> + <tag><c>new_ports</c></tag> + <item>All ports that will be created in the future. </item> </taglist> - <p><c><anno>FlagList</anno></c> can contain any number of the following - flags (the "message tags" refers to the list of messages - following below):</p> + <p><c><anno>FlagList</anno></c> can contain any number of the + following flags (the "message tags" refers to the list of + <seealso marker="#trace_3_trace_messages"> + <c>trace messages</c></seealso>):</p> <taglist> <tag><c>all</c></tag> <item> - <p>Set all trace flags except <c>{tracer, Tracer}</c> and - <c>cpu_timestamp</c> that are in their nature different + <p>Sets all trace flags except <c>tracer</c> and + <c>cpu_timestamp</c>, which are in their nature different than the others.</p> </item> <tag><c>send</c></tag> <item> - <p>Trace sending of messages.</p> - <p>Message tags: <c>send</c>, - <c>send_to_non_existing_process</c>.</p> + <p>Traces sending of messages.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_send"> + <c>send</c></seealso> and + <seealso marker="#trace_3_trace_messages_send_to_non_existing_process"> + <c>send_to_non_existing_process</c></seealso>.</p> </item> <tag><c>'receive'</c></tag> <item> - <p>Trace receiving of messages.</p> - <p>Message tags: <c>'receive'</c>.</p> - </item> - <tag><c>procs</c></tag> - <item> - <p>Trace process related events.</p> - <p>Message tags: <c>spawn</c>, <c>exit</c>, - <c>register</c>, <c>unregister</c>, <c>link</c>, - <c>unlink</c>, <c>getting_linked</c>, - <c>getting_unlinked</c>.</p> + <p>Traces receiving of messages.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_receive"> + <c>'receive'</c></seealso>.</p> </item> <tag><c>call</c></tag> <item> - <p>Trace certain function calls. Specify which function - calls to trace by calling - <seealso marker="#trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> - <p>Message tags: <c>call</c>, <c>return_from</c>.</p> + <p>Traces certain function calls. Specify which function + calls to trace by calling <seealso marker="#trace_pattern/3"> + <c>erlang:trace_pattern/3</c></seealso>.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_call"> + <c>call</c></seealso> and + <seealso marker="#trace_3_trace_messages_return_from"> + <c>return_from</c></seealso>.</p> </item> <tag><c>silent</c></tag> <item> - <p>Used in conjunction with the <c>call</c> trace flag. - The <c>call</c>, <c>return_from</c> and <c>return_to</c> - trace messages are inhibited if this flag is set, - but if there are match specs they are executed as normal.</p> + <p>Used with the <c>call</c> trace flag. + The <c>call</c>, <c>return_from</c>, and <c>return_to</c> + trace messages are inhibited if this flag is set, but they + are executed as normal if there are match specifications.</p> <p>Silent mode is inhibited by executing <c>erlang:trace(_, false, [silent|_])</c>, - or by a match spec executing the <c>{silent, false}</c> - function.</p> + or by a match specification executing the function + <c>{silent, false}</c>.</p> <p>The <c>silent</c> trace flag facilitates setting up a trace on many or even all processes in the system. - Then the interesting trace can be activated and - deactivated using the <c>{silent,Bool}</c> - match spec function, giving a high degree - of control of which functions with which - arguments that triggers the trace.</p> - <p>Message tags: <c>call</c>, <c>return_from</c>, - <c>return_to</c>. Or rather, the absence of.</p> + The trace can then be activated and deactivated using the match + specification function <c>{silent,Bool}</c>, giving + a high degree of control of which functions with which + arguments that trigger the trace.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_call"> + <c>call</c></seealso>, + <seealso marker="#trace_3_trace_messages_return_from"> + <c>return_from</c></seealso>, and + <seealso marker="#trace_3_trace_messages_return_to"> + <c>return_to</c></seealso>. Or rather, the absence of.</p> </item> <tag><c>return_to</c></tag> <item> - <p>Used in conjunction with the <c>call</c> trace flag. - Trace the actual return from a traced function back to + <p>Used with the <c>call</c> trace flag. + Traces the return from a traced function back to its caller. Only works for functions traced with - the <c>local</c> option to - <seealso marker="#trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> + option <c>local</c> to <seealso marker="#trace_pattern/3"> + <c>erlang:trace_pattern/3</c></seealso>.</p> <p>The semantics is that a trace message is sent when a - call traced function actually returns, that is, when a - chain of tail recursive calls is ended. There will be - only one trace message sent per chain of tail recursive - calls, why the properties of tail recursiveness for + call traced function returns, that is, when a + chain of tail recursive calls ends. Only one trace + message is sent per chain of tail recursive calls, + so the properties of tail recursiveness for function calls are kept while tracing with this flag. Using <c>call</c> and <c>return_to</c> trace together makes it possible to know exactly in which function a process executes at any time.</p> <p>To get trace messages containing return values from - functions, use the <c>{return_trace}</c> match_spec - action instead.</p> - <p>Message tags: <c>return_to</c>.</p> + functions, use the <c>{return_trace}</c> match + specification action instead.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_return_to"> + <c>return_to</c></seealso>.</p> + </item> + <tag><c>procs</c></tag> + <item> + <p>Traces process-related events.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_spawn"> + <c>spawn</c></seealso>, + <seealso marker="#trace_3_trace_messages_spawned"> + <c>spawned</c></seealso>, + <seealso marker="#trace_3_trace_messages_exit"> + <c>exit</c></seealso>, + <seealso marker="#trace_3_trace_messages_register"> + <c>register</c></seealso>, + <seealso marker="#trace_3_trace_messages_unregister"> + <c>unregister</c></seealso>, + <seealso marker="#trace_3_trace_messages_link"> + <c>link</c></seealso>, + <seealso marker="#trace_3_trace_messages_unlink"> + <c>unlink</c></seealso>, + <seealso marker="#trace_3_trace_messages_getting_linked"> + <c>getting_linked</c></seealso>, and + <seealso marker="#trace_3_trace_messages_getting_unlinked"> + <c>getting_unlinked</c></seealso>.</p> + </item> + <tag><c>ports</c></tag> + <item> + <p>Traces port-related events.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_open"> + <c>open</c></seealso>, + <seealso marker="#trace_3_trace_messages_closed"> + <c>closed</c></seealso>, + <seealso marker="#trace_3_trace_messages_register"> + <c>register</c></seealso>, + <seealso marker="#trace_3_trace_messages_unregister"> + <c>unregister</c></seealso>, + <seealso marker="#trace_3_trace_messages_getting_linked"> + <c>getting_linked</c></seealso>, and + <seealso marker="#trace_3_trace_messages_getting_unlinked"> + <c>getting_unlinked</c></seealso>.</p> </item> <tag><c>running</c></tag> <item> - <p>Trace scheduling of processes.</p> - <p>Message tags: <c>in</c>, and <c>out</c>.</p> + <p>Traces scheduling of processes.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_in_proc"> + <c>in</c></seealso> and + <seealso marker="#trace_3_trace_messages_out_proc"> + <c>out</c></seealso>.</p> </item> <tag><c>exiting</c></tag> <item> - <p>Trace scheduling of an exiting processes.</p> - <p>Message tags: <c>in_exiting</c>, <c>out_exiting</c>, and - <c>out_exited</c>.</p> + <p>Traces scheduling of exiting processes.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_in_exiting_proc"> + <c>in_exiting</c></seealso>, + <seealso marker="#trace_3_trace_messages_out_exiting_proc"> + <c>out_exiting</c></seealso>, and + <seealso marker="#trace_3_trace_messages_out_exited_proc"> + <c>out_exited</c></seealso>.</p> + </item> + <tag><c>running_procs</c></tag> + <item> + <p>Traces scheduling of processes just like <c>running</c>. + However, this option also includes schedule events when the + process executes within the context of a port without + being scheduled out itself.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_in_proc"> + <c>in</c></seealso> and + <seealso marker="#trace_3_trace_messages_out_proc"> + <c>out</c></seealso>.</p> + </item> + <tag><c>running_ports</c></tag> + <item> + <p>Traces scheduling of ports.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_in_port"> + <c>in</c></seealso> and + <seealso marker="#trace_3_trace_messages_out_port"> + <c>out</c></seealso>.</p> </item> <tag><c>garbage_collection</c></tag> <item> - <p>Trace garbage collections of processes.</p> - <p>Message tags: <c>gc_start</c>, <c>gc_end</c>.</p> + <p>Traces garbage collections of processes.</p> + <p>Message tags: + <seealso marker="#trace_3_trace_messages_gc_minor_start"> + <c>gc_minor_start</c></seealso>, + <seealso marker="#trace_3_trace_messages_gc_max_heap_size"> + <c>gc_max_heap_size</c></seealso>, and + <seealso marker="#trace_3_trace_messages_gc_minor_end"> + <c>gc_minor_end</c></seealso>.</p> </item> <tag><c>timestamp</c></tag> <item> - <p>Include a time stamp in all trace messages. The time - stamp (Ts) is of the same form as returned by + <p>Includes a time stamp in all trace messages. The + time stamp (Ts) has the same form as returned by <c>erlang:now()</c>.</p> </item> <tag><c>cpu_timestamp</c></tag> <item> <p>A global trace flag for the Erlang node that makes all - trace timestamps be in CPU time, not wallclock. It is - only allowed with <c>PidSpec==all</c>. If the host - machine operating system does not support high resolution + trace time stamps using flag <c>timestamp</c> to be + in CPU time, not wall clock time. That is, <c>cpu_timestamp</c> + is not be used if <c>monotonic_timestamp</c> or + <c>strict_monotonic_timestamp</c> is enabled. + Only allowed with <c><anno>PidPortSpec</anno>==all</c>. If the + host machine OS does not support high-resolution CPU time measurements, <c>trace/3</c> exits with - <c>badarg</c>.</p> + <c>badarg</c>. Notice that most OS do + not synchronize this value across cores, so be prepared + that time can seem to go backwards when using this option.</p> + </item> + <tag><c>monotonic_timestamp</c></tag> + <item> + <p>Includes an + <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang + monotonic time</seealso> time stamp in all trace messages. The + time stamp (Ts) has the same format and value as produced by + <seealso marker="#monotonic_time-1"> + <c>erlang:monotonic_time(nanosecond)</c></seealso>. + This flag overrides flag <c>cpu_timestamp</c>.</p> + </item> + <tag><c>strict_monotonic_timestamp</c></tag> + <item> + <p>Includes an time stamp consisting of + <seealso marker="time_correction#Erlang_Monotonic_Time">Erlang + monotonic time</seealso> and a monotonically increasing + integer in all trace messages. The time stamp (Ts) has the + same format and value as produced by <c>{</c> + <seealso marker="#monotonic_time-1"> + <c>erlang:monotonic_time(nanosecond)</c></seealso><c>,</c> + <seealso marker="#unique_integer-1"> + <c>erlang:unique_integer([monotonic])</c></seealso><c>}</c>. + This flag overrides flag <c>cpu_timestamp</c>.</p> </item> <tag><c>arity</c></tag> <item> - <p>Used in conjunction with the <c>call</c> trace flag. - <c>{M, F, Arity}</c> will be specified instead of + <p>Used with the <c>call</c> trace flag. + <c>{M, F, Arity}</c> is specified instead of <c>{M, F, Args}</c> in call trace messages.</p> </item> <tag><c>set_on_spawn</c></tag> <item> <p>Makes any process created by a traced process inherit - its trace flags, including the <c>set_on_spawn</c> flag.</p> + its trace flags, including flag <c>set_on_spawn</c>.</p> </item> <tag><c>set_on_first_spawn</c></tag> <item> <p>Makes the first process created by a traced process - inherit its trace flags, excluding - the <c>set_on_first_spawn</c> flag.</p> + inherit its trace flags, excluding flag + <c>set_on_first_spawn</c>.</p> </item> <tag><c>set_on_link</c></tag> <item> <p>Makes any process linked by a traced process inherit its - trace flags, including the <c>set_on_link</c> flag.</p> + trace flags, including flag <c>set_on_link</c>.</p> </item> <tag><c>set_on_first_link</c></tag> <item> <p>Makes the first process linked to by a traced process - inherit its trace flags, excluding - the <c>set_on_first_link</c> flag.</p> + inherit its trace flags, excluding flag + <c>set_on_first_link</c>.</p> </item> <tag><c>{tracer, Tracer}</c></tag> <item> - <p>Specify where to send the trace messages. <c>Tracer</c> - must be the pid of a local process or the port identifier - of a local port. If this flag is not given, trace - messages will be sent to the process that called - <c>erlang:trace/3</c>.</p> + <p>Specifies where to send the trace messages. <c>Tracer</c> + must be the process identifier of a local process + or the port identifier of a local port.</p> + </item> + <tag><c>{tracer, TracerModule, TracerState}</c></tag> + <item> + <p>Specifies that a tracer module is to be called + instead of sending a trace message. The tracer module + can then ignore or change the trace message. For more details + on how to write a tracer module, see + <seealso marker="erts:erl_tracer"><c>erl_tracer(3)</c></seealso>.</p> </item> </taglist> + <p>If no <c>tracer</c> is specified, the calling process + receives all the trace messages.</p> <p>The effect of combining <c>set_on_first_link</c> with - <c>set_on_link</c> is the same as having + <c>set_on_link</c> is the same as <c>set_on_first_link</c> alone. Likewise for <c>set_on_spawn</c> and <c>set_on_first_spawn</c>.</p> - <p>If the <c>timestamp</c> flag is not given, the tracing - process will receive the trace messages described below. - <c>Pid</c> is the pid of the traced process in which - the traced event has occurred. The third element of the tuple - is the message tag.</p> - <p>If the <c>timestamp</c> flag is given, the first element of - the tuple will be <c>trace_ts</c> instead and the timestamp - is added last in the tuple.</p> + <p>The tracing process receives the <em>trace messages</em> described + in the following list. <c>Pid</c> is the process identifier of the + traced process in which the traced event has occurred. The + third tuple element is the message tag.</p> + <p>If flag <c>timestamp</c>, <c>strict_monotonic_timestamp</c>, or + <c>monotonic_timestamp</c> is specified, the first tuple + element is <c>trace_ts</c> instead, and the time stamp + is added as an extra element last in the message tuple. If + multiple time stamp flags are passed, <c>timestamp</c> has + precedence over <c>strict_monotonic_timestamp</c>, which + in turn has precedence over <c>monotonic_timestamp</c>. All + time stamp flags are remembered, so if two are passed + and the one with highest precedence later is disabled, + the other one becomes active.</p> + <p>Trace messages:</p> + <marker id="trace_3_trace_messages"></marker> <taglist> - <tag><c>{trace, Pid, 'receive', Msg}</c></tag> + <tag> + <marker id="trace_3_trace_messages_send"></marker> + <c>{trace, PidPort, send, Msg, To}</c> + </tag> <item> - <p>When <c>Pid</c> receives the message <c>Msg</c>.</p> + <p>When <c>PidPort</c> sends message <c>Msg</c> to + process <c>To</c>.</p> </item> - <tag><c>{trace, Pid, send, Msg, To}</c></tag> + <tag> + <marker id="trace_3_trace_messages_send_to_non_existing_process"/> + <c>{trace, PidPort, send_to_non_existing_process, Msg, To}</c> + </tag> <item> - <p>When <c>Pid</c> sends the message <c>Msg</c> to - the process <c>To</c>.</p> + <p>When <c>PidPort</c> sends message <c>Msg</c> to + the non-existing process <c>To</c>.</p> </item> - <tag><c>{trace, Pid, send_to_non_existing_process, Msg, To}</c></tag> + <tag> + <marker id="trace_3_trace_messages_receive"></marker> + <c>{trace, PidPort, 'receive', Msg}</c> + </tag> <item> - <p>When <c>Pid</c> sends the message <c>Msg</c> to - the non-existing process <c>To</c>.</p> + <p>When <c>PidPort</c> receives message <c>Msg</c>. + If <c>Msg</c> is set to time-out, a receive + statement can have timed out, or the process received + a message with the payload <c>timeout</c>.</p> </item> - <tag><c>{trace, Pid, call, {M, F, Args}}</c></tag> + <tag> + <marker id="trace_3_trace_messages_call"></marker> + <c>{trace, Pid, call, {M, F, Args}}</c> + </tag> <item> <p>When <c>Pid</c> calls a traced function. The return values of calls are never supplied, only the call and its arguments.</p> - <p>Note that the trace flag <c>arity</c> can be used to + <p>Trace flag <c>arity</c> can be used to change the contents of this message, so that <c>Arity</c> is specified instead of <c>Args</c>.</p> </item> - <tag><c>{trace, Pid, return_to, {M, F, Arity}}</c></tag> + <tag> + <marker id="trace_3_trace_messages_return_to"></marker> + <c>{trace, Pid, return_to, {M, F, Arity}}</c> + </tag> <item> <p>When <c>Pid</c> returns <em>to</em> the specified function. This trace message is sent if both - the <c>call</c> and the <c>return_to</c> flags are set, + the flags <c>call</c> and <c>return_to</c> are set, and the function is set to be traced on <em>local</em> function calls. The message is only sent when returning - from a chain of tail recursive function calls where at + from a chain of tail recursive function calls, where at least one call generated a <c>call</c> trace message - (that is, the functions match specification matched and + (that is, the functions match specification matched, and <c>{message, false}</c> was not an action).</p> </item> - <tag><c>{trace, Pid, return_from, {M, F, Arity}, ReturnValue}</c></tag> + <tag> + <marker id="trace_3_trace_messages_return_from"></marker> + <c>{trace, Pid, return_from, {M, F, Arity}, ReturnValue}</c> + </tag> <item> <p>When <c>Pid</c> returns <em>from</em> the specified - function. This trace message is sent if the <c>call</c> - flag is set, and the function has a match specification + function. This trace message is sent if flag <c>call</c> + is set, and the function has a match specification with a <c>return_trace</c> or <c>exception_trace</c> action.</p> </item> - <tag><c>{trace, Pid, exception_from, {M, F, Arity}, {Class, Value}}</c></tag> + <tag> + <marker id="trace_3_trace_messages_exception_from"></marker> + <c>{trace, Pid, exception_from, {M, F, Arity}, {Class, Value}}</c> + </tag> <item> <p>When <c>Pid</c> exits <em>from</em> the specified - function due to an exception. This trace message is sent - if the <c>call</c> flag is set, and the function has + function because of an exception. This trace message is + sent if flag <c>call</c> is set, and the function has a match specification with an <c>exception_trace</c> action.</p> </item> - <tag><c>{trace, Pid, spawn, Pid2, {M, F, Args}}</c></tag> + <tag> + <marker id="trace_3_trace_messages_spawn"></marker> + <c>{trace, Pid, spawn, Pid2, {M, F, Args}}</c> + </tag> <item> <p>When <c>Pid</c> spawns a new process <c>Pid2</c> with the specified function call as entry point.</p> - <p>Note that <c>Args</c> is supposed to be the argument - list, but may be any term in the case of an erroneous - spawn.</p> + <p><c>Args</c> is supposed to be the argument list, + but can be any term if the spawn is erroneous.</p> </item> - <tag><c>{trace, Pid, exit, Reason}</c></tag> + <tag> + <marker id="trace_3_trace_messages_spawned"></marker> + <c>{trace, Pid, spawned, Pid2, {M, F, Args}}</c> + </tag> + <item> + <p>When <c>Pid</c> is spawned by process <c>Pid2</c> with + the specified function call as entry point.</p> + <p><c>Args</c> is supposed to be the argument list, + but can be any term if the spawn is erroneous.</p> + </item> + <tag> + <marker id="trace_3_trace_messages_exit"></marker> + <c>{trace, Pid, exit, Reason}</c> + </tag> <item> <p>When <c>Pid</c> exits with reason <c>Reason</c>.</p> </item> - <tag><c>{trace, Pid, link, Pid2}</c></tag> + <tag> + <marker id="trace_3_trace_messages_register"></marker> + <c>{trace, PidPort, register, RegName}</c> + </tag> <item> - <p>When <c>Pid</c> links to a process <c>Pid2</c>.</p> + <p>When <c>PidPort</c> gets the name <c>RegName</c> registered.</p> </item> - <tag><c>{trace, Pid, unlink, Pid2}</c></tag> + <tag> + <marker id="trace_3_trace_messages_unregister"></marker> + <c>{trace, PidPort, unregister, RegName}</c> + </tag> <item> - <p>When <c>Pid</c> removes the link from a process - <c>Pid2</c>.</p> + <p>When <c>PidPort</c> gets the name <c>RegName</c> unregistered. + This is done automatically when a registered + process or port exits.</p> </item> - <tag><c>{trace, Pid, getting_linked, Pid2}</c></tag> + <tag> + <marker id="trace_3_trace_messages_link"></marker> + <c>{trace, Pid, link, Pid2}</c> + </tag> <item> - <p>When <c>Pid</c> gets linked to a process <c>Pid2</c>.</p> + <p>When <c>Pid</c> links to a process <c>Pid2</c>.</p> </item> - <tag><c>{trace, Pid, getting_unlinked, Pid2}</c></tag> + <tag> + <marker id="trace_3_trace_messages_unlink"></marker> + <c>{trace, Pid, unlink, Pid2}</c> + </tag> <item> - <p>When <c>Pid</c> gets unlinked from a process <c>Pid2</c>.</p> + <p>When <c>Pid</c> removes the link from a process + <c>Pid2</c>.</p> </item> - <tag><c>{trace, Pid, register, RegName}</c></tag> + <tag> + <marker id="trace_3_trace_messages_getting_linked"></marker> + <c>{trace, PidPort, getting_linked, Pid2}</c> + </tag> <item> - <p>When <c>Pid</c> gets the name <c>RegName</c> registered.</p> + <p>When <c>PidPort</c> gets linked to a process <c>Pid2</c>.</p> </item> - <tag><c>{trace, Pid, unregister, RegName}</c></tag> + <tag> + <marker id="trace_3_trace_messages_getting_unlinked"></marker> + <c>{trace, PidPort, getting_unlinked, Pid2}</c> + </tag> <item> - <p>When <c>Pid</c> gets the name <c>RegName</c> unregistered. - Note that this is done automatically when a registered - process exits.</p> + <p>When <c>PidPort</c> gets unlinked from a process <c>Pid2</c>.</p> </item> - <tag><c>{trace, Pid, in, {M, F, Arity} | 0}</c></tag> + <tag> + <marker id="trace_3_trace_messages_exit"></marker> + <c>{trace, Pid, exit, Reason}</c> + </tag> <item> - <p>When <c>Pid</c> is scheduled to run. The process will - run in function <c>{M, F, Arity}</c>. On some rare - occasions the current function cannot be determined, then - the last element <c>Arity</c> is 0.</p> + <p>When <c>Pid</c> exits with reason <c>Reason</c>.</p> </item> - <tag><c>{trace, Pid, out, {M, F, Arity} | 0}</c></tag> + <tag> + <marker id="trace_3_trace_messages_open"></marker> + <c>{trace, Port, open, Pid, Driver}</c> + </tag> + <item> + <p>When <c>Pid</c> opens a new port <c>Port</c> with + the running <c>Driver</c>.</p> + <p><c>Driver</c> is the name of the driver as an atom.</p> + </item> + <tag> + <marker id="trace_3_trace_messages_closed"></marker> + <c>{trace, Port, closed, Reason}</c> + </tag> + <item> + <p>When <c>Port</c> closes with <c>Reason</c>.</p> + </item> + <tag> + <marker id="trace_3_trace_messages_in_proc"></marker> + <marker id="trace_3_trace_messages_in_exiting_proc"></marker> + <c>{trace, Pid, in | in_exiting, {M, F, Arity} | 0}</c> + </tag> + <item> + <p>When <c>Pid</c> is scheduled to run. The process + runs in function <c>{M, F, Arity}</c>. On some rare + occasions, the current function cannot be determined, + then the last element is <c>0</c>.</p> + </item> + <tag> + <marker id="trace_3_trace_messages_out_proc"></marker> + <marker id="trace_3_trace_messages_out_exiting_proc"></marker> + <marker id="trace_3_trace_messages_out_exited_proc"></marker> + <c>{trace, Pid, out | out_exiting | out_exited, {M, F, Arity} + | 0}</c> + </tag> <item> <p>When <c>Pid</c> is scheduled out. The process was - running in function {M, F, Arity}. On some rare occasions + running in function {M, F, Arity}. On some rare occasions, + the current function cannot be determined, then the last + element is <c>0</c>.</p> + </item> + <tag> + <marker id="trace_3_trace_messages_in_port"></marker> + <c>{trace, Port, in, Command | 0}</c> + </tag> + <item> + <p>When <c>Port</c> is scheduled to run. <c>Command</c> is the + first thing the port will execute, it can however run several + commands before being scheduled out. On some rare + occasions, the current function cannot be determined, + then the last element is <c>0</c>.</p> + <p>The possible commands are <c>call</c>, <c>close</c>, + <c>command</c>, <c>connect</c>, <c>control</c>, <c>flush</c>, + <c>info</c>, <c>link</c>, <c>open</c>, and <c>unlink</c>.</p> + </item> + <tag> + <marker id="trace_3_trace_messages_out_port"></marker> + <c>{trace, Port, out, Command | 0}</c> + </tag> + <item> + <p>When <c>Port</c> is scheduled out. The last command run + was <c>Command</c>. On some rare occasions, the current function cannot be determined, then the last - element <c>Arity</c> is 0.</p> + element is <c>0</c>. <c>Command</c> can contain the same + commands as <c>in</c></p> </item> - <tag><marker id="gc_start"><c>{trace, Pid, gc_start, Info}</c></marker></tag> + <tag> + <marker id="trace_3_trace_messages_gc_minor_start"></marker> + <c>{trace, Pid, gc_minor_start, Info}</c> + </tag> <item> - <p>Sent when garbage collection is about to be started. + <marker id="gc_minor_start"></marker> + <p>Sent when a young garbage collection is about to be started. <c>Info</c> is a list of two-element tuples, where the first element is a key, and the second is the value. - You should not depend on the tuples have any defined - order. Currently, the following keys are defined:</p> + Do not depend on any order of the tuples. + The following keys are defined:</p> <taglist> <tag><c>heap_size</c></tag> <item>The size of the used part of the heap.</item> - <tag><c>heap_block_size</c></tag> - <item>The size of the memory block used for storing - the heap and the stack.</item> + <tag><c>heap_block_size</c></tag> + <item>The size of the memory block used for storing + the heap and the stack.</item> <tag><c>old_heap_size</c></tag> <item>The size of the used part of the old heap.</item> - <tag><c>old_heap_block_size</c></tag> - <item>The size of the memory block used for storing - the old heap.</item> + <tag><c>old_heap_block_size</c></tag> + <item>The size of the memory block used for storing + the old heap.</item> <tag><c>stack_size</c></tag> - <item>The actual size of the stack.</item> + <item>The size of the stack.</item> <tag><c>recent_size</c></tag> <item>The size of the data that survived the previous garbage - collection.</item> + collection.</item> <tag><c>mbuf_size</c></tag> <item>The combined size of message buffers associated with - the process.</item> - + the process.</item> <tag><c>bin_vheap_size</c></tag> - <item>The total size of unique off-heap binaries referenced from the process heap.</item> + <item>The total size of unique off-heap binaries referenced + from the process heap.</item> <tag><c>bin_vheap_block_size</c></tag> - <item>The total size of binaries, in words, allowed in the virtual - heap in the process before doing a garbage collection. </item> + <item>The total size of binaries allowed in the virtual + heap in the process before doing a garbage collection.</item> <tag><c>bin_old_vheap_size</c></tag> - <item>The total size of unique off-heap binaries referenced from the process old heap.</item> - <tag><c>bin_vheap_block_size</c></tag> - <item>The total size of binaries, in words, allowed in the virtual - old heap in the process before doing a garbage collection. </item> - - + <item>The total size of unique off-heap binaries referenced + from the process old heap.</item> + <tag><c>bin_old_vheap_block_size</c></tag> + <item>The total size of binaries allowed in the virtual + old heap in the process before doing a garbage + collection.</item> </taglist> <p>All sizes are in words.</p> </item> - <tag><c>{trace, Pid, gc_end, Info}</c></tag> - <item> - <p>Sent when garbage collection is finished. <c>Info</c> - contains the same kind of list as in the <c>gc_start</c> - message, but the sizes reflect the new sizes after + <tag> + <marker id="trace_3_trace_messages_gc_max_heap_size"></marker> + <c>{trace, Pid, gc_max_heap_size, Info}</c> + </tag> + <item> + <p>Sent when the <seealso marker="#process_flag_max_heap_size"> + <c>max_heap_size</c></seealso> + is reached during garbage collection. <c>Info</c> contains the + same kind of list as in message <c>gc_start</c>, + but the sizes reflect the sizes that triggered + <c>max_heap_size</c> to be reached.</p> + </item> + <tag> + <marker id="trace_3_trace_messages_gc_minor_end"></marker> + <c>{trace, Pid, gc_minor_end, Info}</c> + </tag> + <item> + <p>Sent when young garbage collection is finished. <c>Info</c> + contains the same kind of list as in message + <c>gc_minor_start</c>, + but the sizes reflect the new sizes after garbage collection.</p> </item> + <tag> + <marker id="trace_3_trace_messages_gc_major_start"></marker> + <c>{trace, Pid, gc_major_start, Info}</c> + </tag> + <item> + <p>Sent when fullsweep garbage collection is about to be started. + <c>Info</c> contains the same kind of list as in message + <c>gc_minor_start</c>.</p> + </item> + <tag> + <marker id="trace_3_trace_messages_gc_major_end"></marker> + <c>{trace, Pid, gc_major_end, Info}</c> + </tag> + <item> + <p>Sent when fullsweep garbage collection is finished. <c>Info</c> + contains the same kind of list as in message + <c>gc_minor_start</c>, but the sizes reflect the new sizes after + a fullsweep garbage collection.</p> + </item> </taglist> - <p>If the tracing process dies, the flags will be silently - removed.</p> - <p>Only one process can trace a particular process. For this - reason, attempts to trace an already traced process will fail.</p> - <p>Returns: A number indicating the number of processes that - matched <c><anno>PidSpec</anno></c>. If <c><anno>PidSpec</anno></c> is a pid, - the return value will be <c>1</c>. If <c><anno>PidSpec</anno></c> is - <c>all</c> or <c>existing</c> the return value will be - the number of processes running, excluding tracer processes. - If <c><anno>PidSpec</anno></c> is <c>new</c>, the return value will be + <p>If the tracing process/port dies or the tracer module returns + <c>remove</c>, the flags are silently removed.</p> + <p>Each process can only be traced by one tracer. Therefore, + attempts to trace an already traced process fail.</p> + <p>Returns a number indicating the number of processes that + matched <c><anno>PidPortSpec</anno></c>. + If <c><anno>PidPortSpec</anno></c> is a process + identifier, the return value is <c>1</c>. + If <c><anno>PidPortSpec</anno></c> + is <c>all</c> or <c>existing</c>, the return value is + the number of processes running. + If <c><anno>PidPortSpec</anno></c> is <c>new</c>, the return value is <c>0</c>.</p> - <p>Failure: If specified arguments are not supported. For - example <c>cpu_timestamp</c> is not supported on all - platforms.</p> + <p>Failure: <c>badarg</c> if the specified arguments are + not supported. For example, <c>cpu_timestamp</c> is not + supported on all platforms.</p> </desc> </func> + <func> <name name="trace_delivered" arity="1"/> - <fsummary>Notification when trace has been delivered</fsummary> - <desc> - <p>The delivery of trace messages is dislocated on the time-line - compared to other events in the system. If you know that the - <c><anno>Tracee</anno></c> has passed some specific point in its execution, + <fsummary>Notification when trace has been delivered.</fsummary> + <desc> + <p>The delivery of trace messages (generated by + <seealso marker="#trace/3"><c>erlang:trace/3</c></seealso>, + <seealso marker="kernel:seq_trace"><c>seq_trace(3)</c></seealso>, + or <seealso marker="#system_profile/2"> + <c>erlang:system_profile/2</c></seealso>) + is dislocated on the time-line + compared to other events in the system. If you know that + <c><anno>Tracee</anno></c> has passed some specific point + in its execution, and you want to know when at least all trace messages - corresponding to events up to this point have reached the tracer - you can use <c>erlang:trace_delivered(<anno>Tracee</anno>)</c>. A - <c>{trace_delivered, <anno>Tracee</anno>, <anno>Ref</anno>}</c> message is sent to - the caller of <c>erlang:trace_delivered(<anno>Tracee</anno>)</c> when it - is guaranteed that all trace messages have been delivered to - the tracer up to the point that the <c><anno>Tracee</anno></c> had reached + corresponding to events up to this point have reached the + tracer, use <c>erlang:trace_delivered(<anno>Tracee</anno>)</c>.</p> + <p>When it is guaranteed that all trace messages are delivered to + the tracer up to the point that <c><anno>Tracee</anno></c> reached at the time of the call to - <c>erlang:trace_delivered(<anno>Tracee</anno>)</c>.</p> - <p>Note that the <c>trace_delivered</c> message does <em>not</em> - imply that trace messages have been delivered; instead, it implies - that all trace messages that <em>should</em> be delivered have - been delivered. It is not an error if <c><anno>Tracee</anno></c> isn't, and - hasn't been traced by someone, but if this is the case, - <em>no</em> trace messages will have been delivered when the + <c>erlang:trace_delivered(<anno>Tracee</anno>)</c>, then a + <c>{trace_delivered, <anno>Tracee</anno>, <anno>Ref</anno>}</c> + message is sent to the caller of + <c>erlang:trace_delivered(<anno>Tracee</anno>)</c> .</p> + <p>Notice that message <c>trace_delivered</c> does <em>not</em> + imply that trace messages have been delivered. + Instead it implies that all trace messages that + <em>are to be delivered</em> have been delivered. + It is not an error if <c><anno>Tracee</anno></c> is not, and + has not been traced by someone, but if this is the case, + <em>no</em> trace messages have been delivered when the <c>trace_delivered</c> message arrives.</p> - <p>Note that <c><anno>Tracee</anno></c> has to refer to a process currently, + <p>Notice that <c><anno>Tracee</anno></c> must refer + to a process currently or previously existing on the same node as the caller of <c>erlang:trace_delivered(<anno>Tracee</anno>)</c> resides on. - The special <c><anno>Tracee</anno></c> atom <c>all</c> denotes all processes - that currently are traced in the node.</p> - <p>An example: Process <c>A</c> is <c><anno>Tracee</anno></c>, port <c>B</c> is - tracer, and process <c>C</c> is the port owner of <c>B</c>. - <c>C</c> wants to close <c>B</c> when <c>A</c> exits. <c>C</c> - can ensure that the trace isn't truncated by calling - <c>erlang:trace_delivered(A)</c> when <c>A</c> exits and wait - for the <c>{trace_delivered, A, <anno>Ref</anno>}</c> message before closing - <c>B</c>.</p> - <p>Failure: <c>badarg</c> if <c><anno>Tracee</anno></c> does not refer to a + The special <c><anno>Tracee</anno></c> atom <c>all</c> + denotes all processes that currently are traced in the node.</p> + <p>When used together with a <seealso marker="erts:erl_tracer"> + Tracer Module</seealso>, any message sent in the trace callback + is guaranteed to have reached its recipient before the + <c>trace_delivered</c> message is sent.</p> + <p>Example: Process <c>A</c> is <c><anno>Tracee</anno></c>, + port <c>B</c> is tracer, and process <c>C</c> is the port + owner of <c>B</c>. <c>C</c> wants to close <c>B</c> when + <c>A</c> exits. To ensure that the trace is not truncated, + <c>C</c> can call <c>erlang:trace_delivered(A)</c> when + <c>A</c> exits, and wait for message <c>{trace_delivered, A, + <anno>Ref</anno>}</c> before closing <c>B</c>.</p> + <p>Failure: <c>badarg</c> if <c><anno>Tracee</anno></c> + does not refer to a process (dead or alive) on the same node as the caller of <c>erlang:trace_delivered(<anno>Tracee</anno>)</c> resides on.</p> </desc> </func> + <func> <name name="trace_info" arity="2"/> + <fsummary>Trace information about a process or function.</fsummary> <type name="trace_info_return"/> <type name="trace_info_item_result"/> <type name="trace_info_flag"/> <type name="trace_match_spec"/> - <fsummary>Trace information about a process or function</fsummary> - <desc> - <p>Returns trace information about a process or function.</p> - <p>To get information about a process, <c><anno>PidOrFunc</anno></c> should - be a pid or the atom <c>new</c>. The atom <c>new</c> means - that the default trace state for processes to be created will - be returned. <c><anno>Item</anno></c> must have one of the following - values:</p> + <type name="match_variable"/> + <type_desc name="match_variable"> + Approximation of '$1' | '$2' | '$3' | ... + </type_desc> + <desc> + <p>Returns trace information about a port, process, function, or + event.</p> + <p><em>To get information about a port or process</em>, + <c><anno>PidPortFuncEvent</anno></c> is to + be a process identifier (pid), port identifier, or one of + the atoms <c>new</c>, <c>new_processes</c>, or <c>new_ports</c>. The + atom <c>new</c> or <c>new_processes</c> means that the default trace + state for processes to be created is returned. The atom + <c>new_ports</c> means that the default trace state for ports to be + created is returned.</p> + <p>Valid <c>Item</c>s for ports and processes:</p> <taglist> <tag><c>flags</c></tag> <item> - <p>Return a list of atoms indicating what kind of traces is - enabled for the process. The list will be empty if no + <p>Returns a list of atoms indicating what kind of traces is + enabled for the process. The list is empty if no traces are enabled, and one or more of the followings atoms if traces are enabled: <c>send</c>, <c>'receive'</c>, <c>set_on_spawn</c>, <c>call</c>, - <c>return_to</c>, <c>procs</c>, <c>set_on_first_spawn</c>, - <c>set_on_link</c>, <c>running</c>, + <c>return_to</c>, <c>procs</c>, <c>ports</c>, + <c>set_on_first_spawn</c>, + <c>set_on_link</c>, <c>running</c>, <c>running_procs</c>, + <c>running_ports</c>, <c>silent</c>, <c>exiting</c>, + <c>monotonic_timestamp</c>, <c>strict_monotonic_timestamp</c>, <c>garbage_collection</c>, <c>timestamp</c>, and <c>arity</c>. The order is arbitrary.</p> </item> <tag><c>tracer</c></tag> <item> - <p>Return the identifier for process or port tracing this - process. If this process is not being traced, the return - value will be <c>[]</c>.</p> + <p>Returns the identifier for process, port, or a tuple containing + the tracer module and tracer state tracing this + process. If this process is not traced, the return + value is <c>[]</c>.</p> </item> </taglist> - <p>To get information about a function, <c>PidOrFunc</c> should - be a three-element tuple: <c>{Module, Function, Arity}</c> or + <p><em>To get information about a function</em>, + <c><anno>PidPortFuncEvent</anno></c> is to + be the three-element tuple <c>{Module, Function, Arity}</c> or the atom <c>on_load</c>. No wildcards are allowed. Returns - <c>undefined</c> if the function does not exist or - <c>false</c> if the function is not traced at all. <c>Item</c> - must have one of the following values:</p> + <c>undefined</c> if the function does not exist, or + <c>false</c> if the function is not traced. + If <c><anno>PidPortFuncEvent</anno></c> + is <c>on_load</c>, the information returned refers to + the default value for code that will be loaded.</p> + <p>Valid <c>Item</c>s for functions:</p> <taglist> <tag><c>traced</c></tag> <item> - <p>Return <c>global</c> if this function is traced on + <p>Returns <c>global</c> if this function is traced on global function calls, <c>local</c> if this function is - traced on local function calls (i.e local and global - function calls), and <c>false</c> if neither local nor - global function calls are traced.</p> + traced on local function calls (that is, local and global + function calls), and <c>false</c> if local or + global function calls are not traced.</p> </item> <tag><c>match_spec</c></tag> <item> - <p>Return the match specification for this function, if it + <p>Returns the match specification for this function, if it has one. If the function is locally or globally traced but has no match specification defined, the returned value is <c>[]</c>.</p> </item> <tag><c>meta</c></tag> <item> - <p>Return the meta trace tracer process or port for this - function, if it has one. If the function is not meta - traced the returned value is <c>false</c>, and if - the function is meta traced but has once detected that - the tracer proc is invalid, the returned value is [].</p> + <p>Returns the meta-trace tracer process, port, or trace module + for this function, if it has one. If the function is not + meta-traced, the returned value is <c>false</c>. If + the function is meta-traced but has once detected that + the tracer process is invalid, the returned value is + <c>[]</c>.</p> </item> <tag><c>meta_match_spec</c></tag> <item> - <p>Return the meta trace match specification for this - function, if it has one. If the function is meta traced + <p>Returns the meta-trace match specification for this + function, if it has one. If the function is meta-traced but has no match specification defined, the returned value is <c>[]</c>.</p> </item> <tag><c>call_count</c></tag> <item> - <p>Return the call count value for this function or + <p>Returns the call count value for this function or <c>true</c> for the pseudo function <c>on_load</c> if call - count tracing is active. Return <c>false</c> otherwise. - See also - <seealso marker="#trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> + count tracing is active. Otherwise <c>false</c> is returned.</p> + <p>See also <seealso marker="#trace_pattern/3"> + <c>erlang:trace_pattern/3</c></seealso>.</p> </item> <tag><c>call_time</c></tag> <item> - <p>Return the call time values for this function or + <p>Returns the call time values for this function or <c>true</c> for the pseudo function <c>on_load</c> if call - time tracing is active. Returns <c>false</c> otherwise. - The call time values returned, <c>[{Pid, Count, S, Us}]</c>, - is a list of each process that has executed the function and its specific counters. - See also - <seealso marker="#trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> + time tracing is active. Otherwise <c>false</c> is returned. + The call time values returned, <c>[{Pid, Count, S, Us}]</c>, + is a list of each process that executed the function + and its specific counters.</p> + <p>See also + <seealso marker="#trace_pattern/3"> + <c>erlang:trace_pattern/3</c></seealso>.</p> </item> - <tag><c>all</c></tag> <item> - <p>Return a list containing the <c>{<anno>Item</anno>, Value}</c> tuples - for all other items, or return <c>false</c> if no tracing + <p>Returns a list containing the + <c>{<anno>Item</anno>, Value}</c> tuples + for all other items, or returns <c>false</c> if no tracing is active for this function.</p> </item> </taglist> - <p>The actual return value will be <c>{<anno>Item</anno>, Value}</c>, where - <c>Value</c> is the requested information as described above. - If a pid for a dead process was given, or the name of a - non-existing function, <c>Value</c> will be <c>undefined</c>.</p> - <p>If <c><anno>PidOrFunc</anno></c> is the <c>on_load</c>, the information - returned refers to the default value for code that will be - loaded.</p> + <p><em>To get information about an event</em>, + <c><anno>PidPortFuncEvent</anno></c> is to + be one of the atoms <c>send</c> or <c>'receive'</c>.</p> + <p>One valid <c>Item</c> for events exists:</p> + <taglist> + <tag><c>match_spec</c></tag> + <item> + <p>Returns the match specification for this event, if it + has one, or <c>true</c> if no match specification has been + set.</p> + </item> + </taglist> + <p>The return value is <c>{<anno>Item</anno>, Value}</c>, where + <c>Value</c> is the requested information as described earlier. + If a pid for a dead process was specified, or the name of a + non-existing function, <c>Value</c> is <c>undefined</c>.</p> </desc> </func> + <func> <name name="trace_pattern" arity="2" clause_i="1"/> + <fsummary>Set trace patterns for call, send, or 'receive' tracing. + </fsummary> <type name="trace_pattern_mfa"/> <type name="trace_match_spec"/> - <fsummary>Set trace patterns for global call tracing</fsummary> + <type_desc name="match_variable"> + Approximation of '$1' | '$2' | '$3' | ... + </type_desc> + <type name="match_variable"/> <desc> <p>The same as - <seealso marker="#trace_pattern/3">erlang:trace_pattern(MFA, MatchSpec, [])</seealso>, + <seealso marker="#trace_pattern/3"> + <c>erlang:trace_pattern(Event, MatchSpec, [])</c></seealso>, retained for backward compatibility.</p> </desc> </func> + + <func> + <name name="trace_pattern" arity="3" clause_i="1"/> + <fsummary>Set trace pattern for message sending.</fsummary> + <type name="trace_match_spec"/> + <type name="match_variable"/> + <type_desc name="match_variable"> + Approximation of '$1' | '$2' | '$3' | ... + </type_desc> + <desc> + <p>Sets trace pattern for <em>message sending</em>. + Must be combined with + <seealso marker="#trace/3"><c>erlang:trace/3</c></seealso> + to set the <c>send</c> trace flag for one or more processes. + By default all messages sent from <c>send</c> traced processes + are traced. To limit + traced send events based on the message content, the sender + and/or the receiver, use <c>erlang:trace_pattern/3</c>.</p> + <p>Argument <c><anno>MatchSpec</anno></c> can take the + following forms:</p> + <taglist> + <tag><c><anno>MatchSpecList</anno></c></tag> + <item> + <p>A list of match specifications. The matching is done + on the list <c>[Receiver, Msg]</c>. <c>Receiver</c> + is the process or port identity of the receiver and + <c>Msg</c> is the message term. The pid of the sending + process can be accessed with the guard function + <c>self/0</c>. An empty list is the same as <c>true</c>. + For more information, see section + <seealso marker="erts:match_spec"> + Match Specifications in Erlang</seealso> in the User's Guide.</p> + </item> + <tag><c>true</c></tag> + <item> + <p>Enables tracing for all sent messages (from <c>send</c> + traced processes). Any match specification is + removed. <em>This is the default</em>.</p> + </item> + <tag><c>false</c></tag> + <item> + <p>Disables tracing for all sent messages. + Any match specification is removed.</p> + </item> + </taglist> + <p>Argument <c><anno>FlagList</anno></c> must be <c>[]</c> + for send tracing.</p> + <p>The return value is always <c>1</c>.</p> + <p>Examples:</p> + <p>Only trace messages to a specific process <c>Pid</c>:</p> + <pre> +> <input>erlang:trace_pattern(send, [{[Pid, '_'],[],[]}], []).</input> +1</pre> + <p>Only trace messages matching <c>{reply, _}</c>:</p> + <pre> +> <input>erlang:trace_pattern(send, [{['_', {reply,'_'}],[],[]}], []).</input> +1</pre> + <p>Only trace messages sent to the sender itself:</p> + <pre> +> <input>erlang:trace_pattern(send, [{['$1', '_'],[{'=:=','$1',{self}}],[]}], []).</input> +1</pre> + <p>Only trace messages sent to other nodes:</p> + <pre> +> <input>erlang:trace_pattern(send, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).</input> +1</pre> + <note> + <p>A match specification for <c>send</c> trace can use + all guard and body functions except <c>caller</c>.</p> + </note> + </desc> + </func> + + <func> + <name name="trace_pattern" arity="3" clause_i="2"/> + <fsummary>Set trace pattern for tracing of message receiving.</fsummary> + <type name="trace_match_spec"/> + <type name="match_variable"/> + <type_desc name="match_variable"> + Approximation of '$1' | '$2' | '$3' | ... + </type_desc> + <desc> + <p>Sets trace pattern for <em>message receiving</em>. + Must be combined with + <seealso marker="#trace/3"><c>erlang:trace/3</c></seealso> + to set the <c>'receive'</c> trace flag for one or more processes. + By default all messages received by <c>'receive'</c> traced + processes are traced. To limit + traced receive events based on the message content, the sender + and/or the receiver, use <c>erlang:trace_pattern/3</c>.</p> + <p>Argument <c><anno>MatchSpec</anno></c> can take the + following forms:</p> + <taglist> + <tag><c><anno>MatchSpecList</anno></c></tag> + <item> + <p>A list of match specifications. The matching is done + on the list <c>[Node, Sender, Msg]</c>. <c>Node</c> + is the node name of the sender. <c>Sender</c> is the + process or port identity of the sender, or the atom + <c>undefined</c> if the sender is not known (which can + be the case for remote senders). <c>Msg</c> is the + message term. The pid of the receiving process can be + accessed with the guard function <c>self/0</c>. An empty + list is the same as <c>true</c>. For more information, see + section <seealso marker="erts:match_spec"> + Match Specifications in Erlang</seealso> in the User's Guide.</p> + </item> + <tag><c>true</c></tag> + <item> + <p>Enables tracing for all received messages (to <c>'receive'</c> + traced processes). Any match specification is + removed. <em>This is the default</em>.</p> + </item> + <tag><c>false</c></tag> + <item> + <p>Disables tracing for all received messages. + Any match specification is removed.</p> + </item> + </taglist> + <p>Argument <c><anno>FlagList</anno></c> must be <c>[]</c> + for receive tracing.</p> + <p>The return value is always <c>1</c>.</p> + <p>Examples:</p> + <p>Only trace messages from a specific process <c>Pid</c>:</p> + <pre> +> <input>erlang:trace_pattern('receive', [{['_',Pid, '_'],[],[]}], []).</input> +1</pre> + <p>Only trace messages matching <c>{reply, _}</c>:</p> + <pre> +> <input>erlang:trace_pattern('receive', [{['_','_', {reply,'_'}],[],[]}], []).</input> +1</pre> + <p>Only trace messages from other nodes:</p> + <pre> +> <input>erlang:trace_pattern('receive', [{['$1', '_', '_'],[{'=/=','$1',{node}}],[]}], []).</input> +1</pre> + <note> + <p>A match specification for <c>'receive'</c> trace can + use all guard and body functions except <c>caller</c>, + <c>is_seq_trace</c>, <c>get_seq_token</c>, <c>set_seq_token</c>, + <c>enable_trace</c>, <c>disable_trace</c>, <c>trace</c>, + <c>silent</c>, and <c>process_dump</c>.</p> + </note> + </desc> + </func> + <func> - <name name="trace_pattern" arity="3"/> + <name name="trace_pattern" arity="3" clause_i="3"/> + <fsummary>Set trace patterns for tracing of function calls.</fsummary> <type name="trace_pattern_mfa"/> <type name="trace_match_spec"/> <type name="trace_pattern_flag"/> - <fsummary>Set trace patterns for tracing of function calls</fsummary> - <desc> - <p>This BIF is used to enable or disable call tracing for - exported functions. It must be combined with - <seealso marker="#trace/3">erlang:trace/3</seealso> - to set the <c>call</c> trace flag for one or more processes.</p> - <p>Conceptually, call tracing works like this: Inside - the Erlang virtual machine there is a set of processes to be - traced and a set of functions to be traced. Tracing will be - enabled on the intersection of the set. That is, if a process - included in the traced process set calls a function included - in the traced function set, the trace action will be taken. - Otherwise, nothing will happen.</p> - <p>Use - <seealso marker="#trace/3">erlang:trace/3</seealso> to - add or remove one or more processes to the set of traced - processes. Use <c>erlang:trace_pattern/2</c> to add or remove - exported functions to the set of traced functions.</p> - <p>The <c>erlang:trace_pattern/3</c> BIF can also add match - specifications to an exported function. A match specification - comprises a pattern that the arguments to the function must - match, a guard expression which must evaluate to <c>true</c> + <type name="match_variable"/> + <type_desc name="match_variable"> + Approximation of '$1' | '$2' | '$3' | ... + </type_desc> + <desc> + <p>Enables or disables <em>call tracing</em> for one or more functions. + Must be combined with + <seealso marker="#trace/3"><c>erlang:trace/3</c></seealso> + to set the <c>call</c> trace flag + for one or more processes.</p> + <p>Conceptually, call tracing works as follows. Inside + the Erlang virtual machine, a set of processes and + a set of functions are to be traced. If a traced process + calls a traced function, the trace action is taken. + Otherwise, nothing happens.</p> + <p>To add or remove one or more processes to the set of traced + processes, use + <seealso marker="#trace/3"><c>erlang:trace/3</c></seealso>.</p> + <p>To add or remove functions to the set of traced + functions, use <c>erlang:trace_pattern/3</c>.</p> + <p>The BIF <c>erlang:trace_pattern/3</c> can also add match + specifications to a function. A match specification + comprises a pattern that the function arguments must + match, a guard expression that must evaluate to <c>true</c>, and an action to be performed. The default action is to send a trace message. If the pattern does not match or the guard - fails, the action will not be executed.</p> - <p>The <c><anno>MFA</anno></c> argument should be a tuple like - <c>{Module, Function, Arity}</c> or the atom <c>on_load</c> - (described below). It can be the module, function, and arity - for an exported function (or a BIF in any module). - The <c>'_'</c> atom can be used to mean any of that kind. - Wildcards can be used in any of the following ways:</p> + fails, the action is not executed.</p> + <p>Argument <c><anno>MFA</anno></c> is to be a tuple, such as + <c>{Module, Function, Arity}</c>, or the atom <c>on_load</c> + (described below). It can be the module, function, + and arity for a function (or a BIF in any module). + The atom <c>'_'</c> can be used as a wildcard in any of the + following ways:</p> <taglist> <tag><c>{Module,Function,'_'}</c></tag> <item> - <p>All exported functions of any arity named <c>Function</c> + <p>All functions of any arity named <c>Function</c> in module <c>Module</c>.</p> </item> <tag><c>{Module,'_','_'}</c></tag> <item> - <p>All exported functions in module <c>Module</c>.</p> + <p>All functions in module <c>Module</c>.</p> </item> <tag><c>{'_','_','_'}</c></tag> <item> - <p>All exported functions in all loaded modules.</p> + <p>All functions in all loaded modules.</p> </item> </taglist> <p>Other combinations, such as <c>{Module,'_',Arity}</c>, are - not allowed. Local functions will match wildcards only if - the <c>local</c> option is in the <c><anno>FlagList</anno></c>.</p> - <p>If the <c><anno>MFA</anno></c> argument is the atom <c>on_load</c>, - the match specification and flag list will be used on all + not allowed. Local functions match wildcards only if + option <c>local</c> is in <c><anno>FlagList</anno></c>.</p> + <p>If argument <c><anno>MFA</anno></c> is the atom <c>on_load</c>, + the match specification and flag list are used on all modules that are newly loaded.</p> - <p>The <c><anno>MatchSpec</anno></c> argument can take any of the following - forms:</p> + <p>Argument <c><anno>MatchSpec</anno></c> can take the + following forms:</p> <taglist> <tag><c>false</c></tag> <item> - <p>Disable tracing for the matching function(s). Any match - specification will be removed.</p> + <p>Disables tracing for the matching functions. + Any match specification is removed.</p> </item> <tag><c>true</c></tag> <item> - <p>Enable tracing for the matching function(s).</p> + <p>Enables tracing for the matching functions. + Any match specification is removed.</p> </item> <tag><c><anno>MatchSpecList</anno></c></tag> <item> <p>A list of match specifications. An empty list is - equivalent to <c>true</c>. See the ERTS User's Guide - for a description of match specifications.</p> + equivalent to <c>true</c>. For a description of match + specifications, see section <seealso marker="erts:match_spec"> + Match Specifications in Erlang</seealso> in the User's Guide.</p> </item> <tag><c>restart</c></tag> <item> - <p>For the <c><anno>FlagList</anno></c> option <c>call_count</c> and <c>call_time</c>: - restart the existing counters. The behaviour is undefined + <p>For the <c><anno>FlagList</anno></c> options <c>call_count</c> + and <c>call_time</c>: restarts + the existing counters. The behavior is undefined for other <c><anno>FlagList</anno></c> options.</p> </item> <tag><c>pause</c></tag> <item> - <p>For the <c><anno>FlagList</anno></c> option <c>call_count</c> and <c>call_time</c>: pause - the existing counters. The behaviour is undefined for - other <c>FlagList</c> options.</p> + <p>For the <c><anno>FlagList</anno></c> options + <c>call_count</c> and <c>call_time</c>: pauses + the existing counters. The behavior is undefined for + other <c><anno>FlagList</anno></c> options.</p> </item> </taglist> - <p>The <c><anno>FlagList</anno></c> parameter is a list of options. - The following options are allowed:</p> + <p>Parameter <c><anno>FlagList</anno></c> is a list of options. + The following are the valid options:</p> <taglist> <tag><c>global</c></tag> <item> - <p>Turn on or off call tracing for global function calls + <p>Turns on or off call tracing for global function calls (that is, calls specifying the module explicitly). Only - exported functions will match and only global calls will - generate trace messages. This is the default.</p> + exported functions match and only global calls + generate trace messages. <em>This is the default</em>.</p> </item> <tag><c>local</c></tag> <item> - <p>Turn on or off call tracing for all types of function - calls. Trace messages will be sent whenever any of + <p>Turns on or off call tracing for all types of function + calls. Trace messages are sent whenever any of the specified functions are called, regardless of how they - are called. If the <c>return_to</c> flag is set for - the process, a <c>return_to</c> message will also be sent + are called. If flag <c>return_to</c> is set for + the process, a <c>return_to</c> message is also sent when this function returns to its caller.</p> </item> - <tag><c>meta | {meta, <anno>Pid</anno>}</c></tag> + <tag><c>meta | {meta, <anno>Pid</anno>} | + {meta, <anno>TracerModule</anno>, <anno>TracerState</anno>}</c> + </tag> <item> - <p>Turn on or off meta tracing for all types of function - calls. Trace messages will be sent to the tracer process - or port <c><anno>Pid</anno></c> whenever any of the specified - functions are called, regardless of how they are called. - If no <c><anno>Pid</anno></c> is specified, <c>self()</c> is used as a - default tracer process.</p> - <p>Meta tracing traces all processes and does not care - about the process trace flags set by <c>trace/3</c>, + <p>Turns on or off meta-tracing for all types of function + calls. Trace messages are sent to the tracer whenever any of + the specified functions are called. If no tracer is specified, + <c>self()</c> is used as a default tracer process.</p> + <p>Meta-tracing traces all processes and does not care + about the process trace flags set by <c>erlang:trace/3</c>, the trace flags are instead fixed to <c>[call, timestamp]</c>.</p> - <p>The match spec function <c>{return_trace}</c> works with - meta trace and send its trace message to the same tracer - process.</p> + <p>The match specification function <c>{return_trace}</c> + works with meta-trace and sends its trace message to the + same tracer.</p> </item> <tag><c>call_count</c></tag> <item> <p>Starts (<c><anno>MatchSpec</anno> == true</c>) or stops - (<c><anno>MatchSpec</anno> == false</c>) call count tracing for all - types of function calls. For every function a counter is + (<c><anno>MatchSpec</anno> == false</c>) + call count tracing for all + types of function calls. For every function, a counter is incremented when the function is called, in any process. No process trace flags need to be activated.</p> <p>If call count tracing is started while already running, - the count is restarted from zero. Running counters can be - paused with <c><anno>MatchSpec</anno> == pause</c>. Paused and running - counters can be restarted from zero with + the count is restarted from zero. To pause running + counters, use <c><anno>MatchSpec</anno> == pause</c>. + Paused and running counters can be restarted from zero with <c><anno>MatchSpec</anno> == restart</c>.</p> - <p>The counter value can be read with - <seealso marker="#trace_info/2">erlang:trace_info/2</seealso>.</p> + <p>To read the counter value, use + <seealso marker="#trace_info/2"> + <c>erlang:trace_info/2</c></seealso>.</p> </item> <tag><c>call_time</c></tag> <item> <p>Starts (<c><anno>MatchSpec</anno> == true</c>) or stops - (<c><anno>MatchSpec</anno> == false</c>) call time tracing for all - types of function calls. For every function a counter is - incremented when the function is called. Time spent in the function - is accumulated in two other counters, seconds and micro-seconds. - The counters are stored for each call traced process.</p> + (<c><anno>MatchSpec</anno> == false</c>) call time + tracing for all + types of function calls. For every function, a counter is + incremented when the function is called. + Time spent in the function is accumulated in + two other counters, seconds and microseconds. + The counters are stored for each call traced process.</p> <p>If call time tracing is started while already running, - the count and time is restarted from zero. Running counters can be - paused with <c><anno>MatchSpec</anno> == pause</c>. Paused and running - counters can be restarted from zero with + the count and time restart from zero. To pause + running counters, use <c><anno>MatchSpec</anno> == pause</c>. + Paused and running counters can be restarted from zero with <c><anno>MatchSpec</anno> == restart</c>.</p> - <p>The counter value can be read with - <seealso marker="#trace_info/2">erlang:trace_info/2</seealso>.</p> + <p>To read the counter value, use + <seealso marker="#trace_info/2"> + <c>erlang:trace_info/2</c></seealso>.</p> </item> - </taglist> - <p>The <c>global</c> and <c>local</c> options are mutually - exclusive and <c>global</c> is the default (if no options are - specified). The <c>call_count</c> and <c>meta</c> options - perform a kind of local tracing, and can also not be combined - with <c>global</c>. A function can be either globally or + <p>The options <c>global</c> and <c>local</c> are mutually + exclusive, and <c>global</c> is the default (if no options are + specified). The options <c>call_count</c> and <c>meta</c> + perform a kind of local tracing, and cannot be combined + with <c>global</c>. A function can be globally or locally traced. If global tracing is specified for a - specified set of functions; local, meta, call time and call count - tracing for the matching set of local functions will be - disabled, and vice versa.</p> + set of functions, then local, meta, call time, and call count + tracing for the matching set of local functions is + disabled, and conversely.</p> <p>When disabling trace, the option must match the type of trace - that is set on the function, so that local tracing must be - disabled with the <c>local</c> option and global tracing with - the <c>global</c> option (or no option at all), and so forth.</p> - <p>There is no way to directly change part of a match - specification list. If a function has a match specification, - you can replace it with a completely new one. If you need to - change an existing match specification, use the - <seealso marker="#trace_info/2">erlang:trace_info/2</seealso> - BIF to retrieve the existing match specification.</p> - <p>Returns the number of exported functions that matched - the <c><anno>MFA</anno></c> argument. This will be zero if none matched at - all.</p> + set on the function. That is, local tracing must be + disabled with option <c>local</c> and global tracing with + option <c>global</c> (or no option), and so on.</p> + <p>Part of a match specification list cannot be changed directly. + If a function has a match specification, it can be replaced + with a new one. To change an existing match specification, + use the BIF + <seealso marker="#trace_info/2"><c>erlang:trace_info/2</c></seealso> + to retrieve the existing match specification.</p> + <p>Returns the number of functions matching + argument <c><anno>MFA</anno></c>. This is zero if none matched.</p> </desc> </func> + <func> <name name="trunc" arity="1"/> - <fsummary>Return an integer by the truncating a number</fsummary> + <fsummary>Return an integer by truncating a number.</fsummary> <desc> - <p>Returns an integer by the truncating <c><anno>Number</anno></c>.</p> + <p>Returns an integer by truncating <c><anno>Number</anno></c>, + for example:</p> <pre> > <input>trunc(5.5).</input> 5</pre> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="tuple_size" arity="1"/> - <fsummary>Return the size of a tuple</fsummary> + <fsummary>Return the size of a tuple.</fsummary> <desc> - <p>Returns an integer which is the number of elements in <c><anno>Tuple</anno></c>.</p> + <p>Returns an integer that is the number of elements in + <c><anno>Tuple</anno></c>, for example:</p> <pre> > <input>tuple_size({morni, mulle, bwange}).</input> 3</pre> <p>Allowed in guard tests.</p> </desc> </func> + <func> <name name="tuple_to_list" arity="1"/> - <fsummary>Convert a tuple to a list</fsummary> + <fsummary>Convert a tuple to a list.</fsummary> <desc> - <p>Returns a list which corresponds to <c><anno>Tuple</anno></c>. - <c><anno>Tuple</anno></c> may contain any Erlang terms.</p> + <p>Returns a list corresponding to <c><anno>Tuple</anno></c>. + <c><anno>Tuple</anno></c> can contain any Erlang terms. + Example:</p> <pre> > <input>tuple_to_list({share, {'Ericsson_B', 163}}).</input> [share,{'Ericsson_B',163}]</pre> </desc> </func> + + <func> + <name name="unique_integer" arity="0"/> + <fsummary>Get a unique integer value.</fsummary> + <desc> + <p>Generates and returns an + <seealso marker="doc/efficiency_guide:advanced#unique_integers"> + integer unique on current runtime system instance</seealso>. + The same as calling + <seealso marker="#unique_integer/1"> + <c>erlang:unique_integer([])</c></seealso>.</p> + </desc> + </func> + + <func> + <name name="unique_integer" arity="1"/> + <fsummary>Get a unique integer value.</fsummary> + <desc> + <p>Generates and returns an + <seealso marker="doc/efficiency_guide:advanced#unique_integers"> + integer unique on current runtime system + instance</seealso>. The integer is unique in the + sense that this BIF, using the same set of + modifiers, does not return the same integer more + than once on the current runtime system instance. + Each integer value can of course be constructed + by other means.</p> + <p>By default, when <c>[]</c> is passed as + <c><anno>ModifierList</anno></c>, both negative and + positive integers can be returned. This + to use the range of integers that do + not need heap memory allocation as much as possible. + By default the returned integers are also only + guaranteed to be unique, that is, any returned integer + can be smaller or larger than previously + returned integers.</p> + <p><c><anno>Modifier</anno></c>s:</p> + <taglist> + <tag>positive</tag> + <item> + <p>Returns only positive integers.</p> + <p>Notice that by passing the <c>positive</c> modifier + you will get heap allocated integers (bignums) quicker.</p> + </item> + <tag>monotonic</tag> + <item> + <p>Returns <seealso + marker="time_correction#Strictly_Monotonically_Increasing"> + strictly monotonically increasing</seealso> integers + corresponding to creation time. That is, the integer + returned is always larger than previously + returned integers on the current runtime system + instance.</p> + <p>These values can be used to determine order between events + on the runtime system instance. That is, if both + <c>X = erlang:unique_integer([monotonic])</c> and + <c>Y = erlang:unique_integer([monotonic])</c> are + executed by different processes (or the same + process) on the same runtime system instance and + <c>X < Y</c>, we know that <c>X</c> was created + before <c>Y</c>.</p> + <warning> + <p>Strictly monotonically increasing values + are inherently quite expensive to generate and scales + poorly. This is because the values need to be synchronized + between CPU cores. That is, do not pass the <c>monotonic</c> + modifier unless you really need strictly monotonically + increasing values.</p> + </warning> + </item> + </taglist> + <p>All valid <c><anno>Modifier</anno></c>s + can be combined. Repeated (valid) + <c><anno>Modifier</anno></c>s in the <c>ModifierList</c> + are ignored.</p> + <note> + <p>The set of integers returned by + <c>erlang:unique_integer/1</c> using different sets of + <c><anno>Modifier</anno></c>s <em>will overlap</em>. + For example, by calling <c>unique_integer([monotonic])</c>, + and <c>unique_integer([positive, monotonic])</c> + repeatedly, you will eventually see some integers that are + returned by both calls.</p> + </note> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item>if <c><anno>ModifierList</anno></c> is not a + proper list.</item> + <tag><c>badarg</c></tag> + <item>if <c><anno>Modifier</anno></c> is not a + valid modifier.</item> + </taglist> + </desc> + </func> + <func> <name name="universaltime" arity="0"/> - <fsummary>Current date and time according to Universal Time Coordinated (UTC)</fsummary> + <fsummary>Current date and time according to Universal Time Coordinated + (UTC).</fsummary> <desc> <p>Returns the current date and time according to Universal - Time Coordinated (UTC), also called GMT, in the form + Time Coordinated (UTC) in the form <c>{{Year, Month, Day}, {Hour, Minute, Second}}</c> if - supported by the underlying operating system. If not, - <c>erlang:universaltime()</c> is equivalent to - <c>erlang:localtime()</c>.</p> + supported by the underlying OS. + Otherwise <c>erlang:universaltime()</c> is equivalent to + <c>erlang:localtime()</c>. Example:</p> <pre> > <input>erlang:universaltime().</input> {{1996,11,6},{14,18,43}}</pre> </desc> </func> + <func> <name name="universaltime_to_localtime" arity="1"/> - <fsummary>Convert from Universal Time Coordinated (UTC) to local date and time</fsummary> + <fsummary>Convert from Universal Time Coordinated (UTC) to local date + and time.</fsummary> <desc> <p>Converts Universal Time Coordinated (UTC) date and time to - local date and time, if this is supported by the underlying - OS. Otherwise, no conversion is done, and - <c><anno>Universaltime</anno></c> is returned.</p> + local date and time in the form + <c>{{Year, Month, Day}, {Hour, Minute, Second}}</c> if + supported by the underlying OS. + Otherwise no conversion is done, and + <c><anno>Universaltime</anno></c> is returned. Example:</p> <pre> > <input>erlang:universaltime_to_localtime({{1996,11,6},{14,18,43}}).</input> {{1996,11,7},{15,18,43}}</pre> - <p>Failure: <c>badarg</c> if <c>Universaltime</c> does not denote - a valid date and time.</p> + <p>Failure: <c>badarg</c> if <c>Universaltime</c> denotes + an invalid date and time.</p> </desc> </func> + <func> <name name="unlink" arity="1"/> - <fsummary>Remove a link, if there is one, to another process or port</fsummary> + <fsummary>Remove a link to another process or port.</fsummary> <desc> <p>Removes the link, if there is one, between the calling - process and the process or port referred to by <c><anno>Id</anno></c>.</p> + process and the process or port referred to by + <c><anno>Id</anno></c>.</p> <p>Returns <c>true</c> and does not fail, even if there is no - link to <c><anno>Id</anno></c>, or if <c><anno>Id</anno></c> does not exist.</p> - <p>Once <c>unlink(<anno>Id</anno>)</c> has returned it is guaranteed that + link to <c><anno>Id</anno></c>, or if <c><anno>Id</anno></c> + does not exist.</p> + <p>Once <c>unlink(<anno>Id</anno>)</c> has returned, + it is guaranteed that the link between the caller and the entity referred to by - <c><anno>Id</anno></c> has no effect on the caller in the future (unless - the link is setup again). If caller is trapping exits, an - <c>{'EXIT', <anno>Id</anno>, _}</c> message due to the link might have - been placed in the caller's message queue prior to the call, - though. Note, the <c>{'EXIT', <anno>Id</anno>, _}</c> message can be the - result of the link, but can also be the result of <c><anno>Id</anno></c> - calling <c>exit/2</c>. Therefore, it <em>may</em> be - appropriate to cleanup the message queue when trapping exits - after the call to <c>unlink(<anno>Id</anno>)</c>, as follow:</p> + <c><anno>Id</anno></c> has no effect on the caller + in the future (unless + the link is setup again). If the caller is trapping exits, an + <c>{'EXIT', <anno>Id</anno>, _}</c> message from the link + can have been placed in the caller's message queue before + the call.</p> + <p>Notice that the <c>{'EXIT', <anno>Id</anno>, _}</c> + message can be the + result of the link, but can also be the result of <c>Id</c> + calling <c>exit/2</c>. Therefore, it <em>can</em> be + appropriate to clean up the message queue when trapping exits + after the call to <c>unlink(<anno>Id</anno>)</c>, as follows:</p> <code type="none"> - - unlink(Id), - receive - {'EXIT', Id, _} -> - true - after 0 -> - true - end</code> +unlink(Id), +receive + {'EXIT', Id, _} -> + true +after 0 -> + true +end</code> <note> - <p>Prior to OTP release R11B (erts version 5.5) <c>unlink/1</c> - behaved completely asynchronous, i.e., the link was active + <p>Before Erlang/OTP R11B (ERTS 5.5) <c>unlink/1</c> + behaved completely asynchronously, that is, the link was active until the "unlink signal" reached the linked entity. This - had one undesirable effect, though. You could never know when + had an undesirable effect, as you could never know when you were guaranteed <em>not</em> to be effected by the link.</p> - <p>Current behavior can be viewed as two combined operations: + <p>The current behavior can be viewed as two combined operations: asynchronously send an "unlink signal" to the linked entity and ignore any future results of the link.</p> </note> </desc> </func> + <func> <name name="unregister" arity="1"/> - <fsummary>Remove the registered name for a process (or port)</fsummary> + <fsummary>Remove the registered name for a process (or port).</fsummary> <desc> - <p>Removes the registered name <c><anno>RegName</anno></c>, associated with a - pid or a port identifier.</p> + <p>Removes the registered name <c><anno>RegName</anno></c> + associated with a + process identifier or a port identifier, for example:</p> <pre> > <input>unregister(db).</input> true</pre> @@ -7489,33 +11061,37 @@ true</pre> name.</p> </desc> </func> + <func> <name name="whereis" arity="1"/> - <fsummary>Get the pid (or port) with a given registered name</fsummary> + <fsummary>Get the pid (or port) with a specified registered name. + </fsummary> <desc> - <p>Returns the pid or port identifier with the registered name - <c>RegName</c>. Returns <c>undefined</c> if the name is not - registered.</p> + <p>Returns the process identifier or port identifier with + the registered name <c>RegName</c>. Returns <c>undefined</c> + if the name is not registered. Example:</p> <pre> > <input>whereis(db).</input> <0.43.0></pre> </desc> </func> + <func> <name name="yield" arity="0"/> - <fsummary>Let other processes get a chance to execute</fsummary> + <fsummary>Let other processes get a chance to execute.</fsummary> <desc> - <p>Voluntarily let other processes (if any) get a chance to - execute. Using <c>erlang:yield()</c> is similar to + <p>Voluntarily lets other processes (if any) get a chance to + execute. Using this function is similar to <c>receive after 1 -> ok end</c>, except that <c>yield()</c> is faster.</p> - <warning><p>There is seldom or never any need to use this BIF, - especially in the SMP-emulator as other processes will have a - chance to run in another scheduler thread anyway. - Using this BIF without a thorough grasp of how the scheduler - works may cause performance degradation.</p></warning> + <warning> + <p>There is seldom or never any need to use this BIF + as other processes have a chance to run in another scheduler + thread anyway. + Using this BIF without a thorough grasp of how the scheduler + works can cause performance degradation.</p> + </warning> </desc> </func> </funcs> </erlref> - diff --git a/erts/doc/src/erlc.xml b/erts/doc/src/erlc.xml index c3fc3b1686..be9b4e8d97 100644 --- a/erts/doc/src/erlc.xml +++ b/erts/doc/src/erlc.xml @@ -4,20 +4,21 @@ <comref> <header> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -27,7 +28,7 @@ <docno>1</docno> <approved>Bjarne Däcker</approved> <checked></checked> - <date>97-03-24</date> + <date>1997-03-24</date> <rev>A</rev> <file>erlc.xml</file> </header> @@ -37,167 +38,170 @@ <p>The <c><![CDATA[erlc]]></c> program provides a common way to run all compilers in the Erlang system. Depending on the extension of each input file, <c><![CDATA[erlc]]></c> - will invoke the appropriate compiler. - Regardless of which compiler is used, the same flags are used to provide parameters such as include paths and output directory.</p> - <p>The current working directory, <c>"."</c>, will not be included - in the code path when running the compiler (to avoid loading - Beam files from the current working directory that could potentially - be in conflict with the compiler or Erlang/OTP system used by the - compiler).</p> + invokes the appropriate compiler. + Regardless of which compiler is used, the same flags are used to provide + parameters, such as include paths and output directory.</p> + <p>The current working directory, <c>"."</c>, is not included + in the code path when running the compiler. This to avoid loading + Beam files from the current working directory that could potentially + be in conflict with the compiler or the Erlang/OTP system used by the + compiler.</p> </description> + <funcs> <func> <name>erlc flags file1.ext file2.ext...</name> - <fsummary>Compile files</fsummary> + <fsummary>Compile files.</fsummary> <desc> - <p><c><![CDATA[Erlc]]></c> compiles one or more files. - The files must include the extension, for example <c><![CDATA[.erl]]></c> - for Erlang source code, or <c><![CDATA[.yrl]]></c> for Yecc source code. - <c><![CDATA[Erlc]]></c> uses the extension to invoke the correct compiler.</p> + <p>Compiles one or more files. The files must include the extension, + for example, <c><![CDATA[.erl]]></c> for Erlang source code, or + <c><![CDATA[.yrl]]></c> for Yecc source code. + <c><![CDATA[Erlc]]></c> uses the extension to invoke the correct + compiler.</p> </desc> </func> </funcs> <section> <title>Generally Useful Flags</title> - <p>The following flags are supported: - </p> + <p>The following flags are supported:</p> <taglist> - <tag>-I <em>directory</em></tag> + <tag><c>-I <Directory></c></tag> <item> <p>Instructs the compiler to search for include files in - the specified directory. When encountering an - <c><![CDATA[-include]]></c> or <c><![CDATA[-include_lib]]></c> directive, the - compiler searches for header files in the following + the <c>Directory</c>. When encountering an + <c><![CDATA[-include]]></c> or <c><![CDATA[-include_lib]]></c> + directive, the compiler searches for header files in the following directories:</p> - <list type="ordered"> + <list type="bulleted"> <item> <p><c><![CDATA["."]]></c>, the current working directory of the - file server;</p> + file server</p> </item> <item> - <p>the base name of the compiled file;</p> + <p>The base name of the compiled file</p> </item> <item> - <p>the directories specified using the <c><![CDATA[-I]]></c> option. - The directory specified last is searched first.</p> + <p>The directories specified using option <c><![CDATA[-I]]></c>; + the directory specified last is searched first</p> </item> </list> </item> - <tag>-o <em>directory</em></tag> + <tag><c>-o <Directory></c></tag> <item> - <p>The directory where the compiler should place the output files. - If not specified, output files will be placed in the current working - directory.</p> + <p>The directory where the compiler is to place the output files. + Defaults to the current working directory.</p> </item> - <tag>-D<em>name</em></tag> + <tag><c>-D<Name></c></tag> <item> <p>Defines a macro.</p> </item> - <tag>-D<em>name</em>=<em>value</em></tag> + <tag><c>-D<Name>=<Value></c></tag> <item> - <p>Defines a macro with the given value. + <p>Defines a macro with the specified value. The value can be any Erlang term. Depending on the platform, the value may need to be quoted if the shell itself interprets certain characters. - On Unix, terms which contain tuples and list - must be quoted. Terms which contain spaces + On Unix, terms containing tuples and lists + must be quoted. Terms containing spaces must be quoted on all platforms.</p> </item> - <tag>-W<em>error</em></tag> + <tag><c>-W<Error></c></tag> <item> <p>Makes all warnings into errors.</p> </item> - <tag>-W<em>number</em></tag> + <tag><c>-W<Number></c></tag> <item> - <p>Sets warning level to <em>number</em>. Default is <c><![CDATA[1]]></c>. - Use <c><![CDATA[-W0]]></c> to turn off warnings.</p> + <p>Sets warning level to <c>Number</c>. Defaults to + <c><![CDATA[1]]></c>. To turn off warnings, + use <c><![CDATA[-W0]]></c>.</p> </item> - <tag>-W</tag> + <tag><c>-W</c></tag> <item> <p>Same as <c><![CDATA[-W1]]></c>. Default.</p> </item> - <tag>-v</tag> + <tag><c>-v</c></tag> <item> <p>Enables verbose output.</p> </item> - <tag>-b <em>output-type</em></tag> + <tag><c>-b <Output_type></c></tag> <item> <p>Specifies the type of output file. - Generally, <em>output-type</em> is the same as the file extension - of the output file but without the period. - This option will be ignored by compilers that have a + <c>Output_type</c> is the same as the file extension + of the output file, but without the period. + This option is ignored by compilers that have a single output format.</p> </item> - <tag>-smp</tag> + <tag><c>-smp</c></tag> <item> - <p>Compile using the SMP emulator. This is mainly useful - for compiling native code, which needs to be compiled with the same - run-time system that it should be run on.</p> + <p>Compiles using the SMP emulator. This is mainly useful + for compiling native code, which must be compiled with the same + runtime system that it is to be run on.</p> </item> - <tag>-M</tag> + <tag><c>-M</c></tag> <item> - <p>Produces a Makefile rule to track headers dependencies. The - rule is sent to stdout. No object file is produced. - </p> + <p>Produces a Makefile rule to track header dependencies. The + rule is sent to <c>stdout</c>. No object file is produced.</p> </item> - <tag>-MF <em>Makefile</em></tag> + + <tag><c>-MMD</c></tag> + <item> + <p>Generate dependencies as a side-effect. The object file + will be produced as normal. This option overrides the + option <c><![CDATA[-M]]></c>.</p> + </item> + + <tag><c>-MF <Makefile></c></tag> <item> - <p>Like the <c><![CDATA[-M]]></c> option above, except that the - Makefile is written to <em>Makefile</em>. No object - file is produced. - </p> + <p>As option <c><![CDATA[-M]]></c>, except that the + Makefile is written to <c>Makefile</c>. No object + file is produced.</p> </item> - <tag>-MD</tag> + <tag><c>-MD</c></tag> <item> - <p>Same as <c><![CDATA[-M -MF <File>.Pbeam]]></c>. - </p> + <p>Same as <c><![CDATA[-M -MF <File>.Pbeam]]></c>.</p> </item> - <tag>-MT <em>Target</em></tag> + <tag><c>-MT <Target></c></tag> <item> - <p>In conjunction with <c><![CDATA[-M]]></c> or - <c><![CDATA[-MF]]></c>, change the name of the rule emitted - to <em>Target</em>. - </p> + <p>In conjunction with option <c><![CDATA[-M]]></c> or + <c><![CDATA[-MF]]></c>, changes the name of the rule emitted + to <c>Target</c>.</p> </item> - <tag>-MQ <em>Target</em></tag> + <tag><c>-MQ <Target></c></tag> <item> - <p>Like the <c><![CDATA[-MT]]></c> option above, except that - characters special to make(1) are quoted. - </p> + <p>As option <c><![CDATA[-MT]]></c>, except that characters special to + <c>make/1</c> are quoted.</p> </item> - <tag>-MP</tag> + <tag><c>-MP</c></tag> <item> - <p>In conjunction with <c><![CDATA[-M]]></c> or - <c><![CDATA[-MF]]></c>, add a phony target for each dependency. - </p> + <p>In conjunction with option <c><![CDATA[-M]]></c> or + <c><![CDATA[-MF]]></c>, adds a phony target for each dependency.</p> </item> - <tag>-MG</tag> + <tag><c>-MG</c></tag> <item> - <p>In conjunction with <c><![CDATA[-M]]></c> or - <c><![CDATA[-MF]]></c>, consider missing headers as generated - files and add them to the dependencies. - </p> + <p>In conjunction with option <c><![CDATA[-M]]></c> or + <c><![CDATA[-MF]]></c>, considers missing headers as generated + files and adds them to the dependencies.</p> </item> - <tag>--</tag> + <tag><c>--</c></tag> <item> <p>Signals that no more options will follow. - The rest of the arguments will be treated as file names, + The rest of the arguments is treated as filenames, even if they start with hyphens.</p> </item> - <tag>+<em>term</em></tag> + <tag><c>+<Term></c></tag> <item> - <p>A flag starting with a plus ('<em>+</em>') rather than a hyphen - will be converted to an Erlang term and passed unchanged to + <p>A flag starting with a plus (<c>+</c>) rather than a hyphen + is converted to an Erlang term and passed unchanged to the compiler. - For instance, the <c><![CDATA[export_all]]></c> option for the Erlang + For example, option <c><![CDATA[export_all]]></c> for the Erlang compiler can be specified as follows:</p> <pre> erlc +export_all file.erl</pre> <p>Depending on the platform, the value may need to be quoted if the shell itself interprets certain characters. - On Unix, terms which contain tuples and list - must be quoted. Terms which contain spaces + On Unix, terms containing tuples and lists + must be quoted. Terms containing spaces must be quoted on all platforms.</p> </item> </taglist> @@ -205,19 +209,19 @@ erlc +export_all file.erl</pre> <section> <title>Special Flags</title> - <p>The flags in this section are useful in special situations - such as re-building the OTP system.</p> + <p>The following flags are useful in special situations, + such as rebuilding the OTP system:</p> <taglist> - <tag>-pa <em>directory</em></tag> + <tag><c>-pa <Directory></c></tag> <item> - <p>Appends <em>directory</em> to the front of the code path in + <p>Appends <c>Directory</c> to the front of the code path in the invoked Erlang emulator. This can be used to invoke another compiler than the default one.</p> </item> - <tag>-pz <em>directory</em></tag> + <tag><c>-pz <Directory></c></tag> <item> - <p>Appends <em>directory</em> to the code path in + <p>Appends <c>Directory</c> to the code path in the invoked Erlang emulator.</p> </item> </taglist> @@ -225,63 +229,70 @@ erlc +export_all file.erl</pre> <section> <title>Supported Compilers</title> + <p>The following compilers are supported:</p> <taglist> - <tag>.erl</tag> + <tag><c>.erl</c></tag> <item> <p>Erlang source code. It generates a <c><![CDATA[.beam]]></c> file.</p> - <p>The options -P, -E, and -S are equivalent to +'P', - +'E', and +'S', except that it is not necessary to include the single quotes to protect them - from the shell.</p> - <p>Supported options: -I, -o, -D, -v, -W, -b.</p> + <p>Options <c>-P</c>, <c>-E</c>, and <c>-S</c> are equivalent to + <c>+'P'</c>, <c>+'E'</c>, and <c>+'S'</c>, except that it is not + necessary to include the single quotes to protect them from the + shell.</p> + <p>Supported options: <c>-I</c>, <c>-o</c>, <c>-D</c>, <c>-v</c>, + <c>-W</c>, <c>-b</c>.</p> </item> - <tag>.S</tag> + <tag><c>.S</c></tag> <item> - <p>Erlang assembler source code. It generates a <c><![CDATA[.beam]]></c> file.</p> - <p>Supported options: same as for .erl.</p> + <p>Erlang assembler source code. It generates a <c><![CDATA[.beam]]></c> + file.</p> + <p>Supported options: same as for <c>.erl</c>.</p> </item> - <tag>.core</tag> + <tag><c>.core</c></tag> <item> - <p>Erlang core source code. It generates a <c><![CDATA[.beam]]></c> file.</p> - <p>Supported options: same as for .erl.</p> + <p>Erlang core source code. It generates a <c><![CDATA[.beam]]></c> + file.</p> + <p>Supported options: same as for <c>.erl</c>.</p> </item> - <tag>.yrl</tag> + <tag><c>.yrl</c></tag> <item> <p>Yecc source code. It generates an <c><![CDATA[.erl]]></c> file.</p> - <p>Use the -I option with the name of a file to use that file - as a customized prologue file (the <c><![CDATA[includefile]]></c> option).</p> - <p>Supported options: -o, -v, -I, -W (see above).</p> + <p>Use option <c>-I</c> with the name of a file to use that file + as a customized prologue file (option + <c><![CDATA[includefile]]></c>).</p> + <p>Supported options: <c>-o</c>, <c>-v</c>, <c>-I</c>, <c>-W</c>.</p> </item> - <tag>.mib</tag> + <tag><c>.mib</c></tag> <item> <p>MIB for SNMP. It generates a <c><![CDATA[.bin]]></c> file.</p> - <p>Supported options: -I, -o, -W.</p> + <p>Supported options: <c>-I</c>, <c>-o</c>, <c>-W</c>.</p> </item> - <tag>.bin</tag> + <tag><c>.bin</c></tag> <item> - <p>A compiled MIB for SNMP. It generates a <c><![CDATA[.hrl]]></c> file.</p> - <p>Supported options: -o, -v.</p> + <p>A compiled MIB for SNMP. It generates a <c><![CDATA[.hrl]]></c> + file.</p> + <p>Supported options: <c>-o</c>, <c>-v</c>.</p> </item> - <tag>.rel</tag> + <tag><c>.rel</c></tag> <item> <p>Script file. It generates a boot file.</p> - <p>Use the -I to name directories to be searched for application - files (equivalent to the <c><![CDATA[path]]></c> in the option list for - <c><![CDATA[systools:make_script/2]]></c>).</p> - <p>Supported options: -o.</p> + <p>Use option <c>-I</c> to name directories to be searched for + application files (equivalent to the <c><![CDATA[path]]></c> in the + option list for <c><![CDATA[systools:make_script/2]]></c>).</p> + <p>Supported option: <c>-o</c>.</p> </item> - <tag>.asn1</tag> + <tag><c>.asn1</c></tag> <item> - <p>ASN1 file.</p> - <p>Creates an <c><![CDATA[.erl]]></c>, <c><![CDATA[.hrl]]></c>, and <c><![CDATA[.asn1db]]></c> file from - an <c><![CDATA[.asn1]]></c> file. Also compiles the <c><![CDATA[.erl]]></c> using the Erlang - compiler unless the <c><![CDATA[+noobj]]></c> options is given.</p> - <p>Supported options: -I, -o, -b, -W.</p> + <p>ASN1 file. It creates an <c><![CDATA[.erl]]></c>, + <c><![CDATA[.hrl]]></c>, and <c><![CDATA[.asn1db]]></c> file from + an <c><![CDATA[.asn1]]></c> file. Also compiles the + <c><![CDATA[.erl]]></c> using the Erlang compiler unless option + <c><![CDATA[+noobj]]></c> is specified.</p> + <p>Supported options: <c>-I</c>, <c>-o</c>, <c>-b</c>, <c>-W</c>.</p> </item> - <tag>.idl</tag> + <tag><c>.idl</c></tag> <item> - <p>IC file.</p> - <p>Runs the IDL compiler.</p> - <p>Supported options: -I, -o.</p> + <p>IC file. It runs the IDL compiler.</p> + <p>Supported options: <c>-I</c>, <c>-o</c>.</p> </item> </taglist> </section> @@ -289,20 +300,20 @@ erlc +export_all file.erl</pre> <section> <title>Environment Variables</title> <taglist> - <tag>ERLC_EMULATOR</tag> - <item>The command for starting the emulator. - Default is <em>erl</em> in the same directory as the <em>erlc</em> program - itself, or if it doesn't exist, <em>erl</em> in any of the directories - given in the <em>PATH</em> environment variable.</item> + <tag><c>ERLC_EMULATOR</c></tag> + <item>The command for starting the emulator. Defaults to <c>erl</c> + in the same directory as the <c>erlc</c> program itself, + or, if it does not exist, <c>erl</c> in any of the directories + specified in environment variable <c>PATH</c>.</item> </taglist> </section> <section> - <title>SEE ALSO</title> - <p><seealso marker="erl">erl(1)</seealso>, - <seealso marker="compiler:compile">compile(3)</seealso>, - <seealso marker="parsetools:yecc">yecc(3)</seealso>, - <seealso marker="snmp:snmp">snmp(3)</seealso></p> + <title>See Also</title> + <p><seealso marker="erl"><c>erl(1)</c></seealso>, + <seealso marker="compiler:compile"><c>compile(3)</c></seealso>, + <seealso marker="parsetools:yecc"><c>yecc(3)</c></seealso>, + <seealso marker="snmp:snmp"><c>snmp(3)</c></seealso></p> </section> </comref> diff --git a/erts/doc/src/erlsrv.xml b/erts/doc/src/erlsrv.xml index 71cee714a5..6c08b25220 100644 --- a/erts/doc/src/erlsrv.xml +++ b/erts/doc/src/erlsrv.xml @@ -4,20 +4,21 @@ <comref> <header> <copyright> - <year>1998</year><year>2013</year> + <year>1998</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -27,343 +28,447 @@ <docno></docno> <approved></approved> <checked></checked> - <date>98-04-29</date> + <date>1998-04-29</date> <rev></rev> <file>erlsrv.xml</file> </header> <com>erlsrv</com> - <comsummary>Run the Erlang emulator as a service on Windows NT®</comsummary> + <comsummary>Run the Erlang emulator as a service on Windows</comsummary> <description> - <p>This utility is specific to Windows NT/2000/XP® (and subsequent versions of Windows) It allows Erlang + <p>This utility is specific to Windows NT/2000/XP (and later + versions of Windows). It allows Erlang emulators to run as services on the Windows system, allowing embedded - systems to start without any user needing to log in. The + systems to start without any user needing to log on. The emulator started in this way can be manipulated through the - Windows® services applet in a manner similar to other - services.</p> - <p>Note that erlsrv is not a general service utility for Windows, but designed for embedded Erlang systems.</p> - <p>As well as being the actual service, erlsrv also provides a - command line interface for registering, changing, starting and - stopping services.</p> - <p>To manipulate services, the logged in user should have - Administrator privileges on the machine. The Erlang machine + Windows services applet in a manner similar to other services.</p> + + <p>Notice that <c>erlsrv</c> is not a general service utility for Windows, + but designed for embedded Erlang systems.</p> + + <p><c>erlsrv</c> also provides a command-line interface for registering, + changing, starting, and stopping services.</p> + + <p>To manipulate services, the logged on user is to have + administrator privileges on the machine. The Erlang machine itself is (default) run as the local administrator. This can be - changed with the Services applet in Windows ®.</p> + changed with the Services applet in Windows.</p> + <p>The processes created by the service can, as opposed to normal - services, be "killed" with the task manager. Killing a emulator - that is started by a service will trigger the "OnFail" action - specified for that service, which may be a reboot.</p> - <p>The following parameters may be specified for each Erlang - service:</p> - <list type="bulleted"> + services, be "killed" with the task manager. Killing an emulator + that is started by a service triggers the "OnFail" action + specified for that service, which can be a reboot.</p> + + <p>The following parameters can be specified for each Erlang service:</p> + + <taglist> + <tag><c><![CDATA[StopAction]]></c></tag> <item> - <p><c><![CDATA[StopAction]]></c>: This tells <c><![CDATA[erlsrv]]></c> how to stop + <p>Tells <c><![CDATA[erlsrv]]></c> how to stop the Erlang emulator. Default is to kill it (Win32 TerminateProcess), but this action can specify any Erlang shell command that will be executed in the emulator to make it stop. The emulator is expected to stop within 30 seconds after the command is issued in the shell. If the emulator is - not stopped, it will report a running state to the service + not stopped, it reports a running state to the service manager.</p> </item> + <tag><c><![CDATA[OnFail]]></c></tag> <item> - <p><c><![CDATA[OnFail]]></c>: This can be either of <c><![CDATA[reboot]]></c>, - <c><![CDATA[restart]]></c>, <c><![CDATA[restart_always]]></c> or <c><![CDATA[ignore]]></c> (the - default). In case of <c><![CDATA[reboot]]></c>, the NT system is - rebooted whenever the emulator stops (a more simple form of - watchdog), this could be useful for less critical systems, - otherwise use the heart functionality to accomplish - this. The restart value makes the Erlang emulator be - restarted (with whatever parameters are registered for the - service at the occasion) when it stops. If the emulator - stops again within 10 seconds, it is not restarted to avoid - an infinite loop which could completely hang the NT - system. <c><![CDATA[restart_always]]></c> is similar to restart, but - does not try to detect cyclic restarts, it is expected that - some other mechanism is present to avoid the problem. The - default (ignore) just reports the service as stopped to the - service manager whenever it fails, it has to be manually - restarted.</p> - <p>On a system where release handling is - used, this should always be set to <c><![CDATA[ignore]]></c>. Use - <c><![CDATA[heart]]></c> to restart the service on failure instead.</p> + <p>Can be one of the following:</p> + <taglist> + <tag><c><![CDATA[reboot]]></c></tag> + <item> + <p>The Windows system is rebooted whenever the emulator stops + (a more simple form of watchdog). This can be useful for + less critical systems, otherwise use the heart functionality + to accomplish this.</p> + </item> + <tag><c><![CDATA[restart]]></c></tag> + <item> + <p>Makes the Erlang emulator be + restarted (with whatever parameters are registered for the + service at the occasion) when it stops. If the emulator + stops again within 10 seconds, it is not restarted to avoid + an infinite loop, which could hang the Windows system.</p> + </item> + <tag><c><![CDATA[restart_always]]></c></tag> + <item> + <p>Similar to <c><![CDATA[restart]]></c>, but does + not try to detect cyclic restarts; it is expected that + some other mechanism is present to avoid the problem.</p> + </item> + <tag><c><![CDATA[ignore]]></c> (the default)</tag> + <item> + <p>Reports the service as stopped to the service manager + whenever it fails; it must be manually restarted.</p> + </item> + </taglist> + <p>On a system where release handling is used, + this is always to be set to <c><![CDATA[ignore]]></c>. Use + <c><![CDATA[heart]]></c> to restart the service on failure + instead.</p> </item> + <tag><c><![CDATA[Machine]]></c></tag> <item> - <p><c><![CDATA[Machine]]></c>: The location of the Erlang - emulator. The default is the <c><![CDATA[erl.exe]]></c> located in the - same directory as erlsrv.exe. Do not specify <c><![CDATA[werl.exe]]></c> - as this emulator, it will not work.</p> - <p>If the system - uses release handling, this should be set to a program - similar to <c><![CDATA[start_erl.exe]]></c>.</p> + <p>The location of the Erlang emulator. + The default is the <c><![CDATA[erl.exe]]></c> located in the same + directory as <c>erlsrv.exe</c>. Do not specify + <c><![CDATA[werl.exe]]></c> as this emulator, it will not work.</p> + <p>If the system uses release handling, this is to be set to a + program similar to <c><![CDATA[start_erl.exe]]></c>.</p> </item> + <tag><c><![CDATA[Env]]></c></tag> <item> - <p><c><![CDATA[Env]]></c>: Specifies an <em>additional</em> environment + <p>Specifies an <em>extra</em> environment for the emulator. The environment variables specified - here are added to the system wide environment block that is + here are added to the system-wide environment block that is normally present when a service starts up. Variables present - in both the system wide environment and in the service + in both the system-wide environment and in the service environment specification will be set to the value specified in the service.</p> </item> + <tag><c><![CDATA[WorkDir]]></c></tag> <item> - <p><c><![CDATA[WorkDir]]></c>: The working directory for the Erlang - emulator, has to be on a local drive (there are no network - drives mounted when a service starts). Default working - directory for services is <c><![CDATA[%SystemDrive%%SystemPath%]]></c>. + <p>The working directory for the Erlang emulator. + Must be on a local drive (no network drives are mounted when a + service starts). Default working directory for services is + <c><![CDATA[%SystemDrive%%SystemPath%]]></c>. Debug log files will be placed in this directory.</p> </item> + <tag><c><![CDATA[Priority]]></c></tag> <item> - <p><c><![CDATA[Priority]]></c>: The process priority of the emulator, - this can be one of <c><![CDATA[realtime]]></c>, <c><![CDATA[high]]></c>, <c><![CDATA[low]]></c> - or <c><![CDATA[default]]></c> (the default). Real-time priority is not - recommended, the machine will possibly be inaccessible to - interactive users. High priority could be used if two Erlang - nodes should reside on one dedicated system and one should - have precedence over the other. Low process priority may be - used if interactive performance should not be affected by - the emulator process.</p> + <p>The process priority of the emulator. Can be one of the + following:</p> + <taglist> + <tag><c><![CDATA[realtime]]></c></tag> + <item> + <p>Not recommended, as the machine will possibly be + inaccessible to interactive users.</p> + </item> + <tag><c><![CDATA[high]]></c></tag> + <item> + <p>Can be used if two Erlang nodes are to reside on one dedicated + system and one is to have precedence over the other.</p> + </item> + <tag><c><![CDATA[low]]></c></tag> + <item> + <p>Can be used if interactive performance is not to be affected + by the emulator process.</p> + </item> + <tag><c><![CDATA[default]]></c> (the default></tag> + <item> + </item> + </taglist> </item> + <tag><c><![CDATA[SName or Name]]></c></tag> <item> - <p><c><![CDATA[SName or Name]]></c>: Specifies the short or long - node-name of the Erlang emulator. The Erlang services are - always distributed, default is to use the service name as - (short) node-name.</p> + <p>Specifies the short or long + node name of the Erlang emulator. The Erlang services are + always distributed. Default is to use the service name as + (short) nodename.</p> </item> + <tag><c><![CDATA[DebugType]]></c></tag> <item> - <p><c><![CDATA[DebugType]]></c>: Can be one of <c><![CDATA[none]]></c> (default), - <c><![CDATA[new]]></c>, <c><![CDATA[reuse]]></c> or <c><![CDATA[console]]></c>. - Specifies that output from the Erlang shell should be + <p>Specifies that output from the Erlang shell is to be sent to a "debug log". The log file is named <servicename><c><![CDATA[.debug]]></c> or - <servicename><c><![CDATA[.debug.]]></c><N>, where <N> is - an integer between 1 and 99. The log-file is placed in the - working directory of the service (as specified in WorkDir). The - <c><![CDATA[reuse]]></c> option always reuses the same log file - (<servicename><c><![CDATA[.debug]]></c>) and the <c><![CDATA[new]]></c> option - uses a separate log file for every invocation of the service - (<servicename><c><![CDATA[.debug.]]></c><N>). The <c><![CDATA[console]]></c> - option opens an interactive Windows® console window for - the Erlang shell of the service. The <c><![CDATA[console]]></c> option - automatically - disables the <c><![CDATA[StopAction]]></c> and a service started with an - interactive console window will not survive logouts, - <c><![CDATA[OnFail]]></c> actions do not work with debug-consoles either. - If no <c><![CDATA[DebugType]]></c> is specified (<c><![CDATA[none]]></c>), the - output of the Erlang shell is discarded.</p> - <p>The <c><![CDATA[console]]></c><c><![CDATA[DebugType]]></c> is <em>not in any way</em> - intended for production. It is <em>only</em> a convenient way to - debug Erlang services during development. The <c><![CDATA[new]]></c> and - <c><![CDATA[reuse]]></c> options might seem convenient to have in a - production system, but one has to take into account that the - logs will grow indefinitely during the systems lifetime and - there is no way, short of restarting the service, to - truncate those logs. In short, the <c><![CDATA[DebugType]]></c> is - intended for debugging only. Logs during production are - better produced with the standard Erlang logging - facilities.</p> + <servicename><c><![CDATA[.debug.]]></c><N>, + where <N> is an integer from 1 through 99. + The log file is placed in the working directory of the + service (as specified in <c>WorkDir</c>).</p> + <p>Can be one of the following:</p> + <taglist> + <tag><c><![CDATA[new]]></c></tag> + <item> + <p>Uses a separate log file for every invocation of the service + (<servicename><c><![CDATA[.debug.]]></c><N>).</p> + </item> + <tag><c><![CDATA[reuse]]></c></tag> + <item> + <p>Reuses the same log file + (<servicename><c><![CDATA[.debug]]></c>).</p> + </item> + <tag><c><![CDATA[console]]></c></tag> + <item> + <p>Opens an interactive Windows console window for the Erlang + shell of the service. Automatically disables the + <c><![CDATA[StopAction]]></c>. A service started with an + interactive console window does not survive logouts. + <c><![CDATA[OnFail]]></c> actions do not work with + debug consoles either.</p> + </item> + <tag><c><![CDATA[none]]></c> (the default)</tag> + <item> + <p>The output of the Erlang shell is discarded.</p> + </item> + </taglist> + <note> + <p>The <c><![CDATA[console]]></c> option is <em>not</em> intended + for production. It is <em>only</em> a convenient way to debug + Erlang services during development.</p> + <p>The <c><![CDATA[new]]></c> and <c><![CDATA[reuse]]></c> options + might seem convenient in a production system, but consider that + the logs grow indefinitely during the system lifetime and cannot + be truncated, except if the service is restarted.</p> + <p>In short, the <c><![CDATA[DebugType]]></c> is + intended for debugging only. Logs during production are + better produced with the standard Erlang logging facilities.</p> + </note> </item> + <tag><c><![CDATA[Args]]></c></tag> <item> - <p><c><![CDATA[Args]]></c>: Additional arguments passed to the - emulator startup program <c><![CDATA[erl.exe]]></c> (or - <c><![CDATA[start_erl.exe]]></c>). Arguments that cannot be specified - here are <c><![CDATA[-noinput]]></c> (StopActions would not work), - <c><![CDATA[-name]]></c> and <c><![CDATA[-sname]]></c> (they are specified in any - way. The most common use is for specifying cookies and flags - to be passed to init:boot() (<c><![CDATA[-s]]></c>).</p> + <p>Passes extra arguments to the emulator startup program + <c><![CDATA[erl.exe]]></c> (or <c><![CDATA[start_erl.exe]]></c>). + Arguments that cannot be specified here are + <c><![CDATA[-noinput]]></c> (<c>StopActions</c> would not work), + <c><![CDATA[-name]]></c>, and <c><![CDATA[-sname]]></c> (they are + specified in any way). The most common use is for specifying cookies + and flags to be passed to <c>init:boot()</c> + (<c><![CDATA[-s]]></c>).</p> </item> + <tag><c><![CDATA[InternalServiceName]]></c></tag> <item> - <p><c><![CDATA[InternalServiceName]]></c>: Specifies the Windows® internal service name (not the display name, which is the one <c>erlsrv</c> uses to identify the service).</p> - <p>This internal name can not be changed, it is fixed even if the service is renamed. <c>Erlsrv</c> generates a unique internal name when a service is created, it is recommended to keep to the defaut if release-handling is to be used for the application.</p> - <p>The internal service name can be seen in the Windows® service manager if viewing <c>Properties</c> for an erlang service.</p> + <p>Specifies the Windows-internal service name (not the display name, + which is the one <c>erlsrv</c> uses to identify the service).</p> + <p>This internal name cannot be changed, it is fixed even if the + service is renamed. <c>erlsrv</c> generates a unique internal name + when a service is created. It is recommended to keep to the default + if release handling is to be used for the application.</p> + <p>The internal service name can be seen in the Windows service + manager if viewing <c>Properties</c> for an Erlang service.</p> </item> + <tag><c><![CDATA[Comment]]></c></tag> <item> - <p><c><![CDATA[Comment]]></c>: A textual comment describing the service. Not mandatory, but shows up as the service description in the Windows® service manager.</p> + <p>A textual comment describing the service. Not mandatory, but shows + up as the service description in the Windows service manager.</p> </item> - </list> - <p> <marker id="001"></marker> - The naming of the service in a system that - uses release handling has to follow the convention + </taglist> + + <p><marker id="001"></marker> + The naming of the service in a system that + uses release handling must follow the convention <em>NodeName</em>_<em>Release</em>, where <em>NodeName</em> is - the first part of the Erlang nodename (up to, but not including + the first part of the Erlang node name (up to, but not including the "@") and <em>Release</em> is the current release of the application.</p> </description> + <funcs> <func> <name>erlsrv {set | add} <service-name> [<service options>]</name> - <fsummary>Add or modify an Erlang service</fsummary> + <fsummary>Add or modify an Erlang service.</fsummary> <desc> - <p>The set and add commands adds or modifies a Erlang service - respectively. The simplest form of an add command would be - completely without options in which case all default values + <p>The <c>set</c> and <c>add</c> commands modifies or adds an Erlang + service, respectively. The simplest form of an <c>add</c> command is + without any options in which case all default values (described above) apply. The service name is mandatory.</p> - <p>Every option can be given without parameters, in which case - the default value is applied. Values to the options are - supplied <em>only</em> when the default should not be used - (i.e. <c><![CDATA[erlsrv set myservice -prio -arg]]></c> sets the - default priority and removes all arguments).</p> - <p>The following service options are currently available:</p> + <p>Every option can be specified without parameters, the + default value is then applied. Values to the options are + supplied <em>only</em> when the default is not to be used. + For example, <c><![CDATA[erlsrv set myservice -prio -arg]]></c> + sets the default priority and removes all arguments.</p> + <p>Service options:</p> <taglist> - <tag>-st[opaction] [<erlang shell command>]</tag> - <item>Defines the StopAction, the command given to the Erlang - shell when the service is stopped. Default is none.</item> - <tag>-on[fail] [{reboot | restart | restart_always}]</tag> - <item>Specifies the action to take when the Erlang emulator - stops unexpectedly. Default is to ignore.</item> - <tag>-m[achine] [<erl-command>]</tag> - <item>The complete path to the Erlang emulator, never use the - werl program for this. Default is the <c><![CDATA[erl.exe]]></c> in the - same directory as <c><![CDATA[erlsrv.exe]]></c>. When release handling - is used, this should be set to a program similar to - <c><![CDATA[start_erl.exe]]></c>.</item> - <tag>-e[nv] [<variable>[=<value>]] ...</tag> - <item>Edits the environment block for the service. Every - environment variable specified will add to the system - environment block. If a variable specified here has the same - name as a system wide environment variable, the specified - value overrides the system wide. Environment variables are - added to this list by specifying - <variable>=<value> and deleted from the list by - specifying <variable> alone. The environment block is - automatically sorted. Any number of <c><![CDATA[-env]]></c> options can - be specified in one command. Default is to use the system - environment block unmodified (except for two additions, see - <seealso marker="#002">below</seealso>).</item> - <tag>-w[orkdir] [<directory>]</tag> - <item>The initial working directory of the Erlang - emulator. Default is the system directory.</item> - <tag>-p[riority] [{low|high|realtime}]</tag> - <item>The priority of the Erlang emulator. The default is the - Windows® default priority.</item> - <tag>{-sn[ame] | -n[ame]} [<node-name>]</tag> - <item>The node-name of the Erlang machine, distribution is - mandatory. Default is <c><![CDATA[-sname <service name>]]></c>. + <tag><c>-st[opaction] [<erlang shell command>]</c></tag> + <item> + <p>Defines the <c><![CDATA[StopAction]]></c>, the command given + to the Erlang shell when the service is stopped. + Default is none.</p> + </item> + <tag><c>-on[fail] [{reboot | restart | restart_always}]</c></tag> + <item> + <p>The action to take when the Erlang emulator + stops unexpectedly. Default is to ignore.</p> + </item> + <tag><c>-m[achine] [<erl-command>]</c></tag> + <item> + <p>The complete path to the Erlang emulator. Never use the + <c>werl</c> program for this. Defaults to the + <c><![CDATA[erl.exe]]></c> in the same directory as + <c><![CDATA[erlsrv.exe]]></c>. When release handling + is used, this is to be set to a program similar to + <c><![CDATA[start_erl.exe]]></c>.</p> + </item> + <tag><c>-e[nv] [<variable>[=<value>]] ...</c></tag> + <item> + <p>Edits the environment block for the service. Every + environment variable specified is added to the system + environment block. If a variable specified here has the same + name as a system-wide environment variable, the specified + value overrides the system-wide. Environment variables are + added to this list by specifying + <variable>=<value> and deleted from the list by + specifying <variable> alone. The environment block is + automatically sorted. Any number of <c><![CDATA[-env]]></c> + options can be specified in one command. Default is to use the + system environment block unmodified (except for two additions, + see section <seealso marker="#002">Environment</seealso> + below).</p> + </item> + <tag><c>-w[orkdir] [<directory>]</c></tag> + <item> + <p>The initial working directory of the Erlang + emulator. Defaults to the system directory.</p> + </item> + <tag><c>-p[riority] [{low|high|realtime}]</c></tag> + <item> + <p>The priority of the Erlang emulator. Default to the + Windows default priority.</p> + </item> + <tag><c>{-sn[ame] | -n[ame]} [<node-name>]</c></tag> + <item> + <p>The node name of the Erlang machine. Distribution is mandatory. + Defaults to <c><![CDATA[-sname <service name>]]></c>.</p> + </item> + <tag><c>-d[ebugtype] [{new|reuse|console}]</c></tag> + <item> + <p>Specifies where shell output is to be sent. + Default is that shell output is discarded. + To be used only for debugging.</p> + </item> + <tag><c>-ar[gs] [<limited erl arguments>]</c></tag> + <item> + <p>Extra arguments to the Erlang emulator. Avoid + <c><![CDATA[-noinput]]></c>, <c><![CDATA[-noshell]]></c>, and + <c><![CDATA[-sname]]></c>/<c><![CDATA[-name]]></c>. Default is + no extra arguments. Remember that the services cookie file is not + necessarily the same as the interactive users. The service + runs as the local administrator. Specify all arguments + together in one string, use double quotes (") to specify an + argument string containing spaces, and use quoted quotes (\") + to specify a quote within the argument string if necessary.</p> + </item> + <tag><c>-i[nternalservicename] [<internal name>]</c></tag> + <item> + <p><em>Only</em> allowed for <c>add</c>. Specifies a + Windows-internal service name for the service, which by + default is set to something unique (prefixed with the + original service name) by <c>erlsrv</c> when adding a new + service. Specifying this is a purely cosmethic action and is + <em>not</em> recommended if release handling is to be + performed. The internal service name cannot be changed once + the service is created. The internal name is <em>not</em> to + be confused with the ordinary service name, which is the name + used to identify a service to <c>erlsrv</c>.</p> + </item> + <tag><c>-c[omment] [<short description>]</c></tag> + <item> + <p>Specifies a textual comment describing the + service. This comment shows up as the service description + in the Windows service manager.</p> </item> - <tag>-d[ebugtype] [{new|reuse|console}]</tag> - <item>Specifies where shell output should be sent, - default is that shell output is discarded. - To be used only for debugging.</item> - <tag>-ar[gs] [<limited erl arguments>]</tag> - <item>Additional arguments to the Erlang emulator, avoid - <c><![CDATA[-noinput]]></c>, <c><![CDATA[-noshell]]></c> and - <c><![CDATA[-sname]]></c>/<c><![CDATA[-name]]></c>. Default is no additional - arguments. Remember that the services cookie file is not - necessarily the same as the interactive users. The service - runs as the local administrator. All arguments should be given - together in one string, use double quotes (") to give an - argument string containing spaces and use quoted quotes (\") - to give an quote within the argument string if - necessary.</item> - <tag>-i[nternalservicename] [<internal name>]</tag> - <item><em>Only</em> allowed for <c>add</c>. Specifies a - Windows® internal service name for the service, which by - default is set to something unique (prefixed with the - original service name) by erlsrv when adding a new - service. Specifying this is a purely cosmethic action and is - <em>not</em> recommended if release handling is to be - performed. The internal service name cannot be changed once - the service is created. The internal name is <em>not</em> to - be confused with the ordinary service name, which is the name - used to identify a service to erlsrv.</item> - <tag>-c[omment] [<short description>]</tag> - <item>Specifies a textual comment describing the - service. This comment will show upp as the service description - in the Windows® service manager.</item> </taglist> </desc> </func> + <func> - <name>erlsrv {start | start_disabled | stop | disable | enable} <service-name></name> + <name>erlsrv {start | start_disabled | stop | disable | + enable} <service-name></name> <fsummary>Manipulate the current service status.</fsummary> <desc> <p>These commands are only added for convenience, the normal way to manipulate the state of a service is through the - control panels services applet. The <c><![CDATA[start]]></c> and + control panels services applet.</p> + <p>The <c><![CDATA[start]]></c> and <c><![CDATA[stop]]></c> commands communicates - with the service manager for stopping and starting a - service. The commands wait until the service is actually - stopped or started. When disabling a service, it is not - stopped, the disabled state will not take effect until the - service actually is stopped. Enabling a service sets it in - automatic mode, that is started at boot. This command cannot - set the service to manual. </p> - - <p>The <c>start_disabled</c> command operates on a service - regardless of if it's enabled/disabled or started/stopped. It - does this by first enabling it (regardless of if it's enabled - or not), then starting it (if it's not already started) and - then disabling it. The result will be a disabled but started - service, regardless of its earlier state. This is useful for - starting services temporarily during a release upgrade. The - difference between using <c>start_disabled</c> and the - sequence <c>enable</c>, <c>start</c> and <c>disable</c> is - that all other <c>erlsrv</c> commands are locked out during - the sequence of operations in <c>start_disable</c>, making the - operation atomic from an <c>erlsrv</c> user's point of - view.</p> - + with the service manager for starting and stopping a + service. The commands wait until the service is + started or stopped. When disabling a service, it is not + stopped, the disabled state does not take effect until the + service is stopped. Enabling a service sets it in + automatic mode, which is started at boot. This command cannot + set the service to manual.</p> + <p>The <c>start_disabled</c> command operates on a service + regardless of if it is enabled/disabled or started/stopped. It + does this by first enabling it (regardless of if it is enabled + or not), then starting it (if not already started), and + then disabling it. The result is a disabled but started + service, regardless of its earlier state. This is useful for + starting services temporarily during a release upgrade. The + difference between using <c>start_disabled</c> and the + sequence <c>enable</c>, <c>start</c>, and <c>disable</c> is + that all other <c>erlsrv</c> commands are locked out during + the sequence of operations in <c>start_disable</c>, making the + operation atomic from an <c>erlsrv</c> user's point of view.</p> </desc> </func> + <func> <name>erlsrv remove <service-name></name> <fsummary>Remove the service.</fsummary> <desc> - <p>This command removes the service completely with all its registered - options. It will be stopped before it is removed.</p> + <p>Removes the service completely with all its registered + options. It is stopped before it is removed.</p> </desc> </func> + <func> <name>erlsrv list [<service-name>]</name> - <fsummary>List all Erlang services or all options for one service.</fsummary> + <fsummary>List all Erlang services or all options for one service. + </fsummary> <desc> - <p>If no service name is supplied, a brief listing of all Erlang services - is presented. If a service-name is supplied, all options for that - service are presented.</p> + <p>If no service name is specified, a brief listing of all Erlang + services is presented. If a service name is supplied, all options + for that service are presented.</p> </desc> </func> + <func> <name>erlsrv help</name> - <fsummary>Display a brief help text</fsummary> + <fsummary>Display a brief help text.</fsummary> + <desc> + <p>Displays a brief help text.</p> + </desc> </func> </funcs> <section> - <title>ENVIRONMENT</title> - <p> <marker id="002"></marker> -The environment of an Erlang machine started - as a service will contain two special variables, - <c><![CDATA[ERLSRV_SERVICE_NAME]]></c>, which is the name of the service that - started the machine and <c><![CDATA[ERLSRV_EXECUTABLE]]></c> which is the - full path to the <c><![CDATA[erlsrv.exe]]></c> that can be used to manipulate - the service. This will come in handy when defining a heart command for - your service. A command file for restarting a service will - simply look like this:</p> + <title>Environment</title> + <p><marker id="002"></marker> + The environment of an Erlang machine started + as a service contains two special variables:</p> + + <taglist> + <tag><c><![CDATA[ERLSRV_SERVICE_NAME]]></c></tag> + <item>The name of the service that started the machine.</item> + <tag><c><![CDATA[ERLSRV_EXECUTABLE]]></c></tag> + <item>The full path to the <c><![CDATA[erlsrv.exe]]></c>, which can be + used to manipulate the service. This comes in handy when defining a + heart command for your service.</item> + </taglist> + + <p>A command file for restarting a service looks as follows:</p> + <code type="none"><![CDATA[ @echo off %ERLSRV_EXECUTABLE% stop %ERLSRV_SERVICE_NAME% %ERLSRV_EXECUTABLE% start %ERLSRV_SERVICE_NAME% ]]></code> + <p>This command file is then set as heart command.</p> + <p>The environment variables can also be used to detect that we are running as a service and make port programs react correctly - to the control events generated on logout (see below).</p> + to the control events generated on logout (see the next section).</p> </section> <section> - <title>PORT PROGRAMS</title> + <title>Port Programs</title> <p>When a program runs in - the service context, it has to handle the control events that is + the service context, it must handle the control events that are sent to every program in the system when the interactive user logs off. This is done in different ways for programs running in the console subsystem and programs running as window - applications. An application which runs in the console subsystem + applications. An application running in the console subsystem (normal for port programs) uses the win32 function <c><![CDATA[SetConsoleCtrlHandler]]></c> to register a control handler - that returns TRUE in answer to the <c><![CDATA[CTRL_LOGOFF_EVENT]]></c> + that returns <c>true</c> in answer to the + <c><![CDATA[CTRL_LOGOFF_EVENT]]></c> and <c><![CDATA[CTRL_SHUTDOWN_EVENT]]></c> events. Other applications - just forward <c><![CDATA[WM_ENDSESSION]]></c> and - <c><![CDATA[WM_QUERYENDSESSION]]></c> to the default window procedure. - Here is a brief example in C of how to set the console control - handler:</p> + only forward <c><![CDATA[WM_ENDSESSION]]></c> and + <c><![CDATA[WM_QUERYENDSESSION]]></c> to the default window procedure.</p> + + <p>A brief example in C of how to set the console control handler:</p> + <code type="none"><![CDATA[ #include <windows.h> /* @@ -382,7 +487,7 @@ void initialize_handler(void){ char buffer[2]; /* * We assume we are running as a service if this - * environment variable is defined + * environment variable is defined. */ if(GetEnvironmentVariable("ERLSRV_SERVICE_NAME",buffer, (DWORD) 2)){ @@ -395,29 +500,34 @@ void initialize_handler(void){ </section> <section> - <title>NOTES</title> - <p>Even though the options are described in a Unix-like format, the case of - the options or commands is not relevant, and the "/" character for options - can be used as well as the "-" character. </p> - <p>Note that the program resides in the emulators - <c><![CDATA[bin]]></c>-directory, not in the <c><![CDATA[bin]]></c>-directory directly under + <title>Notes</title> + <p>Although the options are described in a Unix-like format, the case of + the options or commands is not relevant, and both character "/" and "-" + can be used for options.</p> + + <p>Notice that the program resides in the emulator's <c><![CDATA[bin]]></c> + directory, not in the <c><![CDATA[bin]]></c> directory directly under the Erlang root. The reasons for this are the subtle problem of upgrading the emulator on a running system, where a new version of the runtime system should not need to overwrite existing (and probably used) executables.</p> - <p>To easily manipulate the Erlang services, put + + <p>To manipulate the Erlang services easily, put the <c><![CDATA[<erlang_root>\erts-<version>\bin]]></c> directory in - the path instead of <c><![CDATA[<erlang_root>\bin]]></c>. The erlsrv program - can be found from inside Erlang by using the + the path instead of <c><![CDATA[<erlang_root>\bin]]></c>. The + <c>erlsrv</c> program can be found from inside Erlang by using the <c><![CDATA[os:find_executable/1]]></c> Erlang function.</p> - <p>For release handling to work, use <c><![CDATA[start_erl]]></c> as the Erlang - machine. It is also worth mentioning again that the name of the - service is significant (see <seealso marker="#001">above</seealso>).</p> + + <p>For release handling to work, use <c><![CDATA[start_erl]]></c> as the + Erlang machine. As stated <seealso marker="#001">above</seealso>, + the service name is significant.</p> </section> <section> - <title>SEE ALSO</title> - <p>start_erl(1), release_handler(3)</p> + <title>See Also</title> + <p><seealso marker="start_erl"><c>start_erl(1)</c></seealso>, + <seealso marker="sasl:release_handler"> + <c>release_handler(3)</c></seealso></p> </section> </comref> diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml index 1ade41f1aa..a094217959 100644 --- a/erts/doc/src/erts_alloc.xml +++ b/erts/doc/src/erts_alloc.xml @@ -4,88 +4,100 @@ <cref> <header> <copyright> - <year>2002</year><year>2014</year> + <year>2002</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> <title>erts_alloc</title> <prepared>Rickard Green</prepared> <docno>1</docno> - <date>03-06-11</date> + <date>2003-06-11</date> <rev>1</rev> <file>erts_alloc.xml</file> </header> <lib>erts_alloc</lib> - <libsummary>An Erlang Run-Time System internal memory allocator library.</libsummary> + <libsummary>An Erlang runtime system internal memory allocator library. + </libsummary> <description> - <p><c>erts_alloc</c> is an Erlang Run-Time System internal memory + <p><c>erts_alloc</c> is an Erlang runtime system internal memory allocator library. <c>erts_alloc</c> provides the Erlang - Run-Time System with a number of memory allocators.</p> + runtime system with a number of memory allocators.</p> </description> <section> <title>Allocators</title> <marker id="allocators"></marker> - <p>Currently the following allocators are present:</p> + <p>The following allocators are present:</p> + <taglist> <tag><c>temp_alloc</c></tag> <item>Allocator used for temporary allocations.</item> <tag><c>eheap_alloc</c></tag> - <item>Allocator used for Erlang heap data, such as Erlang process heaps.</item> + <item>Allocator used for Erlang heap data, such as Erlang process heaps. + </item> <tag><c>binary_alloc</c></tag> <item>Allocator used for Erlang binary data.</item> <tag><c>ets_alloc</c></tag> - <item>Allocator used for ETS data.</item> + <item>Allocator used for <c>ets</c> data.</item> <tag><c>driver_alloc</c></tag> <item>Allocator used for driver data.</item> + <tag><c>literal_alloc</c></tag> + <item>Allocator used for constant terms in Erlang code.</item> <tag><c>sl_alloc</c></tag> <item>Allocator used for memory blocks that are expected to be - short-lived.</item> + short-lived.</item> <tag><c>ll_alloc</c></tag> <item>Allocator used for memory blocks that are expected to be - long-lived, for example Erlang code.</item> + long-lived, for example, Erlang code.</item> <tag><c>fix_alloc</c></tag> <item>A fast allocator used for some frequently used fixed size data types.</item> + <tag><c>exec_alloc</c></tag> + <item>Allocator used by the <seealso marker="hipe:HiPE_app"><c>HiPE</c></seealso> + application for native executable code.</item> <tag><c>std_alloc</c></tag> - <item>Allocator used for most memory blocks not allocated via any of - the other allocators described above.</item> + <item>Allocator used for most memory blocks not allocated through any of + the other allocators described above.</item> <tag><c>sys_alloc</c></tag> <item>This is normally the default <c>malloc</c> implementation - used on the specific OS.</item> + used on the specific OS.</item> <tag><c>mseg_alloc</c></tag> - <item>A memory segment allocator. <c>mseg_alloc</c> is used by other - allocators for allocating memory segments and is currently only - available on systems that have the <c>mmap</c> system - call. Memory segments that are deallocated are kept for a - while in a segment cache before they are destroyed. When - segments are allocated, cached segments are used if possible - instead of creating new segments. This in order to reduce - the number of system calls made.</item> + <item>A memory segment allocator. It is used by other + allocators for allocating memory segments and is only + available on systems that have the <c>mmap</c> system + call. Memory segments that are deallocated are kept for a + while in a segment cache before they are destroyed. When + segments are allocated, cached segments are used if possible + instead of creating new segments. This to reduce + the number of system calls made.</item> </taglist> - <p><c>sys_alloc</c> is always enabled and - cannot be disabled. <c>mseg_alloc</c> is always enabled if it is + + <p><c>sys_alloc</c>, <c>literal_alloc</c> and <c>temp_alloc</c> are always + enabled and cannot be disabled. <c>exec_alloc</c> is only available if it + is needed and cannot be disabled. <c>mseg_alloc</c> is always enabled if it is available and an allocator that uses it is enabled. All other allocators can be <seealso marker="#M_e">enabled or disabled</seealso>. By default all allocators are enabled. When an allocator is disabled, <c>sys_alloc</c> is used instead of the disabled allocator.</p> + <p>The main idea with the <c>erts_alloc</c> library is to separate memory blocks that are used differently into different memory - areas, and by this achieving less memory fragmentation. By + areas, to achieve less memory fragmentation. By putting less effort in finding a good fit for memory blocks that are frequently allocated than for those less frequently allocated, a performance gain can be achieved.</p> @@ -93,61 +105,85 @@ <section> <marker id="alloc_util"></marker> - <title>The alloc_util framework</title> + <title>The alloc_util Framework</title> <p>Internally a framework called <c>alloc_util</c> is used for - implementing allocators. <c>sys_alloc</c>, and - <c>mseg_alloc</c> do not use this framework; hence, the + implementing allocators. <c>sys_alloc</c> and + <c>mseg_alloc</c> do not use this framework, so the following does <em>not</em> apply to them.</p> + <p>An allocator manages multiple areas, called carriers, in which memory blocks are placed. A carrier is either placed in a - separate memory segment (allocated via <c>mseg_alloc</c>), or in - the heap segment (allocated via <c>sys_alloc</c>). Multiblock - carriers are used for storage of several blocks. Singleblock - carriers are used for storage of one block. Blocks that are - larger than the value of the singleblock carrier threshold - (<seealso marker="#M_sbct">sbct</seealso>) parameter are placed - in singleblock carriers. Blocks that are smaller than the value - of the <c>sbct</c> parameter are placed in multiblock - carriers. Normally an allocator creates a "main multiblock + separate memory segment (allocated through <c>mseg_alloc</c>), or in + the heap segment (allocated through <c>sys_alloc</c>).</p> + + <list type="bulleted"> + <item> + <p>Multiblock carriers are used for storage of several blocks.</p> + </item> + <item> + <p>Singleblock carriers are used for storage of one block.</p> + </item> + <item> + <p>Blocks that are larger than the value of the singleblock carrier + threshold (<seealso marker="#M_sbct"><c>sbct</c></seealso>) parameter + are placed in singleblock carriers.</p> + </item> + <item> + <p>Blocks that are smaller than the value of parameter <c>sbct</c> + are placed in multiblock carriers.</p></item> + </list> + + <p>Normally an allocator creates a "main multiblock carrier". Main multiblock carriers are never deallocated. The - size of the main multiblock carrier is determined by the value - of the <seealso marker="#M_mmbcs">mmbcs</seealso> parameter.</p> + size of the main multiblock carrier is determined by the value of + parameter <seealso marker="#M_mmbcs"><c>mmbcs</c></seealso>.</p> + <p><marker id="mseg_mbc_sizes"></marker>Sizes of multiblock carriers - allocated via <c>mseg_alloc</c> are - decided based on the values of the largest multiblock carrier - size (<seealso marker="#M_lmbcs">lmbcs</seealso>), the smallest - multiblock carrier size (<seealso marker="#M_smbcs">smbcs</seealso>), - and the multiblock carrier growth stages - (<seealso marker="#M_mbcgs">mbcgs</seealso>) parameters. If - <c>nc</c> is the current number of multiblock carriers (the main + allocated through <c>mseg_alloc</c> are decided based on the + following parameters:</p> + + <list type="bulleted"> + <item>The values of the largest multiblock carrier size + (<seealso marker="#M_lmbcs"><c>lmbcs</c></seealso>)</item> + <item>The smallest multiblock carrier size + (<seealso marker="#M_smbcs"><c>smbcs</c></seealso>)</item> + <item>The multiblock carrier growth stages + (<seealso marker="#M_mbcgs"><c>mbcgs</c></seealso>)</item> + </list> + + <p>If <c>nc</c> is the current number of multiblock carriers (the main multiblock carrier excluded) managed by an allocator, the size of the next <c>mseg_alloc</c> multiblock carrier allocated by - this allocator will roughly be + this allocator is roughly <c><![CDATA[smbcs+nc*(lmbcs-smbcs)/mbcgs]]></c> when <c><![CDATA[nc <= mbcgs]]></c>, - and <c>lmbcs</c> when <c><![CDATA[nc > mbcgs]]></c>. If the value of the - <c>sbct</c> parameter should be larger than the value of the - <c>lmbcs</c> parameter, the allocator may have to create - multiblock carriers that are larger than the value of the - <c>lmbcs</c> parameter, though. - Singleblock carriers allocated via <c>mseg_alloc</c> are sized + and <c>lmbcs</c> when <c><![CDATA[nc > mbcgs]]></c>. If the value of + parameter <c>sbct</c> is larger than the value of parameter + <c>lmbcs</c>, the allocator may have to create + multiblock carriers that are larger than the value of + parameter <c>lmbcs</c>, though. + Singleblock carriers allocated through <c>mseg_alloc</c> are sized to whole pages.</p> - <p>Sizes of carriers allocated via <c>sys_alloc</c> are + + <p>Sizes of carriers allocated through <c>sys_alloc</c> are decided based on the value of the <c>sys_alloc</c> carrier size - (<seealso marker="#Muycs">ycs</seealso>) parameter. The size of - a carrier is the least number of multiples of the value of the - <c>ycs</c> parameter that satisfies the request.</p> + (<seealso marker="#Muycs"><c>ycs</c></seealso>) parameter. The size of + a carrier is the least number of multiples of the value of + parameter <c>ycs</c> satisfying the request.</p> + <p>Coalescing of free blocks are always performed immediately. - Boundary tags (headers and footers) in free blocks are used + Boundary tags (headers and footers) in free blocks are used, which makes the time complexity for coalescing constant.</p> + <p><marker id="strategy"></marker>The memory allocation strategy - used for multiblock carriers by an - allocator is configurable via the <seealso marker="#M_as">as</seealso> - parameter. Currently the following strategies are available:</p> + used for multiblock carriers by an allocator can be + configured using parameter <seealso marker="#M_as"><c>as</c></seealso>. + The following strategies are available:</p> + <taglist> <tag>Best fit</tag> <item> - <p>Strategy: Find the smallest block that satisfies the + <p>Strategy: Find the smallest block satisfying the requested block size.</p> <p>Implementation: A balanced binary search tree is used. The time complexity is proportional to log N, where @@ -155,7 +191,7 @@ </item> <tag>Address order best fit</tag> <item> - <p>Strategy: Find the smallest block that satisfies the + <p>Strategy: Find the smallest block satisfying the requested block size. If multiple blocks are found, choose the one with the lowest address.</p> <p>Implementation: A balanced binary search tree is @@ -164,7 +200,7 @@ </item> <tag>Address order first fit</tag> <item> - <p>Strategy: Find the block with the lowest address that satisfies the + <p>Strategy: Find the block with the lowest address satisfying the requested block size.</p> <p>Implementation: A balanced binary search tree is used. The time complexity is proportional to log N, where @@ -173,8 +209,8 @@ <tag>Address order first fit carrier best fit</tag> <item> <p>Strategy: Find the <em>carrier</em> with the lowest address that - can satisfy the requested block size, then find a block within - that carrier using the "best fit" strategy.</p> + can satisfy the requested block size, then find a block within + that carrier using the "best fit" strategy.</p> <p>Implementation: Balanced binary search trees are used. The time complexity is proportional to log N, where N is the number of free blocks.</p> @@ -182,8 +218,35 @@ <tag>Address order first fit carrier address order best fit</tag> <item> <p>Strategy: Find the <em>carrier</em> with the lowest address that - can satisfy the requested block size, then find a block within - that carrier using the "adress order best fit" strategy.</p> + can satisfy the requested block size, then find a block within + that carrier using the "address order best fit" strategy.</p> + <p>Implementation: Balanced binary search trees are + used. The time complexity is proportional to log N, where + N is the number of free blocks.</p> + </item> + <tag>Age order first fit carrier address order first fit</tag> + <item> + <p>Strategy: Find the <em>oldest carrier</em> that + can satisfy the requested block size, then find a block within + that carrier using the "address order first fit" strategy.</p> + <p>Implementation: A balanced binary search tree is + used. The time complexity is proportional to log N, where + N is the number of free blocks.</p> + </item> + <tag>Age order first fit carrier best fit</tag> + <item> + <p>Strategy: Find the <em>oldest carrier</em> that + can satisfy the requested block size, then find a block within + that carrier using the "best fit" strategy.</p> + <p>Implementation: Balanced binary search trees are + used. The time complexity is proportional to log N, where + N is the number of free blocks.</p> + </item> + <tag>Age order first fit carrier address order best fit</tag> + <item> + <p>Strategy: Find the <em>oldest carrier</em> that + can satisfy the requested block size, then find a block within + that carrier using the "address order best fit" strategy.</p> <p>Implementation: Balanced binary search trees are used. The time complexity is proportional to log N, where N is the number of free blocks.</p> @@ -193,12 +256,12 @@ <p>Strategy: Try to find the best fit, but settle for the best fit found during a limited search.</p> <p>Implementation: The implementation uses segregated free - lists with a maximum block search depth (in each list) in - order to find a good fit fast. When the maximum block - search depth is small (by default 3) this implementation + lists with a maximum block search depth (in each list) + to find a good fit fast. When the maximum block + search depth is small (by default 3), this implementation has a time complexity that is constant. The maximum block - search depth is configurable via the - <seealso marker="#M_mbsd">mbsd</seealso> parameter.</p> + search depth can be configured using parameter + <seealso marker="#M_mbsd"><c>mbsd</c></seealso>.</p> </item> <tag>A fit</tag> <item> @@ -206,452 +269,576 @@ block to see if it satisfies the request. This strategy is only intended to be used for temporary allocations.</p> <p>Implementation: Inspect the first block in a free-list. - If it satisfies the request, it is used; otherwise, a new + If it satisfies the request, it is used, otherwise a new carrier is created. The implementation has a time complexity that is constant.</p> - <p>As of erts version 5.6.1 the emulator will refuse to - use this strategy on other allocators than <c>temp_alloc</c>. - This since it will only cause problems for other allocators.</p> + <p>As from ERTS 5.6.1 the emulator refuses to + use this strategy on other allocators than <c>temp_alloc</c>. + This because it only causes problems for other allocators.</p> </item> </taglist> - <p>Apart from the ordinary allocators described above a number of - pre-allocators are used for some specific data types. These - pre-allocators pre-allocate a fixed amount of memory for certain data - types when the run-time system starts. As long as pre-allocated memory - is available, it will be used. When no pre-allocated memory is - available, memory will be allocated in ordinary allocators. These - pre-allocators are typically much faster than the ordinary allocators, - but can only satisfy a limited amount of requests.</p> + + <p>Apart from the ordinary allocators described above, some + pre-allocators are used for some specific data types. These + pre-allocators pre-allocate a fixed amount of memory for certain data + types when the runtime system starts. As long as pre-allocated memory + is available, it is used. When no pre-allocated memory is + available, memory is allocated in ordinary allocators. These + pre-allocators are typically much faster than the ordinary allocators, + but can only satisfy a limited number of requests.</p> </section> <section> <marker id="flags"></marker> <title>System Flags Effecting erts_alloc</title> <warning> - <p>Only use these flags if you are absolutely sure what you are - doing. Unsuitable settings may cause serious performance + <p>Only use these flags if you are sure what you are + doing. Unsuitable settings can cause serious performance degradation and even a system crash at any time during operation.</p> </warning> + <p>Memory allocator system flags have the following syntax: - <c><![CDATA[+M<S><P> <V>]]></c> + <c><![CDATA[+M<S><P> <V>]]></c>, where <c><![CDATA[<S>]]></c> is a letter identifying a subsystem, <c><![CDATA[<P>]]></c> is a parameter, and <c><![CDATA[<V>]]></c> is the value to use. The flags can be passed to the Erlang emulator - (<seealso marker="erl">erl</seealso>) as command line + (<seealso marker="erl"><c>erl(1)</c></seealso>) as command-line arguments.</p> - <p>System flags effecting specific allocators have an upper-case + + <p>System flags effecting specific allocators have an uppercase letter as <c><![CDATA[<S>]]></c>. The following letters are used for - the currently present allocators:</p> + the allocators:</p> + <list type="bulleted"> <item><c>B: binary_alloc</c></item> <item><c>D: std_alloc</c></item> <item><c>E: ets_alloc</c></item> <item><c>F: fix_alloc</c></item> <item><c>H: eheap_alloc</c></item> + <item><c>I: literal_alloc</c></item> <item><c>L: ll_alloc</c></item> <item><c>M: mseg_alloc</c></item> <item><c>R: driver_alloc</c></item> <item><c>S: sl_alloc</c></item> <item><c>T: temp_alloc</c></item> + <item><c>X: exec_alloc</c></item> <item><c>Y: sys_alloc</c></item> </list> - <p>The following flags are available for configuration of - <c>mseg_alloc</c>:</p> - <taglist> - <tag><marker id="MMamcbf"><c><![CDATA[+MMamcbf <size>]]></c></marker></tag> - <item> - Absolute max cache bad fit (in kilobytes). A segment in the - memory segment cache is not reused if its size exceeds the - requested size with more than the value of this - parameter. Default value is 4096. </item> - <tag><marker id="MMrmcbf"><c><![CDATA[+MMrmcbf <ratio>]]></c></marker></tag> - <item> - Relative max cache bad fit (in percent). A segment in the - memory segment cache is not reused if its size exceeds the - requested size with more than relative max cache bad fit - percent of the requested size. Default value is 20.</item> - <tag><marker id="MMsco"><c><![CDATA[+MMsco true|false]]></c></marker></tag> - <item> - Set <seealso marker="#MMscs">super carrier</seealso> only flag. This - flag defaults to <c>true</c>. When a super carrier is used and this - flag is <c>true</c>, <c>mseg_alloc</c> will only create carriers - in the super carrier. Note that the <c>alloc_util</c> framework may - create <c>sys_alloc</c> carriers, so if you want all carriers to - be created in the super carrier, you therefore want to disable use - of <c>sys_alloc</c> carriers by also passing - <seealso marker="#Musac"><c>+Musac false</c></seealso>. When the flag - is <c>false</c>, <c>mseg_alloc</c> will try to create carriers outside - of the super carrier when the super carrier is full. - <br/><br/> - <em>NOTE</em>: Setting this flag to <c>false</c> may not be supported - on all systems. This flag will in that case be ignored. - <br/><br/> - <em>NOTE</em>: The super carrier cannot be enabled nor - disabled on halfword heap systems. This flag will be - ignored on halfword heap systems. - </item> - <tag><marker id="MMscrfsd"><c><![CDATA[+MMscrfsd <amount>]]></c></marker></tag> - <item> - Set <seealso marker="#MMscs">super carrier</seealso> reserved - free segment descriptors. This parameter defaults to <c>65536</c>. - This parameter determines the amount of memory to reserve for - free segment descriptors used by the super carrier. If the system - runs out of reserved memory for free segment descriptors, other - memory will be used. This may however cause fragmentation issues, - so you want to ensure that this never happens. The maximum amount - of free segment descriptors used can be retrieved from the - <c>erts_mmap</c> tuple part of the result from calling - <seealso marker="erts:erlang#system_info_allocator_tuple">erlang:system_info({allocator, mseg_alloc})</seealso>. - </item> - <tag><marker id="MMscrpm"><c><![CDATA[+MMscrpm true|false]]></c></marker></tag> - <item> - Set <seealso marker="#MMscs">super carrier</seealso> reserve physical - memory flag. This flag defaults to <c>true</c>. When this flag is - <c>true</c>, physical memory will be reserved for the whole super - carrier at once when it is created. The reservation will after that - be left unchanged. When this flag is set to <c>false</c> only virtual - address space will be reserved for the super carrier upon creation. - The system will attempt to reserve physical memory upon carrier - creations in the super carrier, and attempt to unreserve physical - memory upon carrier destructions in the super carrier. - <br/><br/> - <em>NOTE</em>: What reservation of physical memory actually means - highly depends on the operating system, and how it is configured. For - example, different memory overcommit settings on Linux drastically - change the behaviour. Also note, setting this flag to <c>false</c> - may not be supported on all systems. This flag will in that case - be ignored. - <br/><br/> - <em>NOTE</em>: The super carrier cannot be enabled nor - disabled on halfword heap systems. This flag will be - ignored on halfword heap systems. - </item> - <tag><marker id="MMscs"><c><![CDATA[+MMscs <size in MB>]]></c></marker></tag> - <item> - Set super carrier size (in MB). The super carrier size defaults to - zero; i.e, the super carrier is by default disabled. The super - carrier is a large continuous area in the virtual address space. - <c>mseg_alloc</c> will always try to create new carriers in the super - carrier if it exists. Note that the <c>alloc_util</c> framework may - create <c>sys_alloc</c> carriers. For more information on this, see the - documentation of the <seealso marker="#MMsco"><c>+MMsco</c></seealso> - flag. - <br/><br/> - <em>NOTE</em>: The super carrier cannot be enabled nor - disabled on halfword heap systems. This flag will be - ignored on halfword heap systems. - </item> - <tag><marker id="MMmcs"><c><![CDATA[+MMmcs <amount>]]></c></marker></tag> - <item> - Max cached segments. The maximum number of memory segments - stored in the memory segment cache. Valid range is - 0-30. Default value is 10.</item> - </taglist> - <p>The following flags are available for configuration of - <c>sys_alloc</c>:</p> - <taglist> - <tag><marker id="MYe"><c>+MYe true</c></marker></tag> - <item> - Enable <c>sys_alloc</c>. Note: <c>sys_alloc</c> cannot be disabled.</item> - <tag><marker id="MYm"><c>+MYm libc</c></marker></tag> - <item> - <c>malloc</c> library to use. Currently only - <c>libc</c> is available. <c>libc</c> enables the standard - <c>libc</c> malloc implementation. By default <c>libc</c> is used.</item> - <tag><marker id="MYtt"><c><![CDATA[+MYtt <size>]]></c></marker></tag> - <item> - Trim threshold size (in kilobytes). This is the maximum amount - of free memory at the top of the heap (allocated by - <c>sbrk</c>) that will be kept by <c>malloc</c> (not - released to the operating system). When the amount of free - memory at the top of the heap exceeds the trim threshold, - <c>malloc</c> will release it (by calling - <c>sbrk</c>). Trim threshold is given in kilobytes. Default - trim threshold is 128. <em>Note:</em> This flag will - only have any effect when the emulator has been linked with - the GNU C library, and uses its <c>malloc</c> implementation.</item> - <tag><marker id="MYtp"><c><![CDATA[+MYtp <size>]]></c></marker></tag> - <item> - Top pad size (in kilobytes). This is the amount of extra - memory that will be allocated by <c>malloc</c> when - <c>sbrk</c> is called to get more memory from the operating - system. Default top pad size is 0. <em>Note:</em> This flag - will only have any effect when the emulator has been linked - with the GNU C library, and uses its <c>malloc</c> - implementation.</item> - </taglist> - <p>The following flags are available for configuration of allocators - based on <c>alloc_util</c>. If <c>u</c> is used as subsystem - identifier (i.e., <c><![CDATA[<S> = u]]></c>) all allocators based on - <c>alloc_util</c> will be effected. If <c>B</c>, <c>D</c>, <c>E</c>, - <c>F</c>, <c>H</c>, <c>L</c>, <c>R</c>, <c>S</c>, or <c>T</c> is used as - subsystem identifier, only the specific allocator identified will be - effected:</p> - <taglist> - <tag><marker id="M_acul"><c><![CDATA[+M<S>acul <utilization>|de]]></c></marker></tag> - <item> - Abandon carrier utilization limit. A valid - <c><![CDATA[<utilization>]]></c> is an integer in the range - <c>[0, 100]</c> representing utilization in percent. When a - utilization value larger than zero 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 will be used. The actual - value chosen depend on allocator type and may be changed between - ERTS versions. Currently the default equals <c>de</c>, but this - may be changed in the future. Carriers will be abandoned when - memory utilization in the allocator instance falls below the - utilization value used. Once a carrier has been abandoned, no new - allocations will be made in it. When an allocator instance gets an - increased multiblock carrier need, it will first try to fetch an - abandoned carrier from an allocator instances of the same - allocator type. If no abandoned carrier could be fetched, it will - create a new empty carrier. When an abandoned carrier has been - fetched it will function as an ordinary carrier. This feature has - special requirements on the - <seealso marker="#M_as">allocation strategy</seealso> used. Currently - only the strategies <c>aoff</c>, <c>aoffcbf</c> and <c>aoffcaobf</c> support - abandoned carriers. This feature also requires - <seealso marker="#M_t">multiple thread specific instances</seealso> - to be enabled. When enabling this feature, multiple thread specific - instances will be enabled if not already enabled, and the - <c>aoffcbf</c> strategy will be enabled if current strategy does not - support abandoned carriers. This feature can be enabled on all - allocators based on the <c>alloc_util</c> framework with the - exception of <c>temp_alloc</c> (which would be pointless). - </item> - <tag><marker id="M_as"><c><![CDATA[+M<S>as bf|aobf|aoff|aoffcbf|aoffcaobf|gf|af]]></c></marker></tag> - <item> - Allocation strategy. Valid strategies are <c>bf</c> (best fit), - <c>aobf</c> (address order best fit), <c>aoff</c> (address order first fit), - <c>aoffcbf</c> (address order first fit carrier best fit), - <c>aoffcaobf</c> (address order first fit carrier address order best fit), - <c>gf</c> (good fit), and <c>af</c> (a fit). See - <seealso marker="#strategy">the description of allocation strategies</seealso> in "the <c>alloc_util</c> framework" section.</item> - <tag><marker id="M_asbcst"><c><![CDATA[+M<S>asbcst <size>]]></c></marker></tag> - <item> - Absolute singleblock carrier shrink threshold (in - kilobytes). When a block located in an - <c>mseg_alloc</c> singleblock carrier is shrunk, the carrier - will be left unchanged if the amount of unused memory is less - than this threshold; otherwise, the carrier will be shrunk. - See also <seealso marker="#M_rsbcst">rsbcst</seealso>.</item> - <tag><marker id="M_e"><c><![CDATA[+M<S>e true|false]]></c></marker></tag> - <item> - Enable allocator <c><![CDATA[<S>]]></c>.</item> - <tag><marker id="M_lmbcs"><c><![CDATA[+M<S>lmbcs <size>]]></c></marker></tag> - <item> - Largest (<c>mseg_alloc</c>) multiblock carrier size (in - kilobytes). See <seealso marker="#mseg_mbc_sizes">the description - on how sizes for mseg_alloc multiblock carriers are decided</seealso> - in "the <c>alloc_util</c> framework" section. On 32-bit Unix style OS - this limit can not be set higher than 128 megabyte.</item> - <tag><marker id="M_mbcgs"><c><![CDATA[+M<S>mbcgs <ratio>]]></c></marker></tag> - <item> - (<c>mseg_alloc</c>) multiblock carrier growth stages. See - <seealso marker="#mseg_mbc_sizes">the description on how sizes for - mseg_alloc multiblock carriers are decided</seealso> - in "the <c>alloc_util</c> framework" section.</item> - <tag><marker id="M_mbsd"><c><![CDATA[+M<S>mbsd <depth>]]></c></marker></tag> - <item> - Max block search depth. This flag has effect only if the - good fit strategy has been selected for allocator - <c><![CDATA[<S>]]></c>. When the good fit strategy is used, free - blocks are placed in segregated free-lists. Each free list - contains blocks of sizes in a specific range. The max block - search depth sets a limit on the maximum number of blocks to - inspect in a free list during a search for suitable block - satisfying the request.</item> - <tag><marker id="M_mmbcs"><c><![CDATA[+M<S>mmbcs <size>]]></c></marker></tag> - <item> - Main multiblock carrier size. Sets the size of the main - multiblock carrier for allocator <c><![CDATA[<S>]]></c>. The main - multiblock carrier is allocated via <c><![CDATA[sys_alloc]]></c> and is - never deallocated.</item> - <tag><marker id="M_mmmbc"><c><![CDATA[+M<S>mmmbc <amount>]]></c></marker></tag> - <item> - Max <c>mseg_alloc</c> multiblock carriers. Maximum number of - multiblock carriers allocated via <c>mseg_alloc</c> by - allocator <c><![CDATA[<S>]]></c>. When this limit has been reached, - new multiblock carriers will be allocated via - <c>sys_alloc</c>.</item> - <tag><marker id="M_mmsbc"><c><![CDATA[+M<S>mmsbc <amount>]]></c></marker></tag> - <item> - Max <c>mseg_alloc</c> singleblock carriers. Maximum number of - singleblock carriers allocated via <c>mseg_alloc</c> by - allocator <c><![CDATA[<S>]]></c>. When this limit has been reached, - new singleblock carriers will be allocated via - <c>sys_alloc</c>.</item> - <tag><marker id="M_ramv"><c><![CDATA[+M<S>ramv <bool>]]></c></marker></tag> - <item> - Realloc always moves. When enabled, reallocate operations will - more or less be translated into an allocate, copy, free sequence. - This often reduce memory fragmentation, but costs performance. - </item> - <tag><marker id="M_rmbcmt"><c><![CDATA[+M<S>rmbcmt <ratio>]]></c></marker></tag> - <item> - Relative multiblock carrier move threshold (in percent). When - a block located in a multiblock carrier is shrunk, - the block will be moved if the ratio of the size of the returned - memory compared to the previous size is more than this threshold; - otherwise, the block will be shrunk at current location.</item> - <tag><marker id="M_rsbcmt"><c><![CDATA[+M<S>rsbcmt <ratio>]]></c></marker></tag> - <item> - Relative singleblock carrier move threshold (in percent). When - a block located in a singleblock carrier is shrunk to - a size smaller than the value of the - <seealso marker="#M_sbct">sbct</seealso> parameter, - the block will be left unchanged in the singleblock carrier if - the ratio of unused memory is less than this threshold; - otherwise, it will be moved into a multiblock carrier. </item> - <tag><marker id="M_rsbcst"><c><![CDATA[+M<S>rsbcst <ratio>]]></c></marker></tag> - <item> - Relative singleblock carrier shrink threshold (in - percent). When a block located in an <c>mseg_alloc</c> - singleblock carrier is shrunk, the carrier will be left - unchanged if the ratio of unused memory is less than this - threshold; otherwise, the carrier will be shrunk. - See also <seealso marker="#M_asbcst">asbcst</seealso>.</item> - <tag><marker id="M_sbct"><c><![CDATA[+M<S>sbct <size>]]></c></marker></tag> - <item> - Singleblock carrier threshold. Blocks larger than this - threshold will be placed in singleblock carriers. Blocks - smaller than this threshold will be placed in multiblock - carriers. On 32-bit Unix style OS this threshold can not be set higher - than 8 megabytes.</item> - <tag><marker id="M_smbcs"><c><![CDATA[+M<S>smbcs <size>]]></c></marker></tag> - <item> - Smallest (<c>mseg_alloc</c>) multiblock carrier size (in - kilobytes). See <seealso marker="#mseg_mbc_sizes">the description - on how sizes for mseg_alloc multiblock carriers are decided</seealso> - in "the <c>alloc_util</c> framework" section.</item> - <tag><marker id="M_t"><c><![CDATA[+M<S>t true|false]]></c></marker></tag> - <item> - <p>Multiple, thread specific instances of the allocator. - This option will only have any effect on the runtime system - with SMP support. Default behaviour on the runtime system with - SMP support is <c>NoSchedulers+1</c> instances. Each scheduler will use - a lock-free instance of its own and other threads will use - a common instance.</p> - <p>It was previously (before ERTS version 5.9) possible to configure - a smaller amount of thread specific instances than schedulers. - This is, however, not possible any more.</p> - </item> - </taglist> - <p>Currently the following flags are available for configuration of - <c>alloc_util</c>, i.e. all allocators based on <c>alloc_util</c> - will be effected:</p> - <taglist> - <tag><marker id="Muycs"><c><![CDATA[+Muycs <size>]]></c></marker></tag> - <item> - <c>sys_alloc</c> carrier size. Carriers allocated via - <c>sys_alloc</c> will be allocated in sizes which are - multiples of the <c>sys_alloc</c> carrier size. This is not - true for main multiblock carriers and carriers allocated - during a memory shortage, though.</item> - <tag><marker id="Mummc"><c><![CDATA[+Mummc <amount>]]></c></marker></tag> - <item> - Max <c>mseg_alloc</c> carriers. Maximum number of carriers - placed in separate memory segments. When this limit has been - reached, new carriers will be placed in memory retrieved from - <c>sys_alloc</c>.</item> - <tag><marker id="Musac"><c><![CDATA[+Musac <bool>]]></c></marker></tag> - <item> - Allow <c>sys_alloc</c> carriers. By default <c>true</c>. If - set to <c>false</c>, <c>sys_alloc</c> carriers will never be - created by allocators using the <c>alloc_util</c> framework.</item> - </taglist> - <p>Instrumentation flags:</p> - <taglist> - <tag><marker id="Mim"><c>+Mim true|false</c></marker></tag> - <item> - A map over current allocations is kept by the emulator. The - allocation map can be retrieved via the <c>instrument</c> - module. <c>+Mim true</c> implies <c>+Mis true</c>. - <c>+Mim true</c> is the same as - <seealso marker="erl#instr">-instr</seealso>.</item> - <tag><marker id="Mis"><c>+Mis true|false</c></marker></tag> - <item> - Status over allocated memory is kept by the emulator. The - allocation status can be retrieved via the <c>instrument</c> - module.</item> - <tag><marker id="Mit"><c>+Mit X</c></marker></tag> - <item> - Reserved for future use. Do <em>not</em> use this flag.</item> - </taglist> - <note> - <p>When instrumentation of the emulator is enabled, the emulator - uses more memory and runs slower.</p> - </note> - <p>Other flags:</p> - <taglist> - <tag><marker id="Mea"><c>+Mea min|max|r9c|r10b|r11b|config</c></marker></tag> - <item> + + <section> + <title>Flags for Configuration of mseg_alloc</title> + <taglist> + <tag><marker id="MMamcbf"/><c><![CDATA[+MMamcbf <size>]]></c></tag> + <item> + <p>Absolute maximum cache bad fit (in kilobytes). A segment in the + memory segment cache is not reused if its size exceeds the + requested size with more than the value of this + parameter. Defaults to <c>4096</c>.</p> + </item> + <tag><marker id="MMrmcbf"/><c><![CDATA[+MMrmcbf <ratio>]]></c></tag> + <item> + <p>Relative maximum cache bad fit (in percent). A segment in the + memory segment cache is not reused if its size exceeds the + requested size with more than relative maximum cache bad fit + percent of the requested size. Defaults to <c>20</c>.</p> + </item> + <tag><marker id="MMsco"/><c><![CDATA[+MMsco true|false]]></c></tag> + <item> + <p>Sets <seealso marker="#MMscs">super carrier</seealso> only flag. + Defaults to <c>true</c>. When a super carrier is used and this + flag is <c>true</c>, <c>mseg_alloc</c> only creates carriers in + the super carrier. Notice that the <c>alloc_util</c> framework can + create <c>sys_alloc</c> carriers, so if you want all carriers to + be created in the super carrier, you therefore want to disable use + of <c>sys_alloc</c> carriers by also passing + <seealso marker="#Musac"><c>+Musac false</c></seealso>. When + the flag is <c>false</c>, <c>mseg_alloc</c> tries to create carriers + outside of the super carrier when the super carrier is full.</p> + <note> + <p>Setting this flag to <c>false</c> is not supported + on all systems. The flag is then ignored.</p> + </note> + </item> + <tag><marker id="MMscrfsd"/><c><![CDATA[+MMscrfsd <amount>]]></c></tag> + <item> + <p>Sets <seealso marker="#MMscs">super carrier</seealso> reserved + free segment descriptors. Defaults to <c>65536</c>. + This parameter determines the amount of memory to reserve for + free segment descriptors used by the super carrier. If the system + runs out of reserved memory for free segment descriptors, other + memory is used. This can however cause fragmentation issues, + so you want to ensure that this never happens. The maximum amount + of free segment descriptors used can be retrieved from the + <c>erts_mmap</c> tuple part of the result from calling + <seealso marker="erts:erlang#system_info_allocator_tuple"> + <c>erlang:system_info({allocator, mseg_alloc})</c></seealso>.</p> + </item> + <tag><marker id="MMscrpm"/><c><![CDATA[+MMscrpm true|false]]></c></tag> + <item> + <p>Sets <seealso marker="#MMscs">super carrier</seealso> reserve + physical memory flag. Defaults to <c>true</c>. When this flag is + <c>true</c>, physical memory is reserved for the whole super + carrier at once when it is created. The reservation is after that + left unchanged. When this flag is set to <c>false</c>, only virtual + address space is reserved for the super carrier upon creation. + The system attempts to reserve physical memory upon carrier + creations in the super carrier, and attempt to unreserve physical + memory upon carrier destructions in the super carrier.</p> + <note> + <p>What reservation of physical memory means, highly + depends on the operating system, and how it is configured. For + example, different memory overcommit settings on Linux drastically + change the behavior.</p> + <p>Setting this flag to <c>false</c> is possibly not supported on + all systems. The flag is then ignored.</p> + </note> + </item> + <tag><marker id="MMscs"/><c><![CDATA[+MMscs <size in MB>]]></c></tag> + <item> + <p>Sets super carrier size (in MB). Defaults to <c>0</c>, that is, + the super carrier is by default disabled. The super + carrier is a large continuous area in the virtual address space. + <c>mseg_alloc</c> always tries to create new carriers in the super + carrier if it exists. Notice that the <c>alloc_util</c> framework + can create <c>sys_alloc</c> carriers. For more information, see + <seealso marker="#MMsco"><c>+MMsco</c></seealso>.</p> + </item> + <tag><marker id="MMmcs"/><c><![CDATA[+MMmcs <amount>]]></c></tag> + <item> + <p>Maximum cached segments. The maximum number of memory segments + stored in the memory segment cache. Valid range is <c>[0, 30]</c>. + Defaults to <c>10</c>.</p> + </item> + </taglist> + </section> + + <section> + <title>Flags for Configuration of sys_alloc</title> + <taglist> + <tag><marker id="MYe"/><c>+MYe true</c></tag> + <item> + <p>Enables <c>sys_alloc</c>.</p> + <note> + <p><c>sys_alloc</c> cannot be disabled.</p> + </note> + </item> + <tag><marker id="MYm"/><c>+MYm libc</c></tag> + <item> + <p><c>malloc</c> library to use. Only + <c>libc</c> is available. <c>libc</c> enables the standard + <c>libc</c> <c>malloc</c> implementation. By default <c>libc</c> + is used.</p> + </item> + <tag><marker id="MYtt"/><c><![CDATA[+MYtt <size>]]></c></tag> + <item> + <p>Trim threshold size (in kilobytes). This is the maximum amount + of free memory at the top of the heap (allocated by + <c>sbrk</c>) that is kept by <c>malloc</c> (not + released to the operating system). When the amount of free + memory at the top of the heap exceeds the trim threshold, + <c>malloc</c> releases it (by calling <c>sbrk</c>). + Trim threshold is specified in kilobytes. + Defaults to <c>128</c>.</p> + <note> + <p>This flag has effect only when the emulator is linked with + the GNU C library, and uses its <c>malloc</c> implementation.</p> + </note> + </item> + <tag><marker id="MYtp"/><c><![CDATA[+MYtp <size>]]></c></tag> + <item> + <p>Top pad size (in kilobytes). This is the amount of extra + memory that is allocated by <c>malloc</c> when + <c>sbrk</c> is called to get more memory from the operating + system. Defaults to <c>0</c>.</p> + <note> + <p>This flag has effect only when the emulator is linked with + the GNU C library, and uses its <c>malloc</c> implementation.</p> + </note> + </item> + </taglist> + </section> + + <section> + <title>Flags for Configuration of Allocators Based on alloc_util</title> + <p>If <c>u</c> is used as subsystem identifier (that is, + <c><![CDATA[<S> = u]]></c>), all allocators based on + <c>alloc_util</c> are effected. If <c>B</c>, <c>D</c>, <c>E</c>, + <c>F</c>, <c>H</c>, <c>L</c>, <c>R</c>, <c>S</c>, or <c>T</c> is used + as subsystem identifier, only the specific allocator identifier is + effected.</p> + + <taglist> + <tag><marker id="M_acul"/><c><![CDATA[+M<S>acul <utilization>|de]]></c> + </tag> + <item> + <p>Abandon carrier utilization limit. A valid + <c><![CDATA[<utilization>]]></c> is an integer in the range + <c>[0, 100]</c> representing utilization in percent. When a + 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 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> + <p>Carriers are abandoned when + memory utilization in the allocator instance falls below the + utilization value used. Once a carrier is abandoned, no new + allocations are made in it. When an allocator instance gets an + increased multiblock carrier need, it first tries to fetch an + abandoned carrier from an allocator instance of the same + allocator type. If no abandoned carrier can be fetched, it + creates a new empty carrier. When an abandoned carrier has been + fetched, it will function as an ordinary carrier. This feature has + special requirements on the + <seealso marker="#M_as">allocation strategy</seealso> used. Only + the strategies <c>aoff</c>, <c>aoffcbf</c>, <c>aoffcaobf</c>, + <c>ageffcaoff</c>m, <c>ageffcbf</c> and <c>ageffcaobf</c> + support abandoned carriers.</p> + <p>This feature also requires + <seealso marker="#M_t">multiple thread specific instances</seealso> + to be enabled. When enabling this feature, multiple thread-specific + instances are enabled if not already enabled, and the + <c>aoffcbf</c> strategy is enabled if the current strategy does not + support abandoned carriers. This feature can be enabled on all + allocators based on the <c>alloc_util</c> framework, except + <c>temp_alloc</c> (which would be pointless).</p> + </item> + + <tag><marker id="M_acfml"/><c><![CDATA[+M<S>acfml <bytes>]]></c> + </tag> + <item> + <p>Abandon carrier free block min limit. A valid <c><![CDATA[<bytes>]]></c> + is a positive integer representing a block size limit. The largest + free block in a carrier must be at least <c>bytes</c> large, for the + carrier to be abandoned. The default is zero but can be changed + in the future.</p> + <p>See also <seealso marker="#M_acul"><c>acul</c></seealso>.</p> + </item> + + <tag><marker id="M_acnl"/><c><![CDATA[+M<S>acnl <amount>]]></c> + </tag> + <item> + <p>Abandon carrier number limit. A valid <c><![CDATA[<amount>]]></c> + is a positive integer representing max number of abandoned carriers per + allocator instance. Defaults to 1000 which will practically disable + the limit, but this can be changed in the future.</p> + <p>See also <seealso marker="#M_acul"><c>acul</c></seealso>.</p> + </item> + + <tag><marker id="M_as"/> + <c><![CDATA[+M<S>as bf|aobf|aoff|aoffcbf|aoffcaobf|ageffcaoff|ageffcbf|ageffcaobf|gf|af]]></c></tag> + <item> + <p>Allocation strategy. The following strategies are valid:</p> + <list type="bulleted"> + <item><c>bf</c> (best fit)</item> + <item><c>aobf</c> (address order best fit)</item> + <item><c>aoff</c> (address order first fit)</item> + <item><c>aoffcbf</c> (address order first fit carrier best fit) + </item> + <item><c>aoffcaobf</c> (address order first fit carrier address + order best fit)</item> + <item><c>ageffcaoff</c> (age order first fit carrier address order first fit)</item> + <item><c>ageffcbf</c> (age order first fit carrier best fit) + </item> + <item><c>ageffcaobf</c> (age order first fit carrier address + order best fit)</item> + <item><c>gf</c> (good fit)</item> + <item><c>af</c> (a fit)</item> + </list> + <p>See the description of allocation strategies in section + <seealso marker="#strategy">The alloc_util Framework</seealso>.</p> + </item> + <tag><marker id="M_asbcst"/><c><![CDATA[+M<S>asbcst <size>]]></c></tag> + <item> + <p>Absolute singleblock carrier shrink threshold (in + kilobytes). When a block located in an + <c>mseg_alloc</c> singleblock carrier is shrunk, the carrier + is left unchanged if the amount of unused memory is less + than this threshold, otherwise the carrier is shrunk. + See also <seealso marker="#M_rsbcst"><c>rsbcst</c></seealso>.</p> + </item> + <tag><marker id="M_atags"/><c><![CDATA[+M<S>atags true|false]]></c></tag> + <item> + <p>Adds a small tag to each allocated block that contains basic + information about what it is and who allocated it. Use the + <seealso marker="tools:instrument"><c>instrument</c></seealso> + module to inspect this information.</p> + + <p>The runtime overhead is one word per allocation when enabled. This + may change at any time in the future.</p> + + <p>The default is <c>true</c> for <c>binary_alloc</c> and + <c>driver_alloc</c>, and <c>false</c> for the other allocator + types.</p> + </item> + <tag><marker id="M_e"/><c><![CDATA[+M<S>e true|false]]></c></tag> + <item> + <p>Enables allocator <c><![CDATA[<S>]]></c>.</p> + </item> + <tag><marker id="M_lmbcs"/><c><![CDATA[+M<S>lmbcs <size>]]></c></tag> + <item> + <p>Largest (<c>mseg_alloc</c>) multiblock carrier size (in kilobytes). + See the description on how sizes for <c>mseg_alloc</c> multiblock + carriers are decided in section + <seealso marker="#mseg_mbc_sizes"> + The alloc_util Framework</seealso>. On + 32-bit Unix style OS this limit cannot be set > 128 MB.</p> + </item> + <tag><marker id="M_mbcgs"/><c><![CDATA[+M<S>mbcgs <ratio>]]></c></tag> + <item> + <p>(<c>mseg_alloc</c>) multiblock carrier growth stages. + See the description on how sizes for <c>mseg_alloc</c> multiblock + carriers are decided in section + <seealso marker="#mseg_mbc_sizes"> + The alloc_util Framework</seealso>.</p> + </item> + <tag><marker id="M_mbsd"/><c><![CDATA[+M<S>mbsd <depth>]]></c></tag> + <item> + <p>Maximum block search depth. This flag has effect only if the + good fit strategy is selected for allocator + <c><![CDATA[<S>]]></c>. When the good fit strategy is used, free + blocks are placed in segregated free-lists. Each free-list + contains blocks of sizes in a specific range. The maxiumum block + search depth sets a limit on the maximum number of blocks to + inspect in a free-list during a search for suitable block + satisfying the request.</p> + </item> + <tag><marker id="M_mmbcs"/><c><![CDATA[+M<S>mmbcs <size>]]></c></tag> + <item> + <p>Main multiblock carrier size. Sets the size of the main + multiblock carrier for allocator <c><![CDATA[<S>]]></c>. The main + multiblock carrier is allocated through <c><![CDATA[sys_alloc]]></c> + and is never deallocated.</p> + </item> + <tag><marker id="M_mmmbc"/><c><![CDATA[+M<S>mmmbc <amount>]]></c></tag> + <item> + <p>Maximum <c>mseg_alloc</c> multiblock carriers. Maximum number of + multiblock carriers allocated through <c>mseg_alloc</c> by + allocator <c><![CDATA[<S>]]></c>. When this limit is reached, + new multiblock carriers are allocated through + <c>sys_alloc</c>.</p> + </item> + <tag><marker id="M_mmsbc"/><c><![CDATA[+M<S>mmsbc <amount>]]></c></tag> + <item> + <p>Maximum <c>mseg_alloc</c> singleblock carriers. Maximum number of + singleblock carriers allocated through <c>mseg_alloc</c> by + allocator <c><![CDATA[<S>]]></c>. When this limit is reached, + new singleblock carriers are allocated through + <c>sys_alloc</c>.</p> + </item> + <tag><marker id="M_ramv"/><c><![CDATA[+M<S>ramv <bool>]]></c></tag> + <item> + <p>Realloc always moves. When enabled, reallocate operations are + more or less translated into an allocate, copy, free sequence. + This often reduces memory fragmentation, but costs performance.</p> + </item> + <tag><marker id="M_rmbcmt"/><c><![CDATA[+M<S>rmbcmt <ratio>]]></c></tag> + <item> + <p>Relative multiblock carrier move threshold (in percent). When + a block located in a multiblock carrier is shrunk, + the block is moved if the ratio of the size of the returned + memory compared to the previous size is more than this threshold, + otherwise the block is shrunk at the current location.</p> + </item> + <tag><marker id="M_rsbcmt"/><c><![CDATA[+M<S>rsbcmt <ratio>]]></c></tag> + <item> + <p>Relative singleblock carrier move threshold (in percent). When + a block located in a singleblock carrier is shrunk to + a size smaller than the value of parameter + <seealso marker="#M_sbct"><c>sbct</c></seealso>, + the block is left unchanged in the singleblock carrier if + the ratio of unused memory is less than this threshold, + otherwise it is moved into a multiblock carrier.</p> + </item> + <tag><marker id="M_rsbcst"/><c><![CDATA[+M<S>rsbcst <ratio>]]></c></tag> + <item> + <p>Relative singleblock carrier shrink threshold (in + percent). When a block located in an <c>mseg_alloc</c> + singleblock carrier is shrunk, the carrier is left + unchanged if the ratio of unused memory is less than this + threshold, otherwise the carrier is shrunk. + See also <seealso marker="#M_asbcst"><c>asbcst</c></seealso>.</p> + </item> + <tag><marker id="M_sbct"/><c><![CDATA[+M<S>sbct <size>]]></c></tag> + <item> + <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 + > 8 MB.</p> + </item> + <tag><marker id="M_smbcs"/><c><![CDATA[+M<S>smbcs <size>]]></c></tag> + <item> + <p>Smallest (<c>mseg_alloc</c>) multiblock carrier size (in + kilobytes). See the description on how sizes for <c>mseg_alloc</c> + multiblock carriers are decided in section + <seealso marker="#mseg_mbc_sizes"> + The alloc_util Framework</seealso>.</p> + </item> + <tag><marker id="M_t"/><c><![CDATA[+M<S>t true|false]]></c></tag> + <item> + <p>Multiple, thread-specific instances of the allocator. + This option has only effect on the runtime system + with SMP support. Default behavior on the runtime system with + SMP support is <c>NoSchedulers+1</c> instances. Each scheduler + uses a lock-free instance of its own and other threads use + a common instance.</p> + <p>Before ERTS 5.9 it was possible to configure + a smaller number of thread-specific instances than schedulers. + This is, however, not possible anymore.</p> + </item> + </taglist> + </section> + + <section> + <title>Flags for Configuration of alloc_util</title> + <p>All allocators based on <c>alloc_util</c> are effected.</p> + <taglist> - <tag><c>min</c></tag> + <tag><marker id="Muycs"/><c><![CDATA[+Muycs <size>]]></c></tag> <item> - Disables all allocators that can be disabled. - </item> + <p><c>sys_alloc</c> carrier size. Carriers allocated through + <c>sys_alloc</c> are allocated in sizes that are + multiples of the <c>sys_alloc</c> carrier size. This is not + true for main multiblock carriers and carriers allocated + during a memory shortage, though.</p> + </item> + <tag><marker id="Mummc"/><c><![CDATA[+Mummc <amount>]]></c></tag> + <item> + <p>Maximum <c>mseg_alloc</c> carriers. Maximum number of carriers + placed in separate memory segments. When this limit is + reached, new carriers are placed in memory retrieved from + <c>sys_alloc</c>.</p> + </item> + <tag><marker id="Musac"/><c><![CDATA[+Musac <bool>]]></c></tag> + <item> + <p>Allow <c>sys_alloc</c> carriers. Defaults to <c>true</c>. + If set to <c>false</c>, <c>sys_alloc</c> carriers are never + created by allocators using the <c>alloc_util</c> framework.</p> + </item> + </taglist> + </section> - <tag><c>max</c></tag> + <section> + <title>Special Flag for literal_alloc</title> + <taglist> + <tag><marker id="MIscs"/><c><![CDATA[+MIscs <size in MB>]]></c></tag> <item> - Enables all allocators (currently default). - </item> + <p><c>literal_alloc</c> super carrier size (in MB). The amount of + <em>virtual</em> address space reserved for literal terms in + Erlang code on 64-bit architectures. Defaults to <c>1024</c> + (that is, 1 GB), which is usually sufficient. + The flag is ignored on 32-bit architectures.</p> + </item> + </taglist> + </section> - <tag><c>r9c|r10b|r11b</c></tag> + <section> + <title>Instrumentation Flags</title> + <taglist> + <tag><c>+M<S>atags</c></tag> + <item> + <p>Adds a small tag to each allocated block that contains basic + information about what it is and who allocated it. See + <seealso marker="#M_atags"><c>+M<S>atags</c></seealso> for a + more complete description.</p> + </item> + <tag><marker id="Mit"/><c>+Mit X</c></tag> <item> - Configures all allocators as they were configured in respective - OTP release. These will eventually be removed. - </item> + <p>Reserved for future use. Do <em>not</em> use this flag.</p> + </item> + </taglist> - <tag><c>config</c></tag> + <note> + <p>When instrumentation of the emulator is enabled, the emulator + uses more memory and runs slower.</p> + </note> + </section> + + <section> + <title>Other Flags</title> + <taglist> + <tag><marker id="Mea"/><c>+Mea min|max|r9c|r10b|r11b|config</c></tag> + <item> + <p>Options:</p> + <taglist> + <tag><c>min</c></tag> + <item> + <p>Disables all allocators that can be disabled.</p> + </item> + <tag><c>max</c></tag> + <item> + <p>Enables all allocators (default).</p> + </item> + <tag><c>r9c|r10b|r11b</c></tag> + <item> + <p>Configures all allocators as they were configured in respective + Erlang/OTP release. These will eventually be removed.</p> + </item> + <tag><c>config</c></tag> + <item> + <p>Disables features that cannot be enabled while creating an + allocator configuration with + <seealso marker="runtime_tools:erts_alloc_config"> + <c>erts_alloc_config(3)</c></seealso>.</p> + <note> + <p>This option is to be used only while running + <c>erts_alloc_config(3)</c>, <em>not</em> when + using the created configuration.</p> + </note> + </item> + </taglist> + </item> + <tag><marker id="Mlpm"/><c>+Mlpm all|no</c></tag> <item> - Disables features that cannot be enabled while creating an - allocator configuration with - <seealso marker="runtime_tools:erts_alloc_config">erts_alloc_config(3)</seealso>. - Note, this option should only be used while running - <c>erts_alloc_config</c>, <em>not</em> when using the created - configuration. + <p>Lock physical memory. Defaults to <c>no</c>, that is, + no physical memory is locked. If set to <c>all</c>, all + memory mappings made by the runtime system are locked into + physical memory. If set to <c>all</c>, the runtime system fails to + start if this feature is not supported, the user has not got enough + privileges, or the user is not allowed to lock enough physical + memory. The runtime system also fails with an out of memory + condition if the user limit on the amount of locked memory is + reached.</p> </item> </taglist> - </item> - <tag><marker id="Mlpm"><c>+Mlpm all|no</c></marker></tag> - <item>Lock physical memory. The default value is <c>no</c>, i.e., - no physical memory will be locked. If set to <c>all</c>, all - memory mappings made by the runtime system, will be locked into - physical memory. If set to <c>all</c>, the runtime system will fail - to start if this feature is not supported, the user has not got enough - privileges, or the user is not allowed to lock enough physical memory. - The runtime system will also fail with an out of memory condition - if the user limit on the amount of locked memory is reached. - </item> - </taglist> - <p>Only some default values have been presented - here. - <seealso marker="erts:erlang#system_info_allocator">erlang:system_info(allocator)</seealso>, - and - <seealso marker="erts:erlang#system_info_allocator_tuple">erlang:system_info({allocator, Alloc})</seealso> - can be used in order to obtain currently used settings and current - status of the allocators.</p> + </section> + </section> + + <section> + <title>Notes</title> + <p>Only some default values have been presented here. For information + about the currently used settings and the current status of the + allocators, see + <seealso marker="erts:erlang#system_info_allocator"> + <c>erlang:system_info(allocator)</c></seealso> and + <seealso marker="erts:erlang#system_info_allocator_tuple"> + <c>erlang:system_info({allocator, Alloc})</c></seealso>.</p> + <note> - <p>Most of these flags are highly implementation dependent, and they - may be changed or removed without prior notice.</p> + <p>Most of these flags are highly implementation-dependent and + can be changed or removed without prior notice.</p> <p><c>erts_alloc</c> is not obliged to strictly use the settings that - have been passed to it (it may even ignore them).</p> + have been passed to it (it can even ignore them).</p> </note> - <p><seealso marker="runtime_tools:erts_alloc_config">erts_alloc_config(3)</seealso> - is a tool that can be used to aid creation of an + + <p>The <seealso marker="runtime_tools:erts_alloc_config"> + <c>erts_alloc_config(3)</c></seealso> + tool can be used to aid creation of an <c>erts_alloc</c> configuration that is suitable for a limited number of runtime scenarios.</p> </section> <section> - <title>SEE ALSO</title> - <p><seealso marker="runtime_tools:erts_alloc_config">erts_alloc_config(3)</seealso>, - <seealso marker="erl">erl(1)</seealso>, - <seealso marker="tools:instrument">instrument(3)</seealso>, - <seealso marker="erts:erlang">erlang(3)</seealso></p> + <title>See Also</title> + <p><seealso marker="erl"><c>erl(1)</c></seealso>, + <seealso marker="erlang"><c>erlang(3)</c></seealso>, + <seealso marker="runtime_tools:erts_alloc_config"> + <c>erts_alloc_config(3)</c></seealso>, + <seealso marker="tools:instrument"> + <c>instrument(3)</c></seealso></p> </section> </cref> diff --git a/erts/doc/src/escript.xml b/erts/doc/src/escript.xml index 9159d68f60..be1664b39f 100644 --- a/erts/doc/src/escript.xml +++ b/erts/doc/src/escript.xml @@ -4,20 +4,21 @@ <comref> <header> <copyright> - <year>2007</year><year>2014</year> + <year>2007</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -32,17 +33,40 @@ <comsummary>Erlang scripting support</comsummary> <description> <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> + 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> <func> <name>script-name script-arg1 script-arg2...</name> <name>escript escript-flags script-name script-arg1 script-arg2...</name> - <fsummary>Run a script written in Erlang</fsummary> + <fsummary>Run a script written in Erlang.</fsummary> <desc> <p><c>escript</c> runs a script written in Erlang.</p> - <p>Here follows an example.</p> + <p>Example:</p> <pre> $ <input>chmod u+x factorial</input> $ <input>cat factorial</input> @@ -72,195 +96,187 @@ factorial 5 = 120 $ <input>./factorial</input> usage: factorial integer $ <input>./factorial five</input> -usage: factorial integer - </pre> +usage: factorial integer</pre> <p>The header of the Erlang script in the example differs from - a normal Erlang module. The first line is intended to be the - interpreter line, which invokes <c>escript</c>. However if you - invoke the <c>escript</c> like this</p> + a normal Erlang module. The first line is intended to be the + interpreter line, which invokes <c>escript</c>.</p> + <p>However, if you invoke the <c>escript</c> as follows, + the contents of the first line does not matter, but it + cannot contain Erlang code as it will be ignored:</p> <pre> -$ <input>escript factorial 5</input> </pre> - <p>the contents of the first line does not matter, but it - cannot contain Erlang code as it will be ignored.</p> - <p>The second line in the example, contains an optional - directive to the <c>Emacs</c> editor which causes it to +$ <input>escript factorial 5</input></pre> + <p>The second line in the example contains an optional + directive to the <c>Emacs</c> editor, which causes it to enter the major mode for editing Erlang source files. If the - directive is present it must be located on the second + directive is present, it must be located on the second line.</p> - - <p>If there is a comment selecting the <seealso - marker="stdlib:epp#encoding">encoding</seealso> it can be + <p>If a comment selecting the <seealso + marker="stdlib:epp#encoding">encoding</seealso> exists, it can be located on the second line.</p> - - <note><p> - The encoding specified by the above mentioned comment - applies to the script itself. The encoding of the - I/O-server, however, has to be set explicitly like this: -<code>io:setopts([{encoding, unicode}])</code></p> + <note> + <p>The encoding specified by the above mentioned comment + applies to the script itself. The encoding of the + I/O-server, however, must be set explicitly as follows:</p> + <code> +io:setopts([{encoding, unicode}])</code> <p>The default encoding of the I/O-server for <c>standard_io</c> - is <c>latin1</c> - since the script runs in a non-interactive terminal - (see <seealso marker="stdlib:unicode_usage#unicode_options_summary"> - Using Unicode in Erlang</seealso>). - </p></note> - - <p>On the third line (or second line depending on the presence - of the Emacs directive), it is possible to give arguments to - the emulator, such as </p> + is <c>latin1</c>, as the script runs in a non-interactive terminal + (see section + <seealso marker="stdlib:unicode_usage#unicode_options_summary"> + Summary of Options</seealso>) in the STDLIB User's Guide.</p> + </note> + <p>On the third line (or second line depending on the presence + of the Emacs directive), arguments can be specified to + the emulator, for example:</p> <pre> %%! -smp enable -sname factorial -mnesia debug verbose</pre> <p>Such an argument line must start with <c>%%!</c> and the - rest of the line will interpreted as arguments to the emulator.</p> + remaining line is interpreted as arguments to the emulator.</p> <p>If you know the location of the <c>escript</c> executable, the first - line can directly give the path to <c>escript</c>. For instance:</p> + line can directly give the path to <c>escript</c>, for example:</p> <pre> -#!/usr/local/bin/escript </pre> - <p>As any other kind of scripts, Erlang scripts will not work on +#!/usr/local/bin/escript</pre> + <p>As any other type of scripts, Erlang scripts do not work on Unix platforms if the execution bit for the script file is not set. - (Use <c>chmod +x script-name</c> to turn on the execution bit.) - </p> - - <p>The rest of the Erlang script file may either contain - Erlang <c>source code</c>, an <c>inlined beam file</c> or an - <c>inlined archive file</c>.</p> - - <p>An Erlang script file must always contain the function - <em>main/1</em>. When the script is run, the - <c>main/1</c> function will be called with a list - of strings representing the arguments given to the script (not - changed or interpreted in any way).</p> - + (To turn on the execution bit, use <c>chmod +x script-name</c>.)</p> + <p>The remaining Erlang script file can either contain + Erlang <em>source code</em>, an <em>inlined beam file</em>, or an + <em>inlined archive file</em>.</p> + <p>An Erlang script file must always contain the <c>main/1</c> + function. When the script is run, the + <c>main/1</c> function is called with a list + of strings representing the arguments specified to the script (not + changed or interpreted in any way).</p> <p>If the <c>main/1</c> function in the script returns successfully, - the exit status for the script will be 0. If an exception is generated - during execution, a short message will be printed and the script terminated - with exit status 127.</p> - - <p>To return your own non-zero exit code, call <c>halt(ExitCode)</c>; - for instance:</p> + the exit status for the script is <c>0</c>. If an exception is + generated during execution, a short message is printed and the script + terminates with exit status <c>127</c>.</p> + <p>To return your own non-zero exit code, call <c>halt(ExitCode)</c>, + for example:</p> <pre> halt(1).</pre> - - <p>Call <seealso marker="#script_name_0">escript:script_name()</seealso> - from your to script to retrieve the pathname of the script - (the pathname is usually, but not always, absolute).</p> - + <p> + To retrieve the pathname of the script, call + <seealso marker="#script_name-0"> + <c>escript:script_name()</c> + </seealso> + from your script + (the pathname is usually, but not always, absolute).</p> <p>If the file contains source code (as in the example above), - it will be processed by the preprocessor <c>epp</c>. This - means that you for example may use pre-defined macros (such as - <c>?MODULE</c>) as well as include directives like - the <c>-include_lib</c> directive. For instance, use</p> + it is processed by the + <seealso marker="stdlib:epp"><c>epp</c></seealso> preprocessor. + This means that you, for example, can use predefined macros + (such as <c>?MODULE</c>) and include directives like + the <c>-include_lib</c> directive. For example, use</p> <pre> -include_lib("kernel/include/file.hrl").</pre> - <p>to include the record definitions for the records used by the - <c>file:read_link_info/1</c> function. You can also select - encoding by including a encoding comment here, but if there - is a valid encoding comment on the second line it takes + <p>to include the record definitions for the records used by function + <seealso marker="kernel:file#read_link_info/1"> + <c>file:read_link_info/1</c></seealso>. You can also select + encoding by including an encoding comment here, but if + a valid encoding comment exists on the second line, it takes precedence.</p> - - <p>The script will be checked for syntactic and semantic - correctness before being run. If there are warnings (such as - unused variables), they will be printed and the script will - still be run. If there are errors, they will be printed and - the script will not be run and its exit status will be - 127.</p> - + <p>The script is checked for syntactic and semantic + correctness before it is run. If there are warnings (such as + unused variables), they are printed and the script will + still be run. If there are errors, they are printed and + the script will not be run and its exit status is + <c>127</c>.</p> <p>Both the module declaration and the export declaration of the <c>main/1</c> function are optional.</p> - <p>By default, the script will be interpreted. You can force it to be compiled by including the following line somewhere - in the script file:</p><pre> + in the script file:</p> + <pre> -mode(compile).</pre> - <p>Execution of interpreted code is slower than compiled code. - If much of the execution takes place in interpreted code it - may be worthwhile to compile it, even though the compilation - itself will take a little while. It is also possible to supply - <c>native</c> instead of <c>compile</c>, this will compile the script - using the native flag, again depending on the characteristics - of the escript this could or could not be worth while.</p> - - <p>As mentioned earlier, it is possible to have a script which + If much of the execution takes place in interpreted code, it + can be worthwhile to compile it, although the compilation + itself takes a little while. Also, <c>native</c> can be supplied + instead of <c>compile</c>. This compiles the script + using the native flag and may or may not be worthwhile + depending on the escript characteristics.</p> + <p>As mentioned earlier, a script can contains precompiled <c>beam</c> code. In a precompiled - script, the interpretation of the script header is exactly - the same as in a script containing source code. That means + script, the interpretation of the script header is + the same as in a script containing source code. This means that you can make a <c>beam</c> file executable by prepending the file with the lines starting with <c>#!</c> and <c>%%!</c> mentioned above. In a precompiled script, the - function - <c>main/1</c> must be exported.</p> - - <p>As yet another option it is possible to have an entire - Erlang archive in the script. In a archive script, the - interpretation of the script header is exactly the same as - in a script containing source code. That means that you can + <c>main/1</c> function must be exported.</p> + <p>Another option is to have an entire + Erlang archive in the script. In an archive script, the + interpretation of the script header is the same as + in a script containing source code. This means that you can make an archive file executable by prepending the file with the lines starting with <c>#!</c> and <c>%%!</c> mentioned - above. In an archive script, the function <c>main/1</c> must + above. In an archive script, the <c>main/1</c> function must be exported. By default the <c>main/1</c> function in the module with the same name as the basename of the - <c>escript</c> file will be invoked. This behavior can be - overridden by setting the flag <c>-escript main Module</c> - as one of the emulator flags. The <c>Module</c> must be the - name of a module which has an exported <c>main/1</c> - function. See <seealso marker="kernel:code">code(3)</seealso> - for more information about archives and code loading.</p> - - <p>In many cases it is very convenient to have a header in - the escript, especially on Unix platforms. But the header is - in fact optional. This means that you directly can "execute" - an Erlang module, beam file or archive file without adding - any header to them. But then you have to invoke the script - like this:</p> - <pre> + <c>escript</c> file is invoked. This behavior can be + overridden by setting flag <c>-escript main Module</c> + as one of the emulator flags. <c>Module</c> must be the + name of a module that has an exported <c>main/1</c> + function. For more information about archives and code loading, see + <seealso marker="kernel:code"><c>code(3)</c></seealso>.</p> + <p>It is often very convenient to have a header in + the escript, especially on Unix platforms. However, the header + is optional, so you directly can "execute" + an Erlang module, Beam file, or archive file without adding + any header to them. But then you have to invoke the script + as follows:</p> + <pre> $ <input>escript factorial.erl 5</input> factorial 5 = 120 $ <input>escript factorial.beam 5</input> factorial 5 = 120 $ <input>escript factorial.zip 5</input> -factorial 5 = 120 -</pre> +factorial 5 = 120</pre> + <marker id="create-2"/> </desc> </func> + <func> - <name>escript:create(FileOrBin, Sections) -> ok | {ok, binary()} | {error, term()}</name> - <fsummary>Create an escript</fsummary> + <name>escript:create(FileOrBin, Sections) -> ok | {ok, binary()} | + {error, term()}</name> + <fsummary>Create an escript.</fsummary> <type> <v>FileOrBin = filename() | 'binary'</v> <v>Sections = [Header] Body | Body</v> <v>Header = shebang | {shebang, Shebang} - | comment | {comment, Comment} - | {emu_args, EmuArgs}</v> + | comment | {comment, Comment} + | {emu_args, EmuArgs}</v> <v>Shebang = string() | 'default' | 'undefined'</v> <v>Comment = string() | 'default' | 'undefined'</v> <v>EmuArgs = string() | 'undefined'</v> - <v>Body = {source, SourceCode} - | {beam, BeamCode} - | {archive, ZipArchive} - | {archive, ZipFiles, ZipOptions}</v> + <v>Body = {source, SourceCode} | {beam, BeamCode} + | {archive, ZipArchive} + | {archive, ZipFiles, ZipOptions}</v> <v>SourceCode = BeamCode = file:filename() | binary()</v> - <v>ZipArchive = <seealso marker="stdlib:zip#type-filename">zip:filename()</seealso> | binary()</v> + <v>ZipArchive = <seealso marker="stdlib:zip#type-filename"> + zip:filename()</seealso> | binary()</v> <v>ZipFiles = [ZipFile]</v> - <v>ZipFile = file:filename() | {file:filename(), binary()} | {file:filename(), binary(), file:file_info()}</v> - <v>ZipOptions = [<seealso marker="stdlib:zip#type-create_option">zip:create_option()</seealso>]</v> + <v>ZipFile = file:filename() + | {file:filename(), binary()} + | {file:filename(), binary(), file:file_info()}</v> + <v>ZipOptions = [<seealso marker="stdlib:zip#type-create_option"> + zip:create_option()</seealso>]</v> </type> <desc> - <p>The <marker id="create_2"></marker> <c>create/2</c> - function creates an escript from a list of sections. The - sections can be given in any order. An escript begins with an - optional <c>Header</c> followed by a mandatory <c>Body</c>. If - the header is present, it does always begin with a - <c>shebang</c>, possibly followed by a <c>comment</c> and - <c>emu_args</c>. The <c>shebang</c> defaults to - <c>"/usr/bin/env escript"</c>. The comment defaults to - <c>"This is an -*- erlang -*- file"</c>. The created escript - can either be returned as a binary or written to file.</p> - - <p>As an example of how the function can be used, we create an - interpreted escript which uses <c>emu_args</c> to set some emulator - flag. In this case it happens to disable the smp_support. We - do also extract the different sections from the newly created - script:</p> + <p> + Creates an escript from a list of sections. The + sections can be specified in any order. An escript begins with an + optional <c>Header</c> followed by a mandatory <c>Body</c>. If + the header is present, it does always begin with a + <c>shebang</c>, possibly followed by a <c>comment</c> and + <c>emu_args</c>. The <c>shebang</c> defaults to + <c>"/usr/bin/env escript"</c>. The <c>comment</c> defaults to + <c>"This is an -*- erlang -*- file"</c>. The created escript + can either be returned as a binary or written to file.</p> + <p>As an example of how the function can be used, we create an + interpreted escript that uses <c>emu_args</c> to set some emulator + flag. In this case, it happens to disable the <c>smp_support</c>. We + also extract the different sections from the newly created script:</p> <pre> > <input>Source = "%% Demo\nmain(_Args) ->\n io:format(erlang:system_info(smp_support)).\n".</input> "%% Demo\nmain(_Args) ->\n io:format(erlang:system_info(smp_support)).\n" @@ -279,11 +295,9 @@ ok "false" > <input>escript:extract("demo.escript", []).</input> {ok,[{shebang,default}, {comment,default}, {emu_args,"-smp disable"}, - {source,<<"%% Demo\nmain(_Args) ->\n io:format(erlang:system_info(smp_su"...>>}]} - </pre> - - <p>An escript without header can be created like this:</p> -<pre> + {source,<<"%% Demo\nmain(_Args) ->\n io:format(erlang:system_info(smp_su"...>>}]}</pre> + <p>An escript without header can be created as follows:</p> + <pre> > <input>file:write_file("demo.erl", ["%% demo.erl\n-module(demo).\n-export([main/1]).\n\n", Source]).</input> ok @@ -298,14 +312,12 @@ ok {beam,<<70,79,82,49,0,0,3,68,66,69,65,77,65,116, 111,109,0,0,0,83,0,0,0,9,...>>}]} > <input>os:cmd("escript demo.beam").</input> -"true" -</pre> - <p>Here we create an archive script containing both Erlang - code as well as beam code. Then we iterate over all files in - the archive and collect their contents and some info about - them. - </p> -<pre> +"true"</pre> + <p>Here we create an archive script containing both Erlang + code and Beam code, then we iterate over all files in + the archive and collect their contents and some information about + them:</p> + <pre> > <input>{ok, SourceCode} = file:read_file("demo.erl").</input> {ok,<<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>} > <input>escript:create("demo.escript", @@ -336,45 +348,48 @@ ok {{2010,3,2},{0,59,22}}, 54,1,0,0,0,0,0}, <<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}]}</pre> + <marker id="extract-2"/> </desc> </func> + <func> - <name>escript:extract(File, Options) -> {ok, Sections} | {error, term()}</name> - <fsummary>Parses an escript and extracts its sections</fsummary> + <name>escript:extract(File, Options) -> {ok, Sections} | + {error, term()}</name> + <fsummary>Parse an escript and extract its sections.</fsummary> <type> <v>File = filename()</v> <v>Options = [] | [compile_source]</v> <v>Sections = Headers Body</v> <v>Headers = {shebang, Shebang} - {comment, Comment} - {emu_args, EmuArgs}</v> + {comment, Comment} + {emu_args, EmuArgs}</v> <v>Shebang = string() | 'default' | 'undefined'</v> <v>Comment = string() | 'default' | 'undefined'</v> <v>EmuArgs = string() | 'undefined'</v> <v>Body = {source, SourceCode} - | {source, BeamCode} - | {beam, BeamCode} - | {archive, ZipArchive}</v> + | {source, BeamCode} + | {beam, BeamCode} + | {archive, ZipArchive}</v> <v>SourceCode = BeamCode = ZipArchive = binary()</v> </type> <desc> - <p>The <marker id="extract_2"></marker> <c>extract/2</c> - function parses an escript and extracts its sections. This is - the reverse of <c>create/2</c>.</p> - - <p>All sections are returned even if they do not exist in the - escript. If a particular section happens to have the same - value as the default value, the extracted value is set to the - atom <c>default</c>. If a section is missing, the extracted - value is set to the atom <c>undefined</c>. </p> - - <p>The <c>compile_source</c> option only affects the result if - the escript contains <c>source</c> code. In that case the - Erlang code is automatically compiled and <c>{source, - BeamCode}</c> is returned instead of <c>{source, - SourceCode}</c>.</p> - - <pre> + <p> + Parses an escript and extracts its sections. + This is the reverse of + <seealso marker="#create-2"><c>create/2</c></seealso>. + </p> + <p>All sections are returned even if they do not exist in the + escript. If a particular section happens to have the same + value as the default value, the extracted value is set to the + atom <c>default</c>. If a section is missing, the extracted + value is set to the atom <c>undefined</c>.</p> + <p>Option <c>compile_source</c> only affects the result if + the escript contains <c>source</c> code. In this case the + Erlang code is automatically compiled and <c>{source, + BeamCode}</c> is returned instead of <c>{source, + SourceCode}</c>.</p> + <p>Example:</p> + <pre> > <input>escript:create("demo.escript", [shebang, {archive, [{"demo.erl", SourceCode}, {"demo.beam", BeamCode}], []}]).</input> @@ -384,52 +399,52 @@ ok escript:extract("demo.escript", []).</input> {ok,[{{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105, 152,61,93,107,0,0,0,118,0,...>>} - {emu_args,undefined}]} - </pre> + {emu_args,undefined}]}</pre> + <marker id="script_name-0"/> </desc> </func> + <func> <name>escript:script_name() -> File</name> - <fsummary>Returns the name of an escript</fsummary> + <fsummary>Return the name of an escript.</fsummary> <type> <v>File = filename()</v> </type> <desc> - <p>The <marker id="script_name_0"></marker> - <c>script_name/0</c> function returns the name of the escript - being executed. If the function is invoked outside the context - of an escript, the behavior is undefined.</p> + <p> + Returns the name of the escript that is executed. + If the function is invoked outside the context + of an escript, the behavior is undefined.</p> </desc> </func> </funcs> <section> - <title>Options accepted by escript</title> + <title>Options Accepted By escript</title> <taglist> - <tag>-c</tag> - <item>Compile the escript regardless of the value of the mode attribute. + <tag><c>-c</c></tag> + <item>Compiles the escript regardless of the value of the mode attribute. </item> - - <tag>-d</tag> - <item>Debug the escript. Starts the debugger, loads the module - containing the <c>main/1</c> function into the debugger, sets a - breakpoint in <c>main/1</c> and invokes <c>main/1</c>. If the - module is precompiled, it must be explicitly compiled with the - <c>debug_info</c> option. + <tag><c>-d</c></tag> + <item>Debugs the escript. Starts the debugger, loads the module + containing the <c>main/1</c> function into the debugger, sets a + breakpoint in <c>main/1</c>, and invokes <c>main/1</c>. If the + module is precompiled, it must be explicitly compiled with option + <c>debug_info</c>. </item> - - <tag>-i</tag> - <item>Interpret the escript regardless of the value of the mode attribute. + <tag><c>-i</c></tag> + <item>Interprets the escript regardless of the value of the mode + attribute. + </item> + <tag><c>-s</c></tag> + <item>Performs a syntactic and semantic check of the script file. + Warnings and errors (if any) are written to the standard output, but + the script will not be run. The exit status is <c>0</c> if any errors + are found, otherwise <c>127</c>. + </item> + <tag><c>-n</c></tag> + <item>Compiles the escript using flag <c>+native</c>. </item> - - <tag>-s</tag> - <item>Only perform a syntactic and semantic check of the script file. - Warnings and errors (if any) are written to the standard output, but - the script will not be run. The exit status will be 0 if there were - no errors, and 127 otherwise.</item> - - <tag>-n</tag> - <item>Compile the escript using the +native flag.</item> </taglist> </section> </comref> diff --git a/erts/doc/src/fascicules.xml b/erts/doc/src/fascicules.xml deleted file mode 100644 index 1c371bd9c8..0000000000 --- a/erts/doc/src/fascicules.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE fascicules SYSTEM "fascicules.dtd"> - -<fascicules> - <fascicule file="part" href="part_frame.html" entry="no"> - ERTS User's Guide - </fascicule> - <fascicule file="ref_man" href="ref_man_frame.html" entry="yes"> - ERTS Reference Manual - </fascicule> - <fascicule file="part_notes" href="part_notes_frame.html" entry="no"> - Release Notes - </fascicule> - <fascicule file="" href="../../../doc/print.html" entry="no"> - Off-Print - </fascicule> -</fascicules> - diff --git a/erts/doc/src/inet_cfg.xml b/erts/doc/src/inet_cfg.xml index d40bc5f9ee..0cfcc7905d 100644 --- a/erts/doc/src/inet_cfg.xml +++ b/erts/doc/src/inet_cfg.xml @@ -4,24 +4,25 @@ <chapter> <header> <copyright> - <year>2004</year><year>2013</year> + <year>2004</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> - <title>Inet configuration</title> + <title>Inet Configuration</title> <prepared>Peter Andersson</prepared> <docno></docno> <date>2004-03-02</date> @@ -31,374 +32,341 @@ <section> <title>Introduction</title> - <p>This chapter tells you how the Erlang runtime system is configured - for IP communication. It also explains how you may configure it - for your own particular needs by means of a configuration file. - The information here is mainly intended for users with special - configuration needs or problems. There should normally be no need - for specific settings for Erlang to function properly on a correctly - IP configured platform. </p> - <p>When Erlang starts up it will read the kernel variable - <c><![CDATA[inetrc]]></c> which, if defined, should specify the location and - name of a user configuration file. Example:</p> - <p><c><![CDATA[% erl -kernel inetrc '"./cfg_files/erl_inetrc"']]></c></p> - <p>Note that the usage of a <c><![CDATA[.inetrc]]></c> file, which was - supported in earlier Erlang versions, is now obsolete.</p> - <p>A second way to specify the configuration file is to set the - environment variable <c><![CDATA[ERL_INETRC]]></c> to the full name of the file. Example (bash):</p> - <p><c><![CDATA[% export ERL_INETRC=./cfg_files/erl_inetrc]]></c></p> - <p>Note that the kernel variable <c><![CDATA[inetrc]]></c> overrides this environment variable.</p> + <p>This section describes how the Erlang runtime system is configured + for IP communication. It also explains how you can configure it + for your needs by a configuration file. + The information is primarily intended for users with special + configuration needs or problems. There is normally no need + for specific settings for Erlang to function properly on a correctly + IP-configured platform.</p> + + <p>When Erlang starts up it reads the Kernel variable + <c><![CDATA[inetrc]]></c>, which, if defined, is to specify the location + and name of a user configuration file. Example:</p> + + <code type="none"><![CDATA[ +% erl -kernel inetrc '"./cfg_files/erl_inetrc"']]></code> + + <p>Notice that the use of an <c><![CDATA[.inetrc]]></c> file, which was + supported in earlier Erlang/OTP versions, is now obsolete.</p> + + <p>A second way to specify the configuration file is to set + environment variable <c><![CDATA[ERL_INETRC]]></c> to the full name of + the file. Example (bash):</p> + + <code type="none"><![CDATA[ +% export ERL_INETRC=./cfg_files/erl_inetrc]]></code> + + <p>Notice that the Kernel variable <c><![CDATA[inetrc]]></c> + overrides this environment variable.</p> + <p>If no user configuration file is specified and Erlang is started - in non-distributed or short name distributed mode, Erlang will use - default configuration settings and a native lookup method that should - work correctly under most circumstances. Erlang - will not read any information from system inet configuration files - (like /etc/host.conf, /etc/nsswitch.conf, etc) in these modes, - except for /etc/resolv.conf and /etc/hosts that is read and monitored - for changes on Unix platforms for the internal DNS client - <seealso marker="kernel:inet_res">inet_res</seealso>.</p> + in non-distributed or short name distributed mode, Erlang uses + default configuration settings and a native lookup method that + works correctly under most circumstances. Erlang reads no + information from system <c>inet</c> configuration files (such as + <c>/etc/host.conf</c> and <c>/etc/nsswitch.conf</c>) in these modes, + except for <c>/etc/resolv.conf</c> and <c>/etc/hosts</c> that is read and + monitored for changes on Unix platforms for the internal DNS client + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso>.</p> + <p>If Erlang is started in long name distributed mode, it needs to - get the domain name from somewhere and will read system inet + get the domain name from somewhere and reads system <c>inet</c> configuration files for this information. Any hosts and resolver - information found then is also recorded, but not - used as long as Erlang is configured for native lookups. (The + information found is also recorded, but not + used as long as Erlang is configured for native lookups. The information becomes useful if the lookup method is changed to - <c><![CDATA['file']]></c> or <c><![CDATA['dns']]></c>, see below).</p> - <p>Native lookup (system calls) is always the default resolver method. This - is true for all platforms except VxWorks and OSE Delta where <c><![CDATA['file']]></c> - or <c><![CDATA['dns']]></c> is used (in that order of priority).</p> - <p>On Windows platforms, Erlang will search the system registry rather than - look for configuration files when started in long name distributed mode. </p> + <c><![CDATA['file']]></c> or <c><![CDATA['dns']]></c>, see below.</p> + + <p>Native lookup (system calls) is always the default resolver method. + This is true for all platforms, except VxWorks and OSE Delta where + <c><![CDATA['file']]></c> or <c><![CDATA['dns']]></c> is used (in that + priority order).</p> + + <p>On Windows platforms, Erlang searches the system registry rather than + looks for configuration files when started in long name distributed + mode.</p> </section> <section> <title>Configuration Data</title> <p>Erlang records the following data in a local database if found in system - inet configuration files (or system registry):</p> - <list type="bulleted"> - <item>Host names and addresses</item> + <c>inet</c> configuration files (or system registry):</p> + + <list type="bulleted"> + <item>Hostnames and host addresses</item> <item>Domain name</item> <item>Nameservers</item> <item>Search domains</item> <item>Lookup method</item> </list> - <p>This data may also be specified explicitly in the user - configuration file. The configuration file should contain lines - of configuration parameters (each terminated with a full - stop). Some parameters add data to the configuration (e.g. host + + <p>This data can also be specified explicitly in the user + configuration file. This file is to contain lines + of configuration parameters (each terminated with a full stop). + Some parameters add data to the configuration (such as host and nameserver), others overwrite any previous settings - (e.g. domain and lookup). The user configuration file is always + (such as domain and lookup). The user configuration file is always examined last in the configuration process, making it possible for the user to override any default values or previously made settings. Call <c><![CDATA[inet:get_rc()]]></c> to view the state of the - inet configuration database.</p> - <p>These are the valid configuration parameters:</p> - <p></p> + <c>inet</c> configuration database.</p> + + <p>The valid configuration parameters are as follows:</p> + <taglist> - <tag><em><c><![CDATA[{file, Format, File}.]]></c></em></tag> + <tag><c><![CDATA[{file, Format, File}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Format = atom()]]></c></p> <p><c><![CDATA[File = string()]]></c></p> - <p></p> - <p>Specify a system file that Erlang should read configuration - data from. <c><![CDATA[Format]]></c> tells the parser how the file should be - interpreted: <c><![CDATA[resolv]]></c> (Unix resolv.conf), <c><![CDATA[host_conf_freebsd]]></c> - (FreeBSD host.conf), <c><![CDATA[host_conf_bsdos]]></c> (BSDOS host.conf), - <c><![CDATA[host_conf_linux]]></c> (Linux host.conf), <c><![CDATA[nsswitch_conf]]></c> - (Unix nsswitch.conf) or <c><![CDATA[hosts]]></c> (Unix hosts). <c><![CDATA[File]]></c> should - specify the name of the file with full path.</p> - <p></p> + <p>Specify a system file that Erlang is to read configuration data from. + <c><![CDATA[Format]]></c> tells the parser how the file is to be + interpreted:</p> + <list type="bulleted"> + <item><c><![CDATA[resolv]]></c> (Unix resolv.conf)</item> + <item><c><![CDATA[host_conf_freebsd]]></c> (FreeBSD host.conf)</item> + <item><c><![CDATA[host_conf_bsdos]]></c> (BSDOS host.conf)</item> + <item><c><![CDATA[host_conf_linux]]></c> (Linux host.conf)</item> + <item><c><![CDATA[nsswitch_conf]]></c> (Unix nsswitch.conf)</item> + <item><c><![CDATA[hosts]]></c> (Unix hosts)</item> + </list> + <p><c><![CDATA[File]]></c> is to specify the filename with full + path.</p> </item> - <tag><em><c><![CDATA[{resolv_conf, File}.]]></c></em></tag> + <tag><c><![CDATA[{resolv_conf, File}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[File = string()]]></c></p> - <p></p> - <p>Specify a system file that Erlang should read resolver + <p>Specify a system file that Erlang is to read resolver configuration from for the internal DNS client - <seealso marker="kernel:inet_res">inet_res</seealso>, + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso>, and monitor for changes, even if it does not exist. The path must be absolute.</p> - <p>This may override the configuration parameters + <p>This can override the configuration parameters <c><![CDATA[nameserver]]></c> and <c><![CDATA[search]]></c> depending on the contents - of the specified file. They may also change any time in the future + of the specified file. They can also change any time in the future reflecting the file contents.</p> - <p>If the file is specified as an empty string "", - no file is read nor monitored in the future. This emulates - the old behaviour of not configuring the DNS client when + <p>If the file is specified as an empty string <c>""</c>, + no file is read or monitored in the future. This emulates + the old behavior of not configuring the DNS client when the node is started in short name distributed mode.</p> - <p>If this parameter is not specified it defaults to - <c><![CDATA[/etc/resolv.conf]]></c> unless the environment variable - <c><![CDATA[ERL_INET_ETC_DIR]]></c> is set which defines + <p>If this parameter is not specified, it defaults to + <c><![CDATA[/etc/resolv.conf]]></c> unless environment variable + <c><![CDATA[ERL_INET_ETC_DIR]]></c> is set, which defines the directory for this file to some maybe other than <c><![CDATA[/etc]]></c>.</p> - <p></p> </item> - <tag><em><c><![CDATA[{hosts_file, File}.]]></c></em></tag> + <tag><c><![CDATA[{hosts_file, File}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[File = string()]]></c></p> - <p></p> - <p>Specify a system file that Erlang should read resolver - configuration from for the internal hosts file resolver + <p>Specify a system file that Erlang is to read resolver + configuration from for the internal hosts file resolver, and monitor for changes, even if it does not exist. The path must be absolute.</p> <p>These host entries are searched after all added with <c>{file, hosts, File}</c> above or - <c>{host, IP, Aliases}</c> below when the lookup option + <c>{host, IP, Aliases}</c> below when lookup option <c>file</c> is used.</p> - <p>If the file is specified as an empty string "", - no file is read nor monitored in the future. This emulates - the old behaviour of not configuring the DNS client when + <p>If the file is specified as an empty string <c>""</c>, + no file is read or monitored in the future. This emulates + the old behavior of not configuring the DNS client when the node is started in short name distributed mode.</p> - <p>If this parameter is not specified it defaults to - <c><![CDATA[/etc/hosts]]></c> unless the environment variable - <c><![CDATA[ERL_INET_ETC_DIR]]></c> is set which defines + <p>If this parameter is not specified, it defaults to + <c><![CDATA[/etc/hosts]]></c> unless environment variable + <c><![CDATA[ERL_INET_ETC_DIR]]></c> is set, which defines the directory for this file to some maybe other than <c><![CDATA[/etc]]></c>.</p> - <p></p> </item> - <tag><em><c><![CDATA[{registry, Type}.]]></c></em></tag> + <tag><c><![CDATA[{registry, Type}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Type = atom()]]></c></p> - <p></p> - <p>Specify a system registry that Erlang should read configuration - data from. Currently, <c><![CDATA[win32]]></c> is the only valid option.</p> - <p></p> + <p>Specify a system registry that Erlang is to read configuration + data from. <c><![CDATA[win32]]></c> is the only valid option.</p> </item> - <tag><em><c><![CDATA[{host, IP, Aliases}.]]></c></em></tag> + <tag><c><![CDATA[{host, IP, Aliases}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[IP = tuple()]]></c></p> <p><c><![CDATA[Aliases = [string()]]]></c></p> - <p></p> <p>Add host entry to the hosts table.</p> - <p></p> </item> - <tag><em><c><![CDATA[{domain, Domain}.]]></c></em></tag> + <tag><c><![CDATA[{domain, Domain}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Domain = string()]]></c></p> - <p></p> <p>Set domain name.</p> - <p></p> </item> - <tag><em><c><![CDATA[{nameserver, IP [,Port]}.]]></c></em></tag> + <tag><c><![CDATA[{nameserver, IP [,Port]}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[IP = tuple()]]></c></p> <p><c><![CDATA[Port = integer()]]></c></p> - <p></p> - <p>Add address (and port, if other than default) of primary + <p>Add address (and port, if other than default) of the primary nameserver to use for - <seealso marker="kernel:inet_res">inet_res</seealso>.</p> - <p></p> + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso>. + </p> </item> - <tag><em><c><![CDATA[{alt_nameserver, IP [,Port]}.]]></c></em></tag> + <tag><c><![CDATA[{alt_nameserver, IP [,Port]}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[IP = tuple()]]></c></p> <p><c><![CDATA[Port = integer()]]></c></p> - <p></p> - <p>Add address (and port, if other than default) of secondary + <p>Add address (and port, if other than default) of the secondary nameserver for - <seealso marker="kernel:inet_res">inet_res</seealso>.</p> - <p></p> + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso>. + </p> </item> - <tag><em><c><![CDATA[{search, Domains}.]]></c></em></tag> + <tag><c><![CDATA[{search, Domains}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Domains = [string()]]]></c></p> - <p></p> <p>Add search domains for - <seealso marker="kernel:inet_res">inet_res</seealso>.</p> - <p></p> + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso>. + </p> </item> - <tag><em><c><![CDATA[{lookup, Methods}.]]></c></em></tag> + <tag><c><![CDATA[{lookup, Methods}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Methods = [atom()]]]></c></p> - <p></p> - <p>Specify lookup methods and in which order to try them. - The valid methods are: <c><![CDATA[native]]></c> (use system calls), - <c><![CDATA[file]]></c> (use host data retrieved from - system configuration files and/or - the user configuration file) or <c><![CDATA[dns]]></c> - (use the Erlang DNS client - <seealso marker="kernel:inet_res">inet_res</seealso> - for nameserver queries).</p> + <p>Specify lookup methods and in which order to try them. + The valid methods are as follows:</p> + <list type="bulleted"> + <item><c><![CDATA[native]]></c> (use system calls)</item> + <item><c><![CDATA[file]]></c> (use host data retrieved from system + configuration files and/or the user configuration file)</item> + <item><c><![CDATA[dns]]></c> (use the Erlang DNS client + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso> + for nameserver queries)</item> + </list> <p>The lookup method <c><![CDATA[string]]></c> tries to - parse the hostname as a IPv4 or IPv6 string and return + parse the hostname as an IPv4 or IPv6 string and return the resulting IP address. It is automatically tried first when <c><![CDATA[native]]></c> is <em>not</em> - in the <c><![CDATA[Methods]]></c> list. To skip it in this case + in the <c><![CDATA[Methods]]></c> list. To skip it in this case, the pseudo lookup method <c><![CDATA[nostring]]></c> can be inserted anywhere in the <c><![CDATA[Methods]]></c> list.</p> - <p></p> </item> - <tag><em><c><![CDATA[{cache_size, Size}.]]></c></em></tag> + <tag><c><![CDATA[{cache_size, Size}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Size = integer()]]></c></p> - <p></p> - <p>Set size of resolver cache. Default is 100 DNS records.</p> - <p></p> + <p>Set the resolver cache size. Defaults to 100 DNS records.</p> </item> - <tag><em><c><![CDATA[{cache_refresh, Time}.]]></c></em></tag> - <item> - <p></p> + <tag><c><![CDATA[{cache_refresh, Time}.]]></c></tag> + <item> <p><c><![CDATA[Time = integer()]]></c></p> - <p></p> - <p>Set how often (in millisec) - the resolver cache for - <seealso marker="kernel:inet_res">inet_res</seealso>. - is refreshed (i.e. expired DNS records are deleted). - Default is 1 h.</p> - <p></p> + <p>Set how often (in milliseconds) the resolver cache for + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso> + is refreshed (that is, expired DNS records are deleted). + Defaults to 1 hour.</p> </item> - <tag><em><c><![CDATA[{timeout, Time}.]]></c></em></tag> + <tag><c><![CDATA[{timeout, Time}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Time = integer()]]></c></p> - <p></p> - <p>Set the time to wait until retry (in millisec) for DNS queries + <p>Set the time to wait until retry (in milliseconds) for DNS queries made by - <seealso marker="kernel:inet_res">inet_res</seealso>. - Default is 2 sec.</p> - <p></p> + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso>. + Defaults to 2 seconds.</p> </item> - <tag><em><c><![CDATA[{retry, N}.]]></c></em></tag> + <tag><c><![CDATA[{retry, N}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[N = integer()]]></c></p> - <p></p> <p>Set the number of DNS queries - <seealso marker="kernel:inet_res">inet_res</seealso> - will try before giving up. - Default is 3.</p> - <p></p> + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso> + will try before giving up. Defaults to 3.</p> </item> - <tag><em><c><![CDATA[{inet6, Bool}.]]></c></em></tag> + <tag><c><![CDATA[{inet6, Bool}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Bool = true | false]]></c></p> - <p></p> - <p>Tells the DNS client - <seealso marker="kernel:inet_res">inet_res</seealso> - to look up IPv6 addresses. Default is false.</p> - <p></p> + <p>Tells the DNS client + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso> + to look up IPv6 addresses. Defaults to <c>false</c>.</p> </item> - <tag><em><c><![CDATA[{usevc, Bool}.]]></c></em></tag> + <tag><c><![CDATA[{usevc, Bool}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Bool = true | false]]></c></p> - <p></p> - <p>Tells the DNS client - <seealso marker="kernel:inet_res">inet_res</seealso> - to use TCP (Virtual Circuit) instead of UDP. Default is false.</p> - <p></p> + <p>Tells the DNS client + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso> + to use TCP (Virtual Circuit) instead of UDP. Defaults to + <c>false</c>.</p> </item> - <tag><em><c><![CDATA[{edns, Version}.]]></c></em></tag> + <tag><c><![CDATA[{edns, Version}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Version = false | 0]]></c></p> - <p></p> <p>Sets the EDNS version that - <seealso marker="kernel:inet_res">inet_res</seealso> - will use. The only allowed is zero. Default is false - which means to not use EDNS.</p> - <p></p> + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso> + will use. The only allowed version is zero. Defaults to <c>false</c>, + which means not to use EDNS.</p> </item> - <tag><em><c><![CDATA[{udp_payload_size, Size}.]]></c></em></tag> + <tag><c><![CDATA[{udp_payload_size, Size}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[N = integer()]]></c></p> - <p></p> <p>Sets the allowed UDP payload size - <seealso marker="kernel:inet_res">inet_res</seealso> + <seealso marker="kernel:inet_res"><c>inet_res(3)</c></seealso> will advertise in EDNS queries. Also sets the limit when the DNS query will be deemed too large for UDP - forcing a TCP query instead, which is not entirely - correct since the advertised UDP payload size of the - individual nameserver is what should be used, + forcing a TCP query instead; this is not entirely + correct, as the advertised UDP payload size of the + individual nameserver is what is to be used, but this simple strategy will do until a more intelligent - (probing, caching) algorithm need be implemented. - The default is 1280 which stems from the - standard Ethernet MTU size.</p> - <p></p> + (probing, caching) algorithm needs to be implemented. + Default to 1280, which stems from the standard Ethernet MTU size.</p> </item> - <tag><em><c><![CDATA[{udp, Module}.]]></c></em></tag> + <tag><c><![CDATA[{udp, Module}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Module = atom()]]></c></p> - <p></p> - <p>Tell Erlang to use other primitive UDP module than inet_udp.</p> - <p></p> + <p>Tell Erlang to use another primitive UDP module than + <c>inet_udp</c>.</p> </item> - <tag><em><c><![CDATA[{tcp, Module}.]]></c></em></tag> + <tag><c><![CDATA[{tcp, Module}.]]></c></tag> <item> - <p></p> <p><c><![CDATA[Module = atom()]]></c></p> - <p></p> - <p>Tell Erlang to use other primitive TCP module than inet_tcp.</p> - <p></p> + <p>Tell Erlang to use another primitive TCP module than + <c>inet_tcp</c>.</p> </item> - <tag><em><c><![CDATA[clear_hosts.]]></c></em></tag> + <tag><c><![CDATA[clear_hosts.]]></c></tag> <item> - <p></p> <p>Clear the hosts table.</p> - <p></p> </item> - <tag><em><c><![CDATA[clear_ns.]]></c></em></tag> + <tag><c><![CDATA[clear_ns.]]></c></tag> <item> - <p></p> <p>Clear the list of recorded nameservers (primary and secondary).</p> - <p></p> </item> - <tag><em><c><![CDATA[clear_search.]]></c></em></tag> + <tag><c><![CDATA[clear_search.]]></c></tag> <item> - <p></p> <p>Clear the list of search domains.</p> - <p></p> </item> </taglist> </section> <section> <title>User Configuration Example</title> - <p>Here follows a user configuration example.</p> - <p>Assume a user does not want Erlang to use the native lookup method, - but wants Erlang to read all information necessary from start and use - that for resolving names and addresses. In case lookup fails, Erlang - should request the data from a nameserver (using the Erlang + <p>Assume that a user does not want Erlang to use the native lookup method, + but wants Erlang to read all information necessary from start and use + that for resolving names and addresses. If lookup fails, Erlang + is to request the data from a nameserver (using the Erlang DNS client, set to use EDNS allowing larger responses). - The resolver configuration will be updated when - its configuration file changes, furthermore, DNS records - should never be cached. The user configuration file + The resolver configuration is updated when + its configuration file changes. Also, DNS records + are never to be cached. The user configuration file (in this example named <c><![CDATA[erl_inetrc]]></c>, stored - in directory <c><![CDATA[./cfg_files]]></c>) could then look like this + in directory <c><![CDATA[./cfg_files]]></c>) can then look as follows (Unix):</p> + <pre> - %% -- ERLANG INET CONFIGURATION FILE -- - %% read the hosts file - {file, hosts, "/etc/hosts"}. - %% add a particular host - {host, {134,138,177,105}, ["finwe"]}. - %% do not monitor the hosts file - {hosts_file, ""}. - %% read and monitor nameserver config from here - {resolv_conf, "/usr/local/etc/resolv.conf"}. - %% enable EDNS - {edns,0}. - %% disable caching - {cache_size, 0}. - %% specify lookup method - {lookup, [file, dns]}.</pre> - <p>And Erlang could, for example, be started like this:</p> - <p><c><![CDATA[% erl -sname my_node -kernel inetrc '"./cfg_files/erl_inetrc"']]></c></p> +%% -- ERLANG INET CONFIGURATION FILE -- +%% read the hosts file +{file, hosts, "/etc/hosts"}. +%% add a particular host +{host, {134,138,177,105}, ["finwe"]}. +%% do not monitor the hosts file +{hosts_file, ""}. +%% read and monitor nameserver config from here +{resolv_conf, "/usr/local/etc/resolv.conf"}. +%% enable EDNS +{edns,0}. +%% disable caching +{cache_size, 0}. +%% specify lookup method +{lookup, [file, dns]}.</pre> + + <p>And Erlang can, for example, be started as follows:</p> + + <code type="none"><![CDATA[ +% erl -sname my_node -kernel inetrc '"./cfg_files/erl_inetrc"']]></code> </section> </chapter> diff --git a/erts/doc/src/init.xml b/erts/doc/src/init.xml index 09b5493341..c14f0a558d 100644 --- a/erts/doc/src/init.xml +++ b/erts/doc/src/init.xml @@ -4,21 +4,22 @@ <erlref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + </legalnotice> <title>init</title> @@ -29,128 +30,140 @@ <file>init.xml</file> </header> <module>init</module> - <modulesummary>Coordination of System Startup</modulesummary> + <modulesummary>Coordination of system startup.</modulesummary> <description> - <p>The <c>init</c> module is pre-loaded and contains the code for - the <c>init</c> system process which coordinates the start-up of - the system. The first function evaluated at start-up is - <c>boot(BootArgs)</c>, where <c>BootArgs</c> is a list of command - line arguments supplied to the Erlang runtime system from - the local operating system. See - <seealso marker="erts:erl">erl(1)</seealso>.</p> - <p><c>init</c> reads the boot script which contains instructions on - how to initiate the system. See - <seealso marker="sasl:script">script(4)</seealso> for more - information about boot scripts.</p> + <p>This module is preloaded and contains the code for + the <c>init</c> system process that coordinates the startup of + the system. The first function evaluated at startup is + <c>boot(BootArgs)</c>, where <c>BootArgs</c> is a list of + command-line arguments supplied to the Erlang runtime system from + the local operating system; see + <seealso marker="erts:erl"><c>erl(1)</c></seealso>.</p> + + <p><c>init</c> reads the boot script, which contains instructions on + how to initiate the system. For more information about boot scripts, see + <seealso marker="sasl:script"><c>script(4)</c></seealso>.</p> + <p><c>init</c> also contains functions to restart, reboot, and stop the system.</p> </description> + <funcs> <func> <name name="boot" arity="1"/> - <fsummary>Start the Erlang runtime system</fsummary> + <fsummary>Start the Erlang runtime system.</fsummary> <desc> <p>Starts the Erlang runtime system. This function is called - when the emulator is started and coordinates system start-up.</p> - <p><c><anno>BootArgs</anno></c> are all command line arguments except - the emulator flags, that is, flags and plain arguments. See - <seealso marker="erts:erl">erl(1)</seealso>.</p> - <p><c>init</c> itself interprets some of the flags, see - <seealso marker="#flags">Command Line Flags</seealso> below. + when the emulator is started and coordinates system startup.</p> + <p><c><anno>BootArgs</anno></c> are all command-line arguments except + the emulator flags, that is, flags and plain arguments; see + <seealso marker="erts:erl"><c>erl(1)</c></seealso>.</p> + <p><c>init</c> interprets some of the flags, see section + <seealso marker="#flags">Command-Line Flags</seealso> below. The remaining flags ("user flags") and plain arguments are passed to the <c>init</c> loop and can be retrieved by calling - <c>get_arguments/0</c> and <c>get_plain_arguments/0</c>, - respectively.</p> + <seealso marker="#get_arguments/0"><c>get_arguments/0</c></seealso> + and <seealso marker="#get_plain_arguments/0"> + <c>get_plain_arguments/0</c></seealso>, respectively.</p> </desc> </func> + <func> <name name="get_argument" arity="1"/> - <fsummary>Get the values associated with a command line user flag</fsummary> + <fsummary>Get the values associated with a command-line user flag. + </fsummary> <desc> - <p>Returns all values associated with the command line user flag - <c><anno>Flag</anno></c>. If <c><anno>Flag</anno></c> is provided several times, each - <c><anno>Values</anno></c> is returned in preserved order.</p> + <p>Returns all values associated with the command-line user flag + <c><anno>Flag</anno></c>. If <c><anno>Flag</anno></c> is provided + several times, each <c><anno>Values</anno></c> is returned in + preserved order. Example:</p> <pre> % <input>erl -a b c -a d</input> ... 1> <input>init:get_argument(a).</input> {ok,[["b","c"],["d"]]}</pre> - <p>There are also a number of flags, which are defined + <p>The following flags are defined automatically and can be retrieved using this function:</p> <taglist> <tag><c>root</c></tag> <item> - <p>The installation directory of Erlang/OTP, <c>$ROOT</c>.</p> + <p>The installation directory of Erlang/OTP, <c>$ROOT</c>:</p> <pre> 2> <input>init:get_argument(root).</input> {ok,[["/usr/local/otp/releases/otp_beam_solaris8_r10b_patched"]]}</pre> </item> <tag><c>progname</c></tag> <item> - <p>The name of the program which started Erlang.</p> + <p>The name of the program which started Erlang:</p> <pre> 3> <input>init:get_argument(progname).</input> {ok,[["erl"]]}</pre> </item> <tag><c>home</c></tag> <item> - <p>The home directory.</p> + <p>The home directory:</p> <pre> 4> <input>init:get_argument(home).</input> {ok,[["/home/harry"]]}</pre> </item> </taglist> - <p>Returns <c>error</c> if there is no value associated with - <c>Flag</c>.</p> + <p>Returns <c>error</c> if no value is associated with <c>Flag</c>.</p> </desc> </func> + <func> <name name="get_arguments" arity="0"/> - <fsummary>Get all command line user flags</fsummary> + <fsummary>Get all command-line user flags.</fsummary> <desc> - <p>Returns all command line flags, as well as the system - defined flags, see <c>get_argument/1</c>.</p> + <p>Returns all command-line flags and the system-defined flags, see + <seealso marker="#get_argument/1"><c>get_argument/1</c></seealso>.</p> </desc> </func> + <func> <name name="get_plain_arguments" arity="0"/> - <fsummary>Get all non-flag command line arguments</fsummary> + <fsummary>Get all non-flag command-line arguments.</fsummary> <desc> - <p>Returns any plain command line arguments as a list of strings + <p>Returns any plain command-line arguments as a list of strings (possibly empty).</p> </desc> </func> + <func> <name name="get_status" arity="0"/> - <fsummary>Get system status information</fsummary> + <fsummary>Get system status information.</fsummary> <type name="internal_status"/> <desc> <p>The current status of the <c>init</c> process can be inspected. During system startup (initialization), <c><anno>InternalStatus</anno></c> is <c>starting</c>, and - <c><anno>ProvidedStatus</anno></c> indicates how far the boot script has - been interpreted. Each <c>{progress, Info}</c> term - interpreted in the boot script affects <c><anno>ProvidedStatus</anno></c>, - that is, <c><anno>ProvidedStatus</anno></c> gets the value of <c>Info</c>.</p> + <c><anno>ProvidedStatus</anno></c> indicates how far the boot + script has been interpreted. Each <c>{progress, Info}</c> term + interpreted in the boot script affects + <c><anno>ProvidedStatus</anno></c>, that is, + <c><anno>ProvidedStatus</anno></c> gets the value of <c>Info</c>.</p> </desc> </func> + <func> <name name="reboot" arity="0"/> - <fsummary>Take down and restart an Erlang node smoothly</fsummary> + <fsummary>Take down and restart an Erlang node smoothly.</fsummary> <desc> <p>All applications are taken down smoothly, all code is unloaded, and all ports are closed before the system - terminates. If the <c>-heart</c> command line flag was given, - the <c>heart</c> program will try to reboot the system. Refer - to <c>heart(3)</c> for more information.</p> + terminates. If command-line flag <c>-heart</c> was specified, + the <c>heart</c> program tries to reboot the system. For more + information, see + <seealso marker="kernel:heart"><c>heart(3)</c></seealso>.</p> <p>To limit the shutdown time, the time <c>init</c> is allowed - to spend taking down applications, the <c>-shutdown_time</c> - command line flag should be used.</p> + to spend taking down applications, command-line flag + <c>-shutdown_time</c> is to be used.</p> </desc> </func> + <func> <name name="restart" arity="0"/> - <fsummary>Restart the running Erlang node</fsummary> + <fsummary>Restart the running Erlang node.</fsummary> <desc> <p>The system is restarted <em>inside</em> the running Erlang node, which means that the emulator is not restarted. All @@ -159,97 +172,104 @@ the same way as initially started. The same <c>BootArgs</c> are used again.</p> <p>To limit the shutdown time, the time <c>init</c> is allowed - to spend taking down applications, the <c>-shutdown_time</c> - command line flag should be used.</p> + to spend taking down applications, command-line flag + <c>-shutdown_time</c> is to be used.</p> </desc> </func> + <func> <name name="script_id" arity="0"/> - <fsummary>Get the identity of the used boot script</fsummary> + <fsummary>Get the identity of the used boot script.</fsummary> <desc> - <p>Get the identity of the boot script used to boot the system. + <p>Gets the identity of the boot script used to boot the system. <c><anno>Id</anno></c> can be any Erlang term. In the delivered boot - scripts, <c><anno>Id</anno></c> is <c>{Name, Vsn}</c>. <c>Name</c> and - <c>Vsn</c> are strings.</p> + scripts, <c><anno>Id</anno></c> is <c>{Name, Vsn}</c>. <c>Name</c> + and <c>Vsn</c> are strings.</p> </desc> </func> + <func> <name name="stop" arity="0"/> - <fsummary>Take down an Erlang node smoothly</fsummary> + <fsummary>Take down an Erlang node smoothly.</fsummary> <desc> - <p>All applications are taken down smoothly, all code is - unloaded, and all ports are closed before the system - terminates. If the <c>-heart</c> command line flag was given, - the <c>heart</c> program is terminated before the Erlang node - terminates. Refer to <c>heart(3)</c> for more information.</p> - <p>To limit the shutdown time, the time <c>init</c> is allowed - to spend taking down applications, the <c>-shutdown_time</c> - command line flag should be used.</p> + <p>The same as + <seealso marker="#stop/1"><c>stop(0)</c></seealso>.</p> </desc> </func> + <func> <name name="stop" arity="1"/> - <fsummary>Take down an Erlang node smoothly</fsummary> + <fsummary>Take down an Erlang node smoothly.</fsummary> <desc> <p>All applications are taken down smoothly, all code is unloaded, and all ports are closed before the system - terminates by calling <c>halt(<anno>Status</anno>)</c>. If the - <c>-heart</c> command line flag was given, the <c>heart</c> - program is terminated before the Erlang node - terminates. Refer to <c>heart(3)</c> for more - information.</p> + terminates by calling <c>halt(<anno>Status</anno>)</c>. If + command-line flag <c>-heart</c> was specified, the <c>heart</c> + program is terminated before the Erlang node terminates. + For more information, see + <seealso marker="kernel:heart"><c>heart(3)</c></seealso>.</p> <p>To limit the shutdown time, the time <c>init</c> is allowed - to spend taking down applications, the <c>-shutdown_time</c> - command line flag should be used.</p> + to spend taking down applications, command-line flag + <c>-shutdown_time</c> is to be used.</p> </desc> </func> </funcs> <section> <marker id="flags"></marker> - <title>Command Line Flags</title> - <warning><p>The support for loading of code from archive files is - experimental. The sole purpose of releasing it before it is ready - is to obtain early feedback. The file format, semantics, - interfaces etc. may be changed in a future release. The - <c>-code_path_choice</c> flag is also experimental.</p></warning> + <title>Command-Line Flags</title> + <warning> + <p>The support for loading of code from archive files is + experimental. The only purpose of releasing it before it is ready + is to obtain early feedback. The file format, semantics, + interfaces, and so on, can be changed in a future release. The + <c>-code_path_choice</c> flag is also experimental.</p> + </warning> - <p>The <c>init</c> module interprets the following command line - flags:</p> + <p>The <c>init</c> module interprets the following command-line flags:</p> <taglist> <tag><c>--</c></tag> <item> <p>Everything following <c>--</c> up to the next flag is considered plain arguments and can be retrieved using - <c>get_plain_arguments/0</c>.</p> + <seealso marker="#get_plain_arguments/0"> + <c>get_plain_arguments/0</c></seealso>.</p> </item> <tag><c>-code_path_choice Choice</c></tag> <item> - <p>This flag can be set to <c>strict</c> or <c>relaxed</c>. It - controls whether each directory in the code path should be - interpreted strictly as it appears in the <c>boot script</c> or if - <c>init</c> should be more relaxed and try to find a suitable - directory if it can choose from a regular ebin directory and - an ebin directory in an archive file. This flag is particular - useful when you want to elaborate with code loading from - archives without editing the <c>boot script</c>. See <seealso - marker="sasl:script">script(4)</seealso> for more information - about interpretation of boot scripts. The flag does also have - a similar affect on how the code server works. See <seealso - marker="kernel:code">code(3)</seealso>.</p> - + <p>Can be set to <c>strict</c> or <c>relaxed</c>. It controls how each + directory in the code path is to be interpreted:</p> + <list type="bulleted"> + <item> + <p>Strictly as it appears in the <c>boot script</c>, or</p> + </item> + <item> + <p><c>init</c> is to be more relaxed and try to find a suitable + directory if it can choose from a regular <c>ebin</c> directory + and an <c>ebin</c> directory in an archive file.</p> + </item> + </list> + <p>This flag is particular + useful when you want to elaborate with code loading from + archives without editing the <c>boot script</c>. For more + information about interpretation of boot scripts, see + <seealso marker="sasl:script"><c>script(4)</c></seealso>. + The flag has also a similar effect on how the code server works; see + <seealso marker="kernel:code"><c>code(3)</c></seealso>.</p> + </item> + <tag><c>-epmd_module Module</c></tag> + <item> + <p>Specifies the module to use for registration and lookup of + node names. Defaults to <c>erl_epmd</c>.</p> </item> <tag><c>-eval Expr</c></tag> <item> - <p>Scans, parses and evaluates an arbitrary expression + <p>Scans, parses, and evaluates an arbitrary expression <c>Expr</c> during system initialization. If any of these - steps fail (syntax error, parse error or exception during - evaluation), Erlang stops with an error message. Here is an - example that seeds the random number generator:</p> - <pre> -% <input>erl -eval '{X,Y,Z}' = now(), random:seed(X,Y,Z).'</input></pre> - <p>This example uses Erlang as a hexadecimal calculator:</p> + steps fail (syntax error, parse error, or exception during + evaluation), Erlang stops with an error message. In the following + example Erlang is used as a hexadecimal calculator:</p> <pre> % <input>erl -noshell -eval 'R = 16#1F+16#A0, io:format("~.16B~n", [R])' \\</input> <input>-s erlang halt</input> @@ -259,14 +279,15 @@ BF</pre> <c>-eval</c> expressions are evaluated sequentially with <c>-s</c> and <c>-run</c> function calls (this also in the order specified). As with <c>-s</c> and <c>-run</c>, an - evaluation that does not terminate, blocks the system + evaluation that does not terminate blocks the system initialization process.</p> </item> <tag><c>-extra</c></tag> <item> <p>Everything following <c>-extra</c> is considered plain arguments and can be retrieved using - <c>get_plain_arguments/0</c>.</p> + <seealso marker="#get_plain_arguments/0"> + <c>get_plain_arguments/0</c></seealso>.</p> </item> <tag><c>-run Mod [Func [Arg1, Arg2, ...]]</c></tag> <item> @@ -288,8 +309,8 @@ foo:bar() foo:bar(["baz", "1", "2"]).</code> <p>The functions are executed sequentially in an initialization process, which then terminates normally and passes control to - the user. This means that a <c>-run</c> call which does not - return will block further processing; to avoid this, use + the user. This means that a <c>-run</c> call that does not + return blocks further processing; to avoid this, use some variant of <c>spawn</c> in such cases.</p> </item> <tag><c>-s Mod [Func [Arg1, Arg2, ...]]</c></tag> @@ -312,11 +333,11 @@ foo:bar() foo:bar([baz, '1', '2']).</code> <p>The functions are executed sequentially in an initialization process, which then terminates normally and passes control to - the user. This means that a <c>-s</c> call which does not - return will block further processing; to avoid this, use + the user. This means that a <c>-s</c> call that does not + return blocks further processing; to avoid this, use some variant of <c>spawn</c> in such cases.</p> - <p>Due to the limited length of atoms, it is recommended that - <c>-run</c> be used instead.</p> + <p>Because of the limited length of atoms, it is recommended to + use <c>-run</c> instead.</p> </item> </taglist> </section> @@ -338,9 +359,9 @@ error</pre> </section> <section> - <title>SEE ALSO</title> - <p><seealso marker="erl_prim_loader">erl_prim_loader(3)</seealso>, - <seealso marker="kernel:heart">heart(3)</seealso></p> + <title>See Also</title> + <p><seealso marker="erl_prim_loader"><c>erl_prim_loader(3)</c></seealso>, + <seealso marker="kernel:heart"><c>heart(3)</c></seealso></p> </section> </erlref> diff --git a/erts/doc/src/introduction.xml b/erts/doc/src/introduction.xml new file mode 100644 index 0000000000..790e24f9f3 --- /dev/null +++ b/erts/doc/src/introduction.xml @@ -0,0 +1,56 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2012</year><year>2016</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + </legalnotice> + + <title>Introduction</title> + <prepared></prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>2016-05-22</date> + <rev>PA1</rev> + <file>introduction.xml</file> + </header> + <section> + <title>Scope</title> + <p>The Erlang Runtime System Application, ERTS, contains + functionality necessary to run the Erlang system.</p> + <note> + <p>By default, <c><![CDATA[ERTS]]></c> is only guaranteed to be + compatible with other Erlang/OTP components from the same release as + <c><![CDATA[ERTS]]></c> itself.</p> + <p>For information on how to communicate with Erlang/OTP components + from earlier releases, see the documentation of system flag + <seealso marker="erl#compat_rel"><c>+R</c></seealso> in <c>erl(1)</c>. + </p> + </note> + </section> + + <section> + <title>Prerequisites</title> + <p>It is assumed that the reader is familiar with the Erlang programming + language.</p> + </section> +</chapter> + diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml index 334b47d34c..48e502739a 100644 --- a/erts/doc/src/match_spec.xml +++ b/erts/doc/src/match_spec.xml @@ -4,24 +4,25 @@ <chapter> <header> <copyright> - <year>1999</year><year>2013</year> + <year>1999</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> - <title>Match specifications in Erlang</title> + <title>Match Specifications in Erlang</title> <prepared>Patrik Nyblom</prepared> <responsible></responsible> <docno></docno> @@ -31,570 +32,832 @@ <rev>PA1</rev> <file>match_spec.xml</file> </header> - <p>A "match specification" (match_spec) is an Erlang term describing a - small "program" that will try to match something (either the - parameters to a function as used in the <c><![CDATA[erlang:trace_pattern/2]]></c> - BIF, or the objects in an ETS table.). - The match_spec in many ways works like a small function in Erlang, but is - interpreted/compiled by the Erlang runtime system to something much more - efficient than calling an Erlang function. The match_spec is also + <p>A "match specification" (<c>match_spec</c>) is an Erlang term describing a + small "program" that tries to match something. It can be used + to either control tracing with + <seealso marker="erlang#trace_pattern/3">erlang:trace_pattern/3</seealso> + or to search for objects in an ETS table with for example + <seealso marker="stdlib:ets#select/2">ets:select/2</seealso>. + The match specification in many ways works like a small function in Erlang, + but is interpreted/compiled by the Erlang runtime system to something much more + efficient than calling an Erlang function. The match specification is also very limited compared to the expressiveness of real Erlang functions.</p> - <p>Match specifications are given to the BIF <c><![CDATA[erlang:trace_pattern/2]]></c> to - execute matching of function arguments as well as to define some actions - to be taken when the match succeeds (the <c><![CDATA[MatchBody]]></c> part). Match - specifications can also be used in ETS, to specify objects to be - returned from an <c><![CDATA[ets:select/2]]></c> call (or other select - calls). The semantics and restrictions differ slightly when using - match specifications for tracing and in ETS, the differences are - defined in a separate paragraph below.</p> - <p>The most notable difference between a match_spec and an Erlang fun is - of course the syntax. Match specifications are Erlang terms, not - Erlang code. A match_spec also has a somewhat strange concept of - exceptions. An exception (e.g., <c><![CDATA[badarg]]></c>) in the <c><![CDATA[MatchCondition]]></c> - part, - which resembles an Erlang guard, will generate immediate failure, - while an exception in the <c><![CDATA[MatchBody]]></c> part, which resembles the body of an - Erlang function, is implicitly caught and results in the single atom - <c><![CDATA['EXIT']]></c>. - </p> + <p>The most notable difference between a match specification and an Erlang + fun is the syntax. Match specifications are Erlang terms, not Erlang code. + Also, a match specification has a strange concept of exceptions:</p> + + <list type="bulleted"> + <item> + <p>An exception (such as <c><![CDATA[badarg]]></c>) in the + <c><![CDATA[MatchCondition]]></c> part, which resembles an Erlang guard, + generates immediate failure.</p> + </item> + <item> + <p>An exception in the <c><![CDATA[MatchBody]]></c> part, which resembles + the body of an Erlang function, is implicitly caught and results in the + single atom <c><![CDATA['EXIT']]></c>.</p> + </item> + </list> <section> <title>Grammar</title> - <p>A match_spec used in tracing can be described in this <em>informal</em> grammar:</p> + <p>A match specification used in tracing can be described in the following + <em>informal</em> grammar:</p> + <list type="bulleted"> <item>MatchExpression ::= [ MatchFunction, ... ] </item> <item>MatchFunction ::= { MatchHead, MatchConditions, MatchBody } </item> - <item>MatchHead ::= MatchVariable | <c><![CDATA['_']]></c> | [ MatchHeadPart, ... ] + <item>MatchHead ::= MatchVariable | <c><![CDATA['_']]></c> | + [ MatchHeadPart, ... ] + </item> + <item>MatchHeadPart ::= term() | MatchVariable | <c><![CDATA['_']]></c> </item> - <item>MatchHeadPart ::= term() | MatchVariable | <c><![CDATA['_']]></c></item> <item>MatchVariable ::= '$<number>' </item> - <item>MatchConditions ::= [ MatchCondition, ...] | <c><![CDATA[[]]]></c></item> - <item>MatchCondition ::= { GuardFunction } | - { GuardFunction, ConditionExpression, ... } + <item>MatchConditions ::= [ MatchCondition, ...] | <c><![CDATA[[]]]></c> + </item> + <item>MatchCondition ::= { GuardFunction } | { GuardFunction, + ConditionExpression, ... } </item> <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | - <c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | <c><![CDATA[is_list]]></c> | - <c><![CDATA[is_number]]></c> | <c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> | - <c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> | <c><![CDATA[is_binary]]></c> | - <c><![CDATA[is_function]]></c> | <c><![CDATA[is_record]]></c> | <c><![CDATA[is_seq_trace]]></c> | - <c><![CDATA['and']]></c> | <c><![CDATA['or']]></c> | <c><![CDATA['not']]></c> | <c><![CDATA['xor']]></c> | - <c><![CDATA[andalso]]></c> | <c><![CDATA[orelse]]></c></item> + <c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | + <c><![CDATA[is_list]]></c> | <c><![CDATA[is_number]]></c> | + <c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> | + <c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> | + <c><![CDATA[is_map]]></c> | <c><![CDATA[is_map_key]]></c> | + <c><![CDATA[is_binary]]></c> | <c><![CDATA[is_function]]></c> | + <c><![CDATA[is_record]]></c> | <c><![CDATA[is_seq_trace]]></c> | + <c><![CDATA['and']]></c> | <c><![CDATA['or']]></c> | + <c><![CDATA['not']]></c> | <c><![CDATA['xor']]></c> | + <c><![CDATA['andalso']]></c> | <c><![CDATA['orelse']]></c> + </item> <item>ConditionExpression ::= ExprMatchVariable | { GuardFunction } | - { GuardFunction, ConditionExpression, ... } | TermConstruct + { GuardFunction, ConditionExpression, ... } | TermConstruct + </item> + <item>ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | + <c><![CDATA['$_']]></c> | <c><![CDATA['$$']]></c> </item> - <item>ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | - <c><![CDATA['$_']]></c> | <c><![CDATA['$$']]></c></item> - <item>TermConstruct = {{}} | {{ ConditionExpression, ... }} | - <c><![CDATA[[]]]></c> | [ConditionExpression, ...] | NonCompositeTerm | Constant + <item>TermConstruct = {{}} | {{ ConditionExpression, ... }} | + <c><![CDATA[[]]]></c> | [ConditionExpression, ...] | + <c><![CDATA[#{}]]></c> | #{term() => ConditionExpression, ...} | + NonCompositeTerm | Constant </item> - <item>NonCompositeTerm ::= term() (not list or tuple) + <item>NonCompositeTerm ::= term() (not list or tuple or map) </item> <item>Constant ::= {<c><![CDATA[const]]></c>, term()} </item> <item>GuardFunction ::= BoolFunction | <c><![CDATA[abs]]></c> | - <c><![CDATA[element]]></c> | <c><![CDATA[hd]]></c> | <c><![CDATA[length]]></c> | <c><![CDATA[node]]></c> | - <c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> | <c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> | - <c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> | <c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> | - <c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> | <c><![CDATA['bor']]></c> | <c><![CDATA['bxor']]></c> | - <c><![CDATA['bnot']]></c> | <c><![CDATA['bsl']]></c> | <c><![CDATA['bsr']]></c> | <c><![CDATA['>']]></c> | - <c><![CDATA['>=']]></c> | <c><![CDATA['<']]></c> | <c><![CDATA['=<']]></c> | <c><![CDATA['=:=']]></c> | - <c><![CDATA['==']]></c> | <c><![CDATA['=/=']]></c> | <c><![CDATA['/=']]></c> | <c><![CDATA[self]]></c> | - <c><![CDATA[get_tcw]]></c></item> + <c><![CDATA[element]]></c> | <c><![CDATA[hd]]></c> | + <c><![CDATA[length]]></c> | <c><![CDATA[map_get]]></c> | + <c><![CDATA[map_size]]></c> | <c><![CDATA[node]]></c> | + <c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> | + <c><![CDATA[bit_size]]></c> | + <c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> | + <c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> | + <c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> | + <c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> | + <c><![CDATA['bor']]></c> | <c><![CDATA['bxor']]></c> | + <c><![CDATA['bnot']]></c> | <c><![CDATA['bsl']]></c> | + <c><![CDATA['bsr']]></c> | <c><![CDATA['>']]></c> | + <c><![CDATA['>=']]></c> | <c><![CDATA['<']]></c> | + <c><![CDATA['=<']]></c> | <c><![CDATA['=:=']]></c> | + <c><![CDATA['==']]></c> | <c><![CDATA['=/=']]></c> | + <c><![CDATA['/=']]></c> | <c><![CDATA[self]]></c> | + <c><![CDATA[get_tcw]]></c> + </item> <item>MatchBody ::= [ ActionTerm ] </item> <item>ActionTerm ::= ConditionExpression | ActionCall </item> - <item>ActionCall ::= {ActionFunction} | - {ActionFunction, ActionTerm, ...} + <item>ActionCall ::= {ActionFunction} | {ActionFunction, ActionTerm, ...} </item> <item>ActionFunction ::= <c><![CDATA[set_seq_token]]></c> | - <c><![CDATA[get_seq_token]]></c> | <c><![CDATA[message]]></c> | - <c><![CDATA[return_trace]]></c> | <c><![CDATA[exception_trace]]></c> | <c><![CDATA[process_dump]]></c> | - <c><![CDATA[enable_trace]]></c> | <c><![CDATA[disable_trace]]></c> | <c><![CDATA[trace]]></c> | - <c><![CDATA[display]]></c> | <c><![CDATA[caller]]></c> | <c><![CDATA[set_tcw]]></c> | - <c><![CDATA[silent]]></c></item> + <c><![CDATA[get_seq_token]]></c> | <c><![CDATA[message]]></c> | + <c><![CDATA[return_trace]]></c> | <c><![CDATA[exception_trace]]></c> | + <c><![CDATA[process_dump]]></c> | <c><![CDATA[enable_trace]]></c> | + <c><![CDATA[disable_trace]]></c> | <c><![CDATA[trace]]></c> | + <c><![CDATA[display]]></c> | <c><![CDATA[caller]]></c> | + <c><![CDATA[set_tcw]]></c> | <c><![CDATA[silent]]></c> + </item> </list> - <p>A match_spec used in ets can be described in this <em>informal</em> grammar:</p> + <p>A match specification used in + <seealso marker="stdlib:ets"><c>ets(3)</c></seealso> + can be described in the following <em>informal</em> grammar:</p> + <list type="bulleted"> <item>MatchExpression ::= [ MatchFunction, ... ] </item> <item>MatchFunction ::= { MatchHead, MatchConditions, MatchBody } </item> - <item>MatchHead ::= MatchVariable | <c><![CDATA['_']]></c> | { MatchHeadPart, ... } + <item>MatchHead ::= MatchVariable | <c><![CDATA['_']]></c> | + { MatchHeadPart, ... } + </item> + <item>MatchHeadPart ::= term() | MatchVariable | <c><![CDATA['_']]></c> </item> - <item>MatchHeadPart ::= term() | MatchVariable | <c><![CDATA['_']]></c></item> <item>MatchVariable ::= '$<number>' </item> - <item>MatchConditions ::= [ MatchCondition, ...] | <c><![CDATA[[]]]></c></item> + <item>MatchConditions ::= [ MatchCondition, ...] | <c><![CDATA[[]]]></c> + </item> <item>MatchCondition ::= { GuardFunction } | - { GuardFunction, ConditionExpression, ... } + { GuardFunction, ConditionExpression, ... } </item> <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | - <c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | <c><![CDATA[is_list]]></c> | - <c><![CDATA[is_number]]></c> | <c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> | - <c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> | <c><![CDATA[is_binary]]></c> | - <c><![CDATA[is_function]]></c> | <c><![CDATA[is_record]]></c> | <c><![CDATA[is_seq_trace]]></c> | - <c><![CDATA['and']]></c> | <c><![CDATA['or']]></c> | <c><![CDATA['not']]></c> | <c><![CDATA['xor']]></c> | - <c><![CDATA[andalso]]></c> | <c><![CDATA[orelse]]></c></item> + <c><![CDATA[is_float]]></c> | <c><![CDATA[is_integer]]></c> | + <c><![CDATA[is_list]]></c> | <c><![CDATA[is_number]]></c> | + <c><![CDATA[is_pid]]></c> | <c><![CDATA[is_port]]></c> | + <c><![CDATA[is_reference]]></c> | <c><![CDATA[is_tuple]]></c> | + <c><![CDATA[is_map]]></c> | <c><![CDATA[map_is_key]]></c> | + <c><![CDATA[is_binary]]></c> | <c><![CDATA[is_function]]></c> | + <c><![CDATA[is_record]]></c> | <c><![CDATA['and']]></c> | + <c><![CDATA['or']]></c> | <c><![CDATA['not']]></c> | + <c><![CDATA['xor']]></c> | <c><![CDATA['andalso']]></c> | + <c><![CDATA['orelse']]></c> + </item> <item>ConditionExpression ::= ExprMatchVariable | { GuardFunction } | - { GuardFunction, ConditionExpression, ... } | TermConstruct + { GuardFunction, ConditionExpression, ... } | TermConstruct </item> <item>ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | - <c><![CDATA['$_']]></c> | <c><![CDATA['$$']]></c></item> + <c><![CDATA['$_']]></c> | <c><![CDATA['$$']]></c> + </item> <item>TermConstruct = {{}} | {{ ConditionExpression, ... }} | - <c><![CDATA[[]]]></c> | [ConditionExpression, ...] | NonCompositeTerm | Constant + <c><![CDATA[[]]]></c> | [ConditionExpression, ...] | #{} | + #{term() => ConditionExpression, ...} | NonCompositeTerm | Constant </item> - <item>NonCompositeTerm ::= term() (not list or tuple) + <item>NonCompositeTerm ::= term() (not list or tuple or map) </item> <item>Constant ::= {<c><![CDATA[const]]></c>, term()} </item> <item>GuardFunction ::= BoolFunction | <c><![CDATA[abs]]></c> | - <c><![CDATA[element]]></c> | <c><![CDATA[hd]]></c> | <c><![CDATA[length]]></c> | <c><![CDATA[node]]></c> | - <c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> | <c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> | - <c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> | <c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> | - <c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> | <c><![CDATA['bor']]></c> | <c><![CDATA['bxor']]></c> | - <c><![CDATA['bnot']]></c> | <c><![CDATA['bsl']]></c> | <c><![CDATA['bsr']]></c> | <c><![CDATA['>']]></c> | - <c><![CDATA['>=']]></c> | <c><![CDATA['<']]></c> | <c><![CDATA['=<']]></c> | <c><![CDATA['=:=']]></c> | - <c><![CDATA['==']]></c> | <c><![CDATA['=/=']]></c> | <c><![CDATA['/=']]></c> | <c><![CDATA[self]]></c> | - <c><![CDATA[get_tcw]]></c></item> - <item>MatchBody ::= [ ConditionExpression, ... ]</item> + <c><![CDATA[element]]></c> | <c><![CDATA[hd]]></c> | + <c><![CDATA[length]]></c> | <c><![CDATA[map_get]]></c> | + <c><![CDATA[map_size]]></c> | <c><![CDATA[node]]></c> | + <c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> | + <c><![CDATA[bit_size]]></c> | + <c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> | + <c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> | + <c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> | + <c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> | + <c><![CDATA['bor']]></c> | <c><![CDATA['bxor']]></c> | + <c><![CDATA['bnot']]></c> | <c><![CDATA['bsl']]></c> | + <c><![CDATA['bsr']]></c> | <c><![CDATA['>']]></c> | + <c><![CDATA['>=']]></c> | <c><![CDATA['<']]></c> | + <c><![CDATA['=<']]></c> | <c><![CDATA['=:=']]></c> | + <c><![CDATA['==']]></c> | <c><![CDATA['=/=']]></c> | + <c><![CDATA['/=']]></c> | <c><![CDATA[self]]></c> + </item> + <item>MatchBody ::= [ ConditionExpression, ... ] + </item> </list> </section> <section> - <title>Function descriptions</title> - + <title>Function Descriptions</title> <section> - <title>Functions allowed in all types of match specifications</title> - <p>The different functions allowed in <c><![CDATA[match_spec]]></c> work like this: - </p> - <p><em>is_atom, is_float, is_integer, is_list, is_number, is_pid, is_port, is_reference, is_tuple, is_binary, is_function: </em> Like the corresponding guard tests in - Erlang, return <c><![CDATA[true]]></c> or <c><![CDATA[false]]></c>. - </p> - <p><em>is_record: </em>Takes an additional parameter, which SHALL - be the result of <c><![CDATA[record_info(size, <record_type>)]]></c>, - like in <c><![CDATA[{is_record, '$1', rectype, record_info(size, rectype)}]]></c>. - </p> - <p><em>'not': </em>Negates its single argument (anything other - than <c><![CDATA[false]]></c> gives <c><![CDATA[false]]></c>). - </p> - <p><em>'and': </em>Returns <c><![CDATA[true]]></c> if all its arguments - (variable length argument list) evaluate to <c><![CDATA[true]]></c>, else - <c><![CDATA[false]]></c>. Evaluation order is undefined. - </p> - <p><em>'or': </em>Returns <c><![CDATA[true]]></c> if any of its arguments - evaluates to <c><![CDATA[true]]></c>. Variable length argument - list. Evaluation order is undefined. - </p> - <p><em>andalso: </em>Like <c><![CDATA['and']]></c>, but quits evaluating its - arguments as soon as one argument evaluates to something else - than true. Arguments are evaluated left to right. - </p> - <p><em>orelse: </em>Like <c><![CDATA['or']]></c>, but quits evaluating as soon - as one of its arguments evaluates to <c><![CDATA[true]]></c>. Arguments are - evaluated left to right. - </p> - <p><em>'xor': </em>Only two arguments, of which one has to be true - and the other false to return <c><![CDATA[true]]></c>; otherwise - <c><![CDATA['xor']]></c> returns false. - </p> - <p><em>abs, element, hd, length, node, round, size, tl, trunc, '+', '-', '*', 'div', 'rem', 'band', 'bor', 'bxor', 'bnot', 'bsl', 'bsr', '>', '>=', '<', '=<', '=:=', '==', '=/=', '/=', self: </em>Work as the corresponding Erlang bif's (or - operators). In case of bad arguments, the result depends on - the context. In the <c><![CDATA[MatchConditions]]></c> part of the - expression, the test fails immediately (like in an Erlang - guard), but in the <c><![CDATA[MatchBody]]></c>, exceptions are implicitly - caught and the call results in the atom <c><![CDATA['EXIT']]></c>.</p> + <title>Functions Allowed in All Types of Match Specifications</title> + <p>The functions allowed in <c><![CDATA[match_spec]]></c> work as + follows:</p> + + <taglist> + <tag><c>is_atom</c>, <c>is_float</c>, <c>is_integer</c>, <c>is_list</c>, + <c>is_number</c>, <c>is_pid</c>, <c>is_port</c>, <c>is_reference</c>, + <c>is_tuple</c>, <c>is_map</c>, <c>is_binary</c>, <c>is_function</c> + </tag> + <item> + <p>Same as the corresponding guard tests in Erlang, return + <c><![CDATA[true]]></c> or <c><![CDATA[false]]></c>.</p> + </item> + <tag><c>is_record</c></tag> + <item> + <p>Takes an additional parameter, which <em>must</em> be the result + of <c><![CDATA[record_info(size, <record_type>)]]></c>, like in + <c><![CDATA[{is_record, '$1', rectype, record_info(size, + rectype)}]]></c>.</p> + </item> + <tag><c>'not'</c></tag> + <item> + <p>Negates its single argument (anything other + than <c><![CDATA[false]]></c> gives <c><![CDATA[false]]></c>).</p> + </item> + <tag><c>'and'</c></tag> + <item> + <p>Returns <c><![CDATA[true]]></c> if all its arguments (variable + length argument list) evaluate to <c><![CDATA[true]]></c>, otherwise + <c><![CDATA[false]]></c>. Evaluation order is undefined.</p> + </item> + <tag><c>'or'</c></tag> + <item> + <p>Returns <c><![CDATA[true]]></c> if any of its arguments + evaluates to <c><![CDATA[true]]></c>. Variable length argument + list. Evaluation order is undefined.</p> + </item> + <tag><c>'andalso'</c></tag> + <item> + <p>Works as <c><![CDATA['and']]></c>, but quits evaluating its + arguments when one argument evaluates to something else + than <c>true</c>. Arguments are evaluated left to right.</p> + </item> + <tag><c>'orelse'</c></tag> + <item> + <p>Works as <c><![CDATA['or']]></c>, but quits evaluating as soon + as one of its arguments evaluates to <c><![CDATA[true]]></c>. + Arguments are evaluated left to right.</p> + </item> + <tag><c>'xor'</c></tag> + <item> + <p>Only two arguments, of which one must be <c>true</c> and the + other <c>false</c> to return <c><![CDATA[true]]></c>; otherwise + <c><![CDATA['xor']]></c> returns false.</p> + </item> + <tag><c>abs</c>, <c>element</c>, <c>hd</c>, <c>length</c>, + <c>map_get</c>, <c>map_size</c>, <c>node</c>, <c>round</c>, + <c>size</c>, <c>bit_size</c>, <c>tl</c>, <c>trunc</c>, <c>'+'</c>, + <c>'-'</c>, <c>'*'</c>, <c>'div'</c>, <c>'rem'</c>, <c>'band'</c>, + <c>'bor'</c>, <c>'bxor'</c>, <c>'bnot'</c>, <c>'bsl'</c>, + <c>'bsr'</c>, <c>'>'</c>, <c>'>='</c>, <c>'<'</c>, <c>'=<'</c>, + <c>'=:='</c>, <c>'=='</c>, <c>'=/='</c>, <c>'/='</c>, + <c>self</c></tag> + <item> + <p>Same as the corresponding Erlang BIFs (or operators). In case of + bad arguments, the result depends on the context. In the + <c><![CDATA[MatchConditions]]></c> part of the expression, the test + fails immediately (like in an Erlang guard). In the + <c><![CDATA[MatchBody]]></c> part, exceptions are implicitly caught + and the call results in the atom <c><![CDATA['EXIT']]></c>.</p> + </item> + </taglist> </section> <section> - <title>Functions allowed only for tracing</title> - <p><em>is_seq_trace: </em>Returns <c><![CDATA[true]]></c> if a sequential - trace token is set for the current process, otherwise <c><![CDATA[false]]></c>. - </p> - <p><em>set_seq_token:</em> Works like - <c><![CDATA[seq_trace:set_token/2]]></c>, but returns <c><![CDATA[true]]></c> on success - and <c><![CDATA['EXIT']]></c> on error or bad argument. Only allowed in the - <c><![CDATA[MatchBody]]></c> part and only allowed when tracing. - </p> - <p><em>get_seq_token:</em> Works just like - <c><![CDATA[seq_trace:get_token/0]]></c>, and is only allowed in the - <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p><em>message:</em> Sets an additional message appended to the - trace message sent. One can only set one additional message in - the body; subsequent calls will replace the appended message. As - a special case, <c><![CDATA[{message, false}]]></c> disables sending of - trace messages ('call' and 'return_to') - for this function call, just like if the match_spec had not matched, - which can be useful if only the side effects of - the <c><![CDATA[MatchBody]]></c> are desired. - Another special case is <c><![CDATA[{message, true}]]></c> which - sets the default behavior, as if the function had no match_spec, - trace message is sent with no extra - information (if no other calls to <c><![CDATA[message]]></c> are placed - before <c><![CDATA[{message, true}]]></c>, it is in fact a "noop"). - </p> - <p>Takes one argument, the message. Returns <c><![CDATA[true]]></c> and can - only be used in the <c><![CDATA[MatchBody]]></c> part and when tracing. - </p> - <p><em>return_trace:</em> Causes a <c><![CDATA[return_from]]></c> trace - message to be sent upon return from the current function. - Takes no arguments, returns <c><![CDATA[true]]></c> and can only be used - in the <c><![CDATA[MatchBody]]></c> part when tracing. - If the process trace flag <c><![CDATA[silent]]></c> - is active the <c><![CDATA[return_from]]></c> trace message is inhibited. - </p> - <p>NOTE! If the traced function is tail recursive, this match - spec function destroys that property. - Hence, if a match spec executing this function is used on a - perpetual server process, it may only be active for a limited - time, or the emulator will eventually use all memory in the host - machine and crash. If this match_spec function is inhibited - using the <c><![CDATA[silent]]></c> process trace flag - tail recursiveness still remains. - </p> - <p><em>exception_trace:</em> Same as <em>return_trace</em>, - plus; if the traced function exits due to an exception, - an <c><![CDATA[exception_from]]></c> trace message is generated, - whether the exception is caught or not. - </p> - <p><em>process_dump:</em> Returns some textual information about - the current process as a binary. Takes no arguments and is only - allowed in the <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p><em>enable_trace:</em> With one parameter this function turns - on tracing like the Erlang call <c><![CDATA[erlang:trace(self(), true, [P2])]]></c>, where <c><![CDATA[P2]]></c> is the parameter to - <c><![CDATA[enable_trace]]></c>. With two parameters, the first parameter - should be either a process identifier or the registered name of - a process. In this case tracing is turned on for the designated - process in the same way as in the Erlang call <c><![CDATA[erlang:trace(P1, true, [P2])]]></c>, where P1 is the first and P2 is the second - argument. The process <c><![CDATA[P1]]></c> gets its trace messages sent to the same - tracer as the process executing the statement uses. <c><![CDATA[P1]]></c> - can <em>not</em> be one of the atoms <c><![CDATA[all]]></c>, <c><![CDATA[new]]></c> or - <c><![CDATA[existing]]></c> (unless, of course, they are registered names). - <c><![CDATA[P2]]></c> can <em>not</em> be <c><![CDATA[cpu_timestamp]]></c> nor - <c><![CDATA[{tracer,_}]]></c>. - Returns <c><![CDATA[true]]></c> and may only be used in - the <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p><em>disable_trace:</em> With one parameter this function - disables tracing like the Erlang call <c><![CDATA[erlang:trace(self(), false, [P2])]]></c>, where <c><![CDATA[P2]]></c> is the parameter to - <c><![CDATA[disable_trace]]></c>. With two parameters it works like the - Erlang call <c><![CDATA[erlang:trace(P1, false, [P2])]]></c>, where P1 can - be either a process identifier or a registered name and is given - as the first argument to the match_spec function. - <c><![CDATA[P2]]></c> can <em>not</em> be <c><![CDATA[cpu_timestamp]]></c> nor - <c><![CDATA[{tracer,_}]]></c>. Returns - <c><![CDATA[true]]></c> and may only be used in the <c><![CDATA[MatchBody]]></c> part - when tracing. - </p> - <p><em>trace:</em> With two parameters this function takes a list - of trace flags to disable as first parameter and a list - of trace flags to enable as second parameter. Logically, the - disable list is applied first, but effectively all changes - are applied atomically. The trace flags - are the same as for <c><![CDATA[erlang:trace/3]]></c> not including - <c><![CDATA[cpu_timestamp]]></c> but including <c><![CDATA[{tracer,_}]]></c>. If a - tracer is specified in both lists, the tracer in the - enable list takes precedence. If no tracer is specified the - same tracer as the process executing the match spec is - used. With three parameters to this function the first is - either a process identifier or the registered name of a - process to set trace flags on, the second is the disable - list, and the third is the enable list. Returns - <c><![CDATA[true]]></c> if any trace property was changed for the - trace target process or <c><![CDATA[false]]></c> if not. It may only - be used in the <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p><em>caller:</em> - Returns the calling function as a tuple {Module, - Function, Arity} or the atom <c><![CDATA[undefined]]></c> if the calling - function cannot be determined. May only be used in the - <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p>Note that if a "technically built in function" (i.e. a - function not written in Erlang) is traced, the <c><![CDATA[caller]]></c> - function will sometimes return the atom <c><![CDATA[undefined]]></c>. The calling - Erlang function is not available during such calls. - </p> - <p><em>display:</em> For debugging purposes only; displays the - single argument as an Erlang term on stdout, which is seldom - what is wanted. Returns <c><![CDATA[true]]></c> and may only be used in the - <c><![CDATA[MatchBody]]></c> part when tracing. - </p> - <p> <marker id="get_tcw"></marker> -<em>get_tcw:</em> - Takes no argument and returns the value of the node's trace - control word. The same is done by - <c><![CDATA[erlang:system_info(trace_control_word)]]></c>. - </p> - <p>The trace control word is a 32-bit unsigned integer intended for - generic trace control. The trace control word can be tested and - set both from within trace match specifications and with BIFs. - This call is only allowed when tracing. - </p> - <p> <marker id="set_tcw"></marker> -<em>set_tcw:</em> - Takes one unsigned integer argument, sets the value of - the node's trace control word to the value of the argument - and returns the previous value. The same is done by - <c><![CDATA[erlang:system_flag(trace_control_word, Value)]]></c>. It is only - allowed to use <c><![CDATA[set_tcw]]></c> in the <c><![CDATA[MatchBody]]></c> part - when tracing. - </p> - <p><em>silent:</em> - Takes one argument. If the argument is <c><![CDATA[true]]></c>, the call - trace message mode for the current process is set to silent - for this call and all subsequent, i.e call trace messages - are inhibited even if <c><![CDATA[{message, true}]]></c> is called in the - <c><![CDATA[MatchBody]]></c> part for a traced function. - </p> - <p>This mode can also be activated with the <c><![CDATA[silent]]></c> flag - to <c><![CDATA[erlang:trace/3]]></c>. - </p> - <p>If the argument is <c><![CDATA[false]]></c>, the call trace message mode - for the current process is set to normal (non-silent) for - this call and all subsequent. - </p> - <p>If the argument is neither <c><![CDATA[true]]></c> nor <c><![CDATA[false]]></c>, - the call trace message mode is unaffected.</p> + <title>Functions Allowed Only for Tracing</title> + <p>The functions allowed only for tracing work as follows:</p> + + <taglist> + <tag><c>is_seq_trace</c></tag> + <item> + <p>Returns <c><![CDATA[true]]></c> if a sequential trace token is set + for the current process, otherwise <c><![CDATA[false]]></c>.</p> + </item> + <tag><c>set_seq_token</c></tag> + <item> + <p>Works as <c><![CDATA[seq_trace:set_token/2]]></c>, but returns + <c><![CDATA[true]]></c> on success, and <c><![CDATA['EXIT']]></c> + on error or bad argument. Only allowed in the + <c><![CDATA[MatchBody]]></c> part and only allowed when tracing.</p> + </item> + <tag><c>get_seq_token</c></tag> + <item> + <p>Same as <c><![CDATA[seq_trace:get_token/0]]></c> and only + allowed in the <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><c>message</c></tag> + <item> + <p>Sets an additional message appended to the + trace message sent. One can only set one additional message in + the body. Later calls replace the appended message.</p> + <p>As a special case, <c><![CDATA[{message, false}]]></c> disables + sending of trace messages ('call' and 'return_to') for this function + call, just like if the match specification had not matched. + This can be useful if only the side effects of + the <c><![CDATA[MatchBody]]></c> part are desired.</p> + <p>Another special case is <c><![CDATA[{message, true}]]></c>, which + sets the default behavior, as if the function had no match + specification; trace message is sent with no extra information + (if no other calls to <c><![CDATA[message]]></c> are placed before + <c><![CDATA[{message, true}]]></c>, it is in fact a "noop").</p> + <p>Takes one argument: the message. Returns <c><![CDATA[true]]></c> + and can only be used in the <c><![CDATA[MatchBody]]></c> part and + when tracing.</p> + </item> + <tag><c>return_trace</c></tag> + <item> + <p>Causes a <c><![CDATA[return_from]]></c> trace message to be sent + upon return from the current function. Takes no arguments, returns + <c><![CDATA[true]]></c> and can only be used in the + <c><![CDATA[MatchBody]]></c> part when tracing. + If the process trace flag <c><![CDATA[silent]]></c> is active, the + <c><![CDATA[return_from]]></c> trace message is inhibited.</p> + <p><em>Warning:</em> If the traced function is tail-recursive, this + match specification function destroys that property. Hence, if a + match specification executing this function is used on a + perpetual server process, it can only be active for a limited + period of time, or the emulator will eventually use all memory in + the host machine and crash. If this match specification function is + inhibited using process trace flag <c><![CDATA[silent]]></c>, + tail-recursiveness still remains.</p> + </item> + <tag><c>exception_trace</c></tag> + <item> + <p>Works as <c>return_trace</c> plus; if the traced function exits + because of an exception, + an <c><![CDATA[exception_from]]></c> trace message is generated, + regardless of the exception is caught or not.</p> + </item> + <tag><c>process_dump</c></tag> + <item> + <p>Returns some textual information about + the current process as a binary. Takes no arguments and is only + allowed in the <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><c>enable_trace</c></tag> + <item> + <p>With one parameter this function turns on tracing like the Erlang + call <c><![CDATA[erlang:trace(self(), true, [P2])]]></c>, where + <c><![CDATA[P2]]></c> is the parameter to + <c><![CDATA[enable_trace]]></c>.</p> + <p>With two parameters, the first parameter is to be either a process + identifier or the registered name of a process. In this case tracing + is turned on for the designated process in the same way as in the + Erlang call <c><![CDATA[erlang:trace(P1, true, [P2])]]></c>, where + <c>P1</c> is the first and <c>P2</c> is the second argument. The + process <c><![CDATA[P1]]></c> gets its trace messages sent to the + same tracer as the process executing the statement uses. + <c><![CDATA[P1]]></c> <em>cannot</em> be one of the atoms + <c><![CDATA[all]]></c>, <c><![CDATA[new]]></c> or + <c><![CDATA[existing]]></c> (unless they are registered names). + <c><![CDATA[P2]]></c> <em>cannot</em> be + <c><![CDATA[cpu_timestamp]]></c> or <c><![CDATA[tracer]]></c>.</p> + <p>Returns <c><![CDATA[true]]></c> and can only be used in + the <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><c>disable_trace</c></tag> + <item> + <p>With one parameter this function disables tracing like the Erlang + call <c><![CDATA[erlang:trace(self(), false, [P2])]]></c>, where + <c><![CDATA[P2]]></c> is the parameter to + <c><![CDATA[disable_trace]]></c>.</p> + <p>With two parameters this function works as the Erlang call + <c><![CDATA[erlang:trace(P1, false, [P2])]]></c>, where <c>P1</c> + can be either a process identifier or a registered name and is + specified as the first argument to the match specification function. + <c><![CDATA[P2]]></c> <em>cannot</em> be + <c><![CDATA[cpu_timestamp]]></c> or <c><![CDATA[tracer]]></c>.</p> + <p>Returns <c><![CDATA[true]]></c> and can only be used in the + <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><c>trace</c></tag> + <item> + <p>With two parameters this function takes a list + of trace flags to disable as first parameter and a list + of trace flags to enable as second parameter. Logically, the + disable list is applied first, but effectively all changes + are applied atomically. The trace flags + are the same as for <c><![CDATA[erlang:trace/3]]></c>, + not including <c><![CDATA[cpu_timestamp]]></c>, but including + <c><![CDATA[tracer]]></c>.</p> + <p>If a tracer is specified in both lists, the tracer in the + enable list takes precedence. If no tracer is specified, the same + tracer as the process executing the match specification is used (not the meta tracer). + If that process doesn't have tracer either, then trace flags are ignored.</p> + <p>When using a <seealso marker="erl_tracer">tracer module</seealso>, + the module must be loaded before the match specification is + executed. If it is not loaded, the match fails.</p> + <p>With three parameters to this function, the first is + either a process identifier or the registered name of a + process to set trace flags on, the second is the disable + list, and the third is the enable list.</p> + <p>Returns <c><![CDATA[true]]></c> if any trace property was changed + for the trace target process, otherwise <c><![CDATA[false]]></c>. + Can only be used in the <c><![CDATA[MatchBody]]></c> part when + tracing.</p> + </item> + <tag><c>caller</c></tag> + <item> + <p>Returns the calling function as a tuple <c>{Module, Function, + Arity}</c> or the atom <c><![CDATA[undefined]]></c> if the calling + function cannot be determined. Can only be used in the + <c><![CDATA[MatchBody]]></c> part when tracing.</p> + <p>Notice that if a "technically built in function" (that is, a + function not written in Erlang) is traced, the + <c><![CDATA[caller]]></c> function sometimes returns the atom + <c><![CDATA[undefined]]></c>. The calling + Erlang function is not available during such calls.</p> + </item> + <tag><c>display</c></tag> + <item> + <p>For debugging purposes only. Displays the single argument as an + Erlang term on <c>stdout</c>, which is seldom what is wanted. + Returns <c><![CDATA[true]]></c> and can only be used in the + <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><marker id="get_tcw"/><c>get_tcw</c></tag> + <item> + <p>Takes no argument and returns the value of the node's trace + control word. The same is done by + <c><![CDATA[erlang:system_info(trace_control_word)]]></c>.</p> + <p>The trace control word is a 32-bit unsigned integer intended for + generic trace control. The trace control word can be tested and + set both from within trace match specifications and with BIFs. + This call is only allowed when tracing.</p> + </item> + <tag><marker id="set_tcw"/><c>set_tcw</c></tag> + <item> + <p>Takes one unsigned integer argument, sets the value of + the node's trace control word to the value of the argument, + and returns the previous value. The same is done by + <c><![CDATA[erlang:system_flag(trace_control_word, Value)]]></c>. + It is only allowed to use <c><![CDATA[set_tcw]]></c> in the + <c><![CDATA[MatchBody]]></c> part when tracing.</p> + </item> + <tag><c>silent</c></tag> + <item> + <p>Takes one argument. If the argument is <c><![CDATA[true]]></c>, + the call trace message mode for the current process is set to + silent for this call and all later calls, that is, call trace + messages are inhibited even if + <c><![CDATA[{message, true}]]></c> is called in the + <c><![CDATA[MatchBody]]></c> part for a traced function.</p> + <p>This mode can also be activated with flag + <c><![CDATA[silent]]></c> to + <c><![CDATA[erlang:trace/3]]></c>.</p> + <p>If the argument is <c><![CDATA[false]]></c>, the call trace + message mode for the current process is set to normal + (non-silent) for this call and all later calls.</p> + <p>If the argument is not <c><![CDATA[true]]></c> or + <c><![CDATA[false]]></c>, the call trace message mode is + unaffected.</p> + </item> + </taglist> </section> - <p><em>Note</em> that all "function calls" have to be tuples, - even if they take no arguments. The value of <c><![CDATA[self]]></c> is - the atom() <c><![CDATA[self]]></c>, but the value of <c><![CDATA[{self}]]></c> is - the pid() of the current process.</p> + + <note> + <p>All "function calls" must be tuples, even if they take no arguments. + The value of <c><![CDATA[self]]></c> is the atom() + <c><![CDATA[self]]></c>, but the value of <c><![CDATA[{self}]]></c> is + the pid() of the current process.</p> + </note> + </section> + + <section> + <marker id="match_target"/> + <title>Match target</title> + <p>Each execution of a match specification is done against + a match target term. The format and content of the target term + depends on the context in which the match is done. The match + target for ETS is always a full table tuple. The match target + for call trace is always a list of all function arguments. The + match target for event trace depends on the event type, see + table below.</p> + <table> + <row> + <cell align="left" valign="middle">Context</cell> + <cell align="left" valign="middle">Type</cell> + <cell align="left" valign="middle">Match target</cell> + <cell align="left" valign="middle">Description</cell> + </row> + <row> + <cell align="left" valign="middle">ETS</cell> + <cell align="left" valign="middle"></cell> + <cell align="left" valign="middle">{Key, Value1, Value2, ...}</cell> + <cell align="left" valign="middle">A table object</cell> + </row> + <row> + <cell align="left" valign="middle">Trace</cell> + <cell align="left" valign="middle">call</cell> + <cell align="left" valign="middle">[Arg1, Arg2, ...]</cell> + <cell align="left" valign="middle">Function arguments</cell> + </row> + <row> + <cell align="left" valign="middle">Trace</cell> + <cell align="left" valign="middle">send</cell> + <cell align="left" valign="middle">[Receiver, Message]</cell> + <cell align="left" valign="middle">Receiving process/port and message term</cell> + </row> + <row> + <cell align="left" valign="middle">Trace</cell> + <cell align="left" valign="middle">'receive'</cell> + <cell align="left" valign="middle">[Node, Sender, Message]</cell> + <cell align="left" valign="middle">Sending node, process/port and message term</cell> + </row> + <tcaption>Match target depending on context</tcaption> + </table> </section> <section> - <title>Variables and literals</title> - <p>Variables take the form <c><![CDATA['$<number>']]></c> where - <c><![CDATA[<number>]]></c> is an integer between 0 (zero) and - 100000000 (1e+8), the behavior if the number is outside these - limits is <em>undefined</em>. In the <c><![CDATA[MatchHead]]></c> part, the special - variable <c><![CDATA['_']]></c> matches anything, and never gets bound (like - <c><![CDATA[_]]></c> in Erlang). In the <c><![CDATA[MatchCondition/MatchBody]]></c> - parts, no unbound variables are allowed, why <c><![CDATA['_']]></c> is - interpreted as itself (an atom). Variables can only be bound in - the <c><![CDATA[MatchHead]]></c> part. In the <c><![CDATA[MatchBody]]></c> and - <c><![CDATA[MatchCondition]]></c> parts, only variables bound previously may - be used. As a special case, in the - <c><![CDATA[MatchCondition/MatchBody]]></c> parts, the variable <c><![CDATA['$_']]></c> - expands to the whole expression which matched the - <c><![CDATA[MatchHead]]></c> (i.e., the whole parameter list to the possibly - traced function or the whole matching object in the ets table) - and the variable <c><![CDATA['$$']]></c> expands to a list - of the values of all bound variables in order - (i.e. <c><![CDATA[['$1','$2', ...]]]></c>). - </p> - <p>In the <c><![CDATA[MatchHead]]></c> part, all literals (except the variables - noted above) are interpreted as is. In the - <c><![CDATA[MatchCondition/MatchBody]]></c> parts, however, the - interpretation is in some ways different. Literals in the - <c><![CDATA[MatchCondition/MatchBody]]></c> can either be written as is, - which works for all literals except tuples, or by using the - special form <c><![CDATA[{const, T}]]></c>, where <c><![CDATA[T]]></c> is any Erlang - term. For tuple literals in the match_spec, one can also use - double tuple parentheses, i.e., construct them as a tuple of + <title>Variables and Literals</title> + <p>Variables take the form <c><![CDATA['$<number>']]></c>, where + <c><![CDATA[<number>]]></c> is an integer between 0 and + 100,000,000 (1e+8). The behavior if the number is outside these limits + is <em>undefined</em>. In the <c><![CDATA[MatchHead]]></c> part, the + special variable <c><![CDATA['_']]></c> matches anything, and never gets + bound (like <c><![CDATA[_]]></c> in Erlang).</p> + + <list type="bulleted"> + <item> + <p>In the <c><![CDATA[MatchCondition/MatchBody]]></c> parts, + no unbound variables are allowed, so <c><![CDATA['_']]></c> is + interpreted as itself (an atom). Variables can only be bound in the + <c><![CDATA[MatchHead]]></c> part.</p> + </item> + <item> + <p>In the <c><![CDATA[MatchBody]]></c> and + <c><![CDATA[MatchCondition]]></c> parts, only variables bound + previously can be used.</p> + </item> + <item> + <p>As a special case, the following apply in the + <c><![CDATA[MatchCondition/MatchBody]]></c> parts:</p> + <list type="bulleted"> + <item> + <p>The variable <c><![CDATA['$_']]></c> expands to the whole + <seealso marker="#match_target">match target</seealso> term. + </p> + </item> + <item> + <p>The variable <c><![CDATA['$$']]></c> expands to a list of the + values of all bound variables in order (that is, + <c><![CDATA[['$1','$2', ...]]]></c>).</p> + </item> + </list> + </item> + </list> + + <p>In the <c><![CDATA[MatchHead]]></c> part, all literals (except the + variables above) are interpreted "as is".</p> + + <p>In the <c><![CDATA[MatchCondition/MatchBody]]></c> parts, the + interpretation is in some ways different. Literals in these parts + can either be written "as is", which works for all literals except + tuples, or by using the special form <c><![CDATA[{const, T}]]></c>, + where <c><![CDATA[T]]></c> is any Erlang term.</p> + + <p>For tuple literals in the match specification, double tuple parentheses + can also be used, that is, construct them as a tuple of arity one containing a single tuple, which is the one to be constructed. The "double tuple parenthesis" syntax is useful to construct tuples from already bound variables, like in - <c><![CDATA[{{'$1', [a,b,'$2']}}]]></c>. Some examples may be needed: - </p> + <c><![CDATA[{{'$1', [a,b,'$2']}}]]></c>. Examples:</p> + <table> <row> - <cell align="left" valign="middle">Expression </cell> - <cell align="left" valign="middle">Variable bindings </cell> - <cell align="left" valign="middle">Result </cell> + <cell align="left" valign="middle"><em>Expression</em></cell> + <cell align="left" valign="middle"><em>Variable Bindings</em></cell> + <cell align="left" valign="middle"><em>Result</em></cell> </row> <row> - <cell align="left" valign="middle">{{'$1','$2'}} </cell> + <cell align="left" valign="middle">{{'$1','$2'}}</cell> <cell align="left" valign="middle">'$1' = a, '$2' = b</cell> <cell align="left" valign="middle">{a,b}</cell> </row> <row> - <cell align="left" valign="middle">{const, {'$1', '$2'}} </cell> - <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">{const, {'$1', '$2'}}</cell> + <cell align="left" valign="middle">Irrelevant</cell> <cell align="left" valign="middle">{'$1', '$2'}</cell> </row> <row> - <cell align="left" valign="middle">a </cell> - <cell align="left" valign="middle">doesn't matter </cell> + <cell align="left" valign="middle">a</cell> + <cell align="left" valign="middle">Irrelevant</cell> <cell align="left" valign="middle">a</cell> </row> <row> - <cell align="left" valign="middle">'$1' </cell> - <cell align="left" valign="middle">'$1' = [] </cell> + <cell align="left" valign="middle">'$1'</cell> + <cell align="left" valign="middle">'$1' = []</cell> <cell align="left" valign="middle">[]</cell> </row> <row> - <cell align="left" valign="middle">['$1'] </cell> - <cell align="left" valign="middle">'$1' = [] </cell> + <cell align="left" valign="middle">['$1']</cell> + <cell align="left" valign="middle">'$1' = []</cell> <cell align="left" valign="middle">[[]]</cell> </row> <row> - <cell align="left" valign="middle">[{{a}}] </cell> - <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">[{{a}}]</cell> + <cell align="left" valign="middle">Irrelevant</cell> <cell align="left" valign="middle">[{a}]</cell> </row> <row> - <cell align="left" valign="middle">42 </cell> - <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">42</cell> + <cell align="left" valign="middle">Irrelevant</cell> <cell align="left" valign="middle">42</cell> </row> <row> - <cell align="left" valign="middle">"hello" </cell> - <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">"hello"</cell> + <cell align="left" valign="middle">Irrelevant</cell> <cell align="left" valign="middle">"hello"</cell> </row> <row> - <cell align="left" valign="middle">$1 </cell> - <cell align="left" valign="middle">doesn't matter</cell> - <cell align="left" valign="middle">49 (the ASCII value for the character '1')</cell> + <cell align="left" valign="middle">$1</cell> + <cell align="left" valign="middle">Irrelevant</cell> + <cell align="left" valign="middle">49 (the ASCII value for + character '1')</cell> </row> - <tcaption>Literals in the MatchCondition/MatchBody parts of a match_spec</tcaption> + <tcaption>Literals in MatchCondition/MatchBody Parts of a Match + Specification</tcaption> </table> </section> <section> - <title>Execution of the match</title> + <title>Execution of the Match</title> <p>The execution of the match expression, when the runtime system - decides whether a trace message should be sent, goes as follows: - </p> - <p>For each tuple in the <c><![CDATA[MatchExpression]]></c> list and while no - match has succeeded:</p> - <list type="bulleted"> - <item>Match the <c><![CDATA[MatchHead]]></c> part against the arguments to the - function, - binding the <c><![CDATA['$<number>']]></c> variables (much like in - <c><![CDATA[ets:match/2]]></c>). - If the <c><![CDATA[MatchHead]]></c> cannot match the arguments, the match fails. - </item> - <item>Evaluate each <c><![CDATA[MatchCondition]]></c> (where only - <c><![CDATA['$<number>']]></c> variables previously bound in the - <c><![CDATA[MatchHead]]></c> can occur) and expect it to return the atom - <c><![CDATA[true]]></c>. As soon as a condition does not evaluate to - <c><![CDATA[true]]></c>, the match fails. If any BIF call generates an - exception, also fail. + decides whether a trace message is to be sent, is as follows:</p> + + <p>For each tuple in the <c><![CDATA[MatchExpression]]></c> list and while + no match has succeeded:</p> + + <list type="ordered"> + <item> + <p>Match the <c><![CDATA[MatchHead]]></c> part against the match target + term, binding the <c><![CDATA['$<number>']]></c> variables + (much like in <c><![CDATA[ets:match/2]]></c>). If the + <c><![CDATA[MatchHead]]></c> part cannot match the arguments, the + match fails.</p> + </item> + <item> + <p>Evaluate each <c><![CDATA[MatchCondition]]></c> (where only + <c><![CDATA['$<number>']]></c> variables previously bound in the + <c><![CDATA[MatchHead]]></c> part can occur) and expect it to return + the atom <c><![CDATA[true]]></c>. When a condition does not evaluate + to <c><![CDATA[true]]></c>, the match fails. If any BIF call + generates an exception, the match also fails.</p> </item> <item> + <p>Two cases can occur:</p> <list type="bulleted"> - <item><em>If the match_spec is executing when tracing:</em><br></br> - Evaluate each <c><![CDATA[ActionTerm]]></c> in the same way as the - <c><![CDATA[MatchConditions]]></c>, but completely ignore the return - values. Regardless of what happens in this part, the match has - succeeded.</item> - <item><em>If the match_spec is executed when selecting objects from an ETS table:</em><br></br> - Evaluate the expressions in order and return the value of - the last expression (typically there is only one expression - in this context)</item> + <item> + <p>If the match specification is executing when tracing:</p> + <p>Evaluate each <c><![CDATA[ActionTerm]]></c> in the same way as + the <c><![CDATA[MatchConditions]]></c>, but ignore the return + values. Regardless of what happens in this part, the match has + succeeded.</p> + </item> + <item> + <p>If the match specification is executed when selecting objects + from an ETS table:</p> + <p>Evaluate the expressions in order and return the value of + the last expression (typically there is only one expression + in this context).</p> + </item> </list> </item> </list> </section> <section> - <title>Differences between match specifications in ETS and tracing</title> - <p>ETS match specifications are there to produce a return - value. Usually the <c><![CDATA[MatchBody]]></c> contains one single - <c><![CDATA[ConditionExpression]]></c> which defines the return value without having - any side effects. Calls with side effects are not allowed in the - ETS context.</p> + <marker id="differences_ets_tracing"/> + <title>Differences between Match Specifications in ETS and Tracing</title> + <p>ETS match specifications produce a return value. + Usually the <c><![CDATA[MatchBody]]></c> contains one single + <c><![CDATA[ConditionExpression]]></c> that defines the return value + without any side effects. Calls with side effects are not allowed in + the ETS context.</p> + <p>When tracing there is no return value to produce, the - match specification either matches or doesn't. The effect when the - expression matches is a trace message rather then a returned - term. The <c><![CDATA[ActionTerm]]></c>'s are executed as in an imperative - language, i.e. for their side effects. Functions with side effects + match specification either matches or does not. The effect when the + expression matches is a trace message rather than a returned + term. The <c><![CDATA[ActionTerm]]></c>s are executed as in an imperative + language, that is, for their side effects. Functions with side effects are also allowed when tracing.</p> - <p>In ETS the match head is a <c><![CDATA[tuple()]]></c> (or a single match - variable) while it is a list (or a single match variable) when - tracing.</p> </section> <section> - <title>Examples</title> - <p>Match an argument list of three where the first and third arguments + <title>Tracing Examples</title> + <p>Match an argument list of three, where the first and third arguments are equal:</p> + <code type="none"><![CDATA[ [{['$1', '_', '$1'], [], []}] ]]></code> - <p>Match an argument list of three where the second argument is - a number greater than three:</p> + + <p>Match an argument list of three, where the second argument is + a number > 3:</p> + <code type="none"><![CDATA[ [{['_', '$1', '_'], [{ '>', '$1', 3}], []}] ]]></code> - <p>Match an argument list of three, where the third argument - is a tuple containing argument one and two <em>or</em> a list - beginning with argument one and two (i. e. <c><![CDATA[[a,b,[a,b,c]]]]></c> or - <c><![CDATA[[a,b,{a,b}]]]></c>): - </p> + + <p>Match an argument list of three, where the third argument is + either a tuple containing argument one and two, <em>or</em> a list + beginning with argument one and two (that is, + <c><![CDATA[[a,b,[a,b,c]]]]></c> or <c><![CDATA[[a,b,{a,b}]]]></c>):</p> + <code type="none"><![CDATA[ [{['$1', '$2', '$3'], - [{orelse, + [{'orelse', {'=:=', '$3', {{'$1','$2'}}}, {'and', {'=:=', '$1', {hd, '$3'}}, {'=:=', '$2', {hd, {tl, '$3'}}}}}], []}] ]]></code> - <p>The above problem may also be solved like this:</p> + + <p>The above problem can also be solved as follows:</p> + <code type="none"><![CDATA[ [{['$1', '$2', {'$1', '$2}], [], []}, {['$1', '$2', ['$1', '$2' | '_']], [], []}] ]]></code> - <p>Match two arguments where the first is a tuple beginning with - a list which in turn begins with the second argument times - two (i. e. [{[4,x],y},2] or [{[8], y, z},4])</p> + + <p>Match two arguments, where the first is a tuple beginning with + a list that in turn begins with the second argument times + two (that is, <c>[{[4,x],y},2]</c> or <c>[{[8], y, z},4])</c>:</p> + <code type="none"><![CDATA[ [{['$1', '$2'],[{'=:=', {'*', 2, '$2'}, {hd, {element, 1, '$1'}}}], []}] ]]></code> + <p>Match three arguments. When all three are equal and are - numbers, append the process dump to the trace message, else - let the trace message be as is, but set the sequential trace - token label to 4711.</p> + numbers, append the process dump to the trace message, otherwise + let the trace message be "as is", but set the sequential trace + token label to 4711:</p> + <code type="none"><![CDATA[ [{['$1', '$1', '$1'], [{is_number, '$1'}], [{message, {process_dump}}]}, {'_', [], [{set_seq_token, label, 4711}]}] ]]></code> - <p>As can be noted above, the parameter list can be matched - against a single <c><![CDATA[MatchVariable]]></c> or an <c><![CDATA['_']]></c>. To replace the - whole - parameter list with a single variable is a special case. In all - other cases the <c><![CDATA[MatchHead]]></c> has to be a <em>proper</em> list. - </p> - <p>Match all objects in an ets table where the first element is - the atom 'strider' and the tuple arity is 3 and return the whole - object.</p> + + <p>As can be noted above, the parameter list can be matched against a + single <c><![CDATA[MatchVariable]]></c> or an <c><![CDATA['_']]></c>. + To replace the whole parameter list with a single variable is a special + case. In all other cases the <c><![CDATA[MatchHead]]></c> must be a + <em>proper</em> list.</p> + + <p>Generate a trace message only if the trace control word is set to 1:</p> + + <code type="none"><![CDATA[ +[{'_', + [{'==',{get_tcw},{const, 1}}], + []}] + ]]></code> + + <p>Generate a trace message only if there is a <c>seq_trace</c> token:</p> + + <code type="none"><![CDATA[ +[{'_', + [{'==',{is_seq_trace},{const, 1}}], + []}] + ]]></code> + + <p>Remove the <c>'silent'</c> trace flag when the first argument is + <c>'verbose'</c>, and add it when it is <c>'silent':</c></p> + + <code type="none"><![CDATA[ +[{'$1', + [{'==',{hd, '$1'},verbose}], + [{trace, [silent],[]}]}, + {'$1', + [{'==',{hd, '$1'},silent}], + [{trace, [],[silent]}]}] + ]]></code> + + <p>Add a <c>return_trace</c> message if the function is of arity 3:</p> + + <code type="none"><![CDATA[ +[{'$1', + [{'==',{length, '$1'},3}], + [{return_trace}]}, + {'_',[],[]}] + ]]></code> + + <p>Generate a trace message only if the function is of arity 3 and the + first argument is <c>'trace'</c>:</p> + + <code type="none"><![CDATA[ +[{['trace','$2','$3'], + [], + []}, + {'_',[],[]}] + ]]></code> + </section> + + <section> + <title>ETS Examples</title> + <p>Match all objects in an ETS table, where the first element is + the atom <c>'strider'</c> and the tuple arity is 3, and return the whole + object:</p> + <code type="none"><![CDATA[ [{{strider,'_','_'}, [], ['$_']}] ]]></code> - <p>Match all objects in an ets table with arity > 1 and the first - element is 'gandalf', return element 2.</p> + + <p>Match all objects in an ETS table with arity > 1 and the first + element is 'gandalf', and return element 2:</p> + <code type="none"><![CDATA[ [{'$1', [{'==', gandalf, {element, 1, '$1'}},{'>=',{size, '$1'},2}], [{element,2,'$1'}]}] ]]></code> - <p>In the above example, if the first element had been the key, - it's much more efficient to match that key in the <c><![CDATA[MatchHead]]></c> - part than in the <c><![CDATA[MatchConditions]]></c> part. The search space of - the tables is restricted with regards to the <c><![CDATA[MatchHead]]></c> so - that only objects with the matching key are searched. - </p> - <p>Match tuples of 3 elements where the second element is either - 'merry' or 'pippin', return the whole objects.</p> + + <p>In this example, if the first element had been the key, it is + much more efficient to match that key in the <c><![CDATA[MatchHead]]></c> + part than in the <c><![CDATA[MatchConditions]]></c> part. + The search space of the tables is restricted with regards to the + <c><![CDATA[MatchHead]]></c> so + that only objects with the matching key are searched.</p> + + <p>Match tuples of three elements, where the second element is either + <c>'merry'</c> or <c>'pippin'</c>, and return the whole objects:</p> + <code type="none"><![CDATA[ [{{'_',merry,'_'}, [], @@ -603,8 +866,8 @@ [], ['$_']}] ]]></code> - <p>The function <c><![CDATA[ets:test_ms/2]]></c> can be useful for testing - complicated ets matches.</p> + + <p>Function <seealso marker="stdlib:ets#test_ms/2"><c>ets:test_ms/2></c></seealso> + can be useful for testing complicated ETS matches.</p> </section> </chapter> - diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index f906019b14..775fed7faf 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -4,20 +4,21 @@ <chapter> <header> <copyright> - <year>2004</year><year>2013</year> + <year>2004</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -30,22 +31,3723 @@ </header> <p>This document describes the changes made to the ERTS application.</p> -<section><title>Erts 6.4.1.7</title> +<section><title>Erts 10.1</title> <section><title>Fixed Bugs and Malfunctions</title> <list> <item> <p> - A process communicating with a port via one of the - <c>erlang:port_*</c> BIFs could potentially end up in an - inconsistent state if the port terminated during the - communication. When this occurred the process could later - block in a <c>receive</c> even though it had messages - matching in its message queue.</p> + Fix the seq_trace token to not be cleared when a process + receives messages sent by erts. Some examples of when + this could happen is all port BIFs, i.e. + <c>open_port</c>, <c>port_command</c> etc etc.</p> <p> - This bug was introduced in erts version 5.10 (OTP R16A).</p> + Fix so that messages sent by nifs can be traced using + normal and <c>seq_trace</c> tracing.</p> <p> - Own Id: OTP-13424 Aux Id: OTP-10336 </p> + Own Id: OTP-15038 Aux Id: ERL-602 </p> + </item> + <item> + <p> + Fixed specs and documentation for <c>process_info</c> + item <c>monitored_by</c> to include port identifiers and + nif resources as possible types.</p> + <p> + Own Id: OTP-15180 Aux Id: ERL-648 </p> + </item> + <item> + <p> + Fix bug in generation of erl_crash.dump, which could + cause VM to crash.</p> + <p> + Bug exist since erts-9.2 (OTP-20.2).</p> + <p> + Own Id: OTP-15181</p> + </item> + <item> + <p> + Fix bug where ctrl-break or ctrl-c would not trigger the + break mode properly on Windows. This bug was introduced + in erts-10.0 (OTP-21).</p> + <p> + Own Id: OTP-15205</p> + </item> + <item> + <p> + Fix a performance bug for reception of UDP packages, + where a memory buffer would be reallocated when it should + not have been.</p> + <p> + Introduce a limit on the maximum automatic increase of + the UDP user-space buffer to the theoretical max of the + network PATH, i.e. 65535.</p> + <p> + Own Id: OTP-15206</p> + </item> + <item> + <p> + Fix alignment of erts allocator state internally in erts. + With the improper alignment the emulator would refuse to + start when compiled with clang on 32-bit systems.</p> + <p> + Own Id: OTP-15208 Aux Id: PR-1897 ERL-677 </p> + </item> + <item> + <p> + Fix bug where too many concurrent calls to + <c>erlang:open_port({spawn,"cmd"},...)</c> would result + in the emulator terminating with the reason "Failed to + write to erl_child_setup: ". After this fix the + <c>open_port</c> call will throw an <c>emfile</c> + exception instead.</p> + <p> + Own Id: OTP-15210</p> + </item> + <item> + <p> + Upgraded the ERTS internal PCRE library from version 8.41 + to version 8.42. See <url + href="http://pcre.org/original/changelog.txt">http://pcre.org/original/changelog.txt</url> + for information about changes made to PCRE. This library + implements major parts of the <seealso + marker="stdlib:re"><c>re</c></seealso> regular + expressions module.</p> + <p> + Own Id: OTP-15217</p> + </item> + <item> + <p> + Fix <c>open_port({fd,X,Y}, ...)</c> to release the file + descriptors from the pollset when closing the port. + Without this fix the same file descriptor number could + not be reused when doing multiple open_port and + port_close sequences.</p> + <p> + Own Id: OTP-15236 Aux Id: ERL-692 </p> + </item> + <item> + <p> + Fixed bug in <c>float_to_list/2</c> and + <c>float_to_binary/2</c> with options + <c>[{decimals,0},compact]</c> causing totally wrong + results. Bug exists since OTP-21.0.</p> + <p> + Own Id: OTP-15276 Aux Id: PR-1920 </p> + </item> + <item> + <p> + Fixed bug in <c>erlang:memory</c> causing <c>ets</c> to + report too much. This small false memory leak (16 bytes + each time) can only happen when a specific race condition + occurs between scheduler threads on a table with option + <c>write_concurrency</c>.</p> + <p> + Own Id: OTP-15278</p> + </item> + <item> + <p> + Minor <c>configure</c> test fixes</p> + <p> + Own Id: OTP-15282</p> + </item> + <item> + <p> + Improved robustness of distribution connection setup. In + OTP-21.0 a truly asynchronous connection setup was + introduced. This is further improvement on that work to + make the emulator more robust and also be able to recover + in cases when involved Erlang processes misbehave.</p> + <p> + Own Id: OTP-15297 Aux Id: OTP-15279, OTP-15280 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The socket options <c>recvtos</c>, <c>recvttl</c>, + <c>recvtclass</c> and <c>pktoptions</c> have been + implemented in the socket modules. See the documentation + for the <c>gen_tcp</c>, <c>gen_udp</c> and <c>inet</c> + modules. Note that support for these in the runtime + system is platform dependent. Especially for + <c>pktoptions</c> which is very Linux specific and + obsoleted by the RFCs that defined it.</p> + <p> + Own Id: OTP-15145 Aux Id: ERIERL-187 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.0.8</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + As of ERTS version 10.0 (OTP 21.0) the + <c>erl_child_setup</c> program, which creates port + programs, ignores <c>TERM</c> signals. This setting was + unintentionally inherited by port programs. Handling of + <c>TERM</c> signals in port programs has now been + restored to the default behavior. That is, terminate the + process.</p> + <p> + Own Id: OTP-15289 Aux Id: ERIERL-235, OTP-14943, ERL-576 </p> + </item> + <item> + <p> + The fix made for OTP-15279 in erts-10.07 (OTP-21.0.8) was + not complete. It could cause a new connection attempt to + be incorrectly aborted in certain cases. This fix will + amend that flaw.</p> + <p> + Own Id: OTP-15296 Aux Id: OTP-15279, ERIERL-226 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.0.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A process could get stuck in an infinite rescheduling + loop between normal and dirty schedulers. This bug was + introduced in ERTS version 10.0.</p> + <p> + Thanks to Maxim Fedorov for finding and fixing this + issue.</p> + <p> + Own Id: OTP-15275 Aux Id: PR-1943 </p> + </item> + <item> + <p> + Garbage collection of a distribution entry could cause an + emulator crash if <c>net_kernel</c> had not brought + previous connection attempts on it down properly.</p> + <p> + Own Id: OTP-15279 Aux Id: ERIERL-226 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.0.6</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A race between termination of a process and resume of the + same process via <c>erlang:resume_process/1</c> could + cause the VM to crash. This bug was introduced in erts + version 10.0 (OTP 21.0).</p> + <p> + Own Id: OTP-15237</p> + </item> + <item> + <p> + When tracing on <c>running</c>, <c>in</c> trace events + could be lost when a process was rescheduled between a + dirty and a normal scheduler.</p> + <p> + Own Id: OTP-15269 Aux Id: ERL-713 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.0.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a bug which caused an emulator crash when + <c>enif_send()</c> was called by a NIF that executed on a + dirty scheduler. The bug was either triggered when the + NIF called <c>enif_send()</c> without a message + environment, or when the process executing the NIF was + <c>send</c> traced.</p> + <p> + Own Id: OTP-15223</p> + </item> + <item> + <p> + Fixed a bug causing some Erlang references to be + inconsistently ordered. This could for example cause + failure to look up certain elements with references as + keys in search data structures. This bug was introduced + in R13B02.</p> + <p> + Thanks to Simon Cornish for finding the bug and supplying + a fix.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15225</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.0.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a bug that prevented the <c>noshell</c> option + from working correctly on Mac OS X and BSD.</p> + <p> + Own Id: OTP-15169</p> + </item> + <item> + <p>Fixed a crash when matching directly against a literal + map using a single key that had been saved on the + stack.</p> + <p> + Own Id: OTP-15184</p> + </item> + <item> + <p>Fix node crash when passing a bad time option to + <c>file:read_file_info/2</c>.</p> + <p> + Own Id: OTP-15196</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.0.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a scheduler bug that caused normal schedulers to + run dirty code.</p> + <p> + Own Id: OTP-15154</p> + </item> + <item> + <p> + Fixed a bug in <c>erlang:trace_info/2</c> which caused + the emulator to crash when a bad argument was passed. The + bug was introduced in ERTS version 10.0.</p> + <p> + Own Id: OTP-15183 Aux Id: ERL-670 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.0.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a rare bug that could cause processes to be + scheduled after they had been freed.</p> + <p> + Own Id: OTP-15067 Aux Id: ERL-573 </p> + </item> + <item> + <p>Fixed a race condition in the inet driver that could + cause receive to hang when the emulator was compiled with + gcc 8.</p> + <p> + Own Id: OTP-15158 Aux Id: ERL-654 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>The keys used in <c>os:getenv</c> and <c>os:putenv</c> + are case-insensitive again on Windows.</p> + <p> + Own Id: OTP-15147 Aux Id: ERL-644 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 10.0</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The type specifications for <c>file:posix/0</c> and + <c>inet:posix/0</c> have been updated according to which + errors file and socket operations should be able to + return.</p> + <p> + Own Id: OTP-14019 Aux Id: ERL-550 </p> + </item> + <item> + <p> + Fix error printout from run_erl and a bug that could + cause unintended fds to be leaked into the started + program.</p> + <p> + Own Id: OTP-14537 Aux Id: PR1529 </p> + </item> + <item> + <p> File operations used to accept <seealso + marker="kernel:file#type-name_all">filenames</seealso> + containing null characters (integer value zero). This + caused the name to be truncated and in some cases + arguments to primitive operations to be mixed up. + Filenames containing null characters inside the filename + are now <em>rejected</em> and will cause primitive file + operations to fail. </p> <p> Also environment variable + operations used to accept <seealso + marker="kernel:os#type-env_var_name">names</seealso> and + <seealso + marker="kernel:os#type-env_var_value">values</seealso> of + environment variables containing null characters (integer + value zero). This caused operations to silently produce + erroneous results. Environment variable names and values + containing null characters inside the name or value are + now <em>rejected</em> and will cause environment variable + operations to fail. </p> <p>Primitive environment + variable operations also used to accept the <c>$=</c> + character in environment variable names causing various + problems. <c>$=</c> characters in environment variable + names are now also <em>rejected</em>. </p> <p>Also + <seealso + marker="kernel:os#cmd/1"><c>os:cmd/1</c></seealso> now + reject null characters inside its <seealso + marker="kernel:os#type-os_command">command</seealso>. + </p> <p><seealso + marker="erts:erlang#open_port/2"><c>erlang:open_port/2</c></seealso> + will also reject null characters inside the port name + from now on.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14543 Aux Id: ERL-370 </p> + </item> + <item> + <p> + Fix bugs related to the bookkeeping of microstate + accounting states.</p> + <p> + Own Id: OTP-14652</p> + </item> + <item> + <p><c>os:putenv</c> and <c>os:getenv</c> no longer access + the process environment directly and instead work on a + thread-safe emulation. The only observable difference is + that it's <em>not</em> kept in sync with libc + <c>getenv(3)</c> / <c>putenv(3)</c>, so those who relied + on that behavior in drivers or NIFs will need to add + manual synchronization.</p> <p>On Windows this means that + you can no longer resolve DLL dependencies by modifying + the <c>PATH</c> just before loading the driver/NIF. To + make this less of a problem, the emulator now adds the + target DLL's folder to the DLL search path.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14666</p> + </item> + <item> + <p>Corrected <c>erlang:is_builtin(erlang, M, F)</c> to + return <c>true</c> for <c>apply/2</c> and + <c>yield/0</c>.</p> + <p> + Own Id: OTP-14713 Aux Id: ERL-500 </p> + </item> + <item> + <p>Fixed a bug where the PATH environment variable wasn't + updated correctly on a release downgrade, effectively + keeping the PATH of the new release.</p> + <p> + Own Id: OTP-14719</p> + </item> + <item> + <p>A receive optimization that avoids scanning the entire + message queue when receiving a message containing a + freshly created reference could in rare circumstances + (involving recursive calls to the functions that does the + receive) cause the receive to hang. This has been + corrected.</p> + <p> + Own Id: OTP-14782 Aux Id: ERL-511 </p> + </item> + <item> + <p> + Fix building of Erlang/OTP on platforms which have small + data area with short addressing. For example the + PowerPC/RTEMS platform.</p> + <p> + Own Id: OTP-14909 Aux Id: PR-1692 </p> + </item> + <item> + <p>Fixed a crash when <c>enif_make_binary</c> is called + with a binary produced by <c>enif_inspect_binary</c> in a + different environment.</p> + <p> + Own Id: OTP-14931</p> + </item> + <item> + <p>Fixed a crash when <c>enif_make_binary</c> is called + more than once with a binary that had previously been + added to an <c>enif_ioq</c>.</p> + <p> + Own Id: OTP-14932</p> + </item> + <item> + <p> + The erl_child_setup program now ignores SIGTERM signals.</p> + <p> + Own Id: OTP-14943 Aux Id: ERL-576 </p> + </item> + <item> + <p> + Force 64-bit alignment on pre-allocators on architectures + which needs it.</p> + <p> + Own Id: OTP-14977</p> + </item> + <item> + <p> + Fixed a bug where dirty scheduler picked up non-dirty + work.</p> + <p> + Own Id: OTP-14978</p> + </item> + <item> + <p> + Calls to <c>gen_tcp:send/2</c> on closed sockets now + returns <c>{error, closed}</c> instead of + <c>{error,enotconn}</c>.</p> + <p> + Own Id: OTP-15001</p> + </item> + <item> + <p> + <c>erlang:monotonic_time/1</c> failed with <c>badarg</c> + when passing the <c>perf_counter</c> time unit as + argument.</p> + <p> + Own Id: OTP-15008</p> + </item> + <item> + <p> + Fix bug where rapid <c>init:restart()</c> calls would + sometimes crash because a code load request leaked in + between the restarts.</p> + <p> + Own Id: OTP-15013</p> + </item> + <item> + <p> + Improve <c>float_to_list(F, [{decimals,D}])</c> to closer + conform with <c>io_lib:format("~.*f", [D,F])</c>.</p> + <p> + There are however, still cases when <c>float_to_list</c> + does not produce the exact same result as + <c>io_lib:format</c>, especially for large values + <c>F</c> and/or many decimals <c>D</c>.</p> + <p> + Own Id: OTP-15015 Aux Id: OTP-14890 </p> + </item> + <item> + <p>Fixed a deadlock that would occur on certain + allocators when a reallocation failed with <c>+ramv</c> + enabled.</p> + <p> + Own Id: OTP-15024</p> + </item> + <item> + <p> + Fix bug that made it impossible to use an erl_tracer as + the seq_trace trace receiver.</p> + <p> + Own Id: OTP-15029</p> + </item> + <item> + <p> + Fix bug where a large (> 1 GB) emulator generated error + logger message would cause the emulator to crash.</p> + <p> + Own Id: OTP-15032</p> + </item> + <item> + <p>The emulator will no longer crash when reading the + file information of an ordinary file that has an NTFS + reparse point, such as files stored in a OneDrive-mapped + folder.</p> + <p> + Own Id: OTP-15062 Aux Id: ERL-615 </p> + </item> + <item> + <p> + Fixed bug in <c>enif_binary_to_term</c> which could cause + memory corruption for immediate terms (atoms, small + integers, pids, ports, empty lists).</p> + <p> + Own Id: OTP-15080</p> + </item> + <item> + <p> + Fixed bug in <c>erlang:system_profile/2</c> that could + cause superfluous <c>{profile,_,active,_,_}</c> messages + for terminating processes.</p> + <p> + Own Id: OTP-15085</p> + </item> + <item> + <p> + On OSs with per thread CPU time support, change + <c>cpu_timestamp</c> in <seealso + marker="erlang#trace/3">erlang:trace/3</seealso> to use + it instead of per process CPU time. This makes this + option useable on such OSs when running multiple + schedulers.</p> + <p> + Own Id: OTP-15090</p> + </item> + <item> + <p> + Fix segfault in abort_signal_task which could happen if a + port terminated while there were outstanding port tasks + that were not signals, for example a + ready_input/ready_output event.</p> + <p> + Own Id: OTP-15108 Aux Id: ERL-621 </p> + </item> + <item> + <p> + Fixed bug in <c>ets</c> that could cause VM crash if + process A terminates after fixating a table and process B + deletes the table at "the same time". The table fixation + could be done with <c>ets:safe_fixtable</c> or if process + A terminates in the middle of a long running + <c>select</c> or <c>match</c> call.</p> + <p> + Own Id: OTP-15109</p> + </item> + <item> + <p>Owner and group changes through + <c>file:write_file_info</c>, <c>file:change_owner</c>, + and <c>file:change_group</c> will no longer report + success on permission errors.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15118</p> + </item> + <item> + <p> + Fix a bug error reporting from escripts on windows where + the error message would get garbled.</p> + <p> + Own Id: OTP-15119 Aux Id: PR-1826 </p> + </item> + <item> + <p> + Fix segfault when a process is interally re-scheduled + while being traced for in out events. This bug was + introduced in erts-8.0 (OTP-19.0).</p> + <p> + Own Id: OTP-15125</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>It is now possible to open device files and FIFOs with + <c>file:open/2</c>.</p> + <p> + Own Id: OTP-11462</p> + </item> + <item> + <p> + The <c>erlang:system_flag(scheduler_wall_time,Bool)</c> + call is now reference counted and will be turned off if + the (last) process that started the performance + statistics dies. Thus it is no longer possible to start + the statistics with <c>rpc:call(Node, erlang, + system_flag, [scheduler_wall_time, true])</c> since it + will be turned off directly afterwards when the rpc + process dies.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-11694</p> + </item> + <item> + <p>A new logging API is added to Erlang/OTP, see the + <seealso + marker="kernel:logger"><c>logger(3)</c></seealso> manual + page, and section <seealso + marker="kernel:logger_chapter">Logging</seealso> in the + Kernel User's Guide.</p> + <p>Calls to <c>error_logger</c> are automatically + redirected to the new API, and legacy error logger event + handlers can still be used. It is, however, recommended + to use the Logger API directly when writing new code.</p> + <p>Notice the following potential incompatibilities:</p> + <list> <item><p>Kernel configuration parameters + <c>error_logger</c> still works, but is overruled if the + default handler's output destination is configured with + Kernel configuration parameter <c>logger</c>.</p> <p>In + general, parameters for configuring error logger are + overwritten by new parameters for configuring + Logger.</p></item> <item><p>The concept of SASL error + logging is deprecated, meaning that by default the SASL + application does not affect which log events are + logged.</p> <p>By default, supervisor reports and crash + reports are logged by the default Logger handler started + by Kernel, and end up at the same destination (terminal + or file) as other standard log event from Erlang/OTP.</p> + <p>Progress reports are not logged by default, but can be + enabled by setting the primary log level to info, for + example with the Kernel configuration parameter + <c>logger_level</c>.</p> <p>To obtain backwards + compatibility with the SASL error logging functionality + from earlier releases, set Kernel configuration parameter + <c>logger_sasl_compatible</c> to <c>true</c>. This + prevents the default Logger handler from logging any + supervisor-, crash-, or progress reports. Instead, SASL + adds a separate Logger handler during application start, + which takes care of these log events. The SASL + configuration parameters <c>sasl_error_logger</c> and + <c>sasl_errlog_type</c> specify the destination (terminal + or file) and severity level to log for these + events.</p></item></list> + <p> + Since Logger is new in Erlang/OTP 21.0, we do reserve the + right to introduce changes to the Logger API and + functionality in patches following this release. These + changes might or might not be backwards compatible with + the initial version.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13295</p> + </item> + <item> + <p> + <c>gen_sctp:connect_init/4</c> or rather connect in + <c>inet_drv.c</c> for SCTP has been fixed to not check + the write file descriptor for writeability after a + connect, since for SCTP (SOCK_SEQPACKET) that property + does not seem to be any kind of indicator for when a + connect has finished. This fixes connects that the OS + returned as "in progress" that was misinterpreted by + <c>gen_sctp:connect_init</c> as failed.</p> + <p> + Own Id: OTP-13760 Aux Id: PR-1592 </p> + </item> + <item> + <p>The file driver has been rewritten as a NIF, + decreasing the latency of file operations. Notable + incompatibilities are:</p> <list> <item><p>The + <c>use_threads</c> option for <c>file:sendfile/5</c> no + longer has any effect; we either use non-blocking + <c>sendfile(2)</c> or fall back to <c>file:read</c> + + <c>gen_tcp:send</c>. </p></item> <item><p>The + file-specific DTrace probes have been removed. The same + effect can be achieved with normal tracing together with + the <c>nif__entry</c>/<c>nif__return</c> probes to track + scheduling.</p></item> </list> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14256</p> + </item> + <item> + <p>The I/O polling functionality of erts has been + re-written to better make use of the OSs polling + mechanisms. This change means that erts will now always + prefer to use a kernel-polling mechanism if possible. + Also all of the I/O polling has been moved to dedicated + threads instead of being placed in the scheduler + loops.</p> <p>As a result of this, the <c>erl</c> options + <c>+K</c> and <c>+secio</c> have been removed. It is + still possible to disable kernel-poll, but it has to be + done at compile time through the configure option + <c>--disable-kernel-poll</c>.</p> <p>The new <c>erl</c> + options <seealso marker="erl#+IOt"><c>+IOt</c></seealso> + and <seealso marker="erl#+IOp"><c>+IOp</c></seealso> can + be used to change how many IO poll threads and poll sets + that erts should use. See their respective documentation + for more details.</p> + <p> + Own Id: OTP-14346</p> + </item> + <item> + <p>Truly asynchronous auto-connect. Earlier, when + <c>erlang:send</c> was aimed toward an unconnected node, + the function would not return until the connection setup + had completed (or failed). Now the function returns + directly after the message has been enqueued and the + connection setup started.</p> + <p>The same applies to all distributed operations that + may trigger auto-connect, i.e. <c>'!'</c>, <c>send</c>, + <c>link</c>, <c>monitor</c>, <c>monitor_node</c>, + <c>exit/2</c> and <c>group_leader</c>.</p> + <p>The interface for all these functions are unchanged as + they do not return connection failures. The only + exception is <c>erlang:monitor</c> where a <em>possible + incompatibility</em> is introduced: An attempt to monitor + a process on a primitive node (such as erl_interface or + jinterface), where remote process monitoring is not + implemented, will no longer fail with <c>badarg</c> + exception. Instead a monitor will be created, but it will + only supervise the connection to the node.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14370</p> + </item> + <item> + <p>Changed the default behaviour of <c>.erlang</c> + loading: <c>.erlang</c> is no longer loaded from the + current directory. <c>c:erlangrc(PathList)</c> can be + used to search and load an <c>.erlang</c> file from user + specified directories.</p> <p><c>escript</c>, + <c>erlc</c>, <c>dialyzer</c> and <c>typer</c> no longer + load an <c>.erlang</c> at all.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14439</p> + </item> + <item> + <p> + New functionality for implementation of alternative + carriers for the Erlang distribution has been introduced. + This mainly consists of support for usage of distribution + controller processes (previously only ports could be used + as distribution controllers). For more information see + <seealso marker="erts:alt_dist#distribution_module">ERTS + User's Guide âžœ How to implement an Alternative Carrier + for the Erlang Distribution âžœ Distribution + Module</seealso>.</p> + <p> + Own Id: OTP-14459</p> + </item> + <item> + <p> + Add support for the lcc compiler and in extension the + Elbrus 2000 platform.</p> + <p> + Own Id: OTP-14492</p> + </item> + <item> + <p>Support for "tuple calls" have been removed from the + run-time system. Tuple calls was an undocumented and + unsupported feature which allowed the module argument for + an apply operation to be a tuple: <c>Var = dict:new(), + Var:size()</c>. This "feature" frequently caused + confusion, especially when such call failed. The + stacktrace would point out functions that don't exist in + the source code.</p> + <p>For legacy code that need to use parameterized modules + or tuple calls for some other reason, there is a new + compiler option called <c>tuple_calls</c>. When this + option is given, the compiler will generate extra code + that emulates the old behavior for calls where the module + is a variable.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14497</p> + </item> + <item> + <p>Creation of small maps with literal keys has been + optimized to be faster and potentially use less memory. + The keys are combined into a literal key tuple which is + put into the literal pool. The key tuple can be shared + between many instances of maps having the same keys.</p> + <p> + Own Id: OTP-14502</p> + </item> + <item> + <p> + When an exception is thrown, include the arguments of the + call in the stacktrace for BIFs <c>band</c>, <c>bor</c>, + <c>bsl</c>, <c>bsr</c>, <c>bxor</c>, <c>div</c>, + <c>rem</c> and the operators <c>+</c>, <c>-</c>, <c>*</c> + and <c>/</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14508</p> + </item> + <item> + <p> + The non-smp emulators have been removed. This means that + the configure options <c>--disable-threads</c> and + <c>--enable-plain-emulator</c> have been removed and + configure will now refuse to build Erlang/OTP on + platforms without thread support.</p> + <p> + In order to achieve a similar setup as the non-smp + emulator, it is possible to start Erlang/OTP with the + <c>+S 1</c> option.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14518</p> + </item> + <item> + <p>Modules that use floating point constants compiled + with R15 or earlier will need to be re-compiled before + they can be loaded.</p> + <p> + Own Id: OTP-14575</p> + </item> + <item> + <p> + Implementation of true asynchronous signaling between + processes in order to improve scalability. Signals + affected include exit, monitor, demonitor, monitor + triggered, link, unlink, and group leader.</p> + <p> + Own Id: OTP-14589</p> + </item> + <item> + <p> + Added a PGO (profile guided optimization) pass to the + build step of erts. This can be disabled by passing + --disable-pgo to configure.</p> + <p> + Own Id: OTP-14604</p> + </item> + <item> + <p> + Improved the performance of <c>binary:split</c> and + <c>binary:match</c>.</p> + <p> + Own Id: OTP-14610 Aux Id: PR-1480 </p> + </item> + <item> + <p> + It is not longer possible to disable dirty schedulers + when building erlang.</p> + <p> + Own Id: OTP-14613</p> + </item> + <item> + <p>Loaded BEAM code in a 64-bit system requires less + memory because of better packing of operands for + instructions.</p> + <p>These memory savings were achieved by major + improvements to the <c>beam_makeops</c> scripts used when + building the run time system and BEAM compiler. There is + also new for documentation for <c>beam_makeops</c> that + describes how new BEAM instructions and loader + transformations can be implemented. The documentation is + found in here in a source directory or git repository: + erts/emulator/internal_doc/beam_makeops.md. An online + version can be found here: + https://github.com/erlang/otp/blob/master/erts/emulator/internal_doc/beam_makeops.md</p> + <p> + Own Id: OTP-14626</p> + </item> + <item> + <p><c>file:read_file</c> has been changed to read the + content of files that report a size of 0 even when data + can be read from them. An example of such a file is + <c>/proc/cpuinfo</c> on Linux.</p> + <p> + Own Id: OTP-14637 Aux Id: ERL-327 PR-1524 </p> + </item> + <item> + <p> + It is no longer possible to disable the <c>temp_alloc</c> + allocator. Disabling it caused serious performance + degradations and was never what was wanted.</p> + <p> + Own Id: OTP-14651</p> + </item> + <item> + <p>The reduction cost of sending messages is now + constant. It will no longer scale according to the length + of the receiving process' message queue.</p> + <p> + Own Id: OTP-14667</p> + </item> + <item> + <p> + Improved loading of modules with <c>-on_load</c> + directive, to no longer block all schedulers when the + load operation is completed.</p> + <p> + Own Id: OTP-14680</p> + </item> + <item> + <p> + On platforms with real-time signals available, SIGRTMIN+1 + is now used as the internal scheduler suspend signal + instead of SIGUSR2.</p> + <p> + Own Id: OTP-14682</p> + </item> + <item> + <p>When the value returned from a '<c>catch</c>' + expression is ignored, no stacktrace will be built if an + exception is caught. That will save time and produce less + garbage. There are also some minor optimizations of + '<c>try</c>/<c>catch</c>' both in the compiler and + run-time system.</p> + <p> + Own Id: OTP-14683</p> + </item> + <item> + <p>The guarantees and non-guarantees of + <c>erlang:get_stacktrace/0</c> are now documented.</p> + <p> + Own Id: OTP-14687</p> + </item> + <item> + <p>There is a new syntax in '<c>try/catch</c>' for + retrieving the stacktrace without calling + '<c>erlang:get_stacktrace/0</c>'. See the reference + manual for a description of the new syntax. The + '<c>erlang:get_stacktrace/0</c>' BIF is now + deprecated.</p> + <p> + Own Id: OTP-14692</p> + </item> + <item> + <p> + New 'used' option for <c>binary_to_term/2</c> that will + also return number of bytes actually read from the + binary. This enables easy access to any extra data in the + binary located directly after the returned term.</p> + <p> + Own Id: OTP-14780</p> + </item> + <item> + <p> + Added more statistics for + <c>erlang:system_info({allocator,A})</c> in the + <c>mbcs_pool</c> section.</p> + <p> + Own Id: OTP-14795 Aux Id: ERL-88 </p> + </item> + <item> + <p>Added <c>enif_ioq_peek_head</c> to retrieve Erlang + terms from NIF IO queues without having to resort to + copying.</p> + <p> + Own Id: OTP-14797</p> + </item> + <item> + <p>There is a new option '<c>makedep_side_effect</c>' for + the compiler and <c>-MMD</c> for '<c>erlc</c>' that + generates dependencies and continues to compile as + normal.</p> + <p> + Own Id: OTP-14830</p> + </item> + <item> + <p>Added <c>ets:whereis/1</c> for retrieving the table + identifier of a named table.</p> + <p> + Own Id: OTP-14884</p> + </item> + <item> + <p><c>seq_trace</c> labels may now be any erlang + term.</p> + <p> + Own Id: OTP-14899</p> + </item> + <item> + <p> + Optimized the common case of <c>monitor</c> followed by + <c>send</c> to the same local process. The monitor signal + is now delayed in order to be piggybacked with the sent + message and thereby only get one lock operation on the + message queue of the receiver. A delayed monitor signal + is flushed if no <c>send</c> has been done at the latest + when the process is scheduled out.</p> + <p> + Own Id: OTP-14901</p> + </item> + <item> + <p> + Make hipe compiled code work on x86_64 (amd64) with OS + security feature PIE, where executable code can be loaded + into a random location. Old behavior, if hipe was + enabled, was to disable PIE build options for the VM.</p> + <p> + Own Id: OTP-14903</p> + </item> + <item> + <p>The number of driver async threads will now default to + 1 as the standard drivers do not use them anymore. Users + that changed this value to tweak the file driver should + replace <c>+A</c> with <c>+SDio</c> since it now uses + dirty IO schedulers instead of async threads.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14928</p> + </item> + <item> + <p> + Optimize <c>==</c> and <c>/=</c> for binaries with + different sizes to be constant in time instead of + proportional to the size of their common prefix.</p> + <p> + Own Id: OTP-14934 Aux Id: PR-1708 </p> + </item> + <item> + <p> + Refactorings making some internal process flags available + for other usage.</p> + <p> + Own Id: OTP-14948</p> + </item> + <item> + <p> + Removed need for HiPE to allocate native executable + memory in low 2GB address space on x86_64. Command line + option <c>+MXscs</c> is thereby obsolete and ignored.</p> + <p> + Own Id: OTP-14951</p> + </item> + <item> + <p>Added <c>enif_make_map_from_arrays</c> for creating a + populated map, analogous to + <c>enif_make_list_from_array</c>.</p> + <p> + Own Id: OTP-14954</p> + </item> + <item> + <p>Added configuration switches for busy-wait and wake up + thresholds for dirty schedulers, and changing these + settings for normal schedulers will no longer affect + dirty schedulers. </p> <p>Refer to the documentation for + details. The new switches are <seealso + marker="erl#+sbwtdcpu">+sbwtdcpu</seealso>, <seealso + marker="erl#+sbwtdio">+sbwtdio</seealso>, <seealso + marker="erl#+swtdcpu">+swtdcpu</seealso>, and <seealso + marker="erl#+swtdio">+swtdio</seealso>.</p> <p>The + default busy wait threshold for dirty scheduler threads + has also been lowered to <c>short</c>.</p> + <p> + Own Id: OTP-14959</p> + </item> + <item> + <p> + The list of "taints" now also includes dynamic loaded + drivers in addition to NIF libraries. Statically linked + drivers and NIF libraries that are part of erts are not + included. The "taints" are returned by + <c>system_info(taints)</c> and printed in the header of + <c>erl_crash.dump</c> files.</p> + <p> + Own Id: OTP-14960</p> + </item> + <item> + <p>Added <c>instrument:allocations</c> and + <c>instrument:carriers</c> for retrieving information + about memory utilization and fragmentation.</p> + <p>The old <c>instrument</c> interface has been removed, + as have the related options <c>+Mim</c> and + <c>+Mis</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14961</p> + </item> + <item> + <p>The process suspend functionality used by the <seealso + marker="erlang#suspend_process/2">erlang:suspend_process/2</seealso> + BIF has been reimplemented using the newly introduced + true asynchronous signaling between processes. This + mainly to reduce memory usage in the process control + block of all processes, but also in order to simplify the + implementation.</p> <warning> <p>You can easily create + deadlocks if processes suspends each other (directly or + in circles). In ERTS versions prior to ERTS version 10.0, + the runtime system prevented such deadlocks, but this + prevention has now been removed due to performance + reasons.</p> </warning> <p>Other ERTS internal + functionality that used the previous process suspend + functionality have also been reimplemented to use + asynchronous signaling instead.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14964 Aux Id: OTP-14589 </p> + </item> + <item> + <p>Added the <c>nifs</c> option to + <c>?MODULE:module_info/1</c> for listing a module's + installed NIF functions.</p> + <p> + Own Id: OTP-14965</p> + </item> + <item> + <p> + New implementation of <c>erlang:process_info/[1,2]</c>.</p> + <p> + In the general case when inspecting another process, the + new implementation sends an asynchronous process-info + request signal to the other process and waits for the + result instead of locking the other process and reading + the result directly. In some special cases where no + conflicts occur, signal order wont be violated, and the + amount of data requested is guaranteed to be small, the + inspected process may be inspected directly.</p> + <p> + Appropriate amount of reductions are now also bumped when + inspecting a process.</p> + <p> + Own Id: OTP-14966</p> + </item> + <item> + <p> + Removed process start time from crash dump in order to + save memory in process control block.</p> + <p> + Own Id: OTP-14975 Aux Id: PR-1597 </p> + </item> + <item> + <p> + Optimize <c>erlang:put/2</c> when updating existing key + with a new immediate value (atom, small integer, pid, + port).</p> + <p> + Own Id: OTP-14976</p> + </item> + <item> + <p> + <c>erlang:process_info/1</c> has been changed to no + longer include <c>messages</c> by default. Instead + <c>erlang:process_info/2</c> should be used.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14986 Aux Id: PR-1745 </p> + </item> + <item> + <p> + New <c>erlang:system_info(ets_count)</c> to get total + number of ets tables existing at the local node.</p> + <p> + Own Id: OTP-14987</p> + </item> + <item> + <p> + New NIF functions: <c>enif_mutex_name</c>, + <c>enif_cond_name</c>, <c>enif_rwlock_name</c>, + <c>enif_thread_name</c>, <c>enif_vfprintf</c>, + <c>enif_vsnprintf</c>.</p> + <p> + Own Id: OTP-14994</p> + </item> + <item> + <p>When <c>erlang:system_flag(backtrace_depth, 0)</c> has + been called, all exceptions will now contain the entry + for <em>one</em> function (despite the zero). It used to + be that a hand-made stack backtrace passed to + <c>erlang:raise/3</c> would be be truncated to an empty + list.</p> + <p> + Own Id: OTP-15026</p> + </item> + <item> + <p> + Fixed bug for named <c>ets</c> tables which could cause + unexpected results from matchspec iteration functions + (<c>ets:select*</c> and <c>ets:match*</c>) if the table + was deleted and recreated with the same name during the + iteration. The iteration could incorrectly continue + through the recreated table. The expected correct + behavior is now for the iteration call to fail with a + <c>badarg</c> exception if the table is deleted before + the iteration has completed.</p> + <p> + Own Id: OTP-15031</p> + </item> + <item> + <p>Two new guards BIFs operating on maps have been added: + <c>map_get/2</c> and <c>is_map_key/2</c>. They do the + same as <c>maps:get/2</c> and <c>maps:is_key/2</c>, + respectively, except that they are allowed to be used in + guards.</p> + <p> + Own Id: OTP-15037 Aux Id: PR-1784, PR-1802 </p> + </item> + <item> + <p> + Release run-queue lock while cleaning up terminated dirty + process.</p> + <p> + Own Id: OTP-15081</p> + </item> + <item> + <p>The callback module passed as <c>-epmd_module</c> to + erl has been expanded to be able to do name and port + resolving.</p> <p>Documentation has also been added in + the <seealso + marker="kernel:erl_epmd"><c>erl_epmd</c></seealso> + reference manual and ERTS User's Guide <seealso + marker="erts:alt_disco">How to Implement an Alternative + Service Discovery for Erlang Distribution</seealso>.</p> + <p> + Own Id: OTP-15086 Aux Id: PR-1694 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.3.3.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a bug which caused an emulator crash when + <c>enif_send()</c> was called by a NIF that executed on a + dirty scheduler. The bug was either triggered when the + NIF called <c>enif_send()</c> without a message + environment, or when the process executing the NIF was + <c>send</c> traced.</p> + <p> + Own Id: OTP-15223</p> + </item> + <item> + <p> + Fixed a bug causing some Erlang references to be + inconsistently ordered. This could for example cause + failure to look up certain elements with references as + keys in search data structures. This bug was introduced + in R13B02.</p> + <p> + Thanks to Simon Cornish for finding the bug and supplying + a fix.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15225</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.3.3.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a race condition in the inet driver that could + cause receive to hang when the emulator was compiled with + gcc 8.</p> + <p> + Own Id: OTP-15158 Aux Id: ERL-654 </p> + </item> + <item> + <p> + Fix bug in generation of erl_crash.dump, which could + cause VM to crash.</p> + <p> + Bug exist since erts-9.2 (OTP-20.2).</p> + <p> + Own Id: OTP-15181</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.3.3.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a rare bug that could cause processes to be + scheduled after they had been freed.</p> + <p> + Own Id: OTP-15067 Aux Id: ERL-573 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.3.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed bug in <c>ets</c> that could cause VM crash if + process A terminates after fixating a table and process B + deletes the table at "the same time". The table fixation + could be done with <c>ets:safe_fixtable</c> or if process + A terminates in the middle of a long running + <c>select</c> or <c>match</c> call.</p> + <p> + Own Id: OTP-15109</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.3.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed bug in <c>enif_binary_to_term</c> which could cause + memory corruption for immediate terms (atoms, small + integers, pids, ports, empty lists).</p> + <p> + Own Id: OTP-15080</p> + </item> + <item> + <p> + Fixed bug in <c>erlang:system_profile/2</c> that could + cause superfluous <c>{profile,_,active,_,_}</c> messages + for terminating processes.</p> + <p> + Own Id: OTP-15085</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.3.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a crash in <c>heart:get_cmd/0</c> when the + stored command was too long.</p> + <p> + Own Id: OTP-15034</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a <c>configure</c> test for <c>libz</c> internals + that unintentionally caused various native code in OTP to + link against <c>libz</c>. Under certain circumstances + this caused the build of OTP to fail.</p> + <p> + Own Id: OTP-14840 Aux Id: ERL-529 </p> + </item> + <item> + <p> + File names containing unicode codepoints larger than 255 + were not correctly encoded in stack traces.</p> + <p> + Own Id: OTP-14847 Aux Id: ERL-544 </p> + </item> + <item> + <p> + Fix HiPE bug for binary constructs like + <c><<X/utf8>></c> which could in rare cases + cause faulty results or VM crash.</p> + <p> + This fix affects both the <c>hipe</c> compiler and + <c>erts</c> runtime in an <em>incompatible</em> way. Old + hipe compiled files need to be recompiled to load and run + properly as native.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14850 Aux Id: PR-1664 </p> + </item> + <item> + <p> + Fix <c>term_to_binary/2</c> spec for + <c>minor_version</c>.</p> + <p> + Own Id: OTP-14876 Aux Id: ERL-548 </p> + </item> + <item> + <p> + Fix bug in erlang:binary_to_integer/2 where invalid + characters were not detected for bases larger then 10. + e.g. <c>binary_to_integer(<<":">>, 16)</c> + would return 3 and not badarg as it should.</p> + <p> + Own Id: OTP-14879</p> + </item> + <item> + <p>Fixed bug in <c>float_to_list/2</c> and + <c>float_to_binary/2</c> with option <c>decimals</c> that + caused a faulty rounding up of the last decimal digit for + about 6% of floats with a fraction part.</p> + <p>For example, <c>float_to_list(0.145, + [{decimals,1}])</c> returned <c>"0.2"</c> instead of + <c>"0.1"</c>.</p> + <p> + Own Id: OTP-14890</p> + </item> + <item> + <p> + Fix bug causing slow hipe execution in modules loaded + early during boot or loaded by <c>code:atomic_load</c> or + <c>code:finish_loading</c>.</p> + <p> + Own Id: OTP-14891</p> + </item> + <item> + <p>Fixed a buffer overflow in an internal string + formatting function that could be hit if specifying a + long floating-point format specifier to + <c>erts_sprintf</c> or similar.</p> + <p> + Own Id: OTP-14920</p> + </item> + <item> + <p><c>erlang:iolist_to_iovec/1</c> and + <c>enif_inspect_iovec</c> will no longer fail when + provided with binaries that have been matched-out on a + non-byte boundary.</p> + <p> + Own Id: OTP-14921</p> + </item> + <item> + <p><c>iolist_to_binary/1</c> and + <c>erlang:iolist_to_iovec/1</c> will now badarg if + supplied with a bitstring (without a list).</p> + <p> + Own Id: OTP-14926</p> + </item> + <item> + <p> + Reject loading modules with names containing directory + separators ('/' or '\' on Windows).</p> + <p> + Own Id: OTP-14933 Aux Id: ERL-564, PR-1716 </p> + </item> + <item> + <p> + Fix potential dead-lock when the tracer process dies + while a the traced process is running on a dirty + scheduler.</p> + <p> + Own Id: OTP-14938</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + More crash dump info such as: process binary virtual heap + stats, full info for process causing out-of-mem during + GC, more port related info, and dirty scheduler info.</p> + <p> + Own Id: OTP-14820</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.2.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Improve search algorithm of abandoned memory carriers. + Instead of limited linear search, each allocator instance + maintain a balanced search tree of all its abandoned + carriers for faster and more exhaustive search.</p> + <p> + Own Id: OTP-14915 Aux Id: ERIERL-88 </p> + </item> + <item> + <p> + New erts_alloc command line options <c>+M_acnl</c> and + <c>+M_acfml</c> to limit carrier abandonment.</p> + <p> + Own Id: OTP-14916 Aux Id: ERIERL-88 </p> + </item> + <item> + <p> + New family of <c>erts_alloc</c> strategies: Age Order + First Fit. Similar to "address order", but instead the + oldest possible carrier is always chosen for allocation.</p> + <p> + Own Id: OTP-14917 Aux Id: ERIERL-88 </p> + </item> + <item> + <p> + Add possibility to change allocator options at runtime + with <c>system_info(erts_alloc, ...)</c>. Only option + <c>sbct</c> (single block carrier threshold) is currently + supported via this interface.</p> + <p> + Own Id: OTP-14918 Aux Id: ERIERL-88 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix a bug in tracing where the {caller} match spec + function would be set to undefined incorrectly when used + in conjunction with return_to or return_trace on some + functions.</p> + <p> + The functions effected are: erlang:put/2, erlang:erase/1, + erlang:process_info/1,2, erlang:nif_load/2, + erts_internal:garbage_collection/1 and + erts_internal:check_process_code/1.</p> + <p> + Because of this bug, the analysis done by fprof could + become incorrect when the functions above are the + tail-call in a function.</p> + <p> + Own Id: OTP-14677</p> + </item> + <item> + <p> + Fix emulator deadlock that would happen if + <c>trap_exit</c> was set to true and a process sends an + exit signal to itself using <c>exit(self(), Reason)</c> + while receive tracing was enabled for that process.</p> + <p> + Own Id: OTP-14678 Aux Id: ERL-495 </p> + </item> + <item> + <p>Writing of crash dumps is significantly faster.</p> + <p>Maps are now included in crash dumps.</p> + <p>Constants terms would only be shown in one process, + while other processes referencing the same constant term + would show a marker for incomplete heap. </p> + <p> + Own Id: OTP-14685 Aux Id: OTP-14611, OTP-14603, OTP-14595 </p> + </item> + <item> + <p> + The fallback home directory for windows has been changed + to be the PROFILE directory instead of the WINDOWS + directory. The fallback is used when the environment + variables HOMEDRIVE and HOMEPATH have not been set.</p> + <p> + Own Id: OTP-14691</p> + </item> + <item> + <p> + Fix bug for hipe compiled code using + <c><<X/utf32>></c> binary construction that + could cause faulty result or even VM crash.</p> + <p> + On architectures other than x86_64, code need to be + recompiled to benefit from this fix.</p> + <p> + Own Id: OTP-14740</p> + </item> + <item> + <p> + Fixed bug in <c>erlang:garbage_collect/2</c> and + <c>erlang:check_process_code/3</c>, when called with + option <c>{async,ReqestId}</c>. Could cause VM crash or + heap corruption if <c>RequestId</c> was an immediate term + (like a pid, atom or small integer). Bug exists since + OTP-17.0.</p> + <p> + Own Id: OTP-14752</p> + </item> + <item> + <p>ERL_NIF_MINOR_VERSION wasn't bumped with the addition + of <c>enif_ioq_*</c>.</p> + <p> + Own Id: OTP-14779</p> + </item> + <item> + <p>Purging of loaded code that contained "fake literals" + (for example the magic reference obtained from + '<c>ets:new/2</c>') would crash the runtime system. + Corrected.</p> + <p> + Own Id: OTP-14791</p> + </item> + <item> + <p>Setting the size of the atom table to a number near + 2147483647 (using the '<c>+t</c>' option) would cause the + emulator to exit with a failure to allocate a huge amount + of memory. This has been corrected. Also the usage + message for the '<c>+t</c>' option has been corrected to + show the correct upper limit 2147483647 instead of 0.</p> + <p> + Own Id: OTP-14796</p> + </item> + <item> + <p>Fixed a bug that prevented registered process names + from being resolved in lcnt results.</p> + <p> + Own Id: OTP-14803</p> + </item> + <item> + <p>Formatting bugs were fixed in several HiPE debug + BIFs.</p> + <p> + Own Id: OTP-14804</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Binaries and some other data in crash dumps are now + encoded in base64 (instead of in hex), which will reduce + the size of crash dumps.</p> + <p>A few bugs in the handling of sub binaries in + <c>crashdump_viewer</c> have been fixed.</p> + <p> + Own Id: OTP-14686</p> + </item> + <item> + <p> + Micro optimization for send operations of messages to + other nodes. The local ack-message, which is otherwise + sent back from TPC/IP port driver to sending client + process, is now ignored earlier for distributed send + operations.</p> + <p> + Own Id: OTP-14689</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.1.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a bug in file closure on Unix; close(2) was + retried on EINTR which could cause a different (recently + opened) file to be closed as well.</p> + <p> + Own Id: OTP-14775</p> + </item> + <item> + <p> + A race-condition when tearing down a connection with + active node monitors could cause the runtime system to + crash.</p> + <p> + This bug was introduced in ERTS version 8.0 (OTP 19.0).</p> + <p> + Own Id: OTP-14781 Aux Id: OTP-13047 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.1.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Microstate accounting sometimes produced incorrect + results for dirty schedulers.</p> + <p> + Own Id: OTP-14707</p> + </item> + <item> + <p>Fixed a regression in <c>zlib:gunzip/1</c> that + prevented it from working when the decompressed size was + a perfect multiple of 16384. This regression was + introduced in 20.1.1</p> + <p> + Own Id: OTP-14730 Aux Id: ERL-507 </p> + </item> + <item> + <p>Fixed a memory corruption bug in + <c>enif_inspect_iovec</c>; writable binaries stayed + writable after entering the iovec.</p> + <p> + Own Id: OTP-14745</p> + </item> + <item> + <p>Fixed a crash in <c>enif_inspect_iovec</c> on + encountering empty binaries.</p> + <p> + Own Id: OTP-14750</p> + </item> + <item> + <p><c>zlib:deflateParams/3</c> will no longer return + <c>buf_error</c> when called after <c>zlib:deflate/2</c> + with zlib <c>1.2.11</c>.</p> + <p> + Own Id: OTP-14751</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.1.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Added zlib:set_controlling_process/2 to move a + zstream() between processes.</p> + <p> + Own Id: OTP-14672 Aux Id: ERL-494 </p> + </item> + <item> + <p> + Fix so that schedulers are bound correctly when the first + available cpu is not the first detected cpu. e.g. when + using "taskset -c X..Y" when X is not equal to 0.</p> + <p> + Own Id: OTP-14694</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.1.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed bug that could cause a VM crash when a corrupt + message is received on distribution channel from other + node.</p> + <p> + Own Id: OTP-14661 Aux Id: ERIERL-80 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.1.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>The new zlib module returned a data_error when + inflating concatenated streams, which was incompatible + with the old module's behavior of returning the + uncompressed data up to the end of the first stream.</p> + <p> + Own Id: OTP-14648</p> + </item> + <item> + <p>zlib:gunzip/1 will no longer stop at the end of the + first stream when decompressing concatenated gzip + files.</p> + <p> + Own Id: OTP-14649</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Changed <c>erlang:apply/2</c> to raise a <c>badarg</c> + exception if the second argument is not a proper list. + Previous behavior was a misleading <c>undef</c> + exception.</p> + <p> + Own Id: OTP-14490 Aux Id: ERL-432 </p> + </item> + <item> + <p>On macOS, <c>crypto</c> would crash if <c>observer</c> + had been started before <c>crypto</c>. On the beta for + macOS 10.13 (High Sierra), <c>crypto</c> would crash. + Both of those bugs have been fixed.</p> + <p> + Own Id: OTP-14499 Aux Id: ERL-251 ERL-439 </p> + </item> + <item> + <p> + Fixed bug in enif_whereis_pid/port that could cause heap + corruption in rare cases.</p> + <p> + Own Id: OTP-14523</p> + </item> + <item> + <p> + Fix so that trace messages generated when in a dirty nif + are flushed correctly when the dirty nif is done + executing.</p> + <p> + Own Id: OTP-14538</p> + </item> + <item> + <p> + Fix escape code handling when using ANSI color codes in + the shell.</p> + <p> + Own Id: OTP-14549 Aux Id: PR1536 </p> + </item> + <item> + <p> + Upgraded the ERTS internal PCRE library from version 8.40 + to version 8.41. See <url + href="http://pcre.org/original/changelog.txt">http://pcre.org/original/changelog.txt</url> + for information about changes made to PCRE. This library + implements major parts of the <seealso + marker="stdlib:re"><c>re</c></seealso> regular + expressions module.</p> + <p> + Own Id: OTP-14574</p> + </item> + <item> + <p> + Fixed a bug causing <c>statistics(runtime)</c> to produce + negative values and a bug in + <c>statistics(wall_clock)</c> causing it to produce + values one second too long.</p> + <p> + <c>statistics(runtime)</c> now also use + <c>getrusage()</c> as source when available preventing + the returned value from wrapping as frequent as before.</p> + <p> + Own Id: OTP-14597 Aux Id: ERL-465 </p> + </item> + <item> + <p> + Fixed small memory leak that could occur when sending to + a terminating port.</p> + <p> + Own Id: OTP-14609</p> + </item> + <item> + <p> + Fix bug causing VM crash when a module with + <c>-on_load</c> directive is loaded while + <c>erlang:trace(on_load, ...)</c> is enabled.</p> + <p> + Own Id: OTP-14612</p> + </item> + <item> + <p>A warning that the compiler may optimize away atoms + have been added to the documentation of + <c>list_to_existing_atom/1</c> and + <c>binary_to_existing_atom/2</c>.</p> + <p> + Own Id: OTP-14614 Aux Id: ERL-453 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Lock counting can now be fully toggled at runtime in + the lock counting emulator (<c>-emu_type lcnt</c>). + Everything is enabled by default to match the old + behavior, but specific categories can be toggled at will + with minimal runtime overhead when disabled. Refer to the + documentation on <c>lcnt:rt_mask/1</c> for details.</p> + <p> + Own Id: OTP-13170</p> + </item> + <item> + <p>The <c>zlib</c> module has been refactored and all its + operations will now yield appropriately, allowing them to + be used freely in concurrent applications.</p> <p>The + following functions have been deprecated, but will not + produce compiler warnings until OTP 21: + <c>zlib:adler32</c>, <c>zlib:crc32</c>, + <c>zlib:inflateChunk</c>, <c>zlib:getBufSize</c>, + <c>zlib:setBufSize</c>.</p> <p>The behavior of throwing + an error when a dictionary is required for decompression + has also been deprecated. Refer to the documentation on + <c>inflateSetDictionary/2</c> for details.</p> + <p> + Own Id: OTP-14185</p> + </item> + <item> + <p><c>lcnt:collect</c> and <c>lcnt:clear</c> will no + longer block all other threads in the runtime system.</p> + <p> + Own Id: OTP-14412</p> + </item> + <item> + <p>Add <c>erlang:iolist_to_iovec/1</c>, which converts an + iolist() to an erlang:iovec(), which suitable for use + with <c>enif_inspect_iovec</c>.</p> + <p> + Own Id: OTP-14520</p> + </item> + <item> + <p>When provided with bad arguments, the <c>zlib</c> + module will now raise named exceptions instead of just + <c>badarg</c>. For example, <c>not_initialized</c> when + using <c>zlib:inflate/2</c> with an uninitialized + stream.</p> + <p> + Own Id: OTP-14527</p> + </item> + <item> + <p> + <c>erlang:halt/2</c> allows any Unicode string as slogan + for the crash dump.</p> + <p> + Own Id: OTP-14553</p> + </item> + <item> + <p>Add new nif API functions for managing an I/O Queue. + The added functions are:</p> <list type="bulleted"> + <item><seealso marker="erl_nif#enif_ioq_create"> + <c>enif_ioq_create()</c></seealso></item> <item><seealso + marker="erl_nif#enif_ioq_destroy"> + <c>enif_ioq_destroy()</c></seealso></item> <item><seealso + marker="erl_nif#enif_ioq_enq_binary"> + <c>enif_ioq_enq_binary()</c></seealso></item> + <item><seealso marker="erl_nif#enif_ioq_enqv"> + <c>enif_ioq_enqv()</c></seealso></item> <item><seealso + marker="erl_nif#enif_ioq_deq"> + <c>enif_ioq_deq()</c></seealso></item> <item><seealso + marker="erl_nif#enif_ioq_peek"> + <c>enif_ioq_peek()</c></seealso></item> <item><seealso + marker="erl_nif#enif_inspect_iovec"> + <c>enif_inspect_iovec()</c></seealso></item> + <item><seealso marker="erl_nif#enif_free_iovec"> + <c>enif_free_iovec()</c></seealso></item> </list> + <p> + Own Id: OTP-14598</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.0.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed bug in <c>binary_to_term</c> and + <c>binary_to_atom</c> that could cause VM crash. + Typically happens when the last character of an UTF8 + string is in the range 128 to 255, but truncated to only + one byte. Bug exists in <c>binary_to_term</c> since ERTS + version 5.10.2 (OTP_R16B01) and <c>binary_to_atom</c> + since ERTS version 9.0 (OTP-20.0).</p> + <p> + Own Id: OTP-14590 Aux Id: ERL-474 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.0.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A timer internal bit-field used for storing scheduler id + was too small. As a result, VM internal timer data + structures could become inconsistent when using 1024 + schedulers on the system. Note that systems with less + than 1024 schedulers are not effected by this bug.</p> + <p> + This bug was introduced in ERTS version 7.0 (OTP 18.0).</p> + <p> + Own Id: OTP-14548 Aux Id: OTP-11997, ERL-468 </p> + </item> + <item> + <p> + Automatic cleanup of a BIF timer, when the owner process + terminated, could race with the timeout of the timer. + This could cause the VM internal data structures to + become inconsistent which very likely caused a VM crash.</p> + <p> + This bug was introduced in ERTS version 9.0 (OTP 20.0).</p> + <p> + Own Id: OTP-14554 Aux Id: OTP-14356, ERL-468 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.0.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Binary append operations did not check for overflow, + resulting in nonsensical results when huge binaries were + appended.</p> + <p> + Own Id: OTP-14524</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.0.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Added missing release notes for OTP-14491 ("performance + bug in pre-allocators") which was included in erts-9.0.1 + (OTP-20.0.1).</p> + <p> + Own Id: OTP-14494</p> + </item> + <item> + <p>Fixed a bug that prevented TCP sockets from being + closed properly on send timeouts.</p> + <p> + Own Id: OTP-14509</p> + </item> + <item> + <p> + Fixed bug in operator <c>bxor</c> causing erroneuos + result when one operand is a big <em>negative</em> + integer with the lowest <c>N*W</c> bits as zero and the + other operand not larger than <c>N*W</c> bits. <c>N</c> + is an integer of 1 or larger and <c>W</c> is 32 or 64 + depending on word size.</p> + <p> + Own Id: OTP-14514</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a bug in gen_tcp:send where it never returned when + repeatedly called on a remotely closed TCP socket.</p> + <p> + Own Id: OTP-13939 Aux Id: ERL-193 </p> + </item> + <item> + <p> + Fixed segfault that could happen during cleanup of + aborted erlang:port_command/3 calls. A port_command is + aborted if the port is closed at the same time as the + port_command was issued. This bug was introduced in + erts-8.0.</p> + <p> + Own Id: OTP-14481</p> + </item> + <item> + <p> + Fixed implementation of <c>statistics(wall_clock)</c> and + <c>statistics(runtime)</c> so that values do not + unnecessarily wrap due to the emulator. Note that the + values returned by <c>statistics(runtime)</c> may still + wrap due to limitations in the underlying functionality + provided by the operating system.</p> + <p> + Own Id: OTP-14484</p> + </item> + <item> + <p> + Fix performance bug in pre-allocators that could cause + them to permanently fall back on normal more expensive memory + allocation. Pre-allocators are used for quick allocation + of short lived meta data used by messages and other + scheduled tasks. Bug exists since OTP_R15B02. + [this release note was missing in erts-9.0.1]</p> + <p> + Own Id: OTP-14491</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 9.0</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fix various bugs regarding loading, upgrade and purge + of HiPE compiled code:</p> <list> <item>The native code + memory for a purged module was never deallocated.</item> + <item>Wrong functions could in some cases be called after + a module upgrade.</item> + <item><c>erlang:check_process_code</c> did not check for + recursive calls made from native code.</item> </list> + <p> + Own Id: OTP-13968</p> + </item> + <item> + <p> + Hipe optional LLVM backend does require LLVM version 3.9 + or later as older versions forced strong dependencies on + erts internals structures.</p> + <p> + Own Id: OTP-14238</p> + </item> + <item> + <p>When an exception such as '<c>throw(HugeTerm)</c>' was + caught, <c>HugeTerm</c> term would be kept in the process + until the next exception occurred, potentially increasing + the heap size for the process. That has been + corrected.</p> + <p> + Own Id: OTP-14255 Aux Id: OTP-14400, OTP-14401 </p> + </item> + <item> + <p> + Slogans in crash dumps have been extended to print more + complex terms.</p> + <p> + Own Id: OTP-14303</p> + </item> + <item> + <p> + Fixed bug when using <c>enif_inspect_binary</c> in + combination with <c>enif_copy</c>. In some circumstances + the inspected binary could be reallocated by the + <c>enif_copy</c> call when it shouldn't have been.</p> + <p> + Own Id: OTP-14304</p> + </item> + <item> + <p> + The address family <c>local</c> (AF_UNIX / AF_LOCAL) now + does not ensure zero termination of Linux Abstract + Addresses so they can use all bytes.</p> + <p> + Own Id: OTP-14305</p> + </item> + <item> + <p> + Use <c>-fno-PIE</c> for Gentoo Hardened and others that + don't accept linker flag <c>-no-pie</c>.</p> + <p> + Own Id: OTP-14307 Aux Id: PR-1379 </p> + </item> + <item> + <p> + Disable hipe for <c>ppc64le</c> architecture (little + endian) as it is not, and has never been, supported. It + was earlier equated with <c>ppc64</c> (big endian) which + lead to broken build without <c>--disable-hipe</c>.</p> + <p> + Own Id: OTP-14314 Aux Id: ERL-369, PR-1394 </p> + </item> + <item> + <p> + Fix 'epmd -kill' to return a failure exit status code if + epmd was not killed because of some error.</p> + <p> + Own Id: OTP-14324</p> + </item> + <item> + <p>Fixed the following dirty scheduler related bugs:</p> + <list> <item><p>the <c>+SDPcpu</c> command line argument + could cause the amount of dirty CPU schedulers to be set + to zero</p></item> + <item><p><c>erlang:system_flag(multi_scheduling, _)</c> + failed when only one normal scheduler was used together + with dirty scheduler support</p></item> </list> + <p> + Own Id: OTP-14335</p> + </item> + <item> + <p> + Fix erlexec to handle mismatch in sysconf and proc fs + when figuring out the cpu topology. This behaviour has + been seen when using docker together with + <c>--cpuset-cpus</c>.</p> + <p> + Own Id: OTP-14352</p> + </item> + <item> + <p> + Fixed memory segment cache used for multiblock carriers. + Huge (> 2GB) memory segments could cause a VM crash. + Creation of such huge memory segments used for multiblock + carriers is however very uncommon.</p> + <p> + Own Id: OTP-14360 Aux Id: ERL-401, PR-1417 </p> + </item> + <item> + <p> + Fix bug causing <c>code:is_module_native</c> to falsely + return true when <c>local</c> call trace is enabled for + the module.</p> + <p> + Own Id: OTP-14390</p> + </item> + <item> + <p> + Fix emulator crash when receive tracing on a + <c>trace_delivered</c> message.</p> + <p> + Own Id: OTP-14411</p> + </item> + <item> + <p> + Fix file:sendfile error handling on SunOS when a + connection is closed during transmission.</p> + <p> + Own Id: OTP-14424</p> + </item> + <item> + <p> + <c>escript</c> did not handle paths with spaces correct.</p> + <p> + Own Id: OTP-14433</p> + </item> + <item> + <p> + Fix erroneous lock check assertion when <c>wx</c> is run + on MacOS X.</p> + <p> + Own Id: OTP-14437 Aux Id: ERL-360 </p> + </item> + <item> + <p>Active-mode TCP sockets are now cleaned up properly on + send/shutdown errors.</p> + <p> + Own Id: OTP-14441 Aux Id: ERL-430 </p> + </item> + <item> + <p> + Fix compilation of hipe_mkliterals when the LIBS + configure variable had to be set.</p> + <p> + Own Id: OTP-14447</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Added <c>erlang:garbage_collect/2</c> that takes an + option list as the last argument that can be used to + control whether a minor or a major garbage collection is + to be done. Doing a minor collection only collects terms + that have recently died, but is cheaper than a major + collection.</p> + <p> + Own Id: OTP-11695</p> + </item> + <item> + <p> + Optimized test for tuples with an atom as first element.</p> + <p> + Own Id: OTP-12148</p> + </item> + <item> + <p> + Erlang literals are no longer copied during process to + process messaging.</p> + <p> + Own Id: OTP-13529</p> + </item> + <item> + <p>Add support in the <c>erl_nif</c> API for asynchronous + message notifications when sockets or other file + descriptors are ready to accept read or write operations. + The following functions have been added:</p> <list> + <item><p>enif_select</p></item> + <item><p>enif_monitor_process</p></item> + <item><p>enif_demonitor_process</p></item> + <item><p>enif_compare_monitors</p></item> + <item><p>enif_open_resource_type_x</p></item> </list> + <p> + Own Id: OTP-13684</p> + </item> + <item> + <p>There are two new guard BIFs '<c>floor/1</c>' and + '<c>ceil/1</c>'. They both return integers. In the + '<c>math</c>' module, there are two new BIFs with the + same names that return floating point values.</p> + <p> + Own Id: OTP-13692</p> + </item> + <item> + <p> + Remove deprecated <c>erlang:hash/2</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13827</p> + </item> + <item> + <p>Replaced usage of deprecated symbolic <seealso + marker="erts:erlang#type-time_unit"><c>time + unit</c></seealso> representations.</p> + <p> + Own Id: OTP-13831 Aux Id: OTP-13735 </p> + </item> + <item> + <p> + Added support in zlib for extraction of the inflation + dictionary.</p> + <p> + Own Id: OTP-13842</p> + </item> + <item> + <p> + The previously used purge strategy has been removed. The + optional purge strategy introduced in ERTS version 8.1 is + now the only strategy available.</p> + <p> + The new purge strategy is slightly incompatible with the + old strategy. Previously processes holding <c>fun</c>s + that referred to the module being purged either failed a + soft purge, or was killed during a hard purge. The new + strategy completely ignores <c>fun</c>s. If <c>fun</c>s + referring to the code being purged exist, and are used + after a purge, an exception will be raised upon usage. + That is, the behavior will be exactly the same as the + case when a <c>fun</c> is received by a process after the + purge.</p> + <p> + For more information see the documentation of <seealso + marker="erts:erlang#check_process_code/3"><c>erlang:check_process_code/3</c></seealso>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13844 Aux Id: OTP-13833 </p> + </item> + <item> + <p> + Dirty schedulers are now enabled by default when the + runtime system is built with SMP support.</p> + <p> + Own Id: OTP-13860</p> + </item> + <item> + <p> + Improved ETS lookup/insert/delete speed for large + <c>set</c>, <c>bag</c> and <c>duplicate_bag</c> by a + significant reduction of the hash load factor. This speed + improvement comes at the expense of less than one word + per table entry. Tables with less than 256 entries are + not affected at all.</p> + <p> + Own Id: OTP-13903</p> + </item> + <item> + <p> + The NIF library <c>reload</c> feature is not supported + anymore. It has been marked as deprecated since OTP R15B. + This means that you are only allowed to do one successful + call to <c>erlang:load_nif/2</c> for each module + instance. A second call to <c>erlang:load_nif/2</c> will + return <c>{error, {reload, _}}</c> even if the NIF + library implements the <c>reload</c> callback.</p> + <p> + Runtime upgrade of a NIF library is still supported by + using the Erlang module upgrade mechanics with a current + and an old module instance existing at the same time with + their corresponding NIF libraries.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13908</p> + </item> + <item> + <p> + Add <c>erlang:system_info(atom_count)</c> and + <c>erlang:system_info(atom_limit)</c> to provide a way to + retrieve the current and maximum number of atoms.</p> + <p> + Own Id: OTP-13976</p> + </item> + <item> + <p>The function <c>fmod/2</c> has been added to the + <c>math</c> module.</p> + <p> + Own Id: OTP-14000</p> + </item> + <item> + <p> + <c>erlang:load_nif/2</c> returns new error type + <c>notsup</c> when called for a HiPE compiled module, + which is not supported.</p> + <p> + Own Id: OTP-14002</p> + </item> + <item> + <p> + Add driver and nif lock instrumentation to lcnt</p> + <p> + Own Id: OTP-14069</p> + </item> + <item> + <p> + Reduce memory pressure by converting sub-binaries to + heap-binaries when possible. This is done during garbage + collection.</p> + <p> + Own Id: OTP-14149</p> + </item> + <item> + <p> + Dirty schedulers are now enabled and supported on Erlang + runtime systems with SMP support.</p> + <p> + Besides support for dirty NIFs also support for dirty + BIFs and dirty garbage collection have been introduced. + All garbage collections that potentially will take a long + time to complete are now performed on dirty schedulers if + enabled.</p> + <p> + <seealso + marker="erts:erlang#statistics/1"><c>erlang:statistics/1</c></seealso> + with arguments inspecting scheduler and run queue states + have been changed due to the dirty scheduler support. + Code using this functionality may have to be rewritten + taking these incompatibilities into consideration. + Examples of such uses are calls to <seealso + marker="erts:erlang#statistics_scheduler_wall_time"><c>erlang:statistics(scheduler_wall_time)</c></seealso>, + <seealso + marker="erts:erlang#statistics_total_run_queue_lengths"><c>statistics(total_run_queue_lengths)</c></seealso>, + <seealso + marker="erts:erlang#statistics_total_active_tasks"><c>statistics(total_active_tasks)</c></seealso>, + etc.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14152</p> + </item> + <item> + <p>Atoms may now contain arbitrary Unicode + characters.</p> + <p> + Own Id: OTP-14178</p> + </item> + <item> + <p> + Introduce an event manager in Erlang to handle OS + signals. A subset of OS signals may be subscribed to and + those are described in the Kernel application.</p> + <p> + Own Id: OTP-14186</p> + </item> + <item> + <p> + The <c>escript</c> program now handles symbolic links to + escripts.</p> + <p> + This is useful for standalone systems with + <c>escript</c>s residing on a bin directory not included + in the execution path (as it may cause their <c>erl</c> + program(s) to override the desired one). Instead the + <c>escript</c>s can be referred to via symbolic links + from a bin directory in the path.</p> + <p> + Own Id: OTP-14201 Aux Id: PR-1293 </p> + </item> + <item> + <p> + All uses of the magic binary kludge has been replaced by + uses of erlang references.</p> + <p> + A magic binary was presented as an empty binary, but + actually referred other data internally in the Erlang VM. + Since they were presented as empty binaries, different + magic binaries compared as equal, and also lost their + internal data when passed out of an erlang node.</p> + <p> + The new usage of references has not got any of these + strange semantic issues, and the usage of these + references has been optimized to give the same + performance benefits as well as memory usage benefits as + magic binaries had.</p> + <p> + A couple of examples of previous uses of magic binaries + are match specifications and NIF resources.</p> + <p> + Own Id: OTP-14205</p> + </item> + <item> + <p> + The non-smp emulators have been deprecated and are + scheduled for removal in OTP-21.</p> + <p> + In preparation for this, the threaded non-smp emulator is + no longer built by default and has to be enabled using + the --enable-plain-emulator to configure.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14272</p> + </item> + <item> + <p> + Allow HiPE to run on VM built with + <c>--enable-m32-build</c>.</p> + <p> + Own Id: OTP-14330 Aux Id: PR-1397 </p> + </item> + <item> + <p> + Upgraded the OTP internal PCRE library from version 8.33 + to version 8.40. This library is used for implementation + of the <seealso marker="stdlib:re"><c>re</c></seealso> + regular expressions module.</p> + <p> + Besides various bug fixes, the new version allows for + better stack protection. In order to utilize this + feature, the stack size of normal scheduler threads is + now by default set to 128 kilo words on all platforms. + The stack size of normal scheduler threads can be set + upon system start by passing the <seealso + marker="erts:erl#sched_thread_stack_size"><c>+sss</c></seealso> + command line argument to the <seealso + marker="erts:erl"><c>erl</c></seealso> command.</p> + <p> + See <url + href="http://pcre.org/original/changelog.txt">http://pcre.org/original/changelog.txt</url> + for information about changes made to PCRE between the + versions 8.33 and 8.40.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-14331 Aux Id: ERL-208 </p> + </item> + <item> + <p> + Remove generation of atoms in old latin1 external format + in the distribution between erlang nodes, + <c>erl_interface</c>, and <c>jinterface</c>. The new utf8 + format for atoms was introduced in OTP R16. An OTP 20 + node can therefore not connect to nodes older than R16.</p> + <p> + Atoms that can be encoded using latin1 are still encoded + by <c>term_to_binary()</c> using latin1 encoding. Note + that all atoms will by default be encoded using utf8 in a + future Erlang/OTP release. For more information see the + documentation of <seealso + marker="erts:erlang#term_to_binary/2"><c>erlang:term_to_binary/2</c></seealso>.</p> + <p> + Own Id: OTP-14337</p> + </item> + <item> + <p> + Added function <c>re:version/0</c> which returns + information about the OTP internal PCRE version used for + implementation of the <c>re</c> module.</p> + <p> + Own Id: OTP-14347 Aux Id: PR-1412 </p> + </item> + <item> + <p> + Added new debug bif <c>erlang:list_to_port/1</c>.</p> + <p> + Own Id: OTP-14348</p> + </item> + <item> + <p> + Various improvements of timer management internally in + the VM. These improvements both reduced memory + consumption of timer wheels as well as reduce the amount + of work that has to be performed in order to handle + timers.</p> + <p> + Own Id: OTP-14356</p> + </item> + <item> + <p> Sockets can now be bound to device (SO_BINDTODEVICE) + on platforms where it is supported. </p> <p> This has + been implemented e.g to support VRF-Lite under Linux; see + <url + href="https://www.kernel.org/doc/Documentation/networking/vrf.txt"> + VRF </url>, and GitHub pull request <url + href="https://github.com/erlang/otp/pull/1326">#1326</url>. + </p> + <p> + Own Id: OTP-14357 Aux Id: PR-1326 </p> + </item> + <item> + <p>Added the following <seealso + marker="erl"><c>erl</c></seealso> command line arguments + with which you can set suggested stack for dirty + schedulers:</p> <taglist> <tag><seealso + marker="erl#dcpu_sched_thread_stack_size"><c>+sssdcpu</c></seealso></tag> + <item><p>for dirty CPU schedulers</p></item> + <tag><seealso + marker="erl#dio_sched_thread_stack_size"><c>+sssdio</c></seealso></tag> + <item><p>for dirty IO schedulers</p></item> </taglist> + <p>The default suggested stack size for dirty schedulers + is 40 kilo words.</p> + <p> + Own Id: OTP-14380</p> + </item> + <item> + <p> + Changed erts startup program name, argv 0, to use the + environment variable <c>ESCRIPT_NAME</c> so that + <c>erlc</c>, <c>dialyzer</c>, <c>typer</c>, + <c>ct_run</c>, or the escript name can be seen with + external programs, such as ps and htop (depending on + options), on unix.</p> + <p> + Own Id: OTP-14381</p> + </item> + <item> + <p> + Improvements of <c>escript</c> documentation.</p> + <p> + Own Id: OTP-14384 Aux Id: OTP-14201 </p> + </item> + <item> + <p> + Add function <c>enif_hash</c> for NIFs to calculate hash + values of arbitrary terms.</p> + <p> + Own Id: OTP-14385 Aux Id: PR-1413 </p> + </item> + <item> + <p>'<c>./configure --enable-lock-counter</c>' will + enabling building of an additional emulator that has + support for lock counting. (The option previously + existed, but would turn on lock counting in the default + emulator being built.) To start the lock-counting + emulator, use '<c>erl -emu_type lcnt</c>'.</p> + <p>On Windows, <c>erl</c> recognized the undocumented + option <c>-debug</c> for starting a debug-compiled + emulator. That option has been removed. Use '<c>erl + -emu_type debug</c>' instead.</p> + <p> + Own Id: OTP-14407</p> + </item> + <item> + <p> + Warnings have been added to the relevant documentation + about not using un-secure distributed nodes in exposed + environments.</p> + <p> + Own Id: OTP-14425</p> + </item> + <item> + <p> + Improvement of the documentation of the environment + variable <c>ERL_CRASH_DUMP_SECONDS</c> as well as the + default behavior when it is not set.</p> + <p> + Own Id: OTP-14434</p> + </item> + <item> + <p> + Enabled off-heap message queue for some system processes + that might receive large amounts of messages.</p> + <p> + Own Id: OTP-14438</p> + </item> + <item> + <p>ETS lock indexes have been replaced with the table + name in LCNT results.</p> + <p> + Own Id: OTP-14442 Aux Id: ERIERL-22 </p> + </item> + <item> + <p> + Introduced the new functions <seealso + marker="erl_nif#enif_whereis_pid"><c>enif_whereis_pid()</c></seealso> + and <seealso + marker="erl_nif#enif_whereis_port"><c>enif_whereis_port()</c></seealso>.</p> + <p> + Own Id: OTP-14453 Aux Id: PR-1400 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.5.6</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed small memory leak that could occur when sending to + a terminating port.</p> + <p> + Own Id: OTP-14609 Aux Id: ERIERL-238 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.5.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a race condition in the inet driver that could + cause receive to hang when the emulator was compiled with + gcc 8.</p> + <p> + Own Id: OTP-15158 Aux Id: ERL-654 </p> + </item> + <item> + <p> + Fixed a bug causing some Erlang references to be + inconsistently ordered. This could for example cause + failure to look up certain elements with references as + keys in search data structures. This bug was introduced + in R13B02.</p> + <p> + Thanks to Simon Cornish for finding the bug and supplying + a fix.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-15225</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.5.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a bug in file closure on Unix; close(2) was + retried on EINTR which could cause a different (recently + opened) file to be closed as well.</p> + <p> + Own Id: OTP-14775</p> + </item> + <item> + <p> + A race-condition when tearing down a connection with + active node monitors could cause the runtime system to + crash.</p> + <p> + This bug was introduced in ERTS version 8.0 (OTP 19.0).</p> + <p> + Own Id: OTP-14781 Aux Id: OTP-13047 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.5.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A timer internal bit-field used for storing scheduler id + was too small. As a result, VM internal timer data + structures could become inconsistent when using 1024 + schedulers on the system. Note that systems with less + than 1024 schedulers are not effected by this bug.</p> + <p> + This bug was introduced in ERTS version 7.0 (OTP 18.0).</p> + <p> + Own Id: OTP-14548 Aux Id: OTP-11997, ERL-468 </p> + </item> + <item> + <p> + Fixed bug in <c>binary_to_term</c> and + <c>binary_to_atom</c> that could cause VM crash. + Typically happens when the last character of an UTF8 + string is in the range 128 to 255, but truncated to only + one byte. Bug exists in <c>binary_to_term</c> since ERTS + version 5.10.2 (OTP_R16B01) and <c>binary_to_atom</c> + since ERTS version 9.0 (OTP-20.0).</p> + <p> + Own Id: OTP-14590 Aux Id: ERL-474 </p> + </item> + <item> + <p> + Fix bug causing VM crash when a module with + <c>-on_load</c> directive is loaded while + <c>erlang:trace(on_load, ...)</c> is enabled.</p> + <p> + Own Id: OTP-14612</p> + </item> + <item> + <p> + Fixed bug that could cause a VM crash when a corrupt + message is received on distribution channel from other + node.</p> + <p> + Own Id: OTP-14661 Aux Id: ERIERL-80 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.5.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix performance bug in pre-allocators that could cause + them to permanently fall back on normal more expensive + memory allocation. Pre-allocators are used for quick + allocation of short lived meta data used by messages and + other scheduled tasks. Bug exists since OTP_R15B02.</p> + <p> + Own Id: OTP-14491</p> + </item> + <item> + <p>Fixed a bug that prevented TCP sockets from being + closed properly on send timeouts.</p> + <p> + Own Id: OTP-14509</p> + </item> + <item> + <p> + Fixed bug in operator <c>bxor</c> causing erroneuos + result when one operand is a big <em>negative</em> + integer with the lowest <c>N*W</c> bits as zero and the + other operand not larger than <c>N*W</c> bits. <c>N</c> + is an integer of 1 or larger and <c>W</c> is 32 or 64 + depending on word size.</p> + <p> + Own Id: OTP-14514</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.5.1</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a bug in gen_tcp:send where it never returned when + repeatedly called on a remotely closed TCP socket.</p> + <p> + Own Id: OTP-13939 Aux Id: ERL-193 </p> + </item> + <item> + <p> + Fixed segfault that could happen during cleanup of + aborted erlang:port_command/3 calls. A port_command is + aborted if the port is closed at the same time as the + port_command was issued. This bug was introduced in + erts-8.0.</p> + <p> + Own Id: OTP-14481</p> + </item> + <item> + <p> + Fixed implementation of <c>statistics(wall_clock)</c> and + <c>statistics(runtime)</c> so that values do not + unnecessarily wrap due to the emulator. Note that the + values returned by <c>statistics(runtime)</c> may still + wrap due to limitations in the underlying functionality + provided by the operating system.</p> + <p> + Own Id: OTP-14484</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Active-mode TCP sockets are now cleaned up properly on + send/shutdown errors.</p> + <p> + Own Id: OTP-14441 Aux Id: ERL-430 </p> + </item> + <item> + <p> + A code purge operation could under certain circumstances + expand the size of hibernated processes.</p> + <p> + Own Id: OTP-14444 Aux Id: ERIERL-24 </p> + </item> + <item> + <p> + Fix so that the ERL_ZZ_SIGTERM_KILL introduced in + erts-8.3.4 works.</p> + <p> + Own Id: OTP-14451</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Add option to make SIGTERM trigger the OS default + behaviour instead of doing a gracefull shutdown. To + activate this bahviour the environment variable + ERL_ZZ_SIGTERM_KILL should be set to "true". This option + only works in OTP 19 as OTP 20 will have a different way + to deal with SIGTERM.</p> + <p> + Own Id: OTP-14418 Aux Id: ERIERL-15 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed memory segment cache used for multiblock carriers. + Huge (> 2GB) memory segments could cause a VM crash. + Creation of such huge memory segments used for multiblock + carriers is however very uncommon.</p> + <p> + Own Id: OTP-14360 Aux Id: ERL-401, PR-1417 </p> + </item> + <item> + <p> + Fix release note for OTP-14290 in ERTS version 8.3.1. It + was erroneously placed under "Known Bugs and Problems".</p> + <p> + Own Id: OTP-14363 Aux Id: OTP-14290 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The <c>+Bi</c> command line argument of <c>erl</c> + erroneously caused <c>SIGTERM</c> to be ignored by the VM + as well as of all its child processes. This bug was + introduced in erts version 8.3.</p> + <p> + Own Id: OTP-14358 Aux Id: OTP-14085 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Invoking <c>init:stop/0</c> via the SIGTERM signal, in a + non-SMP BEAM, could cause BEAM to terminate with fatal + error. This has now been fixed and the BEAM will + terminate normally when SIGTERM is received.</p> + <p> + Own Id: OTP-14290</p> + </item> + <item> + <p> + Trying to open a directory with file:read_file/1 on Unix + leaked a file descriptor. This bug has now been fixed.</p> + <p> + Own Id: OTP-14308 Aux Id: ERL-383 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Fixed a number of bugs that caused faulty stack-traces + to be generated. The faulty stack traces were generated + either when applying the following functions or tracing + the following functions:</p> <list> + <item><c>erlang:error/1</c></item> + <item><c>erlang:error/2</c></item> + <item><c>erlang:exit/1</c></item> + <item><c>erlang:throw/1</c></item> </list> + <p> + Own Id: OTP-14055</p> + </item> + <item> + <p> + Corrected documentation about memory footprint for maps.</p> + <p> + Own Id: OTP-14118</p> + </item> + <item> + <p> + Fix <c>process_info(Pid, current_stacktrace)</c> to use + stack depth limit set by + <c>system_flag(backtrace_depth)</c>. The old behavior was + a hard coded depth limit of 8.</p> + <p> + Own Id: OTP-14119 Aux Id: PR-1263 </p> + </item> + <item> + <p> + A process calling <seealso + marker="erlang#system_flag_multi_scheduling"><c>erlang:system_flag(multi_scheduling, + block)</c></seealso> could end up hanging forever in the + call.</p> + <p> + Own Id: OTP-14121</p> + </item> + <item> + <p>Dirty scheduler bug fixes:</p> <list> <item><p>Fixed + call time tracing of process being scheduled on dirty + scheduler.</p></item> <item><p>GC info from dirty + schedulers.</p></item> <item><p>Multi scheduling block + with dirty schedulers could crash the runtime + system.</p></item> <item><p>Process structures could be + removed prematurely.</p></item> <item><p>GC on dirty + scheduler could crash the runtime system.</p></item> + <item><p>Termination of a process executing on a dirty + scheduler could cause a runtime system crash.</p></item> + </list> + <p> + Own Id: OTP-14122</p> + </item> + <item> + <p> + Fixed crash that occurred when writing timer data to a + crash dump.</p> + <p> + Own Id: OTP-14133</p> + </item> + <item> + <p> + A literal area could be removed while still referred from + processes.</p> + <p> + Own Id: OTP-14134</p> + </item> + <item> + <p> + Fixed a bug in the garbage collector that could crash the + runtime system.</p> + <p> + Own Id: OTP-14135</p> + </item> + <item> + <p> + Fixed a bug in call-time trace for NIFs which caused + tracing to erroneously be started multiple times for one + call.</p> + <p> + Own Id: OTP-14136</p> + </item> + <item> + <p> + Remove a debug printout and an unnecessary garbage + collection when handling exceptions in hipe compiled + code.</p> + <p> + Own Id: OTP-14153</p> + </item> + <item> + <p> + Fix bug in tracing of garbage collection that could cause + VM crash. Bug exists since OTP 19.0.</p> + <p> + Own Id: OTP-14154</p> + </item> + <item> + <p> + Fix bug in <c>binary_to_term</c> for binaries created by + <c>term_to_binary </c> with option <c>compressed</c>. The + bug can cause <c>badarg</c> exception for a valid binary + when Erlang VM is linked against a <c>zlib</c> library of + version 1.2.9 or newer. Bug exists since OTP 17.0.</p> + <p> + Own Id: OTP-14159 Aux Id: ERL-340 </p> + </item> + <item> + <p> + Fix suspension of schedulers when generating a crashdump.</p> + <p> + Own Id: OTP-14164</p> + </item> + <item> + <p>NIF resources was not handled in a thread-safe manner + in the runtime system without SMP support.</p> + <p>As a consequence of this fix, the following driver + functions are now thread-safe also in the runtime system + without SMP support:</p> <list> + <item><p><c>driver_free_binary()</c></p></item> + <item><p><c>driver_realloc_binary()</c></p></item> + <item><p><c>driver_binary_get_refc()</c></p></item> + <item><p><c>driver_binary_inc_refc()</c></p></item> + <item><p><c>driver_binary_dec_refc()</c></p></item> + </list> + <p> + Own Id: OTP-14202</p> + </item> + <item> + <p> + Fix <c>erlang:round/1</c> for large floating point + numbers with an odd absolute value between <c>(1 bsl + 52)</c> and <c>(1 bsl 53)</c>. The result was falsely + calculated as the next higher even number even though all + integer values up to <c>(1 bsl 53)</c> can be represented + as floats with full precision.</p> + <p> + Own Id: OTP-14227</p> + </item> + <item> + <p> + Add size of literals to module code size in crash dump + and <c>(l)oaded</c> command in break menu like it used to + be before OTP-19.0.</p> + <p> + Own Id: OTP-14228</p> + </item> + <item> + <p> + Fix potential bug in <c>enif_send</c> when called without + a process context and with argument <c>msg_env</c> as + <c>NULL</c>.</p> + <p> + Own Id: OTP-14229</p> + </item> + <item> + <p> + Fix bug where passing an appendable binary to + <c>erlang:port_control()</c> could crash the emulator.</p> + <p> + Own Id: OTP-14231</p> + </item> + <item> + <p> + Receive expressions with timeout in the Erlang shell + could cause a VM crash.</p> + <p> + Own Id: OTP-14241 Aux Id: ERL-365 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + A received SIGTERM signal to beam will generate a + <c>'stop'</c> message to the <c>init</c> process and + terminate the Erlang VM nicely. This is equivalent to + calling <c>init:stop/0</c>.</p> + <p> + Own Id: OTP-14085</p> + </item> + <item> + <p> + Workaround for buggy Android implementation of + <c>PTHREAD_STACK_MIN</c> causing build of runtime system + to crash on undeclared <c>PAGE_SIZE</c>.</p> + <p> + Own Id: OTP-14165 Aux Id: ERL-319 </p> + </item> + <item> + <p> + Add configure option --without-thread-names that removes + the naming of individual emulator threads.</p> + <p> + Own Id: OTP-14234</p> + </item> + <item> + <p> + Add warning in documentation of <c>zlib:deflateInit/6</c> + about option <c>WindowsBits</c> values 8 and -8.</p> + <p> + Own Id: OTP-14254 Aux Id: ERL-362 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.2.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix bug in <c>binary_to_term</c> for binaries created by + <c>term_to_binary </c> with option <c>compressed</c>. The + bug can cause <c>badarg</c> exception for a valid binary + when Erlang VM is linked against a <c>zlib</c> library of + version 1.2.9 or newer. Bug exists since OTP 17.0.</p> + <p> + Own Id: OTP-14159 Aux Id: ERL-340 </p> + </item> + <item> + <p> + The driver efile_drv when opening a file now use fstat() + on the open file instead of stat() before opening, if + fstat() exists. This avoids a race when the file happens + to change between stat() and open().</p> + <p> + Own Id: OTP-14184 Aux Id: seq-13266 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.2.1</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix a quite rare bug causing VM crash during code loading + and the use of export funs (fun M:F/A) of not yet loaded + modules. Requires a very specfic timing of concurrent + scheduler threads. Has been seen on ARM but can probably + also occure on other architectures. Bug has existed since + OTP R16.</p> + <p> + Own Id: OTP-14144 Aux Id: seq13242 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed <c>configure</c> failures on MacOSX. Most important + <c>clock_gettime()</c> was detected when building for + MacOSX - El Capitan using XCode 8 despite it is not + available until MacOSX - Sierra.</p> + <p> + Own Id: OTP-13904 Aux Id: ERL-256 </p> + </item> + <item> + <p> + <c>code:add_pathsa/1</c> and command line option + <c>-pa</c> both revert the given list of directories when + adding it at the beginning of the code path. This is now + documented.</p> + <p> + Own Id: OTP-13920 Aux Id: ERL-267 </p> + </item> + <item> + <p> + Fix a compilation error of erts in OpenBSD related to the + usage of the __errno variable.</p> + <p> + Own Id: OTP-13927</p> + </item> + <item> + <p> + Fixed so that when enabling tracing on a process that had + an invalid tracer associated with it, the new tracer + overwrites the old tracer. Before this fix, calling + erlang:trace/3 would behave as if the tracer was still + alive and not apply the new trace.</p> + <p> + This fault was introduced in ERTS 8.0.</p> + <p> + Own Id: OTP-13928</p> + </item> + <item> + <p> + Fix parsing of <c>-profile_boot 'true' | 'false'</c></p> + <p> + Own Id: OTP-13955 Aux Id: ERL-280 </p> + </item> + <item> + <p> + A slight improvement of <c>erlang:get_stacktrace/0</c> + for exceptions raised in hipe compiled code. Beam + compiled functions in such stack trace was earlier + replaced by some unrelated function. They are now instead + omitted. This is an attempt to reduce the confusion in + the absence of a complete and correct stack trace for + mixed beam and hipe functions.</p> + <p> + Own Id: OTP-13992</p> + </item> + <item> + <p> Correct type declaration of match specification head. + </p> + <p> + Own Id: OTP-13996</p> + </item> + <item> + <p> + HiPE code loading failed for x86_64 if gcc was configured + with <c>--enable-default-pie</c>. Fixed by disabling PIE, + if needed for HiPE, when building the VM.</p> + <p> + Own Id: OTP-14031 Aux Id: ERL-294, PR-1239 </p> + </item> + <item> + <p> + Faulty arguments could be presented on exception from a + NIF that had rescheduled itself using + <c>enif_schedule_nif()</c>.</p> + <p> + Own Id: OTP-14048</p> + </item> + <item> + <p> + The runtime system could crash if a garbage collection on + a process was performed immediately after a NIF had been + rescheduled using <c>enif_schedule_nif()</c>.</p> + <p> + Own Id: OTP-14049</p> + </item> + <item> + <p> + A reference to purged code could be left undetected by + the purge operation if a process just had rescheduled a + NIF call using <c>enif_schedule_nif()</c> when the + process was checked. This could cause a runtime system + crash.</p> + <p> + Own Id: OTP-14050</p> + </item> + <item> + <p>Fixed a number of dirty scheduler related bugs:</p> + <list> <item><p>Process priority was not handled correct + when scheduling on a dirty scheduler.</p></item> + <item><p>The runtime system could crash when an exit + signal with a compound exit reason was sent to a process + executing on a dirty scheduler.</p></item> <item><p>The + runtime system crashed when call tracing a process + executing on a dirty scheduler.</p></item> <item><p>A + code purge operation could end up hanging forever when a + process executed on a dirty scheduler</p></item> </list> + <p> + Own Id: OTP-14051</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Fix minor soft purge race bug that could incorrectly + trigger code_server to load new code for the module if + the soft purge failed and no current version of the + module existed.</p> + <p> + Own Id: OTP-13925</p> + </item> + <item> + <p> + To ease troubleshooting, <c>erlang:load_nif/2</c> now + includes the return value from a failed call to + load/reload/upgrade in the text part of the error tuple. + The <c>crypto</c> NIF makes use of this feature by + returning the source line where/if the initialization + fails.</p> + <p> + Own Id: OTP-13951</p> + </item> + <item> + <p> + New environment variable <c>ERL_CRASH_DUMP_BYTES</c> can + be used to limit the size of crash dumps. If the limit is + reached, crash dump generation is aborted and the + generated file will be truncated.</p> + <p> + Own Id: OTP-14046</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.1.1.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A code purge operation could under certain circumstances + expand the size of hibernated processes.</p> + <p> + Own Id: OTP-14444 Aux Id: ERIERL-24 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.1.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The emulator got a dynamic library dependency towards + libsctp, which on Linux was not intended since the + emulator there loads and resolves the needed sctp + functions in runtime. This has been fixed and a configure + switch --enable-sctp=lib has been added for those who + want such a library dependency.</p> + <p> + Own Id: OTP-13956 Aux Id: ERL-262, ERL-133 </p> + </item> + <item> + <p> + Fix SIGUSR1 crashdump generation</p> + <p> + Do not generate a core when a crashdump is asked for.</p> + <p> + Own Id: OTP-13997</p> + </item> + <item> + <p>The new functions in <c>code</c> that allows loading + of many modules at once had a performance problem. While + executing a helper function in the <c>erl_prim_loader</c> + process, garbage messages were produced. The garbages + messages were ignored and ultimately discarded, but there + would be a negative impact on performance and memory + usage. The number of garbage message depended on both the + number of modules to be loaded and the length of the code + path.</p> + <p>The functions affected of this problem were: + <c>atomic_load/1</c>, <c>ensure_modules_loaded/1</c>, and + <c>prepare_loading/1</c>.</p> + <p> + Own Id: OTP-14009</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix bug for calls from hipe code to BIFs that disable GC + while yielding. Has been causing Dialyzer crashes on ARM + (and presumably all other non-intel platforms).</p> + <p> + Own Id: OTP-13724 Aux Id: PR-1116 </p> + </item> + <item> + <p> + Fix a bug where changing the current working directory of + the VM would not change the current working directory of + programs spawned using <c>erlang:open_port({spawn,""}, + ...)</c>.</p> + <p> + Own Id: OTP-13733 Aux Id: ERL-175 </p> + </item> + <item> + <p> + Fix a bug where disabling tracing from a process that had + return_to tracing enabled and was tracing on + <c>erlang:trace/3</c> would cause a segmentation fault.</p> + <p> + Own Id: OTP-13734</p> + </item> + <item> + <p> + Update all erts documentation to use simpler English, use + consistent terminology and be easier to navigate.</p> + <p> + Own Id: OTP-13740</p> + </item> + <item> + <p> + Add dirty schedulers to the microstate accounting + statistics.</p> + <p> + Own Id: OTP-13744</p> + </item> + <item> + <p> + Fixed dirty scheduler build support on 32-bit windows.</p> + <p> + Own Id: OTP-13759</p> + </item> + <item> + <p> + inet:getstat(Socket) on an SCTP socket returned 0 for + send stats. This bug has now been corrected. Reported by + systra as issue ERL-102 on bugs.erlang.org.</p> + <p> + Own Id: OTP-13773 Aux Id: ERL-102 </p> + </item> + <item> + <p> + AF_UNSPEC and unknown address families were misread by + UDP receive in prim_inet resulting in an exception. This + bug has now been corrected.</p> + <p> + Own Id: OTP-13775</p> + </item> + <item> + <p> + Sweep HiPE stack for literals during code purge.</p> + <p> + Own Id: OTP-13777 Aux Id: PR-1122 </p> + </item> + <item> + <p> + Fix bug in run_erl for OpenBSD that could cause it on + rare occations to exit without starting the program (erl) + at all.</p> + <p> + Own Id: OTP-13795</p> + </item> + <item> + <p> + Update build scripts to not make assumtions about where + env, cp and perl are located.</p> + <p> + Own Id: OTP-13800</p> + </item> + <item> + <p> + Fixed a bug where init:stop could deadlock if a process + with infinite shutdown timeout (e.g. a supervisor) + attempted to load code while terminating.</p> + <p> + Own Id: OTP-13802</p> + </item> + <item> + <p> + Fixed a segmentation fault on sparc CPUs when free'ing a + tracer module's state.</p> + <p> + Own Id: OTP-13803</p> + </item> + <item> + <p> + <c>fun</c>s was not properly handled during purge of a + module. This could cause a crash of the VM after a purge + of a module.</p> + <p> + Own Id: OTP-13809</p> + </item> + <item> + <p> + Fixed a memory leak when the process monitoring a port + crashed.</p> + <p> + Own Id: OTP-13818</p> + </item> + <item> + <p> + Fixed multiple dirty scheduler related tracing bugs.</p> + <p> + Own Id: OTP-13822</p> + </item> + <item> + <p> + Fix error handling in beam code runtime loader for a + number of cases when index and size fields got corrupted + (negative) values.</p> + <p> + Own Id: OTP-13848 Aux Id: ERL-216 </p> + </item> + <item> + <p> + Minor fix of dirty scheduler implementation.</p> + <p> + Own Id: OTP-13852</p> </item> <item> <p> @@ -58,6 +3760,14 @@ Own Id: OTP-13866</p> </item> <item> + <p> + Fix a rare race condition in <c>erlang:open_port({spawn, + ""}, ...)</c> that would result in the erl_child_setup + program aborting and cause the emulator to exit.</p> + <p> + Own Id: OTP-13868</p> + </item> + <item> <p>Driver and NIF operations accessing processes or ports could cause an emulator crash when used from non-scheduler threads. Those operations are:</p> <list> @@ -72,13 +3782,965 @@ </item> <item> <p> - Fix bug in <c>binary_to_term</c> for binaries created by - <c>term_to_binary </c> with option <c>compressed</c>. The - bug can cause <c>badarg</c> exception for a valid binary - when Erlang VM is linked against a <c>zlib</c> library of - version 1.2.9 or newer. Bug exists since OTP 17.0.</p> + Fix start scripts generation dependency in Makefile</p> <p> - Own Id: OTP-14159 Aux Id: ERL-340 </p> + Own Id: OTP-13871 Aux Id: ERL-241 </p> + </item> + <item> + <p> + The VM could crash if <c>erlang:get_stacktrace()</c> was + called after a rescheduled NIF had thrown an exception.</p> + <p> + Own Id: OTP-13877</p> + </item> + <item> + <p>Calling <c>code:delete/1</c> before a loading a module + with an on_load function, the old code would be + overwritten, causing a memory or a crash if NIFs were + involved. (Thanks to vans163 for reporting this bug.)</p> + <p> + Own Id: OTP-13893 Aux Id: ERL-240 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Improved accuracy of timeouts on MacOS X. This by setting + premature timeouts followed by a short actual timeout + during scheduler wait.</p> + <p> + Own Id: OTP-13698</p> + </item> + <item> + <p>Added the following symbolic time unit representations + to the <seealso + marker="erlang#type-time_unit"><c>erlang:time_unit()</c></seealso> + type:</p> <list> <item><c>second</c></item> + <item><c>millisecond</c></item> + <item><c>microsecond</c></item> + <item><c>nanosecond</c></item> </list> <p>The following + symbolic time unit representations are now + <em>deprecated</em>, but still part of the + <c>erlang:time_unit()</c> type:</p> <list> + <item><c>seconds</c></item> + <item><c>milli_seconds</c></item> + <item><c>micro_seconds</c></item> + <item><c>nano_seconds</c></item> </list> + <p> + Own Id: OTP-13735</p> + </item> + <item> + <p> + Fix maps hashing entropy of maps with maps keys.</p> + <p> + Own Id: OTP-13763 Aux Id: ERL-199 </p> + </item> + <item> + <p> + Improved dirty scheduler support. A purge of a module can + now be performed without having to wait for completion of + all ongoing dirty NIF calls.</p> + <p> + Note that when enabling support for dirty schedulers, a + new purge strategy will as of ERTS version 8.1 be + enabled. This new strategy is not fully backwards + compatible with the strategy used by default. For more + information see the documentation of <seealso + marker="erts:erlang#check_process_code/3"><c>erlang:check_process_code/3</c></seealso>.</p> + <p> + Own Id: OTP-13808 Aux Id: OTP-13833 </p> + </item> + <item> + <p> + A new purge strategy has been introduced. The new + strategy will by default be disabled during the OTP 19 + release, but will be the only strategy available as of + the OTP 20 release.</p> + <p> + The new strategy is slightly incompatible with the + strategy being used by default in OTP 19. Using the + default strategy, processes holding <c>fun</c>s that + refer to the module being purged either fail a soft + purge, or will be killed during a hard purge. The new + strategy completely ignores <c>fun</c>s. If <c>fun</c>s + referring to the code being purged exist, and are used + after a purge, an exception will be raised upon usage. + That is, the behavior will be exactly the same as the + case when a <c>fun</c> is received by a process after the + purge.</p> + <p> + The new strategy can optionally be enabled when building + OTP during OTP 19, and will automatically be enabled if + the runtime system is built with support for dirty + schedulers.</p> + <p> + For more information see the documentation of <seealso + marker="erts:erlang#check_process_code/3"><c>erlang:check_process_code/3</c></seealso>.</p> + <p> + Own Id: OTP-13833</p> + </item> + <item> + <p> + Fixed unnecessary overestimation of heap size need during + garbage collection.</p> + <p> + Own Id: OTP-13851</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.0.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + 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> + Own Id: OTP-13890</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.0.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + 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> + Own Id: OTP-13889</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.0.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a race that could cause a lost wakeup of a process + that timed out in a <c>receive ... after</c>. This bug + was introduced in ERTS version 7.0.</p> + <p> + Own Id: OTP-13798 Aux Id: OTP-11997 </p> + </item> + <item> + <p> + Fixed segfault after writing an erl crash dump.</p> + <p> + Own Id: OTP-13799</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.0.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix scheduler deadlock bug in <c>ets:update_counter/4</c> + when key is not found and inserting the default object + causes the table to grow.</p> + <p> + Own Id: OTP-13731 Aux Id: ERL-188 </p> + </item> + <item> + <p> + Fix VM abort "Overrun stack and heap" in garbage + collection triggered by a <c>bsl</c> operation and some + very specific heap conditions.</p> + <p> + Own Id: OTP-13732 Aux Id: seq13142 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A memory allocation bug in <c>group_leader/2</c> could + cause an emulator crash when garbage collecting a process + that had been assigned a remote group leader. This bug + was introduced in ERTS version 8.0.</p> + <p> + Own Id: OTP-13716</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 8.0</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>The handling of <c>on_load</c> functions has been + improved. The major improvement is that if a code upgrade + fails because the <c>on_load</c> function fails, the + previous version of the module will now be retained.</p> + <p> + Own Id: OTP-12593</p> + </item> + <item> + <p><c>is_builtin(erlang, apply, 3)</c> will now return + <c>true</c>.</p> + <p> + Own Id: OTP-13034</p> + </item> + <item> + <p> + Fix <c>enif_get_list_length</c> to return false if list + is improper or have length larger than <c>UINT_MAX</c> + (did return true and an incorrect length value).</p> + <p> + Own Id: OTP-13288 Aux Id: PR913 </p> + </item> + <item> + <p> + Cleanup hipe signal handling code for x86 and make it + more portable.</p> + <p> + Own Id: OTP-13341 Aux Id: PR951 </p> + </item> + <item> + <p> + Make file:datasync use fsync instead of fdatasync on Mac + OSX.</p> + <p> + Own Id: OTP-13411</p> + </item> + <item> + <p> + Make sure to create a crash dump when running out of + memory. This was accidentally removed in the erts-7.3 + release.</p> + <p> + Own Id: OTP-13419</p> + </item> + <item> + <p> + A bug has been fixed where if erlang was started +B on a + unix platform it would be killed by a SIGUSR2 signal when + creating a crash dump.</p> + <p> + Own Id: OTP-13425</p> + </item> + <item> + <p> + Fix race between <c>process_flag(trap_exit,true)</c> and + a received exit signal.</p> + <p> + A process could terminate due to exit signal even though + <c>process_flag(trap_exit,true)</c> had returned. A very + specific timing between call to <c>process_flag/2</c> and + exit signal from another scheduler was required for this + to happen.</p> + <p> + Own Id: OTP-13452</p> + </item> + <item> + <p>Don't search for non-existing Map keys twice</p> + <p>For <c>maps:get/2,3</c> and <c>maps:find/2</c>, + searching for an immediate key, e.g. an atom, in a small + map, the search was performed twice if the key did not + exist.</p> + <p> + Own Id: OTP-13459</p> + </item> + <item> + <p> + When an abnormally large distribution message is about to + be sent, the VM has been changed to create a crash dump + instead of a core dump.</p> + <p> + Own Id: OTP-13474</p> + </item> + <item> + <p> + Fix <c>erlang:process_info/2</c> type specification</p> + <p> + Own Id: OTP-13485 Aux Id: ERL-123 </p> + </item> + <item> + <p> + Fix bug in <c>open_port/2</c> with option <c>{args, + List}</c>. A vm crash could be caused by an improper + <c>List</c>.</p> + <p> + Own Id: OTP-13489 Aux Id: ERL-127 </p> + </item> + <item> + <p> + Fixed a race-condition bug where the emulator could crash + when <c>erlang:system_profile/1,2</c> was enabled and a + process had to be re-scheduled during termination.</p> + <p> + Own Id: OTP-13494 Aux Id: ERL-126 </p> + </item> + <item> + <p> + Fixed bugs where the reduction counter was not handled + correct.</p> + <p> + Own Id: OTP-13512</p> + </item> + <item> + <p> + Fixed typo in description of the <c>EPMD_DUMP_REQ</c> + response.</p> + <p> + Own Id: OTP-13517</p> + </item> + <item> + <p> + Fixed a bug where a process flagged as sensitive would + sometimes record its save_calls when it shouldn't.</p> + <p> + Own Id: OTP-13540</p> + </item> + <item> + <p> + Update configure scripts to not use hard-coded path for + /bin/pwd and /bin/rm.</p> + <p> + Own Id: OTP-13562</p> + </item> + <item> + <p> + When passing a larger binary than the outputv callback of + a linked-in driver can handle in one io vector slot, the + binary is now split into multiple slots in the io vector. + This change only effects system where the max size of an + io vector slot is smaller then the word size of the + system (e.g. Windows).</p> + <p> + This change means that it is now possible on Windows to + send binaries that are larger than 4GB to port_command, + which is what is used for file:write, gen_tcp:send etc.</p> + <p> + Own Id: OTP-13628</p> + </item> + <item> + <p> + Workaround of Maps output in crashdumps. Currently the + atom 'undefined' is generated instead of Map data if a + Map type is encountered during crash.</p> + <p> + Own Id: OTP-13657</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The tracing support has been extended to allow a <seealso + marker="erl_tracer">tracer module</seealso> to be the + trace event handler instead of a process or port. The + <seealso marker="erl_tracer">tracer module</seealso> + makes it possible for trace tools to filter or manipulate + trace event data without the trace event first having to + be copied from the traced process or port.</p> + <p> + With the introduction of this feature, + <c>erlang:trace(all|existing, _, _)</c> now also returns + the tracer process as part of the number of processes on + which tracing is enabled. The is incompatible with the + previous releases.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-10267</p> + </item> + <item> + <p> + Introduce LTTng tracing of Erlang Runtime System</p> + <p> + For LTTng to be enabled OTP needs to be built with + configure option <c>--with-dynamic-trace=lttng</c>.</p> + <p> + This feature introduces tracepoints for schedulers, + drivers, memory carriers, memory and async thread pool.</p> + <p> For a list of all tracepoints, see <seealso + marker="runtime_tools:LTTng">Runtime Tools User's + Guide</seealso> .</p> + <p> + Own Id: OTP-10282</p> + </item> + <item> + <p> + Make it possible to monitor/demonitor ports using the + <seealso + marker="erlang#monitor/2">erlang:monitor/2</seealso> API. + The process and port information functions have also been + updated to include information about monitors from + processes to ports.</p> + <p> + Own Id: OTP-11384</p> + </item> + <item> + <p> + Add microstate accounting</p> + <p> + Microstate accounting is a way to track which state the + different threads within ERTS are in. The main usage area + is to pin point performance bottlenecks by checking which + states the threads are in and then from there figuring + out why and where to optimize.</p> + <p> + Since checking whether microstate accounting is on or off + is relatively expensive only a few of the states are + enabled by default and more states can be enabled through + configure.</p> + <p> + There is a convenience module called msacc that has been + added to runtime_tools that can assist in gathering and + interpreting the data from Microstate accounting.</p> + <p> + For more information see <seealso + marker="erts:erlang#statistics_microstate_accounting">erlang:statistics(microstate_accounting, + _)</seealso> and the <seealso + marker="runtime_tools:msacc">msacc</seealso> module in + runtime_tools.</p> + <p> + Own Id: OTP-12345</p> + </item> + <item> + <p> + The port of Erlang/OTP to the real-time operating system + OSE has been removed.</p> + <p> + Own Id: OTP-12573</p> + </item> + <item> + <p> + Sharing preserved copy for messages and exit signals</p> + <p> + Enable sharing preserved copy with configure option + <c>--enable-sharing-preserving</c>. This will preserve + sharing, within the process, when communication with + other processes in the Erlang node. There is a trade-off, + the copy is more costly but this cost can be reclaimed if + there is a lot of sharing in the message. In addition + literals will not be copied in a send except during a + purge phase of the module where the literals are located. + This feature is considered experimental in 19.0.</p> + <p> + Own Id: OTP-12590 Aux Id: OTP-10251 </p> + </item> + <item> + <p> + Halfword BEAM has been removed.</p> + <p> + Own Id: OTP-12883</p> + </item> + <item> + <p> + Added <seealso + marker="kernel:os#perf_counter/1">os:perf_counter/1</seealso>.</p> + <p> + The perf_counter is a very very cheap and high resolution + timer that can be used to timestamp system events. It + does not have monoticity guarantees, but should on most + OS's expose a monotonous time.</p> + <p> + Own Id: OTP-12908</p> + </item> + <item> + <p> + Support for a fragmented young heap generation. That is, + the young heap generation can consist of multiple non + continuous memory areas. The main reason for this change + is to avoid extra copying of messages that could not be + allocated directly on the receivers heap.</p> + <p> + Own Id: OTP-13047</p> + </item> + <item> + <p> + Erlang linked-in driver can now force the call to + open_port to block until a call to erl_drv_init_ack is + made inside the driver. This is useful when you want to + do some asynchronous initialization, for example getting + configuration from a pipe, and you want the initial + open_port call to fail if the configuration is incomplete + or wrong. See the erl_driver documentation for more + details on the API.</p> + <p> + Own Id: OTP-13086</p> + </item> + <item> + <p> + Erlang linked-in drivers can now set their own pids as + seen in <c>erlang:port_info/1</c> by using the + <c>erl_drv_set_pid</c> function. For more details see the + erl_driver documentation.</p> + <p> + Own Id: OTP-13087</p> + </item> + <item> + <p> + The functionality behind <c>erlang:open_port/2</c> when + called with spawn or spawn_executable has been redone so + that the forking of the new program is done in a separate + process called erl_child_setup. This allows for a much + more robust implementation that uses less memory and does + not block the entire emulator if the program to be + started is on an un-accessible NFS. Benchmarks have shown + this approach to be about 3-5 times as fast as the old + approach where the fork/vfork was done by erts. This is a + pure stability and performance fix, however some error + messages may have changed, which is why it is marked as a + backwards incompatible change.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13088</p> + </item> + <item> + <p>Improved yielding strategy in the implementation of + the following native functions:</p> <list> + <item><c>erlang:binary_to_list/1</c></item> + <item><c>erlang:binary_to_list/3</c></item> + <item><c>erlang:bitstring_to_list/1</c></item> + <item><c>erlang:list_to_binary/1</c></item> + <item><c>erlang:iolist_to_binary/1</c></item> + <item><c>erlang:list_to_bitstring/1</c></item> + <item><c>binary:list_to_bin/1</c></item> </list> <p>This + in order to improve performance of these functions.</p> + <p> + Own Id: OTP-13096</p> + </item> + <item> + <p> + All garbage collections of processes now bump reductions. + Also the amount of reductions bumped when garbage + collecting has been adjusted. It now better corresponds + to the amount of work performed. This in order to improve + the real time characteristics of the system.</p> + <p> + Own Id: OTP-13097</p> + </item> + <item> + <p>New functions that can load multiple modules at once + have been added to the '<c>code</c>' module. The + functions are <c>code:atomic_load/1</c>, + <c>code:prepare_loading/1</c>, + <c>code:finish_loading/1</c>, and + <c>code:ensure_modules_loaded/1</c>.</p> + <p> + Own Id: OTP-13111</p> + </item> + <item> + <p>The <c>-boot_var</c> option for <c>erl</c> now only + supports a single key and single value (as documented). + The option used to allow multiple key/value pairs, but + that behavior was undocumented.</p> + <p>The function <c>erl_prim_loader:start/3</c> has been + removed. Its documentation has also been removed.</p> + <p>The undocumented and unsupported function + <c>erl_prim_loader:get_files/2</c> has been removed.</p> + <p> + Own Id: OTP-13112</p> + </item> + <item> + <p> + Low level BIF <c>erlang:purge_module/1</c> is made more + robust against incorrect use. Lingering processes that + still refer the old code are now killed before the module + is purged to prevent fatal VM behavior.</p> + <p> + Own Id: OTP-13122</p> + </item> + <item> + <p>Improved dirty scheduler implementation. For more + information see the <seealso + marker="erl_nif#dirty_nifs">NIF + documentation</seealso>.</p> <note><list> <item><p>The + dirty scheduler support is still + <em>experimental</em>.</p></item> <item><p>The support + for determining whether dirty NIF support exist or not at + compile time using the C preprocessor macro + <c>ERL_NIF_DIRTY_SCHEDULER_SUPPORT</c> has been + removed.</p></item> <item><p>The + <c>enif_is_on_dirty_scheduler()</c> function has been + removed. Use <seealso + marker="erl_nif#enif_thread_type"><c>enif_thread_type()</c></seealso> + instead.</p></item> </list></note> + <p> + Own Id: OTP-13123</p> + </item> + <item> + <p> + Various optimizations done to process dictionary access.</p> + <p> + Own Id: OTP-13167</p> + </item> + <item> + <p> + Added max_heap_size process flag. max_heap_size allows + the user to limit the maximum heap used by a process. See + <seealso + marker="erlang#process_flag/2">erlang:process_flag</seealso> + for more details.</p> + <p> + Own Id: OTP-13174</p> + </item> + <item> + <p> + Allow dynamic drivers and NIF libraries to be built with + gcc option <c>-fvisibility=hidden</c> for faster loading + and more optimized code.</p> + <p> + Own Id: OTP-13227</p> + </item> + <item> + <p> + Add <c>erlang:process_info(Pid, + garbage_collection_info)</c> which returns extended + garbage_collection information. For more details see the + documentation.</p> + <p> + Own Id: OTP-13265</p> + </item> + <item> + <p> + The functions <c>erlang:list_to_integer/1</c> and + <c>string:to_integer/1</c> have been optimized for large + inputs.</p> + <p> + Own Id: OTP-13293</p> + </item> + <item> + <p> + Improved memory allocation strategy for hipe native code + on x86_64 (amd64) architectures by reserving enough low + virtual address space needed for the HiPE/AMD64 small + code model. The default virtual address area for hipe + code is set to 512Mb, but can be changed with emulator + flag <c>+MXscs</c>.</p> + <p> + Own Id: OTP-13359</p> + </item> + <item> + <p> + Introduction of configurable management of data referred + to by the message queue of a process. Each process can be + configured individually.</p> + <p> + It is now possible to configure the message queue of a + process, so that all data referred by it will be kept + outside of the heap, and by this prevent this data from + being part of garbage collections.</p> + <p> + For more information see the documentation of <seealso + marker="erlang#process_flag_message_queue_data"><c>process_flag(message_queue_data, + MQD)</c></seealso>.</p> + <p> + Own Id: OTP-13366 Aux Id: OTP-13047 </p> + </item> + <item> + <p> + Processes now yield when scanning large message queues + and not finding a matching message. This in order to + improve real time characteristics.</p> + <p> + Own Id: OTP-13401</p> + </item> + <item> + <p> + Optimized an erts internal function that is used to + traverse erlang terms. The internal function was mainly + used by term_to_binary and comparison of terms. + Benchmarks have shown up to a 10% performance increase in + those functions after the optimization.</p> + <p> + Own Id: OTP-13440</p> + </item> + <item> + <p>Add the following NIF API functions:</p> + <list> <item><seealso + marker="erl_nif#enif_cpu_time"><c>enif_cpu_time</c></seealso></item> + <item><seealso + marker="erl_nif#enif_now_time"><c>enif_now_time</c></seealso></item> + <item><seealso + marker="erl_nif#enif_make_unique_integer"><c>enif_make_unique_integer</c></seealso></item> + <item><seealso + marker="erl_nif#enif_is_process_alive"><c>enif_is_process_alive</c></seealso></item> + <item><seealso + marker="erl_nif#enif_is_port_alive"><c>enif_is_port_alive</c></seealso></item> + <item><seealso + marker="erl_nif#enif_term_to_binary"><c>enif_term_to_binary</c></seealso></item> + <item><seealso + marker="erl_nif#enif_binary_to_term"><c>enif_binary_to_term</c></seealso></item> + <item><seealso + marker="erl_nif#enif_port_command"><c>enif_port_command</c></seealso></item> + </list> + <p> + For details of what each function does, see the erl_nif + documentation.</p> + <p> + Own Id: OTP-13442</p> + </item> + <item> + <p> + Optimize <c>'++'</c> operator and <c>lists:append/2</c> + by using a single pass to build a new list while checking + for properness.</p> + <p> + Own Id: OTP-13487</p> + </item> + <item> + <p> + Handle terms (pids,ports and refs) from nodes with a + 'creation' value larger than 3. This is a preparation of + the distribution protocol to allow OTP 19 nodes to + correctly communicate with future nodes (20 or higher). + The 'creation' value differentiates different + incarnations of the same node (name).</p> + <p> + Own Id: OTP-13488</p> + </item> + <item> + <p> + Don't send unasked for systemd notifications in epmd</p> + <p> + Own Id: OTP-13493 Aux Id: PR-999 </p> + </item> + <item> + <p> + The enif_send API has been extended to allow NULL to be + used as the message environment. When used this way, a + message environment is implicitly created and the given + term is copied into that environment before sending. This + can be an optimization if many small messages are being + sent by the nif.</p> + <p> + Own Id: OTP-13495</p> + </item> + <item> + <p> + The tracing support has been extended to allow tracing on + ports. Ports can be traced on using the 'ports', 'send' + and 'receive' trace flags.</p> + <p> + The first argument of <seealso + marker="erts:erlang#trace/3">erlang:trace/3</seealso> has + been extended so that <c>'all'</c>, <c>'existing'</c> and + <c>'new'</c> now include both processes and ports. New + <c>Tracee</c> variants, <c>'all_processes'</c>, + <c>'all_ports'</c>, <c>'existing_processes'</c> etc have + been added to specify only processes or ports.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13496</p> + </item> + <item> + <p> + When the <c>'procs'</c> trace flag is enabled, a + <c>'spawned'</c> trace event is now also generated by a + newly created process. The previous event <c>'spawn'</c> + remains, but as it is generated by the process that did + the spawn, it is not guaranteed that it is ordered with + other trace events from the newly spawned process. So + when tracking the lifetime of a process this new event + should be used as the creation event.</p> + <p> + This new trace event is marked as an incompatibility + because tools that expect certain trace events when + enabling 'procs' will have to updated.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13497</p> + </item> + <item> + <p> + Add the <seealso + marker="erts:erlang#match_spec_test/3">erlang:match_spec_test/3</seealso> + function. The functions allows the testing of match + specifications for both tracing and ets tables. It can be + used to test that a match specification does the expected + filtering on specific data. It also returns more verbose + error reasons for incorrectly constructed match + specifications.</p> + <p> + Own Id: OTP-13501</p> + </item> + <item> + <p> + The erts internal tracing support has been changed to + have much less overhead and be more scalable.</p> + <p> + This rewrite does not break any backwards + incompatibilities, but it does change the ordering of + some trace messages when compared to previous releases. + It should be noted that this only applies to trace + messages sent to processes or ports, it does not apply to + the new tracer module. However in future releases they + may also be effected by this.</p> + <p> + Trace messages are only guaranteed to be ordered from one + traced process or port. In previous releases this was not + visible as a <c>'send'</c> trace message would always + arrive before the corresponding <c>'receive'</c> trace + message that is no longer always the case. This also + means that timestamped trace messages may seem to arrive + out of order as the timestamp is taken when the event is + triggered and not when it is put in the queue of the + tracer.</p> + <p> + Own Id: OTP-13503</p> + </item> + <item> + <p> + Add possibility to filter <c>send</c> and <c>receive</c> + trace with match specifications.</p> + <p> + Own Id: OTP-13507</p> + </item> + <item> + <p> + Add <c>maps:update_with/3,4</c> and <c>maps:take/2</c></p> + <p> + Own Id: OTP-13522 Aux Id: PR-1025 </p> + </item> + <item> + <p> + Introduce LTTng tracing via Erlang tracing.</p> + <p> + For LTTng to be enabled OTP needs to be built with + configure option <c>--with-dynamic-trace=lttng</c>.</p> + <p>The dynamic trace module <c>dyntrace</c> is now + capable to be used as a LTTng sink for Erlang tracing. + For a list of all tracepoints, see <seealso + marker="runtime_tools:LTTng">Runtime Tools User's + Guide</seealso> .</p> + <p>This feature also introduces an incompatible change in + trace tags. The trace tags <c>gc_start</c> and + <c>gc_end</c> has been split into <c>gc_minor_start</c>, + <c>gc_minor_end</c> and <c>gc_major_start</c>, + <c>gc_major_end</c>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-13532</p> + </item> + <item> + <p> + Print heap pointers for garbing processes during + crashdump</p> + <p> + Own Id: OTP-13541 Aux Id: PR-1026 </p> + </item> + <item> + <p> + Changed and improved low level memory statistics returned + by <c>erlang:system_info/1</c>. The info for + <c>erts_mmap</c> has been moved from <c>mseg_alloc</c> to + its own section returned by <c>{allocator, + erts_mmap}</c>.</p> + <p> + Own Id: OTP-13560</p> + </item> + <item> + <p> + Add enif_snprintf to the NIF API</p> + <p> + The function <c>enif_snprintf</c> is similar to + <c>snprintf</c> call but can handle formatting of Erlang + terms via <c>%T</c> format specifier.</p> + <p> + Own Id: OTP-13580</p> + </item> + <item> + <p>The warning in the documentation for + <c>erlang:raise/3</c> has been removed. It is now + officially perfectly fine to use raise/3 in production + code.</p> + <p> + Own Id: OTP-13599</p> + </item> + <item> + <p> + Fix bugs caused by the VM sometimes truncating object + sizes or offsets to 32 bits on 64-bit hosts. These bugs + were mainly found when working with large unicode strings + and nifs environments.</p> + <p> + Own Id: OTP-13606</p> + </item> + <item> + <p> + Add <c>-start_epmd</c> command line option, this lets you + disable automatic starting of epmd when starting a + distributed node.</p> + <p> + Add <c>-epmd_module</c> command line option, this lets + you specify a module to register and look-up node names + in. The default module is <c>erl_epmd</c>.</p> + <p> + Own Id: OTP-13627</p> + </item> + <item> + <p> + <c>erlang:halt</c> now truncates strings longer than 200 + characters instead of failing with <c>badarg</c>.</p> + <p> + Own Id: OTP-13630</p> + </item> + <item> + <p> + Fix possible race in poller wake up on windows</p> + <p> + Own Id: OTP-13634</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 7.3.1.4</title> + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix performance bug in pre-allocators that could cause + them to permanently fall back on normal more expensive + memory allocation. Pre-allocators are used for quick + allocation of short lived meta data used by messages and + other scheduled tasks. Bug exists since OTP_R15B02.</p> + <p> + Own Id: OTP-14491</p> </item> <item> <p> @@ -93,6 +4755,18 @@ </item> <item> <p> + A timer internal bit-field used for storing scheduler id + was too small. As a result, VM internal timer data + structures could become inconsistent when using 1024 + schedulers on the system. Note that systems with less + than 1024 schedulers are not effected by this bug.</p> + <p> + This bug was introduced in ERTS version 7.0 (OTP 18.0).</p> + <p> + Own Id: OTP-14548 Aux Id: OTP-11997, ERL-468 </p> + </item> + <item> + <p> Fixed bug in <c>binary_to_term</c> and <c>binary_to_atom</c> that could cause VM crash. Typically happens when the last character of an UTF8 @@ -105,15 +4779,261 @@ </item> </list> </section> +</section> + +<section><title>Erts 7.3.1.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A bug has been fixed where if erlang was started +B on a + unix platform it would be killed by a SIGUSR2 signal when + creating a crash dump.</p> + <p> + Own Id: OTP-13425 Aux Id: ERL-94 </p> + </item> + <item> + <p> + Calls to <c>erl_drv_send_term()</c> or + <c>erl_drv_output_term()</c> from a non-scheduler thread + while the corresponding port was invalid caused the + emulator to enter an inconsistent state which eventually + caused an emulator crash.</p> + <p> + Own Id: OTP-13866</p> + </item> + <item> + <p>Driver and NIF operations accessing processes or ports + could cause an emulator crash when used from + non-scheduler threads. Those operations are:</p> <list> + <item><c>erl_drv_send_term()</c></item> + <item><c>driver_send_term()</c></item> + <item><c>erl_drv_output_term()</c></item> + <item><c>driver_output_term()</c></item> + <item><c>enif_send()</c></item> + <item><c>enif_port_command()</c></item> </list> + <p> + Own Id: OTP-13869</p> + </item> + <item> + <p> + Fix bug in <c>binary_to_term</c> for binaries created by + <c>term_to_binary </c> with option <c>compressed</c>. The + bug can cause <c>badarg</c> exception for a valid binary + when Erlang VM is linked against a <c>zlib</c> library of + version 1.2.9 or newer. Bug exists since OTP 17.0.</p> + <p> + Own Id: OTP-14159 Aux Id: ERL-340 </p> + </item> + </list> + </section> </section> -<section><title>Erts 6.4.1.6</title> +<section><title>Erts 7.3.1.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a race that could cause a lost wakeup of a process + that timed out in a <c>receive ... after</c>. This bug + was introduced in ERTS version 7.0.</p> + <p> + Own Id: OTP-13798 Aux Id: OTP-11997 </p> + </item> + <item> + <p> + Fixed segfault after writing an erl crash dump.</p> + <p> + Own Id: OTP-13799</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 7.3.1.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix scheduler deadlock bug in <c>ets:update_counter/4</c> + when key is not found and inserting the default object + causes the table to grow.</p> + <p> + Own Id: OTP-13731 Aux Id: ERL-188 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 7.3.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + <c>process_info(Pid, last_calls)</c> did not work for + <c>Pid /= self()</c>.</p> + <p> + Own Id: OTP-13418</p> + </item> + <item> + <p> + Make sure to create a crash dump when running out of + memory. This was accidentally removed in the erts-7.3 + release.</p> + <p> + Own Id: OTP-13419</p> + </item> + <item> + <p> + Schedulers could be woken by a premature timeout on + Linux. This premature wakeup was however harmless.</p> + <p> + Own Id: OTP-13420</p> + </item> + <item> + <p> + A process communicating with a port via one of the + <c>erlang:port_*</c> BIFs could potentially end up in an + inconsistent state if the port terminated during the + communication. When this occurred the process could later + block in a <c>receive</c> even though it had messages + matching in its message queue.</p> + <p> + This bug was introduced in erts version 5.10 (OTP R16A).</p> + <p> + Own Id: OTP-13424 Aux Id: OTP-10336 </p> + </item> + <item> + <p> + The reference count of a process structure could under + rare circumstances be erroneously managed. When this + happened invalid memory accesses occurred.</p> + <p> + Own Id: OTP-13446</p> + </item> + <item> + <p> + Fix race between <c>process_flag(trap_exit,true)</c> and + a received exit signal.</p> + <p> + A process could terminate due to exit signal even though + <c>process_flag(trap_exit,true)</c> had returned. A very + specific timing between call to <c>process_flag/2</c> and + exit signal from another scheduler was required for this + to happen.</p> + <p> + Own Id: OTP-13452</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 7.3</title> <section><title>Fixed Bugs and Malfunctions</title> <list> <item> <p> + The '-path' flag to 'erl' has been documented. This flag + replaces the path specified in the boot script. It has + always existed, but was earlier only documented in SASL + (script).</p> + <p> + Own Id: OTP-13060</p> + </item> + <item> + <p> + The <c>call_time</c> tracing functionality internally + used a time based on OS system time in order to measure + call time which could cause erroneous results if OS + system time was changed during tracing.</p> + <p> + This functionality now use Erlang monotonic time in order + to measure time. Besides fixing the erroneous results due + to OS system time being used, the results are often also + better since Erlang monotonic time often has better + accuracy and precision.</p> + <p> + Own Id: OTP-13216</p> + </item> + <item> + <p> + Fix behaviour of -delay_write command line switch of + epmd, which is used for debugging - in some cases epmd + was sleeping twice the requested amount of time.</p> + <p> + Own Id: OTP-13220</p> + </item> + <item> + <p> + Fix race between timeout and exit signal that could cause + a process to ignore the exit signal and continue + execution. Bug exist since OTP 18.0.</p> + <p> + Own Id: OTP-13245</p> + </item> + <item> + <p> + Fix bug in <c>erlang:halt/1,2</c> for large exit status + values, causing either <c>badarg</c> (on 32-bit) or exit + with a crash dump and/or core dump (on 64-bit). Make + <c>erlang:halt/1,2</c> tolerate any non negative integer + as exit status and truncate high order bits if the OS + does not support it.</p> + <p> + Own Id: OTP-13251 Aux Id: ERL-49 </p> + </item> + <item> + <p> + <seealso + marker="kernel:gen_tcp#accept/2"><c>gen_tcp:accept/2</c></seealso> + was not <seealso + marker="erts:time_correction#Time_Warp_Safe_Code">time + warp safe</seealso>. This since it used the same time as + returned by <seealso + marker="erts:erlang#now/0"><c>erlang:now/0</c></seealso> + when calculating timeout. This has now been fixed.</p> + <p> + Own Id: OTP-13254 Aux Id: OTP-11997, OTP-13222 </p> + </item> + <item> + <p> + Fix faulty error handling when writing to a compressed + file.</p> + <p> + Own Id: OTP-13270</p> + </item> + <item> + <p> + Fix sendfile usage for large files on FreeBSD</p> + <p> + Own Id: OTP-13271</p> + </item> + <item> + <p> + Fix bug that could cause + <c>process_info(P,current_location)</c> to crash emulator + for hipe compiled modules.</p> + <p> + Own Id: OTP-13282 Aux Id: ERL-79 </p> + </item> + <item> + <p> + Out of memory errors have been changed to cause an exit + instead of abort.</p> + <p> + Own Id: OTP-13292</p> + </item> + <item> + <p> When calling <c>garbage_collect/[1,2]</c> or <c>check_process_code/[2,3]</c> from a process with a higher priority than the priority of the process operated @@ -122,17 +5042,206 @@ <p> Own Id: OTP-13298 Aux Id: OTP-11388 </p> </item> + <item> + <p> + A workaround for an issue with older gcc versions (less + than 5) and inline assembly on 32-bit x86 caused an + emulator crash when it had been compiled with a newer gcc + version. An improved <c>configure</c> test, run when + building OTP, now detects whether the workaround should + be used or not.</p> + <p> + Own Id: OTP-13326 Aux Id: ERL-80 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Introduced new statistics functionality in order to + more efficiently retrieve information about run able and + active processes and ports. For more information see:</p> + <list> <item><seealso + marker="erlang#statistics_total_run_queue_lengths"><c>statistics(total_run_queue_lengths)</c></seealso></item> + <item><seealso + marker="erlang#statistics_run_queue_lengths"><c>statistics(run_queue_lengths)</c></seealso></item> + <item><seealso + marker="erlang#statistics_total_active_tasks"><c>statistics(total_active_tasks)</c></seealso></item> + <item><seealso + marker="erlang#statistics_active_tasks"><c>statistics(active_tasks)</c></seealso></item> + </list> + <p> + Own Id: OTP-13201</p> + </item> + <item> + <p> + Time warp safety improvements.</p> + <p> + Introduced the options <c>monotonic_timestamp</c>, and + <c>strict_monotonic_timestamp</c> to the trace, + sequential trace, and system profile functionality. This + since the already existing <c>timestamp</c> option is not + time warp safe.</p> + <p> + Introduced the option <c>safe_fixed_monotonic_time</c> to + <c>ets:info/2</c> and <c>dets:info/2</c>. This since the + already existing <c>safe_fixed</c> option is not time + warp safe.</p> + <p> + Own Id: OTP-13222 Aux Id: OTP-11997 </p> + </item> + <item> + <p> + Fix a register race where down nodes goes undetected in + epmd</p> + <p> + Own Id: OTP-13301</p> + </item> + <item> + <p> + Improved the gcc inline assembly implementing double word + atomic compare and exchange on x86/x86_64 so that it also + can be used when compiling with clang.</p> + <p> + Own Id: OTP-13336</p> + </item> + <item> + <p> + An optimization preventing a long wait for a scheduler + thread looking up information about a process executing + on another scheduler thread had unintentionally been lost + in erts-5.10 (OTP R16A). This optimization has now been + reintroduced.</p> + <p> + Own Id: OTP-13365 Aux Id: OTP-9892 </p> + </item> </list> </section> </section> -<section><title>Erts 6.4.1.5</title> +<section><title>Erts 7.2.1.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Introduced new statistics functionality in order to + more efficiently retrieve information about run able and + active processes and ports. For more information see:</p> + <list> <item><seealso + marker="erlang#statistics_total_run_queue_lengths"><c>statistics(total_run_queue_lengths)</c></seealso></item> + <item><seealso + marker="erlang#statistics_run_queue_lengths"><c>statistics(run_queue_lengths)</c></seealso></item> + <item><seealso + marker="erlang#statistics_total_active_tasks"><c>statistics(total_active_tasks)</c></seealso></item> + <item><seealso + marker="erlang#statistics_active_tasks"><c>statistics(active_tasks)</c></seealso></item> + </list> + <p> + Own Id: OTP-13201</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 7.2.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Revert "Fix erroneous splitting of emulator path"</p> + <p> + Own Id: OTP-13202</p> + </item> + <item> + <p> + Fix HiPE enabled emulator for FreeBSD.</p> + <p> + Own Id: OTP-13204 Aux Id: pr926 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 7.2</title> <section><title>Fixed Bugs and Malfunctions</title> <list> <item> <p> + Small documentation fixes</p> + <p> + Own Id: OTP-13017</p> + </item> + <item> + <p> + Fix memory corruption bug caused by disabling + distribution and then re-enable distribution with a node + name that has previously been used by a remote node.</p> + <p> + Own Id: OTP-13076 Aux Id: seq12959 </p> + </item> + <item> + <p> + Renamed variables with name bool as Visual Studio 2015 + now treats this is a keyword.</p> + <p> + Own Id: OTP-13079</p> + </item> + <item> + <p><c>erl_prim_loader</c> has not supported custom + loaders for several releases. In the documentation for + <c>erl_prim_loader</c>, all references to custom loaders + have now been removed.</p> + <p> + Own Id: OTP-13102</p> + </item> + <item> + <p> + Fixed compilation of erts together with libc versions + that do not define __uint32_t.</p> + <p> + Own Id: OTP-13105</p> + </item> + <item> + <p> + erl -make now returns non-zero exit codes on failure</p> + <p> + Own Id: OTP-13107</p> + </item> + <item> + <p> + Fix crash on init:restart in embedded mode caused by + on_load handler process not being relaunched leading to + load failure for modules such as crypto and asn1rt_nif + that need it to be present for correct NIF loading.</p> + <p> + Own Id: OTP-13115</p> + </item> + <item> + <p> + Fix maps decode in erlang:binary_to_term/1</p> + <p>Decoding a term with a large (HAMT) map in an small + (FLAT) map could cause a critical error if the external + format was not produced by beam.</p> + <p> + Own Id: OTP-13125</p> + </item> + <item> + <p> + Fix very rare bug in GC when big maps with a lot of hash + collisions from a remote node are waiting in inner + message queue.</p> + <p> + Own Id: OTP-13146</p> + </item> + <item> + <p> Fixed a bug that could cause a crash dump to become almost empty.</p> <p> @@ -141,33 +5250,171 @@ </list> </section> -</section> -<section><title>Erts 6.4.1.4</title> + <section><title>Improvements and New Features</title> + <list> + <item> + <p> Updated the xmllint target to just check the xml + files with real documentation content.<br/> Corrected + some errors and added some missing target in the DTD's. + </p> + <p> + Own Id: OTP-13026</p> + </item> + <item> + <p> + Add function enif_getenv to read OS environment variables + in a portable way from NIFs.</p> + <p> + Own Id: OTP-13147</p> + </item> + </list> + </section> +</section> + +<section><title>Erts 7.1</title> <section><title>Fixed Bugs and Malfunctions</title> <list> <item> <p> - The 'raw' socket option could not be used multiple times - in one call to any e.g gen_tcp function because only one - of the occurrences were used. This bug has been fixed, - and also a small bug concerning propagating error codes - from within inet:setopts/2.</p> + Fix bug in ETS that could cause stray objects marked for + deletion to occasionally be missed by the cleanup done by + <c>safe_fixtable(_,false)</c>.</p> <p> - Own Id: OTP-11482 Aux Id: seq12872 </p> + Own Id: OTP-12870</p> + </item> + <item> + <p> + Fixed VM crash that could occur if a trace port was + linked to a process, and the trace port terminated + abnormally while handling a trace message. This bug has + always existed in the runtime system with SMP support.</p> + <p> + Own Id: OTP-12901</p> + </item> + <item> + <p> + Instead of aborting, the vm now creates a crash dump when + a system process is terminated.</p> + <p> + Own Id: OTP-12934</p> + </item> + <item> + <p> + Fixed a rare emulator dead lock that occurred when + erlang:process_flag(priority,...) was called by a process + that was also scheduled for an internal system activity.</p> + <p> + Own Id: OTP-12943</p> + </item> + <item> + <p> + The runtime system on various posix platforms (except for + Linux and Solaris) could crash when large amounts of + file-descriptors were in use.</p> + <p> + Own Id: OTP-12954</p> + </item> + <item> + <p> + A beam file compiled by hipe for an incompatible runtime + system was sometimes not rejected by the loader, which + could lead to vm crash. This fix will also allow the same + hipe compiler to be used by both normal and debug-built + vm.</p> + <p> + Own Id: OTP-12962</p> + </item> + <item> + <p> + Fix bug in <c>maps:merge/2</c> when called by hipe + compiled code that could cause vm crash. Bug exists since + erts-7.0 (OTP 18.0).</p> + <p> + Own Id: OTP-12965</p> + </item> + <item> + <p> + When tracing with <c>process_dump</c> option, the VM + could abort if there was an ongoing binary match + somewhere in the call stack of the traced process.</p> + <p> + Own Id: OTP-12968</p> + </item> + <item> + <p> + Fixed possible output deadlock in tty driver when hitting + "CTRL-C" in a non-smp emulator shell on unix.</p> + <p> + Own Id: OTP-12987 Aux Id: Seq12947 </p> + </item> + <item> + <p> + Fix <c>binary_to_integer</c> to throw badarg for "+" and + "-" similar to <c>list_to_integer</c>.</p> + <p> + Own Id: OTP-12988</p> + </item> + <item> + <p> + Suppress warning of unused argument when using macro + enif_make_pid.</p> + <p> + Own Id: OTP-12989</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Changed default clock source used for OS system time on + MacOS X to <c>gettimeofday()</c> in order to improve + performance. The system can be configured during build to + use the previously used higher resolution clock source by + passing the switch <seealso + marker="doc/installation_guide:INSTALL#Advanced-configuration-and-build-of-ErlangOTP_Configuring"><c>--with-clock-resolution=high</c></seealso> + when configuring the build.</p> + <p> + Own Id: OTP-12945 Aux Id: OTP-12892 </p> + </item> + <item> + <p> + Added the <c>configure</c> option <seealso + marker="doc/installation_guide:INSTALL#Advanced-configuration-and-build-of-ErlangOTP_Configuring"><c>--disable-saved-compile-time</c></seealso> + which disables saving of compile date and time in the + emulator binary.</p> + <p> + Own Id: OTP-12971</p> </item> </list> </section> </section> -<section><title>Erts 6.4.1.3</title> +<section><title>Erts 7.0.3</title> <section><title>Fixed Bugs and Malfunctions</title> <list> <item> <p> + Fixed a binary memory leak when printing to shell using + the tty driver (i.e. not -oldshell).</p> + <p> + Own Id: OTP-12941</p> + </item> + <item> + <p> + Fix a bug where the standard error port sometimes crashes + with eagain as the reason.</p> + <p> + Own Id: OTP-12942</p> + </item> + <item> + <p> When tracing with <c>process_dump</c> option, the VM could abort if there was an ongoing binary match somewhere in the call stack of the traced process./</p> @@ -179,7 +5426,7 @@ </section> -<section><title>Erts 6.4.1.2</title> +<section><title>Erts 7.0.2</title> <section><title>Fixed Bugs and Malfunctions</title> <list> @@ -197,16 +5444,245 @@ <p> Own Id: OTP-12889 Aux Id: seq12885 </p> </item> + <item> + <p> + Removed unnecessary copying of data when retrieving + corrected Erlang monotonic time.</p> + <p> + Own Id: OTP-12894</p> + </item> + <item> + <p> + Changed default OS monotonic clock source chosen at build + time. This in order to improve performance. The behavior + will now on most systems be that (both OS and Erlang) + monotonic time stops when the system is suspended.</p> + <p> + If you prefer that monotonic time elapse during suspend + of the machine, you can pass the command line argument + <c>--enable-prefer-elapsed-monotonic-time-during-suspend</c> + to <c>configure</c> when building Erlang/OTP. The + configuration stage will try to find such a clock source, + but might not be able to find it. Note that there might + be a performance penalty associated with such a clock + source.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-12895</p> + </item> + <item> + <p> + <c>erlang:system_info(end_time)</c> returned a faulty + value on 32-bit architectures.</p> + <p> + Own Id: OTP-12896</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The <c>configure</c> command line argument + <c>--enable-gettimeofday-as-os-system-time</c> has been + added which force usage of <c>gettimeofday()</c> for OS + system time. This will improve performance of + <c>os:system_time()</c> and <c>os:timestamp()</c> on + MacOS X, at the expense of worse accuracy, resolution and + precision of Erlang monotonic time, Erlang system time, + and OS system time.</p> + <p> + Own Id: OTP-12892</p> + </item> </list> </section> </section> -<section><title>Erts 6.4.1.1</title> +<section><title>Erts 7.0.1</title> <section><title>Fixed Bugs and Malfunctions</title> <list> <item> + <p> + Fix a rare hanging of the VM seen to happen just after + emulator start. Bug exists since R14.</p> + <p> + Own Id: OTP-12859 Aux Id: seq12882 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 7.0</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fix issuing with spaces and quoting in the arguments when + using erlang:open_port spawn_executable on windows. The + behavior now mimics how unix works. This change implies a + backwards incompatibility for how spawn_executable works + on windows.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-11905</p> + </item> + <item> + <p> + Fix global call trace when hipe compiled code call beam + compiled functions. Tracing of beam functions should now + alway work regardless who the caller is.</p> + <p> + Own Id: OTP-11939</p> + </item> + <item> + <p> + Correct cache alignment for ETS <c>write_concurrency</c> + locks to improve performance by reduced false sharing. + May increase memory footprint for tables with + <c>write_concurrency</c>.</p> + <p> + Own Id: OTP-11974</p> + </item> + <item> + <p> + All possibly blocking operations in the fd/spawn and + terminal driver have been converted to non-blocking + operations. Before this fix it was possible for the VM to + be blocked for a long time if the entity consuming + stdout/stderr did not consume it fast enough.</p> + <p> + Own Id: OTP-12239</p> + </item> + <item> + <p> + Add missing overhead for offheap binaries created from + external format. This fix can improve the garbage + collection of large binaries originating from + <c>binary_to_term</c> or messages from remote nodes.</p> + <p> + Own Id: OTP-12554</p> + </item> + <item> + <p> + Ensure hashing of zero is consistent</p> + <p> Erlang treats positive and negative zero as + equal:</p> + <p> + <c>true = 0.0 =:= 0.0/-1</c></p> + <p>However, Erlangs hash functions: hash, phash and + phash2 did not reflect this behaviour. The hash values + produced by the different hash functions would not be + identical for positive and negative zero.</p> <p>This + change ensures that hash value of positive zero is always + produced regardless of the signedness of the zero float, + i.e.,</p> + <p> + <c>true = erlang:phash2(0.0) =:= + erlang:phash2(0.0/-1)</c></p> + <p> + Own Id: OTP-12641</p> + </item> + <item> + <p> + Ensure NIF term creation disallows illegal floating point + values and too long atoms. Such values will cause a NIF + to throw badarg exception when it returns.</p> + <p> + Own Id: OTP-12655</p> + </item> + <item> + <p> + Fixed building of Map results from match_specs</p> + <p> + A faulty "box-value" entered into the heap which could + cause a segmentation fault in the garbage collector if it + was written on a heap fragment.</p> + <p> + Own Id: OTP-12656</p> + </item> + <item> + <p> + Fix hipe bug when matching a "writable" binary. The bug + has been seen to sometimes cause a failed binary matching + of a correct utf8 character, but other symptoms are also + possible.</p> + <p> + Own Id: OTP-12667</p> + </item> + <item> + <p> + Keep dirty schedulers from waking other schedulers.</p> + <p> + Own Id: OTP-12685</p> + </item> + <item> + <p> + Disable floating point exceptions if the VM is compiled + by clang/llvm. This is a known long-standing problem in + clang/llvm.</p> + <p> + Own Id: OTP-12717</p> + </item> + <item> + <p> + Fix bug in <c>file:sendfile</c> for FreeBSD causing not + the entire file to be sent.</p> + <p> + Own Id: OTP-12720</p> + </item> + <item> + <p> + Fix the broken Android support in erl_child_setup.c</p> + <p> + Own Id: OTP-12751</p> + </item> + <item> + <p> + Faulty statistics reported by the <c>fix_alloc</c> + allocator.</p> + <p> + Own Id: OTP-12766</p> + </item> + <item> + <p> + Fix two erts_snprintf() calls to correct sizes.</p> + <p> + - run_erl.c (ose): Use the size of the signal type, not + its pointer. - erl_node_tables.c: Use the size of the + _BUFFER in erts_snprintf() to make sure we can use the + full space.</p> + <p> + Own Id: OTP-12771</p> + </item> + <item> + <p> + Delayed memory allocations could be delayed an + unnecessarily long time.</p> + <p> + Own Id: OTP-12812</p> + </item> + <item> + <p> + Make sure that timeouts on a pool of acceptors are + released in the correct order.</p> + <p> + Own Id: OTP-12817</p> + </item> + <item> + <p> + Fix segmentation fault in module_info for deleted modules</p> + <p> + Own Id: OTP-12820</p> + </item> + <item> <p>Fix garbage collection of literals in code purge</p> <p>During code purging and check_process_code, the checking of the binary reference embedded in the match @@ -218,16 +5694,666 @@ </item> <item> <p> - Fix a rare hanging of the VM seen to happen just after - emulator start. Bug exists since R14.</p> + A bug has been corrected for gen_tcp:close so when + {linger,{true,0}} is in effect it does not wait for data + in the driver queue to transfer out before closing the + port. Bug fix by Rory Byrne.</p> <p> - Own Id: OTP-12859 Aux Id: seq12882 </p> + Own Id: OTP-12840</p> + </item> + <item> + <p> + The documentation of the driver callback <seealso + marker="driver_entry#start"><c>start()</c></seealso> + erroneously stated that a return value of + <c>ERL_DRV_ERROR_ERRNO</c> caused the error value to be + passed via <c>erl_errno</c> when it should have been + <c>errno</c>.</p> + <p> + Own Id: OTP-12855</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Add <c>md5</c> and <c>module</c> entries to + <c>?MODULE:module_info/0/1</c> and remove obsolete entry + 'import'.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-11940</p> + </item> + <item> + <p> + Debug function <c>erlang:display/1</c> shows content of + binaries and bitstrings, not only the length.</p> + <p> + Own Id: OTP-11941</p> + </item> + <item> + <p>The time functionality of Erlang has been extended. + This both includes a <seealso + marker="time_correction#The_New_Time_API">new + API</seealso> for time, as well as <seealso + marker="time_correction#Time_Warp_Modes">time warp + modes</seealso> which alters the behavior of the system + when system time changes. <em>You are strongly encouraged + to use the new API</em> instead of the old API based on + <seealso + marker="erlang#now/0"><c>erlang:now/0</c></seealso>. + <c>erlang:now/0</c> has been deprecated since it is and + forever will be a scalability bottleneck. For more + information see the <seealso + marker="time_correction">Time and Time + Correction</seealso> chapter of the ERTS User's + Guide.</p> + <p>Besides the API changes and time warp modes a lot of + scalability and performance improvements regarding time + management has been made internally in the runtime + system. Examples of such improvements are scheduler + specific timer wheels, scheduler specific BIF timer + management, parallel retrieval of monotonic time and + system time on systems with primitives that are not + buggy.</p> + <p> + Own Id: OTP-11997</p> + </item> + <item> + <p><c>erlang:function_exported(M, F, A)</c> will now + return <c>true</c> if <c>M:F/A</c> refers to a BIF.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-12099</p> + </item> + <item> + <p> + New BIF: <c>erlang:get_keys/0</c>, lists all keys + associated with the process dictionary. Note: + <c>erlang:get_keys/0</c> is auto-imported.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-12151 Aux Id: seq12521 </p> + </item> + <item> + <p> + Make distributed send of large messages yield to improve + real-time characteristics.</p> + <p> + Own Id: OTP-12232</p> + </item> + <item> + <p> + Use high accuracy poll timeouts</p> + <p> + Where available, use poll/select API's that can handle + time resolutions less than 1ms. In the cases where such + API's are not available the timeout is rounded up to the + nearest ms.</p> + <p> + Own Id: OTP-12236</p> + </item> + <item> + <p> + The internal group to user_drv protocol has been changed + to be synchronous in order to guarantee that output sent + to a process implementing the user_drv protocol is + printed before replying. This protocol is used by the + standard_output device and the ssh application when + acting as a client. </p> + <p> + This change changes the previous unlimited buffer when + printing to standard_io and other devices that end up in + user_drv to 1KB.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-12240</p> + </item> + <item> + <p>The previously introduced "eager check I/O" feature is + now enabled by default.</p> + <p>Eager check I/O can be disabled using the <c>erl</c> + command line argument: <c>+secio false</c></p> + <p>Characteristics impact compared to previous + default:</p> <list> <item>Lower latency and smoother + management of externally triggered I/O operations.</item> + <item>A slightly reduced priority of externally triggered + I/O operations.</item> </list> + <p> + Own Id: OTP-12254 Aux Id: OTP-12117 </p> + </item> + <item> + <p> + Properly support maps in match_specs</p> + <p> + Own Id: OTP-12270</p> + </item> + <item> + <p> + The notice that a crashdump has been written has been + moved to be printed before the crashdump is generated + instead of afterwords. The wording of the notice has also + been changed.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-12292</p> + </item> + <item> + <p> + New function <c>ets:take/2</c>. Works the same as + <c>ets:delete/2</c> but also returns the deleted + object(s).</p> + <p> + Own Id: OTP-12309</p> + </item> + <item> + <p> + Tracing with cpu_timestamp option has been enabled on + Linux.</p> + <p> + Own Id: OTP-12366</p> + </item> + <item> + <p> + ets:info/1,2 now contains information about whether + write_concurrency or read_concurrency is enabled.</p> + <p> + Own Id: OTP-12376</p> + </item> + <item> + <p> + Improved usage of <c>gcc</c>'s builtins for atomic memory + access. These are used when no other implementation of + atomic memory operations is available. For example, when + compiling for ARM when <c>libatomic_ops</c> is not + available.</p> + <p> + The largest improvement will be seen when compiling with + a <c>gcc</c> with support for the <c>__atomic_*</c> + builtins (using a <c>gcc</c> of at least version 4.7), + but also when only the legacy <c>__sync_*</c> builtins + are available (using a <c>gcc</c> of at least version + 4.1) an improvement can be seen.</p> + <p> + For more information see the "<seealso + marker="doc/installation_guide:INSTALL#Advanced-configuration-and-build-of-ErlangOTP_Configuring_Atomic-Memory-Operations-and-the-VM">Atomic + Memory Operations and the VM</seealso>" section of + <c>$ERL_TOP/HOWTO/INSTALL.md</c>.</p> + <p> + Own Id: OTP-12383</p> + </item> + <item> + <p> + Introduce <c>math:log2/1</c> function to math module.</p> + <p> + Own Id: OTP-12411</p> + </item> + <item> + <p>The documentation of the Abstract Format (in the ERTS + User's Guide) has been updated with types and + specification. (Thanks to Anthony Ramine.) </p> <p> The + explicit representation of parentheses used in types of + the abstract format has been removed. Instead the new + functions <c>erl_parse:type_inop_prec()</c> and + <c>erl_parse:type_preop_prec()</c> can be used for + inserting parentheses where needed. </p> + <p> + Own Id: OTP-12492</p> + </item> + <item> + <p> + Remove perfctr support</p> + <p> + Development of perfctr in the linux kernel ceased in + 2010. The perfctr support code in the Erlang VM is thus + effectively dead code and therefor removed.</p> + <p> + Own Id: OTP-12508</p> + </item> + <item> + <p><c>zlib:inflateChunk/2</c> has been added. It works + like <c>zlib:inflate/2</c>, but decompresses no more data + than will fit in the buffer configured by + <c>zlib:setBufSize/2</c>.</p> + <p> + Own Id: OTP-12548</p> + </item> + <item> + <p> + Use linear search for small select_val arrays</p> + <p> + Own Id: OTP-12555</p> + </item> + <item> + <p> + New BIF ets:update_counter/4 with a default object as + argument, which will be inserted in the table if the key + was not found.</p> + <p> + Own Id: OTP-12563</p> + </item> + <item> + <p> + Export missing types from zlib module</p> + <p> + Own Id: OTP-12584</p> + </item> + <item> + <p> + Use persistent hashmaps for large Maps</p> + <p>Maps will use a + persistent hashmap implementation when the number of + pairs in a Map becomes sufficiently large. The change + will occur when a Map reaches 33 pairs in size but this + limit might change in the future.</p> + <p>The most significant impact for the user by this + change is speed, and to a lesser degree memory + consumption and introspection of Maps. Memory consumption + size is probalistic but lesser than <c>gb_trees</c> or + <c>dict</c> for instance. Any other impacts will be + transparent for the user except for the following + changes.</p> + <p>Semantics of Maps have changed in two incompatible + ways compared to the experimental implementation in OTP + 17:</p> <list> <item>Hashing of maps is done different by + <c>erlang:phash2/1,2</c>, <c>erlang:phash/1</c> and + <c>erlang:hash/2</c>.</item> <item>Comparing two maps + with ==, /=, =<, <, >= and >, is done + different if the keys contain floating point + numbers.</item> </list> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-12585</p> + </item> + <item> + <p> + Scalability improvement for <seealso + marker="erlang#make_ref/0">erlang:make_ref/0</seealso>, + and other functionality that create references. Each + scheduler now manage its own set of references. By this + no communication at all is needed when creating + references.</p> + <p> + Previous implementation generated a strictly + monotonically increasing sequence of references + corresponding to creation time on the runtime system + instance. This is <em>not</em> the case with current + implementation. You can only expect reference to be + unique. The Erlang/OTP documentation has never mentioned + anything else but the uniqueness property, so this change + <em>is</em> fully compatible. The only reason we've + marked this as a potential incompatibility is since an + early draft for an Erlang specification mentions strict + monotonicity as a property.</p> + <p> + If you need to create data with a strict monotonicity + property use <seealso + marker="erlang#unique_integer/1">erlang:unique_integer([monotonic])</seealso>. + Do <em>not</em> use the deprecated <seealso + marker="erlang#now/0">erlang:now()</seealso>.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-12610</p> + </item> + <item> + <p> + Enable different abort signal from heart</p> + <p>By using environment variable HEART_KILL_SIGNAL, heart + can now use a different signal to kill the old running + Erlang.</p> + <p>By default the signal is SIGKILL but SIGABRT may also + be used by setting environment variable: + HEART_KILL_SIGNAL=SIGABRT</p> + <p> + Own Id: OTP-12613 Aux Id: seq12826 </p> + </item> + <item> + <p> + Update autconf to latest version 2015-03-04</p> + <p> + Own Id: OTP-12646</p> + </item> + <item> + <p> + Optimization of timers internally in the VM. This include + process timers (<c>receive ... after</c>), port timers + (<c>driver_set_timer()</c>) as well as BIF timers + (<c>erlang:send_after()</c>/<c>erlang:start_timer()</c>).</p> + <p> + Each scheduler thread now has its own lock-free timer + service instead of one locked central service. This + dramatically improves performance of timer management on + systems with a large amount of schedulers and timers.</p> + <p> + The timer service internal data structure has also been + optimized to be able to handle more timers than before. + That is, each timer service is by its self able to handle + more timers without dramatic performance loss than the + old centralized timer service.</p> + <p> + The API of BIF timers has also been extended. Timeout + values are for example no longer limited to 32-bit + integers. For more information see the documentation of + <seealso + marker="erlang#start_timer/4"><c>erlang:start_timer/4</c></seealso>, + <seealso + marker="erlang#send_after/4"><c>erlang:send_after/4</c></seealso>, + <seealso + marker="erlang#cancel_timer/2"><c>erlang:cancel_timer/2</c></seealso>, + and <seealso + marker="erlang#read_timer/2"><c>erlang:read_timer/2</c></seealso>.</p> + <p> + Characteristics impact: Calls to the synchronous versions + of <c>erlang:cancel_timer()</c>, and + <c>erlang:read_timer()</c> may take substantially longer + time to complete than before. This occur when the timer + that is accessed is managed by a remote scheduler. You + typically want to use the new asynchronous option in + order to avoid blocking the calling process.</p> + <p> + Own Id: OTP-12650 Aux Id: OTP-11997 </p> + </item> + <item> + <p> + Specialize instructions from common assembler patterns</p> + <p>Specialize common instructions of <c>rem</c>, + <c>band</c>, <c>minus</c> and <c>plus</c> in the beam + loader. This will reduce the number of fetches and thus + lessen the instruction dispatch pressure during runtime + and speed up those operations in some common cases.</p> + <p>Specialize move patterns from x-registers to the stack + with a new <c>move_window</c> instruction. This change + will reduce instruction dispatch pressure.</p> + <p> + Own Id: OTP-12690</p> + </item> + <item> + <p> + Fix cross compilation for Android.</p> + <p> + Own Id: OTP-12693</p> + </item> + <item> + <p> + Fix incorrect use of autoconf macro AC_EGREP_CPP, which + could cause faulty configuration if run from a path + containing the string 'yes'.</p> + <p> + Own Id: OTP-12706</p> + </item> + <item> + <p> + Minimal Java version is now 1.6</p> + <p> + Own Id: OTP-12715</p> + </item> + <item> + <p> + Send format and args on process exit to error_logger</p> + <p> + Previously, the emulator would generate a whole string + with values and call the error_logger passing + <c>"~s~n"</c>. This changes it to a format string + containing <c>~p</c> with the respective values as + arguments.</p> + <p> + Own Id: OTP-12735</p> + </item> + <item> + <p> + Map error logger warnings to warning messages by default.</p> + <p> + Own Id: OTP-12755</p> + </item> + <item> + <p> + Configure architecture ppc64le architecture as a ppc64</p> + <p> + Own Id: OTP-12761</p> + </item> + <item> + <p> + Add function <c>enif_raise_exception</c> to allow a NIF + to raise an error exception with any type of reason.</p> + <p> + Own Id: OTP-12770</p> + </item> + <item> + <p> + Optimized node table statistics retrieval.</p> + <p> + Own Id: OTP-12777</p> + </item> + <item> + <p> + Map beam error logger warnings to warning messages by + default. Previously these messages were mapped to the + error channel by default.</p> + <p> + Own Id: OTP-12781</p> + </item> + <item> + <p> + gen_tcp:shutdown/2 is now asynchronous</p> + <p> + This solves the following problems with the old + implementation:</p> + <p> + It doesn't block when the TCP peer is idle or slow. This + is the expected behaviour when shutdown() is called: the + caller needs to be able to continue reading from the + socket, not be prevented from doing so.</p> + <p> + It doesn't truncate the output. The current version of + gen_tcp:shutdown/2 will truncate any outbound data in the + driver queue after about 10 seconds if the TCP peer is + idle of slow. Worse yet, it doesn't even inform anyone + that the data has been truncated: 'ok' is returned to the + caller; and a FIN rather than an RST is sent to the TCP + peer.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-12797</p> + </item> + <item> + <p> + Introduced delayed node table GC. This in order to avoid + oscillation of entries in and out of the tables. The + oscillation caused unnecessary lock contention on the + table locks. The delay length can be set by passing the + <seealso marker="erl#+zdntgc"><c>+zdntgc</c></seealso> + command line argument.</p> + <p> + Characteristics impact: The tables can grow to very large + sizes with unused entries if the node is get huge amounts + of short lived connections from other nodes. This problem + can be alleviated by shortening the length of the delay + using the <c>+zdntgc</c> command line argument.</p> + <p> + Own Id: OTP-12802</p> + </item> + <item> + <p>Improved implementation of <seealso + marker="erlang#statistics/1"><c>erlang:statistics</c></seealso><c>(io)</c> + in order to reduce contention between schedulers.</p> + <p>Characteristics impact: The actual call to + <c>erlang:statistics(io)</c> takes longer time to + complete, but the overall impact on the system is + improved.</p> + <p> + Own Id: OTP-12842</p> + </item> + <item> + <p> + There are many cases where user code needs to be able to + distinguish between a socket that was closed normally and + one that was aborted. Setting the option + {show_econnreset, true} enables the user to receive + ECONNRESET errors on both active and passive sockets.</p> + <p> + Own Id: OTP-12843</p> + </item> + <item> + <p> + Do not preallocate too large event pool</p> + <p> + A default pool size of 4000 is too excessive for the + common case. This corresponds directly to the number of + threads in the system. Change + ERTS_TS_EV_ALLOC_DEFAULT_POOL_SIZE to 2048. Change + ERTS_TS_EV_ALLOC_POOL_SIZE to 32.</p> + <p> + Own Id: OTP-12849</p> </item> </list> </section> </section> +<section><title>Erts 6.4.1.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A process communicating with a port via one of the + <c>erlang:port_*</c> BIFs could potentially end up in an + inconsistent state if the port terminated during the + communication. When this occurred the process could later + block in a <c>receive</c> even though it had messages + matching in its message queue.</p> + <p> + This bug was introduced in erts version 5.10 (OTP R16A).</p> + <p> + Own Id: OTP-13424 Aux Id: OTP-10336 </p> + </item> + <item> + <p> + Calls to <c>erl_drv_send_term()</c> or + <c>erl_drv_output_term()</c> from a non-scheduler thread + while the corresponding port was invalid caused the + emulator to enter an inconsistent state which eventually + caused an emulator crash.</p> + <p> + Own Id: OTP-13866</p> + </item> + <item> + <p>Driver and NIF operations accessing processes or ports + could cause an emulator crash when used from + non-scheduler threads. Those operations are:</p> <list> + <item><c>erl_drv_send_term()</c></item> + <item><c>driver_send_term()</c></item> + <item><c>erl_drv_output_term()</c></item> + <item><c>driver_output_term()</c></item> + <item><c>enif_send()</c></item> + <item><c>enif_port_command()</c></item> </list> + <p> + Own Id: OTP-13869</p> + </item> + <item> + <p> + Fix bug in <c>binary_to_term</c> for binaries created by + <c>term_to_binary </c> with option <c>compressed</c>. The + bug can cause <c>badarg</c> exception for a valid binary + when Erlang VM is linked against a <c>zlib</c> library of + version 1.2.9 or newer. Bug exists since OTP 17.0.</p> + <p> + Own Id: OTP-14159 Aux Id: ERL-340 </p> + </item> + <item> + <p> + Fixed bug in operator <c>bxor</c> causing erroneuos + result when one operand is a big <em>negative</em> + integer with the lowest <c>N*W</c> bits as zero and the + other operand not larger than <c>N*W</c> bits. <c>N</c> + is an integer of 1 or larger and <c>W</c> is 32 or 64 + depending on word size.</p> + <p> + Own Id: OTP-14514</p> + </item> + <item> + <p> + Fixed bug in <c>binary_to_term</c> and + <c>binary_to_atom</c> that could cause VM crash. + Typically happens when the last character of an UTF8 + string is in the range 128 to 255, but truncated to only + one byte. Bug exists in <c>binary_to_term</c> since ERTS + version 5.10.2 (OTP_R16B01) and <c>binary_to_atom</c> + since ERTS version 9.0 (OTP-20.0).</p> + <p> + Own Id: OTP-14590 Aux Id: ERL-474 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 6.4.1.6</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + When calling <c>garbage_collect/[1,2]</c> or + <c>check_process_code/[2,3]</c> from a process with a + higher priority than the priority of the process operated + on, the run queues could end up in an inconsistent state. + This bug has now been fixed.</p> + <p> + Own Id: OTP-13298 Aux Id: OTP-11388 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 6.4.1.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a bug that could cause a crash dump to become + almost empty.</p> + <p> + Own Id: OTP-13150</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 6.4.1.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The 'raw' socket option could not be used multiple times + in one call to any e.g gen_tcp function because only one + of the occurrences were used. This bug has been fixed, + and also a small bug concerning propagating error codes + from within inet:setopts/2.</p> + <p> + Own Id: OTP-11482 Aux Id: seq12872 </p> + </item> + </list> + </section> + +</section> + + <section><title>Erts 6.4.1</title> <section><title>Fixed Bugs and Malfunctions</title> @@ -572,8 +6698,7 @@ prioritized to the same extent as when eager check I/O is disabled.</p> <p>Eager check I/O can be enabled using the <c>erl</c> - command line argument: <seealso - marker="erl#+secio"><c>+secio true</c></seealso></p> + command line argument: <c>+secio true</c></p> <p>Characteristics impact when enabled:</p> <list> <item>Lower latency and smoother management of externally triggered I/O operations.</item> <item>A slightly reduced @@ -616,7 +6741,7 @@ <p> Improved support for atomic memory operations provided by the <url - href="https://github.com/ivmai/libatomic_ops/"><c>libatomic_ops</c></url> + href="https://github.com/ivmai/libatomic_ops/">libatomic_ops</url> library. Most importantly support for use of native double word atomics when implemented by <c>libatomic_ops</c> (for example, implemented for ARM).</p> @@ -1583,22 +7708,28 @@ <p> EEP43: New data type - Maps</p> <p> - With Maps you may for instance: <taglist> <item><c>M0 = - #{ a => 1, b => 2}, % create - associations</c></item> <item><c>M1 = M0#{ a := 10 }, % - update values</c></item> <item><c>M2 = M1#{ "hi" => - "hello"}, % add new associations</c></item> <item><c>#{ - "hi" := V1, a := V2, b := V3} = M2. % match keys with - values</c></item> </taglist></p> + With Maps you may for instance:</p> + <taglist> + <tag/> <item><c>M0 = #{ a => 1, b => 2}, % create + associations</c></item> + <tag/><item><c>M1 = M0#{ a := 10 }, % update values</c></item> + <tag/><item><c>M2 = M1#{ "hi" => + "hello"}, % add new associations</c></item> + <tag/><item><c>#{ "hi" := V1, a := V2, b := V3} = M2. + % match keys with values</c></item> + </taglist> <p> For information on how to use Maps please see Map Expressions in the <seealso marker="doc/reference_manual:expressions#map_expressions"> Reference Manual</seealso>.</p> <p> The current implementation is without the following - features: <taglist> <item>No variable keys</item> - <item>No single value access</item> <item>No map - comprehensions</item> </taglist></p> + features:</p> + <taglist> + <tag/><item>No variable keys</item> + <tag/><item>No single value access</item> + <tag/><item>No map comprehensions</item> + </taglist> <p> Note that Maps is <em>experimental</em> during OTP 17.0.</p> <p> @@ -3150,7 +9281,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> @@ -3531,7 +9662,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> @@ -3758,8 +9889,7 @@ <p> Fix erl_prim_loader errors in handling of primary archive. The following errors have been corrected:</p> - <p> - <list> <item> If primary archive was named "xxx", then a + <list> <item> If primary archive was named "xxx", then a file in the same directory named "xxxyyy" would be interpreted as a file named "yyy" inside the archive. </item> <item> erl_prim_loader did not correctly create @@ -3774,7 +9904,8 @@ erl_prim_loader:list_dir/1 would sometimes return an empty string inside the file list. This was a virtual element representing the top directory of the archive. - This has been removed. </item> </list></p> + This has been removed. </item> + </list> <p> Thanks to Tuncer Ayaz and Shunichi Shinohara for reporting and co-authoring corrections.</p> @@ -4508,7 +10639,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> @@ -5723,7 +11854,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> @@ -6217,12 +12348,12 @@ Own Id: OTP-8726 Aux Id: seq11617 </p> </item> <item> - <p>Fix libm linking with --as-needed flag + <p>Fix libm linking with --as-needed flag</p> <p> When building with "--as-needed" linker flags on Linux the build will fail. This has now been fixed.</p> <p> - (Thanks to Christian Faulhammer)</p></p> + (Thanks to Christian Faulhammer)</p> <p> Own Id: OTP-8728</p> </item> @@ -6561,7 +12692,7 @@ <c>update_cpu_info</c> will make the runtime system reread and update the internally stored CPU information. For more information see the documentation of <seealso - marker="erlang#update_cpu_info">erlang:system_info(update_cpu_info)</seealso>.</p> + marker="erlang#system_info_update_cpu_info">erlang:system_info(update_cpu_info)</seealso>.</p> <p> The CPU topology is now automatically detected on Windows systems with less than 33 logical processors. The runtime @@ -6714,7 +12845,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> @@ -7408,9 +13539,9 @@ dynamically linking against <c>libssl.so</c> and <c>libcrypto.so</c>. The runtime library search path has also been extended. </item><item> The <c>configure</c> - scripts of <c>erl_interface</c> and <c>odbc</c> now + scripts of Erl_interface and ODBC now search for thread libraries and thread library quirks the - same way as <c>erts</c> do. </item><item> The + same way as ERTS do. </item><item> The <c>configure</c> script of the <c>odbc</c> application now also looks for odbc libraries in <c>lib64</c> and <c>lib/64</c> directories when building on a 64-bit @@ -8526,7 +14657,7 @@ </item> <item> <p> - A corrected bug in <c>ets</c> for <c>bag</c> and + A corrected bug in ETS for <c>bag</c> and <c>duplicate_bag</c>. A <c>delete/2</c> or <c>lookup_element/3</c> could miss objects in a fixed table if one or more objects with the same key had @@ -8968,7 +15099,7 @@ <list> <item> <p> - A corrected bug in <c>ets</c> for <c>bag</c> and + A corrected bug in ETS for <c>bag</c> and <c>duplicate_bag</c>. A <c>delete/2</c> or <c>lookup_element/3</c> could miss objects in a fixed table if one or more objects with the same key had diff --git a/erts/doc/src/notes_history.xml b/erts/doc/src/notes_history.xml index 4420311912..0bc2ab1383 100644 --- a/erts/doc/src/notes_history.xml +++ b/erts/doc/src/notes_history.xml @@ -4,20 +4,21 @@ <chapter> <header> <copyright> - <year>2006</year><year>2013</year> + <year>2006</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> diff --git a/erts/doc/src/part.xml b/erts/doc/src/part.xml index 7b17b5b551..05e9a24af8 100644 --- a/erts/doc/src/part.xml +++ b/erts/doc/src/part.xml @@ -4,20 +4,21 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -29,13 +30,14 @@ <file>part.xml</file> </header> <description> - <p>The Erlang Runtime System Application <em>ERTS</em>.</p> </description> + <xi:include href="introduction.xml"/> <xi:include href="communication.xml"/> <xi:include href="time_correction.xml"/> <xi:include href="match_spec.xml"/> <xi:include href="crash_dump.xml"/> <xi:include href="alt_dist.xml"/> + <xi:include href="alt_disco.xml"/> <xi:include href="absform.xml"/> <xi:include href="tty.xml"/> <xi:include href="driver.xml"/> diff --git a/erts/doc/src/part_notes.xml b/erts/doc/src/part_notes.xml deleted file mode 100644 index b5c8f0af09..0000000000 --- a/erts/doc/src/part_notes.xml +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2004</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - </legalnotice> - - <title>ERTS Release Notes</title> - <prepared></prepared> - <docno></docno> - <date>2004-09-07</date> - <rev>1.0</rev> - </header> - <description> - <p>The Erlang Runtime System application <em>ERTS</em>.</p> - <p>For information about older versions, see - <url href="part_notes_history_frame.html">Release Notes History</url>.</p> - </description> - <xi:include href="notes.xml"/> -</part> - diff --git a/erts/doc/src/part_notes_history.xml b/erts/doc/src/part_notes_history.xml deleted file mode 100644 index a99fa4a17f..0000000000 --- a/erts/doc/src/part_notes_history.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!DOCTYPE part SYSTEM "part.dtd"> - -<part xmlns:xi="http://www.w3.org/2001/XInclude"> - <header> - <copyright> - <year>2006</year><year>2013</year> - <holder>Ericsson AB. All Rights Reserved.</holder> - </copyright> - <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. - - </legalnotice> - - <title>ERTS Release Notes History</title> - <prepared></prepared> - <docno></docno> - <date></date> - <rev></rev> - </header> - <description> - <p>The Erlang Runtime System application <em>ERTS</em>.</p> - </description> - <xi:include href="notes_history.xml"/> -</part> - diff --git a/erts/doc/src/ref_man.xml b/erts/doc/src/ref_man.xml index 8ed7090a61..0617463a7b 100644 --- a/erts/doc/src/ref_man.xml +++ b/erts/doc/src/ref_man.xml @@ -4,20 +4,21 @@ <application xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -29,14 +30,6 @@ <file>application.xml</file> </header> <description> - <p>The Erlang Runtime System Application <em>ERTS</em>.</p> - <note> - <p>By default, the <c><![CDATA[erts]]></c> is only guaranteed to be compatible - with other Erlang/OTP components from the same release as - the <c><![CDATA[erts]]></c> itself. See the documentation of the system flag - <seealso marker="erl#compat_rel">+R</seealso> on how to communicate - with Erlang/OTP components from earlier releases.</p> - </note> </description> <xi:include href="erl_prim_loader.xml"/> <xi:include href="erlang.xml"/> @@ -55,5 +48,6 @@ <xi:include href="driver_entry.xml"/> <xi:include href="erts_alloc.xml"/> <xi:include href="erl_nif.xml"/> + <xi:include href="erl_tracer.xml"/> </application> diff --git a/erts/doc/src/run_erl.xml b/erts/doc/src/run_erl.xml index 28e94c6da8..fa36457489 100644 --- a/erts/doc/src/run_erl.xml +++ b/erts/doc/src/run_erl.xml @@ -4,20 +4,21 @@ <comref> <header> <copyright> - <year>1999</year><year>2013</year> + <year>1999</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -27,137 +28,189 @@ <docno></docno> <approved></approved> <checked></checked> - <date>99-12-15</date> + <date>1999-12-15</date> <rev></rev> <file>run_erl.xml</file> </header> <com>run_erl</com> - <comsummary>Redirect Erlang input and output streams on Solaris®</comsummary> + <comsummary>Redirect Erlang input and output streams on Unix systems.</comsummary> <description> - <p>This describes the <c><![CDATA[run_erl]]></c> program specific to - Solaris/Linux. This program redirect the standard input and standard - output streams so that all output can be logged. It also let the - program <c><![CDATA[to_erl]]></c> connect to the Erlang console making it - possible to monitor and debug an embedded system remotely.</p> - <p>You can read more about the use in the <c><![CDATA[Embedded System User's Guide]]></c>.</p> + <p>The <c><![CDATA[run_erl]]></c> program is specific to Unix systems. + This program redirects the standard input and standard + output streams so that all output can be logged. It also lets the + program <c><![CDATA[to_erl]]></c> connect to the Erlang console, making + it possible to monitor and debug an embedded system remotely.</p> + + <p>For more information about the use, see the + <seealso marker="doc/embedded:embedded_solaris"> + Embedded System User's Guide</seealso> in System Documentation.</p> </description> + <funcs> <func> - <name>run_erl [-daemon] pipe_dir/ log_dir "exec command [command_arguments]"</name> - <fsummary>Start the Erlang emulator without attached terminal</fsummary> + <name>run_erl [-daemon] pipe_dir/ log_dir "exec command + arg1 arg2 ..."</name> + <fsummary>Start the Erlang emulator without attached terminal.</fsummary> <desc> - <p>The <c><![CDATA[run_erl]]></c> program arguments are:</p> + <p>Arguments:</p> <taglist> - <tag>-daemon</tag> - <item>This option is highly recommended. It makes run_erl run in - the background completely detached from any controlling - terminal and the command returns to the caller immediately. - Without this option, run_erl must be started using several - tricks in the shell to detach it completely from the - terminal in use when starting it. The option must be the - first argument to run_erl on the command line.</item> - <tag>pipe_dir</tag> - <item>This is where to put the named pipe, usually - <c><![CDATA[/tmp/]]></c> on Unix or <c><![CDATA[/pipe/]]></c> on OSE. It shall be suffixed by a <c><![CDATA[/]]></c> (slash), - i.e. not <c><![CDATA[/tmp/epipies]]></c>, but <c><![CDATA[/tmp/epipes/]]></c>. </item> - <tag>log_dir</tag> - <item>This is where the log files are written. There will be one - log file, <c><![CDATA[run_erl.log]]></c> that log progress and - warnings from the <c><![CDATA[run_erl]]></c> program itself and there - will be up to five log files at maximum 100KB each (both - number of logs and sizes can be - changed by environment variables, see below) with - the content of the standard streams from and to the - command. When the logs are full <c><![CDATA[run_erl]]></c> will delete - and reuse the oldest log file.</item> - <tag>"exec command [command_arguments]"</tag> - <item>In the third argument <c><![CDATA[command]]></c> is the to execute - where everything written to stdin and stdout is logged to - <c><![CDATA[log_dir]]></c>.</item> + <tag><c>-daemon</c></tag> + <item> + <p>This option is highly recommended. It makes <c>run_erl</c> run + in the background completely detached from any controlling + terminal and the command returns to the caller immediately. + Without this option, <c>run_erl</c> must be started using several + tricks in the shell to detach it completely from the + terminal in use when starting it. The option must be the + first argument to <c>run_erl</c> on the command line.</p> + </item> + <tag><c>pipe_dir</c></tag> + <item> + <p>The named pipe, usually <c><![CDATA[/tmp/]]></c>. It must be + suffixed by a <c><![CDATA[/]]></c> (slash), that is, + <c><![CDATA[/tmp/epipes/]]></c>, not + <c><![CDATA[/tmp/epipes]]></c>.</p> + </item> + <tag><c>log_dir</c></tag> + <item> + <p>The log files, that is:</p> + <list type="bulleted"> + <item> + <p>One log file, <c><![CDATA[run_erl.log]]></c>, which logs + progress and warnings from the <c><![CDATA[run_erl]]></c> + program itself.</p> + </item> + <item> + <p>Up to five log files at maximum 100 KB each with the content + of the standard streams from and to the command. (Both the + number of logs and sizes can be changed by environment + variables, see section <seealso + marker="#environment_variables">Environment Variables</seealso> + below.)</p> + <p>When the logs are full, <c><![CDATA[run_erl]]></c> deletes + and reuses the oldest log file.</p> + </item> + </list> + </item> + <tag><c>"exec command arg1 arg2 ..."</c></tag> + <item> + <p>A space-separated string specifying the program to be executed. + The second field is typically a command name such as <c>erl</c>.</p> + </item> </taglist> </desc> </func> </funcs> <section> - <title>Notes concerning the log files</title> - <p>While running, run_erl (as stated earlier) sends all output, - uninterpreted, to a log file. The file is called - <c><![CDATA[erlang.log.N]]></c>, where N is a number. When the log is "full", - default after 100KB, run_erl starts to log in file - <c><![CDATA[erlang.log.(N+1)]]></c>, until N reaches a certain number (default - 5), where after N starts at 1 again and the oldest files start - getting overwritten. If no output comes from the erlang shell, but - the erlang machine still seems to be alive, an "ALIVE" message is - written to the log, it is a timestamp and is written, by default, - after 15 minutes of inactivity. Also, if output from erlang is - logged but it's been more than 5 minutes (default) since last time - we got anything from erlang, a timestamp is written in the - log. The "ALIVE" messages look like this:</p> + <title>Notes concerning the Log Files</title> + <p>While running, <c>run_erl</c> sends all output, + uninterpreted, to a log file. The file is named + <c><![CDATA[erlang.log.N]]></c>, where <c>N</c> is an integer. When the + log is "full" (default log size is 100 KB), <c>run_erl</c> starts to log + in file <c><![CDATA[erlang.log.(N+1)]]></c>, until <c>N</c> reaches a + certain number (default 5), whereupon <c>N</c> starts at 1 again and + the oldest files start getting overwritten.</p> + + <p>If no output comes from the Erlang shell, but + the Erlang machine still seems to be alive, an "ALIVE" message is + written to the log; it is a time stamp and is written, by default, + after 15 minutes of inactivity. Also, if output from Erlang is + logged, but more than 5 minutes (default) has passed since last time + we got anything from Erlang, a time stamp is written in the + log. The "ALIVE" messages look as follows:</p> + <code type="none"><![CDATA[ - ===== ALIVE <date-time-string> - ]]></code> - <p>while the other timestamps look like this:</p> +===== ALIVE <date-time-string> ]]></code> + + <p>The other time stamps look as follows:</p> + <code type="none"><![CDATA[ - ===== <date-time-string> - ]]></code> - <p>The <c><![CDATA[date-time-string]]></c> is the date and time the message is - written, default in local time (can be changed to GMT if one wants - to) and is formatted with the ANSI-C function <c><![CDATA[strftime]]></c> - using the format string <c><![CDATA[%a %b %e %T %Z %Y]]></c>, which produces - messages on the line of <c><![CDATA[===== ALIVE Thu May 15 10:13:36 MEST 2003]]></c>, this can be changed, see below.</p> +===== <date-time-string> ]]></code> + + <p><c><![CDATA[date-time-string]]></c> is the date and time the message is + written, default in local time (can be changed to UTC if needed). + It is formatted with the ANSI-C function <c><![CDATA[strftime]]></c> + using the format string <c><![CDATA[%a %b %e %T %Z %Y]]></c>, which + produces messages like + <c><![CDATA[===== ALIVE Thu May 15 10:13:36 MEST 2003]]></c>; this can + be changed, see the next section.</p> </section> <section> - <title>Environment variables</title> - <p>The following environment variables are recognized by run_erl - and change the logging behavior. Also see the notes above to get - more info on how the log behaves.</p> + <marker id="environment_variables"/> + <title>Environment Variables</title> + <p>The following environment variables are recognized by <c>run_erl</c> + and change the logging behavior. For more information, see the previous + section.</p> + <taglist> - <tag>RUN_ERL_LOG_ALIVE_MINUTES</tag> - <item>How long to wait for output (in minutes) before writing an - "ALIVE" message to the log. Default is 15, can never be less - than 1.</item> - <tag>RUN_ERL_LOG_ACTIVITY_MINUTES</tag> - <item>How long erlang need to be inactive before output will be - preceded with a timestamp. Default is - RUN_ERL_LOG_ALIVE_MINUTES div 3, but never less than 1.</item> - <tag>RUN_ERL_LOG_ALIVE_FORMAT</tag> - <item>Specifies another format string to be used in the strftime - C library call. i.e specifying this to <c><![CDATA["%e-%b-%Y, %T %Z"]]></c> - will give log messages with timestamps looking like - <c><![CDATA[15-May-2003, 10:23:04 MET]]></c> etc. See the documentation - for the C library function strftime for more - information. Default is <c><![CDATA["%a %b %e %T %Z %Y"]]></c>.</item> - <tag>RUN_ERL_LOG_ALIVE_IN_UTC</tag> - <item>If set to anything else than "0", it will make all - times displayed by run_erl to be in UTC (GMT,CET,MET, without - DST), rather than - in local time. This does not affect data coming from erlang, - only the logs output directly by run_erl. The application - <c><![CDATA[sasl]]></c> can be modified accordingly by setting the erlang - application variable <c><![CDATA[utc_log]]></c> to <c><![CDATA[true]]></c>.</item> - <tag>RUN_ERL_LOG_GENERATIONS</tag> - <item>Controls the number of log files written before older - files are being reused. Default is 5, minimum is 2, maximum is 1000.</item> - <tag>RUN_ERL_LOG_MAXSIZE</tag> - <item>The size (in bytes) of a log file before switching to a - new log file. Default is 100000, minimum is 1000 and maximum is - approximately 2^30.</item> - <tag>RUN_ERL_DISABLE_FLOWCNTRL</tag> - <item>If defined, disables input and output flow control for the pty opend by run_erl. - Useful if you want to remove any risk of accidentally blocking the flow control - by hit Ctrl-S (instead of Ctrl-D to detach). - Which may result in blocking of the entire beam process - and in the case of running heart as supervisor - even the heart process will be blocked when writing log message to terminal. - Leaving the heart process unable to do its work.</item> + <tag><c>RUN_ERL_LOG_ALIVE_MINUTES</c></tag> + <item> + <p>How long to wait for output (in minutes) before writing an + "ALIVE" message to the log. Defaults to 15, minimum is 1.</p> + </item> + <tag><c>RUN_ERL_LOG_ACTIVITY_MINUTES</c></tag> + <item> + <p>How long Erlang needs to be inactive before output is + preceded with a time stamp. Defaults to + <c>RUN_ERL_LOG_ALIVE_MINUTES div 3</c>, minimum is 1.</p> + </item> + <tag><c>RUN_ERL_LOG_ALIVE_FORMAT</c></tag> + <item> + <p>Specifies another format string to be used in the <c>strftime</c> + C library call. That is, specifying this to + <c><![CDATA["%e-%b-%Y, %T %Z"]]></c> gives + log messages with time stamps like + <c><![CDATA[15-May-2003, 10:23:04 MET]]></c>. For more information, + see the documentation for the C library function <c>strftime</c>. + Defaults to <c><![CDATA["%a %b %e %T %Z %Y"]]></c>.</p> + </item> + <tag><c>RUN_ERL_LOG_ALIVE_IN_UTC</c></tag> + <item> + <p>If set to anything else than <c>0</c>, it makes all + times displayed by <c>run_erl</c> to be in UTC (GMT, CET, MET, + without Daylight Saving Time), rather than in local time. + This does not affect data coming from Erlang, + only the logs output directly by <c>run_erl</c>. Application + SASL can be modified accordingly by setting the Erlang + application variable <c><![CDATA[utc_log]]></c> to + <c><![CDATA[true]]></c>.</p> + </item> + <tag><c>RUN_ERL_LOG_GENERATIONS</c></tag> + <item> + <p>Controls the number of log files written before older + files are reused. Defaults to 5, minimum is 2, maximum is 1000.</p> + <p>Note that, as a way to indicate the newest file, <c>run_erl</c> will + delete the oldest log file to maintain a "hole" in the file + sequences. For example, if log files #1, #2, #4 and #5 exists, that + means #2 is the latest and #4 is the oldest. You will therefore at most + get one less log file than the value set by + <c>RUN_ERL_LOG_GENERATIONS</c>.</p> + </item> + <tag><c>RUN_ERL_LOG_MAXSIZE</c></tag> + <item> + <p>The size, in bytes, of a log file before switching to a + new log file. Defaults to 100000, minimum is 1000, maximum is + about 2^30.</p> + </item> + <tag><c>RUN_ERL_DISABLE_FLOWCNTRL</c></tag> + <item> + <p>If defined, disables input and output flow control for the pty + opend by <c>run_erl</c>. Useful if you want to remove any risk of + accidentally blocking the flow control by using Ctrl-S (instead of + Ctrl-D to detach), which can result in blocking of the entire Beam + process, and in the case of running heart as supervisor even the + heart process becomes blocked when writing log message to terminal, + leaving the heart process unable to do its work.</p> + </item> </taglist> </section> <section> - <title>SEE ALSO</title> - <p>start(1), start_erl(1)</p> + <title>See Also</title> + <p><seealso marker="start"><c>start(1)</c></seealso>, + <seealso marker="start_erl"><c>start_erl(1)</c></seealso></p> </section> </comref> diff --git a/erts/doc/src/specs.xml b/erts/doc/src/specs.xml index 41a3984659..ed6be650e5 100644 --- a/erts/doc/src/specs.xml +++ b/erts/doc/src/specs.xml @@ -2,6 +2,7 @@ <specs xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include href="../specs/specs_erl_prim_loader.xml"/> <xi:include href="../specs/specs_erlang.xml"/> + <xi:include href="../specs/specs_erl_tracer.xml"/> <xi:include href="../specs/specs_init.xml"/> <xi:include href="../specs/specs_zlib.xml"/> </specs> diff --git a/erts/doc/src/start.xml b/erts/doc/src/start.xml index e9a5714f93..6eac47fe94 100644 --- a/erts/doc/src/start.xml +++ b/erts/doc/src/start.xml @@ -4,20 +4,21 @@ <comref> <header> <copyright> - <year>1999</year><year>2013</year> + <year>1999</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -27,38 +28,46 @@ <docno></docno> <approved></approved> <checked></checked> - <date>99-12-15</date> + <date>1999-12-15</date> <rev></rev> <file>start.xml</file> </header> <com>start</com> - <comsummary>OTP start script example for Unix</comsummary> + <comsummary>OTP start script example for Unix.</comsummary> <description> - <p>This describes the <c><![CDATA[start]]></c> script that is an example script on - how to startup the Erlang system in embedded mode on Unix.</p> - <p>You can read more about the use in the <c><![CDATA[Embedded System User's Guide]]></c>.</p> + <p>The <c><![CDATA[start]]></c> script is an example script on + how to start up the Erlang system in embedded mode on Unix.</p> + + <p>For more information about the use, see the + <seealso marker="doc/embedded:embedded_solaris"> + Embedded System User's Guide</seealso> in System Documentation.</p> </description> + <funcs> <func> <name>start [ data_file ]</name> - <fsummary>This is an example script on how to startup the Erlang system in embedded mode on Unix.</fsummary> + <fsummary>Example script on how to start up the Erlang system in embedded + mode on Unix.</fsummary> <desc> - <p>In the example there is one argument</p> + <p>Argument:</p> <taglist> - <tag>data_file</tag> - <item>Optional, specifies what <c><![CDATA[start_erl.data]]></c> file - to use.</item> + <tag><c>data_file</c></tag> + <item> + <p>Optional. Specifies what <c><![CDATA[start_erl.data]]></c> file + to use.</p> + </item> </taglist> - <p>There is also an environment variable <c><![CDATA[RELDIR]]></c> that can - be set prior to calling this example that set the directory + <p>Environment variable <c><![CDATA[RELDIR]]></c> can + be set before calling this example, which sets the directory where to find the release files.</p> </desc> </func> </funcs> <section> - <title>SEE ALSO</title> - <p>run_erl(1), start_erl(1)</p> + <title>See Also</title> + <p><seealso marker="run_erl"><c>run_erl(1)</c></seealso>, + <seealso marker="start_erl"><c>start_erl(1)</c></seealso></p> </section> </comref> diff --git a/erts/doc/src/start_erl.xml b/erts/doc/src/start_erl.xml index fe808f7737..4887d4606e 100644 --- a/erts/doc/src/start_erl.xml +++ b/erts/doc/src/start_erl.xml @@ -4,20 +4,21 @@ <comref> <header> <copyright> - <year>1998</year><year>2013</year> + <year>1998</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -27,117 +28,142 @@ <docno></docno> <approved></approved> <checked></checked> - <date>98-08-05</date> + <date>1998-08-05</date> <rev></rev> <file>start_erl.xml</file> </header> <com>start_erl</com> - <comsummary>Start Erlang for embedded systems on Windows NT®</comsummary> + <comsummary>Start Erlang for embedded systems on Windows systems.</comsummary> <description> - <p>This describes the <c><![CDATA[start_erl]]></c> program specific to Windows - NT. Although there exists programs with the same name on other - platforms, their functionality is not the same.</p> - <p>The <c><![CDATA[start_erl]]></c> program is distributed both in compiled + <p>The <c><![CDATA[start_erl]]></c> program is specific to + Windows NT/2000/XP (and later versions of Windows). + Although there are programs with the same name on other + platforms, their functionality is different.</p> + + <p>This program is distributed both in compiled form (under <Erlang root>\\erts-<version>\\bin) and - in source form (under <Erlang - root>\\erts-<version>\\src). - The purpose of the source code is to make it possible to easily - customize the program for local needs, such as cyclic restart - detection etc. There is also a "make"-file, written for the - <c><![CDATA[nmake]]></c> program distributed with Microsoft® Visual - C++®. The program can however be compiled with - any Win32 C compiler (possibly with slight modifications).</p> - <p>The purpose of the program is to aid release handling on - Windows NT®. The program should be called by the + in source form (under <Erlang root>\\erts-<version>\\src). + The purpose of the source code is to ease customization of the + program for local needs, such as cyclic restart + detection. There is also a "make"-file, written for the + <c><![CDATA[nmake]]></c> program distributed with Microsoft Visual + C++. This program can, however, be compiled with + any Win32 C compiler (possibly with minor modifications).</p> + + <p>This program aids release handling on Windows systems. + The program is to be called by the <c><![CDATA[erlsrv]]></c> program, read up the release data file - start_erl.data and start Erlang. Certain options to start_erl - are added and removed by the release handler during upgrade with - emulator restart (more specifically the <c><![CDATA[-data]]></c> option).</p> + <c>start_erl.data</c>, and start Erlang. Some options to + <c>start_erl</c> are added and removed by the release handler + during upgrade with emulator restart (more specifically option + <c><![CDATA[-data]]></c>).</p> </description> + <funcs> <func> <name>start_erl [<erl options>] ++ [<start_erl options>]</name> - <fsummary>Start the Erlang emulator with the correct release data</fsummary> + <fsummary>Start the Erlang emulator with the correct release data. + </fsummary> <desc> - <p>The <c><![CDATA[start_erl]]></c> program in its original form + <p>The <c><![CDATA[start_erl]]></c> program in its original form recognizes the following options:</p> <taglist> - <tag>++</tag> - <item>Mandatory, delimits start_erl options from normal Erlang - options. Everything on the command line <em>before</em> the - <c><![CDATA[++]]></c> is interpreted as options to be sent to the - <c><![CDATA[erl]]></c> program. Everything <em>after</em><c><![CDATA[++]]></c> is - interpreted as options to <c><![CDATA[start_erl]]></c> itself.</item> - <tag>-reldir <release root></tag> - - <item>Mandatory if the environment variable - <c><![CDATA[RELDIR]]></c> is not specified and no - <c>-rootdir</c> option is given. Tells start_erl where the - root of the release tree is placed in the file-system (typically - <Erlang root>\\releases). The - <c><![CDATA[start_erl.data]]></c> file is expected to be - placed in this directory (if not otherwise specified). If - only the <c>-rootdir</c> option is given, the directory is - assumed to be <Erlang root>\\releases.</item> - - <tag>-rootdir <Erlang root directory></tag> - - <item>Mandatory if <c>-reldir</c> is not given and there is - no <c><![CDATA[RELDIR]]></c> in the environment. This - specifies the Erlang installation root directory (under - which the <c>lib</c>, <c>releases</c> and - <c>erts-<Version></c> directories are placed). If only - <c>-reldir</c> (or the environment variable - <c><![CDATA[RELDIR]]></c>) is given, the Erlang root is assumed to - be the directory exactly one level above the release - directory.</item> - - <tag>-data <data file name></tag> - <item>Optional, specifies another data file than start_erl.data - in the <release root>. It is specified relative to the - <release root> or absolute (including drive letter - etc.). This option is used by the release handler during - upgrade and should not be used during normal - operation. The release data file should not normally be - named differently.</item> - <tag>-bootflags <boot flags file name></tag> - <item>Optional, specifies a file name relative to actual release - directory (that is the subdirectory of <release - root> where the <c><![CDATA[.boot]]></c> file etc. are placed). - The contents of this file is appended to the command line - when Erlang is started. This makes it easy to start the - emulator with different options for different releases.</item> + <tag><c>++</c></tag> + <item> + <p>Mandatory. Delimits <c>start_erl</c> options from normal Erlang + options. Everything on the command line <em>before</em> + <c><![CDATA[++]]></c> is interpreted as options to be sent to the + <c><![CDATA[erl]]></c> program. Everything <em>after</em> + <c><![CDATA[++]]></c> is interpreted as options to + <c><![CDATA[start_erl]]></c> itself.</p> + </item> + <tag><c>-reldir <release root></c></tag> + <item> + <p>Mandatory if environment variable + <c><![CDATA[RELDIR]]></c> is not specified and no + <c>-rootdir</c> option is specified. Tells <c>start_erl</c> where + the root of the release tree is located in the file system + (typically <Erlang root>\\releases). The + <c><![CDATA[start_erl.data]]></c> file is expected to be + located in this directory (unless otherwise specified). If + only option <c>-rootdir</c> is specified, the directory is + assumed to be <Erlang root>\\releases.</p> + </item> + <tag><c>-rootdir <Erlang root directory></c></tag> + <item> + <p>Mandatory if <c>-reldir</c> is not specified and no + <c><![CDATA[RELDIR]]></c> exists in the environment. This + specifies the Erlang installation root directory (under + which the <c>lib</c>, <c>releases</c>, and + <c>erts-<Version></c> directories are located). If only + <c>-reldir</c> (or environment variable <c><![CDATA[RELDIR]]></c>) + is specified, the Erlang root is assumed to + be the directory exactly one level above the release + directory.</p> + </item> + <tag><c>-data <data file name></c></tag> + <item> + <p>Optional. Specifies another data file than <c>start_erl.data</c> + in the <release root>. It is specified relative to the + <release root> or absolute (including drive letter, and so + on). This option is used by the release handler during + upgrade and is not to be used during normal + operation. Normally the release data file is not to be + named differently.</p> + </item> + <tag><c>-bootflags <boot flags file name></c></tag> + <item> + <p>Optional. Specifies a file name relative to the release + directory (that is, the subdirectory of <release root> + where the <c><![CDATA[.boot]]></c> file and others are located). + The contents of this file is appended to the command line + when Erlang is started. This makes it easy to start the + emulator with different options for different releases.</p> + </item> </taglist> </desc> </func> </funcs> <section> - <title>NOTES</title> - <p>As the source code is distributed, it can easily be modified to - accept other options. The program must still accept the - <c><![CDATA[-data]]></c> option with the semantics described above for the - release handler to work correctly.</p> - <p>The Erlang emulator is found by examining the registry keys for - the emulator version specified in the release data file. The new - emulator needs to be properly installed before the upgrade for - this to work.</p> - <p>Although the program is located together with files specific to - emulator version, it is not expected to be specific to the - emulator version. The release handler does <em>not</em> change the - <c><![CDATA[-machine]]></c> option to <c><![CDATA[erlsrv]]></c> during emulator restart. - Place the (possibly customized) <c><![CDATA[start_erl]]></c> program so that - it is not overwritten during upgrade. </p> - <p>The <c><![CDATA[erlsrv]]></c> program's default options are not - sufficient for release handling. The machine <c><![CDATA[erlsrv]]></c> - starts should be specified as the <c><![CDATA[start_erl]]></c> program and - the arguments should contain the <c><![CDATA[++]]></c> followed by desired - options.</p> + <title>Notes</title> + <list type="bulleted"> + <item> + <p>As the source code is distributed, it can easily be modified to + accept other options. The program must still accept option + <c><![CDATA[-data]]></c> with the semantics described above for the + release handler to work correctly.</p> + </item> + <item> + <p>The Erlang emulator is found by examining the registry keys for + the emulator version specified in the release data file. The new + emulator must be properly installed before the upgrade for + this to work.</p> + </item> + <item> + <p>Although the program is located together with files specific to the + emulator version, it is not expected to be specific to the + emulator version. The release handler does <em>not</em> change option + <c><![CDATA[-machine]]></c> to <c><![CDATA[erlsrv]]></c> during + emulator restart. Locate the (possibly customized) + <c><![CDATA[start_erl]]></c> program so that it is not overwritten + during upgrade.</p> + </item> + <item> + <p>The default options of the <c><![CDATA[erlsrv]]></c> program are not + sufficient for release handling. The machine started by + <c><![CDATA[erlsrv]]></c> is be specified as the + <c><![CDATA[start_erl]]></c> program and the arguments are to contain + <c><![CDATA[++]]></c> followed by the desired options.</p> + </item> + </list> </section> <section> - <title>SEE ALSO</title> - <p>erlsrv(1), release_handler(3)</p> + <title>See Also</title> + <p><seealso marker="erlsrv"><c>erlsrv(1)</c></seealso>, + <seealso marker="sasl:release_handler"> + <c>release_handler(3)</c></seealso></p> </section> </comref> diff --git a/erts/doc/src/time_correction.xml b/erts/doc/src/time_correction.xml index 7f7c28fc30..a9f06d8a7d 100644 --- a/erts/doc/src/time_correction.xml +++ b/erts/doc/src/time_correction.xml @@ -4,25 +4,26 @@ <chapter> <header> <copyright> - <year>1999</year><year>2014</year> + <year>1999</year><year>2018</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> - <title>Time and time correction in Erlang</title> - <prepared>Patrik Nyblom</prepared> + <title>Time and Time Correction in Erlang</title> + <prepared></prepared> <responsible></responsible> <docno></docno> <approved></approved> @@ -31,244 +32,923 @@ <rev>PA1</rev> <file>time_correction.xml</file> </header> + + <section> + <title>New Extended Time Functionality</title> + <note><p>As from Erlang/OTP 18 (ERTS 7.0) the time functionality + has been extended. This includes a + <seealso marker="#The_New_Time_API">new API</seealso> + for time and + <seealso marker="#Time_Warp_Modes">time warp + modes</seealso> that change the system behavior when + system time changes.</p> + + <p>The <seealso marker="#No_Time_Warp_Mode">default + time warp mode</seealso> has the same behavior as before, and the + old API still works. Thus, you are not required to change + anything unless you want to. However, <em>you are strongly + encouraged to use the new API</em> instead of the old API based + on <seealso marker="erlang#now/0"><c>erlang:now/0</c></seealso>. + <c>erlang:now/0</c> is deprecated, as it is and + will be a scalability bottleneck.</p> + + <p>By using the new API, you + automatically get scalability and performance improvements. This + also enables you to use the + <seealso marker="#Multi_Time_Warp_Mode">multi-time warp mode</seealso> + that improves accuracy and precision of time measurements.</p> + </note> + </section> + + <section> + <title>Terminology</title> + <p>To make it easier to understand this section, some terms + are defined. This is a mix of our own terminology + (Erlang/OS system time, Erlang/OS monotonic time, time warp) + and globally accepted terminology.</p> + + <marker id="Monotonically_Increasing"/> + <section> + <title>Monotonically Increasing</title> + <p>In a monotonically increasing sequence of values, all values + that have a predecessor are either larger than or equal to its + predecessor.</p> + </section> + + <marker id="Strictly_Monotonically_Increasing"/> + <section> + <title>Strictly Monotonically Increasing</title> + <p>In a strictly monotonically increasing sequence of values, + all values that have a predecessor are larger than its + predecessor.</p> + </section> + + <marker id="UT1"/> + <section> + <title>UT1</title> + <p>Universal Time. UT1 is based on the rotation of the earth + and conceptually means solar time at 0° longitude.</p> + </section> + + <marker id="UTC"/> + <section> + <title>UTC</title> + <p>Coordinated Universal Time. UTC almost aligns with + <seealso marker="#UT1">UT1</seealso>. However, UTC uses the + SI definition of a second, which has not exactly the same length + as the second used by UT1. This means that UTC slowly drifts from + UT1. To keep UTC relatively in sync with UT1, leap seconds + are inserted, and potentially also deleted. That is, an UTC day can + be 86400, 86401, or 86399 seconds long.</p> + </section> + + <marker id="POSIX_Time"/> + <section> + <title>POSIX Time</title> + <p>Time since + <url href="http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap03.html#tag_21_03_00_17"> + Epoch</url>. + Epoch is defined to be 00:00:00 <seealso marker="#UTC">UTC</seealso>, + 1970-01-01. + <url href="http://pubs.opengroup.org/onlinepubs/009604499/basedefs/xbd_chap04.html#tag_04_14"> + A day in POSIX time</url> + is defined to be exactly 86400 seconds long. Strangely enough, + Epoch is defined to be a time in UTC, and UTC has another + definition of how long a day is. Quoting the Open Group + <url href="http://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_15"> + "POSIX time is therefore not necessarily UTC, despite its + appearance"</url>. + The effect of this is that when an UTC leap second is + inserted, POSIX time either stops for a second, or repeats the + last second. If an UTC leap second would be deleted (which has not + happened yet), POSIX time would make a one second leap forward.</p> + </section> + + <marker id="Time_Resolution"/> + <section> + <title>Time Resolution</title> + <p>The shortest time interval that can be distinguished when + reading time values.</p> + </section> + + <marker id="Time_Precision"/> + <section> + <title>Time Precision</title> + <p>The shortest time interval that can be distinguished + repeatedly and reliably when reading time values. Precision + is limited by the + <seealso marker="#Time_Resolution">resolution</seealso>, but + resolution and precision can differ significantly.</p> + </section> + + <marker id="Time_Accuracy"/> + <section> + <title>Time Accuracy</title> + <p>The correctness of time values.</p> + </section> + + <marker id="Time_Warp"/> + <section> + <title>Time Warp</title> + <p>A time warp is a leap forwards or backwards in time. That + is, the difference of time values taken before and after the + time warp does not correspond to the actual elapsed time.</p> + </section> + + <marker id="OS_System_Time"/> + <section> + <title>OS System Time</title> + <p>The operating systems view of + <seealso marker="#POSIX_Time">POSIX time</seealso>. To + retrieve it, call + <seealso marker="kernel:os#system_time/0"> + <c>os:system_time()</c></seealso>. + This may or may not be an accurate view of POSIX time. This time + may typically be adjusted both backwards and forwards without + limitation. That is, <seealso marker="#Time_Warp">time warps</seealso> + may be observed.</p> + + <p>To get information about the Erlang runtime + system's source of OS system time, call + <seealso marker="erlang#system_info_os_system_time_source"> + <c>erlang:system_info(os_system_time_source)</c></seealso>.</p> + </section> + + <marker id="OS_Monotonic_Time"/> + <section> + <title>OS Monotonic Time</title> + <p>A monotonically increasing time provided by the OS. + This time does not leap and has a relatively steady + frequency although not completely correct. However, it is not + uncommon that OS monotonic time stops if the system is + suspended. This time typically increases since some + unspecified point in time that is not connected to + <seealso marker="#OS_System_Time">OS system time</seealso>. + This type of time is not necessarily provided by all OSs.</p> + + <p>To get information about the Erlang + runtime system's source of OS monotonic time, call + <seealso marker="erlang#system_info_os_monotonic_time_source"> + <c>erlang:system_info(os_monotonic_time_source)</c></seealso>.</p> + </section> + + <marker id="Erlang_System_Time"/> + <section> + <title>Erlang System Time</title> + <p>The Erlang runtime systems view of + <seealso marker="#POSIX_Time">POSIX time</seealso>. To + retrieve it, call + <seealso marker="erlang#system_time/0"> + <c>erlang:system_time()</c></seealso>.</p> + + <p>This time may or may not be an accurate view of POSIX time, + and may + or may not align with <seealso marker="#OS_System_Time">OS system + time</seealso>. The runtime system works towards aligning the two + system times. Depending on the + <seealso marker="#Time_Warp_Modes">time warp mode</seealso> used, + this can be achieved by letting Erlang + system time perform a <seealso marker="#Time_Warp">time + warp</seealso>.</p> + </section> + + <marker id="Erlang_Monotonic_Time"/> + <section> + <title>Erlang Monotonic Time</title> + <p>A monotonically increasing time provided by the + Erlang runtime system. Erlang monotonic time increases since + some unspecified point in time. To retrieve it, call + <seealso marker="erlang#monotonic_time/0"> + <c>erlang:monotonic_time()</c></seealso>.</p> + + <p>The <seealso marker="#Time_Accuracy">accuracy</seealso> and + <seealso marker="#Time_Precision">precision</seealso> of Erlang + monotonic time heavily depends on the following:</p> + + <list type="bulleted"> + <item>Accuracy and precision of + <seealso marker="#OS_Monotonic_Time">OS monotonic time</seealso> + </item> + <item>Accuracy and precision of + <seealso marker="#OS_System_Time">OS system time</seealso> + </item> + <item><seealso marker="#Time_Warp_Modes"> + time warp mode</seealso> used + </item> + </list> + + <p>On a system without OS monotonic time, Erlang monotonic + time guarantees monotonicity, but cannot give + other guarantees. The frequency adjustments made to + Erlang monotonic time depend on the time warp mode used.</p> + + <p>Internally in the runtime system, Erlang monotonic + time is the "time engine" that is used for more or less + everything that has anything to do with time. All timers, + regardless of it is a <c>receive ... after</c> timer, BIF timer, + or a timer in the + <seealso marker="stdlib:timer"><c>timer(3)</c></seealso> + module, are triggered relative Erlang monotonic time. Even + <seealso marker="#Erlang_System_Time">Erlang system + time</seealso> is based on Erlang monotonic time. + By adding current Erlang monotonic time with current time + offset, you get current Erlang system time.</p> + + <p>To retrieve the current time offset, call + <seealso marker="erlang#time_offset/0"> + <c>erlang:time_offset/0</c></seealso>.</p> + </section> + + </section> + + <section> + <title>Introduction</title> <p>Time is vital to an Erlang program and, more importantly, <em>correct</em> time is vital to an Erlang program. As Erlang is a language with - soft real time properties and we have the possibility to express - time in our programs, the Virtual Machine and the language has to be - very careful about what is considered a correct point in time and in + soft real-time properties and we can express + time in our programs, the Virtual Machine and the language must be + careful about what is considered a correct time and in how time functions behave.</p> - <p>In the beginning, Erlang was constructed assuming that the wall + <p>When Erlang was designed, it was assumed that the wall clock time in the system showed a monotonic time moving forward at - exactly the same pace as the definition of time. That more or less - meant that an atomic clock (or better) was expected to be attached + exactly the same pace as the definition of time. This more or less meant + that an atomic clock (or better time source) was expected to be attached to your hardware and that the hardware was then expected to be - locked away from any human (or unearthly) tinkering for all - eternity. While this might be a compelling thought, it's simply - never the case.</p> - - <p>A "normal" modern computer can not keep time. Not on itself and - not unless you actually have a chip level atomic clock wired to - it. Time, as perceived by your computer, will normally need to be - corrected. Hence the NTP protocol that together with the ntpd - process will do it's best to keep your computers time in sync with - the "real" time in the universe. Between NTP corrections, usually a + locked away from any human tinkering forever. While this can be a + compelling thought, it is simply never the case.</p> + + <p>A "normal" modern computer cannot keep time, not on itself and + not unless you have a chip-level atomic clock wired to it. Time, + as perceived by your computer, must normally be corrected. Hence + the Network Time Protocol (NTP) protocol, together with the <c>ntpd</c> + process, does its best to keep your computer time in sync with + the correct time. Between NTP corrections, usually a less potent time-keeper than an atomic clock is used.</p> - <p>But NTP is not fail safe. The NTP server can be unavailable, the - ntp.conf can be wrongly configured or your computer may from time to - time be disconnected from the internet. Furthermore you can have a - user (or even system administrator) on your system that thinks the - right way to handle daylight saving time is to adjust the clock one - hour two times a year (a tip, that is not the right way to do - it...). To further complicate things, this user fetched your - software from the internet and has never ever thought about what's - the correct time as perceived by a computer. The user simply does - not care about keeping the wall clock in sync with the rest of the - universe. The user expects your program to have omnipotent knowledge + <p>However, NTP is not fail-safe. The NTP server can be unavailable, + <c>ntp.conf</c> can be wrongly configured, or your computer can + sometimes be disconnected from Internet. Furthermore, you can have a + user (or even system administrator) who thinks the correct + way to handle Daylight Saving Time is to adjust the clock one + hour two times a year (which is the incorrect way to do it). + To complicate things further, this user fetched your + software from Internet and has not considered what + the correct time is as perceived by a computer. The user does + not care about keeping the wall clock in sync with the correct + time. The user expects your program to have unlimited knowledge about the time.</p> <p>Most programmers also expect time to be reliable, at least until - they realize that the wall clock time on their workstation is of by - a minute. Then they simply set it to the correct time, maybe or - maybe not in a smooth way. Most probably not in a smooth way.</p> + they realize that the wall clock time on their workstation is off by + a minute. Then they set it to the correct time, but most probably + not in a smooth way.</p> - <p>The amount of problems that arise when you expect the wall clock - time on the system to always be correct may be immense. Therefore Erlang + <p>The number of problems that arise when you always expect the wall clock + time on the system to be correct can be immense. Erlang therefore introduced the "corrected estimate of time", or the "time - correction" many years ago. The time correction relies on the fact + correction", many years ago. The time correction relies on the fact that most operating systems have some kind of monotonic clock, - either a real time extension or some built in "tick counter" that is - independent of the wall clock settings. This counter may have - microsecond resolution or much less, but generally it has a drift - that is not to be ignored.</p> - - <p>So we have this monotonic ticking and we have the wall clock - time. Two unreliable times that together can give us an estimate of - an actual wall clock time that does not jump around and that - monotonically moves forward. If the tick counter has a high - resolution, this is fairly easy to do, if the counter has a low - resolution, it's more expensive, but still doable down to - frequencies of 50-60 Hz (of the tick counter).</p> - - <p>So the corrected time is the nearest approximation of an atomic - clock that is available on the computer. We want it to have the - following properties:</p> - <taglist> - <tag>Monotonic</tag> - <item>The clock should not move backwards</item> - <tag>Intervals should be near the truth</tag> - <item>We want the actual time (as measured by an atomic clock or - an astronomer) that passes between two time stamps, T1 and T2, to be as - near to T2 - T1 as possible.</item> - <tag>Tight coupling to the wall clock</tag> - <item>We want a timer that is to be fired when the wall clock - reaches a time in the future, to fire as near to that point in - time as possible</item> - </taglist> - <p>To meet all the criteria, we have to utilize both times in such a - way that Erlangs "corrected time" moves slightly slower or slightly - faster than the wall clock to get in sync with it. The word - "slightly" means a maximum of 1% difference to the wall clock time, - meaning that a sudden change in the wall clock of one minute, takes - 100 minutes to fix, by letting all "corrected time" move 1% slower - or faster.</p> - - <p>Needless to say, correcting for a faulty handling of daylight - saving time may be disturbing to a user comparing wall clock - time to for example calendar:now_to_local_time(erlang:now()). But - calendar:now_to_local_time/1 is not supposed to be used for presenting wall - clock time to the user.</p> - - <p>Time correction is not perfect, but it saves you from the havoc - of clocks jumping around, which would make timers in your program - fire far to late or far to early and could bring your whole system - to it's knees (or worse) just because someone detected a small error - in the wall clock time of the server where your program runs. So - while it might be confusing, it is still a really good feature of - Erlang and you should not throw it away using time functions which - may give you higher benchmark results, not unless you really know - what you're doing.</p> + either a real-time extension or some built-in "tick counter" that is + independent of the wall clock settings. This counter can have + microsecond resolution or much less, but it has a drift that cannot + be ignored.</p> + </section> <section> - <title>What does time correction mean in my system?</title> - <p>Time correction means that Erlang estimates a time from current - and previous settings of the wall clock, and it uses a fairly - exact tick counter to detect when the wall clock time has jumped - for some reason, slowly adjusting to the new value.</p> - - <p>In practice, this means that the difference between two calls - to time corrected functions, like erlang:now(), might differ up to - one percent from the corresponding calls to non time corrected - functions (like os:timestamp()). Furthermore, if comparing - calendar:local_time/0 to calendar:now_to_local_time(erlang:now()), - you might temporarily see a difference, depending on how well kept your - system is.</p> - - <p>It is important to understand that it is (to the program) - always unknown if it is the wall clock time that moves in the - wrong pace or the Erlang corrected time. The only way to determine - that, is to have an external source of universally correct time. If - some such source is available, the wall clock time can be kept - nearly perfect at all times, and no significant difference will be - detected between erlang:now/0's pace and the wall clock's.</p> - - <p>Still, the time correction will mean that your system keeps - it's real time characteristics very well, even when the wall clock - is unreliable.</p> + <marker id="Time_Correction"/> + <title>Time Correction</title> + <p>If time correction is enabled, the Erlang runtime system + makes use of both + <seealso marker="#OS_System_Time">OS system time</seealso> + and <seealso marker="#OS_Monotonic_Time">OS monotonic time</seealso>, + to adjust the frequency of the Erlang + monotonic clock. Time correction ensures that + <seealso marker="#Erlang_Monotonic_Time">Erlang monotonic time</seealso> + does not warp and that the frequency is relatively accurate. + The type of frequency adjustments depends on the time warp mode used. + Section <seealso marker="#Time_Warp_Modes">Time Warp Modes</seealso> + provides more details.</p> + + <p>By default time correction is enabled if support for + it exists on the specific platform. Support for it includes + both OS monotonic time, provided by the OS, and an + implementation in the Erlang runtime system using + OS monotonic time. To check if your system has support + for OS monotonic time, call + <seealso marker="erlang#system_info_os_monotonic_time_source"> + <c>erlang:system_info(os_monotonic_time_source)</c></seealso>. + To check if time correction is enabled on your system, call + <seealso marker="erlang#system_info_time_correction"> + <c>erlang:system_info(time_correction)</c></seealso>.</p> + + <p>To enable or disable time correction, pass command-line argument + <seealso marker="erl#+c"><c>+c [true|false]</c></seealso> to + <seealso marker="erl"><c>erl(1)</c></seealso>.</p> + + <p>If time correction is disabled, Erlang monotonic time + can warp forwards or stop, or even freeze for extended + periods of time. There are then no guarantees that the frequency + of the Erlang monotonic clock is accurate or stable.</p> + + <p><em>You typically never want to disable time correction</em>. + Previously a performance penalty was associated with time + correction, but nowadays it is usually the other way around. + If time correction is disabled, you probably get bad scalability, + bad performance, and bad time measurements.</p> </section> + <section> - <title>Where does Erlang use corrected time?</title> - <p>For all functionality where real time characteristics are - desirable, time correction is used. This basically means:</p> - <taglist> - <tag>erlang:now/0</tag> - <item>The infamous erlang:now/0 function uses time correction so - that differences between two "now-timestamps" will correspond to - other timeouts in the system. erlang:now/0 also holds other - properties, discussed later.</item> - <tag>receive ... after</tag> - <item>Timeouts on receive uses time correction to determine a - stable timeout interval.</item> - <tag>The timer module</tag> - <item>As the timer module uses other built in functions which - deliver corrected time, the timer module itself works with - corrected time.</item> - <tag>erlang:start_timer/3 and erlang:send_after/3</tag> - <item>The timer BIF's work with corrected time, so that they - will not fire prematurely or too late due to changes in the wall - clock time.</item> - </taglist> - - <p>All other functionality in the system where erlang:now/0 or any - other time corrected functionality is used, will of course - automatically benefit from it, as long as it's not "optimized" to - use some other time stamp function (like os:timestamp/0).</p> - - <p>Modules like calendar and functions like erlang:localtime/0 use - the wall clock time as it is currently set on the system. They - will not use corrected time. However, if you use a now-value and - convert it to local time, you will get a corrected local time - value, which may or may not be what you want. Typically older code - tend to use erlang:now/0 as a wall clock time, which is usually - correct (at least when testing), but might surprise you when - compared to other times in the system.</p> + <marker id="Time_Warp_Safe_Code"/> + <title>Time Warp Safe Code</title> + <p>Time warp safe code can handle + a <seealso marker="#Time_Warp">time warp</seealso> of + <seealso marker="#Erlang_System_Time">Erlang system time</seealso>.</p> + + <p><seealso marker="erlang#now/0"><c>erlang:now/0</c></seealso> + behaves bad when Erlang system time warps. When Erlang + system time does a time warp backwards, the values returned + from <c>erlang:now/0</c> freeze (if you disregard the + microsecond increments made because of the actual call) until + OS system time reaches the point of the last value returned by + <c>erlang:now/0</c>. This freeze can continue for a long time. It + can take years, decades, and even longer until the freeze stops.</p> + + <p>All uses of <c>erlang:now/0</c> are not necessarily + time warp unsafe. If you do not use it to get time, it + is time warp safe. However, <em>all uses of + <c>erlang:now/0</c> are suboptimal</em> from a performance + and scalability perspective. So you really want to replace + the use of it with other functionality. For examples + of how to replace the use of <c>erlang:now/0</c>, see section + <seealso marker="#Dos_and_Donts">How to Work with the New + API</seealso>.</p> </section> + <section> - <title>What is erlang:now/0 really?</title> - <p>erlang:now/0 is a function designed to serve multiple purposes - (or a multi-headed beast if you're a VM designer). It is expected - to hold the following properties:</p> - <taglist> - <tag>Monotonic</tag> - <item>erlang:now() never jumps backwards - it always moves - forward</item> - <tag>Interval correct</tag> - <item>The interval between two erlang:now() calls is expected to - correspond to the correct time in real life (as defined by an - atomic clock, or better)</item> - <tag>Absolute correctness</tag> - <item>The erlang:now/0 value should be possible to convert to an - absolute and correct date-time, corresponding to the real world - date and time (the wall clock)</item> - <tag>System correspondence</tag> - <item>The erlang:now/0 value converted to a date-time is - expected to correspond to times given by other programs on the - system (or by functions like os:timestamp/0)</item> - <tag>Unique</tag> - <item>No two calls to erlang:now on one Erlang node should - return the same value</item> - </taglist> - <p>All these requirements are possible to uphold at the same - time if (and only if):</p> - <taglist> - <tag>The wall clock time of the system is perfect</tag> - <item>The system (Operating System) time needs to be perfectly - in sync with the actual time as defined by an atomic clock or - a better time source. A good installation using NTP, and that is - up to date before Erlang starts, will have properties that for - most users and programs will be near indistinguishable from the - perfect time. Note that any larger corrections to the time done - by hand, or after Erlang has started, will partly (or - temporarily) invalidate some of the properties, as the time is - no longer perfect.</item> - <tag>Less than one call per microsecond to erlang:now/0 is - done</tag> - <item>This means that at <em>any</em> microsecond interval in - time, there can be no more than one call to erlang:now/0 in the - system. However, for the system not to loose it's properties - completely, it's enough that it on average is no more than one - call per microsecond (in one Erlang node).</item> - </taglist> - <p>The uniqueness property of erlang:now/0 is the most limiting - property. It means that erlang:now() maintains a global state and - that there is a hard-to-check property of the system that needs to - be maintained. For most applications this is still not a problem, - but a future system might very well manage to violate the - frequency limit on the calls globally. The uniqueness property is - also quite useless, as there are globally unique references that - provide a much better unique value to programs. However the - property will need to be maintained unless a really subtle - backward compatibility issue is to be introduced.</p> + <title>Time Warp Modes</title> + <marker id="Time_Warp_Modes"/> + <p>Current <seealso marker="#Erlang_System_Time">Erlang system + time</seealso> is determined by adding the current + <seealso marker="erlang#monotonic_time/0">Erlang monotonic time</seealso> + with current + <seealso marker="erlang#time_offset/0">time offset</seealso>. The + time offset is managed differently depending on which time + warp mode you use.</p> + + <p>To set the time warp mode, pass command-line argument + <seealso marker="erl#+C_"><c>+C + [no_time_warp|single_time_warp|multi_time_warp]</c></seealso> to + <seealso marker="erl"><c>erl(1)</c></seealso>.</p> + + <marker id="No_Time_Warp_Mode"/> + <section> + <title>No Time Warp Mode</title> + <p>The time offset is determined at runtime system start + and does not change later. This is the default behavior, but + not because it is the best mode (which it is not). It is + default <em>only</em> because this is how the runtime system + behaved until ERTS 7.0. + Ensure that your Erlang code that can execute during a time + warp is <seealso marker="#Time_Warp_Safe_Code">time warp + safe</seealso> before enabling other modes.</p> + + <p>As the time offset is not allowed to change, time + correction must adjust the frequency of the Erlang + monotonic clock to align Erlang system time with OS + system time smoothly. A significant downside of this approach + is that we on purpose will use a faulty frequency on the + Erlang monotonic clock if adjustments are needed. This + error can be as large as 1%. This error will show up in all + time measurements in the runtime system.</p> + + <p>If time correction is not enabled, Erlang monotonic + time freezes when OS system time leaps backwards. + The freeze of monotonic time continues until + OS system time catches up. The freeze can continue for + a long time. When OS system time leaps forwards, + Erlang monotonic time also leaps forward.</p> + </section> + + <marker id="Single_Time_Warp_Mode"/> + <section> + <title>Single Time Warp Mode</title> + <p>This mode is more or less a backward compatibility mode + as from its introduction.</p> + + <p>On an embedded system it is not uncommon that the system + has no power supply, not even a battery, when it is + shut off. The system clock on such a system is typically + way off when the system boots. If + <seealso marker="#No_Time_Warp_Mode">no time warp mode</seealso> + is used, and the Erlang runtime system is started before + OS system time has been corrected, Erlang system time + can be wrong for a long time, centuries or even longer.</p> + + <p>If you need to use Erlang code that is not + <seealso marker="#Time_Warp_Safe_Code">time warp safe</seealso>, + and you need to start the Erlang runtime system before OS + system time has been corrected, you may want to use the single + time warp mode.</p> + + <note><p>There are limitations to when you can + execute time warp unsafe code using this mode. If it is possible + to use time warp safe code only, it is <em>much</em> better + to use the <seealso marker="#Multi_Time_Warp_Mode">multi-time + warp mode</seealso> instead.</p></note> + + <p>Using the single time warp mode, the time offset is + handled in two phases:</p> + + <taglist> + <tag>Preliminary Phase</tag> + <item> + <p>This phase starts when the runtime + system starts. A preliminary time offset based on + current OS system time is determined. This offset is from + now on to be fixed during the whole preliminary phase.</p> + + <p>If time correction is enabled, adjustments to the + Erlang monotonic clock are made to keep its + frequency as correct as possible. However, <em>no</em> + adjustments are made trying to align Erlang system + time and OS system time. That is, during the preliminary phase + Erlang system time and OS system time can diverge + from each other, and no attempt is made to prevent this.</p> + + <p>If time correction is disabled, changes in OS system + time affects the monotonic clock the same way as + when the <seealso marker="#No_Time_Warp_Mode">no time warp + mode</seealso> is used.</p> + </item> + + <tag>Final Phase</tag> + <item> + <p>This phase begins when the user finalizes the time + offset by calling + <seealso marker="erlang#system_flag_time_offset"> + <c>erlang:system_flag(time_offset, finalize)</c></seealso>. + The finalization can only be performed once.</p> + + <p>During finalization, the time offset is adjusted and + fixed so that current Erlang system time aligns with the + current OS system time. As the time offset can + change during the finalization, Erlang system time + can do a time warp at this point. The time offset is + from now on fixed until the runtime system terminates. + If time correction has been enabled, the time + correction from now on also makes adjustments + to align Erlang system time with OS system + time. When the system is in the final phase, it behaves + exactly as in <seealso marker="#No_Time_Warp_Mode">no + time warp mode</seealso>.</p> + </item> + </taglist> + + <p>In order for this to work properly, the user must ensure + that the following two requirements are satisfied:</p> + + <taglist> + <tag>Forward Time Warp</tag> + <item><p>The time warp made when finalizing the time offset + can only be done forwards without encountering problems. + This implies that the user must ensure that OS + system time is set to a time earlier or equal to actual + POSIX time before starting the Erlang runtime system.</p> + + <p>If you are not sure that OS system time is correct, + set it to a time that is guaranteed to be earlier than + actual POSIX time before starting the Erlang runtime + system, just to be safe.</p> + </item> + + <tag>Finalize Correct OS System Time</tag> + <item><p>OS system time must be correct when + the user finalizes the time offset.</p> + </item> + </taglist> + + <p>If these requirements are not fulfilled, the system + may behave very bad.</p> + + <p>Assuming that these requirements are fulfilled, + time correction is enabled, and OS system time + is adjusted using a time adjustment protocol such as NTP, + only small adjustments of Erlang monotonic + time are needed to keep system times + aligned after finalization. As long as the system is not + suspended, the largest adjustments needed are for + inserted (or deleted) leap seconds.</p> + + <warning><p>To use this mode, ensure that + all Erlang code that will execute in both phases is + <seealso marker="#Time_Warp_Safe_Code">time warp + safe</seealso>.</p> + + <p>Code executing only in the final phase does not have + to be able to cope with the time warp.</p></warning> + </section> + + <marker id="Multi_Time_Warp_Mode"/> + <section> + <title>Multi-Time Warp Mode</title> + <p><em>Multi-time warp mode in combination with time + correction is the preferred configuration</em>. This as + the Erlang runtime system have better performance, scale + better, and behave better on almost all platforms. + Also, the accuracy and precision of time measurements + are better. Only Erlang runtime systems executing on + ancient platforms benefit from another configuration.</p> + + <p>The time offset can change at any time without limitations. + That is, Erlang system time can perform time warps both + forwards and backwards at <em>any</em> time. As we align + Erlang system time with OS system time by changing + the time offset, we can enable a time correction that tries + to adjust the frequency of the Erlang monotonic clock to be as + correct as possible. This makes time measurements using + Erlang monotonic time more accurate and precise.</p> + + <p>If time correction is disabled, Erlang monotonic time + leaps forward if OS system time leaps forward. If + OS system time leaps backwards, Erlang monotonic time + stops briefly, but it does not freeze for extended periods + of time. This as the time offset is changed to + align Erlang system time with OS system time.</p> + + <warning><p>To use this mode, ensure that all + Erlang code that will execute on the runtime system is + <seealso marker="#Time_Warp_Safe_Code">time warp + safe</seealso>.</p></warning> + </section> </section> + <section> - <title>Should I use erlang:now/0 or os:timestamp/0</title> - <p>The simple answer is to use erlang:now/0 for everything where - you want to keep real time characteristics, but use os:timestamp - for things like logs, user communication and debugging (typically - timer:ts uses os:timestamp, as it is a test tool, not a real world - application API). The benefit of using os:timestamp/0 is that it's - faster and does not involve any global state (unless the operating - system has one). The downside is that it will be vulnerable to wall - clock time changes.</p> + <title>New Time API</title> + <marker id="The_New_Time_API"/> + <p>The old time API is based on + <seealso marker="erlang#now/0"><c>erlang:now/0</c></seealso>. + <c>erlang:now/0</c> was intended to be used for many unrelated + things. This tied these unrelated operations together and + caused issues with performance, scalability, accuracy, and + precision for operations that did not need to have + such issues. To improve this, the new API spreads different + functionality over multiple functions.</p> + + <p>To be backward compatible, <c>erlang:now/0</c> + remains "as is", but <em>you are strongly discouraged from using + it</em>. Many use cases of <c>erlang:now/0</c> + prevents you from using the new + <seealso marker="#Multi_Time_Warp_Mode">multi-time warp + mode</seealso>, which is an important part of this + new time functionality improvement.</p> + + <p>Some of the new BIFs on some systems, perhaps surprisingly, + return negative integer values on a newly started runtime + system. This is not a bug, but a memory use optimization.</p> + + <p>The new API consists of the following new BIFs:</p> + + <list> + <item><p><seealso marker="erlang#convert_time_unit/3"> + <c>erlang:convert_time_unit/3</c></seealso></p></item> + <item><p><seealso marker="erlang#monotonic_time/0"> + <c>erlang:monotonic_time/0</c></seealso></p></item> + <item><p><seealso marker="erlang#monotonic_time/1"> + <c>erlang:monotonic_time/1</c></seealso></p></item> + <item><p><seealso marker="erlang#system_time/0"> + <c>erlang:system_time/0</c></seealso></p></item> + <item><p><seealso marker="erlang#system_time/1"> + <c>erlang:system_time/1</c></seealso></p></item> + <item><p><seealso marker="erlang#time_offset/0"> + <c>erlang:time_offset/0</c></seealso></p></item> + <item><p><seealso marker="erlang#time_offset/1"> + <c>erlang:time_offset/1</c></seealso></p></item> + <item><p><seealso marker="erlang#timestamp/0"> + <c>erlang:timestamp/0</c></seealso></p></item> + <item><p><seealso marker="erlang#unique_integer/0"> + <c>erlang:unique_integer/0</c></seealso></p></item> + <item><p><seealso marker="erlang#unique_integer/1"> + <c>erlang:unique_integer/1</c></seealso></p></item> + <item><p><seealso marker="kernel:os#system_time/0"> + <c>os:system_time/0</c></seealso></p></item> + <item><p><seealso marker="kernel:os#system_time/1"> + <c>os:system_time/1</c></seealso></p></item> + </list> + + <p>The new API also consists of extensions of the following existing BIFs: + </p> + + <list> + <item><p><seealso marker="erlang#monitor/2"> + <c>erlang:monitor(time_offset, clock_service)</c></seealso></p></item> + <item><p><seealso marker="erlang#system_flag_time_offset"> + <c>erlang:system_flag(time_offset, finalize)</c></seealso></p></item> + <item><p><seealso marker="erlang#system_info_os_monotonic_time_source"> + <c>erlang:system_info(os_monotonic_time_source)</c></seealso></p></item> + <item><p><seealso marker="erlang#system_info_os_system_time_source"> + <c>erlang:system_info(os_system_time_source)</c></seealso></p></item> + <item><p><seealso marker="erlang#system_info_time_offset"> + <c>erlang:system_info(time_offset)</c></seealso></p></item> + <item><p><seealso marker="erlang#system_info_time_warp_mode"> + <c>erlang:system_info(time_warp_mode)</c></seealso></p></item> + <item><p><seealso marker="erlang#system_info_time_correction"> + <c>erlang:system_info(time_correction)</c></seealso></p></item> + <item><p><seealso marker="erlang#system_info_start_time"> + <c>erlang:system_info(start_time)</c></seealso></p></item> + <item><p><seealso marker="erlang#system_info_end_time"> + <c>erlang:system_info(end_time)</c></seealso></p></item> + </list> + + <marker id="The_New_Erlang_Monotonic_Time"/> + <section> + <title>New Erlang Monotonic Time</title> + <p>Erlang monotonic time as such is new as from ERTS 7.0. + It is introduced to detach time measurements, such as elapsed + time from calendar time. In many use cases there is a need to + measure elapsed time or specify a time relative to another point + in time without the need to know the involved times in UTC or + any other globally defined time scale. By introducing a time + scale with a local definition of where it starts, time that do + not concern calendar time can be managed on that time + scale. Erlang monotonic time uses such a time scale with a + locally defined start.</p> + + <p>The introduction of Erlang monotonic time allows + us to adjust the two Erlang times (Erlang + monotonic time and Erlang system time) separately. By + doing this, the accuracy of elapsed time does not have to + suffer just because the system time happened to be + wrong at some point in time. Separate adjustments + of the two times are only performed in the time warp + modes, and only fully separated in the + <seealso marker="#Multi_Time_Warp_Mode">multi-time + warp mode</seealso>. All other modes than the + multi-time warp mode are for backward + compatibility reasons. When using these modes, the + accuracy of Erlang monotonic time suffer, as + the adjustments of Erlang monotonic time in these + modes are more or less tied to Erlang system time.</p> + + <p>The adjustment of system time could have been made + smother than using a time warp approach, but we think + that would be a bad choice. As we can + express and measure time that is not connected to + calendar time by the use of Erlang monotonic time, it + is better to expose the change in Erlang system time + immediately. This as the Erlang applications + executing on the system can react on the change in + system time as soon as possible. This is also more or + less exactly how most operating systems handle this + (OS monotonic time and OS system time). By adjusting + system time smoothly, we would just hide the fact that + system time changed and make it harder for the Erlang + applications to react to the change in a sensible way.</p> + + <p>To be able to react to a change in Erlang + system time, you must be able to detect that it + happened. The change in Erlang system time occurs when the + current time offset is changed. We have therefore + introduced the possibility to monitor the time offset using + <seealso marker="erlang#monitor/2"> + <c>erlang:monitor(time_offset, clock_service)</c></seealso>. + A process monitoring the time + offset is sent a message on the following format + when the time offset is changed:</p> + + <code type="none"> +{'CHANGE', MonitorReference, time_offset, clock_service, NewTimeOffset}</code> + </section> + + <marker id="Unique_Values"/> + <section> + <title>Unique Values</title> + <p>Besides reporting time, <c>erlang:now/0</c> also + produces unique and strictly monotonically increasing + values. To detach this functionality from + time measurements, we have introduced + <seealso marker="erlang#unique_integer/1"> + <c>erlang:unique_integer()</c></seealso>.</p> + </section> + + <marker id="Dos_and_Donts"/> + <section> + <title>How to Work with the New API</title> + <p>Previously <c>erlang:now/0</c> was the only option for doing + many things. This section deals with some things that + <c>erlang:now/0</c> can be used for, and how you use the new API.</p> + + <marker id="Dos_and_Donts_Retrieve_Erlang_System_Time"/> + <section> + <title>Retrieve Erlang System Time</title> + <dont> + <p> + Use <c>erlang:now/0</c> to retrieve the current Erlang system time. + </p> + </dont> + <do> + <p> + Use + <seealso marker="erlang#system_time/1"> + <c>erlang:system_time/1</c></seealso> + to retrieve the current Erlang system time on the + <seealso marker="erlang#type_time_unit">time unit</seealso> + of your choice.</p> + <p>If you want the same format as returned by <c>erlang:now/0</c>, + use <seealso marker="erlang#timestamp/0"> + <c>erlang:timestamp/0</c></seealso>. + </p> + </do> + </section> + + <marker id="Dos_and_Donts_Measure_Elapsed_Time"/> + <section> + <title>Measure Elapsed Time</title> + <dont> + <p> + Take time stamps with <c>erlang:now/0</c> and calculate + the difference in time with + <seealso marker="stdlib:timer#now_diff/2"> + <c>timer:now_diff/2</c></seealso>. + </p> + </dont> + <do> + <p> + Take time stamps with + <seealso marker="erlang#monotonic_time/0"> + <c>erlang:monotonic_time/0</c></seealso> + and calculate the time difference using ordinary subtraction. + The result is in <c>native</c> + <seealso marker="erlang#type_time_unit">time unit</seealso>. + If you want to convert the + result to another time unit, you can use + <seealso marker="erlang#convert_time_unit/3"> + <c>erlang:convert_time_unit/3</c></seealso>. + </p> + <p>An easier way to do this is to use + <seealso marker="erlang#monotonic_time/1"> + <c>erlang:monotonic_time/1</c></seealso> + with the desired time unit. However, you can then lose accuracy + and precision. + </p> + </do> + </section> + + <marker id="Dos_and_Donts_Determine_Order_of_Events"/> + <section> + <title>Determine Order of Events</title> + <dont> + <p> + Determine the order of events by saving a time stamp + with <c>erlang:now/0</c> when the event occurs. + </p> + </dont> + <do> + <p> + Determine the order of events by saving the integer + returned by + <seealso marker="erlang#unique_integer/1"> + <c>erlang:unique_integer([monotonic])</c></seealso> + when the event occurs. These integers are strictly + monotonically ordered on current runtime system instance + corresponding to creation time. + </p> + </do> + </section> + + <marker id="Dos_and_Donts_Determine_Order_of_Events_With_Time_of_the_Event"/> + <section> + <title>Determine Order of Events with Time of the Event</title> + <dont> + <p> + Determine the order of events by saving a time stamp + with <c>erlang:now/0</c> when the event occurs. + </p> + </dont> + <do> + <p> + Determine the order of events by saving a tuple containing + <seealso marker="erlang#monotonic_time/0">monotonic time</seealso> + and a <seealso marker="erlang#unique_integer/1">strictly + monotonically increasing integer</seealso> as follows:</p> + + <code type="none"> +Time = erlang:monotonic_time(), +UMI = erlang:unique_integer([monotonic]), +EventTag = {Time, UMI}</code> + + <p>These tuples are strictly monotonically ordered + on the current runtime system instance according to + creation time. It is important that the + monotonic time is in the first element (the most + significant element when comparing two-tuples). Using + the monotonic time in the tuples, you can calculate time + between events.</p> + + <p>If you are interested in Erlang system time at the + time when the event occurred, you can also save the time + offset before or after saving the events using + <seealso marker="erlang#time_offset/0"> + <c>erlang:time_offset/0</c></seealso>. + Erlang monotonic time added with the time + offset corresponds to Erlang system time.</p> + + <p>If you are executing in a mode where time offset + can change, and you want to get the actual + Erlang system time when the event occurred, you can + save the time offset as a third element in the tuple + (the least significant element when comparing three-tuples).</p> + </do> + </section> + + <marker id="Dos_and_Donts_Create_a_Unique_Name"/> + <section> + <title>Create a Unique Name</title> + <dont> + <p> + Use the values returned from <c>erlang:now/0</c> + to create a name unique on the current runtime system instance. + </p> + </dont> + <do> + <p> + Use the value returned from + <seealso marker="erlang#unique_integer/0"> + <c>erlang:unique_integer/0</c></seealso> + to create a name unique on the current runtime system + instance. If you only want positive integers, you can use + <seealso marker="erlang#unique_integer/1"> + <c>erlang:unique_integer([positive])</c></seealso>. + </p> + </do> + </section> + + <marker id="Dos_and_Donts_Seed_Random_Number_Generation_With_a_Unique_Value"/> + <section> + <title>Seed Random Number Generation with a Unique Value</title> + <dont> + <p> + Seed random number generation using <c>erlang:now()</c>. + </p> + </dont> + <do> + <p> + Seed random number generation using a combination of + <seealso marker="erlang#monotonic_time/0"> + <c>erlang:monotonic_time()</c></seealso>, + <seealso marker="erlang#time_offset/0"> + <c>erlang:time_offset()</c></seealso>, + <seealso marker="erlang#unique_integer/0"> + <c>erlang:unique_integer()</c></seealso>, + and other functionality. + </p> + </do> + </section> + + <p>To sum up this section: <em>Do not use <c>erlang:now/0</c>.</em></p> + </section> </section> + <section> - <title>Turning off time correction</title> - <p>If, for some reason, time correction causes trouble and you are - absolutely confident that the wall clock on the system is nearly - perfect, you can turn off time correction completely by giving the - <c>+c</c> option to <c>erl</c>. The probability for this being a - good idea, is very low.</p> + <marker id="Supporting_Both_New_and_Old_OTP_Releases"/> + <title>Support of Both New and Old OTP Releases</title> + <p>It can be required that your code must run on a variety + of OTP installations of different OTP releases. If so, you + cannot use the new API out of the box, as it will + not be available on releases before OTP 18. The solution + is <em>not</em> to avoid using the new API, as your + code would then not benefit from the scalability + and accuracy improvements made. Instead, use the + new API when available, and fall back on <c>erlang:now/0</c> + when the new API is unavailable.</p> + + <p>Fortunately most of the new API can easily be + implemented using existing primitives, except for:</p> + + <list type="bulleted"> + <item> + <seealso marker="erlang#system_info_start_time"> + <c>erlang:system_info(start_time)</c></seealso> + </item> + <item> + <seealso marker="erlang#system_info_end_time"> + <c>erlang:system_info(end_time)</c></seealso> + </item> + <item> + <seealso marker="erlang#system_info_os_monotonic_time_source"> + <c>erlang:system_info(os_monotonic_time_source)</c></seealso> + </item> + <item> + <seealso marker="erlang#system_info_os_system_time_source"> + <c>erlang:system_info(os_system_time_source)</c></seealso> + </item> + </list> + + <p>By wrapping the API with functions that fall back on + <c>erlang:now/0</c> when the new API is unavailable, + and using these wrappers instead of using the API directly, + the problem is solved. These wrappers can, for example, + be implemented as in + <url href="time_compat.erl">$ERL_TOP/erts/example/time_compat.erl</url>.</p> </section> </chapter> - diff --git a/erts/doc/src/tty.xml b/erts/doc/src/tty.xml index db15195f65..51db1ba8e2 100644 --- a/erts/doc/src/tty.xml +++ b/erts/doc/src/tty.xml @@ -4,24 +4,25 @@ <chapter> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> - <title>tty - A command line interface</title> + <title>tty - A Command-Line Interface</title> <prepared>ETX/B/SFP C. Granbom</prepared> <responsible></responsible> <docno></docno> @@ -31,24 +32,48 @@ <rev>A</rev> <file>tty.xml</file> </header> - <p><c><![CDATA[tty]]></c> is a simple command line interface program where keystrokes are collected and interpreted. Completed lines are sent to the shell for interpretation. There is a simple history mechanism, which saves previous lines. These can be edited before sending them to the shell. - <c><![CDATA[tty]]></c> is started when Erlang is started with the command:<br></br></p> - <p><em>erl</em></p> - <p><c><![CDATA[tty]]></c> operates in one of two modes:<br></br></p> + <p><c><![CDATA[tty]]></c> is a simple command-line interface program where + keystrokes are collected and interpreted. Completed lines are sent to the + shell for interpretation. A simple history mechanism saves previous lines, + which can be edited before sending them to the shell. <c><![CDATA[tty]]></c> + is started when Erlang is started with the following command:</p> + + <pre> +erl</pre> + + <p><c><![CDATA[tty]]></c> operates in one of two modes:</p> + <list type="bulleted"> <item> - <p><em>normal mode</em>, in which lines of text can be edited and sent to the shell.</p> + <p>Normal mode, in which text lines can be edited and sent to the + shell.</p> </item> <item> - <p><em>shell break</em> mode, which allows the user to kill the current shell, start multiple shells etc. Shell break mode is started by typing <em>Control G</em>.</p> + <p>Shell break mode, which allows the user to kill the current shell, + start multiple shells, and so on.</p> </item> </list> <section> <title>Normal Mode</title> - <p>In normal mode keystrokes from the user are collected and interpreted by <c><![CDATA[tty]]></c>. Most of the <em>emacs</em> line editing commands are supported. The following is a complete list of the supported line editing commands.<br></br></p> - <p><em>Note:</em> The notation <c><![CDATA[C-a]]></c> means pressing the control key and the letter <c><![CDATA[a]]></c> simultaneously. <c><![CDATA[M-f]]></c> means pressing the <c><![CDATA[ESC]]></c> key followed by the letter <c><![CDATA[f]]></c>. <c><![CDATA[Home]]></c> and <c><![CDATA[End]]></c> represent the keys with the same name on the keyboard, whereas <c><![CDATA[Left]]></c> and <c><![CDATA[Right]]></c> represent the corresponding arrow keys. - </p> + <p>In normal mode keystrokes from the user are collected and interpreted by + <c><![CDATA[tty]]></c>. Most of the <em>Emacs</em> line-editing commands + are supported. The following is a complete list of the supported + line-editing commands.</p> + + <p>Typographic conventions:</p> + + <list type="bulleted"> + <item><c>C-a</c> means pressing the <em>Ctrl</em> key and the letter + <c>a</c> simultaneously.</item> + <item><c>M-f</c> means pressing the <em>Esc</em> key and the letter + <c>f</c> in sequence.</item> + <item><c>Home</c> and <c>End</c> represent the keys with the same + name on the keyboard.</item> + <item><c>Left</c> and <c>Right</c> represent the corresponding arrow + keys.</item> + </list> + <table> <row> <cell align="left" valign="middle"><em>Key Sequence</em></cell> @@ -120,11 +145,13 @@ </row> <row> <cell align="left" valign="middle">C-n</cell> - <cell align="left" valign="middle">Fetch next line from the history buffer</cell> + <cell align="left" valign="middle">Fetch next line from the history + buffer</cell> </row> <row> <cell align="left" valign="middle">C-p</cell> - <cell align="left" valign="middle">Fetch previous line from the history buffer</cell> + <cell align="left" valign="middle">Fetch previous line from the history + buffer</cell> </row> <row> <cell align="left" valign="middle">C-t</cell> @@ -138,23 +165,18 @@ <cell align="left" valign="middle">C-y</cell> <cell align="left" valign="middle">Insert previously killed text</cell> </row> - <tcaption>tty text editing</tcaption> + <tcaption>tty Text Editing</tcaption> </table> </section> <section> <title>Shell Break Mode</title> - <p><em>tty</em> enters <em>shell</em> break mode when you type <em>Control G</em>. In this mode you can:<br></br></p> + <p>In this mode the following can be done:</p> + <list type="bulleted"> - <item> - <p>Kill or suspend the current shell</p> - </item> - <item> - <p>Connect to a suspended shell</p> - </item> - <item> - <p>Start a new shell</p> - </item> + <item>Kill or suspend the current shell</item> + <item>Connect to a suspended shell</item> + <item>Start a new shell</item> </list> </section> </chapter> diff --git a/erts/doc/src/werl.xml b/erts/doc/src/werl.xml index 49cc45e745..792fe204e8 100644 --- a/erts/doc/src/werl.xml +++ b/erts/doc/src/werl.xml @@ -4,20 +4,21 @@ <comref> <header> <copyright> - <year>1998</year><year>2013</year> + <year>1998</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. - - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -27,62 +28,91 @@ <docno>1</docno> <approved>Bjarne Däcker</approved> <checked></checked> - <date>98-01-26</date> + <date>1998-01-26</date> <rev>A</rev> <file>werl.xml</file> </header> <com>werl</com> <comsummary>The Erlang Emulator</comsummary> <description> - <p>On Windows, the preferred way to start the Erlang system for interactive use is:</p> + <p>On Windows, the preferred way to start the Erlang system for interactive + use is as follows:</p> + <p><c><![CDATA[werl <arguments>]]></c></p> - <p>This will start Erlang in its own window, with fully - functioning command-line editing and scrollbars. All flags + <p>This starts Erlang in its own window, with fully + functioning command-line editing and scrollbars. All flags except <c><![CDATA[-oldshell]]></c> work as they do for - the <seealso marker="erl">erl</seealso> command.</p> + <seealso marker="erl"><c>erl(1)</c></seealso>.</p> + + <list type="bulleted"> + <item> + <p>To copy text to the clipboard, use <c>Ctrl-C</c>.</p> + </item> + <item> + <p>To paste text, use <c>Ctrl-V</c>.</p> + </item> + <item> + <p>To interrupt the runtime system or the shell process (depending + on what has been specified with system flag <c>+B</c>), use + <c>Ctrl-Break</c>.</p> + </item> + </list> - <p>Ctrl-C is reserved for copying text to the clipboard (Ctrl-V to paste). - To interrupt the runtime system or the shell process (depending on what - has been specified with the +B system flag), you should use Ctrl-Break.</p> <p>In cases where you want to redirect standard input and/or - standard output or use Erlang in a pipeline, the <c>werl</c> is - not suitable, and the <c>erl</c> program should be used instead.</p> + standard output or use Erlang in a pipeline, <c>werl</c> is + not suitable, and the <c>erl</c> program is to be used instead.</p> - <p>The <c>werl</c> window is in many ways modelled after the <c>xterm</c> + <p>The <c>werl</c> window is in many ways modeled after the <c>xterm</c> window present on other platforms, as the <c>xterm</c> model - fits well with line oriented command based interaction. This - means that selecting text is line oriented rather than rectangle - oriented.</p> - - <p>To select text in the <c>werl</c> window , simply press and hold - the left mouse button and drag the mouse over the text you want - to select. If the selection crosses line boundaries, the - selected text will consist of complete lines where applicable - (just like in a word processor). To select more text than fits - in the window, start by selecting a small portion in the - beginning of the text you want, then use the scrollbar - to view the end of the desired selection, point to it and press - the <em>right</em> mouse-button. The whole area between your - first selection and the point where you right-clicked will be - included in the selection.</p> + fits well with line-oriented command-based interaction. This + means that selecting text is line-oriented rather than + rectangle-oriented.</p> - <p>The selected text is copied to the clipboard by either - pressing <c>Ctrl-C</c>, using the menu or pressing the copy - button in the toolbar.</p> + <list type="bulleted"> + <item> + <p>To select text in the <c>werl</c> window, press and hold + the left mouse button and drag the mouse over the text you want + to select. If the selection crosses line boundaries, the + selected text consists of complete lines where applicable + (just like in a word processor).</p> + </item> + <item> + <p>To select more text than fits + in the window, start by selecting a small part in the + beginning of the text you want, then use the scrollbar + to view the end of the desired selection, point to it, and press + the <em>right</em> mouse button. The whole area between your + first selection and the point where you right-clicked is + included in the selection.</p> + </item> + <item> + <p>To copy the selected text to the clipboard, either + use <c>Ctrl-C</c>, use the menu, or press the copy + button in the toolbar.</p> + </item> + </list> - <p>Pasted text is always inserted at the current prompt position - and will be interpreted by Erlang as usual keyboard input.</p> + <p>Pasted text is inserted at the current prompt position + and is interpreted by Erlang as usual keyboard input.</p> - <p>Previous command lines can be retrieved by pressing the <c>Up - arrow</c> or by pressing <c>Ctrl-P</c>. There is also a drop - down box in the toolbar containing the command - history. Selecting a command in the drop down box will insert it - at the prompt, just as if you used the keyboard to retrieve the + <list type="bulleted"> + <item> + <p>To retrieve previous command lines, press the <c>Up arrow</c> or + use <c>Ctrl-P</c>.</p> + </item> + </list> + + <p>A drop-down box in the toolbar contains the command + history. Selecting a command in the drop-down box inserts the command + at the prompt, as if you used the keyboard to retrieve the command.</p> - - <p>Closing the <c>werl</c> window will stop the Erlang emulator.</p> + <list type="bulleted"> + <item> + <p>To stop the Erlang emulator, close the <c>werl</c> window.</p> + </item> + </list> </description> </comref> diff --git a/erts/doc/src/zlib.xml b/erts/doc/src/zlib.xml index da8ccdecdf..6f4c42da27 100644 --- a/erts/doc/src/zlib.xml +++ b/erts/doc/src/zlib.xml @@ -4,20 +4,21 @@ <erlref> <header> <copyright> - <year>2005</year><year>2013</year> + <year>2005</year><year>2017</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> - The contents of this file are subject to the Erlang Public License, - Version 1.1, (the "License"); you may not use this file except in - compliance with the License. You should have received a copy of the - Erlang Public License along with this software. If not, it can be - retrieved online at http://www.erlang.org/. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 - Software distributed under the License is distributed on an "AS IS" - basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - the License for the specific language governing rights and limitations - under the License. + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. </legalnotice> @@ -29,13 +30,18 @@ <file>zlib.xml</file> </header> <module>zlib</module> - <modulesummary>Zlib Compression interface.</modulesummary> + <modulesummary>zlib compression interface.</modulesummary> <description> - <p>The zlib module provides an API for the zlib library - (http://www.zlib.org). - It is used to compress and decompress data. The - data format is described by RFCs 1950 to 1952.</p> - <p>A typical (compress) usage looks like:</p> + <p>This module provides an API for the zlib library + (<url href="http://www.zlib.net">www.zlib.net</url>). + It is used to compress and decompress data. + The data format is described by + <url href="https://www.ietf.org/rfc/rfc1950.txt">RFC 1950</url>, + <url href="https://www.ietf.org/rfc/rfc1951.txt">RFC 1951</url>, and + <url href="https://www.ietf.org/rfc/rfc1952.txt">RFC 1952</url>.</p> + + <p>A typical (compress) usage is as follows:</p> + <pre> Z = zlib:open(), ok = zlib:deflateInit(Z,default), @@ -49,29 +55,34 @@ Last = zlib:deflate(Z, [], finish), ok = zlib:deflateEnd(Z), zlib:close(Z), list_to_binary([Compressed|Last])</pre> + <p>In all functions errors, <c>{'EXIT',{Reason,Backtrace}}</c>, - might be thrown, where <c>Reason</c> describes the - error. Typical reasons are:</p> + can be thrown, where <c>Reason</c> describes the error.</p> + + <p>Typical <c>Reasons</c>s:</p> + <taglist> <tag><c>badarg</c></tag> - <item> - <p>Bad argument</p> + <item>Bad argument. </item> + <tag><c>not_initialized</c></tag> + <item>The stream hasn't been initialized, eg. if + <seealso marker="#inflateInit/1"><c>inflateInit/1</c></seealso> wasn't + called prior to a call to + <seealso marker="#inflate/2"><c>inflate/2</c></seealso>. + </item> + <tag><c>not_on_controlling_process</c></tag> + <item>The stream was used by a process that doesn't control it. Use + <seealso marker="#set_controlling_process/2"> + <c>set_controlling_process/2</c></seealso> if you need to transfer + a stream to a different process.</item> <tag><c>data_error</c></tag> - <item> - <p>The data contains errors</p> + <item>The data contains errors. </item> <tag><c>stream_error</c></tag> - <item> - <p>Inconsistent stream state</p> - </item> - <tag><c>einval</c></tag> - <item> - <p>Bad value or wrong function called</p> - </item> + <item>Inconsistent stream state.</item> <tag><c>{need_dictionary,Adler32}</c></tag> - <item> - <p>See <c>inflate/2</c></p> + <item>See <seealso marker="#inflate/2"><c>inflate/2</c></seealso>. </item> </taglist> </description> @@ -80,7 +91,7 @@ list_to_binary([Compressed|Last])</pre> <datatype> <name name="zstream"/> <desc> - <p>A zlib stream, see <seealso marker="#open/0">open/0</seealso>. + <p>A zlib stream, see <seealso marker="#open/0"><c>open/0</c></seealso>. </p> </desc> </datatype> @@ -88,6 +99,9 @@ list_to_binary([Compressed|Last])</pre> <name name="zlevel"/> </datatype> <datatype> + <name name="zflush"/> + </datatype> + <datatype> <name name="zmemlevel"/> </datatype> <datatype> @@ -99,120 +113,184 @@ list_to_binary([Compressed|Last])</pre> <datatype> <name name="zwindowbits"/> <desc> - <p>Normally in the range <c>-15..-9 | 9..15</c>.</p> + <p>Normally in the range <c>-15..-8 | 8..15</c>.</p> </desc> </datatype> </datatypes> + <funcs> <func> - <name name="open" arity="0"/> - <fsummary>Open a stream and return a stream reference</fsummary> + <name name="adler32" arity="2"/> + <fsummary>Calculate the Adler checksum.</fsummary> <desc> - <p>Open a zlib stream.</p> + <p>Calculates the Adler-32 checksum for <c><anno>Data</anno></c>.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#adler32/1"> + <c>erlang:adler32/1</c></seealso> instead.</p> + </warning> + </desc> + </func> + + <func> + <name name="adler32" arity="3"/> + <fsummary>Calculate the Adler checksum.</fsummary> + <desc> + <p>Updates a running Adler-32 checksum for <c><anno>Data</anno></c>. + If <c><anno>Data</anno></c> is the empty binary or the empty iolist, + this function returns the required initial value for the checksum.</p> + <p>Example:</p> + <pre> +Crc = lists:foldl(fun(Data,Crc0) -> + zlib:adler32(Z, Crc0, Data), + end, zlib:adler32(Z,<< >>), Datas)</pre> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#adler32/2"> + <c>erlang:adler32/2</c></seealso> instead.</p> + </warning> + </desc> + </func> + + <func> + <name name="adler32_combine" arity="4"/> + <fsummary>Combine two Adler-32 checksums.</fsummary> + <desc> + <p>Combines two Adler-32 checksums into one. For two binaries or + iolists, <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> + and <c><anno>Size2</anno></c>, with Adler-32 checksums + <c><anno>Adler1</anno></c> and <c><anno>Adler2</anno></c>.</p> + <p>This function returns the <c><anno>Adler</anno></c> checksum of + <c>[Data1,Data2]</c>, requiring only <c><anno>Adler1</anno></c>, + <c><anno>Adler2</anno></c>, and <c><anno>Size2</anno></c>.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#adler32_combine/3"> + <c>erlang:adler32_combine/3</c></seealso> instead.</p> + </warning> </desc> </func> + <func> <name name="close" arity="1"/> - <fsummary>Close a stream</fsummary> + <fsummary>Close a stream.</fsummary> <desc> <p>Closes the stream referenced by <c><anno>Z</anno></c>.</p> </desc> </func> + <func> - <name name="deflateInit" arity="1"/> - <fsummary>Initialize a session for compression</fsummary> + <name name="compress" arity="1"/> + <fsummary>Compress data with standard zlib functionality.</fsummary> <desc> - <p>Same as <c>zlib:deflateInit(<anno>Z</anno>, default)</c>.</p> + <p>Compresses data with zlib headers and checksum.</p> </desc> </func> + <func> - <name name="deflateInit" arity="2"/> - <fsummary>Initialize a session for compression</fsummary> + <name name="crc32" arity="1"/> + <fsummary>Get current CRC.</fsummary> <desc> - <p>Initialize a zlib stream for compression.</p> - <p><c><anno>Level</anno></c> decides the compression level to be used, 0 - (<c>none</c>), gives no compression at all, 1 - (<c>best_speed</c>) gives best speed and 9 - (<c>best_compression</c>) gives best compression.</p> + <p>Gets the current calculated CRC checksum.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#crc32/1"> + <c>erlang:crc32/1</c></seealso> on the uncompressed data + instead.</p> + </warning> </desc> </func> + <func> - <name name="deflateInit" arity="6"/> - <fsummary>Initialize a session for compression</fsummary> + <name name="crc32" arity="2"/> + <fsummary>Calculate CRC.</fsummary> <desc> - <p>Initiates a zlib stream for compression.</p> - <p>The <c><anno>Level</anno></c> parameter decides the compression level to be - used, 0 (<c>none</c>), gives no compression at all, 1 - (<c>best_speed</c>) gives best speed and 9 - (<c>best_compression</c>) gives best compression.</p> - <p>The <c><anno>Method</anno></c> parameter decides which compression method to use, - currently the only supported method is <c>deflated</c>.</p> - <p>The <c><anno>WindowBits</anno></c> parameter is the base two logarithm - of the window size (the size of the history buffer). It - should be in the range 9 through 15. Larger values - of this parameter result in better compression at the - expense of memory usage. The default value is 15 if - <c>deflateInit/2</c>. A negative <c><anno>WindowBits</anno></c> - value suppresses the zlib header (and checksum) from the - stream. Note that the zlib source mentions this only as a - undocumented feature.</p> - <p>The <c><anno>MemLevel</anno></c> parameter specifies how much memory - should be allocated for the internal compression - state. <c><anno>MemLevel</anno></c>=1 uses minimum memory but is slow and - reduces compression ratio; <c><anno>MemLevel</anno></c>=9 uses maximum - memory for optimal speed. The default value is 8.</p> - <p>The <c><anno>Strategy</anno></c> parameter is used to tune - the compression algorithm. Use the value <c>default</c> for - normal data, <c>filtered</c> for data produced by a filter (or - predictor), <c>huffman_only</c> to force Huffman encoding - only (no string match), or <c>rle</c> to limit match - distances to one (run-length encoding). Filtered data - consists mostly of small values with a somewhat random - distribution. In this case, the compression algorithm is tuned - to compress them better. The effect of <c>filtered</c>is to - force more Huffman coding and less string matching; it is - somewhat intermediate between <c>default</c> and - <c>huffman_only</c>. <c>rle</c> is designed to be almost as - fast as <c>huffman_only</c>, but give better compression for PNG - image data. The <c><anno>Strategy</anno></c> parameter only - affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately.</p> + <p>Calculates the CRC checksum for <c><anno>Data</anno></c>.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#crc32/1"> + <c>erlang:crc32/1</c></seealso> instead.</p> + </warning> + </desc> + </func> + + <func> + <name name="crc32" arity="3"/> + <fsummary>Calculate CRC.</fsummary> + <desc> + <p>Updates a running CRC checksum for <c><anno>Data</anno></c>. + If <c><anno>Data</anno></c> is the empty binary or the empty iolist, + this function returns the required initial value for the CRC.</p> + <p>Example:</p> + <pre> +Crc = lists:foldl(fun(Data,Crc0) -> + zlib:crc32(Z, Crc0, Data), + end, zlib:crc32(Z,<< >>), Datas)</pre> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#crc32/2"> + <c>erlang:crc32/2</c></seealso> instead.</p> + </warning> </desc> </func> + + <func> + <name name="crc32_combine" arity="4"/> + <fsummary>Combine two CRCs.</fsummary> + <desc> + <p>Combines two CRC checksums into one. For two binaries or iolists, + <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and + <c><anno>Size2</anno></c>, with CRC checksums <c><anno>CRC1</anno></c> + and <c><anno>CRC2</anno></c>.</p> + <p>This function returns the <c><anno>CRC</anno></c> checksum of + <c>[Data1,Data2]</c>, requiring only <c><anno>CRC1</anno></c>, + <c><anno>CRC2</anno></c>, and <c><anno>Size2</anno></c>.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="erts:erlang#crc32_combine/3"> + <c>erlang:crc32_combine/3</c></seealso> instead.</p> + </warning> + </desc> + </func> + <func> <name name="deflate" arity="2"/> - <fsummary>Compress data</fsummary> + <fsummary>Compress data.</fsummary> <desc> <p>Same as <c>deflate(<anno>Z</anno>, <anno>Data</anno>, none)</c>.</p> </desc> </func> + <func> <name name="deflate" arity="3"/> - <fsummary>Compress data</fsummary> + <fsummary>Compress data.</fsummary> <desc> - <p><c>deflate/3</c> compresses as much data as possible, and - stops when the input buffer becomes empty. It may introduce + <p>Compresses as much data as possible, and + stops when the input buffer becomes empty. It can introduce some output latency (reading input without producing any output) except when forced to flush.</p> - <p>If the parameter <c><anno>Flush</anno></c> is set to <c>sync</c>, all + <p>If <c><anno>Flush</anno></c> is set to <c>sync</c>, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. - Flushing may degrade compression for some compression algorithms and so - it should be used only when necessary.</p> - <p>If <c><anno>Flush</anno></c> is set to <c>full</c>, all output is flushed as with - <c>sync</c>, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using <c>full</c> too often can seriously degrade - the compression.</p> - <p>If the parameter <c><anno>Flush</anno></c> is set to <c>finish</c>, - pending input is processed, pending output is flushed and - <c>deflate/3</c> returns. Afterwards the only possible - operations on the stream are <c>deflateReset/1</c> or <c>deflateEnd/1</c>.</p> - <p><c><anno>Flush</anno></c> can be set to <c>finish</c> immediately after - <c>deflateInit</c> if all compression is to be done in one step.</p> + Flushing can degrade compression for some compression algorithms; + thus, use it only when necessary.</p> + <p>If <c><anno>Flush</anno></c> is set to <c>full</c>, all output is + flushed as with <c>sync</c>, and the compression state is reset so + that decompression can restart from this point if previous compressed + data has been damaged or if random access is desired. Using + <c>full</c> too often can seriously degrade the compression.</p> + <p>If <c><anno>Flush</anno></c> is set to <c>finish</c>, + pending input is processed, pending output is flushed, and + <c>deflate/3</c> returns. Afterwards the only possible operations + on the stream are + <seealso marker="#deflateReset/1"><c>deflateReset/1</c></seealso> or + <seealso marker="#deflateEnd/1"><c>deflateEnd/1</c></seealso>.</p> + <p><c><anno>Flush</anno></c> can be set to <c>finish</c> immediately + after <seealso marker="#deflateInit/1"><c>deflateInit</c></seealso> + if all compression is to be done in one step.</p> + <p>Example:</p> <pre> - zlib:deflateInit(Z), B1 = zlib:deflate(Z,Data), B2 = zlib:deflate(Z,<< >>,finish), @@ -220,268 +298,482 @@ zlib:deflateEnd(Z), list_to_binary([B1,B2])</pre> </desc> </func> + <func> - <name name="deflateSetDictionary" arity="2"/> - <fsummary>Initialize the compression dictionary</fsummary> + <name name="deflateEnd" arity="1"/> + <fsummary>End deflate session.</fsummary> <desc> - <p>Initializes the compression dictionary from the given byte - sequence without producing any compressed output. This - function must be called immediately after - <c>deflateInit/[1|2|6]</c> or <c>deflateReset/1</c>, before - any call of <c>deflate/3</c>. The compressor and - decompressor must use exactly the same dictionary (see - <c>inflateSetDictionary/2</c>). The adler checksum of the - dictionary is returned.</p> + <p>Ends the deflate session and cleans all data used. Notice that this + function throws a <c>data_error</c> exception if the last call to + <seealso marker="#deflate/3"><c>deflate/3</c></seealso> + was not called with <c>Flush</c> set to <c>finish</c>.</p> </desc> </func> + <func> - <name name="deflateReset" arity="1"/> - <fsummary>Reset the deflate session</fsummary> + <name name="deflateInit" arity="1"/> + <fsummary>Initialize a session for compression.</fsummary> <desc> - <p>This function is equivalent to <c>deflateEnd/1</c> - followed by <c>deflateInit/[1|2|6]</c>, but does not free - and reallocate all the internal compression state. The - stream will keep the same compression level and any other - attributes.</p> + <p>Same as <c>zlib:deflateInit(<anno>Z</anno>, default)</c>.</p> + </desc> + </func> + + <func> + <name name="deflateInit" arity="2"/> + <fsummary>Initialize a session for compression.</fsummary> + <desc> + <p>Initializes a zlib stream for compression.</p> + <p><c><anno>Level</anno></c> decides the compression level to be + used:</p> + <list type="bulleted"> + <item>0 (<c>none</c>), gives no compression</item> + <item>1 (<c>best_speed</c>) gives best speed</item> + <item>9 (<c>best_compression</c>) gives best compression</item> + </list> </desc> </func> + + <func> + <name name="deflateInit" arity="6"/> + <fsummary>Initialize a session for compression.</fsummary> + <desc> + <p>Initiates a zlib stream for compression.</p> + <taglist> + <tag><c><anno>Level</anno></c></tag> + <item> + <p>Compression level to use:</p> + <list type="bulleted"> + <item>0 (<c>none</c>), gives no compression</item> + <item>1 (<c>best_speed</c>) gives best speed</item> + <item>9 (<c>best_compression</c>) gives best compression</item> + </list> + </item> + <tag><c><anno>Method</anno></c></tag> + <item> + <p>Compression method to use, currently the only supported method + is <c>deflated</c>.</p> + </item> + <tag><c><anno>WindowBits</anno></c></tag> + <item> + <p>The base two logarithm of the window size (the size of the + history buffer). It is to be in the range 8 through 15. Larger + values result in better compression at the expense of memory + usage. Defaults to 15 if <seealso marker="#deflateInit/2"> + <c>deflateInit/2</c></seealso> is used. A negative + <c><anno>WindowBits</anno></c> value suppresses the zlib header + (and checksum) from the stream. Notice that the zlib source + mentions this only as a undocumented feature.</p> + <warning> + <p>Due to a known bug in the underlying zlib library, <c>WindowBits</c> values 8 and -8 + do not work as expected. In zlib versions before 1.2.9 values + 8 and -8 are automatically changed to 9 and -9. <em>From zlib version 1.2.9 + value -8 is rejected</em> causing <c>zlib:deflateInit/6</c> to fail + (8 is still changed to 9). It also seem possible that future versions + of zlib may fix this bug and start accepting 8 and -8 as is.</p> + <p>Conclusion: Avoid values 8 and -8 unless you know your zlib version supports them.</p> + </warning> + </item> + <tag><c><anno>MemLevel</anno></c></tag> + <item> + <p>Specifies how much memory is to be allocated for the internal + compression state: <c><anno>MemLevel</anno></c>=1 uses minimum + memory but is slow and reduces compression ratio; + <c><anno>MemLevel</anno></c>=9 uses maximum memory for optimal + speed. Defaults to 8.</p> + </item> + <tag><c><anno>Strategy</anno></c></tag> + <item> + <p>Tunes the compression algorithm. Use the following values:</p> + <list type="bulleted"> + <item><c>default</c> for normal data</item> + <item><c>filtered</c> for data produced by a filter (or + predictor)</item> + <item><c>huffman_only</c> to force Huffman encoding only + (no string match)</item> + <item><c>rle</c> to limit match distances to one (run-length + encoding)</item> + </list> + <p>Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of <c>filtered</c> is to + force more Huffman coding and less string matching; it is somewhat + intermediate between <c>default</c> and <c>huffman_only</c>. + <c>rle</c> is designed to be almost as fast as + <c>huffman_only</c>, but gives better compression for PNG image + data.</p> + <p><c><anno>Strategy</anno></c> affects only the compression ratio, + but not the correctness of the compressed output even if it is not + set appropriately.</p> + </item> + </taglist> + </desc> + </func> + <func> <name name="deflateParams" arity="3"/> - <fsummary>Dynamicly update deflate parameters</fsummary> + <fsummary>Dynamicly update deflate parameters.</fsummary> <desc> - <p>Dynamically update the compression level and compression - strategy. The interpretation of <c><anno>Level</anno></c> and - <c><anno>Strategy</anno></c> is as in <c>deflateInit/6</c>. This can be + <p>Dynamically updates the compression level and compression + strategy. The interpretation of <c><anno>Level</anno></c> and + <c><anno>Strategy</anno></c> is as in + <seealso marker="#deflateInit/6"><c>deflateInit/6</c></seealso>. + This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression level is changed, the input available so far is compressed with the - old level (and may be flushed); the new level will take - effect only at the next call of <c>deflate/3</c>.</p> - <p>Before the call of <c>deflateParams</c>, the stream state must be set as for - a call of <c>deflate/3</c>, since the currently available input may have to - be compressed and flushed.</p> + old level (and can be flushed); the new level takes + effect only at the next call of + <seealso marker="#deflate/3"><c>deflate/3</c></seealso>.</p> + <p>Before the call of <c>deflateParams</c>, the stream state must be + set as for a call of <c>deflate/3</c>, as the currently available + input may have to be compressed and flushed.</p> </desc> </func> + <func> - <name name="deflateEnd" arity="1"/> - <fsummary>End deflate session</fsummary> - <desc> - <p>End the deflate session and cleans all data used. - Note that this function will throw an <c>data_error</c> - exception if the last call to - <c>deflate/3</c> was not called with <c>Flush</c> set to - <c>finish</c>.</p> + <name name="deflateReset" arity="1"/> + <fsummary>Reset the deflate session.</fsummary> + <desc> + <p>Equivalent to + <seealso marker="#deflateEnd/1"><c>deflateEnd/1</c></seealso> + followed by + <seealso marker="#deflateInit/1"><c>deflateInit/1,2,6</c></seealso>, + but does not free and reallocate all the internal compression state. + The stream keeps the same compression level and any other + attributes.</p> </desc> </func> + <func> - <name name="inflateInit" arity="1"/> - <fsummary>Initialize a session for decompression</fsummary> + <name name="deflateSetDictionary" arity="2"/> + <fsummary>Initialize the compression dictionary.</fsummary> <desc> - <p>Initialize a zlib stream for decompression.</p> + <p>Initializes the compression dictionary from the specified byte + sequence without producing any compressed output.</p> + <p>This function must be called immediately after + <seealso marker="#deflateInit/1"><c>deflateInit/1,2,6</c></seealso> or + <seealso marker="#deflateReset/1"><c>deflateReset/1</c></seealso>, + before any call of + <seealso marker="#deflate/3"><c>deflate/3</c></seealso>.</p> + <p>The compressor and decompressor must use the same dictionary (see + <seealso marker="#inflateSetDictionary/2"> + <c>inflateSetDictionary/2</c></seealso>).</p> + <p>The Adler checksum of the dictionary is returned.</p> </desc> </func> + <func> - <name name="inflateInit" arity="2"/> - <fsummary>Initialize a session for decompression</fsummary> + <name name="getBufSize" arity="1"/> + <fsummary>Get buffer size.</fsummary> <desc> - <p>Initialize decompression session on zlib stream.</p> - <p>The <c><anno>WindowBits</anno></c> parameter is the base two logarithm - of the maximum window size (the size of the history buffer). - It should be in the range 9 through 15. - The default value is 15 if <c>inflateInit/1</c> is used. - If a compressed stream with a larger window size is - given as input, inflate() will throw the <c>data_error</c> - exception. A negative <c><anno>WindowBits</anno></c> value makes zlib ignore the - zlib header (and checksum) from the stream. Note that the zlib - source mentions this only as a undocumented feature.</p> + <p>Gets the size of the intermediate buffer.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release.</p> + </warning> </desc> </func> + <func> - <name name="inflate" arity="2"/> - <fsummary>Decompress data</fsummary> + <name name="gunzip" arity="1"/> + <fsummary>Uncompress data with gz header.</fsummary> <desc> - <p><c>inflate/2</c> decompresses as much data as possible. - It may introduce some output latency (reading - input without producing any output).</p> - <p>If a preset dictionary is needed at this point (see - <c>inflateSetDictionary</c> below), <c>inflate/2</c> throws a - <c>{need_dictionary,Adler}</c> exception where <c>Adler</c> is - the adler32 checksum of the dictionary chosen by the - compressor.</p> + <p>Uncompresses data with gz headers and checksum.</p> </desc> </func> + <func> - <name name="inflateSetDictionary" arity="2"/> - <fsummary>Initialize the decompression dictionary</fsummary> - <desc> - <p>Initializes the decompression dictionary from the given - uncompressed byte sequence. This function must be called - immediately after a call of <c>inflate/2</c> if this call - threw a <c>{need_dictionary,Adler}</c> exception. - The dictionary chosen by the - compressor can be determined from the Adler value thrown - by the call to <c>inflate/2</c>. The compressor and decompressor - must use exactly the same dictionary (see <c>deflateSetDictionary/2</c>).</p> - <p>Example:</p> - <pre> -unpack(Z, Compressed, Dict) -> - case catch zlib:inflate(Z, Compressed) of - {'EXIT',{{need_dictionary,DictID},_}} -> - zlib:inflateSetDictionary(Z, Dict), - Uncompressed = zlib:inflate(Z, []); - Uncompressed -> - Uncompressed - end.</pre> + <name name="gzip" arity="1"/> + <fsummary>Compress data with gz header.</fsummary> + <desc> + <p>Compresses data with gz headers and checksum.</p> </desc> </func> + <func> - <name name="inflateReset" arity="1"/> - <fsummary>>Reset the inflate session</fsummary> + <name name="inflate" arity="2"/> + <fsummary>Decompress data.</fsummary> <desc> - <p>This function is equivalent to <c>inflateEnd/1</c> followed - by <c>inflateInit/1</c>, but does not free and reallocate all - the internal decompression state. The stream will keep - attributes that may have been set by <c>inflateInit/[1|2]</c>.</p> + <p>Equivalent to + <seealso marker="#inflate/3"><c>inflate(Z, Data, [])</c></seealso> + </p> </desc> </func> + <func> - <name name="inflateEnd" arity="1"/> - <fsummary>End inflate session</fsummary> - <desc> - <p>End the inflate session and cleans all data used. Note - that this function will throw a <c>data_error</c> exception - if no end of stream was found (meaning that not all data - has been uncompressed).</p> + <name name="inflate" arity="3"/> + <fsummary>Decompress data.</fsummary> + <desc> + <p>Decompresses as much data as possible. It can introduce some output + latency (reading input without producing any output).</p> + <p>Currently the only available option is + <c>{exception_on_need_dict,boolean()}</c> which controls whether the + function should throw an exception when a preset dictionary is + required for decompression. When set to false, a + <c>need_dictionary</c> tuple will be returned instead. See + <seealso marker="#inflateSetDictionary/2"> + <c>inflateSetDictionary/2</c></seealso> for details.</p> + <warning> + <p>This option defaults to <c>true</c> for backwards compatibility + but we intend to remove the exception behavior in a future + release. New code that needs to handle dictionaries manually + should always specify <c>{exception_on_need_dict,false}</c>.</p> + </warning> </desc> </func> + <func> - <name name="setBufSize" arity="2"/> - <fsummary>Set buffer size</fsummary> + <name name="inflateChunk" arity="1"/> + <fsummary>Read next uncompressed chunk.</fsummary> <desc> - <p>Sets the intermediate buffer size.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="#safeInflate/2"><c>safeInflate/2</c> + </seealso> instead.</p> + </warning> + <p>Reads the next chunk of uncompressed data, initialized by + <seealso marker="#inflateChunk/2"><c>inflateChunk/2</c></seealso>.</p> + <p>This function is to be repeatedly called, while it returns + <c>{more, Decompressed}</c>.</p> </desc> </func> + <func> - <name name="getBufSize" arity="1"/> - <fsummary>Get buffer size</fsummary> - <desc> - <p>Get the size of intermediate buffer.</p> + <name name="inflateChunk" arity="2"/> + <fsummary>Decompress data with limited output size.</fsummary> + <desc> + <warning> + <p>This function is deprecated and will be removed in a future + release. Use <seealso marker="#safeInflate/2"><c>safeInflate/2</c> + </seealso> instead.</p> + </warning> + <p>Like <seealso marker="#inflate/2"><c>inflate/2</c></seealso>, + but decompresses no more data than will fit in the buffer configured + through <seealso marker="#setBufSize/2"><c>setBufSize/2</c> + </seealso>. Is is useful when decompressing a stream with a high + compression ratio, such that a small amount of compressed input can + expand up to 1000 times.</p> + <p>This function returns <c>{more, Decompressed}</c>, when there is + more output available, and + <seealso marker="#inflateChunk/1"><c>inflateChunk/1</c></seealso> + is to be used to read it.</p> + <p>This function can introduce some output latency (reading input + without producing any output).</p> + <p>An exception will be thrown if a preset dictionary is required for + further decompression. See + <seealso marker="#inflateSetDictionary/2"> + <c>inflateSetDictionary/2</c></seealso> for details.</p> + <p>Example:</p> + <pre> +walk(Compressed, Handler) -> + Z = zlib:open(), + zlib:inflateInit(Z), + % Limit single uncompressed chunk size to 512kb + zlib:setBufSize(Z, 512 * 1024), + loop(Z, Handler, zlib:inflateChunk(Z, Compressed)), + zlib:inflateEnd(Z), + zlib:close(Z). + +loop(Z, Handler, {more, Uncompressed}) -> + Handler(Uncompressed), + loop(Z, Handler, zlib:inflateChunk(Z)); +loop(Z, Handler, Uncompressed) -> + Handler(Uncompressed).</pre> </desc> </func> + <func> - <name name="crc32" arity="1"/> - <fsummary>Get current CRC</fsummary> + <name name="inflateEnd" arity="1"/> + <fsummary>End inflate session.</fsummary> <desc> - <p>Get the current calculated CRC checksum.</p> + <p>Ends the inflate session and cleans all data used. Notice + that this function throws a <c>data_error</c> exception + if no end of stream was found (meaning that not all data + has been uncompressed).</p> </desc> </func> + <func> - <name name="crc32" arity="2"/> - <fsummary>Calculate CRC</fsummary> + <name name="inflateGetDictionary" arity="1"/> + <fsummary>Return the decompression dictionary.</fsummary> <desc> - <p>Calculate the CRC checksum for <c><anno>Data</anno></c>.</p> + <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="crc32" arity="3"/> - <fsummary>Calculate CRC</fsummary> + <name name="inflateInit" arity="1"/> + <fsummary>Initialize a session for decompression.</fsummary> <desc> - <p>Update a running CRC checksum for <c><anno>Data</anno></c>. - If <c><anno>Data</anno></c> is the empty binary or the empty iolist, this function returns - the required initial value for the crc.</p> - <pre> -Crc = lists:foldl(fun(Data,Crc0) -> - zlib:crc32(Z, Crc0, Data), - end, zlib:crc32(Z,<< >>), Datas)</pre> + <p>Initializes a zlib stream for decompression.</p> </desc> </func> + <func> - <name name="crc32_combine" arity="4"/> - <fsummary>Combine two CRC's</fsummary> + <name name="inflateInit" arity="2"/> + <fsummary>Initialize a session for decompression.</fsummary> <desc> - <p>Combine two CRC checksums into one. For two binaries or iolists, - <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and - <c><anno>Size2</anno></c>, with CRC checksums <c><anno>CRC1</anno></c> and - <c><anno>CRC2</anno></c>. <c>crc32_combine/4</c> returns the <c><anno>CRC</anno></c> - checksum of <c>[Data1,Data2]</c>, requiring - only <c><anno>CRC1</anno></c>, <c><anno>CRC2</anno></c>, and <c><anno>Size2</anno></c>. - </p> + <p>Initializes a decompression session on zlib stream.</p> + <p><c><anno>WindowBits</anno></c> is the base two logarithm + of the maximum window size (the size of the history buffer). + It is to be in the range 8 through 15. Default to 15 if + <seealso marker="#inflateInit/1"><c>inflateInit/1</c></seealso> + is used.</p> + <p>If a compressed stream with a larger window size is specified as + input, <seealso marker="#inflate/2"><c>inflate/2</c></seealso> + throws the <c>data_error</c> exception.</p> + <p>A negative <c><anno>WindowBits</anno></c> value makes zlib + ignore the zlib header (and checksum) from the stream. Notice that + the zlib source mentions this only as a undocumented feature.</p> </desc> </func> + <func> - <name name="adler32" arity="2"/> - <fsummary>Calculate the adler checksum</fsummary> + <name name="inflateReset" arity="1"/> + <fsummary>>Reset the inflate session.</fsummary> <desc> - <p>Calculate the Adler-32 checksum for <c><anno>Data</anno></c>.</p> + <p>Equivalent to + <seealso marker="#inflateEnd/1"><c>inflateEnd/1</c></seealso> + followed by + <seealso marker="#inflateInit/1"><c>inflateInit/1</c></seealso>, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that could have been set by + <c>inflateInit/1,2</c>.</p> </desc> </func> + <func> - <name name="adler32" arity="3"/> - <fsummary>Calculate the adler checksum</fsummary> - <desc> - <p>Update a running Adler-32 checksum for <c><anno>Data</anno></c>. - If <c><anno>Data</anno></c> is the empty binary or the empty iolist, this function returns - the required initial value for the checksum.</p> + <name name="inflateSetDictionary" arity="2"/> + <fsummary>Initialize the decompression dictionary.</fsummary> + <desc> + <p>Initializes the decompression dictionary from the specified + uncompressed byte sequence. This function must be called as a + response to an inflate operation (eg. + <seealso marker="#safeInflate/2"><c>safeInflate/2</c></seealso>) + returning <c>{need_dictionary,Adler,Output}</c> or in the case of + deprecated functions, throwing an + <c>{'EXIT',{{need_dictionary,Adler},_StackTrace}}</c> exception.</p> + <p>The dictionary chosen by the compressor can be determined from the + Adler value returned or thrown by the call to the inflate function. + The compressor and decompressor must use the same dictionary (See + <seealso marker="#deflateSetDictionary/2"> + <c>deflateSetDictionary/2</c></seealso>).</p> + <p>After setting the dictionary the inflate operation should be + retried without new input.</p> + <p>Example:</p> <pre> -Crc = lists:foldl(fun(Data,Crc0) -> - zlib:adler32(Z, Crc0, Data), - end, zlib:adler32(Z,<< >>), Datas)</pre> +deprecated_unpack(Z, Compressed, Dict) -> + case catch zlib:inflate(Z, Compressed) of + {'EXIT',{{need_dictionary,_DictID},_}} -> + ok = zlib:inflateSetDictionary(Z, Dict), + Uncompressed = zlib:inflate(Z, []); + Uncompressed -> + Uncompressed + end. + +new_unpack(Z, Compressed, Dict) -> + case zlib:inflate(Z, Compressed, [{exception_on_need_dict, false}]) of + {need_dictionary, _DictId, Output} -> + ok = zlib:inflateSetDictionary(Z, Dict), + [Output | zlib:inflate(Z, [])]; + Uncompressed -> + Uncompressed + end.</pre> </desc> </func> + <func> - <name name="adler32_combine" arity="4"/> - <fsummary>Combine two Adler-32 checksums</fsummary> + <name name="open" arity="0"/> + <fsummary>Open a stream and return a stream reference.</fsummary> <desc> - <p>Combine two Adler-32 checksums into one. For two binaries or iolists, - <c>Data1</c> and <c>Data2</c> with sizes of <c>Size1</c> and - <c><anno>Size2</anno></c>, with Adler-32 checksums <c><anno>Adler1</anno></c> and - <c><anno>Adler2</anno></c>. <c>adler32_combine/4</c> returns the <c><anno>Adler</anno></c> - checksum of <c>[Data1,Data2]</c>, requiring - only <c><anno>Adler1</anno></c>, <c><anno>Adler2</anno></c>, and <c><anno>Size2</anno></c>. - </p> + <p>Opens a zlib stream.</p> </desc> </func> + <func> - <name name="compress" arity="1"/> - <fsummary>Compress data with standard zlib functionality</fsummary> - <desc> - <p>Compress data (with zlib headers and checksum).</p> + <name name="safeInflate" arity="2"/> + <fsummary>Decompress data with limited output size.</fsummary> + <desc> + <p>Like <seealso marker="#inflate/2"><c>inflate/2</c></seealso>, + but returns once it has expanded beyond a small + implementation-defined threshold. It's useful when decompressing + untrusted input which could have been maliciously crafted to expand + until the system runs out of memory.</p> + <p>This function returns <c>{continue | finished, Output}</c>, where + <anno>Output</anno> is the data that was decompressed in this call. + New input can be queued up on each call if desired, and the function + will return <c>{finished, Output}</c> once all queued data has been + decompressed.</p> + <p>This function can introduce some output latency (reading + input without producing any output).</p> + <p>If a preset dictionary is required for further decompression, this + function returns a <c>need_dictionary</c> tuple. See + <seealso marker="#inflateSetDictionary/2"> + <c>inflateSetDictionary/2</c></seealso>) for details.</p> + <p>Example:</p> + <pre> +walk(Compressed, Handler) -> + Z = zlib:open(), + zlib:inflateInit(Z), + loop(Z, Handler, zlib:safeInflate(Z, Compressed)), + zlib:inflateEnd(Z), + zlib:close(Z). + +loop(Z, Handler, {continue, Output}) -> + Handler(Output), + loop(Z, Handler, zlib:safeInflate(Z, [])); +loop(Z, Handler, {finished, Output}) -> + Handler(Output).</pre> </desc> </func> + <func> - <name name="uncompress" arity="1"/> - <fsummary>Uncompress data with standard zlib functionality</fsummary> + <name name="setBufSize" arity="2"/> + <fsummary>Set buffer size.</fsummary> <desc> - <p>Uncompress data (with zlib headers and checksum).</p> + <p>Sets the intermediate buffer size.</p> + <warning> + <p>This function is deprecated and will be removed in a future + release.</p> + </warning> </desc> </func> + <func> - <name name="zip" arity="1"/> - <fsummary>Compress data without the zlib headers</fsummary> + <name name="set_controlling_process" arity="2"/> + <fsummary>Transfers ownership of a zlib stream.</fsummary> <desc> - <p>Compress data (without zlib headers and checksum).</p> + <p>Changes the controlling process of <c><anno>Z</anno></c> to + <c><anno>Pid</anno></c>, which must be a local process.</p> </desc> </func> + <func> - <name name="unzip" arity="1"/> - <fsummary>Uncompress data without the zlib headers</fsummary> + <name name="uncompress" arity="1"/> + <fsummary>Uncompress data with standard zlib functionality.</fsummary> <desc> - <p>Uncompress data (without zlib headers and checksum).</p> + <p>Uncompresses data with zlib headers and checksum.</p> </desc> </func> + <func> - <name name="gzip" arity="1"/> - <fsummary>Compress data with gz header</fsummary> + <name name="unzip" arity="1"/> + <fsummary>Uncompress data without the zlib headers.</fsummary> <desc> - <p>Compress data (with gz headers and checksum).</p> + <p>Uncompresses data without zlib headers and checksum.</p> </desc> </func> + <func> - <name name="gunzip" arity="1"/> - <fsummary>Uncompress data with gz header</fsummary> + <name name="zip" arity="1"/> + <fsummary>Compress data without the zlib headers.</fsummary> <desc> - <p>Uncompress data (with gz headers and checksum).</p> + <p>Compresses data without zlib headers and checksum.</p> </desc> </func> </funcs> |