diff options
Diffstat (limited to 'erts/doc')
47 files changed, 27626 insertions, 0 deletions
diff --git a/erts/doc/Makefile b/erts/doc/Makefile new file mode 100644 index 0000000000..8ea3793d90 --- /dev/null +++ b/erts/doc/Makefile @@ -0,0 +1,36 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1996-2009. All Rights Reserved. +# +# 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. +# +# %CopyrightEnd% +# + +# +# Default Rules +# +OTP_MAKE_ROOT=/home/super/otp/otp_make +include $(OTP_MAKE_ROOT)/otp.mk + +# +# Macros +# +SUB_DIRECTORIES = src + +SPECIAL_TARGETS = + +# +# Default Subdir Targets +# +include $(OTP_MAKE_ROOT)/otp_subdir.mk diff --git a/erts/doc/html/.gitignore b/erts/doc/html/.gitignore new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/erts/doc/html/.gitignore diff --git a/erts/doc/man1/.gitignore b/erts/doc/man1/.gitignore new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/erts/doc/man1/.gitignore diff --git a/erts/doc/man3/.gitignore b/erts/doc/man3/.gitignore new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/erts/doc/man3/.gitignore diff --git a/erts/doc/pdf/.gitignore b/erts/doc/pdf/.gitignore new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/erts/doc/pdf/.gitignore diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile new file mode 100644 index 0000000000..3dfefa2001 --- /dev/null +++ b/erts/doc/src/Makefile @@ -0,0 +1,153 @@ +# +# %CopyrightBegin% +# +# Copyright Ericsson AB 1997-2009. All Rights Reserved. +# +# 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. +# +# %CopyrightEnd% +# +include $(ERL_TOP)/make/target.mk +include $(ERL_TOP)/make/$(TARGET)/otp.mk + +# ---------------------------------------------------- +# Application version +# ---------------------------------------------------- +include ../../vsn.mk +APPLICATION=erts +# ---------------------------------------------------- +# Release directory specification +# ---------------------------------------------------- +RELSYSDIR = $(RELEASE_PATH)/$(APPLICATION)-$(VSN) + +# ---------------------------------------------------- +# Target Specs +# ---------------------------------------------------- +XML_APPLICATION_FILES = ref_man.xml +XML_REF1_FILES = epmd.xml \ + erl.xml \ + erlc.xml \ + escript.xml \ + werl.xml \ + erlsrv.xml \ + start_erl.xml \ + run_erl.xml \ + start.xml + +XML_REF3_FILES = \ + driver_entry.xml \ + erl_set_memory_block.xml \ + erl_driver.xml \ + erl_prim_loader.xml \ + erlang.xml \ + erts_alloc.xml \ + init.xml \ + zlib.xml + +XML_PART_FILES = \ + part.xml \ + part_notes.xml \ + part_notes_history.xml + +XML_CHAPTER_FILES = \ + tty.xml \ + match_spec.xml \ + crash_dump.xml \ + alt_dist.xml \ + driver.xml \ + absform.xml \ + inet_cfg.xml \ + erl_ext_dist.xml \ + erl_dist_protocol.xml \ + notes.xml \ + notes_history.xml + +TOPDOCDIR=../../../doc + +BOOK_FILES = book.xml + +GIF_FILES = \ + erl_ext_fig.gif + +XML_FILES = \ + $(BOOK_FILES) $(XML_CHAPTER_FILES) \ + $(XML_PART_FILES) $(XML_REF3_FILES) $(XML_REF1_FILES) $(XML_APPLICATION_FILES) + +# ---------------------------------------------------- + +HTML_FILES = $(XML_APPLICATION_FILES:%.xml=$(HTMLDIR)/%.html) \ + $(XML_PART_FILES:%.xml=$(HTMLDIR)/%.html) + +INFO_FILE = ../../info +INFO_FILE_SRC = ../../info.src + +MAN1_FILES = $(XML_REF1_FILES:%.xml=$(MAN1DIR)/%.1) +MAN3_FILES = $(XML_REF3_FILES:%.xml=$(MAN3DIR)/%.3) + +HTML_REF_MAN_FILE = $(HTMLDIR)/index.html + +TOP_PDF_FILE = $(PDFDIR)/$(APPLICATION)-$(VSN).pdf + +# ---------------------------------------------------- +# FLAGS +# ---------------------------------------------------- +XML_FLAGS += + +# ---------------------------------------------------- +# Targets +# ---------------------------------------------------- +$(HTMLDIR)/%.gif: %.gif + $(INSTALL_DATA) $< $@ + +docs: pdf html man $(INFO_FILE) + +$(TOP_PDF_FILE): $(XML_FILES) + +pdf: $(TOP_PDF_FILE) + +html: gifs $(HTML_REF_MAN_FILE) + +man: $(MAN1_FILES) $(MAN3_FILES) + +gifs: $(GIF_FILES:%=$(HTMLDIR)/%) + +$(INFO_FILE): $(INFO_FILE_SRC) ../../vsn.mk + sed -e 's;%RELEASE%;$(SYSTEM_VSN);' $(INFO_FILE_SRC) > $(INFO_FILE) + + +debug opt: + +clean: + rm -rf $(HTMLDIR)/* + rm -f $(MAN1DIR)/* + rm -f $(MAN3DIR)/* + rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) + rm -f errs core *~ + +# ---------------------------------------------------- +# Release Target +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_release_targets.mk + +release_docs_spec: docs + $(INSTALL_DIR) $(RELSYSDIR)/doc/pdf + $(INSTALL_DATA) $(TOP_PDF_FILE) $(RELSYSDIR)/doc/pdf + $(INSTALL_DIR) $(RELSYSDIR)/doc/html + $(INSTALL_DATA) $(HTMLDIR)/* \ + $(RELSYSDIR)/doc/html + $(INSTALL_DATA) $(INFO_FILE) $(RELSYSDIR) + $(INSTALL_DIR) $(RELEASE_PATH)/man/man3 + $(INSTALL_DATA) $(MAN3DIR)/* $(RELEASE_PATH)/man/man3 + $(INSTALL_DIR) $(RELEASE_PATH)/man/man1 + $(INSTALL_DATA) $(MAN1_FILES) $(RELEASE_PATH)/man/man1 + +release_spec: diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml new file mode 100644 index 0000000000..4c84412dd6 --- /dev/null +++ b/erts/doc/src/absform.xml @@ -0,0 +1,444 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2001</year><year>2009</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>The Abstract Format</title> + <prepared>Arndt Jonasson</prepared> + <responsible>Kenneth Lundin</responsible> + <docno>1</docno> + <approved>Jultomten</approved> + <checked></checked> + <date>00-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 + 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 + 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 + be the atom with a printname consisting of the same characters as the + operator. + </p> + + <section> + <title>Module declarations and forms</title> + <p>A module declaration consists of a sequence of forms that 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> + </list> + + <section> + <title>Record fields</title> + <p>Each field in a record declaration may have an optional + explicit default initializer expression</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> + </list> + </section> + + <section> + <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> + </section> + </section> + + <section> + <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> + <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> + </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> + </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 + 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> + </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> + </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> + <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[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,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[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> + </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> + <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> + </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> + <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> + </list> + </section> + </section> + + <section> + <title>Clauses</title> + <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> + <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> + </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> + <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> + </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> + + <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 + (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> + </section> +</chapter> + diff --git a/erts/doc/src/alt_dist.xml b/erts/doc/src/alt_dist.xml new file mode 100644 index 0000000000..9a68b3cf40 --- /dev/null +++ b/erts/doc/src/alt_dist.xml @@ -0,0 +1,1099 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2000</year><year>2009</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>How to implement an alternative carrier for the Erlang distribution</title> + <prepared>Patrik Nyblom</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>2000-10-17</date> + <rev>PA2</rev> + <file>alt_dist.xml</file> + </header> + <p>This document describes how one can implement ones own 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> + + <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> + </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> + + <section> + <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 + 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 + 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>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> + <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> + </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 + implemented in the driver or by the underlying communications + 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> + <code type="none"><![CDATA[ +( 1) #include <stdio.h> +( 2) #include <stdlib.h> +( 3) #include <string.h> +( 4) #include <unistd.h> +( 5) #include <errno.h> +( 6) #include <sys/types.h> +( 7) #include <sys/stat.h> +( 8) #include <sys/socket.h> +( 9) #include <sys/un.h> +(10) #include <fcntl.h> + +(11) #define HAVE_UIO_H +(12) #include "erl_driver.h" + +(13) /* +(14) ** Interface routines +(15) */ +(16) static ErlDrvData uds_start(ErlDrvPort port, char *buff); +(17) static void uds_stop(ErlDrvData handle); +(18) static void uds_command(ErlDrvData handle, char *buff, int bufflen); +(19) static void uds_input(ErlDrvData handle, ErlDrvEvent event); +(20) static void uds_output(ErlDrvData handle, ErlDrvEvent event); +(21) static void uds_finish(void); +(22) static int uds_control(ErlDrvData handle, unsigned int command, +(23) char* buf, int count, char** res, int res_size); + +(24) /* The driver entry */ +(25) static ErlDrvEntry uds_driver_entry = { +(26) NULL, /* init, N/A */ +(27) uds_start, /* start, called when port is opened */ +(28) uds_stop, /* stop, called when port is closed */ +(29) uds_command, /* output, called when erlang has sent */ +(30) uds_input, /* ready_input, called when input +(31) descriptor ready */ +(32) uds_output, /* ready_output, called when output +(33) descriptor ready */ +(34) "uds_drv", /* char *driver_name, the argument +(35) to open_port */ +(36) uds_finish, /* finish, called when unloaded */ +(37) NULL, /* void * that is not used (BC) */ +(38) uds_control, /* control, port_control callback */ +(39) NULL, /* timeout, called on timeouts */ +(40) NULL, /* outputv, vector output interface */ +(41) NULL, /* ready_async callback */ +(42) NULL, /* flush callback */ +(43) NULL, /* call callback */ +(44) NULL, /* event callback */ +(45) ERL_DRV_EXTENDED_MARKER, /* Extended driver interface marker */ +(46) ERL_DRV_EXTENDED_MAJOR_VERSION, /* Major version number */ +(47) ERL_DRV_EXTENDED_MINOR_VERSION, /* Minor version number */ +(48) ERL_DRV_FLAG_SOFT_BUSY, /* Driver flags. Soft busy flag is +(49) required for distribution drivers */ +(50) NULL, /* Reserved for internal use */ +(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 + 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 + 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 + (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> + <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> + <code type="none"><![CDATA[ +( 1) typedef enum { +( 2) portTypeUnknown, /* An uninitialized port */ +( 3) portTypeListener, /* A listening port/socket */ +( 4) portTypeAcceptor, /* An intermidiate stage when accepting +( 5) on a listen port */ +( 6) portTypeConnector, /* An intermediate stage when connecting */ +( 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 */ +(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> + <code type="none"><![CDATA[ +( 1) typedef unsigned char Byte; +( 2) typedef unsigned int Word; + +( 3) typedef struct uds_data { +( 4) int fd; /* File descriptor */ +( 5) ErlDrvPort port; /* The port identifier */ +( 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 */ +(10) PortType type; /* Type of port */ +(11) char *name; /* Short name of socket for unlink */ +(12) Word sent; /* Bytes sent */ +(13) Word received; /* Bytes received */ +(14) struct uds_data *partner; /* The partner in an accept/listen pair */ +(15) struct uds_data *next; /* Next structure in list */ +(16) /* The input buffer and it's data */ +(17) int buffer_size; /* The allocated size of the input buffer */ +(18) int buffer_pos; /* Current position in input buffer */ +(19) int header_pos; /* Where the current header is in the +(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 + 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> + <item> + <p>lockfd - 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 + 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 + 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 + 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 + <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> + </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 + 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 + 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 + to use is named <c><![CDATA[DRIVER_INIT]]></c> and takes the driver name + 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 + 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) { +( 3) UdsData *ud; +( 4) +( 5) ud = ALLOC(sizeof(UdsData)); +( 6) ud->fd = -1; +( 7) ud->lockfd = -1; +( 8) ud->creation = 0; +( 9) ud->port = port; +(10) ud->type = portTypeUnknown; +(11) ud->name = NULL; +(12) ud->buffer_size = 0; +(13) ud->buffer_pos = 0; +(14) ud->header_pos = 0; +(15) ud->buffer = NULL; +(16) ud->sent = 0; +(17) ud->received = 0; +(18) ud->partner = NULL; +(19) ud->next = first_data; +(20) first_data = ud; +(21) +(22) return((ErlDrvData) ud); +(23) } ]]></code> + <p>Every data item is initialized, so that no problems will 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> + <code type="none"><![CDATA[ +( 1) static void uds_command(ErlDrvData handle, char *buff, int bufflen) +( 2) { +( 3) UdsData *ud = (UdsData *) handle; + +( 4) if (ud->type == portTypeData || ud->type == portTypeIntermediate) { +( 5) DEBUGF(("Passive do_send %d",bufflen)); +( 6) do_send(ud, buff + 1, bufflen - 1); /* XXX */ +( 7) return; +( 8) } +( 9) if (bufflen == 0) { +(10) return; +(11) } +(12) switch (*buff) { +(13) case 'L': +(14) if (ud->type != portTypeUnknown) { +(15) driver_failure_posix(ud->port, ENOTSUP); +(16) return; +(17) } +(18) uds_command_listen(ud,buff,bufflen); +(19) return; +(20) case 'A': +(21) if (ud->type != portTypeUnknown) { +(22) driver_failure_posix(ud->port, ENOTSUP); +(23) return; +(24) } +(25) uds_command_accept(ud,buff,bufflen); +(26) return; +(27) case 'C': +(28) if (ud->type != portTypeUnknown) { +(29) driver_failure_posix(ud->port, ENOTSUP); +(30) return; +(31) } +(32) uds_command_connect(ud,buff,bufflen); +(33) return; +(34) case 'S': +(35) if (ud->type != portTypeCommand) { +(36) driver_failure_posix(ud->port, ENOTSUP); +(37) return; +(38) } +(39) do_send(ud, buff + 1, bufflen - 1); +(40) return; +(41) case 'R': +(42) if (ud->type != portTypeCommand) { +(43) driver_failure_posix(ud->port, ENOTSUP); +(44) return; +(45) } +(46) do_recv(ud); +(47) return; +(48) default: +(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 + 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 + 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 + 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> + <code type="none"><![CDATA[ +( 1) static void do_recv(UdsData *ud) +( 2) { +( 3) int res; +( 4) char *ibuf; +( 5) for(;;) { +( 6) if ((res = buffered_read_package(ud,&ibuf)) < 0) { +( 7) if (res == NORMAL_READ_FAILURE) { +( 8) driver_select(ud->port, (ErlDrvEvent) ud->fd, DO_READ, 1); +( 9) } else { +(10) driver_failure_eof(ud->port); +(11) } +(12) return; +(13) } +(14) /* Got a package */ +(15) if (ud->type == portTypeCommand) { +(16) ibuf[-1] = 'R'; /* There is always room for a single byte +(17) opcode before the actual buffer +(18) (where the packet header was) */ +(19) driver_output(ud->port,ibuf - 1, res + 1); +(20) driver_select(ud->port, (ErlDrvEvent) ud->fd, DO_READ,0); +(21) return; +(22) } else { +(23) ibuf[-1] = DIST_MAGIC_RECV_TAG; /* XXX */ +(24) driver_output(ud->port,ibuf - 1, res + 1); +(25) driver_select(ud->port, (ErlDrvEvent) ud->fd, DO_READ,1); +(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 + 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 + 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) { +( 3) UdsData *ud = (UdsData *) handle; + +( 4) if (ud->type == portTypeListener) { +( 5) UdsData *ad = ud->partner; +( 6) struct sockaddr_un peer; +( 7) int pl = sizeof(struct sockaddr_un); +( 8) int fd; + +( 9) if ((fd = accept(ud->fd, (struct sockaddr *) &peer, &pl)) < 0) { +(10) if (errno != EWOULDBLOCK) { +(11) driver_failure_posix(ud->port, errno); +(12) return; +(13) } +(14) return; +(15) } +(16) SET_NONBLOCKING(fd); +(17) ad->fd = fd; +(18) ad->partner = NULL; +(19) ad->type = portTypeCommand; +(20) ud->partner = NULL; +(21) driver_select(ud->port, (ErlDrvEvent) ud->fd, DO_READ, 0); +(22) driver_output(ad->port, "Aok",3); +(23) return; +(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 + 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> + <code type="none"><![CDATA[ +( 1) static void do_send(UdsData *ud, char *buff, int bufflen) +( 2) { +( 3) char header[4]; +( 4) int written; +( 5) SysIOVec iov[2]; +( 6) ErlIOVec eio; +( 7) ErlDrvBinary *binv[] = {NULL,NULL}; + +( 8) put_packet_length(header, bufflen); +( 9) iov[0].iov_base = (char *) header; +(10) iov[0].iov_len = 4; +(11) iov[1].iov_base = buff; +(12) iov[1].iov_len = bufflen; +(13) eio.iov = iov; +(14) eio.binv = binv; +(15) eio.vsize = 2; +(16) eio.size = bufflen + 4; +(17) written = 0; +(18) if (driver_sizeq(ud->port) == 0) { +(19) if ((written = writev(ud->fd, iov, 2)) == eio.size) { +(20) ud->sent += written; +(21) if (ud->type == portTypeCommand) { +(22) driver_output(ud->port, "Sok", 3); +(23) } +(24) return; +(25) } else if (written < 0) { +(26) if (errno != EWOULDBLOCK) { +(27) driver_failure_eof(ud->port); +(28) return; +(29) } else { +(30) written = 0; +(31) } +(32) } else { +(33) ud->sent += written; +(34) } +(35) /* Enqueue remaining */ +(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> + 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 it's own buffers when we call + <c><![CDATA[driver_enqv]]></c> (line 37).</p> + <p></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 + 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 + 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> + <code type="none"><![CDATA[ +( 1) static int send_out_queue(UdsData *ud) +( 2) { +( 3) for(;;) { +( 4) int vlen; +( 5) SysIOVec *tmp = driver_peekq(ud->port, &vlen); +( 6) int wrote; +( 7) if (tmp == NULL) { +( 8) driver_select(ud->port, (ErlDrvEvent) ud->fd, DO_WRITE, 0); +( 9) if (ud->type == portTypeCommand) { +(10) driver_output(ud->port, "Sok", 3); +(11) } +(12) return 0; +(13) } +(14) if (vlen > IO_VECTOR_MAX) { +(15) vlen = IO_VECTOR_MAX; +(16) } +(17) if ((wrote = writev(ud->fd, tmp, vlen)) < 0) { +(18) if (errno == EWOULDBLOCK) { +(19) driver_select(ud->port, (ErlDrvEvent) ud->fd, +(20) DO_WRITE, 1); +(21) return 0; +(22) } else { +(23) driver_failure_eof(ud->port); +(24) return -1; +(25) } +(26) } +(27) driver_deq(ud->port, wrote); +(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 + 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 + 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> + <code type="none"><![CDATA[ +( 1) static void uds_output(ErlDrvData handle, ErlDrvEvent event) +( 2) { +( 3) UdsData *ud = (UdsData *) handle; +( 4) if (ud->type == portTypeConnector) { +( 5) ud->type = portTypeCommand; +( 6) driver_select(ud->port, (ErlDrvEvent) ud->fd, DO_WRITE, 0); +( 7) driver_output(ud->port, "Cok",3); +( 8) return; +( 9) } +(10) send_out_queue(ud); +(11) } ]]></code> + <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 + 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 + 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.\011 </item> + </list> + <p>The control interface gets a buffer to return its value in, + but is free to allocate it's own buffer is the provided one is + to small. Here is the code for <c><![CDATA[uds_control]]></c>:</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) +( 3) { +( 4) /* Local macro to ensure large enough buffer. */ +( 5) #define ENSURE(N) \\ +( 6) do { \\ +( 7) if (res_size < N) { \\ +( 8) *res = ALLOC(N); \\ +( 9) } \\ +(10) } while(0) + +(11) UdsData *ud = (UdsData *) handle; + +(12) switch (command) { +(13) case 'S': +(14) { +(15) ENSURE(13); +(16) **res = 0; +(17) put_packet_length((*res) + 1, ud->received); +(18) put_packet_length((*res) + 5, ud->sent); +(19) put_packet_length((*res) + 9, driver_sizeq(ud->port)); +(20) return 13; +(21) } +(22) case 'C': +(23) if (ud->type < portTypeCommand) { +(24) return report_control_error(res, res_size, "einval"); +(25) } +(26) ud->type = portTypeCommand; +(27) driver_select(ud->port, (ErlDrvEvent) ud->fd, DO_READ, 0); +(28) ENSURE(1); +(29) **res = 0; +(30) return 1; +(31) case 'I': +(32) if (ud->type < portTypeCommand) { +(33) return report_control_error(res, res_size, "einval"); +(34) } +(35) ud->type = portTypeIntermediate; +(36) driver_select(ud->port, (ErlDrvEvent) ud->fd, DO_READ, 0); +(37) ENSURE(1); +(38) **res = 0; +(39) return 1; +(40) case 'D': +(41) if (ud->type < portTypeCommand) { +(42) return report_control_error(res, res_size, "einval"); +(43) } +(44) ud->type = portTypeData; +(45) do_recv(ud); +(46) ENSURE(1); +(47) **res = 0; +(48) return 1; +(49) case 'N': +(50) if (ud->type != portTypeListener) { +(51) return report_control_error(res, res_size, "einval"); +(52) } +(53) ENSURE(5); +(54) (*res)[0] = 0; +(55) put_packet_length((*res) + 1, ud->fd); +(56) return 5; +(57) case 'T': /* tick */ +(58) if (ud->type != portTypeData) { +(59) return report_control_error(res, res_size, "einval"); +(60) } +(61) do_send(ud,"",0); +(62) ENSURE(1); +(63) **res = 0; +(64) return 1; +(65) case 'R': +(66) if (ud->type != portTypeListener) { +(67) return report_control_error(res, res_size, "einval"); +(68) } +(69) ENSURE(2); +(70) (*res)[0] = 0; +(71) (*res)[1] = ud->creation; +(72) return 2; +(73) default: +(74) return report_control_error(res, res_size, "einval"); +(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 + 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 it's 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 + 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 + 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 + specified and an <c><![CDATA[-sname <name>]]></c> flag is present at the + command line, here follows two examples: </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 + +Eshell V5.0 (abort with ^G) +1> <input>net_kernel:start([bing,shortnames]).</input> +{ok,<0.30.0>} +(bing@hador)2></pre> + <p>...</p> + <pre> +$ <input>erl -pa $ERL_TOP/lib/kernel/examples/uds_dist/ebin -proto_dist uds \\ </input> +<input> -no_epmd -sname bong</input> +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 + 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> +$ <input>export ERL_FLAGS</input> +$ <input>erl -sname bang</input> +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> + </section> +</chapter> + diff --git a/erts/doc/src/book.xml b/erts/doc/src/book.xml new file mode 100644 index 0000000000..00a2888685 --- /dev/null +++ b/erts/doc/src/book.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE book SYSTEM "book.dtd"> + +<book xmlns:xi="http://www.w3.org/2001/XInclude"> + <header titlestyle="normal"> + <copyright> + <year>1997</year><year>2009</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>Erlang Run-Time System Application (ERTS)</title> + <prepared>Magnus Fröberg</prepared> + <docno></docno> + <date>1997-05-02</date> + <rev>4.5.2</rev> + <file>book.xml</file> + </header> + <insidecover> + </insidecover> + <pagetext>Erlang Run-Time System Application (ERTS)</pagetext> + <preamble> + <contents level="2"></contents> + </preamble> + <parts lift="no"> + <xi:include href="part.xml"/> + </parts> + <applications> + <xi:include href="ref_man.xml"/> + </applications> + <releasenotes> + <xi:include href="notes.xml"/> + </releasenotes> + <listofterms></listofterms> + <index></index> +</book> + diff --git a/erts/doc/src/crash_dump.xml b/erts/doc/src/crash_dump.xml new file mode 100644 index 0000000000..5182929358 --- /dev/null +++ b/erts/doc/src/crash_dump.xml @@ -0,0 +1,518 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>1999</year><year>2009</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>How to interpret the Erlang crash dumps</title> + <prepared>Patrik Nyblom</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>1999-11-11</date> + <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 + 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> + <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 + system has detected an error that cannot be handled. The most + usual reason that the system can't 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 + reaching limits in the emulator itself (like the number of atoms + 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> + + <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> + + <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 + <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 + 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>")." - 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">erts_alloc(3)</seealso>.</item> + <item>"<em><A></em>: Cannot reallocate <em><N></em> + bytes of memory\011(of type "<em><T></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" - The SIGUSR1 signal was sent to the + Erlang machine (Unix only).</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 + 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> + </section> + + <section> + <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> + </section> + </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> + </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> + </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> + </section> + + <section> + <marker id="allocator"></marker> + <title>Allocator</title> + <p>Under the tag <em>=allocator:<A></em> you will find + 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> + </section> + + <section> + <marker id="processes"></marker> + <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> + <taglist> + <tag><em>=proc:<pid></em></tag> + <item>Heading, states the process identifier</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> + </item> + <tag><em>Registered name</em></tag> + <item>The registered name of the process, if any.</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> + <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>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> + <tag><em>Started</em></tag> + <item>The date and time when the process was started.</item> + <tag><em>Message queue length</em></tag> + <item>The number of messages in the process' message queue.</item> + <tag><em>Number of heap fragments</em></tag> + <item>The number of allocated heap fragments.</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> + <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> + <tag><em>Reductions</em></tag> + <item>The number of reductions consumed by the process.</item> + <tag><em>Stack+heap</em></tag> + <item>The size of the stack and heap (they share memory segment)</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> + <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> + <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> + <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> + <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> + </taglist> + <p>See also the section about <seealso marker="#proc_data">process data</seealso>.</p> + </section> + + <section> + <marker id="ports"></marker> + <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> + </section> + + <section> + <marker id="ets_tables"></marker> + <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> + <taglist> + <tag><em>=ets:<owner></em></tag> + <item>Heading, states the owner of the table (a process identifier)</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> + <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> + <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> + <tag><em>Objects</em></tag> + <item>The number of objects in the table</item> + <tag><em>Words</em></tag> + <item>The number of words (usually 4 bytes/word) allocated to data + in the table.</item> + </taglist> + </section> + + <section> + <marker id="timers"></marker> + <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> + <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> + <tag><em>Message</em></tag> + <item>The message to be sent.</item> + <tag><em>Time left</em></tag> + <item>Number of milliseconds left until the message would have been + sent.</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 + 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> + <tag><em>no_distribution</em></tag> + <item>This will only occur if the node was not distributed.</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> + <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> + <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> + <tag><em>Name</em></tag> + <item>The name of the remote node.</item> + <tag><em>Controller</em></tag> + <item>The port which controls the communication with the remote node.</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> + <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> + </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> + <taglist> + <tag><em>=mod:<module_name></em></tag> + <item>Heading, and the name of the module.</item> + <tag><em>Current size</em></tag> + <item>Memory usage for the loaded code in bytes</item> + <tag><em>Old size</em></tag> + <item>Memory usage for the old code, if any.</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> + <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> + <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> + <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> + </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> + <taglist> + <tag><em>=fun</em></tag> + <item>Heading</item> + <tag><em>Module</em></tag> + <item>The name of the module where the fun was defined.</item> + <tag><em>Uniq, Index</em></tag> + <item>Identifiers</item> + <tag><em>Address</em></tag> + <item>The address of the fun's code.</item> + <tag><em>Native_address</em></tag> + <item>The address of the fun's code when HiPE is enabled.</item> + <tag><em>Refc</em></tag> + <item>The number of references to the fun.</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 + 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>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> + <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> + <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"] +(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> + <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> + </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 + be a problem, otherwise this section can be ignored.</p> + <p>Note that the last created atom is printed 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 + an explanation of the crash dump in general and as a help + when trying to find application errors, not as a complete + specification.</p> + </section> +</chapter> + diff --git a/erts/doc/src/driver.xml b/erts/doc/src/driver.xml new file mode 100644 index 0000000000..c396ee0b90 --- /dev/null +++ b/erts/doc/src/driver.xml @@ -0,0 +1,812 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2001</year><year>2009</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>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 + valid, but some things have changed since it was first written. + Updates of this document 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> + + <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>A driver can be dynamically loaded, as a shared library (known as + 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> + </section> + + <section> + <title>Sample driver</title> + <p>This is 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 www.postgres.org.</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 + 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 <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 + 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 + <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 + 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. + 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 + 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 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> + <code type="none"><![CDATA[ +/* Driver interface declarations */ +static ErlDrvData start(ErlDrvPort port, char *command); +static void stop(ErlDrvData drv_data); +static int control(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen); + +static ErlDrvEntry pq_driver_entry = { + NULL, /* init */ + start, + stop, + NULL, /* output */ + NULL, /* ready_input */ + NULL, /* ready_output */ + "pg_sync", /* the name of the driver */ + NULL, /* finish */ + NULL, /* handle */ + control, + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + 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> + <code type="none"><![CDATA[ +typedef struct our_data_s { + PGconn* conn; +} our_data_t; + ]]></code> + <p>These are control codes we have defined.</p> + <code type="none"><![CDATA[ +/* Keep the following definitions in alignment with the + * defines in erl_pq_sync.erl + */ + +#define DRV_CONNECT 'C' +#define DRV_DISCONNECT 'D' +#define DRV_SELECT 'S' + ]]></code> + <p>This just 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 */ + +/* + * This is the init function called after this driver has been loaded. + * It must *not* be declared static. Must return the address to + * the driver entry. + */ + +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> + <code type="none"><![CDATA[ +/* DRIVER INTERFACE */ +static ErlDrvData start(ErlDrvPort port, char *command) +{ + our_data_t* data; + + data = (our_data_t*)driver_alloc(sizeof(our_data_t)); + data->conn = NULL; + set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY); + 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); + +static void stop(ErlDrvData drv_data) +{ + do_disconnect((our_data_t*)drv_data, NULL); +} + ]]></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 + <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 is used to make the code shorter. <c><![CDATA[get_s]]></c> + duplicates the string and zero-terminates it, since 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> + <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 + * is irrelevant, as long as it is not negative. + */ +static int control(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen) +{ + int r; + ei_x_buff x; + our_data_t* data = (our_data_t*)drv_data; + char* s = get_s(buf, len); + ei_x_new_with_version(&x); + switch (command) { + case DRV_CONNECT: r = do_connect(s, data, &x); break; + case DRV_DISCONNECT: r = do_disconnect(data, &x); break; + case DRV_SELECT: r = do_select(s, data, &x); break; + default: r = -1; break; + } + *rbuf = (char*)ei_x_to_new_binary(&x); + ei_x_free(&x); + driver_free(s); + return r; +} + ]]></code> + <p>In <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> + <code type="none"><![CDATA[ +static int do_connect(const char *s, our_data_t* data, ei_x_buff* x) +{ + PGconn* conn = PQconnectdb(s); + if (PQstatus(conn) != CONNECTION_OK) { + encode_error(x, conn); + PQfinish(conn); + conn = NULL; + } else { + encode_ok(x); + } + data->conn = conn; + return 0; +} + ]]></code> + <p>If we are connected (if the connection handle is not <c><![CDATA[NULL]]></c>), + we log out from the database. We need to check if a 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> + <code type="none"><![CDATA[ +static int do_disconnect(our_data_t* data, ei_x_buff* x) +{ + if (data->conn == NULL) + return 0; + PQfinish(data->conn); + data->conn = NULL; + if (x != NULL) + encode_ok(x); + return 0; +} + ]]></code> + <p>We execute a query and encodes 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) +{ + PGresult* res = PQexec(data->conn, s); + encode_result(x, res, data->conn); + PQclear(res); + return 0; +} + ]]></code> + <p>Here we simply checks the result from postgres, and + if it's 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 + 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) +{ + int row, n_rows, col, n_cols; + switch (PQresultStatus(res)) { + case PGRES_TUPLES_OK: + n_rows = PQntuples(res); + n_cols = PQnfields(res); + ei_x_encode_tuple_header(x, 2); + encode_ok(x); + ei_x_encode_list_header(x, n_rows+1); + ei_x_encode_list_header(x, n_cols); + for (col = 0; col < n_cols; ++col) { + ei_x_encode_string(x, PQfname(res, col)); + } + ei_x_encode_empty_list(x); + for (row = 0; row < n_rows; ++row) { + ei_x_encode_list_header(x, n_cols); + for (col = 0; col < n_cols; ++col) { + ei_x_encode_string(x, PQgetvalue(res, row, col)); + } + ei_x_encode_empty_list(x); + } + ei_x_encode_empty_list(x); + break; + case PGRES_COMMAND_OK: + ei_x_encode_tuple_header(x, 2); + encode_ok(x); + ei_x_encode_string(x, PQcmdTuples(res)); + break; + default: + encode_error(x, conn); + break; + } +} + ]]></code> + </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 + 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 + 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> + <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 + 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 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> + <code type="none"><![CDATA[ +-module(pg_sync). + +-define(DRV_CONNECT, 1). +-define(DRV_DISCONNECT, 2). +-define(DRV_SELECT, 3). + +-export([connect/1, disconnect/1, select/2]). + +connect(ConnectStr) -> + case erl_ddll:load_driver(".", "pg_sync") of + ok -> ok; + {error, already_loaded} -> ok; + E -> exit({error, E}) + end, + Port = open_port({spawn, ?MODULE}, []), + case binary_to_term(port_control(Port, ?DRV_CONNECT, ConnectStr)) of + ok -> {ok, Port}; + Error -> Error + end. + +disconnect(Port) -> + R = binary_to_term(port_control(Port, ?DRV_DISCONNECT, "")), + port_close(Port), + R. + +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, + 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 + <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 + <c><![CDATA[catch]]></c>.)</p> + </section> + + <section> + <title>Sample asynchronous driver</title> + <p>Sometimes database queries can take long time to + complete, in our <c><![CDATA[pg_sync]]></c> driver, the emulator + halts while the driver is doing it's job. This is + often not acceptable, since no other Erlang processes + gets a chance to do anything. To improve on our + postgres driver, we reimplement 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> + <code type="none"><![CDATA[ +/* Driver interface declarations */ +static ErlDrvData start(ErlDrvPort port, char *command); +static void stop(ErlDrvData drv_data); +static int control(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen); +static void ready_io(ErlDrvData drv_data, ErlDrvEvent event); + +static ErlDrvEntry pq_driver_entry = { + NULL, /* init */ + start, + stop, + NULL, /* output */ + ready_io, /* ready_input */ + ready_io, /* ready_output */ + "pg_async", /* the name of the driver */ + NULL, /* finish */ + NULL, /* handle */ + control, + NULL, /* timeout */ + NULL, /* outputv */ + NULL, /* ready_async */ + NULL, /* flush */ + NULL, /* call */ + NULL /* event */ +}; + +typedef struct our_data_t { + PGconn* conn; + ErlDrvPort port; + int socket; + 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 + 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> + <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 + 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 + when there is query result.)</p> + <code type="none"><![CDATA[ +static int do_connect(const char *s, our_data_t* data) +{ + PGconn* conn = PQconnectStart(s); + if (PQstatus(conn) == CONNECTION_BAD) { + ei_x_buff x; + ei_x_new_with_version(&x); + encode_error(&x, conn); + PQfinish(conn); + conn = NULL; + driver_output(data->port, x.buff, x.index); + ei_x_free(&x); + } + PQconnectPoll(conn); + int socket = PQsocket(conn); + data->socket = socket; + driver_select(data->port, (ErlDrvEvent)socket, DO_READ, 1); + driver_select(data->port, (ErlDrvEvent)socket, DO_WRITE, 1); + data->conn = conn; + data->connecting = 1; + 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 + 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 + 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> + <code type="none"><![CDATA[ +static int do_select(const char* s, our_data_t* data) +{ + data->connecting = 0; + PGconn* conn = data->conn; + /* if there's an error return it now */ + if (PQsendQuery(conn, s) == 0) { +\011ei_x_buff x; +\011ei_x_new_with_version(&x); +\011encode_error(&x, conn); +\011driver_output(data->port, x.buff, x.index); +\011ei_x_free(&x); + } + /* else wait for ready_output to get results */ + 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 + when <c><![CDATA[ready_io]]></c> is called.</p> + <code type="none"><![CDATA[ +static void ready_io(ErlDrvData drv_data, ErlDrvEvent event) +{ + PGresult* res = NULL; + our_data_t* data = (our_data_t*)drv_data; + PGconn* conn = data->conn; + ei_x_buff x; + ei_x_new_with_version(&x); + if (data->connecting) { +\011ConnStatusType status; +\011PQconnectPoll(conn); +\011status = PQstatus(conn); +\011if (status == CONNECTION_OK) +\011 encode_ok(&x); +\011else if (status == CONNECTION_BAD) +\011 encode_error(&x, conn); + } else { +\011PQconsumeInput(conn); +\011if (PQisBusy(conn)) +\011 return; +\011res = PQgetResult(conn); +\011encode_result(&x, res, conn); +\011PQclear(res); +\011for (;;) { +\011 res = PQgetResult(conn); +\011 if (res == NULL) +\011\011break; +\011 PQclear(res); +\011} + } + if (x.index > 1) { +\011driver_output(data->port, x.buff, x.index); +\011if (data->connecting) +\011 driver_select(data->port, (ErlDrvEvent)data->socket, DO_WRITE, 0); + } + ei_x_free(&x); +} + ]]></code> + <p>The <c><![CDATA[ready_io]]></c> function will be 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> + <p>If we have result from a connect, indicated that we have 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 + <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>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). + +-define(DRV_CONNECT, $C). +-define(DRV_DISCONNECT, $D). +-define(DRV_SELECT, $S). + +-export([connect/1, disconnect/1, select/2]). + +connect(ConnectStr) -> + case erl_ddll:load_driver(".", "pg_async") of +\011ok -> ok; +\011{error, already_loaded} -> ok; +\011_ -> exit({error, could_not_load_driver}) + end, + Port = open_port({spawn, ?MODULE}, [binary]), + port_control(Port, ?DRV_CONNECT, ConnectStr), + case return_port_data(Port) of +\011ok -> +\011 {ok, Port}; +\011Error -> +\011 Error + end. + +disconnect(Port) -> + port_control(Port, ?DRV_DISCONNECT, ""), + R = return_port_data(Port), + port_close(Port), + R. + +select(Port, Query) -> + port_control(Port, ?DRV_SELECT, Query), + return_port_data(Port). + +return_port_data(Port) -> + receive +\011{Port, {data, Data}} -> +\011 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>, + 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 + binary format, we use <c><![CDATA[binary_to_term/1]]></c> to convert + it to Erlang term. Note that the driver is opened in + binary mode, <c><![CDATA[open_port/2]]></c> is called with the 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> + </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>. + 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 + as an asynchronous task.</p> + <p>The asynchronous api for drivers are 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 all 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. + 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> + <code type="none"><![CDATA[ +static ErlDrvEntry next_perm_driver_entry = { + NULL,\011\011\011/* init */ + start, + NULL, \011\011\011/* stop */ + output,\011\011\011 + NULL,\011\011\011/* ready_input */ + NULL,\011\011\011/* ready_output */ + "next_perm", /* the name of the driver */ + NULL,\011\011\011/* finish */ + NULL,\011\011\011/* handle */ + NULL,\011\011\011/* control */ + NULL,\011\011\011/* timeout */ + NULL,\011\011\011/* outputv */ + ready_async, + NULL,\011\011\011/* flush */ + NULL,\011\011\011/* call */ + NULL\011\011\011/* 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, + 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 + programmatically.</p> + <code type="none"><![CDATA[ +struct our_async_data { + bool prev; + vector<int> data; + our_async_data(ErlDrvPort p, int command, const char* buf, int len); +}; + +our_async_data::our_async_data(ErlDrvPort p, int command, +\011\011\011 const char* buf, int len) + : prev(command == 2), + data((int*)buf, (int*)buf + len / sizeof(int)) +{ +} + +static void do_perm(void* async_data); + +static void output(ErlDrvData drv_data, char *buf, int len) +{ + if (*buf < 1 || *buf > 2) return; + ErlDrvPort port = reinterpret_cast<ErlDrvPort>(drv_data); + void* async_data = new our_async_data(port, *buf, buf+1, 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 + on the structure that was allocated in <c><![CDATA[output]]></c>.</p> + <code type="none"><![CDATA[ +static void do_perm(void* async_data) +{ + our_async_data* d = reinterpret_cast<our_async_data*>(async_data); + if (d->prev) +\011prev_permutation(d->data.begin(), d->data.end()); + else +\011next_permutation(d->data.begin(), d->data.end()); +} + ]]></code> + <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 + <c><![CDATA[ei]]></c> to handle the binary term format.</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) +{ + ErlDrvPort port = reinterpret_cast<ErlDrvPort>(drv_data); + our_async_data* d = reinterpret_cast<our_async_data*>(async_data); + int n = d->data.size(), result_n = n*2 + 3; + ErlDrvTermData* result = new ErlDrvTermData[result_n], * rp = result; + for (vector<int>::iterator i = d->data.begin(); +\011 i != d->data.end(); ++i) { +\011*rp++ = ERL_DRV_INT; +\011*rp++ = *i; + } + *rp++ = ERL_DRV_NIL; + *rp++ = ERL_DRV_LIST; + *rp++ = n+1; + driver_output_term(port, result, result_n); + delete[] result; + delete d; +} + ]]></code> + <p>This driver is called like the others from Erlang, however, since + 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><![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). + +-export([next_perm/1, prev_perm/1, load/0, all_perm/1]). + +load() -> + case whereis(next_perm) of +\011undefined -> +\011 case erl_ddll:load_driver(".", "next_perm") of +\011\011ok -> ok; +\011\011{error, already_loaded} -> ok; +\011\011E -> exit(E) +\011 end, +\011 Port = open_port({spawn, "next_perm"}, []), +\011 register(next_perm, Port); +\011_ -> +\011 ok + end. + +list_to_integer_binaries(L) -> + [<<I:32/integer-native>> || I <- L]. + +next_perm(L) -> + next_perm(L, 1). + +prev_perm(L) -> + next_perm(L, 2). + +next_perm(L, Nxt) -> + load(), + B = list_to_integer_binaries(L), + port_control(next_perm, Nxt, B), + receive +\011Result -> +\011 Result + end. + +all_perm(L) -> + New = prev_perm(L), + all_perm(New, L, [New]). + +all_perm(L, L, Acc) -> + Acc; +all_perm(L, Orig, Acc) -> + New = prev_perm(L), + all_perm(New, Orig, [New | Acc]). + ]]></code> + </section> +</chapter> + diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml new file mode 100644 index 0000000000..6b7d2acf24 --- /dev/null +++ b/erts/doc/src/driver_entry.xml @@ -0,0 +1,453 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>2001</year><year>2009</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>driver_entry</title> + <prepared>Jakob Cederlund</prepared> + <responsible>Jakob Cederlund</responsible> + <docno>1</docno> + <approved></approved> + <checked></checked> + <date>2001-10-01</date> + <rev>PA1</rev> + <file>driver_entry.xml</file> + </header> + <lib>driver_entry</lib> + <libsummary>The driver-entry structure used by erlang drivers.</libsummary> + <description> + <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 + <seealso marker="erl_driver#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> + <note> + <p>Old drivers (compiled with an <c>erl_driver.h</c> from an + earlier erts version than 5.5.3) have to be recompiled + (but does not have to use the extended interface).</p> + </note> + <p>The <c>driver_entry</c> structure is a C struct that all erlang + drivers defines. It contains entry points for the erlang driver + that are called by the erlang emulator when erlang code accesses + the driver.</p> + <p> + <marker id="emulator"></marker> + The <seealso marker="driver_entry">erl_driver</seealso> driver + API functions needs 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 + not to the other functions. The <c>start</c> function returns a + driver-defined handle that is passed to the other functions. A + common practice is to have the <c>start</c> function allocating + 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 + responsive.</p> + <p>The driver structure contains the name of the driver and some + 15 function pointers. These pointers 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> + <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> + <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> + </note> + </description> + + <section> + <title>DATA TYPES</title> + <taglist> + <tag><b>ErlDrvEntry</b></tag> + <item> + <p/> + <code type="none"> +typedef struct erl_drv_entry { + int (*init)(void); /* called at system start up for statically + linked drivers, and after loading for + 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. */ +#else + ErlDrvData (*start)(ErlDrvPort port, char *command, SysDriverOpts* opts); + /* special options, only for system driver */ +#endif + void (*stop)(ErlDrvData drv_data); + /* called when port is closed, and when the + emulator is halted. */ + void (*output)(ErlDrvData drv_data, char *buf, int len); + /* 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 + the driver's handles) */ + void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event); + /* 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 */ + int (*control)(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen); + /* "ioctl" for drivers - invoked by + port_control/3) */ + void (*timeout)(ErlDrvData drv_data); /* Handling of timeout in driver */ + void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev); + /* 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 + before 'stop' can be called */ + int (*call)(ErlDrvData drv_data, unsigned int command, char *buf, + int len, char **rbuf, int rlen, unsigned int *flags); + /* Works mostly like 'control', a syncronous + call into the driver. */ + void (*event)(ErlDrvData drv_data, ErlDrvEvent event, + ErlDrvEventData event_data); + /* Called when an event selected by + driver_event() has occurred */ + 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 (*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/> + <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> + </item> + <tag><marker id="start"/>int (*start)(ErlDrvPort port, char* command)</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> + </item> + <tag><marker id="stop"/>void (*stop)(ErlDrvData drv_data)</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\011 port.</p> + </item> + <tag><marker id="output"/>void (*output)(ErlDrvData drv_data, char *buf, int len)</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> + </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> + <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 + 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 + function understands). (Some trickery in the emulator allows + more than the built-in limit of 64 <c>Events</c> to be used.)</p> + <p>To use this with threads and asynchronous routines, create a + pipe on unix and an Event on Windows. When the routine + completes, write to the pipe (use <c>SetEvent</c> on + Windows), this will make the emulator call + <c>ready_input</c> or <c>ready_output</c>.</p> + </item> + <tag><marker id="driver_name"/>char *driver_name</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 + library file (without the extension).</p> + </item> + <tag><marker id="finish"/>void (*finish)(void)</tag> + <item> + <p>This function is 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> + </item> + <tag>void *handle</tag> + <item> + <p>This field is reserved for the emulators 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> + </item> + <tag><marker id="control"></marker>int (*control)(ErlDrvData drv_data, unsigned int command, char *buf, int len, char **rbuf, int rlen)</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 + 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 + is too slow.</p> + <p>If the driver wants to return data, it should 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 + the port control flags (those that are set with + <seealso marker="erl_driver#set_port_control_flags">set_port_control_flags</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. + 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> + <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> + <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> + </item> + + <tag><marker id="timeout"/>void (*timeout)(ErlDrvData drv_data)</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> + </item> + + <tag><marker id="outputv"/>void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev)</tag> + <item> + <p>This function is 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 + 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>, + 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 + variable, the reference counter can be incremented.</p> + </item> + <tag><marker id="ready_async"/>void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data)</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 + opposed to the asynchronous function, which is called in + some thread (if multithreading is enabled).</p> + </item> + <tag><marker id="call"/>int (*call)(ErlDrvData drv_data, unsigned int command, char *buf, int len, char **rbuf, int rlen, unsigned int *flags)</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 + 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> + <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 + term and returned by <c>erlang:port_call/3</c> to the + 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> + <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> + </item> + <tag>void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data)</tag> + <item> + <p>Intentionally left undocumented.</p> + </item> + <tag><marker id="extended_marker"/>int extended_marker</tag> + <item> + <p> + This field should either 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> + </item> + <tag>int major_version</tag> + <item> + <p>This field should equal <c>ERL_DRV_EXTENDED_MAJOR_VERSION</c> if + the <c>extended_marker</c> field equals + <c>ERL_DRV_EXTENDED_MARKER</c>.</p> + </item> + <tag>int minor_version</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> + </item> + + <tag><marker id="driver_flags"/>int driver_flags</tag> + <item> + <p>This field is used to pass driver capability 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> + <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> + <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). + </item> + </taglist> + </item> + <tag>void *handle2</tag> + <item> + <p> + This field is reserved for the emulators 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> + </item> + <tag><marker id="process_exit"/>void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor)</tag> + <item> + <p>This callback is 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> + 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 + an <c>ErlDrvTermData</c>.</p> + </item> + <tag><marker id="stop_select"/>void (*stop_select)(ErlDrvEvent event, void* reserved)</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>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> + <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> + </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="erts:erlang">erlang(3)</seealso>, + kernel(3)</p> + </section> +</cref> + diff --git a/erts/doc/src/epmd.xml b/erts/doc/src/epmd.xml new file mode 100644 index 0000000000..796ab3820b --- /dev/null +++ b/erts/doc/src/epmd.xml @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE comref SYSTEM "comref.dtd"> + +<comref> + <header> + <copyright> + <year>1996</year><year>2009</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>epmd</title> + <prepared>Claes Wikström</prepared> + <responsible></responsible> + <docno>1</docno> + <approved></approved> + <checked></checked> + <date>98-01-05</date> + <rev>A</rev> + <file>epmd.xml</file> + </header> + <com>epmd</com> + <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 + <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 + 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> map + symbolic node names to machine addresses.</p> + <p>The daemon is started automatically by the Erlang start-up script.</p> + <p>The program <c><![CDATA[epmd]]></c> can also be used for a variety of other + purposes, for example checking the DNS (Domain Name System) + configuration of a host.</p> + </description> + <funcs> + <func> + <name>epmd [-daemon] </name> + <fsummary>Start a name server as a daemon</fsummary> + <desc> + <p>Starts a name server as a daemon. If it has no argument, the + <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> + </desc> + </func> + <func> + <name>epmd -names</name> + <fsummary>Request the names of the registered Erlang nodes on this host</fsummary> + <desc> + <p>Requests the names of the local Erlang nodes <c><![CDATA[epmd]]></c> has + registered.</p> + </desc> + </func> + <func> + <name>epmd -kill</name> + <fsummary>Kill the <c><![CDATA[epmd]]></c>process</fsummary> + <desc> + <p>Kills the <c><![CDATA[epmd]]></c> process.</p> + </desc> + </func> + <func> + <name>epmd -help</name> + <fsummary>List options</fsummary> + <desc> + <p>Write short info about the usage including some debugging + options not listed here.</p> + </desc> + </func> + </funcs> + + <section> + <marker id="environment_variables"></marker> + <title>Environment variables</title> + <taglist> + <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> + </item> + </taglist> + </section> + + <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> + <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> + </section> +</comref> + diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml new file mode 100644 index 0000000000..90a3c53a37 --- /dev/null +++ b/erts/doc/src/erl.xml @@ -0,0 +1,928 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE comref SYSTEM "comref.dtd"> + +<comref> + <header> + <copyright> + <year>1996</year><year>2009</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>erl</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>erl.xml</file> + </header> + <com>erl</com> + <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 + 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 + you want to redirect standard input or output.</p> + </description> + <funcs> + <func> + <name>erl <arguments></name> + <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> +% <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> +% <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> + </desc> + </func> + </funcs> + + <section> + <marker id="init_flags"></marker> + <title>Flags</title> + <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 + application documentation.</p> + <taglist> + <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> + </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><c><![CDATA[-args_file FileName]]></c></tag> + <item> + <marker id="args_file"></marker> + <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> + </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 + later). This flag disables the start synchronization feature + and lets the shell start in parallel with the rest of + the system.</p> + </item> + <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 + <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> + <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> + </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> + </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> + </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> + </item> + <tag><c><![CDATA[-connect_all false]]></c></tag> + <item> + <marker id="connect_all"></marker> + <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> + </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> + </item> + <tag><c><![CDATA[-detached]]></c></tag> + <item> + <p>Starts the Erlang runtime system detached from the system + console. Useful for running daemons and backgrounds processes.</p> + </item> + <tag><c><![CDATA[-emu_args]]></c></tag> + <item> + <p>Useful for debugging. Prints out the actual arguments + sent to the emulator.</p> + </item> + <tag><c><![CDATA[-env Variable Value]]></c></tag> + <item> + <p>Sets the host OS environment variable <c><![CDATA[Variable]]></c> to + the value <c><![CDATA[Value]]></c> for the Erlang runtime system. + Example:</p> + <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> + </item> + <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> + </item> + <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 + <c><![CDATA[init:get_plain_arguments/0]]></c>.</p> + </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> + </item> + <tag><c><![CDATA[-hidden]]></c></tag> + <item> + <p>Starts the Erlang runtime system as a hidden node, if it is + 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 + neither 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> + </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) + 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> + </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><c><![CDATA[-instr]]></c>(emulator flag)</tag> + <item> + <marker id="instr"></marker> + <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>. + 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 + <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 + <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> + </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> + </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> + </item> + <tag><c><![CDATA[-noinput]]></c></tag> + <item> + <p>Ensures that the Erlang runtime system never tries to read + any input. Implies <c><![CDATA[-noshell]]></c>.</p> + </item> + <tag><c><![CDATA[-noshell]]></c></tag> + <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> + </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> + </item> + <tag><c><![CDATA[-oldshell]]></c></tag> + <item> + <p>Invokes the old Erlang shell from Erlang 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> + </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> + </item> + <tag><c><![CDATA[-remsh Node]]></c></tag> + <item> + <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> + </item> + <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> + </item> + <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> + </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#erlang:set_cookie/2">erlang:set_cookie/2</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> + </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 + 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 + names must be unique in distributed Erlang systems.</p> + </item> + <tag><c><![CDATA[-smp [enable|auto|disable]]]></c></tag> + <item> + <marker id="smp"></marker> + <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. + By default <c>-smp auto</c> will be used unless a conflicting + parameter has been passed, then <c>-smp disable</c> will be + used. Currently only the <c>-hybrid</c> parameter conflicts + with <c>-smp auto</c>.</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> + </item> + <tag><c><![CDATA[-version]]></c>(emulator flag)</tag> + <item> + <p>Makes the emulator print out its version number. The same + as <c><![CDATA[erl +V]]></c>.</p> + </item> + </taglist> + </section> + + <section> + <marker id="emu_flags"></marker> + <title>Emulator Flags</title> + <p><c><![CDATA[erl]]></c> invokes the code for the Erlang emulator (virtual + machine), which supports the following flags:</p> + <taglist> + <tag><c><![CDATA[+a size]]></c></tag> + <item> + <marker id="async_thread_stack_size"></marker> + <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 + 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> + </item> + <tag><c><![CDATA[+A size]]></c></tag> + <item> + <marker id="async_thread_pool_size"></marker> + <p>Sets the number of threads in async thread pool, valid range + is 0-1024. Default is 0.</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><c><![CDATA[+c]]></c></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> + </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.</p> + </item> + <tag><c><![CDATA[+h Size]]></c></tag> + <item> + <p>Sets the default heap size of processes to the size + <c><![CDATA[Size]]></c>.</p> + </item> + <tag><c><![CDATA[+K true | false]]></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> + </item> + <tag><c><![CDATA[+l]]></c></tag> + <item> + <p>Enables auto load tracing, displaying info while loading + code.</p> + </item> + <tag><c><![CDATA[+MFlag Value]]></c></tag> + <item> + <marker id="erts_alloc"></marker> + <p>Memory allocator specific flags, see + <seealso marker="erts_alloc">erts_alloc(3)</seealso> for + further information.</p> + </item> + <tag><c><![CDATA[+P Number]]></c></tag> + <item> + <marker id="max_processes"></marker> + <p>Sets the maximum number of concurrent processes for this + system. <c><![CDATA[Number]]></c> must be in the range 16..134217727. + Default is 32768.</p> + </item> + <tag><c><![CDATA[+R ReleaseNumber]]></c></tag> + <item> + <marker id="compat_rel"></marker> + <p>Sets the compatibility mode.</p> + <p>The distribution mechanism is not backwards compatible by + default. This flags 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[7..<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>For example, an R10 node is not automatically compatible + with an R9 node, but R10 nodes started with the <c><![CDATA[+R 9]]></c> + flag can co-exist with R9 nodes in the same distributed + Erlang system, they are R9-compatible.</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> + <p>For example: A distributed Erlang system can consist of + R10 nodes, or of R9 nodes and R9-compatible R10 nodes, but + not of R9 nodes, R9-compatible R10 nodes and "regular" R10 + nodes, as R9 and "regular" R10 nodes are not compatible.</p> + </item> + <tag><c><![CDATA[+r]]></c></tag> + <item> + <p>Force ets memory block to be moved on realloc.</p> + </item> + <tag><c><![CDATA[+S Schedulers:SchedulerOnline]]></c></tag> + <item> + <marker id="+S"></marker> + <p>Sets the amount of scheduler threads to create and scheduler + threads to set online when SMP support has been enabled. + Valid range for both values are 1-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 + amount 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 flag will be ignored if the emulator doesn't have + SMP support enabled (see the <seealso marker="#smp">-smp</seealso> + flag).</p> + </item> + <tag><c><![CDATA[+sFlag Value]]></c></tag> + <item> + <p>Scheduling specific flags.</p> + <taglist> + <tag>+sbt BindType</tag> + <item> + <marker id="+sbt"></marker> + <p>Set scheduler bind type. Currently valid <c>BindType</c>s: + </p> + <taglist> + <tag><c>u</c></tag> + <item><p>Same as + <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, unbound)</seealso>. + </p></item> + <tag><c>ns</c></tag> + <item><p>Same as + <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, no_spread)</seealso>. + </p></item> + <tag><c>ts</c></tag> + <item><p>Same as + <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, thread_spread)</seealso>. + </p></item> + <tag><c>ps</c></tag> + <item><p>Same as + <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, processor_spread)</seealso>. + </p></item> + <tag><c>s</c></tag> + <item><p>Same as + <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, spread)</seealso>. + </p></item> + <tag><c>nnts</c></tag> + <item><p>Same as + <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, no_node_thread_spread)</seealso>. + </p></item> + <tag><c>nnps</c></tag> + <item><p>Same as + <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, no_node_processor_spread)</seealso>. + </p></item> + <tag><c>tnnps</c></tag> + <item><p>Same as + <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, thread_no_node_processor_spread)</seealso>. + </p></item> + <tag><c>db</c></tag> + <item><p>Same as + <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, default_bind)</seealso>. + </p></item> + </taglist> + <p>Binding of schedulers are currently only supported on newer + Linux and Solaris 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>For more information, see + <seealso marker="erlang#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, SchedulerBindType)</seealso>. + </p> + </item> + <tag><c>+sct CpuTopology</c></tag> + <item> + <marker id="+sct"></marker> + <list type="bulleted"> + <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[<LogicalIds> = L<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[<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> + </list> + <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> +<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> +<pre> +% <input>erl +sct L0-1,3-2c0-3p0N0:L7,4,6-5c0-3p1N1</input> +1> <input>erlang:system_info(cpu_topology).</input> +[{node,[{processor,[{core,{logical,0}}, + {core,{logical,1}}, + {core,{logical,3}}, + {core,{logical,2}}]}]}, + {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> +<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_flag_cpu_topology">erlang:system_flag(cpu_topology, CpuTopology)</seealso>.</p> + </item> + </taglist> + </item> + <tag><c><![CDATA[+sss size]]></c></tag> + <item> + <marker id="sched_thread_stack_size"></marker> + <p>Suggested stack size, in kilowords, for scheduler threads. + Valid range is 4-8192 kilowords. The default stack size + is OS dependent.</p> + </item> + <tag><c><![CDATA[+T Level]]></c></tag> + <item> + <marker id="+T"></marker> + <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> + <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> + <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> + <tag>Input reductions</tag> + <item>The amount 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> + </item> + <tag><c><![CDATA[+v]]></c></tag> + <item> + <p>Verbose.</p> + </item> + <tag><c><![CDATA[+W w | i]]></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> + </item> + </taglist> + </section> + + <section> + <marker id="environment_variables"></marker> + <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> + </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> + </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> + </item> + <tag><c><![CDATA[ERL_AFLAGS]]></c></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><c><![CDATA[ERL_ZFLAGS]]></c>and <c><![CDATA[ERL_FLAGS]]></c></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> + </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> + </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 + 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> + </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> +</comref> + diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml new file mode 100644 index 0000000000..9a203289e9 --- /dev/null +++ b/erts/doc/src/erl_dist_protocol.xml @@ -0,0 +1,802 @@ +<?xml version="1.0" encoding="iso-8859-1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2007</year> + <year>2007</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. + + The Initial Developer of the Original Code is Ericsson AB. + </legalnotice> + + <title>Distribution Protocol</title> + <prepared></prepared> + <docno></docno> + <date>2007-09-21</date> + <rev>PA1</rev> + <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> + 1. Low level socket connection. + </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> + + <section> + <title>EPMD Protocol</title> + <p> + The requests served by the EPMD (Erlang Port Mapper Daemon) are + summarized in the figure below. + </p> + + <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> + + <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">LowestVersion</cell> + <cell align="center">HighestVersion</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>LowestVersion</c></tag> + <item> + The lowest distribution version that this node can handle. + See the next field for possible values. + </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>Nlen</c></tag> + <item> + The length of the <c>NodeName</c>. + </item> + <tag><c>NodeName</c></tag> + <item> + The NodeName as a string of length <c>Nlen</c>. + </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> + + <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> + + <section> + <title>Unregister a node from the EPMD</title> + <p> + A node unregister itself from the EPMD by simply closing the + TCP connection towards 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 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> + + <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> + + <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> + </table> + <p>Or</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 ~s at port ~p~n", [NodeName, Port]). + </code> + </section> + + + <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 ~s at port ~p, fd = ~p ~n", + [NodeName, Port, Fd]). + </code> + <p> + or + </p> + <code> + io:format("old/unused name ~s at port ~p, fd = ~p~n", + [NodeName, Port, Fd]). + </code> + + </section> + + <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> + 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>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> + + + <section> + <title>PORT_NOTOK_RESP ()</title> + <p> + EPMD closed the connection. + </p> + </section> +--> + + </section> + + <section> + <title>Handshake</title> + <p> + The handshake is discussed in detail in the internal documentation for + the kernel (Erlang) application. + </p> + </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> + + <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> + + <section> + <title>New Ctrlmessages for distrvsn = 2</title> + <p> + distrvsn 2 was never used. + </p> + </section> + + <section> + <title>New Ctrlmessages for distrvsn = 3 (OTP R5C)</title> + <p> + None, but the version number was increased anyway. + </p> + </section> + + <section> + <title>New Ctrlmessages for distrvsn = 4 (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> + + <c>FromPid</c> = monitoring process + <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> + 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) + </p> + </item> + + <tag><c>MONITOR_P_EXIT</c></tag> + <item> + <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 + </p> + </item> + </taglist> + </section> + </chapter> diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml new file mode 100644 index 0000000000..0b11f4bbcb --- /dev/null +++ b/erts/doc/src/erl_driver.xml @@ -0,0 +1,2465 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>2001</year><year>2009</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>erl_driver</title> + <prepared>Jakob Cederlund</prepared> + <responsible>Jakob Cederlund</responsible> + <docno>1</docno> + <approved></approved> + <checked></checked> + <date>2000-11-27</date> + <rev>PA1</rev> + <file>erl_driver.xml</file> + </header> + <lib>erl_driver</lib> + <libsummary>API functions for an Erlang driver</libsummary> + <description> + <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 + <seealso marker="erl_driver#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> + <note> + <p>Old drivers (compiled with an <c>erl_driver.h</c> from an + earlier erts version than 5.5.3) have to be recompiled + (but does not have to use the extended interface).</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> + <p>A driver is a library with a set of function that the emulator + calls, in response to Erlang functions and message + sending. There may be multiple instances of a driver, each + instance is connected to an Erlang port. Every port has a port + owner process. Communication with the port is normally done + through the port owner process.</p> + <p>Most of the functions takes the <c>port</c> handle as an + argument. This identifies the driver instance. Note 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> + <p>Some of the functions takes a parameter of type + <c>ErlDrvBinary</c>, a driver binary. It should be both + allocated and freed by the caller. Using a binary directly avoid + one extra copying of data.</p> + <p>Many of the output functions has 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 + 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> + <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 + 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 + level locking is used.</p> + <note> + <p>It is assumed that drivers does not access other drivers. If + drivers should access each other they have to 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 + 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 + 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> + </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. Function + 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 + different threads. This, however, is not a problem for any + functions in this API, since the emulator have control over + these threads.</p> + <note> + <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 + system with SMP support.</p> + </note> + </description> + + <section> + <title>FUNCTIONALITY</title> + <p>All functions that a driver needs to do with Erlang are + performed through driver API functions. There are functions + 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> + <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, + it is a byte stream. If the port owner process closes the + driver, and the queue is not empty, the driver will not be + 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> + </item> + <tag>Output functions</tag> + <item>With the output functions, the driver sends data back + 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 is faster, because that 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> + <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> + <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>Multi-threading</tag> + <item><marker id="multi_threading"></marker> + <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 return 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 exist 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> + </item> + <tag>Adding / remove drivers</tag> + <item>A driver can add and later remove drivers.</item> + <tag>Monitoring processes</tag> + <item>A driver can monitor a process that does not own a port.</item> + <tag>Version management</tag> + <item> + <marker id="version_management"></marker> + <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 use the minor version + of the driver to determine what features to use. + The runtime system will refuse 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.</p> + <p>The emulator tries to check that a driver that doesn't use the + extended driver interface isn't incompatible when loading it. + It can, however, not make sure that it isn't incompatible. Therefore, + when loading a driver that doesn't use the extended driver + interface, there is a risk that it will be loaded also when + the driver is incompatible. When the driver use the extended driver + interface, the emulator can verify that it isn't of an incompatible + driver version. You are therefore advised to use the extended driver + interface.</p> + </item> + </taglist> + </section> + + <section> + <title>DATA TYPES</title> + + <taglist> + <tag><marker id="ErlDrvSysInfo"/>ErlDrvSysInfo</tag> + <item> + <p/> + <code type="none"> +typedef struct ErlDrvSysInfo { + int driver_major_version; + int driver_minor_version; + char *erts_version; + char *otp_release; + int thread_support; + int smp_support; + int async_threads; + int scheduler_threads; +} 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 follow: + </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="erts: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="erts: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>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="erts: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="erts:erlang#system_info_schedulers">erlang:system_info(schedulers)</seealso>). + </item> + </taglist> + </item> + + <tag><marker id="ErlDrvBinary"/>ErlDrvBinary</tag> + <item> + <p/> + <code type="none"> +typedef struct ErlDrvBinary { + int orig_size; + char orig_bytes[]; +} 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 + <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> + </note> + <p>Some driver calls, such as <c>driver_enq_binary</c>, + increments the driver reference count, and others, such as + <c>driver_deq</c> decrements 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, + 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 + 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 of 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>From erts version 5.5 (OTP release R11B), orig_bytes is + guaranteed to be properly aligned for storage of an array of + doubles (usually 8-byte aligned).</p> + </item> + <tag>ErlDrvData</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 + most often casted to a specific pointer in the driver.</p> + </item> + <tag>SysIOVec</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 + <c>ErlIOVec</c>.</p> + </item> + <tag><marker id="ErlIOVec"/>ErlIOVec</tag> + <item> + <p/> + <code type="none"> +typedef struct ErlIOVec { + int vsize; + int size; + SysIOVec* iov; + >ErlDrvBinary** binv; +} 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 + <c>ErlIOVec</c>.</p> + </item> + + <tag>ErlDrvMonitor</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 + 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> + </item> + <tag><marker id="ErlDrvNowData"/>ErlDrvNowData</tag> + <item> + <p>The <c>ErlDrvNowData</c> structure holds a timestamp + consisting of three values measured from some arbitrary + point in the past. The three structure members are:</p> + <taglist> + <tag>megasecs</tag> + <item>The number of whole megaseconds elapsed since the arbitrary + point in time</item> + <tag>secs</tag> + <item>The number of whole seconds elapsed since the arbitrary + point in time</item> + <tag>microsecs</tag> + <item>The number of whole microseconds elapsed since the arbitrary + point in time</item> + </taglist> + </item> + <tag><marker id="ErlDrvPDL"/>ErlDrvPDL</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 + 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 want to use a port data lock, it has to + 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 have 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> + <p>A port data lock is reference counted, and when the reference + count reach 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, or canceled. Besides + this, it is the responsibility of the driver to ensure 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> + </item> + + <tag><marker id="ErlDrvTid"/>ErlDrvTid</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> + </item> + <tag><marker id="ErlDrvThreadOpts"/>ErlDrvThreadOpts</tag> + <item> + <p/> + <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> + <taglist> + <tag>suggested_stack_size</tag> + <item>A suggestion, in kilo-words, on how large stack to use. A value less + than zero 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> + </item> + + <tag><marker id="ErlDrvMutex"/>ErlDrvMutex</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> + </item> + <tag><marker id="ErlDrvCond"/>ErlDrvCond</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> + </item> + <tag><marker id="ErlDrvRWLock"/>ErlDrvRWLock</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> + </item> + <tag><marker id="ErlDrvTSDKey"/>ErlDrvTSDKey</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> + </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> + <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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_output(ErlDrvPort port, char *buf, int len)</nametext></name> + <fsummary>Send data from driver to port owner</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 runs 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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_output2(ErlDrvPort port, char *hbuf, int hlen, char *buf, int len)</nametext></name> + <fsummary>Send data and binary data to port owner</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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_output_binary(ErlDrvPort port, char *hbuf, int hlen, ErlDrvBinary* bin, int offset, int len)</nametext></name> + <fsummary>Send data from a driver binary to port owner</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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_outputv(ErlDrvPort port, char* hbuf, int hlen, ErlIOVec *ev, int skip)</nametext></name> + <fsummary>Send vectorized data to port owner</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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_vec_to_buf(ErlIOVec *ev, char *buf, int len)</nametext></name> + <fsummary>Collect data segments into a buffer</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> + </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> + <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#emulator">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 i 0 (-1 only when the <c>timeout</c> driver + function is <c>NULL</c>).</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> + </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> + <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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_get_now(ErlDrvNowData *now)</nametext></name> + <fsummary>Read a system timestamp</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 it's fields. </p> + <p>The return value is 0 unless the <c>now</c> pointer is not + valid, in which case it is < 0. </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> + <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 restriction on the event object. + Refer to the Win32 SDK documentation.</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 bitwise-or combination of + <c>ERL_DRV_READ</c>, <c>ERL_DRV_WRITE</c> and <c>ERL_DRV_USE</c>. + The first two specifies 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) does not differ 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> + </desc> + </func> + <func> + <name><ret>void *</ret><nametext>driver_alloc(size_t size)</nametext></name> + <fsummary>Allocate memory</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> + </desc> + </func> + <func> + <name><ret>void *</ret><nametext>driver_realloc(void *ptr, size_t size)</nametext></name> + <fsummary>Resize an allocated memory block</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> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>driver_free(void *ptr)</nametext></name> + <fsummary>Free an allocated memory block</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> + </desc> + </func> + <func> + <name><ret>ErlDrvBinary*</ret><nametext>driver_alloc_binary(int size)</nametext></name> + <fsummary>Allocate a driver binary</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> + </desc> + </func> + <func> + <name><ret>ErlDrvBinary*</ret><nametext>driver_realloc_binary(ErlDrvBinary *bin, int size)</nametext></name> + <fsummary>Resize a driver binary</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> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>driver_free_binary(ErlDrvBinary *bin)</nametext></name> + <fsummary>Free a driver binary</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> + </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> + <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> + </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 only thread-safe when the emulator with SMP + support is used.</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> + <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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_enq(ErlDrvPort port, char* buf, int len)</nametext></name> + <fsummary>Enqueue data in the driver queue</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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_pushq(ErlDrvPort port, char* buf, int len)</nametext></name> + <fsummary>Push data at the head of the driver queue</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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_deq(ErlDrvPort port, int size)</nametext></name> + <fsummary>Dequeue data from the head of the driver queue</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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_sizeq(ErlDrvPort port)</nametext></name> + <fsummary>Return the size of the driver queue</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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, int offset, int len)</nametext></name> + <fsummary>Enqueue binary in the driver queue</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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, int offset, int len)</nametext></name> + <fsummary>Push binary at the head of the driver queue</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> + </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> + <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 the only way to get data + out of the queue.</p> + <p>Nothing is remove 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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_enqv(ErlDrvPort port, ErlIOVec *ev, int skip)</nametext></name> + <fsummary>Enqueue vector in the driver queue</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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_pushqv(ErlDrvPort port, ErlIOVec *ev, int skip)</nametext></name> + <fsummary>Push vector at the head of the driver queue</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> + </desc> + </func> + <func> + <name><ret>ErlDrvPDL</ret><nametext>driver_pdl_create(ErlDrvPort port)</nametext></name> + <fsummary>Create a port data lock</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> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>driver_pdl_lock(ErlDrvPDL pdl)</nametext></name> + <fsummary>Lock 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> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>driver_pdl_unlock(ErlDrvPDL pdl)</nametext></name> + <fsummary>Unlock port data lock</fsummary> + <desc> + <marker id="driver_pdl_unlock"></marker> + <p>This function unlocks 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_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 + 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> + <fsummary></fsummary> + <desc> + <marker id="driver_pdl_inc_refc"></marker> + <p>This function 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> + <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> + <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> + <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> + </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> + <desc> + <marker id="driver_demonitor_process"></marker> + <p>This function cancels an monitor created earlier. </p> + <p>The function returns 0 if a monitor was removed and > 0 + if the monitor did no longer exist.</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> + <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> + </desc> + </func> + <func> + <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_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> + </desc> + </func> + <func> + <name><ret>void</ret><nametext>add_driver_entry(ErlDrvEntry *de)</nametext></name> + <fsummary>Add a driver entry</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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>remove_driver_entry(ErlDrvEntry *de)</nametext></name> + <fsummary>Remove a driver entry</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> + </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> + <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> + </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 resets the busy status of the port. If + <c>on</c> is 1, the port is set to busy, if it's 0 the port + is set to not busy.</p> + <p>When the port is busy, sending to it with <c>Port ! Data</c> + or <c>port_command/2</c>, will block the port owner process, + until the port is signaled as not busy.</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#erlang:port_command/3">port_command(Port, Data, [force])</seealso> + even though the driver has signaled that it is busy. + </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> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_failure_eof(ErlDrvPort port)</nametext></name> + <fsummary>Fail with EOF</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 close and an + <c>'EXIT'</c> message is sent to the port owner process.</p> + <p>The return value is 0.</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> + <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. Normal errors is more + appropriate to handle with sending error codes with + <c>driver_output</c>.</p> + <p>The return value is 0.</p> + </desc> + </func> + <func> + <name><ret>ErlDrvTermData</ret><nametext>driver_connected(ErlDrvPort port)</nametext></name> + <fsummary>Return the port owner process</fsummary> + <desc> + <marker id="driver_connected"></marker> + <p>This function returns the port owner process.</p> + </desc> + </func> + <func> + <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>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 return 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> + </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> + <desc> + <marker id="driver_output_term"></marker> + <p>This functions sends data in the special driver term + format. 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.</p> + <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.</p> + <p>Tuple 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.</p> + <p>A tuple must be specified with the number of elements. (The + elements precedes 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>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 + </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(port), + ERL_DRV_INT, 100, + ERL_DRV_BINARY, bin, 50, 0, + ERL_DRV_LIST, 2, + ERL_DRV_TUPLE, 3, + }; + driver_output_term(port, spec, sizeof(spec) / sizeof(spec[0])); + ]]> + </code> + <p>Where <c>bin</c> is a driver binary of length at least 50 + and <c>port</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 + }; + driver_output_term(port, 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, + }; + driver_output_term(port, 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="erts: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, + }; + driver_output_term(port, spec, sizeof(spec) / sizeof(spec[0])); + ]]></code> + <p>If you want to pass a binary and doesn'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>Note 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>ErlDrvTermData</ret><nametext>driver_mk_atom(char* string)</nametext></name> + <fsummary>Make an atom from a name</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> + </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> + <desc> + <marker id="driver_mk_port"></marker> + <p>This function converts a port handle to the erlang term + format, usable in the <c>driver_output_send</c> function.</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> + <desc> + <marker id="driver_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> + <p>The parameters <c>term</c> and <c>n</c> does the same thing + as in <seealso marker="#driver_output_term">driver_output_term</seealso>.</p> + <p>This function is only thread-safe when the emulator with SMP + support is used.</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> + <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>Erlang is by default started without an async thread pool. The + number of async threads that the runtime system should use + is specified by 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 = (unsigned int) 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 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>, because it's + called if <c>driver_async_cancel</c> is called.</p> + <p>When the async operation is done, <seealso marker="driver_entry#ready_async">ready_async</seealso> driver + entry function is called. If <c>async_ready</c> is null in + the driver entry, the <c>async_free</c> function is called + instead.</p> + <p>The return value is a handle to the asynchronous task, which + can be used as argument to <c>driver_async_cancel</c>.</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> + </note> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_async_cancel(long id)</nametext></name> + <fsummary>Cancel an asynchronous call</fsummary> + <desc> + <marker id="driver_async_cancel"></marker> + <p>This function cancels an asynchronous operation, by removing + it from the queue. Only functions in the queue can be + cancelled; if a function is executing, it's too late to + cancel it. The <c>async_free</c> function is also called.</p> + <p>The return value is 1 if the operation was removed from the + queue, otherwise 0.</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> + <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> + </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> + <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> + <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="erts:erlang#open_port/2">erlang:open_port/2</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, 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> + </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>Arguments:</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> + </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> + </desc> + </func> + + <func> + <name><ret>ErlDrvThreadOpts *</ret><nametext>erl_drv_thread_opts_create(char *name)</nametext></name> + <fsummary>Create thread options</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> + <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> + <desc> + <marker id="erl_drv_thread_opts_destroy"></marker> + <p>Arguments:</p> + <taglist> + <tag><c>opts</c></tag> + <item>A pointer to thread options to destroy.</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>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> + <desc> + <marker id="erl_drv_thread_exit"></marker> + <p>Arguments:</p> + <taglist> + <tag><c>exit_value</c></tag> + <item>A pointer to an exit value or <c>NULL</c>.</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>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> + <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> + <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> + <desc> + <marker id="erl_drv_thread_self"></marker> + <p>This function returns the thread identifier of the + calling thread. + </p> + <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> + <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 + expected result. + </p></note> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + </desc> + </func> + + <func> + <name><ret>void</ret><nametext>erl_drv_cond_signal(ErlDrvCond *cnd)</nametext></name> + <fsummary>Signal on a condition variable</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> + <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> + <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 + broadcasted on, <em>all</em> of them will be woken. + </p> + <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> + <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 broadcasted 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> + <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> + <desc> + <marker id="erl_drv_rwlock_create"></marker> + <p>Arguments:</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> + </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>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> + <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> + <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> + <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> + <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> + <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> + </desc> + </func> + + <func> + <name><ret>void</ret><nametext>erl_drv_rwlock_runlock(ErlDrvRWLock *rwlck)</nametext></name> + <fsummary>Read unlock an rwlock</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> + <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> + <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> + <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> + <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> + <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> + <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> + <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> + <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>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> + <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>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> + <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>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> + <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> + </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> + <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> + </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> + <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> + </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="erts:erlang">erlang(3)</seealso></p> + <p>An Alternative Distribution Driver (ERTS User's + Guide Ch. 3)</p> + </section> +</cref> + diff --git a/erts/doc/src/erl_ext_dist.xml b/erts/doc/src/erl_ext_dist.xml new file mode 100644 index 0000000000..c2d58d1ef1 --- /dev/null +++ b/erts/doc/src/erl_ext_dist.xml @@ -0,0 +1,1014 @@ +<?xml version="1.0" encoding="iso-8859-1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2007</year> + <year>2007</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. + + The Initial Developer of the Original Code is Ericsson AB. + </legalnotice> + + <title>External Term Format</title> + <prepared>Kenneth</prepared> + <docno></docno> + <date>2007-09-21</date> + <rev>PA1</rev> + <file>erl_ext_dist.xml</file> + </header> + + <section> + <title>Introduction</title> + <p> + 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 + within some application. + All Erlang terms has an external representation and the interpretation + of the different terms are 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 + <seealso marker="erts:erlang#binary_to_term/1"> + binary_to_term/1 + </seealso> + is used. + </p> + <p> + 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: + </p> + <table align="left"> + <row> + <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> + <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> + </note> + <p> + A compressed term looks like this: + </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> + </row> + <row> + <cell align="center">131</cell> + <cell align="center">80</cell> + <cell align="center">UncompressedSize</cell> + <cell align="center">Zlib-compressedData</cell> + </row> + <tcaption></tcaption></table> + <p> + 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: + </p> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">Uncompressed Size</cell> + </row> + <row> + <cell align="center">Tag</cell> + <cell align="center">Data</cell> + </row> + <tcaption></tcaption></table> + </section> + + <section> + <marker id="distribution_header"/> + <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 + earlier than 5.7.2 can still communicate with new nodes, + but no distribution header and no atom cache will be used.</p> + <p> + The distribution header currently only contains an atom cache + reference section, but could in the future contain more + information. The distribution header precedes one or more Erlang + terms on the external format. For more information see the + documentation of the + <seealso marker="erl_dist_protocol#connected_nodes">protocol between + connected nodes</seealso> in the + <seealso marker="erl_dist_protocol">distribution protocol</seealso> + documentation. + </p> + <p> + <seealso marker="#ATOM_CACHE_REF">ATOM_CACHE_REF</seealso> + entries with corresponding <c>AtomCacheReferenceIndex</c> in terms + encoded on the external format following a distribution header refers + to the atom cache references made in the distribution header. The range + is 0 <= <c>AtomCacheReferenceIndex</c> < 255, i.e., at most 255 + different atom cache references from the following terms can be made. + </p> + <p> + The distribution header format is: + </p> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">NumberOfAtomCacheRefs/2+1 | 0</cell> + <cell align="center">N | 0</cell> + </row> + <row> + <cell align="center"><c>131</c></cell> + <cell align="center"><c>68</c></cell> + <cell align="center"><c>NumberOfAtomCacheRefs</c></cell> + <cell align="center"><c>Flags</c></cell> + <cell align="center"><c>AtomCacheRefs</c></cell> + </row> + <tcaption></tcaption></table> + <p> + <c>Flags</c> consists 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 + a half byte flag field. Flags corresponding to a specific + <c>AtomCacheReferenceIndex</c>, are located in flag byte number + <c>AtomCacheReferenceIndex/2</c>. Flag byte 0 is the first byte + after the <c>NumberOfAtomCacheRefs</c> byte. Flags for an even + <c>AtomCacheReferenceIndex</c> are located in the least significant + half byte and flags for an odd <c>AtomCacheReferenceIndex</c> are + located in the most significant half byte. + </p> + <p> + The flag field of an atom cache reference has the following + format: + </p> + <table align="left"> + <row> + <cell align="center">1 bit</cell> + <cell align="center">3 bits</cell> + </row> + <row> + <cell align="center"><c>NewCacheEntryFlag</c></cell> + <cell align="center"><c>SegmentIndex</c></cell> + </row> + <tcaption></tcaption></table> + <p> + The most significant bit is the <c>NewCacheEntryFlag</c>. If set, + the corresponding cache reference is new. The three least + significant bits are the <c>SegmentIndex</c> of the corresponding + atom cache entry. An atom cache consists of 8 segments each of size + 256, i.e., 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: + </p> + <table align="left"> + <row> + <cell align="center">3 bits</cell> + <cell align="center">1 bit</cell> + </row> + <row> + <cell align="center"><c>CurrentlyUnused</c></cell> + <cell align="center"><c>LongAtoms</c></cell> + </row> + <tcaption></tcaption></table> + <p> + The least significant bit in that half byte is the <c>LongAtoms</c> + flag. If it is set, 2 bytes are used for atom lengths instead of + 1 byte in the distribution header. However, the current emulator + cannot handle long atoms, so it will currently always be 0. + </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 + 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: + </p> + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">1 | 2</cell> + <cell align="center">Length</cell> + </row> + <row> + <cell align="center"><c>InternalSegmentIndex</c></cell> + <cell align="center"><c>Length</c></cell> + <cell align="center"><c>AtomText</c></cell> + </row> + <tcaption></tcaption></table> + <p> + <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c> + completely identify the location of an atom cache entry in the + atom cache. <c>Length</c> is number of one byte characters that + the atom text consists of. Length is a two byte big endian integer + if the <c>LongAtoms</c> flag has been set, otherwise a one byte + integer. Subsequent <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> with the same <c>SegmentIndex</c> + and <c>InternalSegmentIndex</c> appear. + </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: + </p> + <table align="left"> + <row> + <cell align="center">1</cell> + </row> + <row> + <cell align="center"><c>InternalSegmentIndex</c></cell> + </row> + <tcaption></tcaption></table> + <p> + <c>InternalSegmentIndex</c> together with the <c>SegmentIndex</c> + identify the location of the atom cache entry in the atom cache. + The atom corresponding to this <c>CachedAtomRef</c> is the + latest <c>NewAtomCacheRef</c> preceding this <c>CachedAtomRef</c> + in another previously passed distribution header. + </p> + </section> + + <section> + <marker id="ATOM_CACHE_REF"/> + <title>ATOM_CACHE_REF</title> + + <table align="left"> + <row> + <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> + </row> + <tcaption></tcaption></table> + <p> + Refers to the atom with <c>AtomCacheReferenceIndex</c> in the + <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> + </row> + <row> + <cell align="center">97</cell> + <cell align="center">Int</cell> + </row> + <tcaption></tcaption></table> + <p> + 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> + </row> + <row> + <cell align="center">98</cell> + <cell align="center">Int</cell> + </row> + <tcaption></tcaption></table> + <p> + Signed 32 bit integer in big-endian format (i.e. MSB first) + </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> + </row> + <row> + <cell align="center">99</cell> + <cell align="center">Float String</cell> + </row> + <tcaption></tcaption></table> + <p> + 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". + </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>. + </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 characters that forms the + <c>AtomName</c>. + Note: 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> + <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. + </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>. + </p> + </section> + + <section> + <marker id="PORT_EXT"/> + <title>PORT_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>102</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> + <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. + Port operations are not allowed across node boundaries. + The <c>Creation</c> works just like in + <seealso marker="#REFERENCE_EXT">REFERENCE_EXT</seealso>. + </p> + </section> + + <section> + <marker id="PID_EXT"/> + <title>PID_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">N</cell> + <cell align="center">4</cell> + <cell align="center">4</cell> + <cell align="center">1</cell> + </row> + <row> + <cell align="center"><c>103</c></cell> + <cell align="center"><c>Node</c></cell> + <cell align="center"><c>ID</c></cell> + <cell align="center"><c>Serial</c></cell> + <cell align="center"><c>Creation</c></cell> + </row> + <tcaption></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. + </p> + + </section> + + <section> + <marker id="SMALL_TUPLE_EXT"/> + <title>SMALL_TUPLE_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">1</cell> + <cell align="center">N</cell> + </row> + <row> + <cell align="center">104</cell> + <cell align="center">Arity</cell> + <cell align="center">Elements</cell> + </row> + <tcaption></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. + </p> + </section> + + <section> + <marker id="LARGE_TUPLE_EXT"/> + <title>LARGE_TUPLE_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">4</cell> + <cell align="center">N</cell> + </row> + <row> + <cell align="center">105</cell> + <cell align="center">Arity</cell> + <cell align="center">Elements</cell> + </row> + <tcaption></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. + </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> + </row> + <tcaption></tcaption></table> + <p> + The representation for an empty list, i.e. 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> + <cell align="center">2</cell> + <cell align="center">Len</cell> + </row> + <row> + <cell align="center">107</cell> + <cell align="center">Length</cell> + <cell align="center">Characters</cell> + </row> + <tcaption></tcaption></table> + <p> + String does NOT 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>. + </p> + + </section> + + <section> + <marker id="LIST_EXT"/> + <title>LIST_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">4</cell> + <cell align="center"> </cell> + <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> + </row> + <tcaption></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>). + </p> + </section> + + <section> + <marker id="BINARY_EXT"/> + <title>BINARY_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">4</cell> + <cell align="center">Len</cell> + </row> + <row> + <cell align="center">109</cell> + <cell align="center">Len</cell> + <cell align="center">Data</cell> + </row> + <tcaption></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>, + or as input from binary ports. + 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> + <cell align="center">1</cell> + <cell align="center">1</cell> + <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> + </row> + <tcaption></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)) + </p> + </section> + + <section> + <marker id="LARGE_BIG_EXT"/> + <title>LARGE_BIG_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">4</cell> + <cell align="center">1</cell> + <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> + </row> + <tcaption></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. + </p> + + </section> + + <section> + <marker id="NEW_REFERENCE_EXT"/> + <title>NEW_REFERENCE_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">2</cell> + <cell align="center">N</cell> + <cell align="center">1</cell> + <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> + </row> + <tcaption></tcaption></table> + <p> + Node and Creation are as in + <seealso marker="#REFERENCE_EXT">REFERENCE_EXT</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. + </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. + </p> + <p> + NEW_REFERENCE_EXT was introduced with distribution version 4. + In version 4, <c>N'</c> should be at most 12. + </p> + <p> + See <seealso marker="#REFERENCE_EXT">REFERENCE_EXT</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 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 a small atom distribution flag exchanged in the distribution + handshake. + </p> + </section> + + <section> + <marker id="FUN_EXT"/> + <title>FUN_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">4</cell> + <cell align="center">N1</cell> + <cell align="center">N2</cell> + <cell align="center">N3</cell> + <cell align="center">N4</cell> + <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> + </row> + <tcaption></tcaption></table> + <taglist> + <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. + </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. + </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. + </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. + </item> + <tag><c>Free vars</c></tag> + <item> + is <c>NumFree</c> number of terms, each one encoded according + to its type. + </item> + </taglist> + </section> + + <section> + <marker id="NEW_FUN_EXT"/> + <title>NEW_FUN_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">4</cell> + <cell align="center">1</cell> + <cell align="center">16</cell> + <cell align="center">4</cell> + <cell align="center">4</cell> + <cell align="center">N1</cell> + <cell align="center">N2</cell> + <cell align="center">N3</cell> + <cell align="center">N4</cell> + <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> + </row> + <tcaption></tcaption></table> + <p> + This is the new encoding of internal funs: <c>fun F/A</c> and + <c>fun(Arg1,..) -> ... end</c>. + </p> + <taglist> + <tag><c>Size</c></tag> + <item> + is the total number of bytes, including the <c>Size</c> field. + </item> + <tag><c>Arity</c></tag> + <item> + is the arity of the function implementing the fun. + </item> + <tag><c>Uniq</c></tag> + <item> + is the 16 bytes MD5 of the significant parts of the Beam file. + </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. + </item> + <tag><c>NumFree</c></tag> + <item> + is the number of free variables. + </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. + </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. + </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. + </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. + </item> + + <tag><c>Free vars</c></tag> + <item> + is <c>NumFree</c> number of terms, each one encoded according + to its type. + </item> + </taglist> + </section> + + <section> + <marker id="EXPORT_EXT"/> + <title>EXPORT_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">N1</cell> + <cell align="center">N2</cell> + <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> + </row> + <tcaption></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>). + </p> + <p> + <c>Arity</c> is an integer encoded using + <seealso marker="#SMALL_INTEGER_EXT">SMALL_INTEGER_EXT</seealso>. + </p> + + </section> + + <section> + <marker id="BIT_BINARY_EXT"/> + <title>BIT_BINARY_EXT</title> + + <table align="left"> + <row> + <cell align="center">1</cell> + <cell align="center">4</cell> + <cell align="center">1</cell> + <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> + </row> + <tcaption></tcaption></table> + <p> + This term represents a bitstring whose length in bits is not a + multiple of 8 (created using the bit syntax in R12B and later). + The <c>Len</c> field is an unsigned 4 byte integer (big endian). + The <c>Bits</c> field is the number of bits that are used + in the last byte in the data field, + counting from the most significant bit towards 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> + </row> + <tcaption></tcaption></table> + <p> + A float is stored as 8 bytes in big-endian IEEE format. + </p> + <p> + This term is used in minor version 1 of the external format. + </p> + </section> + + + </chapter> + + diff --git a/erts/doc/src/erl_ext_fig.gif b/erts/doc/src/erl_ext_fig.gif Binary files differnew file mode 100755 index 0000000000..14d6bbc871 --- /dev/null +++ b/erts/doc/src/erl_ext_fig.gif diff --git a/erts/doc/src/erl_ext_fig.ps b/erts/doc/src/erl_ext_fig.ps new file mode 100644 index 0000000000..2501dc3c05 --- /dev/null +++ b/erts/doc/src/erl_ext_fig.ps @@ -0,0 +1,153 @@ +%!PS-Adobe-3.0 EPSF-2.0 +%%BoundingBox: 0 0 600 520 +%%Creator: mscgen 1 +%%EndComments +0.70 0.70 scale +0 0 moveto +0 520 lineto +600 520 lineto +600 0 lineto +closepath +clip +%PageTrailer +%Page: 1 1 +/Helvetica findfont +10 scalefont +setfont +0 520 translate +/mtrx matrix def +/ellipse + { /endangle exch def + /startangle exch def + /ydia exch def + /xdia exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y translate + xdia 2 div ydia 2 div scale + 0 0 1 startangle endangle arc + savematrix setmatrix +} def +150 -12 moveto (Client (or Node)) dup stringwidth pop 2 div neg 0 rmoveto show +450 -12 moveto (EPMD) dup stringwidth pop 2 div neg 0 rmoveto show +newpath 150 -20 moveto 150 -45 lineto stroke +newpath 450 -20 moveto 450 -45 lineto stroke +newpath 150 -32 moveto 450 -32 lineto stroke +newpath 450 -32 moveto 440 -38 lineto 440 -26 lineto closepath fill +270 -30 moveto (ALIVE2_REQ) show +newpath 150 -45 moveto 150 -70 lineto stroke +newpath 450 -45 moveto 450 -70 lineto stroke +[2] 0 setdash +newpath 450 -57 moveto 150 -57 lineto stroke +[] 0 setdash +newpath 150 -57 moveto 160 -63 lineto 160 -51 lineto closepath fill +267 -55 moveto (ALIVE2_RESP) show +[2] 0 setdash +newpath 150 -70 moveto 150 -95 lineto stroke +[] 0 setdash +[2] 0 setdash +newpath 450 -70 moveto 450 -95 lineto stroke +[] 0 setdash +newpath 150 -95 moveto 150 -120 lineto stroke +newpath 450 -95 moveto 450 -120 lineto stroke +newpath 150 -107 moveto 450 -107 lineto stroke +newpath 450 -107 moveto 440 -113 lineto 440 -101 lineto closepath fill +253 -105 moveto (ALIVE_CLOSE_REQ) show +[2] 0 setdash +newpath 150 -120 moveto 150 -145 lineto stroke +[] 0 setdash +[2] 0 setdash +newpath 450 -120 moveto 450 -145 lineto stroke +[] 0 setdash +newpath 150 -145 moveto 150 -170 lineto stroke +newpath 450 -145 moveto 450 -170 lineto stroke +newpath 150 -157 moveto 450 -157 lineto stroke +newpath 450 -157 moveto 440 -163 lineto 440 -151 lineto closepath fill +248 -155 moveto (PORT_PLEASE2_REQ) show +newpath 150 -170 moveto 150 -195 lineto stroke +newpath 450 -170 moveto 450 -195 lineto stroke +[2] 0 setdash +newpath 450 -182 moveto 150 -182 lineto stroke +[] 0 setdash +newpath 150 -182 moveto 160 -188 lineto 160 -176 lineto closepath fill +267 -180 moveto (PORT2_RESP) show +[2] 0 setdash +newpath 150 -195 moveto 150 -220 lineto stroke +[] 0 setdash +[2] 0 setdash +newpath 450 -195 moveto 450 -220 lineto stroke +[] 0 setdash +newpath 150 -220 moveto 150 -245 lineto stroke +newpath 450 -220 moveto 450 -245 lineto stroke +newpath 150 -232 moveto 450 -232 lineto stroke +newpath 450 -232 moveto 440 -238 lineto 440 -226 lineto closepath fill +269 -230 moveto (NAMES_REQ) show +newpath 150 -245 moveto 150 -270 lineto stroke +newpath 450 -245 moveto 450 -270 lineto stroke +[2] 0 setdash +newpath 450 -257 moveto 150 -257 lineto stroke +[] 0 setdash +newpath 150 -257 moveto 160 -263 lineto 160 -251 lineto closepath fill +266 -255 moveto (NAMES_RESP) show +[2] 0 setdash +newpath 150 -270 moveto 150 -295 lineto stroke +[] 0 setdash +[2] 0 setdash +newpath 450 -270 moveto 450 -295 lineto stroke +[] 0 setdash +newpath 150 -295 moveto 150 -320 lineto stroke +newpath 450 -295 moveto 450 -320 lineto stroke +newpath 150 -307 moveto 450 -307 lineto stroke +newpath 450 -307 moveto 440 -313 lineto 440 -301 lineto closepath fill +272 -305 moveto (DUMP_REQ) show +newpath 150 -320 moveto 150 -345 lineto stroke +newpath 450 -320 moveto 450 -345 lineto stroke +[2] 0 setdash +newpath 450 -332 moveto 150 -332 lineto stroke +[] 0 setdash +newpath 150 -332 moveto 160 -338 lineto 160 -326 lineto closepath fill +269 -330 moveto (DUMP_RESP) show +[2] 0 setdash +newpath 150 -345 moveto 150 -370 lineto stroke +[] 0 setdash +[2] 0 setdash +newpath 450 -345 moveto 450 -370 lineto stroke +[] 0 setdash +newpath 150 -370 moveto 150 -395 lineto stroke +newpath 450 -370 moveto 450 -395 lineto stroke +newpath 150 -382 moveto 450 -382 lineto stroke +newpath 450 -382 moveto 440 -388 lineto 440 -376 lineto closepath fill +277 -380 moveto (KILL_REQ) show +newpath 150 -395 moveto 150 -420 lineto stroke +newpath 450 -395 moveto 450 -420 lineto stroke +[2] 0 setdash +newpath 450 -407 moveto 150 -407 lineto stroke +[] 0 setdash +newpath 150 -407 moveto 160 -413 lineto 160 -401 lineto closepath fill +274 -405 moveto (KILL_RESP) show +[2] 0 setdash +newpath 150 -420 moveto 150 -445 lineto stroke +[] 0 setdash +[2] 0 setdash +newpath 450 -420 moveto 450 -445 lineto stroke +[] 0 setdash +newpath 150 -445 moveto 150 -470 lineto stroke +newpath 450 -445 moveto 450 -470 lineto stroke +newpath 150 -457 moveto 450 -457 lineto stroke +newpath 450 -457 moveto 440 -463 lineto 440 -451 lineto closepath fill +273 -455 moveto (STOP_REQ) show +newpath 150 -470 moveto 150 -495 lineto stroke +newpath 450 -470 moveto 450 -495 lineto stroke +[2] 0 setdash +newpath 450 -482 moveto 150 -482 lineto stroke +[] 0 setdash +newpath 150 -482 moveto 160 -488 lineto 160 -476 lineto closepath fill +260 -480 moveto (STOP_OK_RESP) show +newpath 150 -495 moveto 150 -520 lineto stroke +newpath 450 -495 moveto 450 -520 lineto stroke +[2] 0 setdash +newpath 450 -507 moveto 150 -507 lineto stroke +[] 0 setdash +newpath 150 -507 moveto 160 -513 lineto 160 -501 lineto closepath fill +250 -505 moveto (STOP_NOTOK_RESP) show diff --git a/erts/doc/src/erl_fix_alloc.fig b/erts/doc/src/erl_fix_alloc.fig new file mode 100644 index 0000000000..57db965a74 --- /dev/null +++ b/erts/doc/src/erl_fix_alloc.fig @@ -0,0 +1,104 @@ +#FIG 3.1 +Landscape +Center +Inches +1200 2 +6 300 1200 2850 3600 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 4 + 750 3600 750 1200 2325 1200 2325 3600 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 750 1500 2325 1500 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 750 1800 2325 1800 +2 1 0 2 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 375 2100 2775 2100 +4 0 -1 0 0 0 12 0.0000 4 180 1275 900 2025 allocated_blocks\001 +4 0 -1 0 0 0 12 0.0000 4 180 630 1200 1725 free_list\001 +4 0 -1 0 0 0 12 0.0000 4 180 735 1200 1425 item_size\001 +-6 +6 3525 1200 5025 1800 +6 3525 1200 5025 1800 +2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 + 3525 1200 5025 1200 5025 1800 3525 1800 3525 1200 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 3525 1500 5025 1500 +-6 +4 0 -1 0 0 0 12 0.0000 4 105 330 4050 1425 next\001 +4 0 -1 0 0 0 12 0.0000 4 135 405 4050 1725 block\001 +-6 +6 5850 1200 7350 1800 +6 5850 1200 7350 1800 +2 2 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 5 + 5850 1200 7350 1200 7350 1800 5850 1800 5850 1200 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 0 0 2 + 5850 1500 7350 1500 +-6 +4 0 -1 0 0 0 12 0.0000 4 105 330 6375 1425 next\001 +4 0 -1 0 0 0 12 0.0000 4 135 405 6375 1725 block\001 +-6 +2 1 1 2 -1 7 0 0 -1 6.000 0 0 7 0 0 2 + 3450 5700 5400 5700 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 7 0 0 4 + 3600 8000 3600 3450 5175 3450 5175 8000 +2 1 1 2 -1 7 0 0 -1 6.000 0 0 -1 0 0 2 + 3525 6900 5325 6900 +2 2 1 0 -1 7 0 0 42 2.000 0 0 -1 0 0 5 + 3675 3525 5100 3525 5100 4425 3675 4425 3675 3525 +2 2 1 0 -1 7 0 0 42 2.000 0 0 -1 0 0 5 + 3675 5775 5100 5775 5100 6825 3675 6825 3675 5775 +2 1 2 1 -1 7 0 0 -1 3.000 0 0 -1 0 0 2 + 3600 4725 5250 4725 +2 1 2 1 -1 7 0 0 -1 3.000 0 0 -1 0 0 2 + 3600 4950 5175 4950 +2 2 2 0 -1 7 0 0 42 1.500 0 0 -1 0 0 5 + 6375 3750 6675 3750 6675 4050 6375 4050 6375 3750 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 4275 1800 4275 3400 +2 1 1 2 -1 7 0 0 -1 6.000 0 0 -1 0 0 2 + 3450 4500 5325 4500 +2 1 0 1 -1 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 6600 1800 6600 2925 +2 1 0 2 -1 7 0 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 240.00 + 450 600 750 1125 +3 0 0 1 -1 7 0 0 -1 0.000 0 1 0 3 + 1 1 1.00 60.00 120.00 + 4875 1350 5400 1350 5775 1200 +3 0 0 1 -1 7 0 0 -1 0.000 0 1 0 3 + 1 1 1.00 60.00 120.00 + 7125 1350 7650 1350 8025 1200 +3 2 0 1 -1 7 0 0 -1 0.000 0 1 0 9 + 1 1 1.00 60.00 120.00 + 2175 1650 2475 1650 2625 1725 2775 1875 2775 2025 2775 4275 + 2850 4350 3000 4425 3450 4500 + 0.00 0.00 2346.89 1637.46 2421.89 1637.46 2514.58 1659.34 + 2593.04 1701.97 2665.43 1754.14 2753.11 1822.15 2790.48 1912.37 + 2775.00 1990.83 2775.01 2537.57 2542.79 3714.42 2785.95 4301.43 + 2829.79 4335.43 2881.96 4373.03 2962.69 4412.87 3076.12 4449.75 + 3188.62 4468.50 0.00 0.00 +3 2 0 1 -1 7 0 0 -1 0.000 0 1 0 8 + 1 1 1.00 60.00 120.00 + 5100 4575 5400 4575 5625 4725 5700 4950 5700 6675 5625 6825 + 5475 6900 5175 6975 + 0.00 0.00 5270.86 4558.61 5345.86 4558.61 5465.07 4594.70 + 5582.72 4669.65 5662.08 4773.55 5691.07 4895.01 5764.92 5349.99 + 5796.11 6267.84 5690.66 6714.58 5655.36 6794.64 5594.64 6855.36 + 5511.35 6886.55 5424.73 6918.60 5349.73 6937.35 0.00 0.00 +3 2 0 1 -1 7 0 0 -1 0.000 0 1 0 8 + 1 1 1.00 60.00 120.00 + 2250 1950 2475 1950 2625 1875 2775 1725 2925 1425 3000 1350 + 3150 1275 3450 1200 + 0.00 0.00 2378.92 1959.40 2435.17 1959.40 2514.58 1940.66 + 2593.04 1898.04 2665.43 1845.86 2745.86 1765.43 2821.07 1661.08 + 2878.93 1488.92 2939.57 1404.79 2979.79 1364.57 3031.96 1326.96 + 3113.65 1288.45 3200.27 1256.40 3275.27 1237.65 0.00 0.00 +4 0 -1 0 0 0 12 0.0000 4 180 720 3975 4650 next_free\001 +4 0 -1 0 0 0 12 0.0000 4 180 450 4050 4875 magic\001 +4 0 -1 0 0 2 14 0.0000 4 195 1860 6825 3975 = allocated memory\001 +4 0 -1 0 0 18 12 0.0000 4 135 1305 3675 1125 AllocatedBlock\001 +4 0 -1 0 0 18 12 0.0000 4 135 660 1575 1125 FixItem\001 +4 0 -1 0 0 18 12 0.0000 4 135 1020 2400 4650 FreeHeader\001 +4 0 -1 0 0 2 12 4.7124 4 180 765 5250 3600 item_size\001 +4 0 -1 0 0 2 18 0.0000 4 255 1080 300 525 fix_array\001 diff --git a/erts/doc/src/erl_fix_alloc.gif b/erts/doc/src/erl_fix_alloc.gif Binary files differnew file mode 100644 index 0000000000..c6b41ce801 --- /dev/null +++ b/erts/doc/src/erl_fix_alloc.gif diff --git a/erts/doc/src/erl_fix_alloc.ps b/erts/doc/src/erl_fix_alloc.ps new file mode 100644 index 0000000000..bf65d1556c --- /dev/null +++ b/erts/doc/src/erl_fix_alloc.ps @@ -0,0 +1,646 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: erl_fix_alloc.fig +%%Creator: fig2dev Version 3.1 Patchlevel 2 +%%CreationDate: Tue May 20 11:10:33 1997 +%%For: jocke@akvavit (Joakim Greben|,ETX/B/DUP) +%Magnification: 1.00 +%%Orientation: Portrait +%%BoundingBox: 0 0 506 462 +%%Pages: 0 +%%BeginSetup +%%IncludeFeature: *PageSize A4 +%%EndSetup +%%EndComments +/MyAppDict 100 dict dup begin def +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +-18.0 481.0 translate +1 -1 scale +.9 .9 scale % to make patterns same scale as in xfig + +% This junk string is used by the show operators +/PATsstr 1 string def +/PATawidthshow { % cx cy cchar rx ry string + % Loop over each character in the string + { % cx cy cchar rx ry char + % Show the character + dup % cx cy cchar rx ry char char + PATsstr dup 0 4 -1 roll put % cx cy cchar rx ry char (char) + false charpath % cx cy cchar rx ry char + /clip load PATdraw + % Move past the character (charpath modified the + % current point) + currentpoint % cx cy cchar rx ry char x y + newpath + moveto % cx cy cchar rx ry char + % Reposition by cx,cy if the character in the string is cchar + 3 index eq { % cx cy cchar rx ry + 4 index 4 index rmoveto + } if + % Reposition all characters by rx ry + 2 copy rmoveto % cx cy cchar rx ry + } forall + pop pop pop pop pop % - + currentpoint + newpath + moveto +} bind def +/PATcg { + 7 dict dup begin + /lw currentlinewidth def + /lc currentlinecap def + /lj currentlinejoin def + /ml currentmiterlimit def + /ds [ currentdash ] def + /cc [ currentrgbcolor ] def + /cm matrix currentmatrix def + end +} bind def +% PATdraw - calculates the boundaries of the object and +% fills it with the current pattern +/PATdraw { % proc + save exch + PATpcalc % proc nw nh px py + 5 -1 roll exec % nw nh px py + newpath + PATfill % - + restore +} bind def +% PATfill - performs the tiling for the shape +/PATfill { % nw nh px py PATfill - + PATDict /CurrentPattern get dup begin + setfont + % Set the coordinate system to Pattern Space + PatternGState PATsg + % Set the color for uncolored pattezns + PaintType 2 eq { PATDict /PColor get PATsc } if + % Create the string for showing + 3 index string % nw nh px py str + % Loop for each of the pattern sources + 0 1 Multi 1 sub { % nw nh px py str source + % Move to the starting location + 3 index 3 index % nw nh px py str source px py + moveto % nw nh px py str source + % For multiple sources, set the appropriate color + Multi 1 ne { dup PC exch get PATsc } if + % Set the appropriate string for the source + 0 1 7 index 1 sub { 2 index exch 2 index put } for pop + % Loop over the number of vertical cells + 3 index % nw nh px py str nh + { % nw nh px py str + currentpoint % nw nh px py str cx cy + 2 index show % nw nh px py str cx cy + YStep add moveto % nw nh px py str + } repeat % nw nh px py str + } for + 5 { pop } repeat + end +} bind def + +% PATkshow - kshow with the current pattezn +/PATkshow { % proc string + exch bind % string proc + 1 index 0 get % string proc char + % Loop over all but the last character in the string + 0 1 4 index length 2 sub { + % string proc char idx + % Find the n+1th character in the string + 3 index exch 1 add get % string proe char char+1 + exch 2 copy % strinq proc char+1 char char+1 char + % Now show the nth character + PATsstr dup 0 4 -1 roll put % string proc chr+1 chr chr+1 (chr) + false charpath % string proc char+1 char char+1 + /clip load PATdraw + % Move past the character (charpath modified the current point) + currentpoint newpath moveto + % Execute the user proc (should consume char and char+1) + mark 3 1 roll % string proc char+1 mark char char+1 + 4 index exec % string proc char+1 mark... + cleartomark % string proc char+1 + } for + % Now display the last character + PATsstr dup 0 4 -1 roll put % string proc (char+1) + false charpath % string proc + /clip load PATdraw + neewath + pop pop % - +} bind def +% PATmp - the makepattern equivalent +/PATmp { % patdict patmtx PATmp patinstance + exch dup length 7 add % We will add 6 new entries plus 1 FID + dict copy % Create a new dictionary + begin + % Matrix to install when painting the pattern + TilingType PATtcalc + /PatternGState PATcg def + PatternGState /cm 3 -1 roll put + % Check for multi pattern sources (Level 1 fast color patterns) + currentdict /Multi known not { /Multi 1 def } if + % Font dictionary definitions + /FontType 3 def + % Create a dummy encoding vector + /Encoding 256 array def + 3 string 0 1 255 { + Encoding exch dup 3 index cvs cvn put } for pop + /FontMatrix matrix def + /FontBBox BBox def + /BuildChar { + mark 3 1 roll % mark dict char + exch begin + Multi 1 ne {PaintData exch get}{pop} ifelse % mark [paintdata] + PaintType 2 eq Multi 1 ne or + { XStep 0 FontBBox aload pop setcachedevice } + { XStep 0 setcharwidth } ifelse + currentdict % mark [paintdata] dict + /PaintProc load % mark [paintdata] dict paintproc + end + gsave + false PATredef exec true PATredef + grestore + cleartomark % - + } bind def + currentdict + end % newdict + /foo exch % /foo newlict + definefont % newfont +} bind def +% PATpcalc - calculates the starting point and width/height +% of the tile fill for the shape +/PATpcalc { % - PATpcalc nw nh px py + PATDict /CurrentPattern get begin + gsave + % Set up the coordinate system to Pattern Space + % and lock down pattern + PatternGState /cm get setmatrix + BBox aload pop pop pop translate + % Determine the bounding box of the shape + pathbbox % llx lly urx ury + grestore + % Determine (nw, nh) the # of cells to paint width and height + PatHeight div ceiling % llx lly urx qh + 4 1 roll % qh llx lly urx + PatWidth div ceiling % qh llx lly qw + 4 1 roll % qw qh llx lly + PatHeight div floor % qw qh llx ph + 4 1 roll % ph qw qh llx + PatWidth div floor % ph qw qh pw + 4 1 roll % pw ph qw qh + 2 index sub cvi abs % pw ph qs qh-ph + exch 3 index sub cvi abs exch % pw ph nw=qw-pw nh=qh-ph + % Determine the starting point of the pattern fill + %(px, py) + 4 2 roll % nw nh pw ph + PatHeight mul % nw nh pw py + exch % nw nh py pw + PatWidth mul exch % nw nh px py + end +} bind def + +% Save the original routines so that we can use them later on +/oldfill /fill load def +/oldeofill /eofill load def +/oldstroke /stroke load def +/oldshow /show load def +/oldashow /ashow load def +/oldwidthshow /widthshow load def +/oldawidthshow /awidthshow load def +/oldkshow /kshow load def + +% These defs are necessary so that subsequent procs don't bind in +% the originals +/fill { oldfill } bind def +/eofill { oldeofill } bind def +/stroke { oldstroke } bind def +/show { oldshow } bind def +/ashow { oldashow } bind def +/widthshow { oldwidthshow } bind def +/awidthshow { oldawidthshow } bind def +/kshow { oldkshow } bind def +/PATredef { + MyAppDict begin + { + /fill { /clip load PATdraw newpath } bind def + /eofill { /eoclip load PATdraw newpath } bind def + /stroke { PATstroke } bind def + /show { 0 0 null 0 0 6 -1 roll PATawidthshow } bind def + /ashow { 0 0 null 6 3 roll PATawidthshow } + bind def + /widthshow { 0 0 3 -1 roll PATawidthshow } + bind def + /awidthshow { PATawidthshow } bind def + /kshow { PATkshow } bind def + } { + /fill { oldfill } bind def + /eofill { oldeofill } bind def + /stroke { oldstroke } bind def + /show { oldshow } bind def + /ashow { oldashow } bind def + /widthshow { oldwidthshow } bind def + /awidthshow { oldawidthshow } bind def + /kshow { oldkshow } bind def + } ifelse + end +} bind def +false PATredef +% Conditionally define setcmykcolor if not available +/setcmykcolor where { pop } { + /setcmykcolor { + 1 sub 4 1 roll + 3 { + 3 index add neg dup 0 lt { pop 0 } if 3 1 roll + } repeat + setrgbcolor - pop + } bind def +} ifelse +/PATsc { % colorarray + aload length % c1 ... cn length + dup 1 eq { pop setgray } { 3 eq { setrgbcolor } { setcmykcolor + } ifelse } ifelse +} bind def +/PATsg { % dict + begin + lw setlinewidth + lc setlinecap + lj setlinejoin + ml setmiterlimit + ds aload pop setdash + cc aload pop setrgbcolor + cm setmatrix + end +} bind def + +/PATDict 3 dict def +/PATsp { + true PATredef + PATDict begin + /CurrentPattern exch def + % If it's an uncolored pattern, save the color + CurrentPattern /PaintType get 2 eq { + /PColor exch def + } if + /CColor [ currentrgbcolor ] def + end +} bind def +% PATstroke - stroke with the current pattern +/PATstroke { + countdictstack + save + mark + { + currentpoint strokepath moveto + PATpcalc % proc nw nh px py + clip newpath PATfill + } stopped { + (*** PATstroke Warning: Path is too complex, stroking + with gray) = + cleartomark + restore + countdictstack exch sub dup 0 gt + { { end } repeat } { pop } ifelse + gsave 0.5 setgray oldstroke grestore + } { pop restore pop } ifelse + newpath +} bind def +/PATtcalc { % modmtx tilingtype PATtcalc tilematrix + % Note: tiling types 2 and 3 are not supported + gsave + exch concat % tilingtype + matrix currentmatrix exch % cmtx tilingtype + % Tiling type 1 and 3: constant spacing + 2 ne { + % Distort the pattern so that it occupies + % an integral number of device pixels + dup 4 get exch dup 5 get exch % tx ty cmtx + XStep 0 dtransform + round exch round exch % tx ty cmtx dx.x dx.y + XStep div exch XStep div exch % tx ty cmtx a b + 0 YStep dtransform + round exch round exch % tx ty cmtx a b dy.x dy.y + YStep div exch YStep div exch % tx ty cmtx a b c d + 7 -3 roll astore % { a b c d tx ty } + } if + grestore +} bind def +/PATusp { + false PATredef + PATDict begin + CColor PATsc + end +} bind def + +% right30 +11 dict begin +/PaintType 1 def +/PatternType 1 def +/TilingType 1 def +/BBox [0 0 1 1] def +/XStep 1 def +/YStep 1 def +/PatWidth 1 def +/PatHeight 1 def +/Multi 2 def +/PaintData [ + { clippath } bind + { 32 16 true [ 32 0 0 -16 0 16 ] + {<00030003000c000c0030003000c000c0030003000c000c00 + 30003000c000c00000030003000c000c0030003000c000c0 + 030003000c000c0030003000c000c000>} + imagemask } bind +] def +/PaintProc { + pop + exec fill +} def +currentdict +end +/P2 exch def +1.1111 1.1111 scale %restore scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def + /DrawSplineSection { + /y3 exch def + /x3 exch def + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + /xa x1 x2 x1 sub 0.666667 mul add def + /ya y1 y2 y1 sub 0.666667 mul add def + /xb x3 x2 x3 sub 0.666667 mul add def + /yb y3 y2 y3 sub 0.666667 mul add def + x1 y1 lineto + xa ya xb yb x3 y3 curveto + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def +%%EndProlog + +$F2psBegin +10 setmiterlimit +n 0 842 m 0 0 l 595 0 l 595 842 l cp clip + 0.06000 0.06000 sc +7.500 slw +% Polyline +n 750 3600 m 750 1200 l 2325 1200 l 2325 3600 l gs col-1 s gr +% Polyline +n 750 1500 m 2325 1500 l gs col-1 s gr +% Polyline +n 750 1800 m 2325 1800 l gs col-1 s gr +15.000 slw +% Polyline +n 375 2100 m 2775 2100 l gs col-1 s gr +/Times-Roman ff 180.00 scf sf +900 2025 m +gs 1 -1 sc (allocated_blocks) col-1 sh gr +/Times-Roman ff 180.00 scf sf +1200 1725 m +gs 1 -1 sc (free_list) col-1 sh gr +/Times-Roman ff 180.00 scf sf +1200 1425 m +gs 1 -1 sc (item_size) col-1 sh gr +7.500 slw +% Polyline +n 3525 1200 m 5025 1200 l 5025 1800 l 3525 1800 l cp gs col-1 s gr +% Polyline +n 3525 1500 m 5025 1500 l gs col-1 s gr +/Times-Roman ff 180.00 scf sf +4050 1425 m +gs 1 -1 sc (next) col-1 sh gr +/Times-Roman ff 180.00 scf sf +4050 1725 m +gs 1 -1 sc (block) col-1 sh gr +% Polyline +n 5850 1200 m 7350 1200 l 7350 1800 l 5850 1800 l cp gs col-1 s gr +% Polyline +n 5850 1500 m 7350 1500 l gs col-1 s gr +/Times-Roman ff 180.00 scf sf +6375 1425 m +gs 1 -1 sc (next) col-1 sh gr +/Times-Roman ff 180.00 scf sf +6375 1725 m +gs 1 -1 sc (block) col-1 sh gr +15.000 slw +% Polyline + [100.0] 0 sd +n 3450 5700 m 5400 5700 l gs col-1 s gr [] 0 sd +7.500 slw +% Polyline +n 3600 8000 m 3600 3450 l 5175 3450 l 5175 8000 l gs col-1 s gr +15.000 slw +% Polyline + [100.0] 0 sd +n 3525 6900 m 5325 6900 l gs col-1 s gr [] 0 sd +0.000 slw +% Polyline + [33.3] 0 sd +n 3675 3525 m 5100 3525 l 5100 4425 l 3675 4425 l cp gs /PC [[1.00 1.00 1.00] [0.00 0.00 0.00]] def +15.00 15.00 sc P2 [16 0 0 -8 245.00 235.00] PATmp PATsp ef gr PATusp [] 0 sd +% Polyline + [33.3] 0 sd +n 3675 5775 m 5100 5775 l 5100 6825 l 3675 6825 l cp gs /PC [[1.00 1.00 1.00] [0.00 0.00 0.00]] def +15.00 15.00 sc P2 [16 0 0 -8 245.00 385.00] PATmp PATsp ef gr PATusp [] 0 sd +7.500 slw +% Polyline + [15 50.0] 50.0 sd +n 3600 4725 m 5250 4725 l gs col-1 s gr [] 0 sd +% Polyline + [15 50.0] 50.0 sd +n 3600 4950 m 5175 4950 l gs col-1 s gr [] 0 sd +0.000 slw +% Polyline + [15 25.0] 25.0 sd +n 6375 3750 m 6675 3750 l 6675 4050 l 6375 4050 l cp gs /PC [[1.00 1.00 1.00] [0.00 0.00 0.00]] def +15.00 15.00 sc P2 [16 0 0 -8 425.00 250.00] PATmp PATsp ef gr PATusp [] 0 sd +7.500 slw +% Polyline +gs clippath +4305 3253 m 4275 3373 l 4245 3253 l 4245 3415 l 4305 3415 l cp clip +n 4275 1800 m 4275 3400 l gs col-1 s gr gr + +% arrowhead +n 4305 3253 m 4275 3373 l 4245 3253 l 4275 3253 l 4305 3253 l cp gs 0.00 setgray ef gr col-1 s +15.000 slw +% Polyline + [100.0] 0 sd +n 3450 4500 m 5325 4500 l gs col-1 s gr [] 0 sd +7.500 slw +% Polyline +gs clippath +6630 2778 m 6600 2898 l 6570 2778 l 6570 2940 l 6630 2940 l cp clip +n 6600 1800 m 6600 2925 l gs col-1 s gr gr + +% arrowhead +n 6630 2778 m 6600 2898 l 6570 2778 l 6600 2778 l 6630 2778 l cp gs 0.00 setgray ef gr col-1 s +15.000 slw +% Polyline +gs clippath +656 840 m 723 1078 l 552 900 l 713 1181 l 817 1121 l cp clip +n 450 600 m 750 1125 l gs col-1 s gr gr + +% arrowhead +n 656 840 m 723 1078 l 552 900 l 604 870 l 656 840 l cp gs 0.00 setgray ef gr col-1 s +% Open spline +gs clippath +5627 1227 m 5749 1210 l 5650 1282 l 5800 1222 l 5778 1167 l cp clip +7.500 slw +n 4875.0 1350.0 m 5137.5 1350.0 l + 5137.5 1350.0 5400.0 1350.0 5587.5 1275.0 DrawSplineSection + 5775.0 1200.0 l gs col-1 s gr + gr + +% arrowhead +n 5627 1227 m 5749 1210 l 5650 1282 l 5639 1255 l 5627 1227 l cp gs 0.00 setgray ef gr col-1 s +% Open spline +gs clippath +7877 1227 m 7999 1210 l 7900 1282 l 8050 1222 l 8028 1167 l cp clip +n 7125.0 1350.0 m 7387.5 1350.0 l + 7387.5 1350.0 7650.0 1350.0 7837.5 1275.0 DrawSplineSection + 8025.0 1200.0 l gs col-1 s gr + gr + +% arrowhead +n 7877 1227 m 7999 1210 l 7900 1282 l 7889 1255 l 7877 1227 l cp gs 0.00 setgray ef gr col-1 s +% Interp Spline +gs clippath +3308 4453 m 3423 4496 l 3300 4512 l 3461 4532 l 3468 4472 l cp clip +n 2175 1650 m + 2346.9 1637.5 2421.9 1637.5 2475 1650 curveto + 2514.6 1659.3 2593.0 1702.0 2625 1725 curveto + 2665.4 1754.1 2753.1 1822.2 2775 1875 curveto + 2790.5 1912.4 2775.0 1990.8 2775 2025 curveto + 2775.0 2537.6 2542.8 3714.4 2775 4275 curveto + 2785.9 4301.4 2829.8 4335.4 2850 4350 curveto + 2882.0 4373.0 2962.7 4412.9 3000 4425 curveto + 3076.1 4449.8 3188.6 4468.5 3450 4500 curveto + gs col-1 s gr + gr + +% arrowhead +n 3308 4453 m 3423 4496 l 3300 4512 l 3304 4483 l 3308 4453 l cp gs 0.00 setgray ef gr col-1 s +% Interp Spline +gs clippath +5325 6973 m 5201 6969 l 5312 6914 l 5154 6949 l 5167 7007 l cp clip +n 5100 4575 m + 5270.9 4558.6 5345.9 4558.6 5400 4575 curveto + 5465.1 4594.7 5582.7 4669.6 5625 4725 curveto + 5662.1 4773.6 5691.1 4895.0 5700 4950 curveto + 5764.9 5350.0 5796.1 6267.8 5700 6675 curveto + 5690.7 6714.6 5655.4 6794.6 5625 6825 curveto + 5594.6 6855.4 5511.4 6886.6 5475 6900 curveto + 5424.7 6918.6 5349.7 6937.4 5175 6975 curveto + gs col-1 s gr + gr + +% arrowhead +n 5325 6973 m 5201 6969 l 5312 6914 l 5319 6944 l 5325 6973 l cp gs 0.00 setgray ef gr col-1 s +% Interp Spline +gs clippath +3300 1202 m 3423 1205 l 3313 1261 l 3471 1226 l 3458 1168 l cp clip +n 2250 1950 m + 2378.9 1959.4 2435.2 1959.4 2475 1950 curveto + 2514.6 1940.7 2593.0 1898.0 2625 1875 curveto + 2665.4 1845.9 2745.9 1765.4 2775 1725 curveto + 2821.1 1661.1 2878.9 1488.9 2925 1425 curveto + 2939.6 1404.8 2979.8 1364.6 3000 1350 curveto + 3032.0 1327.0 3113.7 1288.5 3150 1275 curveto + 3200.3 1256.4 3275.3 1237.7 3450 1200 curveto + gs col-1 s gr + gr + +% arrowhead +n 3300 1202 m 3423 1205 l 3313 1261 l 3306 1231 l 3300 1202 l cp gs 0.00 setgray ef gr col-1 s +/Times-Roman ff 180.00 scf sf +3975 4650 m +gs 1 -1 sc (next_free) col-1 sh gr +/Times-Roman ff 180.00 scf sf +4050 4875 m +gs 1 -1 sc (magic) col-1 sh gr +/Times-Bold ff 210.00 scf sf +6825 3975 m +gs 1 -1 sc (= allocated memory) col-1 sh gr +/Helvetica-Bold ff 180.00 scf sf +3675 1125 m +gs 1 -1 sc (AllocatedBlock) col-1 sh gr +/Helvetica-Bold ff 180.00 scf sf +1575 1125 m +gs 1 -1 sc (FixItem) col-1 sh gr +/Helvetica-Bold ff 180.00 scf sf +2400 4650 m +gs 1 -1 sc (FreeHeader) col-1 sh gr +/Times-Bold ff 180.00 scf sf +5250 3600 m +gs 1 -1 sc 270.0 rot (item_size) col-1 sh gr +/Times-Bold ff 270.00 scf sf +300 525 m +gs 1 -1 sc (fix_array) col-1 sh gr +$F2psEnd +rs +end diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml new file mode 100644 index 0000000000..c636d65ef3 --- /dev/null +++ b/erts/doc/src/erl_nif.xml @@ -0,0 +1,351 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>2001</year><year>2009</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>erl_nif</title> + <prepared>Sverker Eriksson</prepared> + <responsible>Sverker Eriksson</responsible> + <docno>1</docno> + <approved></approved> + <checked></checked> + <date>2009-11-17</date> + <rev>PA1</rev> + <file>erl_nif.xml</file> + </header> + <lib>erl_nif</lib> + <libsummary>API functions for an Erlang NIF library</libsummary> + <description> + <warning><p>The NIF concept is introduced in R13B03 as an + EXPERIMENTAL feature. The interfaces may be changed in any way + in coming releases. The API introduced in this release is very + sparse and contains only the most basic functions to read and + write Erlang terms. + </p></warning> + + <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> + <p>A minimal example of a NIF library can look like this:</p> + <p/> + <code type="none"> +/* niftest.c */ +#include "erl_nif.h" + +static ERL_NIF_TERM hello(ErlNifEnv* env) +{ + return enif_make_string(env, "Hello world!"); +} + +static ErlNifFunc nif_funcs[] = +{ + {"hello", 0, hello} +}; + +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"> +-module(niftest). + +-export([init/0, hello/0]). + +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"> +$> gcc -fPIC -shared -o niftest.so niftest.c -I $ERL_ROOT/usr/include/ +$> erl + +1> c(niftest). +{ok,niftest} +2> niftest:hello(). +"NIF library not loaded" +3> niftest:init(). +ok +4> niftest:hello(). +"Hello world!" +</code> + + <p>A better solution for a real module is to take advantage of + the new attribute <c>on_load</c> to automatically load the NIF + library when the module is loaded.</p> + <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 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 + global private data can be set when the NIF library is loaded and + then retrieved by calling <seealso marker="erl_nif#enif_get_data">enif_get_data()</seealso>.</p> + <p>There is currently 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. A NIF + library will can also be unloaded by replacing it with another + version of the library by a second call to + <c>erlang:load_nif/2</c> from the same module code.</p> + </description> + + <section> + <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> + </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> + <p><c>*priv_data</c> can be set to point to some private data + that the library needs in able to keep a state between NIF + calls. <c>enif_get_data()</c> will return this pointer.</p> + <p><c>load_info</c> is the second argument to <seealso + marker="erlang#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="reload"/>int (*reload)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)</tag> + <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> + </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 no previously loaded library for this module + code, BUT 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. 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> + </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.</p> + </item> + + + </taglist> + </section> + + <section> + <title>DATA TYPES</title> + + <taglist> + <tag><marker id="ErlDrvEnv"/>ErlDrvEnv</tag> + <item> + <p><c>ErlNifEnv</c> contains information about the context in + which a NIF call is made. This pointer should not be + dereferenced in any way, but only passed on to API + functions. An <c>ErlNifEnv</c> pointer is only valid until + the function, where is what supplied as argument, + returns. There is thus useless and dangerous to store <c>ErlNifEnv</c> + pointers in between NIF calls.</p> + </item> + <tag><marker id="ErlNifFunc"/>ErlNifFunc</tag> + <item> + <p/> + <code type="none"> +typedef struct { + const char* name; + unsigned arity; + ERL_NIF_TERM (*fptr)(ErlNifEnv* env, ...); +} 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 number of arguments must match the arity. A NIF of + arity 2 will thus look like:</p> + <p/> + <code type="none"> +ERL_NIF_TERM my_nif(ErlNifEnv* env, ERL_NIF_TERM arg1, ERL_NIF_TERM arg2) +{ + /* ... */ +} +</code> + <p>The maximum allowed arity for a NIF is 3 in current implementation.</p> + </item> + <tag><marker id="ErlNifBinary"/>ErlNifBinary</tag> + <item> + <p/> + <code type="none"> +typedef struct { + 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> + </item> + <tag><marker id="ERL_NIF_TERM"/>ERL_NIF_TERM</tag> + <item> + <p>Variables of type <c>ERL_NIF_TERM</c> can refere 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. A variable of type <c>ERL_NIF_TERM</c> is + only valid until the NIF call, where it was obtained, + returns.</p> + </item> + </taglist> + </section> + + <funcs> + <func><name><ret>void*</ret><nametext>enif_get_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 <c>load</c>, <c>reload</c> or <c>upgrade</c>.</p></desc> + </func> + <func><name><ret>void*</ret><nametext>enif_alloc(ErlNifEnv* env, size_t size)</nametext></name> + <fsummary>Allocate dynamic memory.</fsummary> + <desc><p>Allocate memory of <c>size</c> bytes.</p></desc> + </func> + <func><name><ret>void</ret><nametext>enif_free(ErlNifEnv* env, 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>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_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 + transient information about the binary term + <c>bin_term</c>. Return false if <c>bin_term</c> is not a binary.</p></desc> + </func> + <func><name><ret>int</ret><nametext>enif_alloc_binary(ErlNifEnv* env, unsigned size, ErlNifBinary* bin)</nametext></name> + <fsummary>Create a new binary.</fsummary> + <desc><p>Allocate a new binary of size of <c>size</c> + bytes. Initialize the structure pointed to by <c>bin</c> to + refer to the allocated binary.</p></desc> + </func> + <func><name><ret>void</ret><nametext>enif_release_binary(ErlNifEnv* env, ErlNifBinary* bin)</nametext></name> + <fsummary>Release a binary.</fsummary> + <desc><p>Release a binary obtained from <c>enif_alloc_binary</c> or <c>enif_inspect_binary</c>.</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> or return 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_ulong(ErlNifEnv* env, ERL_NIF_TERM term, unsigned long* ip)</nametext></name> + <fsummary>Read an unsigned long integer</fsummary> + <desc><p>Set <c>*ip</c> to the unsigned long integer value of + <c>term</c> 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_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> or return false if <c>list</c> is not a non-empty + list.</p></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>. Will also release + the binary.</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.</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_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>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 C-string <c>name</c>. Atom + terms may be saved and used between NIF calls.</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_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_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> + </func> + <func><name><ret>ERL_NIF_TERM</ret><nametext>enif_make_string(ErlNifEnv* env, const char* string)</nametext></name> + <fsummary>Create a string.</fsummary> + <desc><p>Creates a list containing the characters of the + C-string <c>string</c>.</p></desc> + </func> + </funcs> + <section> + <title>SEE ALSO</title> + <p><seealso marker="erlang#erlang:load_nif-2">load_nif(3)</seealso></p> + </section> +</cref> + diff --git a/erts/doc/src/erl_prim_loader.xml b/erts/doc/src/erl_prim_loader.xml new file mode 100644 index 0000000000..ccaa9b725f --- /dev/null +++ b/erts/doc/src/erl_prim_loader.xml @@ -0,0 +1,251 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>1996</year><year>2009</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>erl_prim_loader</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>erl_prim_loader.xml</file> + </header> + <module>erl_prim_loader</module> + <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 + 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> + + </description> + <funcs> + <func> + <name>start(Id, Loader, Hosts) -> {ok, Pid} | {error, What}</name> + <fsummary>Start the Erlang low level loader</fsummary> + <type> + <v>Id = term()</v> + <v>Loader = atom() | string()</v> + <v>Hosts = [Host]</v> + <v>Host = atom()</v> + <v>Pid = pid()</v> + <v>What = term()</v> + </type> + <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 Id</c>, + <c>-loader Loader</c>, and <c>-hosts Hosts</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 Id</c>, + <c>-hosts Hosts</c>, and <c>-setcookie Cookie</c> flags must + also be supplied. <c>Hosts</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>Hosts</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>get_file(Filename) -> {ok, Bin, FullName} | error</name> + <fsummary>Get a file</fsummary> + <type> + <v>Filename = string()</v> + <v>Bin = binary()</v> + <v>FullName = string()</v> + </type> + <desc> + <p>This function fetches a file using the low level loader. + <c>Filename</c> is either an absolute file name or just 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>FullName</c> is the complete name of the fetched file. + <c>Bin</c> is the contents of the file as a binary.</p> + + <p>The <c>Filename</c> can also be a file in an archive. For example + <c>/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin/mnesia_backup.beam</c> + See <seealso marker="kernel:code">code(3)</seealso> about archive files.</p> + </desc> + </func> + <func> + <name>get_path() -> {ok, Path}</name> + <fsummary>Get the path set in the loader</fsummary> + <type> + <v>Path = [Dir]</v> + <v>Dir = string()</v> + </type> + <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> + </desc> + </func> + <func> + <name>list_dir(Dir) -> {ok, Filenames} | error</name> + <fsummary>List files in a directory</fsummary> + <type> + <v>Dir = name()</v> + <v>Filenames = [Filename]</v> + <v>Filename = string()</v> + </type> + <desc> + <p>Lists all the files in a directory. Returns + <c>{ok, Filenames}</c> if successful. Otherwise, it returns + <c>error</c>. <c>Filenames</c> is a list of + the names of all the files in the directory. The names are + not sorted.</p> + <p>The <c>Dir</c> can also be a directory in an archive. For example + <c>/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin</c> + See <seealso marker="kernel:code">code(3)</seealso> about archive files.</p> + </desc> + </func> + <func> + <name>read_file_info(Filename) -> {ok, FileInfo} | error</name> + <fsummary>Get information about a file</fsummary> + <type> + <v>Filename = name()</v> + <v>FileInfo = #file_info{}</v> + </type> + <desc> + <p>Retrieves information about a file. Returns + <c>{ok, FileInfo}</c> if successful, otherwise + <c>error</c>. <c>FileInfo</c> is a record + <c>file_info</c>, defined in the Kernel include file + <c>file.hrl</c>. Include the following directive in the module + 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>Filename</c> can also be a file in an archive. For example + <c>/otp/root/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin/mnesia_backup.beam</c> + See <seealso marker="kernel:code">code(3)</seealso> about archive files.</p> + </desc> + </func> + <func> + <name>set_path(Path) -> ok</name> + <fsummary>Set the path of the loader</fsummary> + <type> + <v>Path = [Dir]</v> + <v>Dir = string()</v> + </type> + <desc> + <p>This function sets the path of the loader if <c>init</c> + 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> + <p>The <c>erl_prim_loader</c> module interprets the following + 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 + <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> + </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 + 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> + </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> + </section> +</erlref> + diff --git a/erts/doc/src/erl_set_memory_block.xml b/erts/doc/src/erl_set_memory_block.xml new file mode 100644 index 0000000000..d77da56d95 --- /dev/null +++ b/erts/doc/src/erl_set_memory_block.xml @@ -0,0 +1,172 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>1998</year><year>2009</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>erl_set_memory_block</title> + <prepared>Patrik Nyblom</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>98-08-05</date> + <rev>A</rev> + <file>erl_set_memory_block.xml</file> + </header> + <lib>erl_set_memory_block</lib> + <libsummary>Custom memory allocation for Erlang on VxWorks®</libsummary> + <description> + <p>This documentation is specific to VxWorks.</p> + <p>The <c><![CDATA[erl_set_memory_block]]></c> function/command initiates custom + memory allocation for the Erlang emulator. It has to be called + before the Erlang emulator is started and makes Erlang use one + single large memory block for all memory allocation.</p> + <p>The memory within the block can be utilized by other tasks than + Erlang. This is accomplished by calling the functions + <c><![CDATA[sys_alloc]]></c>, <c><![CDATA[sys_realloc]]></c> and <c><![CDATA[sys_free]]></c> instead + of <c><![CDATA[malloc]]></c>, <c><![CDATA[realloc]]></c> and <c><![CDATA[free]]></c> respectively.</p> + <p>The purpose of this is to avoid problems inherent in the + VxWorks systems <c><![CDATA[malloc]]></c> library. The memory allocation within the + large memory block avoids fragmentation by using an "address + order first fit" algorithm. Another advantage of using a + separate memory block is that resource reclamation can be made + more easily when Erlang is stopped.</p> + <p>The <c><![CDATA[erl_set_memory_block]]></c> function is callable from any C + program as an ordinary 10 argument function as well as + from the commandline.</p> + </description> + <funcs> + <func> + <name><ret>int</ret><nametext>erl_set_memory_block(size_t size, void *ptr, int warn_mixed_malloc, int realloc_always_moves, int use_reclaim, ...)</nametext></name> + <fsummary>Specify parameters for Erlang internal memory allocation.</fsummary> + <desc> + <p>The function is called before Erlang is + started to specify a large memory block where Erlang can + maintain memory internally.</p> + <p>Parameters:</p> + <taglist> + <tag>size_t size</tag> + <item>The size in bytes of Erlang's internal memory block. Has to + be specified. Note that the VxWorks system uses dynamic + memory allocation heavily, so leave some memory to the system.</item> + <tag>void *ptr</tag> + <item> + <p>A pointer to the actual memory block of size + <c><![CDATA[size]]></c>. If this is specified as 0 (NULL), Erlang will + allocate the memory when starting and will reclaim the + memory block (as a whole) when stopped.</p> + <p>If a memory block is allocated and provided here, the + <c><![CDATA[sys_alloc]]></c> etc routines can still be used after + the Erlang emulator is stopped. The Erlang emulator can + also be restarted while other tasks using the memory + block are running without destroying the memory. If + Erlang is to be restarted, also set the + <c><![CDATA[use_reclaim]]></c> flag.</p> + <p>If 0 is specified here, the Erlang system should not + be stopped while some other task uses the memory block + (has called <c><![CDATA[sys_alloc]]></c>).</p> + </item> + <tag>int warn_mixed_malloc</tag> + <item> + <p>If this flag is set to true (anything else than 0), the + system will write a warning message on the console if a + program is mixing normal <c><![CDATA[malloc]]></c> with + <c><![CDATA[sys_realloc]]></c> or <c><![CDATA[sys_free]]></c>.</p> + </item> + <tag>int realloc_always_moves</tag> + <item> + <p>If this flag is set to true (anything else than 0), all + calls to <c><![CDATA[sys_realloc]]></c> result in a moved memory + block. This can in certain conditions give less + fragmentation. This flag may be removed in future releases.</p> + </item> + <tag>int use_reclaim</tag> + <item> + <p>If this flag is set to true (anything else than 0), all + memory allocated with <c><![CDATA[sys_alloc]]></c> is automatically + reclaimed as soon as a task exits. This is very useful + to make writing port programs (and other programs as + well) easier. Combine this with using the routines + <c><![CDATA[save_open]]></c> etc. specified in the reclaim.h + file delivered in the Erlang distribution.</p> + </item> + </taglist> + <p>Return Value:</p> + <p>Returns 0 (OK) on success, otherwise a value <> 0.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_memory_show(...)</nametext></name> + <fsummary>A utility similar to VxWorks <c><![CDATA[memShow]]></c>, but for the Erlang memory area.</fsummary> + <desc> + <p>Return Value:</p> + <p>Returns 0 (OK) on success, otherwise a value <> 0.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>erl_mem_info_get(MEM_PART_STATS *stats)</nametext></name> + <fsummary>A utility similar to VxWorks <c><![CDATA[memPartInfoGet]]></c>, but for the Erlang memory area.</fsummary> + <desc> + <p>Parameter:</p> + <taglist> + <tag>MEM_PART_STATS *stats</tag> + <item>A pointer to a MEM_PART_STATS structure as defined in + <c><![CDATA[<memLib.h>]]></c>. A successful call will fill in all + fields of the structure, on error all fields are left untouched. </item> + </taglist> + <p>Return Value:</p> + <p>Returns 0 (OK) on success, otherwise a value <> 0</p> + </desc> + </func> + </funcs> + + <section> + <title>NOTES</title> + <p>The memory block used by Erlang actually does not need to be + inside the area known to ordinary <c><![CDATA[malloc]]></c>. It is possible + to set the <c><![CDATA[USER_RESERVED_MEM]]></c> preprocessor symbol when compiling + the wind kernel and then use user reserved memory for + Erlang. Erlang can therefor utilize memory above the 32 Mb limit + of VxWorks on the PowerPC architecture.</p> + <p>Example:</p> + <p>In config.h for the wind kernel:</p> + <code type="none"><![CDATA[ + #undef LOCAL_MEM_AUTOSIZE + #undef LOCAL_MEM_SIZE + #undef USER_RESERVED_MEM + + #define LOCAL_MEM_SIZE 0x05000000 + #define USER_RESERVED_MEM 0x03000000 + ]]></code> + <p>In the start-up script/code for the VxWorks node:</p> + <code type="none"><![CDATA[ +erl_set_memory_block(sysPhysMemTop()-sysMemTop(),sysMemTop(),0,0,1); + ]]></code> + <p>Setting the <c><![CDATA[use_reclaim]]></c> flag decreases performance of the + system, but makes programming much easier. Other similar + facilities are present in the Erlang system even without using a + separate memory block. The routines called <c><![CDATA[save_malloc]]></c>, + <c><![CDATA[save_realloc]]></c> and <c><![CDATA[save_free]]></c> provide the same + facilities by using VxWorks own <c><![CDATA[malloc]]></c>. Similar routines + exist for files, see the file <c><![CDATA[reclaim.h]]></c> in the distribution.</p> + </section> +</cref> + diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml new file mode 100644 index 0000000000..fd4447009a --- /dev/null +++ b/erts/doc/src/erlang.xml @@ -0,0 +1,6920 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>1996</year><year>2009</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>erlang</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>erlang.xml</file> + </header> + <module>erlang</module> + <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 + 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. + BIFs listed with module prefix are not auto-imported.</p> + <p>BIFs may fail for a variety of 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 + "Allowed in guard tests".</p> + </description> + + <section> + <title>DATA TYPES</title> + <marker id="iolist_definition"></marker> + <code type="none"> +ext_binary() + a binary data object, + structured according to the Erlang external term format + +iodata() = iolist() | binary() + +iolist() = [char() | binary() | iolist()] + a binary is allowed as the tail of the list</code> + </section> + <funcs> + <func> + <name>abs(Number) -> int() | float()</name> + <fsummary>Arithmetical absolute value</fsummary> + <type> + <v>Number = number()</v> + </type> + <desc> + <p>Returns an integer or float which is the arithmetical + absolute value of <c>Number</c>.</p> + <pre> +> <input>abs(-3.33).</input> +3.33 +> <input>abs(-3).</input> +3</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>adler32(Data) -> int()</name> + <fsummary>Compute adler32 checksum</fsummary> + <type> + <v>Data = iodata()</v> + </type> + <desc> + <p>Computes and returns the adler32 checksum for <c>Data</c>.</p> + </desc> + </func> + <func> + <name>adler32(OldAdler, Data) -> int()</name> + <fsummary>Compute adler32 checksum</fsummary> + <type> + <v>OldAdler = int()</v> + <v>Data = iodata()</v> + </type> + <desc> + <p>Continue computing the adler32 checksum by combining + the previous checksum, <c>OldAdler</c>, with the checksum of + <c>Data</c>.</p> + <p>The following code:</p> + <code> + X = adler32(Data1), + Y = adler32(X,Data2). + </code> + <p>- would assign the same value to <c>Y</c> as this would:</p> + <code> + Y = adler32([Data1,Data2]). + </code> + </desc> + </func> + <func> + <name>adler32_combine(FirstAdler, SecondAdler, SecondSize) -> int()</name> + <fsummary>Combine two adler32 checksums</fsummary> + <type> + <v>FirstAdler = SecondAdler = int()</v> + <v>SecondSize = int()</v> + </type> + <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 = adler32(Data1), + Z = adler32(Y,Data2). + </code> + <p>- would assign the same value to <c>Z</c> as this would:</p> + <code> + X = adler32(Data1), + Y = adler32(Data2), + Z = adler32_combine(X,Y,iolist_size(Data2)). + </code> + </desc> + </func> + <func> + <name>erlang:append_element(Tuple1, Term) -> Tuple2</name> + <fsummary>Append an extra element to a tuple</fsummary> + <type> + <v>Tuple1 = Tuple2 = tuple()</v> + <v>Term = term()</v> + </type> + <desc> + <p>Returns a new tuple which has one element more than + <c>Tuple1</c>, and contains the elements in <c>Tuple1</c> + followed by <c>Term</c> as the last element. Semantically + equivalent to + <c>list_to_tuple(tuple_to_list(Tuple ++ [Term])</c>, but much + faster.</p> + <pre> +> <input>erlang:append_element({one, two}, three).</input> +{one,two,three}</pre> + </desc> + </func> + <func> + <name>apply(Fun, Args) -> term() | empty()</name> + <fsummary>Apply a function to an argument list</fsummary> + <type> + <v>Fun = fun()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>Call a fun, passing the elements in <c>Args</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 + <c>Fun(Arg1, Arg2, ... ArgN)</c>.</p> + <warning> + <p>Earlier, <c>Fun</c> could also be given 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> + </warning> + </desc> + </func> + <func> + <name>apply(Module, Function, Args) -> term() | empty()</name> + <fsummary>Apply a function to an argument list</fsummary> + <type> + <v>Module = Function = atom()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>Returns the result of applying <c>Function</c> in + <c>Module</c> to <c>Args</c>. The applied function must + be exported from <c>Module</c>. The arity of the function is + the length of <c>Args</c>.</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> +> <input>apply(erlang, atom_to_list, ['Erlang']).</input> +"Erlang"</pre> + <p>Note: If the number of arguments are known at compile-time, + the call is better written as + <c>Module:Function(Arg1, Arg2, ..., ArgN)</c>.</p> + <p>Failure: <c>error_handler:undefined_function/3</c> 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 + redefined the default <c>error_handler</c> so the replacement + module is undefined, an error with the reason <c>undef</c> + is generated.</p> + </desc> + </func> + <func> + <name>atom_to_binary(Atom, Encoding) -> binary()</name> + <fsummary>Return the binary representation of an atom</fsummary> + <type> + <v>Atom = atom()</v> + <v>Encoding = latin1 | utf8 | unicode</v> + </type> + <desc> + <p>Returns a binary which corresponds to the text + representation of <c>Atom</c>. If <c>Encoding</c> + is <c>latin1</c>, there will be one byte for each character + in the text representation. If <c>Encoding</c> is <c>utf8</c> or + <c>unicode</c>, the characters will encoded using UTF-8 + (meaning that characters from 16#80 up to 0xFF will be + encode in two bytes).</p> + + <note><p>Currently, <c>atom_to_binary(Atom, 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(Atom, latin1)</c> will fail if the + text representation for the <c>Atom</c> contains a Unicode + character greater than 16#FF.</p></note> + + <pre> +> <input>atom_to_binary('Erlang', latin1).</input> +<<"Erlang">></pre> + </desc> + </func> + <func> + <name>atom_to_list(Atom) -> string()</name> + <fsummary>Text representation of an atom</fsummary> + <type> + <v>Atom = atom()</v> + </type> + <desc> + <p>Returns a string which corresponds to the text + representation of <c>Atom</c>.</p> + <pre> +> <input>atom_to_list('Erlang').</input> +"Erlang"</pre> + </desc> + </func> + <func> + <name>binary_to_atom(Binary, Encoding) -> atom()</name> + <fsummary>Convert from text representation to an atom</fsummary> + <type> + <v>Binary = binary()</v> + <v>Encoding = latin1 | utf8 | unicode</v> + </type> + <desc> + <p>Returns the atom whose text representation is + <c>Binary</c>. If <c>Encoding</c> is <c>latin1</c>, no + translation of bytes in the binary is done. If <c>Encoding</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(Binary, 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(Binary, utf8)</c> + will not fail in that case.</p></note> + + <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> + </desc> + </func> + <func> + <name>binary_to_existing_atom(Binary, Encoding) -> atom()</name> + <fsummary>Convert from text representation to an atom</fsummary> + <type> + <v>Binary = binary()</v> + <v>Encoding = latin1 | utf8 | unicode</v> + </type> + <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> + </desc> + </func> + <func> + <name>binary_to_list(Binary) -> [char()]</name> + <fsummary>Convert a binary to a list</fsummary> + <type> + <v>Binary = binary()</v> + </type> + <desc> + <p>Returns a list of integers which correspond to the bytes of + <c>Binary</c>.</p> + </desc> + </func> + <func> + <name>binary_to_list(Binary, Start, Stop) -> [char()]</name> + <fsummary>Convert part of a binary to a list</fsummary> + <type> + <v>Binary = binary()</v> + <v>Start = Stop = 1..byte_size(Binary)</v> + </type> + <desc> + <p>As <c>binary_to_list/1</c>, but returns a list of integers + corresponding to the bytes from position <c>Start</c> to + position <c>Stop</c> in <c>Binary</c>. Positions in the + binary are numbered starting from 1.</p> + </desc> + </func> + <func> + <name>bitstring_to_list(Bitstring) -> [char()|bitstring()]</name> + <fsummary>Convert a bitstring to a list</fsummary> + <type> + <v>Bitstring = bitstring()</v> + </type> + <desc> + <p>Returns a list of integers which correspond to the bytes of + <c>Bitstring</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> + </desc> + </func> + <func> + <name>binary_to_term(Binary) -> term()</name> + <fsummary>Decode an Erlang external term format binary</fsummary> + <type> + <v>Binary = ext_binary()</v> + </type> + <desc> + <p>Returns an Erlang term which is the result of decoding + the binary object <c>Binary</c>, which must be encoded + according to the Erlang external term format. See also + <seealso marker="#term_to_binary/1">term_to_binary/1</seealso>.</p> + </desc> + </func> + <func> + <name>bit_size(Bitstring) -> int()</name> + <fsummary>Return the size of a bitstring</fsummary> + <type> + <v>Bitstring = bitstring()</v> + </type> + <desc> + <p>Returns an integer which is the size in bits of <c>Bitstring</c>.</p> + <pre> +> <input>bit_size(<<433:16,3:3>>).</input> +19 +> <input>bit_size(<<1,2,3>>).</input> +24</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>erlang:bump_reductions(Reductions) -> void()</name> + <fsummary>Increment the reduction counter</fsummary> + <type> + <v>Reductions = int()</v> + </type> + <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> + <warning> + <p>This BIF might 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>byte_size(Bitstring) -> int()</name> + <fsummary>Return the size of a bitstring (or binary)</fsummary> + <type> + <v>Bitstring = bitstring()</v> + </type> + <desc> + <p>Returns an integer which is the number of bytes needed to contain + <c>Bitstring</c>. (That is, if the number of bits in <c>Bitstring</c> is not + divisible by 8, the resulting number of bytes will be rounded <em>up</em>.)</p> + <pre> +> <input>byte_size(<<433:16,3:3>>).</input> +3 +> <input>byte_size(<<1,2,3>>).</input> +3</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>erlang:cancel_timer(TimerRef) -> Time | false</name> + <fsummary>Cancel a timer</fsummary> + <type> + <v>TimerRef = ref()</v> + <v>Time = int()</v> + </type> + <desc> + <p>Cancels a timer, where <c>TimerRef</c> was returned by + either + <seealso marker="#erlang:send_after/3">erlang:send_after/3</seealso> + or + <seealso marker="#erlang: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>TimerRef</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="#erlang:send_after/3">erlang:send_after/3</seealso>, + <seealso marker="#erlang:start_timer/3">erlang:start_timer/3</seealso>, + and + <seealso marker="#erlang: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> + </desc> + </func> + + <func> + <name>check_process_code(Pid, Module) -> bool()</name> + <fsummary>Check if a process is executing old code for a module</fsummary> + <type> + <v>Pid = pid()</v> + <v>Module = atom()</v> + </type> + <desc> + <p>Returns <c>true</c> if the process <c>Pid</c> is executing + old code for <c>Module</c>. That is, if the current call of + the process executes old code for this module, or if the + process has references to old code for this module, or if the + process contains funs that references old code for this + module. Otherwise, it returns <c>false</c>.</p> + <pre> +> <input>check_process_code(Pid, lists).</input> +false</pre> + <p>See also <seealso marker="kernel:code">code(3)</seealso>.</p> + </desc> + </func> + <func> + <name>concat_binary(ListOfBinaries)</name> + <fsummary>Concatenate a list of binaries (deprecated)</fsummary> + <desc> + <p>Do not use; use + <seealso marker="#list_to_binary/1">list_to_binary/1</seealso> + instead.</p> + </desc> + </func> + <func> + <name>crc32(Data) -> int()</name> + <fsummary>Compute crc32 (IEEE 802.3) checksum</fsummary> + <type> + <v>Data = iodata()</v> + </type> + <desc> + <p>Computes and returns the crc32 (IEEE 802.3 style) checksum for <c>Data</c>.</p> + </desc> + </func> + <func> + <name>crc32(OldCrc, Data) -> int()</name> + <fsummary>Compute crc32 (IEEE 802.3) checksum</fsummary> + <type> + <v>OldCrc = int()</v> + <v>Data = iodata()</v> + </type> + <desc> + <p>Continue computing the crc32 checksum by combining + the previous checksum, <c>OldCrc</c>, with the checksum of + <c>Data</c>.</p> + <p>The following code:</p> + <code> + X = crc32(Data1), + Y = crc32(X,Data2). + </code> + <p>- would assign the same value to <c>Y</c> as this would:</p> + <code> + Y = crc32([Data1,Data2]). + </code> + </desc> + </func> + <func> + <name>crc32_combine(FirstCrc, SecondCrc, SecondSize) -> int()</name> + <fsummary>Combine two crc32 (IEEE 802.3) checksums</fsummary> + <type> + <v>FirstCrc = SecondCrc = int()</v> + <v>SecondSize = int()</v> + </type> + <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 = crc32(Data1), + Z = crc32(Y,Data2). + </code> + <p>- would assign the same value to <c>Z</c> as this would:</p> + <code> + X = crc32(Data1), + Y = crc32(Data2), + Z = crc32_combine(X,Y,iolist_size(Data2)). + </code> + </desc> + </func> + <func> + <name>date() -> {Year, Month, Day}</name> + <fsummary>Current date</fsummary> + <type> + <v>Year = Month = Day = int()</v> + </type> + <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> + <pre> +> <input>date().</input> +{1995,2,19}</pre> + </desc> + </func> + <func> + <name>decode_packet(Type,Bin,Options) -> {ok,Packet,Rest} | {more,Length} | {error,Reason}</name> + <fsummary>Extracts a protocol packet from a binary</fsummary> + <type> + <v>Bin = binary()</v> + <v>Options = [Opt]</v> + <v>Packet = binary() | HttpPacket</v> + <v>Rest = binary()</v> + <v>Length = int() | undefined</v> + <v>Reason = term()</v> + <v> Type, Opt -- see below</v> + <v></v> + <v>HttpPacket = HttpRequest | HttpResponse | HttpHeader | http_eoh | HttpError</v> + <v>HttpRequest = {http_request, HttpMethod, HttpUri, HttpVersion}</v> + <v>HttpResponse = {http_response, HttpVersion, integer(), HttpString}</v> + <v>HttpHeader = {http_header, int(), HttpField, Reserved=term(), Value=HttpString}</v> + <v>HttpError = {http_error, HttpString}</v> + <v>HttpMethod = HttpMethodAtom | HttpString</v> + <v>HttpMethodAtom = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE'</v> + <v>HttpUri = '*' | {absoluteURI, http|https, Host=HttpString, Port=int()|undefined, Path=HttpString} | + {scheme, Scheme=HttpString, HttpString} | {abs_path, HttpString} | HttpString</v> + <v>HttpVersion = {Major=int(), Minor=int()}</v> + <v>HttpString = string() | binary()</v> + <v>HttpField = HttpFieldAtom | HttpString</v> + <v>HttpFieldAtom = 'Cache-Control' | 'Connection' | 'Date' | 'Pragma' | 'Transfer-Encoding' | 'Upgrade' | 'Via' | 'Accept' | 'Accept-Charset' | 'Accept-Encoding' | 'Accept-Language' | 'Authorization' | 'From' | 'Host' | 'If-Modified-Since' | 'If-Match' | 'If-None-Match' | 'If-Range' | 'If-Unmodified-Since' | 'Max-Forwards' | 'Proxy-Authorization' | 'Range' | 'Referer' | 'User-Agent' | 'Age' | 'Location' | 'Proxy-Authenticate' | 'Public' | 'Retry-After' | 'Server' | 'Vary' | 'Warning' | 'Www-Authenticate' | 'Allow' | 'Content-Base' | 'Content-Encoding' | 'Content-Language' | 'Content-Length' | 'Content-Location' | 'Content-Md5' | 'Content-Range' | 'Content-Type' | 'Etag' | 'Expires' | 'Last-Modified' | 'Accept-Ranges' | 'Set-Cookie' | 'Set-Cookie2' | 'X-Forwarded-For' | 'Cookie' | 'Keep-Alive' | 'Proxy-Connection'</v> + <v></v> + </type> + <desc> + <p>Decodes the binary <c>Bin</c> according to the packet + protocol specified by <c>Type</c>. Very similar to the packet + handling done by sockets with the option {packet,Type}.</p> + <p>If an entire packet is contained in <c>Bin</c> it is + returned together with the remainder of the binary as + <c>{ok,Packet,Rest}</c>.</p> + <p>If <c>Bin</c> does not contain the entire packet, + <c>{more,Length}</c> is returned. <c>Length</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,Reason}</c> is returned.</p> + <p>The following values of <c>Type</c> are valid:</p> + <taglist> + <tag><c>raw | 0</c></tag> + <item> + <p>No packet handling is done. 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 order of the bytes is big-endian. The header + will be 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> + </item> + <tag><c>asn1 | cdr | sunrm | fcgi | tpkt</c></tag> + <item> + <p>The header is <em>not</em> stripped off.</p> + <p>The meanings of the packet types are as follows:</p> + <taglist> + <tag><c>asn1</c> - ASN.1 BER</tag><item></item> + <tag><c>sunrm</c> - Sun's RPC encoding</tag><item></item> + <tag><c>cdr</c> - CORBA (GIOP 1.1)</tag><item></item> + <tag><c>fcgi</c> - Fast CGI</tag><item></item> + <tag><c>tpkt</c> - TPKT format [RFC1006]</tag><item></item> + </taglist> + </item> + <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>HttpPacket</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>HttpError</c>.</p> + <p>Recognized request methods and header fields are returned as atoms. + Others are returned as strings.</p> + <p>The protocol type <c>http</c> should only be used for + the first line when a <c>HttpRequest</c> or a + <c>HttpResponse</c> is expected. The following calls + should use <c>httph</c> to get <c>HttpHeader</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> + </item> + </taglist> + <p>The following options are available:</p> + <taglist> + <tag><c>{packet_size, int()}</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, int()}</c></tag> + <item><p>Applies only to line oriented protocols + (<c>line</c>, <c>http</c>). Lines longer than this + will be truncated.</p> + </item> + </taglist> + <pre> +> <input>erlang:decode_packet(1,<<3,"abcd">>,[]).</input> +{ok,<<"abc">>,<<"d">>} +> <input>erlang:decode_packet(1,<<5,"abcd">>,[]).</input> +{more,6}</pre> + </desc> + </func> + <func> + <name>delete_module(Module) -> true | undefined</name> + <fsummary>Make the current code for a module old</fsummary> + <type> + <v>Module = atom()</v> + </type> + <desc> + <p>Makes the current code for <c>Module</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> + </warning> + <p>Failure: <c>badarg</c> if there is already an old version of + <c>Module</c>.</p> + </desc> + </func> + <func> + <name>erlang:demonitor(MonitorRef) -> true</name> + <fsummary>Stop monitoring</fsummary> + <type> + <v>MonitorRef = ref()</v> + </type> + <desc> + <p>If <c>MonitorRef</c> is a reference which the calling process + obtained by calling + <seealso marker="#erlang:monitor/2">erlang:monitor/2</seealso>, + this monitoring is turned off. If the monitoring is already + turned off, nothing happens.</p> + <p>Once <c>erlang:demonitor(MonitorRef)</c> has returned it is + guaranteed that no <c>{'DOWN', MonitorRef, _, _, _}</c> message + due to the monitor will be placed in the callers message queue + in the future. A <c>{'DOWN', MonitorRef, _, _, _}</c> message + might have been placed in the callers message queue prior to + the call, though. Therefore, in most cases, it is advisable + to remove such a <c>'DOWN'</c> message from the message queue + after monitoring has been stopped. + <seealso marker="#erlang:demonitor/2">erlang:demonitor(MonitorRef, [flush])</seealso> can be used instead of + <c>erlang:demonitor(MonitorRef)</c> if this cleanup is wanted.</p> + <note> + <p>Prior to OTP release R11B (erts version 5.5) <c>erlang:demonitor/1</c> + behaved completely asynchronous, i.e., the monitor was active + until the "demonitor signal" reached the monitored entity. This + had one undesirable effect, though. 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: + asynchronously send a "demonitor signal" to the monitored entity + and ignore any future results of the monitor. </p> + </note> + <p>Failure: It is an error if <c>MonitorRef</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>MonitorRef</c> is a remote + reference).</p> + </desc> + </func> + <func> + <name>erlang:demonitor(MonitorRef, OptionList) -> true|false</name> + <fsummary>Stop monitoring</fsummary> + <type> + <v>MonitorRef = ref()</v> + <v>OptionList = [Option]</v> + <v>Option = flush</v> + <v>Option = info</v> + </type> + <desc> + <p>The returned value is <c>true</c> unless <c>info</c> is part + of <c>OptionList</c>. + </p> + <p><c>erlang:demonitor(MonitorRef, [])</c> is equivalent to + <seealso marker="#erlang:demonitor/1">erlang:demonitor(MonitorRef)</seealso>.</p> + <p>Currently the following <c>Option</c>s are valid:</p> + <taglist> + <tag><c>flush</c></tag> + <item> + <p>Remove (one) <c>{_, MonitorRef, _, _, _}</c> message, + if there is one, from the callers message queue after + monitoring has been stopped.</p> + <p>Calling <c>erlang:demonitor(MonitorRef, [flush])</c> + is equivalent to the following, but more efficient:</p> + <code type="none"> + + erlang:demonitor(MonitorRef), + receive +\011{_, MonitorRef, _, _, _} -> +\011 true + after 0 -> +\011 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 callers 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> + </item> + </taglist> + <note> + <p>More options may be added in the future.</p> + </note> + <p>Failure: <c>badarg</c> if <c>OptionList</c> is not a list, or + if <c>Option</c> is not a valid option, or the same failure as for + <seealso marker="#erlang:demonitor/1">erlang:demonitor/1</seealso></p> + </desc> + </func> + <func> + <name>disconnect_node(Node) -> bool() | ignored</name> + <fsummary>Force the disconnection of a node</fsummary> + <type> + <v>Node = atom()</v> + </type> + <desc> + <p>Forces the disconnection of a node. This will appear to + the node <c>Node</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, + otherwise <c>false</c>. If the local node is not alive, + the function returns <c>ignored</c>.</p> + </desc> + </func> + <func> + <name>erlang:display(Term) -> true</name> + <fsummary>Print a term on standard output</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Prints a text representation of <c>Term</c> on the standard + output.</p> + <warning> + <p>This BIF is intended for debugging only.</p> + </warning> + </desc> + </func> + <func> + <name>element(N, Tuple) -> term()</name> + <fsummary>Get Nth element of a tuple</fsummary> + <type> + <v>N = 1..tuple_size(Tuple)</v> + <v>Tuple = tuple()</v> + </type> + <desc> + <p>Returns the <c>N</c>th element (numbering from 1) of + <c>Tuple</c>.</p> + <pre> +> <input>element(2, {a, b, c}).</input> +b</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>erase() -> [{Key, Val}]</name> + <fsummary>Return and delete the process dictionary</fsummary> + <type> + <v>Key = Val = term()</v> + </type> + <desc> + <p>Returns the process dictionary and deletes it.</p> + <pre> +> <input>put(key1, {1, 2, 3}),</input> +<input>put(key2, [a, b, c]),</input> +<input>erase().</input> +[{key1,{1,2,3}},{key2,[a,b,c]}]</pre> + </desc> + </func> + <func> + <name>erase(Key) -> Val | undefined</name> + <fsummary>Return and delete a value from the process dictionary</fsummary> + <type> + <v>Key = Val = term()</v> + </type> + <desc> + <p>Returns the value <c>Val</c> associated with <c>Key</c> and + deletes it from the process dictionary. Returns + <c>undefined</c> if no value is associated with <c>Key</c>.</p> + <pre> +> <input>put(key1, {merry, lambs, are, playing}),</input> +<input>X = erase(key1),</input> +<input>{X, erase(key1)}.</input> +{{merry,lambs,are,playing},undefined}</pre> + </desc> + </func> + <func> + <name>erlang:error(Reason)</name> + <fsummary>Stop execution with a given reason</fsummary> + <type> + <v>Reason = term()</v> + </type> + <desc> + <p>Stops the execution of the calling process with the reason + <c>Reason</c>, where <c>Reason</c> is any term. The actual + exit reason will be <c>{Reason, 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> + <pre> +> <input>catch erlang: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> + </desc> + </func> + <func> + <name>erlang:error(Reason, Args)</name> + <fsummary>Stop execution with a given reason</fsummary> + <type> + <v>Reason = term()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>Stops the execution of the calling process with the reason + <c>Reason</c>, where <c>Reason</c> is any term. The actual + exit reason will be <c>{Reason, Where}</c>, where <c>Where</c> + is a list of the functions most recently called (the current + function first). <c>Args</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 + the process to terminate, it has no return value.</p> + </desc> + </func> + <func> + <name>exit(Reason)</name> + <fsummary>Stop execution with a given reason</fsummary> + <type> + <v>Reason = term()</v> + </type> + <desc> + <p>Stops the execution of the calling process with the exit + reason <c>Reason</c>, where <c>Reason</c> is any term. Since + evaluating this function causes the process to terminate, it + has no return value.</p> + <pre> +> <input>exit(foobar).</input> +** exception exit: foobar +> <input>catch exit(foobar).</input> +{'EXIT',foobar}</pre> + </desc> + </func> + <func> + <name>exit(Pid, Reason) -> true</name> + <fsummary>Send an exit signal to a process</fsummary> + <type> + <v>Pid = pid()</v> + <v>Reason = term()</v> + </type> + <desc> + <p>Sends an exit signal with exit reason <c>Reason</c> to + the process <c>Pid</c>.</p> + <p>The following behavior apply if <c>Reason</c> is any term + except <c>normal</c> or <c>kill</c>:</p> + <p>If <c>Pid</c> is not trapping exits, <c>Pid</c> itself will + exit with exit reason <c>Reason</c>. If <c>Pid</c> is trapping + exits, the exit signal is transformed into a message + <c>{'EXIT', From, Reason}</c> and delivered to the message + queue of <c>Pid</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>Reason</c> is the atom <c>normal</c>, <c>Pid</c> will + 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>Reason</c> is the atom <c>kill</c>, that is if + <c>exit(Pid, kill)</c> is called, an untrappable exit signal + is sent to <c>Pid</c> which will unconditionally exit with + exit reason <c>killed</c>.</p> + </desc> + </func> + <func> + <name>float(Number) -> float()</name> + <fsummary>Convert a number to a float</fsummary> + <type> + <v>Number = number()</v> + </type> + <desc> + <p>Returns a float by converting <c>Number</c> to a float.</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>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> + </note> + </desc> + </func> + <func> + <name>float_to_list(Float) -> string()</name> + <fsummary>Text representation of a float</fsummary> + <type> + <v>Float = float()</v> + </type> + <desc> + <p>Returns a string which corresponds to the text + representation of <c>Float</c>.</p> + <pre> +> <input>float_to_list(7.0).</input> +"7.00000000000000000000e+00"</pre> + </desc> + </func> + <func> + <name>erlang:fun_info(Fun) -> [{Item, Info}]</name> + <fsummary>Information about a fun</fsummary> + <type> + <v>Fun = fun()</v> + <v>Item, Info -- see below</v> + </type> + <desc> + <p>Returns a list containing information about the fun + <c>Fun</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 + 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> + </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 + 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> + </item> + <tag><c>{module, Module}</c></tag> + <item> + <p><c>Module</c> (an atom) is the module name.</p> + <p>If <c>Fun</c> is a local fun, <c>Module</c> is the module + in which the fun is defined.</p> + <p>If <c>Fun</c> is an external fun, <c>Module</c> is the + module that the fun refers to.</p> + </item> + <tag><c>{name, Name}</c></tag> + <item> + <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 + only of informational use. As it is a local function, it + is not possible to call it directly.) + If no code is currently loaded for the fun, <c>[]</c> + will be 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> + </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> + </item> + </taglist> + <p>The following elements will only be 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> + </item> + <tag><c>{index, Index}</c></tag> + <item> + <p><c>Index</c> (an integer) is an index into the module's + 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 + 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.</p> + </item> + <tag><c>{uniq, Uniq}</c></tag> + <item> + <p><c>Uniq</c> (an integer) is a unique value for this fun.</p> + </item> + </taglist> + </desc> + </func> + <func> + <name>erlang:fun_info(Fun, Item) -> {Item, Info}</name> + <fsummary>Information about a fun</fsummary> + <type> + <v>Fun = fun()</v> + <v>Item, Info -- see below</v> + </type> + <desc> + <p>Returns information about <c>Fun</c> as specified by + <c>Item</c>, in the form <c>{Item,Info}</c>.</p> + <p>For any fun, <c>Item</c> can be any of the atoms + <c>module</c>, <c>name</c>, <c>arity</c>, or <c>env</c>.</p> + <p>For a local fun, <c>Item</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="#erlang:fun_info/1">erlang:fun_info/1</seealso>.</p> + </desc> + </func> + <func> + <name>erlang:fun_to_list(Fun) -> string()</name> + <fsummary>Text representation of a fun</fsummary> + <type> + <v>Fun = fun()</v> + </type> + <desc> + <p>Returns a string which corresponds to the text + representation of <c>Fun</c>.</p> + </desc> + </func> + <func> + <name>erlang:function_exported(Module, Function, Arity) -> bool()</name> + <fsummary>Check if a function is exported and loaded</fsummary> + <type> + <v>Module = Function = atom()</v> + <v>Arity = int()</v> + </type> + <desc> + <p>Returns <c>true</c> if the module <c>Module</c> is loaded + and contains an exported function <c>Function/Arity</c>; + otherwise <c>false</c>.</p> + <p>Returns <c>false</c> for any BIF (functions implemented in C + rather than in Erlang).</p> + </desc> + </func> + <func> + <name>garbage_collect() -> true</name> + <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 -- + that the spontaneous garbage collection will occur too late + or not at all. Improper use may seriously degrade system + performance.</p> + <p>Compatibility note: In versions of OTP prior to R7, + the garbage collection took place at the next context switch, + not immediately. To force a context switch after a call to + <c>erlang:garbage_collect()</c>, it was sufficient to make + any function call.</p> + </desc> + </func> + <func> + <name>garbage_collect(Pid) -> bool()</name> + <fsummary>Force an immediate garbage collection of a process</fsummary> + <type> + <v>Pid = pid()</v> + </type> + <desc> + <p>Works like <c>erlang:garbage_collect()</c> but on any + process. The same caveats apply. Returns <c>false</c> if + <c>Pid</c> refers to a dead process; <c>true</c> otherwise.</p> + </desc> + </func> + <func> + <name>get() -> [{Key, Val}]</name> + <fsummary>Return the process dictionary</fsummary> + <type> + <v>Key = Val = term()</v> + </type> + <desc> + <p>Returns the process dictionary as a list of + <c>{Key, Val}</c> tuples.</p> + <pre> +> <input>put(key1, merry),</input> +<input>put(key2, lambs),</input> +<input>put(key3, {are, playing}),</input> +<input>get().</input> +[{key1,merry},{key2,lambs},{key3,{are,playing}}]</pre> + </desc> + </func> + <func> + <name>get(Key) -> Val | undefined</name> + <fsummary>Return a value from the process dictionary</fsummary> + <type> + <v>Key = Val = term()</v> + </type> + <desc> + <p>Returns the value <c>Val</c>associated with <c>Key</c> in + the process dictionary, or <c>undefined</c> if <c>Key</c> + does not exist.</p> + <pre> +> <input>put(key1, merry),</input> +<input>put(key2, lambs),</input> +<input>put({any, [valid, term]}, {are, playing}),</input> +<input>get({any, [valid, term]}).</input> +{are,playing}</pre> + </desc> + </func> + <func> + <name>erlang:get_cookie() -> Cookie | nocookie</name> + <fsummary>Get the magic cookie of the local node</fsummary> + <type> + <v>Cookie = atom()</v> + </type> + <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>get_keys(Val) -> [Key]</name> + <fsummary>Return a list of keys from the process dictionary</fsummary> + <type> + <v>Val = Key = term()</v> + </type> + <desc> + <p>Returns a list of keys which are associated with the value + <c>Val</c> in the process dictionary.</p> + <pre> +> <input>put(mary, {1, 2}),</input> +<input>put(had, {1, 2}),</input> +<input>put(a, {1, 2}),</input> +<input>put(little, {1, 2}),</input> +<input>put(dog, {1, 3}),</input> +<input>put(lamb, {1, 2}),</input> +<input>get_keys({1, 2}).</input> +[mary,had,a,little,lamb]</pre> + </desc> + </func> + <func> + <name>erlang:get_stacktrace() -> [{Module, Function, Arity | Args}]</name> + <fsummary>Get the call stack back-trace of the last exception</fsummary> + <type> + <v>Module = Function = atom()</v> + <v>Arity = int()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>Get the call stack back-trace (<em>stacktrace</em>) of the last + exception in the calling process as a list of + <c>{Module,Function,Arity}</c> tuples. + The <c>Arity</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> + <p>If there has not been any exceptions in a process, the + stacktrace is []. 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 + returns, for example:</p> + <p><c>{'EXIT',{badarg,Stacktrace}} = catch abs(x)</c></p> + <p>See also + <seealso marker="#erlang:error/1">erlang:error/1</seealso> and + <seealso marker="#erlang:error/2">erlang:error/2</seealso>.</p> + </desc> + </func> + <func> + <name>group_leader() -> GroupLeader</name> + <fsummary>Get the group leader for the calling process</fsummary> + <type> + <v>GroupLeader = pid()</v> + </type> + <desc> + <p>Returns the pid of the group leader for the process which + evaluates 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 + 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 + its own group leader and the group leader of all processes.</p> + </desc> + </func> + <func> + <name>group_leader(GroupLeader, Pid) -> true</name> + <fsummary>Set the group leader for a process</fsummary> + <type> + <v>GroupLeader = Pid = pid()</v> + </type> + <desc> + <p>Sets the group leader of <c>Pid</c> to <c>GroupLeader</c>. + Typically, this is used when a processes started from a + certain shell should have another group leader than + <c>init</c>.</p> + <p>See also + <seealso marker="#group_leader/0">group_leader/0</seealso>.</p> + </desc> + </func> + <func> + <name>halt()</name> + <fsummary>Halt the Erlang runtime system and indicate normal exit to the calling environment</fsummary> + <desc> + <p>Halts the Erlang runtime system and indicates normal exit to + the calling environment. Has no return value.</p> + <pre> +> <input>halt().</input> +os_prompt%</pre> + </desc> + </func> + <func> + <name>halt(Status)</name> + <fsummary>Halt the Erlang runtime system</fsummary> + <type> + <v>Status = int()>=0 | string()</v> + </type> + <desc> + <p><c>Status</c> must be a non-negative integer, or a string. + Halts the Erlang runtime system. Has no return value. + If <c>Status</c> is an integer, it is returned as an exit + status of Erlang to the calling environment. + If <c>Status</c> is a string, produces an Erlang crash dump + with <c>String</c> as slogan, and then exits with a non-zero + status code.</p> + <p>Note that on many platforms, only the status codes 0-255 are + supported by the operating system.</p> + </desc> + </func> + <func> + <name>erlang:hash(Term, Range) -> Hash</name> + <fsummary>Hash function (deprecated)</fsummary> + <desc> + <p>Returns a hash value for <c>Term</c> within the range + <c>1..Range</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> + </desc> + </func> + <func> + <name>hd(List) -> term()</name> + <fsummary>Head of a list</fsummary> + <type> + <v>List = [term()]</v> + </type> + <desc> + <p>Returns the head of <c>List</c>, that is, the first element.</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>List</c> is the empty list [].</p> + </desc> + </func> + <func> + <name>erlang:hibernate(Module, Function, Args)</name> + <fsummary>Hibernate a process until a message is sent to it</fsummary> + <type> + <v>Module = Function = atom()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>Puts the calling process into a wait state where its memory + allocation has been reduced as much as possible, which 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>Module:Function</c> with + the arguments given by <c>Args</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> + <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 + is then shrunken to the exact same size as the live data + which 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 + 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 + 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 + when the process wakes up.</p> + </desc> + </func> + <func> + <name>integer_to_list(Integer) -> string()</name> + <fsummary>Text representation of an integer</fsummary> + <type> + <v>Integer = int()</v> + </type> + <desc> + <p>Returns a string which corresponds to the text + representation of <c>Integer</c>.</p> + <pre> +> <input>integer_to_list(77).</input> +"77"</pre> + </desc> + </func> + <func> + <name>erlang:integer_to_list(Integer, Base) -> string()</name> + <fsummary>Text representation of an integer</fsummary> + <type> + <v>Integer = int()</v> + <v>Base = 2..36</v> + </type> + <desc> + <p>Returns a string which corresponds to the text + representation of <c>Integer</c> in base <c>Base</c>.</p> + <pre> +> <input>erlang:integer_to_list(1023, 16).</input> +"3FF"</pre> + </desc> + </func> + <func> + <name>iolist_to_binary(IoListOrBinary) -> binary()</name> + <fsummary>Convert an iolist to a binary</fsummary> + <type> + <v>IoListOrBinary = iolist() | binary()</v> + </type> + <desc> + <p>Returns a binary which is made from the integers and + binaries in <c>IoListOrBinary</c>.</p> + <pre> +> <input>Bin1 = <<1,2,3>>.</input> +<<1,2,3>> +> <input>Bin2 = <<4,5>>.</input> +<<4,5>> +> <input>Bin3 = <<6>>.</input> +<<6>> +> <input>iolist_to_binary([Bin1,1,[2,3,Bin2],4|Bin3]).</input> +<<1,2,3,1,2,3,4,5,4,6>></pre> + </desc> + </func> + <func> + <name>iolist_size(Item) -> int()</name> + <fsummary>Size of an iolist</fsummary> + <type> + <v>Item = iolist() | binary()</v> + </type> + <desc> + <p>Returns an integer which is the size in bytes + of the binary that would be the result of + <c>iolist_to_binary(Item)</c>.</p> + <pre> +> <input>iolist_size([1,2|<<3,4>>]).</input> +4</pre> + </desc> + </func> + <func> + <name>is_alive() -> bool()</name> + <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> + </desc> + </func> + <func> + <name>is_atom(Term) -> bool()</name> + <fsummary>Check whether a term is an atom</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is an atom; + otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>is_binary(Term) -> bool()</name> + <fsummary>Check whether a term is a binary</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a binary; + otherwise returns <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>is_bitstring(Term) -> bool()</name> + <fsummary>Check whether a term is a bitstring</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a bitstring (including a binary); + otherwise returns <c>false</c>.</p> + + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>is_boolean(Term) -> bool()</name> + <fsummary>Check whether a term is a boolean</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</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>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>erlang:is_builtin(Module, Function, Arity) -> bool()</name> + <fsummary>Check if a function is a BIF implemented in C</fsummary> + <type> + <v>Module = Function = atom()</v> + <v>Arity = int()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Module:Function/Arity</c> is + a BIF implemented in C; otherwise returns <c>false</c>. + This BIF is useful for builders of cross reference tools.</p> + </desc> + </func> + <func> + <name>is_float(Term) -> bool()</name> + <fsummary>Check whether a term is a float</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a floating point + number; otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>is_function(Term) -> bool()</name> + <fsummary>Check whether a term is a fun</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a fun; otherwise + returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>is_function(Term, Arity) -> bool()</name> + <fsummary>Check whether a term is a fun with a given arity</fsummary> + <type> + <v>Term = term()</v> + <v>Arity = int()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a fun that can be + applied with <c>Arity</c> number of arguments; otherwise + returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + <warning> + <p>Currently, <c>is_function/2</c> will also return + <c>true</c> if the first argument is a tuple fun (a tuple + containing two atoms). In a future release, tuple funs will + no longer be supported and <c>is_function/2</c> will return + <c>false</c> if given a tuple fun.</p> + </warning> + </desc> + </func> + <func> + <name>is_integer(Term) -> bool()</name> + <fsummary>Check whether a term is an integer</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is an integer; + otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>is_list(Term) -> bool()</name> + <fsummary>Check whether a term is a list</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a list with + zero or more elements; otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>is_number(Term) -> bool()</name> + <fsummary>Check whether a term is a number</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is either an integer or a + floating point number; otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>is_pid(Term) -> bool()</name> + <fsummary>Check whether a term is a pid</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a pid (process + identifier); otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>is_port(Term) -> bool()</name> + <fsummary>Check whether a term is a port</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a port identifier; + otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>is_process_alive(Pid) -> bool()</name> + <fsummary>Check whether a process is alive</fsummary> + <type> + <v>Pid = pid()</v> + </type> + <desc> + <p> + <c>Pid</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> + </desc> + </func> + <func> + <name>is_record(Term, RecordTag) -> bool()</name> + <fsummary>Check whether a term appears to be a record</fsummary> + <type> + <v>Term = term()</v> + <v>RecordTag = atom()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a tuple and its first + element is <c>RecordTag</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>Term</c> is a + tuple, that its first element is <c>RecordTag</c>, and that + the size is correct. However, if the <c>RecordTag</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> + </note> + <p>Allowed in guard tests, if <c>RecordTag</c> is a literal + atom.</p> + </desc> + </func> + <func> + <name>is_record(Term, RecordTag, Size) -> bool()</name> + <fsummary>Check whether a term appears to be a record</fsummary> + <type> + <v>Term = term()</v> + <v>RecordTag = atom()</v> + <v>Size = int()</v> + </type> + <desc> + <p><c>RecordTag</c> must be an atom. Returns <c>true</c> if + <c>Term</c> is a tuple, its first element is <c>RecordTag</c>, + and its size is <c>Size</c>. Otherwise, returns <c>false</c>.</p> + <p>Allowed in guard tests, provided that <c>RecordTag</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> + </note> + </desc> + </func> + <func> + <name>is_reference(Term) -> bool()</name> + <fsummary>Check whether a term is a reference</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a reference; + otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>is_tuple(Term) -> bool()</name> + <fsummary>Check whether a term is a tuple</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns <c>true</c> if <c>Term</c> is a tuple; + otherwise returns <c>false</c>.</p> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>length(List) -> int()</name> + <fsummary>Length of a list</fsummary> + <type> + <v>List = [term()]</v> + </type> + <desc> + <p>Returns the length of <c>List</c>.</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>link(Pid) -> true</name> + <fsummary>Create a link to another process (or port)</fsummary> + <type> + <v>Pid = pid() | port()</v> + </type> + <desc> + <p>Creates a link between the calling process and another + process (or port) <c>Pid</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>Pid</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> + <list type="bulleted"> + <item>If the calling process is not trapping exits, and + checking <c>Pid</c> is cheap -- that is, if <c>Pid</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>Pid</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> + </list> + </desc> + </func> + <func> + <name>list_to_atom(String) -> atom()</name> + <fsummary>Convert from text representation to an atom</fsummary> + <type> + <v>String = string()</v> + </type> + <desc> + <p>Returns the atom whose text representation is <c>String</c>.</p> + <pre> +> <input>list_to_atom("Erlang").</input> +'Erlang'</pre> + </desc> + </func> + <func> + <name>list_to_binary(IoList) -> binary()</name> + <fsummary>Convert a list to a binary</fsummary> + <type> + <v>IoList = iolist()</v> + </type> + <desc> + <p>Returns a binary which is made from the integers and + binaries in <c>IoList</c>.</p> + <pre> +> <input>Bin1 = <<1,2,3>>.</input> +<<1,2,3>> +> <input>Bin2 = <<4,5>>.</input> +<<4,5>> +> <input>Bin3 = <<6>>.</input> +<<6>> +> <input>list_to_binary([Bin1,1,[2,3,Bin2],4|Bin3]).</input> +<<1,2,3,1,2,3,4,5,4,6>></pre> + </desc> + </func> + <func> + <name>list_to_bitstring(BitstringList) -> bitstring()</name> + <fsummary>Convert a list to a bitstring</fsummary> + <type> + <v>BitstringList = [BitstringList | bitstring() | char()]</v> + </type> + <desc> + <p>Returns a bitstring which is made from the integers and + bitstrings in <c>BitstringList</c>. (The last tail in <c>BitstringList</c> + is allowed to be a bitstring.)</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>list_to_binary([Bin1,1,[2,3,Bin2],4|Bin3]).</input> +<<1,2,3,1,2,3,4,5,4,6,7:46>></pre> + </desc> + </func> + <func> + <name>list_to_existing_atom(String) -> atom()</name> + <fsummary>Convert from text representation to an atom</fsummary> + <type> + <v>String = string()</v> + </type> + <desc> + <p>Returns the atom whose text representation is <c>String</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>String</c>.</p> + </desc> + </func> + <func> + <name>list_to_float(String) -> float()</name> + <fsummary>Convert from text representation to a float</fsummary> + <type> + <v>String = string()</v> + </type> + <desc> + <p>Returns the float whose text representation is <c>String</c>.</p> + <pre> +> <input>list_to_float("2.2017764e+0").</input> +2.2017764</pre> + <p>Failure: <c>badarg</c> if <c>String</c> contains a bad + representation of a float.</p> + </desc> + </func> + <func> + <name>list_to_integer(String) -> int()</name> + <fsummary>Convert from text representation to an integer</fsummary> + <type> + <v>String = string()</v> + </type> + <desc> + <p>Returns an integer whose text representation is + <c>String</c>.</p> + <pre> +> <input>list_to_integer("123").</input> +123</pre> + <p>Failure: <c>badarg</c> if <c>String</c> contains a bad + representation of an integer.</p> + </desc> + </func> + <func> + <name>erlang:list_to_integer(String, Base) -> int()</name> + <fsummary>Convert from text representation to an integer</fsummary> + <type> + <v>String = string()</v> + <v>Base = 2..36</v> + </type> + <desc> + <p>Returns an integer whose text representation in base + <c>Base</c> is <c>String</c>.</p> + <pre> +> <input>erlang:list_to_integer("3FF", 16).</input> +1023</pre> + <p>Failure: <c>badarg</c> if <c>String</c> contains a bad + representation of an integer.</p> + </desc> + </func> + <func> + <name>list_to_pid(String) -> pid()</name> + <fsummary>Convert from text representation to a pid</fsummary> + <type> + <v>String = string()</v> + </type> + <desc> + <p>Returns a pid whose text representation is <c>String</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> + <pre> +> <input>list_to_pid("<0.4.1>").</input> +<0.4.1></pre> + <p>Failure: <c>badarg</c> if <c>String</c> contains a bad + representation of a pid.</p> + </desc> + </func> + <func> + <name>list_to_tuple(List) -> tuple()</name> + <fsummary>Convert a list to a tuple</fsummary> + <type> + <v>List = [term()]</v> + </type> + <desc> + <p>Returns a tuple which corresponds to <c>List</c>. <c>List</c> + can contain any Erlang terms.</p> + <pre> +> <input>list_to_tuple([share, ['Ericsson_B', 163]]).</input> +{share, ['Ericsson_B', 163]}</pre> + </desc> + </func> + <func> + <name>load_module(Module, Binary) -> {module, Module} | {error, Reason}</name> + <fsummary>Load object code for a module</fsummary> + <type> + <v>Module = atom()</v> + <v>Binary = binary()</v> + <v>Reason = badfile | not_purged | badfile</v> + </type> + <desc> + <p>If <c>Binary</c> contains the object code for the module + <c>Module</c>, this BIF loads that object code. Also, if + the code for the module <c>Module</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, Module}</c>, or <c>{error, Reason}</c> if loading + fails. <c>Reason</c> is one of the following:</p> + <taglist> + <tag><c>badfile</c></tag> + <item> + <p>The object code in <c>Binary</c> has an incorrect format.</p> + </item> + <tag><c>not_purged</c></tag> + <item> + <p><c>Binary</c> contains a module which cannot be loaded + because old code for this module already exists.</p> + </item> + <tag><c>badfile</c></tag> + <item> + <p>The object code contains code for another module than + <c>Module</c></p> + </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> + </warning> + </desc> + </func> + <func> + <name>erlang:load_nif(Path, LoadInfo) -> ok | {error, Reason, Text}</name> + <fsummary>Load NIF library</fsummary> + <type> + <v>Path = string()</v> + <v>LoadInfo = term()</v> + <v>Reason = load_failed | bad_lib | load | reload | + upgrade | old_code</v> + <v>Text = string()</v> + </type> + <desc> + <warning> + <p>This BIF is currently introduced as an experimental + feature. The interface may be changed in any way in future + releases.</p> + </warning> + <p>Loads and links a dynamic library containing native + implemented functions (NIFs) for a module. <c>Path</c> is a + file path to the sharable object/dynamic library file minus + the OS-dependant file extension (.so for Unix and .ddl for + Windows). See <seealso marker="erl_nif">erl_nif</seealso> + on how to implement a NIF library.</p> + <p><c>LoadInfo</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> + <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,Reason,Text}</c> + if loading fails. <c>Reason</c> is one of the atoms below, + while <c>Text</c> is a human readable string that may give + some 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> + <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> + <tag><c>load | reload | upgrade</c></tag> + <item> + <p>The corresponding library callback was not successful.</p> + </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> + </taglist> + </desc> + </func> + <func> + <name>erlang:loaded() -> [Module]</name> + <fsummary>List of all loaded modules</fsummary> + <type> + <v>Module = atom()</v> + </type> + <desc> + <p>Returns a list of all loaded Erlang modules (current and/or + old code), including preloaded modules.</p> + <p>See also <seealso marker="kernel:code">code(3)</seealso>.</p> + </desc> + </func> + <func> + <name>erlang:localtime() -> {Date, Time}</name> + <fsummary>Current local date and time</fsummary> + <type> + <v>Date = {Year, Month, Day}</v> + <v>Time = {Hour, Minute, Second}</v> + <v> Year = Month = Day = Hour = Minute = Second = int()</v> + </type> + <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> + <pre> +> <input>erlang:localtime().</input> +{{1996,11,6},{14,45,17}}</pre> + </desc> + </func> + <func> + <name>erlang:localtime_to_universaltime({Date1, Time1}) -> {Date2, Time2}</name> + <fsummary>Convert from local to Universal Time Coordinated (UTC) date and time</fsummary> + <type> + <v>Date1 = Date2 = {Year, Month, Day}</v> + <v>Time1 = Time2 = {Hour, Minute, Second}</v> + <v> Year = Month = Day = Hour = Minute = Second = int()</v> + </type> + <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>{Date1, Time1}</c> is returned.</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>Date1</c> or <c>Time1</c> do + not denote a valid date or time.</p> + </desc> + </func> + <func> + <name>erlang:localtime_to_universaltime({Date1, Time1}, IsDst) -> {Date2, Time2}</name> + <fsummary>Convert from local to Universal Time Coordinated (UTC) date and time</fsummary> + <type> + <v>Date1 = Date2 = {Year, Month, Day}</v> + <v>Time1 = Time2 = {Hour, Minute, Second}</v> + <v> Year = Month = Day = Hour = Minute = Second = int()</v> + <v>IsDst = true | false | undefined</v> + </type> + <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>IsDst == true</c> the <c>{Date1, Time1}</c> is during + daylight saving time, if <c>IsDst == false</c> it is not, + and if <c>IsDst == undefined</c> the underlying OS may + guess, which is the same as calling + <c>erlang:localtime_to_universaltime({Date1, Time1})</c>.</p> + <pre> +> <input>erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}, true).</input> +{{1996,11,6},{12,45,17}} +> <input>erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}, false).</input> +{{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>Date1</c> or <c>Time1</c> do + not denote a valid date or time.</p> + </desc> + </func> + <func> + <name>make_ref() -> ref()</name> + <fsummary>Return an almost 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> + </desc> + </func> + <func> + <name>erlang:make_tuple(Arity, InitialValue) -> tuple()</name> + <fsummary>Create a new tuple of a given arity</fsummary> + <type> + <v>Arity = int()</v> + <v>InitialValue = term()</v> + </type> + <desc> + <p>Returns a new tuple of the given <c>Arity</c>, where all + elements are <c>InitialValue</c>.</p> + <pre> +> <input>erlang:make_tuple(4, []).</input> +{[],[],[],[]}</pre> + </desc> + </func> + <func> + <name>erlang:make_tuple(Arity, Default, InitList) -> tuple()</name> + <fsummary>Create a new tuple with given arity and contents</fsummary> + <type> + <v>Arity = int()</v> + <v>Default = term()</v> + <v>InitList = [{Position,term()}]</v> + <v>Position = integer()</v> + </type> + <desc> + <p><c>erlang:make_tuple</c> first creates a tuple of size <c>Arity</c> + where each element has the value <c>Default</c>. It then fills + in values from <c>InitList</c>. Each list element in <c>InitList</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> + <pre> +> <input>erlang:make_tuple(5, [], [{2,ignored},{5,zz},{2,aa}]).</input> +{{[],aa,[],[],zz}</pre> + </desc> + </func> + <func> + <name>erlang:max(Term1, Term2) -> Maximum</name> + <fsummary>Return the largest of two term</fsummary> + <type> + <v>Term1 = Term2 = Maximum = term()</v> + </type> + <desc> + <p>Return the largest of <c>Term1</c> and <c>Term2</c>; + if the terms compares equal, <c>Term1</c> will be returned.</p> + </desc> + </func> + <func> + <name>erlang:md5(Data) -> Digest</name> + <fsummary>Compute an MD5 message digest</fsummary> + <type> + <v>Data = iodata()</v> + <v>Digest = binary()</v> + </type> + <desc> + <p>Computes an <c>MD5</c> message digest from <c>Data</c>, where + the length of the digest is 128 bits (16 bytes). <c>Data</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> + </desc> + </func> + <func> + <name>erlang:md5_final(Context) -> Digest</name> + <fsummary>Finish the update of an MD5 context and return the computed MD5 message digest</fsummary> + <type> + <v>Context = Digest = binary()</v> + </type> + <desc> + <p>Finishes the update of an MD5 <c>Context</c> and returns + the computed <c>MD5</c> message digest.</p> + </desc> + </func> + <func> + <name>erlang:md5_init() -> Context</name> + <fsummary>Create an MD5 context</fsummary> + <type> + <v>Context = binary()</v> + </type> + <desc> + <p>Creates an MD5 context, to be used in subsequent calls to + <c>md5_update/2</c>.</p> + </desc> + </func> + <func> + <name>erlang:md5_update(Context, Data) -> NewContext</name> + <fsummary>Update an MD5 context with data, and return a new context</fsummary> + <type> + <v>Data = iodata()</v> + <v>Context = NewContext = binary()</v> + </type> + <desc> + <p>Updates an MD5 <c>Context</c> with <c>Data</c>, and returns + a <c>NewContext</c>.</p> + </desc> + </func> + <func> + <name>erlang:memory() -> [{Type, Size}]</name> + <fsummary>Information about dynamically allocated memory</fsummary> + <type> + <v>Type, Size -- see below</v> + </type> + <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>Type</c>is an atom describing memory type. The second + element <c>Size</c>is memory size in bytes. A description of + each memory type follows:</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> + and <c>system</c>.</p> + </item> + <tag><c>processes</c></tag> + <item> + <p>The total amount of memory currently allocated by + 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 + <c>processes</c> memory.</p> + </item> + <tag><c>system</c></tag> + <item> + <p>The total amount of memory currently allocated by + 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> + </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 + <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 + <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> + </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> + </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 + <c>system</c> memory.</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> + <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> + </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> + <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 + 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 + 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 + 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> + </note> + <p>The different values has the following relation to each + other. Values beginning with an uppercase letter is not part + of the result.</p> + <code type="none"> +\011total = processes + system +\011processes = processes_used + ProcessesNotUsed +\011system = atom + binary + code + ets + OtherSystem +\011atom = atom_used + AtomNotUsed + +\011RealTotal = processes + RealSystem +\011RealSystem = system + MissedSystem</code> + <p>More tuples in the returned list may be added in the future.</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 + 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 + 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> + </desc> + </func> + <func> + <name>erlang:memory(Type | [Type]) -> Size | [{Type, Size}]</name> + <fsummary>Information about dynamically allocated memory</fsummary> + <type> + <v>Type, Size -- see below</v> + </type> + <desc> + <p>Returns the memory size in bytes allocated for memory of + type <c>Type</c>. The argument can also be given as a list + of <c>Type</c> atoms, in which case a corresponding list of + <c>{Type, Size}</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> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item> + If <c>Type</c> is not one of the memory types listed in the + documentation of + <seealso marker="#erlang:memory/0">erlang:memory/0</seealso>. + </item> + <tag><c>badarg</c></tag> + <item> + If <c>maximum</c> is passed as <c>Type</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> + <p>See also + <seealso marker="#erlang:memory/0">erlang:memory/0</seealso>.</p> + </desc> + </func> + <func> + <name>erlang:min(Term1, Term2) -> Minimum</name> + <fsummary>Return the smallest of two term</fsummary> + <type> + <v>Term1 = Term2 = Minimum = term()</v> + </type> + <desc> + <p>Return the smallest of <c>Term1</c> and <c>Term2</c>; + if the terms compare equal, <c>Term1</c> will be returned.</p> + </desc> + </func> + <func> + <name>module_loaded(Module) -> bool()</name> + <fsummary>Check if a module is loaded</fsummary> + <type> + <v>Module = atom()</v> + </type> + <desc> + <p>Returns <c>true</c> if the module <c>Module</c> is loaded, + otherwise returns <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> + </warning> + </desc> + </func> + <func> + <name>erlang:monitor(Type, Item) -> MonitorRef</name> + <fsummary>Start monitoring</fsummary> + <type> + <v>Type = process</v> + <v>Item = pid() | {RegName, Node} | RegName</v> + <v> RegName = atom()</v> + <v> Node = node()</v> + <v>MonitorRef = reference()</v> + </type> + <desc> + <p>The calling process starts monitoring <c>Item</c> which is + an object of type <c>Type</c>.</p> + <p>Currently only processes can be monitored, i.e. the only + allowed <c>Type</c> is <c>process</c>, but other types may be + allowed in the future.</p> + <p><c>Item</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>erlang: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>Item</c> dies, if <c>Item</c> does not exist, + or if the connection is lost to the node which <c>Item</c> + resides on. A <c>'DOWN'</c> message 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> + <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>Item</c> was + specified as a pid.</item> + <item><c>{RegName, Node}</c>, if <c>Item</c> was specified as + <c>{RegName, Node}</c>.</item> + <item><c>{RegName, Node}</c>, if <c>Item</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> + </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>Node</c>).</p> + </item> + </taglist> + <note> + <p>If/when <c>erlang: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="#erlang:demonitor/1">erlang: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>erlang:monitor/2</c> for the same + <c>Item</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> + </note> + </desc> + </func> + <func> + <name>monitor_node(Node, Flag) -> true</name> + <fsummary>Monitor the status of a node</fsummary> + <type> + <v>Node = node()</v> + <v>Flag = bool()</v> + </type> + <desc> + <p>Monitors the status of the node <c>Node</c>. If <c>Flag</c> + is <c>true</c>, monitoring is turned on; if <c>Flag</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>Node</c> is not an error; it results in as many, + completely independent, monitorings.</p> + <p>If <c>Node</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>Node</c> terminates, two <c>nodedown</c> messages are + delivered to the process. If there is no connection to + <c>Node</c>, there will be an attempt 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> + <p>Failure: <c>badarg</c>if the local node is not alive.</p> + </desc> + </func> + <func> + <name>erlang:monitor_node(Node, Flag, Options) -> true</name> + <fsummary>Monitor the status of a node</fsummary> + <type> + <v>Node = node()</v> + <v>Flag = bool()</v> + <v>Options = [Option]</v> + <v>Option = allow_passive_connect</v> + </type> + <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, + 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> + <note> + <p>The <c>allow_passive_connect</c> option is used + internally and is seldom needed in applications where the + network topology and the kernel options in effect is 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>node() -> Node</name> + <fsummary>Name of the local node</fsummary> + <type> + <v>Node = node()</v> + </type> + <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>node(Arg) -> Node</name> + <fsummary>At which node is a pid, port or reference located</fsummary> + <type> + <v>Arg = pid() | port() | ref()</v> + <v>Node = node()</v> + </type> + <desc> + <p>Returns the node where <c>Arg</c> is located. <c>Arg</c> can + be a pid, 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>nodes() -> Nodes</name> + <fsummary>All visible nodes in the system</fsummary> + <type> + <v>Nodes = [node()]</v> + </type> + <desc> + <p>Returns a list of all visible nodes in the system, excluding + the local node. Same as <c>nodes(visible)</c>.</p> + </desc> + </func> + <func> + <name>nodes(Arg | [Arg]) -> Nodes</name> + <fsummary>All nodes of a certain type in the system</fsummary> + <type> + <v>Arg = visible | hidden | connected | this | known</v> + <v>Nodes = [node()]</v> + </type> + <desc> + <p>Returns a list of nodes according to argument given. + The result returned when the argument is a list, is the list + of nodes satisfying the disjunction(s) of the list elements.</p> + <p><c>Arg</c> can be any of the following:</p> + <taglist> + <tag><c>visible</c></tag> + <item> + <p>Nodes connected to this node through normal connections.</p> + </item> + <tag><c>hidden</c></tag> + <item> + <p>Nodes connected to this node through hidden connections.</p> + </item> + <tag><c>connected</c></tag> + <item> + <p>All nodes connected to this node.</p> + </item> + <tag><c>this</c></tag> + <item> + <p>This node.</p> + </item> + <tag><c>known</c></tag> + <item> + <p>Nodes which are known to this node, i.e., connected, + previously connected, etc.</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>Arg</c> the empty list [] is returned.</p> + </desc> + </func> + <func> + <name>now() -> {MegaSecs, Secs, MicroSecs}</name> + <fsummary>Elapsed time since 00:00 GMT</fsummary> + <type> + <v>MegaSecs = Secs = MicroSecs = int()</v> + </type> + <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 + continuously increasing values. Hence, the return value from + <c>now()</c> can be used to generate unique time-stamps. It + can only be used to check the local time of day if + the time-zone info of the underlying operating system is + properly configured.</p> + </desc> + </func> + <func> + <name>open_port(PortName, PortSettings) -> port()</name> + <fsummary>Open a port</fsummary> + <type> + <v>PortName = {spawn, Command} | {spawn_driver, Command} | {spawn_executable, Command} | {fd, In, Out}</v> + <v> Command = string()</v> + <v> In = Out = int()</v> + <v>PortSettings = [Opt]</v> + <v> Opt = {packet, N} | stream | {line, L} | {cd, Dir} | {env, Env} | {args, [ string() ]} | {arg0, string()} | exit_status | use_stdio | nouse_stdio | stderr_to_stdout | in | out | binary | eof</v> + <v> N = 1 | 2 | 4</v> + <v> L = int()</v> + <v> Dir = string()</v> + <v> Env = [{Name, Val}]</v> + <v> Name = string()</v> + <v> Val = string() | false</v> + </type> + <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. <c>PortName</c> is one of the following:</p> + <taglist> + <tag><c>{spawn, Command}</c></tag> + <item> + <p>Starts an external program. <c>Command</c> is the name + of the external program which will be run. <c>Command</c> + runs outside the Erlang work space unless an Erlang + driver with the name <c>Command</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 + 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 och 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, Command} instead if spaces in executable + file names is desired.</p> + </item> + <tag><c>{spawn_driver, Command}</c></tag> + <item> + <p>Works like <c>{spawn, Command}</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, Command}</c></tag> + <item> + + <p>Works like <c>{spawn, Command}</c>, but only runs + external executables. The <c>Command</c> in it's 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>PortSettings</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>Command</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>eaccess</c> is raised when the given file is not + executable.</p> + </item> + <tag><c>{fd, In, Out}</c></tag> + <item> + <p>Allows an Erlang process to access any currently opened + file descriptors used by Erlang. The file descriptor + <c>In</c> can be used for standard input, and the file + descriptor <c>Out</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> + </item> + </taglist> + <p><c>PortSettings</c> is a list of settings for the port. + Valid settings are:</p> + <taglist> + <tag><c>{packet, N}</c></tag> + <item> + <p>Messages are preceded by their length, sent in <c>N</c> + bytes, with the most significant byte first. Valid values + for <c>N</c> are 1, 2, or 4.</p> + </item> + <tag><c>stream</c></tag> + <item> + <p>Output messages are sent without packet lengths. A + user-defined protocol must be used between the Erlang + process and the external object.</p> + </item> + <tag><c>{line, L}</c></tag> + <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 + data delivered (without the newline sequence).</p> + <p><c>L</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 + 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, + lines are delivered with <c>Flag</c> set to <c>eol</c>.</p> + <p>The <c>{packet, N}</c> and <c>{line, L}</c> settings are + mutually exclusive.</p> + </item> + <tag><c>{cd, Dir}</c></tag> + <item> + <p>This is only valid for <c>{spawn, Command}</c> and + <c>{spawn_executable, Command}</c>. + The external program starts using <c>Dir</c> as its + working directory. <c>Dir</c> must be a string. Not + available on VxWorks.</p> + </item> + <tag><c>{env, Env}</c></tag> + <item> + <p>This is only valid for <c>{spawn, Command}</c> and + <c>{spawn_executable, Command}</c>. + The environment of the started process is extended using + the environment specifications in <c>Env</c>.</p> + <p><c>Env</c> should be a list of tuples <c>{Name, Val}</c>, + where <c>Name</c> is the name of an environment variable, + and <c>Val</c> is the value it is to have in the spawned + port process. Both <c>Name</c> and <c>Val</c> must be + strings. The one exception is <c>Val</c> being the atom + <c>false</c> (in analogy with <c>os:getenv/1</c>), which + removes the environment variable. Not available on + VxWorks.</p> + </item> + <tag><c>{args, [ string() ]}</c></tag> + <item> + + <p>This option is only valid for <c>{spawn_executable, Command}</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()}</c></tag> + <item> + + <p>This option is only valid for <c>{spawn_executable, Command}</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>exit_status</c></tag> + <item> + <p>This is only valid for <c>{spawn, Command}</c> where + <c>Command</c> refers to an external program, and for + <c>{spawn_executable, Command}</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> + </item> + <tag><c>use_stdio</c></tag> + <item> + <p>This is only valid for <c>{spawn, Command}</c> and + <c>{spawn_executable, Command}</c>. It + allows the standard input and output (file descriptors 0 + 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 + 3 and 4 for communication with Erlang.</p> + </item> + <tag><c>stderr_to_stdout</c></tag> + <item> + <p>Affects ports to external programs. The executed program + gets its standard error file redirected to its standard + output file. <c>stderr_to_stdout</c> and + <c>nouse_stdio</c> are mutually exclusive.</p> + </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 it's 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> + <p>The port can only be used for input.</p> + </item> + <tag><c>out</c></tag> + <item> + <p>The port can only be used for output.</p> + </item> + <tag><c>binary</c></tag> + <item> + <p>All IO from the port are 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 + 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> + </item> + </taglist> + <p>The default is <c>stream</c> for all types of port 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> + <taglist> + <tag><c>badarg</c></tag> + <item> + <p>Bad input arguments to <c>open_port</c>.</p> + </item> + <tag><c>system_limit</c></tag> + <item> + <p>All available ports in the Erlang emulator are in use.</p> + </item> + <tag><c>enomem</c></tag> + <item> + <p>There was not enough memory to create the port.</p> + </item> + <tag><c>eagain</c></tag> + <item> + <p>There are no more available operating system processes.</p> + </item> + <tag><c>enametoolong</c></tag> + <item> + <p>The external command given was too long.</p> + </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> + <tag><c>enfile</c></tag> + <item> + <p>The file table is full (for the entire operating system).</p> + </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> + <tag><c>enoent</c></tag> + <item> + <p>The <c>Command</c> given in <c>{spawn_executable, Command}</c> does not point out an existing file.</p> + </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>, + 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><marker id="ERL_MAX_PORTS"></marker> + The maximum number of ports that can be open at the same + time is 1024 by default, but can be configured by + the environment variable <c>ERL_MAX_PORTS</c>.</p> + </desc> + </func> + <func> + <name>erlang:phash(Term, Range) -> Hash</name> + <fsummary>Portable hash function</fsummary> + <type> + <v>Term = term()</v> + <v>Range = 1..2^32</v> + <v>Hash = 1..Range</v> + </type> + <desc> + <p>Portable hash function that will give 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>Term</c> within the range <c>1..Range</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> + </desc> + </func> + <func> + <name>erlang:phash2(Term [, Range]) -> Hash</name> + <fsummary>Portable hash function</fsummary> + <type> + <v>Term = term()</v> + <v>Range = 1..2^32</v> + <v>Hash = 0..Range-1</v> + </type> + <desc> + <p>Portable hash function that will give 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>Term</c> within the range <c>0..Range-1</c>. When called + without the <c>Range</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 + 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..Range-1</c> is different from + the range of <c>phash/2</c> (<c>1..Range</c>).</p> + </desc> + </func> + <func> + <name>pid_to_list(Pid) -> string()</name> + <fsummary>Text representation of a pid</fsummary> + <type> + <v>Pid = pid()</v> + </type> + <desc> + <p>Returns a string which corresponds to the text + representation of <c>Pid</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>port_close(Port) -> true</name> + <fsummary>Close an open port</fsummary> + <type> + <v>Port = port() | atom()</v> + </type> + <desc> + <p>Closes an open port. Roughly the same as + <c>Port ! {self(), close}</c> except for the error behaviour + (see below), 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).</p> + <p>For comparison: <c>Port ! {self(), close}</c> fails with + <c>badarg</c> if <c>Port</c> cannot be sent to (i.e., + <c>Port</c> refers neither to a port nor to a process). If + <c>Port</c> is a closed port nothing happens. If <c>Port</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>Port ! {PortOwner, close}</c> just as if it itself was + the port owner, but the reply always goes to the port owner.</p> + <p>In short: <c>port_close(Port)</c> has a cleaner and more + logical behaviour than <c>Port ! {self(), close}</c>.</p> + <p>Failure: <c>badarg</c> if <c>Port</c> is not an open port or + the registered name of an open port.</p> + </desc> + </func> + <func> + <name>port_command(Port, Data) -> true</name> + <fsummary>Send data to a port</fsummary> + <type> + <v>Port = port() | atom()</v> + <v>Data = iodata()</v> + </type> + <desc> + <p>Sends data to a port. Same as + <c>Port ! {self(), {command, Data}}</c> except for the error + behaviour (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>Port ! {self(), {command, Data}}</c> + fails with <c>badarg</c> if <c>Port</c> cannot be sent to + (i.e., <c>Port</c> refers neither to a port nor to a process). + If <c>Port</c> is a closed port the data message disappears + without a sound. If <c>Port</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>Data</c> is not a valid IO list.</p> + <p>Note that any process can send to a port using + <c>Port ! {PortOwner, {command, Data}}</c> just as if it + itself was the port owner.</p> + <p>In short: <c>port_command(Port, Data)</c> has a cleaner and + more logical behaviour than + <c>Port ! {self(), {command, Data}}</c>.</p> + <p>If the port is busy, the calling process will be suspended + until the port is not busy anymore.</p> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item> + If <c>Port</c> is not an open port or the registered name + of an open port. + </item> + <tag><c>badarg</c></tag> + <item> + If <c>Data</c> is not a valid io list. + </item> + </taglist> + </desc> + </func> + <func> + <name>erlang:port_command(Port, Data, OptionList) -> true|false</name> + <fsummary>Send data to a port</fsummary> + <type> + <v>Port = port() | atom()</v> + <v>Data = iodata()</v> + <v>OptionList = [Option]</v> + <v>Option = force</v> + <v>Option = nosuspend</v> + </type> + <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>Option</c>s are valid:</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> + <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> + </taglist> + <note> + <p>More options may be added in the future.</p> + </note> + <note> + <p><c>erlang:port_command/3</c> is currently not auto imported, but + it is planned to be auto imported in OTP R14.</p> + </note> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item> + If <c>Port</c> is not an open port or the registered name + of an open port. + </item> + <tag><c>badarg</c></tag> + <item> + If <c>Data</c> is not a valid io list. + </item> + <tag><c>badarg</c></tag> + <item> + If <c>OptionList</c> is not a valid 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> + </desc> + </func> + <func> + <name>port_connect(Port, Pid) -> true</name> + <fsummary>Set the owner of a port</fsummary> + <type> + <v>Port = port() | atom()</v> + <v>Pid = pid()</v> + </type> + <desc> + <p>Sets the port owner (the connected port) to <c>Pid</c>. + Roughly the same as <c>Port ! {self(), {connect, Pid}}</c> + except for the following:</p> + <list type="bulleted"> + <item> + <p>The error behavior differs, see below.</p> + </item> + <item> + <p>The port does <em>not</em> reply with + <c>{Port,connected}</c>.</p> + </item> + <item> + <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 + set the port owner to be any process with + <c>port_connect/2</c>.</p> + <p>For comparison: <c>Port ! {self(), {connect, Pid}}</c> fails + with <c>badarg</c> if <c>Port</c> cannot be sent to (i.e., + <c>Port</c> refers neither to a port nor to a process). If + <c>Port</c> is a closed port nothing happens. If <c>Port</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>Port</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>Pid</c> is not an + existing local pid.</p> + <p>Note that any process can set the port owner using + <c>Port ! {PortOwner, {connect, Pid}}</c> just as if it + itself was the port owner, but the reply always goes to + the port owner.</p> + <p>In short: <c>port_connect(Port, Pid)</c> has a cleaner and + more logical behaviour than + <c>Port ! {self(),{connect,Pid}}</c>.</p> + <p>Failure: <c>badarg</c> if <c>Port</c> is not an open port + or the registered name of an open port, or if <c>Pid</c> is + not an existing local pid.</p> + </desc> + </func> + <func> + <name>port_control(Port, Operation, Data) -> Res</name> + <fsummary>Perform a synchronous control operation on a port</fsummary> + <type> + <v>Port = port() | atom()</v> + <v>Operation = int()</v> + <v>Data = Res = iodata()</v> + </type> + <desc> + <p>Performs a synchronous control operation on a port. + The meaning of <c>Operation</c> and <c>Data</c> depends on + the port, i.e., 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 + 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>Port</c> is not an open port or + the registered name of an open port, if <c>Operation</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>Operation</c> or <c>Data</c>).</p> + </desc> + </func> + <func> + <name>erlang:port_call(Port, Operation, Data) -> term()</name> + <fsummary>Synchronous call to a port with term data</fsummary> + <type> + <v>Port = port() | atom()</v> + <v>Operation = int()</v> + <v>Data = term()</v> + </type> + <desc> + <p>Performs a synchronous call to a port. The meaning of + <c>Operation</c> and <c>Data</c> depends on the port, i.e., + on the port driver. Not all port drivers support this feature.</p> + <p><c>Port</c> is a port identifier, referring to a driver.</p> + <p><c>Operation</c> is an integer, which is passed on to + the driver.</p> + <p><c>Data</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>Failure: <c>badarg</c> if <c>Port</c> is not an open port or + the registered name of an open port, if <c>Operation</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>Operation</c> or <c>Data</c>).</p> + </desc> + </func> + <func> + <name>erlang:port_info(Port) -> [{Item, Info}] | undefined</name> + <fsummary>Information about a port</fsummary> + <type> + <v>Port = port() | atom()</v> + <v>Item, Info -- see below</v> + </type> + <desc> + <p>Returns a list containing tuples with information about + the <c>Port</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.</p> + <taglist> + <tag><c>{registered_name, RegName}</c></tag> + <item> + <p><c>RegName</c> (an atom) is the registered name of + the port. If the port has no registered name, this tuple + is not present in the list.</p> + </item> + <tag><c>{id, Index}</c></tag> + <item> + <p><c>Index</c> (an integer) is the internal index of the + port. This index may be used to separate ports.</p> + </item> + <tag><c>{connected, Pid}</c></tag> + <item> + <p><c>Pid</c> is the process connected to the port.</p> + </item> + <tag><c>{links, Pids}</c></tag> + <item> + <p><c>Pids</c> is a list of pids to which processes the + port is linked.</p> + </item> + <tag><c>{name, String}</c></tag> + <item> + <p><c>String</c> is the command name set by + <c>open_port</c>.</p> + </item> + <tag><c>{input, Bytes}</c></tag> + <item> + <p><c>Bytes</c> is the total number of bytes read from + the port.</p> + </item> + <tag><c>{output, Bytes}</c></tag> + <item> + <p><c>Bytes</c> is the total number of bytes written to + the port.</p> + </item> + </taglist> + <p>Failure: <c>badarg</c> if <c>Port</c> is not a local port.</p> + </desc> + </func> + <func> + <name>erlang:port_info(Port, Item) -> {Item, Info} | undefined | []</name> + <fsummary>Information about a port</fsummary> + <type> + <v>Port = port() | atom()</v> + <v>Item, Info -- see below</v> + </type> + <desc> + <p>Returns information about <c>Port</c> as specified + by <c>Item</c>, or <c>undefined</c> if the port is not open. + Also, if <c>Item == registered_name</c> and the port has no + registered name, [] is returned.</p> + <p>For valid values of <c>Item</c>, and corresponding + values of <c>Info</c>, see + <seealso marker="#erlang:port_info/1">erlang:port_info/1</seealso>.</p> + <p>Failure: <c>badarg</c> if <c>Port</c> is not a local port.</p> + </desc> + </func> + <func> + <name>erlang:port_to_list(Port) -> string()</name> + <fsummary>Text representation of a port identifier</fsummary> + <type> + <v>Port = port()</v> + </type> + <desc> + <p>Returns a string which corresponds to the text + representation of the port identifier <c>Port</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>erlang:ports() -> [port()]</name> + <fsummary>All open ports</fsummary> + <desc> + <p>Returns a list of all ports on the local node.</p> + </desc> + </func> + <func> + <name>pre_loaded() -> [Module]</name> + <fsummary>List of all pre-loaded modules</fsummary> + <type> + <v>Module = atom()</v> + </type> + <desc> + <p>Returns a list of Erlang modules which are pre-loaded 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> + </desc> + </func> + <func> + <name>erlang:process_display(Pid, Type) -> void()</name> + <fsummary>Write information about a local process on standard error</fsummary> + <type> + <v>Pid = pid()</v> + <v>Type = backtrace</v> + </type> + <desc> + <p>Writes information about the local process <c>Pid</c> on + standard error. The currently allowed value for the atom + <c>Type</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>process_flag(Flag, Value) -> OldValue</name> + <fsummary>Set process flags for the calling process</fsummary> + <type> + <v>Flag, Value, OldValue -- see below</v> + </type> + <desc> + <p>Sets certain flags for the process which calls this + function. Returns the old value of the flag.</p> + <taglist> + <tag><c>process_flag(trap_exit, Boolean)</c></tag> + <item> + <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 + 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> + <p>See also <seealso marker="#exit/2">exit/2</seealso>.</p> + </item> + <tag><c>process_flag(error_handler, Module)</c></tag> + <item> + <p>This is 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 + operation of the error handling module.</p> + </item> + <tag><c>process_flag(min_heap_size, MinHeapSize)</c></tag> + <item> + <p>This changes the minimum heap size for the calling + process.</p> + </item> + <tag><c>process_flag(priority, Level)</c></tag> + <item> + <marker id="process_flag_priority"></marker> + <p>This sets the process priority. <c>Level</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. + </p> + <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> + 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 + 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> + <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 + <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> + <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> + </item> + + <tag><c>process_flag(save_calls, N)</c></tag> + <item> + <p>When there are runnable processes on priority <c>max</c> + 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><c>N</c> must be an integer in the interval 0..10000. + If <c>N</c> > 0, call saving is made active for the + process, which means that information about the <c>N</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, + 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> + </item> + <tag><c>process_flag(sensitive, Boolean)</c></tag> + <item> + <p>Set or clear the <c>sensitive</c> flag 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 + 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> + <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> + <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> + </item> + </taglist> + </desc> + </func> + <func> + <name>process_flag(Pid, Flag, Value) -> OldValue</name> + <fsummary>Set process flags for a process</fsummary> + <type> + <v>Pid = pid()</v> + <v>Flag, Value, OldValue -- see below</v> + </type> + <desc> + <p>Sets certain flags for the process <c>Pid</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 + <c>Flag</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>Pid</c> is not a local process.</p> + </desc> + </func> + <func> + <name>process_info(Pid) -> InfoResult</name> + <fsummary>Information about a process</fsummary> + <type> + <v>Pid = pid()</v> + <v>Item = atom()</v> + <v>Info = term()</v> + <v>InfoTuple = {Item, Info}</v> + <v>InfoTupleList = [InfoTuple]</v> + <v>InfoResult = InfoTupleList | undefined</v> + </type> + <desc> + <p>Returns a list containing <c>InfoTuple</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>InfoTuple</c>s is not defined, nor + are all the <c>InfoTuple</c>s mandatory. The <c>InfoTuple</c>s + part of the result may be changed without prior notice. + Currently <c>InfoTuple</c>s with the following <c>Item</c>s + 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>Pid</c> has a registered name + also an <c>InfoTuple</c> with <c>Item == registered_name</c> + will appear. + </p> + <p>See <seealso marker="#process_info/2">process_info/2</seealso> + for information about specific <c>InfoTuple</c>s.</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> + </warning> + <p>Failure: <c>badarg</c> if <c>Pid</c> is not a local process.</p> + </desc> + </func> + <func> + <name>process_info(Pid, ItemSpec) -> InfoResult</name> + <fsummary>Information about a process</fsummary> + <type> + <v>Pid = pid()</v> + <v>Item = atom()</v> + <v>Info = term()</v> + <v>ItemList = [Item]</v> + <v>ItemSpec = Item | ItemList</v> + <v>InfoTuple = {Item, Info}</v> + <v>InfoTupleList = [InfoTuple]</v> + <v>InfoResult = InfoTuple | InfoTupleList | undefined | []</v> + </type> + <desc> + <p>Returns information about the process identified by <c>Pid</c> + as specified by the <c>ItemSpec</c>, or <c>undefined</c> if the + process is not alive. + </p> + <p>If the process is alive and <c>ItemSpec</c> is a single + <c>Item</c>, the returned value is the corresponding + <c>InfoTuple</c> unless <c>ItemSpec == 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 <c>ItemSpec</c> is an <c>ItemList</c>, the result is an + <c>InfoTupleList</c>. The <c>InfoTuple</c>s in the + <c>InfoTupleList</c> will appear with the corresponding + <c>Item</c>s in the same order as the <c>Item</c>s appeared + in the <c>ItemList</c>. Valid <c>Item</c>s may appear multiple + times in the <c>ItemList</c>. + </p> + <note><p>If <c>registered_name</c> is part of an <c>ItemList</c> + and the process has no name registered a + <c>{registered_name, []}</c> <c>InfoTuple</c> <em>will</em> + appear in the resulting <c>InfoTupleList</c>. This + behavior is different than when + <c>ItemSpec == registered_name</c>, and than when + <c>process_info/1</c> is used. + </p></note> + <p>Currently the following <c>InfoTuple</c>s with corresponding + <c>Item</c>s are valid:</p> + <taglist> + <tag><c>{backtrace, Bin}</c></tag> + <item> + <p>The binary <c>Bin</c> contains the same information as + the output from + <c>erlang:process_display(Pid, backtrace)</c>. Use + <c>binary_to_list/1</c> to obtain the string of characters + from the binary.</p> + </item> + <tag><c>{binary, BinInfo}</c></tag> + <item> + <p><c>BinInfo</c> is a list containing miscellaneous information + about binaries currently being referred to by this process. + This <c>InfoTuple</c> may be changed or removed without prior + notice.</p> + </item> + <tag><c>{catchlevel, CatchLevel}</c></tag> + <item> + <p><c>CatchLevel</c> is the number of currently active + catches in this process. This <c>InfoTuple</c> may be + changed or removed without prior notice.</p> + </item> + <tag><c>{current_function, {Module, Function, Args}}</c></tag> + <item> + <p><c>Module</c>, <c>Function</c>, <c>Args</c> is + the current function call of the process.</p> + </item> + <tag><c>{dictionary, Dictionary}</c></tag> + <item> + <p><c>Dictionary</c> is the dictionary of the process.</p> + </item> + <tag><c>{error_handler, Module}</c></tag> + <item> + <p><c>Module</c> is the error handler module used by + the process (for undefined function calls, for example).</p> + </item> + <tag><c>{garbage_collection, GCInfo}</c></tag> + <item> + <p><c>GCInfo</c> is a list which contains miscellaneous + information about garbage collection for this process. + The content of <c>GCInfo</c> may be changed without + prior notice.</p> + </item> + <tag><c>{group_leader, GroupLeader}</c></tag> + <item> + <p><c>GroupLeader</c> is group leader for the IO of + the process.</p> + </item> + <tag><c>{heap_size, Size}</c></tag> + <item> + <p><c>Size</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> + </item> + <tag><c>{initial_call, {Module, Function, Arity}}</c></tag> + <item> + <p><c>Module</c>, <c>Function</c>, <c>Arity</c> is + the initial function call with which the process was + spawned.</p> + </item> + <tag><c>{links, Pids}</c></tag> + <item> + <p><c>Pids</c> is a list of pids, with processes 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>). + If call saving is active, a list is returned, in which + the last element is the most recent called.</p> + </item> + <tag><c>{memory, Size}</c></tag> + <item> + <p><c>Size</c> is the size in bytes of the process. This + includes call stack, heap and internal structures.</p> + </item> + <tag><c>{message_binary, BinInfo}</c></tag> + <item> + <p><c>BinInfo</c> is a list containing miscellaneous information + about binaries currently being referred to by the message + area. This <c>InfoTuple</c> is only valid on an emulator + using the hybrid heap type. This <c>InfoTuple</c> may be + changed or removed without prior notice.</p> + </item> + <tag><c>{message_queue_len, MessageQueueLen}</c></tag> + <item> + <p><c>MessageQueueLen</c> is the number of messages + currently in the message queue of the process. This is + the length of the list <c>MessageQueue</c> returned as + the info item <c>messages</c> (see below).</p> + </item> + <tag><c>{messages, MessageQueue}</c></tag> + <item> + <p><c>MessageQueue</c> is a list of the messages to + the process, which have not yet been processed.</p> + </item> + <tag><c>{monitored_by, Pids}</c></tag> + <item> + <p>A list of pids that are monitoring the process (with + <c>erlang:monitor/2</c>).</p> + </item> + <tag><c>{monitors, Monitors}</c></tag> + <item> + <p>A list of monitors (started by <c>erlang: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, Pid}</c>, and for a remote process + monitor by name, the list item is + <c>{process, {RegName, Node}}</c>.</p> + </item> + <tag><c>{priority, Level}</c></tag> + <item> + <p><c>Level</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> + </item> + <tag><c>{reductions, Number}</c></tag> + <item> + <p><c>Number</c> is the number of reductions executed by + the process.</p> + </item> + <tag><c>{registered_name, Atom}</c></tag> + <item> + <p><c>Atom</c> is the registered name of the process. If + the process has no registered name, this tuple is not + present in the list.</p> + </item> + <tag><c>{sequential_trace_token, [] | SequentialTraceToken}</c></tag> + <item> + <p><c>SequentialTraceToken</c> the sequential trace token for + the process. This <c>InfoTuple</c> may be changed or removed + without prior notice.</p> + </item> + <tag><c>{stack_size, Size}</c></tag> + <item> + <p><c>Size</c> is the stack size of the process in words.</p> + </item> + <tag><c>{status, Status}</c></tag> + <item> + <p><c>Status</c> is the status of the process. <c>Status</c> + is <c>waiting</c> (waiting 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> + </item> + <tag><c>{suspending, SuspendeeList}</c></tag> + <item> + <p><c>SuspendeeList</c> is a list of <c>{Suspendee, + ActiveSuspendCount, OutstandingSuspendCount}</c> tuples. + <c>Suspendee</c> is the pid of a process that have been or is to + be suspended by the process identified by <c>Pid</c> via the + <seealso marker="#erlang:suspend_process/2">erlang:suspend_process/2</seealso> + BIF, or the + <seealso marker="#erlang:suspend_process/1">erlang:suspend_process/1</seealso> + BIF. <c>ActiveSuspendCount</c> is the number of times the + <c>Suspendee</c> has been suspended by <c>Pid</c>. + <c>OutstandingSuspendCount</c> is the number of not yet + completed suspend requests sent by <c>Pid</c>. That is, + if <c>ActiveSuspendCount /= 0</c>, <c>Suspendee</c> is + currently in the suspended state, and if + <c>OutstandingSuspendCount /= 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>Pid</c>. + Note that the <c>ActiveSuspendCount</c> and + <c>OutstandingSuspendCount</c> are not the total suspend count + on <c>Suspendee</c>, only the parts contributed by <c>Pid</c>. + </p> + </item> + <tag><c>{total_heap_size, Size}</c></tag> + <item> + <p><c>Size</c> is the total size in words of all heap + fragments of the process. This currently include the stack + of the process. + </p> + </item> + <tag><c>{trace, InternalTraceFlags}</c></tag> + <item> + <p><c>InternalTraceFlags</c> is an integer representing + internal trace flag for this process. This <c>InfoTuple</c> + may be changed or removed without prior notice.</p> + </item> + <tag><c>{trap_exit, Boolean}</c></tag> + <item> + <p><c>Boolean</c> is <c>true</c> if the process is trapping + exits, otherwise it is <c>false</c>.</p> + </item> + </taglist> + <p>Note however, that not all implementations support every one + of the above <c>Items</c>.</p> + <p>Failure: <c>badarg</c> if <c>Pid</c> is not a local process, + or if <c>Item</c> is not a valid <c>Item</c>.</p> + </desc> + </func> + <func> + <name>processes() -> [pid()]</name> + <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> + <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>purge_module(Module) -> void()</name> + <fsummary>Remove old code for a module</fsummary> + <type> + <v>Module = atom()</v> + </type> + <desc> + <p>Removes old code for <c>Module</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> + <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> + </warning> + <p>Failure: <c>badarg</c> if there is no old code for + <c>Module</c>.</p> + </desc> + </func> + <func> + <name>put(Key, Val) -> OldVal | undefined</name> + <fsummary>Add a new value to the process dictionary</fsummary> + <type> + <v>Key = Val = OldVal = term()</v> + </type> + <desc> + <p>Adds a new <c>Key</c> to the process dictionary, associated + with the value <c>Val</c>, and returns <c>undefined</c>. If + <c>Key</c> already exists, the old value is deleted and + replaced by <c>Val</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> + <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> + </desc> + </func> + <func> + <name>erlang:raise(Class, Reason, Stacktrace)</name> + <fsummary>Stop execution with an exception of given class, reason and call stack backtrace</fsummary> + <type> + <v>Class = error | exit | throw</v> + <v>Reason = term()</v> + <v>Stacktrace = [{Module, Function, Arity | Args} | {Fun, Args}]</v> + <v> Module = Function = atom()</v> + <v> Arity = int()</v> + <v> Args = [term()]</v> + <v> Fun = [fun()]</v> + </type> + <desc> + <p>Stops the execution of the calling process with an + exception of given 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>Class</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(Class, Reason, Stacktrace)</c> is + equivalent to <c>erlang:Class(Reason)</c>. + <c>Reason</c> is any term and <c>Stacktrace</c> is a list as + returned from <c>get_stacktrace()</c>, that is a list of + 3-tuples <c>{Module, Function, Arity | Args}</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}</c> tuples where + <c>Fun</c> is a local fun and <c>Args</c> is an argument list.</p> + <p>The stacktrace is used as the exception stacktrace for the + calling process; it will be 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>erlang:error(erlang:raise(Class, Reason, Stacktrace))</c> + and hope to distinguish exceptions later.</p> + </desc> + </func> + <func> + <name>erlang:read_timer(TimerRef) -> int() | false</name> + <fsummary>Number of milliseconds remaining for a timer</fsummary> + <type> + <v>TimerRef = ref()</v> + </type> + <desc> + <p><c>TimerRef</c> is a timer reference returned by + <seealso marker="#erlang:send_after/3">erlang:send_after/3</seealso> + or + <seealso marker="#erlang: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>TimerRef</c> was never a + timer, that it has been cancelled, or that it has already + delivered its message).</p> + <p>See also + <seealso marker="#erlang:send_after/3">erlang:send_after/3</seealso>, + <seealso marker="#erlang:start_timer/3">erlang:start_timer/3</seealso>, + and + <seealso marker="#erlang:cancel_timer/1">erlang:cancel_timer/1</seealso>.</p> + </desc> + </func> + <func> + <name>erlang:ref_to_list(Ref) -> string()</name> + <fsummary>Text representation of a reference</fsummary> + <type> + <v>Ref = ref()</v> + </type> + <desc> + <p>Returns a string which corresponds to the text + representation of <c>Ref</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>register(RegName, Pid | Port) -> true</name> + <fsummary>Register a name for a pid (or port)</fsummary> + <type> + <v>RegName = atom()</v> + <v>Pid = pid()</v> + <v>Port = port()</v> + </type> + <desc> + <p>Associates the name <c>RegName</c> with a pid or a port + identifier. <c>RegName</c>, which must be an atom, can be used + instead of the pid / port identifier in the send operator + (<c>RegName ! Message</c>).</p> + <pre> +> <input>register(db, Pid).</input> +true</pre> + <p>Failure: <c>badarg</c> if <c>Pid</c> is not an existing, + local process or port, if <c>RegName</c> is already in use, + if the process or port is already registered (already has a + name), or if <c>RegName</c> is the atom <c>undefined</c>.</p> + </desc> + </func> + <func> + <name>registered() -> [RegName]</name> + <fsummary>All registered names</fsummary> + <type> + <v>RegName = atom()</v> + </type> + <desc> + <p>Returns a list of names which have been registered using + <seealso marker="#register/2">register/2</seealso>.</p> + <pre> +> <input>registered().</input> +[code_server, file_server, init, user, my_db]</pre> + </desc> + </func> + <func> + <name>erlang:resume_process(Suspendee) -> true</name> + <fsummary>Resume a suspended process</fsummary> + <type> + <v>Suspendee = pid()</v> + </type> + <desc> + <p>Decreases the suspend count on the process identified by + <c>Suspendee</c>. <c>Suspendee</c> should previously have been + suspended via + <seealso marker="#erlang:suspend_process/2">erlang:suspend_process/2</seealso>, + or + <seealso marker="#erlang:suspend_process/1">erlang:suspend_process/1</seealso> + by the process calling <c>erlang:resume_process(Suspendee)</c>. When + the suspend count on <c>Suspendee</c> reach zero, <c>Suspendee</c> + will be resumed, i.e., the state of the <c>Suspendee</c> is changed + from suspended into the state <c>Suspendee</c> was in before it was + suspended. + </p> + <warning> + <p>This BIF is intended for debugging only.</p> + </warning> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item> + If <c>Suspendee</c> isn't 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>Suspendee</c>. + </item> + <tag><c>badarg</c></tag> + <item> + If the process identified by <c>Suspendee</c> is not alive. + </item> + </taglist> + </desc> + </func> + <func> + <name>round(Number) -> int()</name> + <fsummary>Return an integer by rounding a number</fsummary> + <type> + <v>Number = number()</v> + </type> + <desc> + <p>Returns an integer by rounding <c>Number</c>.</p> + <pre> +> <input>round(5.5).</input> +6</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>self() -> pid()</name> + <fsummary>Pid of the calling process</fsummary> + <desc> + <p>Returns the pid (process identifier) of the calling process.</p> + <pre> +> <input>self().</input> +<0.26.0></pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>erlang:send(Dest, Msg) -> Msg</name> + <fsummary>Send a message</fsummary> + <type> + <v>Dest = pid() | port() | RegName | {RegName, Node}</v> + <v>Msg = term()</v> + <v> RegName = atom()</v> + <v> Node = node()</v> + </type> + <desc> + <p>Sends a message and returns <c>Msg</c>. This is the same as + <c>Dest ! Msg</c>.</p> + <p><c>Dest</c> may be a remote or local pid, a (local) port, a + locally registered name, or a tuple <c>{RegName, Node}</c> + for a registered name at another node.</p> + </desc> + </func> + <func> + <name>erlang:send(Dest, Msg, [Option]) -> Res</name> + <fsummary>Send a message conditionally</fsummary> + <type> + <v>Dest = pid() | port() | RegName | {RegName, Node}</v> + <v> RegName = atom()</v> + <v> Node = node()</v> + <v>Msg = term()</v> + <v>Option = nosuspend | noconnect</v> + <v>Res = ok | nosuspend | noconnect</v> + </type> + <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="#erlang:send/2">erlang:send/2</seealso>. See + also + <seealso marker="#erlang:send_nosuspend/2">erlang:send_nosuspend/2,3</seealso>. + for more detailed explanation and warnings.</p> + <p>The possible options are:</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> + <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> + </item> + </taglist> + <warning> + <p>As with <c>erlang:send_nosuspend/2,3</c>: Use with extreme + care!</p> + </warning> + </desc> + </func> + <func> + <name>erlang:send_after(Time, Dest, Msg) -> TimerRef</name> + <fsummary>Start a timer</fsummary> + <type> + <v>Time = int()</v> + <v> 0 <= Time <= 4294967295</v> + <v>Dest = pid() | RegName </v> + <v> LocalPid = pid() (of a process, alive or dead, on the local node)</v> + <v>Msg = term()</v> + <v>TimerRef = ref()</v> + </type> + <desc> + <p>Starts a timer which will send the message <c>Msg</c> + to <c>Dest</c> after <c>Time</c> milliseconds.</p> + <p>If <c>Dest</c> is an atom, 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>Dest</c> is a pid, the timer will be automatically + canceled if the process referred to by the pid 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>Dest</c> is an atom.</p> + <p>See also + <seealso marker="#erlang:start_timer/3">erlang:start_timer/3</seealso>, + <seealso marker="#erlang:cancel_timer/1">erlang:cancel_timer/1</seealso>, + and + <seealso marker="#erlang: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> + </desc> + </func> + <func> + <name>erlang:send_nosuspend(Dest, Msg) -> bool()</name> + <fsummary>Try to send a message without ever blocking</fsummary> + <type> + <v>Dest = pid() | port() | RegName | {RegName, Node}</v> + <v> RegName = atom()</v> + <v> Node = node()</v> + <v>Msg = term()</v> + </type> + <desc> + <p>The same as + <seealso marker="#erlang:send/3">erlang:send(Dest, Msg, [nosuspend])</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 + 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>Dest</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 + 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 + 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 + 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 + 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 + 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> + <warning> + <p>Use with extreme care!</p> + </warning> + </desc> + </func> + <func> + <name>erlang:send_nosuspend(Dest, Msg, Options) -> bool()</name> + <fsummary>Try to send a message without ever blocking</fsummary> + <type> + <v>Dest = pid() | port() | RegName | {RegName, Node}</v> + <v> RegName = atom()</v> + <v> Node = node()</v> + <v>Msg = term()</v> + <v>Option = noconnect</v> + </type> + <desc> + <p>The same as + <seealso marker="#erlang:send/3">erlang:send(Dest, Msg, [nosuspend | Options])</seealso>, + but with boolean return value.</p> + <p>This function behaves like + <seealso marker="#erlang: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 + 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 + 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> + <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> + </warning> + </desc> + </func> + <func> + <name>erlang:set_cookie(Node, Cookie) -> true</name> + <fsummary>Set the magic cookie of a node</fsummary> + <type> + <v>Node = node()</v> + <v>Cookie = atom()</v> + </type> + <desc> + <p>Sets the magic cookie of <c>Node</c> to the atom + <c>Cookie</c>. If <c>Node</c> is the local node, the function + also sets the cookie of all other unknown nodes to + <c>Cookie</c> (see + <seealso marker="doc/reference_manual:distributed">Distributed Erlang</seealso> in the Erlang Reference Manual).</p> + <p>Failure: <c>function_clause</c> if the local node is not + alive.</p> + </desc> + </func> + <func> + <name>setelement(Index, Tuple1, Value) -> Tuple2</name> + <fsummary>Set Nth element of a tuple</fsummary> + <type> + <v>Index = 1..tuple_size(Tuple1)</v> + <v>Tuple1 = Tuple2 = tuple()</v> + <v>Value = term()</v> + </type> + <desc> + <p>Returns a tuple which is a copy of the argument <c>Tuple1</c> + with the element given by the integer argument <c>Index</c> + (the first element is the element with index 1) replaced by + the argument <c>Value</c>.</p> + <pre> +> <input>setelement(2, {10, green, bottles}, red).</input> +{10,red,bottles}</pre> + </desc> + </func> + <func> + <name>size(Item) -> int()</name> + <fsummary>Size of a tuple or binary</fsummary> + <type> + <v>Item = tuple() | binary()</v> + </type> + <desc> + <p>Returns an integer which is the size of the argument + <c>Item</c>, which must be either a tuple or a binary.</p> + <pre> +> <input>size({morni, mulle, bwange}).</input> +3</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>spawn(Fun) -> pid()</name> + <fsummary>Create a new process with a fun as entry point</fsummary> + <type> + <v>Fun = fun()</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Fun</c> to the empty list <c>[]</c>. Otherwise works + like <seealso marker="#spawn/3">spawn/3</seealso>.</p> + </desc> + </func> + <func> + <name>spawn(Node, Fun) -> pid()</name> + <fsummary>Create a new process with a fun as entry point on a given node</fsummary> + <type> + <v>Node = node()</v> + <v>Fun = fun()</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Fun</c> to the empty list <c>[]</c> on <c>Node</c>. If + <c>Node</c> does not exist, a useless pid is returned. + Otherwise works like + <seealso marker="#spawn/3">spawn/3</seealso>.</p> + </desc> + </func> + <func> + <name>spawn(Module, Function, Args) -> pid()</name> + <fsummary>Create a new process with a function as entry point</fsummary> + <type> + <v>Module = Function = atom()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Module:Function</c> to <c>Args</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(Module, Function, Args)</c> is evaluated by the new process if + <c>Module:Function/Arity</c> does not exist (where + <c>Arity</c> is the length of <c>Args</c>). The error handler + can be redefined (see + <seealso marker="#process_flag/2">process_flag/2</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> + <pre> +> <input>spawn(speed, regulator, [high_speed, thin_cut]).</input> +<0.13.1></pre> + </desc> + </func> + <func> + <name>spawn(Node, Module, Function, ArgumentList) -> pid()</name> + <fsummary>Create a new process with a function as entry point on a given node</fsummary> + <type> + <v>Node = node()</v> + <v>Module = Function = atom()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Module:Function</c> to <c>Args</c> on <c>Node</c>. If + <c>Node</c> does not exists, a useless pid is returned. + Otherwise works like + <seealso marker="#spawn/3">spawn/3</seealso>.</p> + </desc> + </func> + <func> + <name>spawn_link(Fun) -> pid()</name> + <fsummary>Create and link to a new process with a fun as entry point</fsummary> + <type> + <v>Fun = fun()</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Fun</c> to the empty list []. A link is created between + the calling process and the new process, atomically. + Otherwise works like + <seealso marker="#spawn/3">spawn/3</seealso>.</p> + </desc> + </func> + <func> + <name>spawn_link(Node, Fun) -></name> + <fsummary>Create and link to a new process with a fun as entry point on a specified node</fsummary> + <type> + <v>Node = node()</v> + <v>Fun = fun()</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Fun</c> to the empty list [] on <c>Node</c>. A link is + created between the calling process and the new process, + atomically. If <c>Node</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> + </desc> + </func> + <func> + <name>spawn_link(Module, Function, Args) -> pid()</name> + <fsummary>Create and link to a new process with a function as entry point</fsummary> + <type> + <v>Module = Function = atom()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Module:Function</c> to <c>Args</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> + </desc> + </func> + <func> + <name>spawn_link(Node, Module, Function, Args) -> pid()</name> + <fsummary>Create and link to a new process with a function as entry point on a given node</fsummary> + <type> + <v>Node = node()</v> + <v>Module = Function = atom()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Module:Function</c> to <c>Args</c> on <c>Node</c>. A + link is created between the calling process and the new + process, atomically. If <c>Node</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> + </desc> + </func> + <func> + <name>spawn_monitor(Fun) -> {pid(),reference()}</name> + <fsummary>Create and monitor a new process with a fun as entry point</fsummary> + <type> + <v>Fun = fun()</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Fun</c> to the empty list [] and reference for a monitor + created to the new process. + Otherwise works like + <seealso marker="#spawn/3">spawn/3</seealso>.</p> + </desc> + </func> + <func> + <name>spawn_monitor(Module, Function, Args) -> {pid(),reference()}</name> + <fsummary>Create and monitor a new process with a function as entry point</fsummary> + <type> + <v>Module = Function = atom()</v> + <v>Args = [term()]</v> + </type> + <desc> + <p>A new process is started by the application + of <c>Module:Function</c> to <c>Args</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> + </desc> + </func> + <func> + <name>spawn_opt(Fun, [Option]) -> pid() | {pid(),reference()}</name> + <fsummary>Create a new process with a fun as entry point</fsummary> + <type> + <v>Fun = fun()</v> + <v>Option = link | monitor | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size}</v> + <v> Level = low | normal | high</v> + <v> Number = int()</v> + <v> Size = int()</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Fun</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> + </desc> + </func> + <func> + <name>spawn_opt(Node, Fun, [Option]) -> pid()</name> + <fsummary>Create a new process with a fun as entry point on a given node</fsummary> + <type> + <v>Node = node()</v> + <v>Fun = fun()</v> + <v>Option = link | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size}</v> + <v> Level = low | normal | high</v> + <v> Number = int()</v> + <v> Size = int()</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Fun</c> to the empty list <c>[]</c> on <c>Node</c>. If + <c>Node</c> does not exist, a useless pid is returned. + Otherwise works like + <seealso marker="#spawn_opt/4">spawn_opt/4</seealso>.</p> + </desc> + </func> + <func> + <name>spawn_opt(Module, Function, Args, [Option]) -> pid() | {pid(),reference()}</name> + <fsummary>Create a new process with a function as entry point</fsummary> + <type> + <v>Module = Function = atom()</v> + <v>Args = [term()]</v> + <v>Option = link | monitor | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size}</v> + <v> Level = low | normal | high</v> + <v> Number = int()</v> + <v> Size = int()</v> + </type> + <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> + <taglist> + <tag><c>link</c></tag> + <item> + <p>Sets a link to the parent process (like + <c>spawn_link/3</c> does).</p> + </item> + <tag><c>monitor</c></tag> + <item> + <p>Monitor the new process (just like + <seealso marker="#erlang:monitor/2">erlang:monitor/2</seealso> does).</p> + </item> + <tag><c>{priority, Level}</c></tag> + <item> + <p>Sets the priority of the new process. Equivalent to + executing + <seealso marker="#process_flag_priority">process_flag(priority, Level)</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> + </item> + <tag><c>{fullsweep_after, Number}</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>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 + 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 + 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>Number</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>Number</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>Number</c> to zero. (The value may be set + globally, see + <seealso marker="#erlang:system_flag/2">erlang:system_flag/2</seealso>.)</p> + </item> + <tag><c>{min_heap_size, Size}</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 + 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 + fine-tuning an application and to measure the execution + time with various <c>Size</c> values.</p> + </item> + </taglist> + </desc> + </func> + <func> + <name>spawn_opt(Node, Module, Function, Args, [Option]) -> pid()</name> + <fsummary>Create a new process with a function as entry point on a given node</fsummary> + <type> + <v>Node = node()</v> + <v>Module = Function = atom()</v> + <v>Args = [term()]</v> + <v>Option = link | {priority, Level} | {fullsweep_after, Number} | {min_heap_size, Size}</v> + <v> Level = low | normal | high</v> + <v> Number = int()</v> + <v> Size = int()</v> + </type> + <desc> + <p>Returns the pid of a new process started by the application + of <c>Module:Function</c> to <c>Args</c> on <c>Node</c>. If + <c>Node</c> does not exist, a useless pid is returned. + Otherwise works like + <seealso marker="#spawn_opt/4">spawn_opt/4</seealso>.</p> + </desc> + </func> + <func> + <name>split_binary(Bin, Pos) -> {Bin1, Bin2}</name> + <fsummary>Split a binary into two</fsummary> + <type> + <v>Bin = Bin1 = Bin2 = binary()</v> + <v>Pos = 1..byte_size(Bin)</v> + </type> + <desc> + <p>Returns a tuple containing the binaries which are the result + of splitting <c>Bin</c> into two parts at position <c>Pos</c>. + This is not a destructive operation. After the operation, + there will be three binaries altogether.</p> + <pre> +> <input>B = list_to_binary("0123456789").</input> +<<"0123456789">> +> <input>byte_size(B).</input> +10 +> <input>{B1, B2} = split_binary(B,3).</input> +{<<"012">>,<<"3456789">>} +> <input>byte_size(B1).</input> +3 +> <input>byte_size(B2).</input> +7</pre> + </desc> + </func> + <func> + <name>erlang:start_timer(Time, Dest, Msg) -> TimerRef</name> + <fsummary>Start a timer</fsummary> + <type> + <v>Time = int()</v> + <v> 0 <= Time <= 4294967295</v> + <v>Dest = LocalPid | RegName </v> + <v> LocalPid = pid() (of a process, alive or dead, on the local node)</v> + <v> RegName = atom()</v> + <v>Msg = term()</v> + <v>TimerRef = ref()</v> + </type> + <desc> + <p>Starts a timer which will send the message + <c>{timeout, TimerRef, Msg}</c> to <c>Dest</c> + after <c>Time</c> milliseconds.</p> + <p>If <c>Dest</c> is an atom, 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>Dest</c> is a pid, the timer will be automatically + canceled if the process referred to by the pid 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>Dest</c> is an atom.</p> + <p>See also + <seealso marker="#erlang:send_after/3">erlang:send_after/3</seealso>, + <seealso marker="#erlang:cancel_timer/1">erlang:cancel_timer/1</seealso>, + and + <seealso marker="#erlang: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> + </desc> + </func> + <func> + <name>statistics(Type) -> Res</name> + <fsummary>Information about the system</fsummary> + <type> + <v>Type, Res -- see below</v> + </type> + <desc> + <p>Returns information about the system as specified by + <c>Type</c>:</p> + <taglist> + <tag><c>context_switches</c></tag> + <item> + <p>Returns <c>{ContextSwitches, 0}</c>, where + <c>ContextSwitches</c> is the total number of context + switches since the system started.</p> + </item> + <tag><c>exact_reductions</c></tag> + <item> + <marker id="statistics_exact_reductions"></marker> + <p>Returns + <c>{Total_Exact_Reductions, Exact_Reductions_Since_Last_Call}</c>.</p> + <p><em>NOTE:</em><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> + </item> + <tag><c>garbage_collection</c></tag> + <item> + <p>Returns <c>{Number_of_GCs, Words_Reclaimed, 0}</c>. This + information may not be valid for all implementations.</p> + </item> + <tag><c>io</c></tag> + <item> + <p>Returns <c>{{input, Input}, {output, Output}}</c>, + where <c>Input</c> is the total number of bytes received + through ports, and <c>Output</c> is the total number of + bytes output to ports.</p> + </item> + <tag><c>reductions</c></tag> + <item> + <marker id="statistics_reductions"></marker> + <p>Returns + <c>{Total_Reductions, Reductions_Since_Last_Call}</c>.</p> + <p><em>NOTE:</em> From erts version 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> + </item> + <tag><c>run_queue</c></tag> + <item> + <p>Returns the length of the run queue, that is, the number + of processes that are ready to run.</p> + </item> + <tag><c>runtime</c></tag> + <item> + <p>Returns <c>{Total_Run_Time, Time_Since_Last_Call}</c>. + 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.</p> + </item> + <tag><c>wall_clock</c></tag> + <item> + <p>Returns + <c>{Total_Wallclock_Time, Wallclock_Time_Since_Last_Call}</c>. + <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> + </item> + </taglist> + <p>All times are in milliseconds.</p> + <pre> +> <input>statistics(runtime).</input> +{1690,1620} +> <input>statistics(reductions).</input> +{2046,11} +> <input>statistics(garbage_collection).</input> +{85,23961,0}</pre> + </desc> + </func> + <func> + <name>erlang:suspend_process(Suspendee, OptList) -> true | false</name> + <fsummary>Suspend a process</fsummary> + <type> + <v>Suspendee = pid()</v> + <v>OptList = [Opt]</v> + <v>Opt = atom()</v> + </type> + <desc> + <p>Increases the suspend count on the process identified by + <c>Suspendee</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>Suspendee</c> is + decreased when + <seealso marker="#erlang:resume_process/1">erlang:resume_process(Suspendee)</seealso> + is called by the same process that called + <c>erlang:suspend_process(Suspendee)</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>Opt</c>s) are available:</p> + <taglist> + <tag><c>asynchronous</c></tag> + <item> + A suspend request is sent to the process identified by + <c>Suspendee</c>. <c>Suspendee</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>Suspendee</c> has suspended yet + or not. Note that the point in time when the <c>Suspendee</c> + will actually suspend cannot be deduced from other events + in the system. The only guarantee given is that the + <c>Suspendee</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>Suspendee</c> has actually suspended. + </item> + <tag><c>unless_suspending</c></tag> + <item> + The process identified by <c>Suspendee</c> will be suspended + unless the calling process already is suspending the + <c>Suspendee</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>Suspendee</c> or if a suspend request already has been sent + and is in transit. If the calling process already is suspending + the <c>Suspendee</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>Suspendee</c> + will remain unchanged. + </item> + </taglist> + + <p>If the suspend count on the process identified by + <c>Suspendee</c> was increased, <c>true</c> is returned; otherwise, + <c>false</c> is returned.</p> + + <warning> + <p>This BIF is intended for debugging only.</p> + </warning> + <p>Failures:</p> + <taglist> + <tag><c>badarg</c></tag> + <item> + If <c>Suspendee</c> isn't a process identifier. + </item> + <tag><c>badarg</c></tag> + <item> + If the process identified by <c>Suspendee</c> is same the process as + the process calling <c>erlang:suspend_process/2</c>. + </item> + <tag><c>badarg</c></tag> + <item> + If the process identified by <c>Suspendee</c> is not alive. + </item> + <tag><c>badarg</c></tag> + <item> + If the process identified by <c>Suspendee</c> resides on another node. + </item> + <tag><c>badarg</c></tag> + <item> + If <c>OptList</c> isn't a proper list of valid <c>Opt</c>s. + </item> + <tag><c>system_limit</c></tag> + <item> + If the process identified by <c>Suspendee</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> + </taglist> + </desc> + </func> + <func> + <name>erlang:suspend_process(Suspendee) -> true</name> + <fsummary>Suspend a process</fsummary> + <type> + <v>Suspendee = pid()</v> + </type> + <desc> + <p>Suspends the process identified by <c>Suspendee</c>. The + same as calling + <seealso marker="#erlang:suspend_process/2">erlang:suspend_process(Suspendee, [])</seealso>. For more information see the documentation of <seealso marker="#erlang:suspend_process/2">erlang:suspend_process/2</seealso>. + </p> + <warning> + <p>This BIF is intended for debugging only.</p> + </warning> + </desc> + </func> + <func> + <name>erlang:system_flag(Flag, Value) -> OldValue</name> + <fsummary>Set system flags</fsummary> + <type> + <v>Flag, Value, OldValue -- see below</v> + </type> + <desc> + <p>Sets various system properties of the Erlang node. Returns + the old value of the flag.</p> + <taglist> + <tag><c>erlang:system_flag(backtrace_depth, Depth)</c></tag> + <item> + <p>Sets the maximum depth of call stack back-traces in the + exit reason element of <c>'EXIT'</c> tuples.</p> + </item> + <tag><c>erlang:system_flag(cpu_topology, CpuTopology)</c></tag> + <item> + <marker id="system_flag_cpu_topology"></marker> + <p>Sets the user defined <c>CpuTopology</c>. The user defined + CPU topology will override any automatically detected + CPU topology. By passing <c>undefined</c> as <c>CpuTopology</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>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="erl#+sct">+sct</seealso> command + line argument to <c>erl</c>. + </p> + <p>For information on the <c>CpuTopology</c> type + and more, see the documentation of + <seealso marker="#system_info_cpu_topology">erlang:system_info(cpu_topology)</seealso>, + the <c>erl</c> <seealso marker="erl#+sct">+sct</seealso> + emulator flag, and + <seealso marker="#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, How)</seealso>. + </p> + </item> + <tag><c>erlang:system_flag(fullsweep_after, Number)</c></tag> + <item> + <p><c>Number</c> is a non-negative integer which indicates + how many times generational garbage collections can be + done without forcing a fullsweep collection. The value + applies to new processes; processes already running are + not affected.</p> + <p>In low-memory systems (especially without virtual + memory), setting the value to 0 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> + </item> + <tag><c>erlang:system_flag(min_heap_size, MinHeapSize)</c></tag> + <item> + <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> + </item> + <tag><c>erlang:system_flag(multi_scheduling, BlockState)</c></tag> + <item> + <marker id="system_flag_multi_scheduling"></marker> + <p><c>BlockState = block | unblock</c></p> + <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>BlockState =:= block</c>, multi-scheduling will + be blocked. If <c>BlockState =:= 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> + <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>erlang:system_flag(multi_scheduling, BlockState)</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> + </item> + <tag><c>erlang:system_flag(scheduler_bind_type, How)</c></tag> + <item> + <marker id="system_flag_scheduler_bind_type"></marker> + <p>Controls if and how schedulers are bound to logical + processors.</p> + <p>When <c>erlang:system_flag(scheduler_bind_type, How)</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 + and Solaris systems, but more systems will be supported + in the future. + </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 + <seealso marker="#system_flag_cpu_topology">erlang:system_flag(cpu_topology, CpuTopology)</seealso>. + </p> + <p><em>NOTE:</em> If other programs on the system have bound + to processors, e.g. another Erlang runtime system, you + may loose performance when binding schedulers. Therefore, + schedulers are by default not bound.</p> + <p>Schedulers can be bound in different ways. The <c>How</c> + argument determines how schedulers are bound. <c>How</c> can + currently be one of:</p> + <taglist> + <tag><c>unbound</c></tag> + <item> + <p>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> + </item> + <tag><c>no_spread</c></tag> + <item> + <p>Schedulers with close scheduler identifiers will be bound + as close as possible in hardware.</p> + </item> + <tag><c>thread_spread</c></tag> + <item> + <p>Thread refers to hardware threads (e.g. Intels + 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> + </item> + <tag><c>processor_spread</c></tag> + <item> + <p>Schedulers will be spread like <c>thread_spread</c>, but + also over physical processor chips.</p> + </item> + <tag><c>spread</c></tag> + <item> + <p>Schedulers will be spread as much as possible.</p> + </item> + <tag><c>no_node_thread_spread</c></tag> + <item> + <p>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> + </item> + <tag><c>no_node_processor_spread</c></tag> + <item> + <p>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> + </item> + <tag><c>thread_no_node_processor_spread</c></tag> + <item> + <p>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> + </item> + <tag><c>default_bind</c></tag> + <item> + <p>Binds schedulers the default way. Currently the default + is <c>thread_no_node_processor_spread</c> (which might change + in the future).</p> + </item> + </taglist> + <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>The value returned equals <c>How</c> before the + <c>scheduler_bind_type</c> flag was changed.</p> + <p>Failure:</p> + <taglist> + <tag><c>notsup</c></tag> + <item> + <p>If binding of schedulers is not supported.</p> + </item> + <tag><c>badarg</c></tag> + <item> + <p>If <c>How</c> isn't one of the documented alternatives.</p> + </item> + <tag><c>badarg</c></tag> + <item> + <p>If no CPU topology information is available.</p> + </item> + </taglist> + <p>The scheduler bind type can also be set by passing + the <seealso marker="erl#+sbt">+sbt</seealso> command + line argument to <c>erl</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="erl#+sbt">+sbt</seealso> + emulator flag, and + <seealso marker="#system_flag_cpu_topology">erlang:system_flag(cpu_topology, CpuTopology)</seealso>. + </p> + </item> + <tag><c>erlang:system_flag(schedulers_online, SchedulersOnline)</c></tag> + <item> + <marker id="system_flag_schedulers_online"></marker> + <p>Sets the amount of schedulers online. Valid range is + <![CDATA[1 <= SchedulerId <= erlang:system_info(schedulers)]]>. + </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> + </item> + <tag><c>erlang:system_flag(trace_control_word, TCW)</c></tag> + <item> + <p>Sets the value of the node's trace control word to + <c>TCW</c>. <c>TCW</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> + </item> + </taglist> + <note> + <p>The <c>schedulers</c> option has been removed as + of erts version 5.5.3. The number of scheduler + threads is determined at emulator boot time, and + cannot be changed after that.</p> + </note> + </desc> + </func> + <func> + <name>erlang:system_info(Type) -> Res</name> + <fsummary>Information about the system</fsummary> + <type> + <v>Type, Res -- see below</v> + </type> + <desc> + <p>Returns various information about the current system + (emulator) as specified by <c>Type</c>:</p> + <taglist> + <tag><c>allocated_areas</c></tag> + <item> + <marker id="system_info_allocated_areas"></marker> + <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 + 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> + 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="#erlang:memory/0">erlang:memory/0,1</seealso>.</p> + </item> + <tag><c>allocator</c></tag> + <item> + <marker id="system_info_allocator"></marker> + <p>Returns <c>{Allocator, Version, Features, Settings}.</c></p> + <p>Types:</p> + <list type="bulleted"> + <item><c>Allocator = undefined | elib_malloc | glibc</c></item> + <item><c>Version = [int()]</c></item> + <item><c>Features = [atom()]</c></item> + <item><c>Settings = [{Subsystem, [{Parameter, Value}]}]</c></item> + <item><c>Subsystem = atom()</c></item> + <item><c>Parameter = atom()</c></item> + <item><c>Value = term()</c></item> + </list> + <p>Explanation:</p> + <list type="bulleted"> + <item> + <p><c>Allocator</c> corresponds to the <c>malloc()</c> + implementation used. If <c>Allocator</c> equals + <c>undefined</c>, the <c>malloc()</c> implementation + used could not be identified. Currently + <c>elib_malloc</c> and <c>glibc</c> can be identified.</p> + </item> + <item> + <p><c>Version</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>Features</c> is a list of atoms representing + allocation features used.</p> + </item> + <item> + <p><c>Settings</c> is a list of subsystems, their + configurable parameters, and used values. Settings + may 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><c>alloc_util_allocators</c></tag> + <item> + <marker id="system_info_alloc_util_allocators"></marker> + <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> + </item> + <tag><c>{allocator, Alloc}</c></tag> + <item> + <marker id="system_info_allocator_tuple"></marker> + <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. + If <c>Alloc</c> is not a recognized allocator, + <c>undefined</c> is returned. If <c>Alloc</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 + 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 + 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 + 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. + <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> + </item> + <tag><c>{allocator_sizes, Alloc}</c></tag> + <item> + <marker id="system_info_allocator_sizes"></marker> + <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, Alloc})</seealso>. + </p> + </item> + <tag><c>c_compiler_used</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> + </item> + <tag><c>check_io</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> + </item> + <tag><c>compat_rel</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> + </item> + <tag><c>cpu_topology</c></tag> + <item> + <marker id="system_info_cpu_topology"></marker> + <p>Returns the <c>CpuTopology</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 user defined + CPU topology if such exist; otherwise, the automatically + detected CPU topology if such exist. If no CPU topology + exist <c>undefined</c> is returned.</p> + <p>Types:</p> + <list type="bulleted"> + <item><c>CpuTopology = LevelEntryList | undefined</c></item> + <item><c>LevelEntryList = [LevelEntry]</c> (all + <c>LevelEntry</c>s of a <c>LevelEntryList</c> + must contain the same <c>LevelTag</c>, except + on the top level where both <c>node</c> and + <c>processor</c> <c>LevelTag</c>s may co-exist)</item> + <item><c>LevelEntry = {LevelTag, SubLevel} + | {LevelTag, InfoList, SubLevel}</c> + (<c>{LevelTag, SubLevel} + == {LevelTag, [], SubLevel}</c>)</item> + <item><c>LevelTag = node|processor|core|thread</c> + (more <c>LevelTag</c>s may be introduced in + the future)</item> + <item><c>SubLevel = [LevelEntry] | LogicalCpuId</c></item> + <item><c>LogicalCpuId = {logical, integer()}</c></item> + <item><c>InfoList = []</c> (the <c>InfoList</c> + may be extended in the future)</item> + </list> + <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>CpuTopology</c> term can be omitted if + only one entry exists and the <c>InfoList</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>CpuTopology</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>CpuTopology</c> type to change. + </p> + </item> + <tag><c>{cpu_topology, defined}</c></tag> + <item> + <p>Returns the user defined <c>CpuTopology</c>. For more + information see the documentation of + <seealso marker="#system_flag_cpu_topology">erlang:system_flag(cpu_topology, CpuTopology)</seealso> + and the documentation of the + <seealso marker="#system_info_cpu_topology">cpu_topology</seealso> + argument. + </p> + </item> + <tag><c>{cpu_topology, detected}</c></tag> + <item> + <p>Returns the automatically detected <c>CpuTopology</c>. The + emulator currently only detects the CPU topology on some newer + linux and solaris systems. For more information see the + documentation of the + <seealso marker="#system_info_cpu_topology">cpu_topology</seealso> + argument. + </p> + </item> + <tag><c>{cpu_topology, used}</c></tag> + <item> + <p>Returns the <c>CpuTopology</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> + </item> + <tag><c>creation</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> + </item> + <tag><c>debug_compiled</c></tag> + <item> + <p>Returns <c>true</c> if the emulator has been debug + compiled; otherwise, <c>false</c>. + </p> + </item> + <tag><c>dist</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> + </item> + <tag><c>dist_ctrl</c></tag> + <item> + <p>Returns a list of tuples + <c>{Node, ControllingEntity}</c>, one entry for each + connected remote node. The <c>Node</c> is the name of the + node and the <c>ControllingEntity</c> is the port or pid + responsible for the communication to that node. More + specifically, the <c>ControllingEntity</c> for nodes + connected via TCP/IP (the normal case) is the socket + actually used in communication with the specific node.</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> + </item> + <tag><c>elib_malloc</c></tag> + <item> + <p>If the emulator uses the <c>elib_malloc</c> memory + allocator, a list of two-element tuples containing status + information is returned; otherwise, <c>false</c> is + returned. The list currently contains the following + two-element tuples (all sizes are presented in bytes):</p> + <taglist> + <tag><c>{heap_size, Size}</c></tag> + <item> + <p>Where <c>Size</c> is the current heap size.</p> + </item> + <tag><c>{max_alloced_size, Size}</c></tag> + <item> + <p>Where <c>Size</c> is the maximum amount of memory + allocated on the heap since the emulator started.</p> + </item> + <tag><c>{alloced_size, Size}</c></tag> + <item> + <p>Where <c>Size</c> is the current amount of memory + allocated on the heap.</p> + </item> + <tag><c>{free_size, Size}</c></tag> + <item> + <p>Where <c>Size</c> is the current amount of free + memory on the heap.</p> + </item> + <tag><c>{no_alloced_blocks, No}</c></tag> + <item> + <p>Where <c>No</c> is the current number of allocated + blocks on the heap.</p> + </item> + <tag><c>{no_free_blocks, No}</c></tag> + <item> + <p>Where <c>No</c> is the current number of free blocks + on the heap.</p> + </item> + <tag><c>{smallest_alloced_block, Size}</c></tag> + <item> + <p>Where <c>Size</c> is the size of the smallest + allocated block on the heap.</p> + </item> + <tag><c>{largest_free_block, Size}</c></tag> + <item> + <p>Where <c>Size</c> is the size of the largest free + block on the heap.</p> + </item> + </taglist> + </item> + <tag><c>fullsweep_after</c></tag> + <item> + <p>Returns <c>{fullsweep_after, int()}</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>garbage_collection</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="#erlang: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> + </item> + <tag><c>global_heaps_size</c></tag> + <item> + <p>Returns the current size of the shared (global) heap.</p> + </item> + <tag><c>heap_sizes</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> + </item> + <tag><c>heap_type</c></tag> + <item> + <p>Returns the heap type used by the current emulator. + Currently the following heap types exist:</p> + <taglist> + <tag><c>private</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> + </item> + <tag><c>shared</c></tag> + <item> + <p>One heap for use by all processes. Messages passed + between processes are passed by reference.</p> + </item> + <tag><c>hybrid</c></tag> + <item> + <p>A hybrid of the <c>private</c> and <c>shared</c> heap + types. A shared heap as well as private heaps are + used.</p> + </item> + </taglist> + </item> + <tag><c>info</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> + </item> + <tag><c>kernel_poll</c></tag> + <item> + <p>Returns <c>true</c> if the emulator uses some kind of + kernel-poll implementation; otherwise, <c>false</c>.</p> + </item> + <tag><c>loaded</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> + </item> + <tag><c>logical_processors</c></tag> + <item> + <p>Returns the number of logical processors detected on the + system as an integer or the atom <c>unknown</c> if the + emulator wasn't able to detect any. + </p> + </item> + <tag><c>machine</c></tag> + <item> + <p>Returns a string containing the Erlang machine name.</p> + </item> + <tag><c>modified_timing_level</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> + </item> + <tag><c>multi_scheduling</c></tag> + <item> + <marker id="system_info_multi_scheduling"></marker> + <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> + </item> + <tag><c>multi_scheduling_blockers</c></tag> + <item> + <marker id="system_info_multi_scheduling_blockers"></marker> + <p>Returns a list of <c>PID</c>s when multi-scheduling + is blocked; otherwise, the empty list. The <c>PID</c>s + in the list is <c>PID</c>s of the processes currently + blocking multi-scheduling. A <c>PID</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> + </item> + <tag><c>otp_release</c></tag> + <item> + <marker id="system_info_otp_release"></marker> + <p>Returns a string containing the OTP release number.</p> + </item> + <tag><c>process_count</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.</p> + </item> + <tag><c>process_limit</c></tag> + <item> + <p>Returns the maximum number of concurrently existing + processes at the local node as an integer. This limit + can be configured at startup by using the command line + flag <c>+P</c>, see + <seealso marker="erts:erl#max_processes">erl(1)</seealso>.</p> + </item> + <tag><c>procs</c></tag> + <item> + <p>Returns a binary containing a string of process and port + 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> + </item> + <tag><c>scheduler_bind_type</c></tag> + <item> + <marker id="system_info_scheduler_bind_type"></marker> + <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 via + <seealso marker="#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, How)</seealso>, + 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 + <seealso marker="#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, How)</seealso>, and + <seealso marker="#system_info_scheduler_bindings">erlang:system_info(scheduler_bindings)</seealso>. + </p> + </item> + <tag><c>scheduler_bindings</c></tag> + <item> + <marker id="system_info_scheduler_bindings"></marker> + <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 + <seealso marker="#system_flag_scheduler_bind_type">erlang:system_flag(scheduler_bind_type, How)</seealso>, + <seealso marker="#system_info_schedulers_online">erlang:system_info(schedulers_online)</seealso>. + </p> + </item> + <tag><c>scheduler_id</c></tag> + <item> + <marker id="system_info_scheduler_id"></marker> + <p>Returns the scheduler id (<c>SchedulerId</c>) of the + scheduler thread that the calling process is executing + on. <c>SchedulerId</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> + </item> + <tag><c>schedulers</c></tag> + <item> + <marker id="system_info_schedulers"></marker> + <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><c>schedulers_online</c></tag> + <item> + <marker id="system_info_schedulers_online"></marker> + <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> + </item> + <tag><c>smp_support</c></tag> + <item> + <p>Returns <c>true</c> if the emulator has been compiled + with smp support; otherwise, <c>false</c>.</p> + </item> + <tag><c>system_version</c></tag> + <item> + <p>Returns a string containing version number and + some important properties such as the number of schedulers.</p> + </item> + <tag><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><c>thread_pool_size</c></tag> + <item> + <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">driver_async()</seealso>) + as an integer.</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><c>version</c></tag> + <item> + <marker id="system_info_version"></marker> + <p>Returns a string containing the version number of the + emulator.</p> + </item> + <tag><c>wordsize</c></tag> + <item> + <p>Returns the word size in bytes as an integer, i.e. on a + 32-bit architecture 4 is returned, and on a 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>erlang:system_monitor() -> MonSettings</name> + <fsummary>Current system performance monitoring settings</fsummary> + <type> + <v>MonSettings -> {MonitorPid, Options} | undefined</v> + <v> MonitorPid = pid()</v> + <v> Options = [Option]</v> + <v> Option = {long_gc, Time} | {large_heap, Size} | busy_port | busy_dist_port</v> + <v> Time = Size = int()</v> + </type> + <desc> + <p>Returns the current system monitoring settings set by + <seealso marker="#erlang:system_monitor/2">erlang:system_monitor/2</seealso> + as <c>{MonitorPid, Options}</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> + </desc> + </func> + + <func> + <name>erlang:system_monitor(undefined | {MonitorPid, Options}) -> MonSettings</name> + <fsummary>Set or clear system performance monitoring options</fsummary> + <type> + <v>MonitorPid, Options, MonSettings -- see below</v> + </type> + <desc> + <p>When called with the argument <c>undefined</c>, all + system performance monitoring settings are cleared.</p> + <p>Calling the function with <c>{MonitorPid, Options}</c> as + argument, is the same as calling + <seealso marker="#erlang:system_monitor/2">erlang:system_monitor(MonitorPid, Options)</seealso>.</p> + <p>Returns the previous system monitor settings just like + <seealso marker="#erlang:system_monitor/0">erlang:system_monitor/0</seealso>.</p> + </desc> + </func> + + <func> + <name>erlang:system_monitor(MonitorPid, [Option]) -> MonSettings</name> + <fsummary>Set system performance monitoring options</fsummary> + <type> + <v>MonitorPid = pid()</v> + <v>Option = {long_gc, Time} | {large_heap, Size} | busy_port | busy_dist_port</v> + <v> Time = Size = int()</v> + <v>MonSettings = {OldMonitorPid, [Option]}</v> + <v> OldMonitorPid = pid()</v> + </type> + <desc> + <p>Sets system performance monitoring options. <c>MonitorPid</c> + is a local pid that will receive system monitor messages, and + 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>{monitor, GcPid, long_gc, Info}</c> is sent to + <c>MonitorPid</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 + 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="#erlang: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> + </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>MonitorPid</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> + </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>MonitorPid</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> + <p>If a process in the system gets suspended because it + 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>MonitorPid</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="#erlang:system_monitor/0">erlang:system_monitor/0</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 + 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>MonitorPid</c> does not exist.</p> + </desc> + </func> + + <func> + <name>erlang:system_profile() -> ProfilerSettings</name> + <fsummary>Current system profiling settings</fsummary> + <type> + <v>ProfilerSettings -> {ProfilerPid, Options} | undefined</v> + <v> ProfilerPid = pid() | port()</v> + <v> Options = [Option]</v> + <v> Option = runnable_procs | runnable_ports | scheduler | exclusive</v> + </type> + <desc> + <p>Returns the current system profiling settings set by + <seealso marker="#erlang:system_profile/2">erlang:system_profile/2</seealso> + as <c>{ProfilerPid, Options}</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> + </desc> + </func> + + <func> + <name>erlang:system_profile(ProfilerPid, Options) -> ProfilerSettings</name> + <fsummary>Current system profiling settings</fsummary> + <type> + <v>ProfilerSettings -> {ProfilerPid, Options} | undefined</v> + <v> ProfilerPid = pid() | port()</v> + <v> Options = [Option]</v> + <v> Option = runnable_procs | runnable_ports | scheduler | exclusive</v> + </type> + <desc> + <p>Sets system profiler options. <c>ProfilerPid</c> + is a local pid or port that will receive profiling messages. The + receiver is excluded from all profiling. + The second argument is a list of profiling options:</p> + <taglist> + <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>ProfilerPid</c>. Running processes that is reinserted into the + run queue after having been preemptively scheduled out will 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>ProfilerPid</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>ProfilerPid</c>. + </p> + </item> + <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> + </item> + </taglist> + <note><p><c>erlang:system_profile</c> is considered experimental and + its behaviour may change in the future.</p> + </note> + </desc> + </func> + + <func> + <name>term_to_binary(Term) -> ext_binary()</name> + <fsummary>Encode a term to an Erlang external term format binary</fsummary> + <type> + <v>Term = term()</v> + </type> + <desc> + <p>Returns a binary data object which is the result of encoding + <c>Term</c> according to the Erlang external term format.</p> + <p>This can be used for a variety of 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> + </desc> + </func> + <func> + <name>term_to_binary(Term, [Option]) -> ext_binary()</name> + <fsummary>Encode a term to en Erlang external term format binary</fsummary> + <type> + <v>Term = term()</v> + <v>Option = compressed | {compressed,Level} | {minor_version,Version}</v> + </type> + <desc> + <p>Returns a binary data object which is the result of encoding + <c>Term</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,Level}</c>, where <c>Level</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,Version}</c> can be use to control + some details of the encoding. This option was + introduced in R11B-4. Currently, the allowed values for <c>Version</c> + are <c>0</c> and <c>1</c>.</p> + <p><c>{minor_version,1}</c> 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 the new representation.</p> + <p><c>{minor_version,0}</c> is currently the default, 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> + </desc> + </func> + <func> + <name>throw(Any)</name> + <fsummary>Throw an exception</fsummary> + <type> + <v>Any = term()</v> + </type> + <desc> + <p>A non-local return from a function. If evaluated within a + <c>catch</c>, <c>catch</c> will return the value <c>Any</c>.</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>time() -> {Hour, Minute, Second}</name> + <fsummary>Current time</fsummary> + <type> + <v>Hour = Minute = Second = int()</v> + </type> + <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> + <pre> +> <input>time().</input> +{9,42,44}</pre> + </desc> + </func> + <func> + <name>tl(List1) -> List2</name> + <fsummary>Tail of a list</fsummary> + <type> + <v>List1 = List2 = [term()]</v> + </type> + <desc> + <p>Returns the tail of <c>List1</c>, that is, the list minus + the first element.</p> + <pre> +> <input>tl([geesties, guilies, beasties]).</input> +[guilies, beasties]</pre> + <p>Allowed in guard tests.</p> + <p>Failure: <c>badarg</c> if <c>List</c> is the empty list [].</p> + </desc> + </func> + <func> + <name>erlang:trace(PidSpec, How, FlagList) -> int()</name> + <fsummary>Set trace flags for a process or processes</fsummary> + <type> + <v>PidSpec = pid() | existing | new | all</v> + <v>How = bool()</v> + <v>FlagList = [Flag]</v> + <v> Flag -- see below</v> + </type> + <desc> + <p>Turns on (if <c>How == true</c>) or off (if + <c>How == false</c>) the trace flags in <c>FlagList</c> for + the process or processes represented by <c>PidSpec</c>.</p> + <p><c>PidSpec</c> is either a pid for a local process, or one of + the following atoms:</p> + <taglist> + <tag><c>existing</c></tag> + <item> + <p>All processes currently existing.</p> + </item> + <tag><c>new</c></tag> + <item> + <p>All processes that will be created in the future.</p> + </item> + <tag><c>all</c></tag> + <item> + <p>All currently existing processes and all processes that + will be created in the future.</p> + </item> + </taglist> + <p><c>FlagList</c> can contain any number of the following + flags (the "message tags" refers to the list of messages + following below):</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 + 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> + </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> + </item> + <tag><c>call</c></tag> + <item> + <p>Trace certain function calls. Specify which function + calls to trace by calling + <seealso marker="#erlang:trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> + <p>Message tags: <c>call</c>, <c>return_from</c>.</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>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> + <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> + </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 + its caller. Only works for functions traced with + the <c>local</c> option to + <seealso marker="#erlang:trace_pattern/3">erlang:trace_pattern/3</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 + 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> + </item> + <tag><c>running</c></tag> + <item> + <p>Trace scheduling of processes.</p> + <p>Message tags: <c>in</c>, and <c>out</c>.</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> + </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> + </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 + <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 + CPU time measurements, <c>trace/3</c> exits with + <c>badarg</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 + <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> + </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> + </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> + </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> + </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> + </item> + </taglist> + <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_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> + <taglist> + <tag><c>{trace, Pid, 'receive', Msg}</c></tag> + <item> + <p>When <c>Pid</c> receives the message <c>Msg</c>.</p> + </item> + <tag><c>{trace, Pid, send, Msg, To}</c></tag> + <item> + <p>When <c>Pid</c> sends the message <c>Msg</c> to + the process <c>To</c>.</p> + </item> + <tag><c>{trace, Pid, send_to_non_existing_process, Msg, To}</c></tag> + <item> + <p>When <c>Pid</c> sends the message <c>Msg</c> to + the non-existing process <c>To</c>.</p> + </item> + <tag><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 + 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> + <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, + 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 + least one call generated a <c>call</c> trace message + (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> + <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 + 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> + <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 + a match specification with an <c>exception_trace</c> action.</p> + </item> + <tag><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> + </item> + <tag><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> + <item> + <p>When <c>Pid</c> links to a process <c>Pid2</c>.</p> + </item> + <tag><c>{trace, Pid, unlink, Pid2}</c></tag> + <item> + <p>When <c>Pid</c> removes the link from a process + <c>Pid2</c>.</p> + </item> + <tag><c>{trace, Pid, getting_linked, Pid2}</c></tag> + <item> + <p>When <c>Pid</c> gets linked to a process <c>Pid2</c>.</p> + </item> + <tag><c>{trace, Pid, getting_unlinked, Pid2}</c></tag> + <item> + <p>When <c>Pid</c> gets unlinked from a process <c>Pid2</c>.</p> + </item> + <tag><c>{trace, Pid, register, RegName}</c></tag> + <item> + <p>When <c>Pid</c> gets the name <c>RegName</c> registered.</p> + </item> + <tag><c>{trace, Pid, unregister, RegName}</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> + </item> + <tag><c>{trace, Pid, in, {M, F, Arity} | 0}</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> + </item> + <tag><c>{trace, Pid, out, {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 + the current function cannot be determined, then the last + element <c>Arity</c> is 0.</p> + </item> + <tag><c>{trace, Pid, gc_start, Info}</c></tag> + <item> + <marker id="gc_start"></marker> + <p>Sent when 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> + <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>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>stack_size</c></tag> + <item>The actual size of the stack.</item> + <tag><c>recent_size</c></tag> + <item>The size of the data that survived the previous garbage + collection.</item> + <tag><c>mbuf_size</c></tag> + <item>The combined size of message buffers associated with + the process.</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 + 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>PidSpec</c>. If <c>PidSpec</c> is a pid, + the return value will be <c>1</c>. If <c>PidSpec</c> is + <c>all</c> or <c>existing</c> the return value will be + the number of processes running, excluding tracer processes. + If <c>PidSpec</c> is <c>new</c>, the return value will be + <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> + </desc> + </func> + <func> + <name>erlang:trace_delivered(Tracee) -> Ref</name> + <fsummary>Notification when trace has been delivered</fsummary> + <type> + <v>Tracee = pid() | all</v> + <v>Ref = reference()</v> + </type> + <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>Tracee</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(Tracee)</c>. A + <c>{trace_delivered, Tracee, Ref}</c> message is sent to + the caller of <c>erlang:trace_delivered(Tracee)</c> when it + is guaranteed that all trace messages have been delivered to + the tracer up to the point that the <c>Tracee</c> had reached + at the time of the call to + <c>erlang:trace_delivered(Tracee)</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>Tracee</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>trace_delivered</c> message arrives.</p> + <p>Note that <c>Tracee</c> has to refer to a process currently, + or previously existing on the same node as the caller of + <c>erlang:trace_delivered(Tracee)</c> resides on. + The special <c>Tracee</c> atom <c>all</c> denotes all processes + that currently are traced in the node.</p> + <p>An example: Process <c>A</c> is tracee, 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, Ref}</c> message before closing + <c>B</c>.</p> + <p>Failure: <c>badarg</c> if <c>Tracee</c> does not refer to a + process (dead or alive) on the same node as the caller of + <c>erlang:trace_delivered(Tracee)</c> resides on.</p> + </desc> + </func> + <func> + <name>erlang:trace_info(PidOrFunc, Item) -> Res</name> + <fsummary>Trace information about a process or function</fsummary> + <type> + <v>PidOrFunc = pid() | new | {Module, Function, Arity} | on_load</v> + <v> Module = Function = atom()</v> + <v> Arity = int()</v> + <v>Item, Res -- see below</v> + </type> + <desc> + <p>Returns trace information about a process or function.</p> + <p>To get information about a process, <c>PidOrFunc</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>Item</c> must have one of the following + values:</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 + 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>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> + </item> + </taglist> + <p>To get information about a function, <c>PidOrFunc</c> should + be a 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> + <taglist> + <tag><c>traced</c></tag> + <item> + <p>Return <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> + </item> + <tag><c>match_spec</c></tag> + <item> + <p>Return 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> + </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 + 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 + <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="#erlang:trace_pattern/3">erlang:trace_pattern/3</seealso>.</p> + </item> + <tag><c>all</c></tag> + <item> + <p>Return a list containing the <c>{Item, Value}</c> tuples + for all other items, or return <c>false</c> if no tracing + is active for this function.</p> + </item> + </taglist> + <p>The actual return value will be <c>{Item, 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>PidOrFunc</c> is the <c>on_load</c>, the information + returned refers to the default value for code that will be + loaded.</p> + </desc> + </func> + <func> + <name>erlang:trace_pattern(MFA, MatchSpec) -> int()</name> + <fsummary>Set trace patterns for global call tracing</fsummary> + <desc> + <p>The same as + <seealso marker="#erlang:trace_pattern/3">erlang:trace_pattern(MFA, MatchSpec, [])</seealso>, + retained for backward compatibility.</p> + </desc> + </func> + <func> + <name>erlang:trace_pattern(MFA, MatchSpec, FlagList) -> int()</name> + <fsummary>Set trace patterns for tracing of function calls</fsummary> + <type> + <v>MFA, MatchSpec, FlagList -- see below</v> + </type> + <desc> + <p>This BIF is used to enable or disable call tracing for + exported functions. It must be combined with + <seealso marker="#erlang: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="#erlang: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> + 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>MFA</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> + <taglist> + <tag><c>{Module,Function,'_'}</c></tag> + <item> + <p>All exported 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> + </item> + <tag><c>{'_','_','_'}</c></tag> + <item> + <p>All exported 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>FlagList</c>.</p> + <p>If the <c>MFA</c> argument is the atom <c>on_load</c>, + the match specification and flag list will be used on all + modules that are newly loaded.</p> + <p>The <c>MatchSpec</c> argument can take any of 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> + </item> + <tag><c>true</c></tag> + <item> + <p>Enable tracing for the matching function(s).</p> + </item> + <tag><c>MatchSpecList</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> + </item> + <tag><c>restart</c></tag> + <item> + <p>For the <c>FlagList</c> option <c>call_count</c>: + restart the existing counters. The behaviour is undefined + for other <c>FlagList</c> options.</p> + </item> + <tag><c>pause</c></tag> + <item> + <p>For the <c>FlagList</c> option <c>call_count</c>: pause + the existing counters. The behaviour is undefined for + other <c>FlagList</c> options.</p> + </item> + </taglist> + <p>The <c>FlagList</c> parameter is a list of options. + The following options are allowed:</p> + <taglist> + <tag><c>global</c></tag> + <item> + <p>Turn 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> + </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 + 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 + when this function returns to its caller.</p> + </item> + <tag><c>meta | {meta, Pid}</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>Pid</c> whenever any of the specified + functions are called, regardless of how they are called. + If no <c>Pid</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>, + 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> + </item> + <tag><c>call_count</c></tag> + <item> + <p>Starts (<c>MatchSpec == true</c>) or stops + (<c>MatchSpec == 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>MatchSpec == pause</c>. Paused and running + counters can be restarted from zero with + <c>MatchSpec == restart</c>.</p> + <p>The counter value can be read with + <seealso marker="#erlang:trace_info/2">erlang:trace_info/2</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 + locally traced. If global tracing is specified for a + specified set of functions; local, meta and call count + tracing for the matching set of local functions will be + disabled, and vice versa.</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="#erlang: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>MFA</c> argument. This will be zero if none matched at + all.</p> + </desc> + </func> + <func> + <name>trunc(Number) -> int()</name> + <fsummary>Return an integer by the truncating a number</fsummary> + <type> + <v>Number = number()</v> + </type> + <desc> + <p>Returns an integer by the truncating <c>Number</c>.</p> + <pre> +> <input>trunc(5.5).</input> +5</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>tuple_size(Tuple) -> int()</name> + <fsummary>Return the size of a tuple</fsummary> + <type> + <v>Tuple = tuple()</v> + </type> + <desc> + <p>Returns an integer which is the number of elements in <c>Tuple</c>.</p> + <pre> +> <input>tuple_size({morni, mulle, bwange}).</input> +3</pre> + <p>Allowed in guard tests.</p> + </desc> + </func> + <func> + <name>tuple_to_list(Tuple) -> [term()]</name> + <fsummary>Convert a tuple to a list</fsummary> + <type> + <v>Tuple = tuple()</v> + </type> + <desc> + <p>Returns a list which corresponds to <c>Tuple</c>. + <c>Tuple</c> may contain any Erlang terms.</p> + <pre> +> <input>tuple_to_list({share, {'Ericsson_B', 163}}).</input> +[share,{'Ericsson_B',163}]</pre> + </desc> + </func> + <func> + <name>erlang:universaltime() -> {Date, Time}</name> + <fsummary>Current date and time according to Universal Time Coordinated (UTC)</fsummary> + <type> + <v>Date = {Year, Month, Day}</v> + <v>Time = {Hour, Minute, Second}</v> + <v> Year = Month = Day = Hour = Minute = Second = int()</v> + </type> + <desc> + <p>Returns the current date and time according to Universal + Time Coordinated (UTC), also called GMT, 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> + <pre> +> <input>erlang:universaltime().</input> +{{1996,11,6},{14,18,43}}</pre> + </desc> + </func> + <func> + <name>erlang:universaltime_to_localtime({Date1, Time1}) -> {Date2, Time2}</name> + <fsummary>Convert from Universal Time Coordinated (UTC) to local date and time</fsummary> + <type> + <v>Date1 = Date2 = {Year, Month, Day}</v> + <v>Time1 = Time2 = {Hour, Minute, Second}</v> + <v> Year = Month = Day = Hour = Minute = Second = int()</v> + </type> + <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>{Date1, Time1}</c> is returned.</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>Date1</c> or <c>Time1</c> do + not denote a valid date or time.</p> + </desc> + </func> + <func> + <name>unlink(Id) -> true</name> + <fsummary>Remove a link, if there is one, to another process or port</fsummary> + <type> + <v>Id = pid() | port()</v> + </type> + <desc> + <p>Removes the link, if there is one, between the calling + process and the process or port referred to by <c>Id</c>.</p> + <p>Returns <c>true</c> and does not fail, even if there is no + link to <c>Id</c>, or if <c>Id</c> does not exist.</p> + <p>Once <c>unlink(Id)</c> has returned it is guaranteed that + the link between the caller and the entity referred to by + <c>Id</c> has no effect on the caller in the future (unless + the link is setup again). If caller is trapping exits, an + <c>{'EXIT', Id, _}</c> message due to the link might have + been placed in the callers message queue prior to the call, + though. Note, the <c>{'EXIT', Id, _}</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>may</em> be + appropriate to cleanup the message queue when trapping exits + after the call to <c>unlink(Id)</c>, as follow:</p> + <code type="none"> + + unlink(Id), + receive +\011{'EXIT', Id, _} -> +\011 true + after 0 -> +\011 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 + until the "unlink signal" reached the linked entity. This + had one undesirable effect, though. 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: + asynchronously send an "unlink signal" to the linked entity + and ignore any future results of the link.</p> + </note> + </desc> + </func> + <func> + <name>unregister(RegName) -> true</name> + <fsummary>Remove the registered name for a process (or port)</fsummary> + <type> + <v>RegName = atom()</v> + </type> + <desc> + <p>Removes the registered name <c>RegName</c>, associated with a + pid or a port identifier.</p> + <pre> +> <input>unregister(db).</input> +true</pre> + <p>Users are advised not to unregister system processes.</p> + <p>Failure: <c>badarg</c> if <c>RegName</c> is not a registered + name.</p> + </desc> + </func> + <func> + <name>whereis(RegName) -> pid() | port() | undefined</name> + <fsummary>Get the pid (or port) with a given 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> + <pre> +> <input>whereis(db).</input> +<0.43.0></pre> + </desc> + </func> + <func> + <name>erlang:yield() -> true</name> + <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 + <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> + </desc> + </func> + </funcs> +</erlref> + diff --git a/erts/doc/src/erlc.xml b/erts/doc/src/erlc.xml new file mode 100644 index 0000000000..3859ac8365 --- /dev/null +++ b/erts/doc/src/erlc.xml @@ -0,0 +1,256 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE comref SYSTEM "comref.dtd"> + +<comref> + <header> + <copyright> + <year>1997</year><year>2009</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>erlc</title> + <prepared>Björn Gustavsson</prepared> + <responsible>Bjarne Däcker</responsible> + <docno>1</docno> + <approved>Bjarne Däcker</approved> + <checked></checked> + <date>97-03-24</date> + <rev>A</rev> + <file>erlc.xml</file> + </header> + <com>erlc</com> + <comsummary>Compiler</comsummary> + <description> + <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> + </description> + <funcs> + <func> + <name>erlc flags file1.ext file2.ext...</name> + <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> + </desc> + </func> + </funcs> + + <section> + <title>Generally Useful Flags</title> + <p>The following flags are supported: + </p> + <taglist> + <tag>-I <em>directory</em></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_dir]]></c> directive, the + compiler searches for header files in the following + directories:</p> + <list type="ordered"> + <item> + <p><c><![CDATA["."]]></c>, the current working directory of the + file server;</p> + </item> + <item> + <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> + </item> + </list> + </item> + <tag>-o <em>directory</em></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> + </item> + <tag>-D<em>name</em></tag> + <item> + <p>Defines a macro.</p> + </item> + <tag>-D<em>name</em>=<em>value</em></tag> + <item> + <p>Defines a macro with the given 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 + must be quoted on all platforms.</p> + </item> + <tag>-W<em>number</em></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> + </item> + <tag>-W</tag> + <item> + <p>Same as <c><![CDATA[-W1]]></c>. Default.</p> + </item> + <tag>-v</tag> + <item> + <p>Enables verbose output.</p> + </item> + <tag>-b <em>output-type</em></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 + a single output format.</p> + </item> + <tag>-hybrid</tag> + <item> + <p>Compile using the hybrid-heap 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> + </item> + <tag>-smp</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> + </item> + <tag>--</tag> + <item> + <p>Signals that no more options will follow. + The rest of the arguments will be treated as file names, + even if they start with hyphens.</p> + </item> + <tag>+<em>term</em></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 + the compiler. + For instance, the <c><![CDATA[export_all]]></c> option 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 + must be quoted on all platforms.</p> + </item> + </taglist> + </section> + + <section> + <title>Special Flags</title> + <p>The flags in this section are useful in special situations + such as re-building the OTP system.</p> + <taglist> + <tag>-pa <em>directory</em></tag> + <item> + <p>Appends <em>directory</em> 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> + <item> + <p>Appends <em>directory</em> to the code path in + the invoked Erlang emulator.</p> + </item> + </taglist> + </section> + + <section> + <title>Supported Compilers</title> + <taglist> + <tag>.erl</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> + </item> + <tag>.yrl</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> + </item> + <tag>.mib</tag> + <item> + <p>MIB for SNMP. It generates a <c><![CDATA[.bin]]></c> file.</p> + <p>Supported options: -I, -o, -W.</p> + </item> + <tag>.bin</tag> + <item> + <p>A compiled MIB for SNMP. It generates a <c><![CDATA[.hrl]]></c> file.</p> + <p>Supported options: -o, -v.</p> + </item> + <tag>.rel</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> + </item> + <tag>.asn1</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> + </item> + <tag>.idl</tag> + <item> + <p>IC file.</p> + <p>Runs the IDL compiler.</p> + <p>Supported options: -I, -o.</p> + </item> + </taglist> + </section> + + <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> + </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> + </section> +</comref> + diff --git a/erts/doc/src/erlsrv.xml b/erts/doc/src/erlsrv.xml new file mode 100644 index 0000000000..93db56fc7c --- /dev/null +++ b/erts/doc/src/erlsrv.xml @@ -0,0 +1,405 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE comref SYSTEM "comref.dtd"> + +<comref> + <header> + <copyright> + <year>1998</year><year>2009</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>erlsrv</title> + <prepared>Patrik Nyblom</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>98-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> + <description> + <p>This utility is specific to Windows NT/2000/XP® (and subsequent 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 + 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 + itself is (default) run as the local administrator. This can be + 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"> + <item> + <p><c><![CDATA[StopAction]]></c>: This 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 + manager.</p> + </item> + <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> + </item> + <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> + </item> + <item> + <p><c><![CDATA[Env]]></c>: Specifies an <em>additional</em> environment + for the emulator. The environment variables specified + 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 + environment specification will be set to the value specified + in the service.</p> + </item> + <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>. + Debug log files will be placed in this directory.</p> + </item> + <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> + </item> + <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> + </item> + <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 + 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> + </item> + <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> + </item> + <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> + </item> + <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> + </item> + </list> + <p> <marker id="001"></marker> + The naming of the service in a system that + uses release handling has to 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 "@") 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> + <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 + (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> + <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>. + </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 | 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 + <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> + </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> + </desc> + </func> + <func> + <name>erlsrv list [<service-name>]</name> + <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> + </desc> + </func> + <func> + <name>erlsrv help</name> + <fsummary>Display a brief help text</fsummary> + </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> + <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> + </section> + + <section> + <title>PORT PROGRAMS</title> + <p>When a program runs in + the service context, it has to handle the control events that is + 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 + (normal for port programs) uses the win32 function + <c><![CDATA[SetConsoleCtrlHandler]]></c> to a control handler that returns + TRUE in answer to the <c><![CDATA[CTRL_LOGOFF_EVENT]]></c>. 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> + <code type="none"><![CDATA[ +#include <windows.h> +/* +** A Console control handler that ignores the log off events, +** and lets the default handler take care of other events. +*/ +BOOL WINAPI service_aware_handler(DWORD ctrl){ + if(ctrl == CTRL_LOGOFF_EVENT) +\011return TRUE; + return FALSE; +} + +void initialize_handler(void){ + char buffer[2]; + /* + * We assume we are running as a service if this + * environment variable is defined + */ + if(GetEnvironmentVariable("ERLSRV_SERVICE_NAME",buffer, + (DWORD) 2)){ +\011/* +\011** Actually set the control handler +\011*/ +\011SetConsoleCtrlHandler(&service_aware_handler, TRUE); + } +} ]]></code> + </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 + 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 + 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 + <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> + </section> + + <section> + <title>SEE ALSO</title> + <p>start_erl(1), release_handler(3)</p> + </section> +</comref> + diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml new file mode 100644 index 0000000000..d51e5b3ea4 --- /dev/null +++ b/erts/doc/src/erts_alloc.xml @@ -0,0 +1,554 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE cref SYSTEM "cref.dtd"> + +<cref> + <header> + <copyright> + <year>2002</year><year>2009</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_alloc</title> + <prepared>Rickard Green</prepared> + <docno>1</docno> + <date>03-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> + <description> + <p><c>erts_alloc</c> is an Erlang Run-Time System internal memory + allocator library. <c>erts_alloc</c> provides the Erlang + Run-Time 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> + <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> + <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> + <tag><c>driver_alloc</c></tag> + <item>Allocator used for driver data.</item> + <tag><c>sl_alloc</c></tag> + <item>Allocator used for memory blocks that are expected to be + 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> + <tag><c>fix_alloc</c></tag> + <item>A very fast allocator used for some fix-sized + data. <c>fix_alloc</c> manages a set of memory pools from + which memory blocks are handed out. <c>fix_alloc</c> + allocates memory pools from <c>ll_alloc</c>. Memory pools + that have been allocated are never deallocated.</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> + <tag><c>sys_alloc</c></tag> + <item>This is normally the default <c>malloc</c> implementation + 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> + </taglist> + <p><c>sys_alloc</c> and <c>fix_alloc</c> are always enabled 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 + 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> + </section> + + <section> + <marker id="alloc_util"></marker> + <title>The alloc_util framework</title> + <p>Internally a framework called <c>alloc_util</c> is used for + implementing allocators. <c>sys_alloc</c>, <c>fix_alloc</c>, and + <c>mseg_alloc</c> do not use this framework; hence, 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 smaller than the value of the + <c>sbct</c> parameter are placed in multiblock + carriers. 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> + <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_smbcs">mbcgs</seealso>) parameters. 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 + <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 to whole pages.</p> + <p>Sizes of carriers allocated via <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> + <p>Coalescing of free blocks are always performed immediately. + 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> + <taglist> + <tag>Best fit</tag> + <item> + <p>Strategy: Find the smallest block that satisfies the + requested block size.</p> + <p>Implementation: A balanced binary search tree is + used. The time complexity is proportional to log N, where + N is the number of sizes of free blocks.</p> + </item> + <tag>Address order best fit</tag> + <item> + <p>Strategy: Find the smallest block that satisfies 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 + used. The time complexity is proportional to log N, where + N is the number of free blocks.</p> + </item> + <tag>Good fit</tag> + <item> + <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 + has a time complexity that is constant. The maximum block + search depth is configurable via the + <seealso marker="#M_mbsd">mbsd</seealso> parameter.</p> + </item> + <tag>A fit</tag> + <item> + <p>Strategy: Do not search for a fit, inspect only one free + 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 + 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> + </item> + </taglist> + </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 + 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> + 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 + arguments.</p> + <p>System flags effecting specific allocators have an upper-case + letter as <c><![CDATA[<S>]]></c>. The following letters are used for + the currently present 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>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>Y: sys_alloc</c></item> + </list> + <p>The following flags are available for configuration of + <c>mseg_alloc</c>:</p> + <taglist> + <tag><c><![CDATA[+MMamcbf <size>]]></c></tag> + <item> <marker id="MMamcbf"></marker> + + 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><c><![CDATA[+MMrmcbf <ratio>]]></c></tag> + <item> <marker id="MMrmcbf"></marker> + + 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><c><![CDATA[+MMmcs <amount>]]></c></tag> + <item> <marker id="MMmcs"></marker> + + Max cached segments. The maximum number of memory segments + stored in the memory segment cache. Valid range is + 0-30. Default value is 5.</item> + <tag><c><![CDATA[+MMcci <time>]]></c></tag> + <item> <marker id="MMcci"></marker> + + Cache check interval (in milliseconds). The memory segment + cache is checked for segments to destroy at an interval + determined by this parameter. Default value is 1000.</item> + </taglist> + <p>The following flags are available for configuration of + <c>fix_alloc</c>:</p> + <taglist> + <tag><c>+MFe true</c></tag> + <item> <marker id="MFe"></marker> + + Enable <c>fix_alloc</c>. Note: <c>fix_alloc</c> cannot be disabled.</item> + </taglist> + <p>The following flags are available for configuration of + <c>sys_alloc</c>:</p> + <taglist> + <tag><c>+MYe true</c></tag> + <item> <marker id="MYe"></marker> + + Enable <c>sys_alloc</c>. Note: <c>sys_alloc</c> cannot be disabled.</item> + <tag><c>+MYm libc</c></tag> + <item> <marker id="MYm"></marker> +<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><c><![CDATA[+MYtt <size>]]></c></tag> + <item> <marker id="MYtt"></marker> + + 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><c><![CDATA[+MYtp <size>]]></c></tag> + <item> <marker id="MYtp"></marker> + + 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>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><c><![CDATA[+M<S>as bf|aobf|gf|af]]></c></tag> + <item> <marker id="M_as"></marker> + + Allocation strategy. Valid strategies are <c>bf</c> (best fit), + <c>aobf</c> (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><c><![CDATA[+M<S>asbcst <size>]]></c></tag> + <item> <marker id="M_asbcst"></marker> + + 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><c><![CDATA[+M<S>e true|false]]></c></tag> + <item> <marker id="M_e"></marker> + + Enable allocator <c><![CDATA[<S>]]></c>.</item> + <tag><c><![CDATA[+M<S>lmbcs <size>]]></c></tag> + <item> <marker id="M_lmbcs"></marker> + + 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.</item> + <tag><c><![CDATA[+M<S>mbcgs <ratio>]]></c></tag> + <item> <marker id="M_mbcgs"></marker> + + (<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><c><![CDATA[+M<S>mbsd <depth>]]></c></tag> + <item> <marker id="M_mbsd"></marker> + + 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><c><![CDATA[+M<S>mmbcs <size>]]></c></tag> + <item> <marker id="M_mmbcs"></marker> + + 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><c><![CDATA[+M<S>mmmbc <amount>]]></c></tag> + <item> <marker id="M_mmmbc"></marker> + + 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><c><![CDATA[+M<S>mmsbc <amount>]]></c></tag> + <item> <marker id="M_mmsbc"></marker> + + 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><c><![CDATA[+M<S>ramv <bool>]]></c></tag> + <item> <marker id="M_ramv"></marker> + + 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><c><![CDATA[+M<S>rmbcmt <ratio>]]></c></tag> + <item> <marker id="M_rmbcmt"></marker> + + 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><c><![CDATA[+M<S>rsbcmt <ratio>]]></c></tag> + <item> <marker id="M_rsbcmt"></marker> + + 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><c><![CDATA[+M<S>rsbcst <ratio>]]></c></tag> + <item> <marker id="M_rsbcst"></marker> + + 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><c><![CDATA[+M<S>sbct <size>]]></c></tag> + <item> <marker id="M_sbct"></marker> + + 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.</item> + <tag><c><![CDATA[+M<S>smbcs <size>]]></c></tag> + <item> <marker id="M_smbcs"></marker> + + 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><c><![CDATA[+M<S>t true|false|<amount>]]></c></tag> + <item> <marker id="M_t"></marker> + + 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 (<c>N</c> equals the number of scheduler threads): + <taglist> + <tag><c>temp_alloc</c></tag> + <item><c>N + 1</c> instances.</item> + <tag><c>ll_alloc</c></tag> + <item><c>1</c> instance.</item> + <tag>Other allocators</tag> + <item><c>N</c> instances when <c>N</c> is less than or equal to + <c>16</c>. <c>16</c> instances when <c>N</c> is greater than + <c>16</c>.</item> + </taglist> + <c>temp_alloc</c> will always use <c>N + 1</c> instances when + this option has been enabled regardless of the amount passed. + Other allocators will use the same amount of instances as the + amount passed as long as it isn't greater than <c>N</c>. + </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><c><![CDATA[+Muycs <size>]]></c></tag> + <item> <marker id="Muycs"></marker> +<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><c><![CDATA[+Mummc <amount>]]></c></tag> + <item> <marker id="Mummc"></marker> + + 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> + </taglist> + <p>Instrumentation flags:</p> + <taglist> + <tag><c>+Mim true|false</c></tag> + <item> <marker id="Mim"></marker> + + 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><c>+Mis true|false</c></tag> + <item> <marker id="Mis"></marker> + + Status over allocated memory is kept by the emulator. The + allocation status can be retrieved via the <c>instrument</c> + module.</item> + <tag><c>+Mit X</c></tag> + <item> <marker id="Mit"></marker> + + 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><c>+Mea min|max|r9c|r10b|r11b|config</c></tag> + <item> <marker id="Mea"></marker> + <taglist> + <tag><c>min</c></tag> + <item> + Disables all allocators that can be disabled. + </item> + + <tag><c>max</c></tag> + <item> + Enables all allocators (currently default). + </item> + + <tag><c>r9c|r10b|r11b</c></tag> + <item> + Configures all allocators as they were configured in respective + OTP release. These will eventually be removed. + </item> + + <tag><c>config</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. + </item> + </taglist> + </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> + <note> + <p>Most of these flags are highly implementation dependent, and they + may 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> + </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 + <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> + </section> +</cref> + diff --git a/erts/doc/src/escript.xml b/erts/doc/src/escript.xml new file mode 100644 index 0000000000..8df179b3e2 --- /dev/null +++ b/erts/doc/src/escript.xml @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE comref SYSTEM "comref.dtd"> + +<comref> + <header> + <copyright> + <year>2007</year><year>2009</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>escript</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>escript.xml</file> + </header> + <com>escript</com> + <comsummary>Erlang scripting support</comsummary> + <description> + <p><c><![CDATA[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> + </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> + <desc> + <p><c><![CDATA[escript]]></c> runs a script written in Erlang.</p> + <p>Here follows an example.</p> + <pre> +$ <input>cat factorial</input> +#!/usr/bin/env escript +%% -*- erlang -*- +%%! -smp enable -sname factorial -mnesia debug verbose +main([String]) -> + try +\011N = list_to_integer(String), +\011F = fac(N), +\011io:format("factorial ~w = ~w\ +", [N,F]) + catch +\011_:_ -> +\011 usage() + end; +main(_) -> + usage(). + +usage() -> + io:format("usage: factorial integer\ +"), + halt(1). + +fac(0) -> 1; +fac(N) -> N * fac(N-1). +$ <input>factorial 5</input> +factorial 5 = 120 +$ <input>factorial</input> +usage: factorial integer +$ <input>factorial five</input> +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><![CDATA[escript]]></c>. However if you invoke the + <c><![CDATA[escript]]></c> like this</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 + enter the major mode for editing Erlang source files. If the + directive is present it must be located on the second + line.</p> + <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> + <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> + <p>If you know the location of the <c><![CDATA[escript]]></c> executable, the first + line can directly give the path to <c><![CDATA[escript]]></c>. For instance:</p> + <pre> +#!/usr/local/bin/escript </pre> + <p>As any other kind of scripts, Erlang scripts will not work on + Unix platforms if the execution bit for the script file is not set. + (Use <c><![CDATA[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><![CDATA[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> + + <p>If the <c><![CDATA[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><![CDATA[halt(ExitCode)]]></c>; + for instance:</p> + <pre> +halt(1).</pre> + + <p>Call <c><![CDATA[escript:script_name/0]]></c> from your to + script to retrieve the pathname of the 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><![CDATA[?MODULE]]></c>) as well as include directives like + the <c><![CDATA[-include_lib]]></c> directive. For instance, use</p> + <pre> +-include_lib("kernel/include/file.hrl"). </pre> + <p>to include the record definitions for the records used by the + <c><![CDATA[file:read_link_info/1]]></c> function.</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>Both the module declaration and the export declaration of + the <c><![CDATA[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> +-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.</p> + + <p>As mentioned earlier, it is possible to have a script which + 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 + 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 + 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 + 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> +$ <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> + </desc> + </func> + </funcs> + + <section> + <title>Options accepted by escript</title> + <taglist> + <tag>-c</tag> + <item>Compile 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. + </item> + + <tag>-i</tag> + <item>Interpret the escript regardless of the value of the mode attribute. + </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> + </taglist> + </section> +</comref> + diff --git a/erts/doc/src/fascicules.xml b/erts/doc/src/fascicules.xml new file mode 100644 index 0000000000..cae197a516 --- /dev/null +++ b/erts/doc/src/fascicules.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="latin1" ?> +<!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 new file mode 100644 index 0000000000..18cf65759a --- /dev/null +++ b/erts/doc/src/inet_cfg.xml @@ -0,0 +1,397 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2004</year><year>2009</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>Inet configuration</title> + <prepared>Peter Andersson</prepared> + <docno></docno> + <date>2004-03-02</date> + <rev>PA1</rev> + <file>inet_cfg.xml</file> + </header> + + <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>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> + <p>If Erlang is started in long name distributed mode, it needs to + get the domain name from somewhere and will read system inet + 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 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> + </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> + <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 + and nameserver), others overwrite any previous settings + (e.g. 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> + <taglist> + <tag><em><c><![CDATA[{file, Format, File}.]]></c></em></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> + </item> + <tag><em><c><![CDATA[{resolv_conf, File}.]]></c></em></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 DNS client + <seealso marker="kernel:inet_res">inet_res</seealso>, + and monitor for changes, even if it does not exist. + The path must be absolute.</p> + <p>This may 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 + 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 + 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 + 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> + <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 + 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>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 + 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 + 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> + <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> + </item> + <tag><em><c><![CDATA[{host, IP, Aliases}.]]></c></em></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> + <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> + <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 + nameserver to use for + <seealso marker="kernel:inet_res">inet_res</seealso>.</p> + <p></p> + </item> + <tag><em><c><![CDATA[{alt_nameserver, IP [,Port]}.]]></c></em></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 + nameserver for + <seealso marker="kernel:inet_res">inet_res</seealso>.</p> + <p></p> + </item> + <tag><em><c><![CDATA[{search, Domains}.]]></c></em></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> + </item> + <tag><em><c><![CDATA[{lookup, Methods}.]]></c></em></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></p> + </item> + <tag><em><c><![CDATA[{cache_size, Size}.]]></c></em></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> + </item> + <tag><em><c><![CDATA[{cache_refresh, Time}.]]></c></em></tag> + <item> + <p></p> + <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> + </item> + <tag><em><c><![CDATA[{timeout, Time}.]]></c></em></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 + made by + <seealso marker="kernel:inet_res">inet_res</seealso>. + Default is 2 sec.</p> + <p></p> + </item> + <tag><em><c><![CDATA[{retry, N}.]]></c></em></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> + </item> + <tag><em><c><![CDATA[{inet6, Bool}.]]></c></em></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> + </item> + <tag><em><c><![CDATA[{usevc, Bool}.]]></c></em></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> + </item> + <tag><em><c><![CDATA[{edns, Version}.]]></c></em></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> + </item> + <tag><em><c><![CDATA[{udp_payload_size, Size}.]]></c></em></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> + 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, + 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> + </item> + <tag><em><c><![CDATA[{udp, Module}.]]></c></em></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> + </item> + <tag><em><c><![CDATA[{tcp, Module}.]]></c></em></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> + </item> + <tag><em><c><![CDATA[clear_hosts.]]></c></em></tag> + <item> + <p></p> + <p>Clear the hosts table.</p> + <p></p> + </item> + <tag><em><c><![CDATA[clear_ns.]]></c></em></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> + <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 + 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 + (in this example named <c><![CDATA[erl_inetrc]]></c>, stored + in directory <c><![CDATA[./cfg_files]]></c>) could then look like this + (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> + </section> +</chapter> + diff --git a/erts/doc/src/init.xml b/erts/doc/src/init.xml new file mode 100644 index 0000000000..33364c709a --- /dev/null +++ b/erts/doc/src/init.xml @@ -0,0 +1,384 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>1996</year><year>2009</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>init</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>init.xml</file> + </header> + <module>init</module> + <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><c>init</c> also contains functions to restart, reboot, and stop + the system.</p> + </description> + <funcs> + <func> + <name>boot(BootArgs) -> void()</name> + <fsummary>Start the Erlang runtime system</fsummary> + <type> + <v>BootArgs = [binary()]</v> + </type> + <desc> + <p>Starts the Erlang runtime system. This function is called + when the emulator is started and coordinates system start-up.</p> + <p><c>BootArgs</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. + 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> + </desc> + </func> + <func> + <name>get_args() -> [Arg]</name> + <fsummary>Get all non-flag command line arguments</fsummary> + <type> + <v>Arg = atom()</v> + </type> + <desc> + <p>Returns any plain command line arguments as a list of atoms + (possibly empty). It is recommended that + <c>get_plain_arguments/1</c> is used instead, because of + the limited length of atoms.</p> + </desc> + </func> + <func> + <name>get_argument(Flag) -> {ok, Arg} | error</name> + <fsummary>Get the values associated with a command line user flag</fsummary> + <type> + <v>Flag = atom()</v> + <v>Arg = [Values]</v> + <v> Values = [string()]</v> + </type> + <desc> + <p>Returns all values associated with the command line user flag + <c>Flag</c>. If <c>Flag</c> is provided several times, each + <c>Values</c> is returned in preserved order.</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 + 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> + <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> + <pre> +3> <input>init:get_argument(progname).</input> +{ok,[["erl"]]}</pre> + </item> + <tag><c>home</c></tag> + <item> + <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> + </desc> + </func> + <func> + <name>get_arguments() -> Flags</name> + <fsummary>Get all command line user flags</fsummary> + <type> + <v>Flags = [{Flag, Values}]</v> + <v> Flag = atom()</v> + <v> Values = [string()]</v> + </type> + <desc> + <p>Returns all command line flags, as well as the system + defined flags, see <c>get_argument/1</c>.</p> + </desc> + </func> + <func> + <name>get_plain_arguments() -> [Arg]</name> + <fsummary>Get all non-flag command line arguments</fsummary> + <type> + <v>Arg = string()</v> + </type> + <desc> + <p>Returns any plain command line arguments as a list of strings + (possibly empty).</p> + </desc> + </func> + <func> + <name>get_status() -> {InternalStatus, ProvidedStatus}</name> + <fsummary>Get system status information</fsummary> + <type> + <v>InternalStatus = starting | started | stopping</v> + <v>ProvidedStatus = term()</v> + </type> + <desc> + <p>The current status of the <c>init</c> process can be + inspected. During system startup (initialization), + <c>InternalStatus</c> is <c>starting</c>, and + <c>ProvidedStatus</c> indicates how far the boot script has + been interpreted. Each <c>{progress, Info}</c> term + interpreted in the boot script affects <c>ProvidedStatus</c>, + that is, <c>ProvidedStatus</c> gets the value of <c>Info</c>.</p> + </desc> + </func> + <func> + <name>reboot() -> void()</name> + <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> + <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> + </desc> + </func> + <func> + <name>restart() -> void()</name> + <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 + applications are taken down smoothly, all code is unloaded, + and all ports are closed before the system is booted again in + 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> + </desc> + </func> + <func> + <name>script_id() -> Id</name> + <fsummary>Get the identity of the used boot script</fsummary> + <type> + <v>Id = term()</v> + </type> + <desc> + <p>Get the identity of the boot script used to boot the system. + <c>Id</c> can be any Erlang term. In the delivered boot + scripts, <c>Id</c> is <c>{Name, Vsn}</c>. <c>Name</c> and + <c>Vsn</c> are strings.</p> + </desc> + </func> + <func> + <name>stop() -> void()</name> + <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> + </desc> + </func> + <func> + <name>stop(Status) -> void()</name> + <fsummary>Take down an Erlang node smoothly</fsummary> + <type> + <v>Status = int()>=0 | string()</v> + </type> + <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(Status)</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> + <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> + </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> + + <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> + </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> + + </item> + <tag><c>-eval Expr</c></tag> + <item> + <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> + <pre> +% <input>erl -noshell -eval 'R = 16#1F+16#A0, io:format("~.16B~n", [R])' \\</input> +<input>-s erlang halt</input> +BF</pre> + <p>If multiple <c>-eval</c> expressions are specified, they + are evaluated sequentially in the order specified. + <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 + 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> + </item> + <tag><c>-run Mod [Func [Arg1, Arg2, ...]]</c></tag> + <item> + <p>Evaluates the specified function call during system + initialization. <c>Func</c> defaults to <c>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>[Arg1,Arg2,...]</c> as argument. All arguments are passed + as strings. If an exception is raised, Erlang stops with an + error message.</p> + <p>Example:</p> + <pre> +% <input>erl -run foo -run foo bar -run foo bar baz 1 2</input></pre> + <p>This starts the Erlang runtime system and evaluates + the following functions:</p> + <code type="none"> +foo:start() +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 + some variant of <c>spawn</c> in such cases.</p> + </item> + <tag><c>-s Mod [Func [Arg1, Arg2, ...]]</c></tag> + <item> + <p>Evaluates the specified function call during system + initialization. <c>Func</c> defaults to <c>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>[Arg1,Arg2,...]</c> as argument. All arguments are passed + as atoms. If an exception is raised, Erlang stops with an + error message.</p> + <p>Example:</p> + <pre> +% <input>erl -s foo -s foo bar -s foo bar baz 1 2</input></pre> + <p>This starts the Erlang runtime system and evaluates + the following functions:</p> + <code type="none"> +foo:start() +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 + 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> + </item> + </taglist> + </section> + + <section> + <title>Example</title> + <pre> +% <input>erl -- a b -children thomas claire -ages 7 3 -- x y</input> +... + +1> <input>init:get_plain_arguments().</input> +["a","b","x","y"] +2> <input>init:get_argument(children).</input> +{ok,[["thomas","claire"]]} +3> <input>init:get_argument(ages).</input> +{ok, [["7","3"]]} +4> <input>init:get_argument(silly).</input> +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> + </section> +</erlref> + diff --git a/erts/doc/src/make.dep b/erts/doc/src/make.dep new file mode 100644 index 0000000000..98bac78235 --- /dev/null +++ b/erts/doc/src/make.dep @@ -0,0 +1,32 @@ +# ---------------------------------------------------- +# >>>> Do not edit this file <<<< +# This file was automaticly generated by +# /home/gandalf/otp/bin/docdepend +# ---------------------------------------------------- + + +# ---------------------------------------------------- +# TeX files that the DVI file depend on +# ---------------------------------------------------- + +book.dvi: absform.tex alt_dist.tex book.tex crash_dump.tex \ + driver.tex driver_entry.tex epmd.tex erl.tex \ + erl_dist_protocol.tex erl_driver.tex erl_ext_dist.tex \ + erl_prim_loader.tex erl_set_memory_block.tex \ + erlang.tex erlc.tex erlsrv.tex erts_alloc.tex \ + escript.tex inet_cfg.tex init.tex match_spec.tex \ + part.tex ref_man.tex run_erl.tex start.tex \ + start_erl.tex tty.tex werl.tex zlib.tex + +# ---------------------------------------------------- +# Source inlined when transforming from source to LaTeX +# ---------------------------------------------------- + +book.tex: ref_man.xml + +# ---------------------------------------------------- +# Pictures that the DVI file depend on +# ---------------------------------------------------- + +book.dvi: erl_ext_fig.ps + diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml new file mode 100644 index 0000000000..26480473d2 --- /dev/null +++ b/erts/doc/src/match_spec.xml @@ -0,0 +1,564 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>1999</year><year>2009</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>Match specifications in Erlang</title> + <prepared>Patrik Nyblom</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>1999-06-01</date> + <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 + 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> + + <section> + <title>Grammar</title> + <p>A match_spec can be described in this <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> + <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> + <item>BoolFunction ::= <c><![CDATA[is_atom]]></c> | <c><![CDATA[is_constant]]></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> + <item>ConditionExpression ::= ExprMatchVariable | { GuardFunction } | + { GuardFunction, ConditionExpression, ... } | TermConstruct + </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> + <item>NonCompositeTerm ::= term() (not list or tuple) + </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 ::= [ ActionTerm ] + </item> + <item>ActionTerm ::= ConditionExpression | ActionCall + </item> + <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> + </list> + </section> + + <section> + <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_constant, 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> + </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> + </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> + </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 + 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> + <table> + <row> + <cell align="left" valign="middle">Expression\011\011</cell> + <cell align="left" valign="middle">Variable bindings\011\011</cell> + <cell align="left" valign="middle">Result\011</cell> + </row> + <row> + <cell align="left" valign="middle">{{'$1','$2'}}\011\011</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'}}\011</cell> + <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">{'$1', '$2'}</cell> + </row> + <row> + <cell align="left" valign="middle">a\011\011\011</cell> + <cell align="left" valign="middle">doesn't matter\011\011\011</cell> + <cell align="left" valign="middle">a</cell> + </row> + <row> + <cell align="left" valign="middle">'$1'\011\011\011</cell> + <cell align="left" valign="middle">'$1' = []\011\011\011</cell> + <cell align="left" valign="middle">[]</cell> + </row> + <row> + <cell align="left" valign="middle">['$1']\011\011\011</cell> + <cell align="left" valign="middle">'$1' = []\011\011\011</cell> + <cell align="left" valign="middle">[[]]</cell> + </row> + <row> + <cell align="left" valign="middle">[{{a}}]\011\011\011</cell> + <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">[{a}]</cell> + </row> + <row> + <cell align="left" valign="middle">42\011\011\011</cell> + <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">42</cell> + </row> + <row> + <cell align="left" valign="middle">"hello"\011\011\011</cell> + <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">"hello"</cell> + </row> + <row> + <cell align="left" valign="middle">$1\011\011\011</cell> + <cell align="left" valign="middle">doesn't matter</cell> + <cell align="left" valign="middle">49 (the ASCII value for the character '1')</cell> + </row> + <tcaption>Literals in the MatchCondition/MatchBody parts of a match_spec</tcaption> + </table> + </section> + + <section> + <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. + </item> + <item> + <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> + </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 expression contains one single + <c><![CDATA[ActionTerm]]></c> which defines the return value without having + 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 + 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 + 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> + <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> + <code type="none"><![CDATA[ +[{['$1', '$2', '$3'], + [{orelse, + {'=:=', '$3', {{'$1','$2'}}}, + {'and', + {'=:=', '$1', {hd, '$3'}}, + {'=:=', '$2', {hd, {tl, '$3'}}}}}], + []}] + ]]></code> + <p>The above problem may also be solved like this:</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> + <code type="none"><![CDATA[ +[{['$1', '$2'],\011[{'=:=', {'*', 2, '$2'}, {hd, {element, 1, '$1'}}}], + []}]\011 + ]]></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> + <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> + <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> + <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> + <code type="none"><![CDATA[ +[{{'_',merry,'_'}, + [], + ['$_']}, + {{'_',pippin,'_'}, + [], + ['$_']}] + ]]></code> + <p>The function <c><![CDATA[ets:test_ms/2]]></c> 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 new file mode 100644 index 0000000000..2252358e0d --- /dev/null +++ b/erts/doc/src/notes.xml @@ -0,0 +1,5439 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2004</year><year>2009</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>otp_appnotes</prepared> + <docno>nil</docno> + <date>nil</date> + <rev>nil</rev> + <file>notes.xml</file> + </header> + <p>This document describes the changes made to the ERTS application.</p> + +<section><title>Erts 5.7.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + An insufficient stack allocation was made when reading + CPU information on BSD operating systems. (Thanks Michael + Turner and Akira Kitada)</p> + <p> + Own Id: OTP-8207</p> + </item> + <item> + <p> + A bug when supplying an argument without a dash directly + after the program name when starting erlang could prevent + distribution to start. This is now corrected.</p> + <p> + Own Id: OTP-8209</p> + </item> + <item> + <p> + A ticker process could potentially be blocked + indefinitely trying to send a tick to a node not + responding. If this happened, the connection would not be + brought down as it should.</p> + <p> + Own Id: OTP-8218</p> + </item> + <item> + <p> + Using certain firewalls (i.e. MS IAS Client and certain + versions of COMODO) could expose an undocumented + behaviour in the Win32 socket interface causing the name + resolution calls to hang infinitely. This is now worked + around by adding possibilities for port programs under + Windows to use overlapped I/O on their standard + input/output file handles.</p> + <p> + Own Id: OTP-8230</p> + </item> + <item> + <p> + Fixed bug on ETS tables with <c>write_concurrency</c>. + The emulator could crash when doing a <c>select</c> or + <c>match</c> with a bound key without finding any object.</p> + <p> + Own Id: OTP-8242</p> + </item> + <item> + <p>The <c>information-request</c> / + <c>information-response</c>, and + <c>group-leader-change-request</c> / + <c>group-leader-changed-response</c> signal pairs + described below did not always adhere to the signal order + guarantees of Erlang's signal model in the runtime system + with SMP support. These signals could for example + sometimes pass exit signals.</p> + <p>The following BIFs behaviors can be modeled as if an + asynchronous <c>information-request</c> signal is sent to + <c>Pid</c>. If <c>Pid</c> is alive, it responds with an + asynchronous <c>information-response</c> signal; + otherwise, the runtime system responds with a + <c>no-such-process</c> signal. When the response is + received, the caller transforms it into the result of the + BIF.</p> <list> <item><c>is_process_alive(Pid)</c></item> + <item><c>erlang:process_display(Pid, Type)</c></item> + <item><c>process_info(Pid)</c></item> + <item><c>process_info(Pid, ItemSpec)</c></item> </list> + <p>When <c>Pid</c> resides on the same node as the caller + of <c>group_leader(GroupLeader, Pid)</c>, the + <c>group_leader/2</c> BIFs behavior can be modeled as if + an asynchronous <c>group-leader-change-request</c> signal + is sent to <c>Pid</c>. If <c>Pid</c> is alive, it + responds with an asynchronous + <c>group-leader-changed-response</c> signal; otherwise, + the runtime system responds with a <c>no-such-process</c> + signal. When the response is received, the caller + transforms it into the result of the BIF. The distributed + case which only consists of an asynchronous + <c>group-leader-change-request</c> signal and no response + is not effected.</p> + <p> + Own Id: OTP-8245</p> + </item> + <item> + <p> + Errors in the <c>system_profile</c> documentation has + been corrected.</p> + <p> + Own Id: OTP-8257</p> + </item> + <item> + <p> + Low watermark socket option modified high watermark + instead of low watermark in the inet_driver. (Thanks to + Feng Yu and Tuncer Ayaz)</p> + <p> + Own Id: OTP-8279</p> + </item> + <item> + <p> + A race condition could cause the runtime system with SMP + support to end up in a completely unresponsive state.</p> + <p> + Own Id: OTP-8297</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The use of <c>pthread_cond_timedwait()</c> have been + completely removed from the runtime system. This since + its behavior is unpredictable when the system clock is + suddenly changed. The previous use of it was harmless.</p> + <p> + Own Id: OTP-8193</p> + </item> + <item> + <p> + The documentation is now built with open source tools + (xsltproc and fop) that exists on most platforms. One + visible change is that the frames are removed.</p> + <p> + Own Id: OTP-8201</p> + </item> + <item> + <p> + A new garbage collecting strategy for binaries which is + more aggressive than the previous implementation. + Binaries now has a virtual binary heap tied to each + process. When binaries are created or received to a + process it will check if the heap limit has been reached + and if a reclaim should be done. This imitates the + behavior of ordinary Erlang terms. The virtual heaps are + grown and shrunk like ordinary heaps. This will lessen + the memory footprint of binaries in a system.</p> + <p> + Own Id: OTP-8202</p> + </item> + <item> + <p> + The <c>ErlDrvTermData</c> term types used by + <c>driver_output_term()</c> and <c>driver_send_term()</c> + have been extended with the term types + <c>ERL_DRV_INT64</c>, and <c>ERL_DRV_UINT64</c> for + passing 64-bit integers. Also the 64-bit integer data + types <c>ErlDrvSInt64</c> and <c>ErlDrvUInt64</c> have + been introduced.</p> + <p> + For more information see the <seealso + marker="erl_driver">erl_driver(3)</seealso> + documentation.</p> + <p> + Own Id: OTP-8205</p> + </item> + <item> + <p> + [escript] The restriction that the first line in escripts + must begin with <c>#!</c> has been removed.</p> + <p> + [escript] Some command line options to the escript + executable has now been documented. For example you can + run an escript in the debugger by just adding a command + line option.</p> + <p> + [escript] The documentation of the escript header syntax + has been clarified. For example the header is optional. + This means that it is possible to directly "execute" + <c>.erl</c>, <c>.beam</c> and<c>.zip</c> files.</p> + <p> + Own Id: OTP-8215</p> + </item> + <item> + <p> + The instruction for building OTP on Windows was outdated + and incomplete, the document is updated.</p> + <p> + Also the otp_build script required windows drives to show + up in Cygwin using the /cygdrive prefix. That requirement + is now removed.</p> + <p> + Own Id: OTP-8219</p> + </item> + <item> + <p> + A module can have native implemented functions (NIFs) + that are dynamically loaded by calling + <c>erlang:load_nif/2</c>. This is an experimental feature + that is not yet intended for production systems. It is + released with intention to get some early feedback on the + interfaces before they are carved in stone.</p> + <p> + Own Id: OTP-8220</p> + </item> + <item> + <p> + The <c>float/1</c> BIF would always force a garbage + collection. The BIFs <c>size/1</c>, <c>byte_size/1</c>, + <c>bit_size/1</c>, <c>abs/1</c>, and <c>round/1</c> would + force a garbage-collection if the result was not a + sufficiently small integer.</p> + <p> + Own Id: OTP-8221</p> + </item> + <item> + <p> + The <seealso + marker="erlang#erlang:port_command/3">erlang:port_command/3</seealso> + BIF has been added. <c>erlang:port_command/3</c> is + currently not auto imported, but it is planned to be auto + imported in OTP R14. For more information see the + <seealso marker="erlang">erlang(3)</seealso> + documentation.</p> + <p> + Own Id: OTP-8225</p> + </item> + <item> + <p> + '<c>configure --enable-darwin-64bit</c>' would fail if + Snow Leopard had been booted with the 64-bit kernel. + (Thanks to Ryan M. Graham.)</p> + <p> + Own Id: OTP-8236</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.7.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + On Windows, open_port({spawn,Command},Opts) could not run + executables with spaces in the path or filename, + regardless of quoting efforts. While + open_port({spawn_executable,Exec},Opts) can run any + executable, it was still impossible to use 'spawn' to do + the same thing. This is now corrected.</p> + <p> + Own Id: OTP-8055</p> + </item> + <item> + <p> + The scheduler bind type <c>processor_spread</c> spread + schedulers too much on large NUMA systems.</p> + <p> + The new scheduler bind type <c>spread</c> spreads + schedulers as much as possible, and behaves as + <c>processor_spread</c> previously did. For more + information see the documentation of the <c>+sbt</c> + command line argument in the <c>erl(1)</c> documentation, + and the documentation of + <c>erlang:system_flag(scheduler_bind_type, + SchedulerBindType)</c>.</p> + <p> + Own Id: OTP-8063</p> + </item> + <item> + <p> + Automatically detected CPU topology on Linux system could + erroneously contain logical processors with <c>-1</c> as + identifiers. This happened when + <c>sysconf(_SC_NPROCESSORS_CONF)</c> returned a value + larger than the amount of logical processors found.</p> + <p> + Own Id: OTP-8064</p> + </item> + <item> + <p> + When the minimal term [] (end of list) was sent as the + complete message to a process on another node, and + received there, it could not be decoded. This bug is now + corrected. Fortunately [] is uncommon as the complete + message in real applications but it is a serious bug + anyway.</p> + <p> + Own Id: OTP-8092</p> + </item> + <item> + <p>A bug when the floating point exception pointer was + not initialized has been corrected. It manifested itself + on CentOS 5.1 sometimes when a floating point value was + sent to a remote node. Bug reported and patch suggested + by David Reiss, confirmed by Mikael Pettersson.</p> + <p>Some build problems on IRIX was also corrected. + Problem reported by Patrick Baggett, patch by Mikael + Pettersson.</p> + <p> + Own Id: OTP-8095</p> + </item> + <item> + <p> + A terminating process could erroneously unregister a name + for another process. This could occur under the following + conditions: The name of the terminating process was + unregistered and then registered for another process + simultaneously as the process that first had the name was + terminating.</p> + <p> + Own Id: OTP-8099 Aux Id: seq11344 </p> + </item> + <item> + <p> + Running erlc in a very deep directory (with a path length + of more 256 or more characters) would cause the emulator + to crash in a call to <c>list_to_atom/1</c>. (Thanks to + Chris Newcombe.)</p> + <p> + Own Id: OTP-8124</p> + </item> + <item> + <p> + A deadlock of the runtime system could occur when + unregistering the name of a port.</p> + <p> + Own Id: OTP-8145</p> + </item> + <item> + <p> + <c>Makefile.in</c> has been updated to use the LDFLAGS + environment variable (if set). (Thanks to Davide + Pesavento.)</p> + <p> + Own Id: OTP-8157</p> + </item> + <item> + <p> + The pthread rwlock implemention on Linux could cause + starvation of writers. We, therefore, now use our own + rwlock implementation on Linux.</p> + <p> + Own Id: OTP-8158</p> + </item> + <item> + <p> + Open source Erlang builds are updated to work well on + Snow Leopard (MacOS X 10.6)</p> + <p> + Own Id: OTP-8168</p> + </item> + <item> + <p> + A call to <c>erlang:system_info(schedulers_online)</c> + could end up in an infinite loop. This happened if the + amount of schedulers was larger than one, the amount of + schedulers online was one, and someone was blocking + multi-scheduling.</p> + <p> + Own Id: OTP-8169</p> + </item> + <item> + <p> + An error in erlang:system_profile/2 could cause + timestamped messages to arrive out of order in the SMP + case. This has now been fixed.</p> + <p> + Own Id: OTP-8171</p> + </item> + <item> + <p> + <c>binary_to_atom/2</c> and + <c>binary_to_existing_atom/2</c> would leak memory if the + binary contained unaligned data.</p> + <p> + Own Id: OTP-8192</p> + </item> + <item> + <p> + The async thread pool in the runtime system without SMP + support used a memory allocator that was not thread safe + for async jobs.</p> + <p> + Own Id: OTP-8194</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Processor internal NUMA nodes are now supported in the + ERTS internal CPU topology representation. For more + information see the documentation of the <c>+sct</c> + command line argument in the <c>erl(1)</c> documentation, + and the documentation of + <c>erlang:system_info(cpu_topology)</c>.</p> + <p> + Own Id: OTP-8041</p> + </item> + <item> + <p> + Documentation for ets improved about concurrency.</p> + <p> + Own Id: OTP-8050</p> + </item> + <item> + <p> + Emulator flags in an escript were earlier inherited to + emulators started from from the emulator running the + escript. For example when an escript invoked + <c>os:cmd("erl")</c>, the new emulator were given + erroneous emulator flags. This bug has now been fixed</p> + <p> + Escript filenames may now contain dots.</p> + <p> + Own Id: OTP-8060</p> + </item> + <item> + <p> + Made some BIFs non-recursive (relational operators,hash + and phash) to limit internal stack usage.</p> + <p> + Own Id: OTP-8065</p> + </item> + <item> + <p> + Fixed Windows specific bug in erl_prim_loader. Now it + handles the root directory (e.g. c:/) better. This bug + affected the directory listing in the debugger.</p> + <p> + Own Id: OTP-8080</p> + </item> + <item> + <p> + A TCP socket with option <c>{packet,4}</c> could crash + the emulator if it received a packet header with a very + large size value (>2Gb). The same bug caused + <c>erlang:decode_packet/3</c> to return faulty values. + (Thanks to Georgos Seganos.)</p> + <p> + Own Id: OTP-8102</p> + </item> + <item> + <p> + The maximum size of the export table has been raised from + 65536 to 524288 entries.</p> + <p> + Own Id: OTP-8104 Aux Id: seq11345 </p> + </item> + <item> + <p> + The file module has now a read_line/1 function similar to + the io:get_line/2, but with byte oriented semantics. The + function file:read_line/1 works for raw files as well, + but for good performance it is recommended to use it + together with the 'read_ahead' option for raw file + access.</p> + <p> + Own Id: OTP-8108</p> + </item> + <item> + <p> + Fixed bug causing emulator crash when reading a term in + external format containing a corrupt list with a negative + length.</p> + <p> + Own Id: OTP-8117</p> + </item> + <item> + <p> + New emulator flag <c>+sss</c>, to set stack size of + scheduler threads.</p> + <p> + Own Id: OTP-8119</p> + </item> + <item> + <p> + The Windows utility Erlsrv, run in interactive mode now + accepts options for registering internal service name and + description field of Windows registry database.</p> + <p> + Own Id: OTP-8132</p> + </item> + <item> + <p> + <c>erlang:demonitor(Mon, [flush])</c> has been optimized. + Previously it always searched the message queue of the + caller for a <c>'DOWN'</c> message. Current + implementation only search the message queue when + necessary. It is quite common that the search is not + necessary.</p> + <p> + A new option <c>info</c> has been added to + <c>erlang:demonitor/2</c>. For more information see the + <c>erlang(3)</c> documentation.</p> + <p> + Own Id: OTP-8143</p> + </item> + <item> + <p> + I/O tasks could unnecessarily be rescheduled. This was + harmless, but not useful work.</p> + <p> + Own Id: OTP-8148</p> + </item> + <item> + <p> + Minor improvements of <c>erlang:memory/[1,2]</c>.</p> + <p> + Own Id: OTP-8152</p> + </item> + <item> + <p> + New configuration option to enable use of shared zlib.</p> + <p> + Own Id: OTP-8155</p> + </item> + <item> + <p> + Fixed smp bug in ETS that could cause emulator crash when + table with more than 1000 objects accessed by several + processes, including calls to variants of <c>select</c> + or <c>match</c> combined with concurrent object deletion.</p> + <p> + Own Id: OTP-8166 Aux Id: seq11392 </p> + </item> + <item> + <p> + The code path interpretation is now more relaxed. The + flag -code_path_choice now defaults to relaxed instead of + strict. See the documentation of code and init for more + info.</p> + <p> + Own Id: OTP-8170</p> + </item> + <item> + <p> + Load balancing of run queues and check for I/O are + triggered more often than before in situations where + processes are scheduled often but are doing very little + work each time they execute.</p> + <p> + Own Id: OTP-8172</p> + </item> + <item> + <p> + Call tracing binary comprehensions would cause an + emulator crash. (Thanks to Paul Mineiro.)</p> + <p> + Own Id: OTP-8179</p> + </item> + <item> + <p> + <c>binary_to_term/1</c> would crash the emulator instead + of generating a <c>badarg</c> exception when given + certain invalid terms. (Thanks to Scott Lystig Fritchie.)</p> + <p> + Own Id: OTP-8180</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.7.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Crash dumps should now cause less problems for the + crashdump_viewer application. (For processes where arity + was non-zero, the arguments are now longer printed - they + used to be printed in a format that was not parseable.)</p> + <p> + Own Id: OTP-7472 Aux Id: seq11019, 11292 </p> + </item> + <item> + <p> + Processes could potentially get stuck on an offline + scheduler.</p> + <p> + Own Id: OTP-7990</p> + </item> + <item> + <p> + <c>binary_to_atom/2</c> and + <c>binary_to_existing_atom/2</c> could leak memory if + they caused a <c>badarg</c> exception.</p> + <p> + Own Id: OTP-7997</p> + </item> + <item> + <p> + A process could under very rare circumstances erroneously + be resumed.</p> + <p> + Own Id: OTP-8000</p> + </item> + <item> + <p> + Load balancing between schedulers could under rare + circumstances cause an emulator crash.</p> + <p> + Own Id: OTP-8008</p> + </item> + <item> + <p> + <c>erlang:memory(processes_used)</c> always returned + <c>0</c> instead of the correct value. (Thanks to Geoff + Cant)</p> + <p> + Own Id: OTP-8022</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Major improvements of the Erlang distribution for Erlang + runtime systems with SMP support. Previously distribution + port locks were heavily contended, and all encoding and + decoding for a specific distribution channel had to be + done in sequence. Lock contention due to the distribution + is now negligible and both encoding and decoding of + Erlang messages can be done in parallel.</p> + <p> + The old atom cache protocol used by the Erlang + distribution has been dropped since it effectively + prevented all parallel encoding and decoding of messages + passed over the same distribution channel.</p> + <p> + A new atom cache protocol has been introduced which + isolates atom cache accesses and makes parallel encoding + and decoding of messages passed over the same + distribution channel possible. The new atom cache + protocol also use an atom cache size 8 times larger than + before. The new atom cache protocol is documented in the + ERTS users guide.</p> + <p> + Erlang messages received via the distribution are now + decoded by the receiving Erlang processes without holding + any distribution channel specific locks. Erlang messages + and signals sent over the distribution are as before + encoded by the sending Erlang process, but now without + holding any distribution channel specific locks during + the encoding. That is, both encoding and decoding can be + and are done in parallel regardless of distribution + channel used.</p> + <p> + The part that cannot be parallelized is the atom cache + updates. Atom cache updates are therefore now scheduled + on the distribution port. Since it is only one entity per + distribution channel doing this work there is no lock + contention due to the atom cache updates.</p> + <p> + The new runtime system does not understand the old atom + cache protocol. New and old runtime systems can however + still communicate, but no atom cache will be used.</p> + <p> + Own Id: OTP-7774</p> + </item> + <item> + <p> + Fixed a bug that caused error logging from + <c>driver_select</c> sometimes with additional symptoms + such as failing IP communications or even an emulator + crash.</p> + <p> + Own Id: OTP-7898 Aux Id: seq11304 </p> + </item> + <item> + <p> + Improved SMP concurrency for ETS tables. Several mutating + operations can now be performed truly concurrent on + different records of the same table. To support this, the + table has to be created with option + <c>write_concurrency</c>, as it is achieved at the + expense of some execution and memory overhead. + <c>ets:select</c> and <c>select_count</c> has also been + improved for all tables to not acquire exclusive table + lock during the iteration.</p> + <p> + Own Id: OTP-7922</p> + </item> + <item> + <p> + erl (that is erl.exe and dyn_erl) and erlexec has been + made more dynamic so no hard coded paths needs to added + at installation time to erl (that is erl.ini and erl). + Reltool will make use of this in a future release.</p> + <p> + Own Id: OTP-7952</p> + </item> + <item> + <p> + Added functionality to get higher resolution timestamp + from system. The erlang:now function returns a timestamp + that's not always consistent with the actual operating + system time (due to resilience against large time changes + in the operating system). The function os:timestamp/0 is + added to get a similar timestamp as the one being + returned by erlang:now, but untouched by Erlangs time + correcting and smoothing algorithms. The timestamp + returned by os:timestamp is always consistent with the + operating systems view of time, like the calendar + functions for getting wall clock time, but with higher + resolution. Example of usage can be found in the os + manual page.</p> + <p> + Own Id: OTP-7971</p> + </item> + <item> + <p> + Two new options are added to open_port - spawn_executable + which runs external executables in a controlled way, and + spawn_driver which only opens port to loaded Erlang + drivers. See the erlang manual page for details.</p> + <p> + Own Id: OTP-7995</p> + </item> + <item> + <p> + New functionality in ETS to transfer the ownership of a + table. A table can either change owner be declaring an + "heir", another process that will inherit the table if + the owner terminates. A table can also change owner by + calling a new function <c>ets:give_away</c>.</p> + <p> + Own Id: OTP-8006</p> + </item> + <item> + <p> + Updates to Tilera build environment.</p> + <p> + Own Id: OTP-8009</p> + </item> + <item> + <p> + A stack trace was unnecessarily saved during process + termination.</p> + <p> + Own Id: OTP-8014</p> + </item> + <item> + <p> + User defined CPU topology and scheduler bind type can now + be set from the command line when starting an emulator. + For more information see the documentation of the + <c>+sct</c>, and the <c>+sbt</c> emulator flags in the + <c>erl(1)</c> documentation.</p> + <p> + The CPU topologies returned from + <c>erlang:system_info/1</c> and + <c>erlang:system_flag/2</c> now always contain the + <c>processor</c> level, also when not strictly necessary.</p> + <p> + Own Id: OTP-8030</p> + </item> + <item> + <p> + Various fixes in ETS: <c>ets:first</c> could return a + deleted key in a fixated table. <c>ets:lookup</c> could + return objects out of order if a deleted object was + re-inserted into a fixed bag. <c>ets:delete_object</c> + could fail to delete duplicate objects in a + duplicate_bag.</p> + <p> + Own Id: OTP-8040</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.7.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed a bug on Windows that could make + <c>gen_tcp:send</c> hang trying to send an iolist of more + than 16 binaries.</p> + <p> + Own Id: OTP-7816</p> + </item> + <item> + <p> + The runtime system could under rare circumstances crash + during load balancing.</p> + <p> + Own Id: OTP-7908 Aux Id: otp-7500 </p> + </item> + <item> + <p> + <c>run_erl</c> uses fallback if Unix98 pseudo-terminal is + not present on host.</p> + <p> + Own Id: OTP-7916 Aux Id: seq11249 </p> + </item> + <item> + <p> + A message buffer memory leak in the runtime system + without smp support has been fixed.</p> + <p> + Own Id: OTP-7941</p> + </item> + <item> + <p>Attempting to append a binary of 16Mb or greater to + another binary using the bit syntax would cause a + <c>system_limit</c> exception. There was also several + cases when constructing binaries when a <c>badarg</c> + exception was generated when it should have been + <c>system_limit</c>.</p> + <p> + Own Id: OTP-7942</p> + </item> + <item> + <p> + The runtime system with SMP support failed to terminate + the caller of <c>link(RemotePid)</c> properly, if + <c>RemotePid</c> was the pid of a process on an + unreachable node. The calling process was in this case + marked as exiting, but never terminated.</p> + <p> + Own Id: OTP-7946</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Rudimentary support for cross compiling is added to the + source release. The support is still in its infancy and + has only been used to cross compile on Linux for a + different cpu architecture and a different Linux version, + but should be extendible to support other platforms as + well. The cross configuration files with examples are + placed in $ERL_TOP/xcomp/. View README.xcomp and run + $ERL_TOP/otp_build -help for further information.</p> + <p> + Own Id: OTP-7854</p> + </item> + <item> + <p>The escape sequence <c>\{</c> which was given a new + interpretation in R13A has retained its old meaning (the + ASCII code for <c>{</c>), which means that codes greater + than 255 have to be stated using hexadecimal characters + (for example, <c>\x{AAA}</c>). The escape sequence + <c>\xH</c> where H is a hexadecimal character followed by + something else but a hexadecimal character is no longer + valid (incompatibility with R13A). Character codes less + than 256 can be stated using two hexadecimal characters + (for example, <c>\x0D</c>).</p> + <p> + Own Id: OTP-7891 Aux Id: OTP-7855 </p> + </item> + <item> + <p>The <c>term_to_binary/1</c> BIF used to be implemented + with recursive C code, which could cause the Erlang + emulator to terminate because of a stack overflow.</p> + <p>Also fixed some minor issues in + <c>term_to_binary/1</c> and <c>binary_to_term/1</c> + pointed out by Matthew Dempsky.</p> + <p> + Own Id: OTP-7894</p> + </item> + <item> + <p> + Several glitches and performance issues in the Unicode + and I/O-system implementation of R13A have been + corrected.</p> + <p> + Own Id: OTP-7896 Aux Id: OTP-7648 OTP-7887 </p> + </item> + <item> + <p> + Minor documentation improvements of the + <c>scheduler_bind_type</c> argument of + <c>erlang:system_flag/2</c>, and the + <c>scheduler_bind_type</c>, and the + <c>scheduler_bindings</c> arguments of + <c>erlang:system_info/1</c>.</p> + <p> + Own Id: OTP-7901 Aux Id: OTP-7777 </p> + </item> + <item> + <p> + There is a new BIF <c>erlang:make_tuple/3</c>.</p> + <p> + Own Id: OTP-7913</p> + </item> + </list> + </section> + +</section> + + +<section><title>Erts 5.7</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p><em>OpenSource:</em></p> + <p>FreeBSD leap-seconds are handled according to patch + submitted by OpenSource user Kenji Rikitake. No test case + covers this functionality (unsupported platform).</p> + <p> + Own Id: OTP-7609</p> + </item> + <item> + <p> + A corrected bug in <c>ets</c> 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 + already been deleted.</p> + <p> + Own Id: OTP-7665</p> + </item> + <item> + <p> + A new driver call-back <c>stop_select</c> is introduced + to allow drivers to de-select and then close a file + descriptor in a safe way in a SMP emulator. The old way + was not strictly according to posix standard and could in + some rare cases lead to unexpected behavior. A new flag + <c>ERL_DRV_USE</c> can be passed to + <c>driver_select()</c> to tell it that the descriptor + should be closed. <c>stop_select</c> is then called when + it is safe to do so. Old drivers will however still work + as before.</p> + <p> + Own Id: OTP-7670</p> + </item> + <item> + <p> + A bug fixed for TCP sockets with option + <c>{packet,http}</c>. An HTTP request with an absolute + URI was returned with a corrupt path string. This bug did + only exist in R12B-4 and R12B-5.</p> + <p> + Own Id: OTP-7682 Aux Id: OTP-7647 </p> + </item> + <item> + <p> + run_erl did in some cases fail to extract control + sequences from to_erl (like: winsize=X,Y) and did instead + send them to be interpreted by the erlang shell.</p> + <p> + Own Id: OTP-7688</p> + </item> + <item> + <p> + A bug in the installer on Windows not updating file + associations properly is now corrected.</p> + <p> + Own Id: OTP-7746</p> + </item> + <item> + <p>More space than necessary could be allocated in + binaries when appending to a binary (also in a binary + comprehension) and the data appended did not consist of + wholes bytes (e.g. 13 bits).</p> + <p> + Own Id: OTP-7747</p> + </item> + <item> + <p> + The gen_sctp option sctp_peer_addr_params, + #sctp_paddrparams{address={IP,Port} was erroneously + decoded in the inet driver. This bug has now been + corrected.</p> + <p> + Own Id: OTP-7755</p> + </item> + <item> + <p> + Outstanding async driver jobs leaked memory if the + issuing port died before the async jobs completed.</p> + <p> + Own Id: OTP-7784</p> + </item> + <item> + <p>A bug in the dynamic library loading affecting, among + others, OpenSolaris is now corrected. (Thanks to Paul + Fisher.)</p> + <p> + Own Id: OTP-7796</p> + </item> + <item> + <p> + run_erl compile errors fixed for FreeBSD</p> + <p> + Own Id: OTP-7817</p> + </item> + <item> + <p> + A bug in the inet driver for SCTP on Solaris showing for + e.g gen_sctp:abort/1 and gen_sctp:eof/1 has been + corrected. Patch suggestion by Simon Cornish.</p> + <p> + Own Id: OTP-7866</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The order of objects visited in select for ordered_set is + now documented.</p> + <p> + Own Id: OTP-7339</p> + </item> + <item> + <p> + The runtime system with SMP support now uses multiple, + scheduler specific run queues, instead of one globally + shared run queue.</p> + <p> + The lock protecting the shared run queue was heavily + contended, and the shared run queue also caused Erlang + processes to randomly migrate between schedulers with + negative cache effects as a result.</p> + <p> + With the current scheduler specific run queue solution, + lock contention due to run queue protection has been + reduced, and Erlang processes are only migrated when + needed to balance the load between the schedulers. The + reduced amount of migration also reduce lock contention + on locks protecting the scheduler specific instances of + the erts internal memory allocators.</p> + <p> + The scheduler specific run queues are also a necessity + for a lot of future planned NUMA (Non-Uniform Memory + Access) specific optimizations.</p> + <p> + Own Id: OTP-7500</p> + </item> + <item> + <p>Support for Unicode is implemented as described in + EEP10. Formatting and reading of unicode data both from + terminals and files is supported by the io and io_lib + modules. Files can be opened in modes with automatic + translation to and from different unicode formats. The + module 'unicode' contains functions for conversion + between external and internal unicode formats and the re + module has support for unicode data. There is also + language syntax for specifying string and character data + beyond the ISO-latin-1 range.</p> + <p>The interactive shell will support input and output of + unicode characters when the terminal and operating system + supports it.</p> + <p>Please see the EEP and the io/io_lib manual pages as + well as the stdlib users guide for details.</p> + <p><em>I/O-protocol incompatibilities:</em></p> + <p>The io_protocol between io_Server and client is + updated to handle protocol data in unicode formats. The + updated protocol is now documented. The specification + resides in the stdlib <em>users manual</em>, which is a + new part of the manual.</p> + <p><em>io module incompatibilities:</em></p> + <p>The io:put_chars, io:get_chars and io:get_line all + handle and return unicode data. In the case where + binaries can be provided (as to io:put_chars), they shall + be encoded in UTF-8. When binaries are returned (as by + io:get_line/get_chars when the io_server is set in + <em>binary mode</em>) the returned data is also + <em>always</em> encoded as UTF-8. The file module however + still returns byte-oriented data, why file:read can be + used instead of io:get_chars to read binary data in + ISO-latin-1.</p> + <p><em>io_lib module incompatibilities:</em></p> + <p>io_lib:format can, given new format directives (i.e + "~ts" and "~tc"), return lists containing integers larger + than 255. </p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-7648 Aux Id: OTP-7580 OTP-7514 OTP-7494 + OTP-7443 OTP-7181 EEP10 EEP11 </p> + </item> + <item> + <p> + The format of the string returned by + <c>erlang:system_info(system_version)</c> (as well as the + first message when Erlang is started) has changed. The + string now contains the both the OTP version number as + well as the erts version number.</p> + <p> + Own Id: OTP-7649</p> + </item> + <item> + <p> + Message passing has been further optimized for parallel + execution. Serial message passing is slightly more + expensive than before, but parallel send to a common + receiver is much cheaper.</p> + <p> + Own Id: OTP-7659</p> + </item> + <item> + <p> + Lock contention on the atom table lock when decoding + Erlang terms on the external format has been drastically + reduced.</p> + <p> + Own Id: OTP-7660</p> + </item> + <item> + <p> + The undocumented, unsupported, and deprecated guard BIF + <c>is_constant/1</c> has been removed.</p> + <p> + *** INCOMPATIBILITY with R12B ***</p> + <p> + Own Id: OTP-7673</p> + </item> + <item> + <p> + The Erlang process lock implementation has been improved + by Mat Hostetter at Tilera Corporation.</p> + <p> + Own Id: OTP-7692</p> + </item> + <item> + <p> + A <c>{nodedown, Node}</c> message passed by the + <c>net_kernel:monitor_nodes/X</c> functionality is now + guaranteed to be sent after <c>Node</c> has been removed + from the result returned by <c>erlang:nodes/Y</c>.</p> + <p> + Own Id: OTP-7725</p> + </item> + <item> + <p>The short-circuit operators <c>andalso</c> and + <c>orelse</c> no longer guarantees that their second + argument is either <c>true</c> or <c>false</c>. As a + consequence, <c>andalso</c>/<c>orelse</c> are now + tail-recursive.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-7748</p> + </item> + <item> + <p> + A new BIF, <c>lists:keyfind/3</c>, has been added. It + works like <c>lists:keysearch/3</c> except that it does + not wrap the returned tuple in a <c>value</c> tuple in + case of success. (Thanks to James Hague for suggesting + this function.)</p> + <p> + Own Id: OTP-7752</p> + </item> + <item> + <p> + Optimization for drivers by creating small binaries + direct on process heap.</p> + <p> + Own Id: OTP-7762</p> + </item> + <item> + <p><c>I bsl N</c> could cause the Erlang virtual machine + to run of memory instead generating a <c>system_limit</c> + if N was absurdly huge. (Thanks to Daniel Hedlund.)</p> + <p>There would always be a garbage collection when + evaluating <c>I bsl N</c> or <c>I bsr N</c> if <c>I</c> + was a bignum.</p> + <p>If <c>I</c> is an integer and <c>N</c> a bignum, <c>I + bsl N</c> will now cause the correct <c>system_limit</c> + exception instead of <c>bad_arith</c> as in earlier + releases.</p> + <p>If <c>I</c> is an integer and <c>N</c> a bignum, <c>I + bsr N</c> will return either 0 or -1 depending on the + sign of <c>I</c> instead of causing a <c>bad_arith</c> + exception as in earlier releases.</p> + <p> + Own Id: OTP-7764</p> + </item> + <item> + <p> + Scheduler threads can now be bound to logical processors + on newer Linux and Solaris systems. More systems will be + supported in the future.</p> + <p> + In some cases performance has increased drastically when + binding schedulers. Schedulers are not bound by default, + though. This since it might cause a performance + degradation if multiple programs have bound to + processors, e.g. multiple Erlang runtime systems. For + more information see the documentation of + <c>erlang:system_flag/2</c>.</p> + <p> + In order to bind scheduler threads the CPU topology need + to be known. On some newer Linux and Solaris systems the + runtime system automatically detects the CPU topology. If + the emulator isn't able to automatically detect the CPU + topology, the CPU topology can be defined. For more + information see the documentation of + <c>erlang:system_flag/2</c>.</p> + <p> + Own Id: OTP-7777</p> + </item> + <item> + <p>The compiler will refuse to a compile file where the + module name in the file differs from the output file + name.</p> + <p>When compiling using <c>erlc</c>, the current working + directory will no be included in the code path (unless + explicitly added using "-pa .").</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-7793</p> + </item> + <item> + <p> + The BIFs <c>atom_to_binary/2</c>, + <c>binary_to_atom/2</c>, and + <c>binary_to_existing_atom/2</c> have been added.</p> + <p> + Own Id: OTP-7804</p> + </item> + <item> + <p> + The amount of schedulers online can now be changed during + operation. The amount of schedulers online defaults to + the same amount as available logical processors. For more + information see the documentation of + <c>erlang:system_flag/2</c> and <c>erl</c>.</p> + <p> + Own Id: OTP-7811</p> + </item> + <item> + <p>The deprecated functions <c>erlang:fault/1</c>, + <c>erlang:fault/2</c>, and <c>file:rawopen/2</c> have + been removed.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-7812</p> + </item> + <item> + <p> + Erts internal dynamically allocated process and port + specific data for rarely used data. This is used to + reduce memory usage of processes and ports that do not + use specific functionality. More functionality will be + moved to process and port specific data in future + releases.</p> + <p> + Own Id: OTP-7818</p> + </item> + <item> + <p> + New packet type <c>http_bin</c> for gen_tcp sockets and + <c>erlang:decode_packet</c>. It works like <c>http</c> + except that strings are returned as binaries instead of + lists.</p> + <p> + Own Id: OTP-7821</p> + </item> + <item> + <p> + The obsolete wd_keeper program for embedded Solaris + systems has been removed.</p> + <p> + Own Id: OTP-7822</p> + </item> + <item> + <p> + Nodes belonging to different independent clusters can now + co-exist on the same host with the help of a new + environment variable setting ERL_EPMD_PORT.</p> + <p> + Own Id: OTP-7826</p> + </item> + <item> + <p>There are new functions <c>erlang:min/2</c> and + <c>erlang:max/2</c> to calculate the minimum and maximum + of two terms, respectively. Note that the functions are + not auto-imported, so they need to be imported explicitly + or the <c>erlang</c> prefix must be used when calling + them.</p> + <p> + Own Id: OTP-7841</p> + </item> + <item> + <p>The copyright notices have been updated.</p> + <p> + Own Id: OTP-7851</p> + </item> + <item> + <p>Enhanced build environment for cross compilation to + Tilera Tile architecture.</p> + <p>Support for native ethread atomics on Tilera + Tile64/TilePro (Thanks to Tilera Corporation).</p> + <p> + Own Id: OTP-7852</p> + </item> + <item> + <p>The escape sequences <c>\x</c> and <c>\{</c> have been + assigned new interpretations (they used to return the + ASCII code for <c>x</c> and <c>{</c> respectively). One + or more octal characters inside curly brackets after a + leading backslash is from now on an alternative to the + existing syntax <c>\NNN</c>, but can also be used for + codes greater than 255. In a similar fashion, one or more + hexadecimal characters can be put inside curly brackets + after a leading <c>\x</c>. Furthermore, the escape + sequences <c>\xH</c> and <c>\xHH</c>, where N is a + hexadecimal character, can be used for codes less than + 256.</p> + <p>NOTE: These new escape sequences are still considered + experimental and may be changed in the R13B release.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-7855</p> + </item> + <item> + <p> + The PCRE library's exported function names are now + prefixed with erts_ in the erlang emulator to avoid + clashes with dynamically loaded drivers.</p> + <p> + Own Id: OTP-7861</p> + </item> + <item> + <p> + A runtime system with SMP support will now be built by + default on most platforms if a usable posix thread + library or native windows threads are found.</p> + <p> + For more information see the top README file.</p> + <p> + Own Id: OTP-7872</p> + </item> + </list> + </section> + +</section> + + +<section><title>Erts 5.6.5.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A corrected bug in <c>ets</c> 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 + already been deleted.</p> + <p> + Own Id: OTP-7665</p> + </item> + <item> + <p> + A bug fixed for TCP sockets with option + <c>{packet,http}</c>. An HTTP request with an absolute + URI was returned with a corrupt path string. This bug did + only exist in R12B-4 and R12B-5.</p> + <p> + Own Id: OTP-7682 Aux Id: OTP-7647 </p> + </item> + <item> + <p> + Calling <c>gen_tcp:send()</c> from several processes on + socket with option <c>send_timeout</c> could lead to much + longer timeout than specified. The solution is a new + socket option <c>{send_timeout_close,true}</c> that will + do automatic close on timeout. Subsequent calls to send + will then immediately fail due to the closed connection.</p> + <p> + Own Id: OTP-7731 Aux Id: seq11161 </p> + </item> + <item> + <p> + A process being garbage collected via the + <c>garbage_collect/1</c> BIF or the + <c>check_process_code/2</c> BIF didn't handle message + receive and resume correctly during the garbage collect. + When this occurred, the process returned to the state it + had before the garbage collect instead of entering the + new state.</p> + <p> + Own Id: OTP-7738</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.6.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A bug in inet_drv concerning gen_tcp:connect has been + corrected. A connect towards a non-open port through open + firewalls could sometimes erroneously be successful. Any + subsequent operation would fail, though.</p> + <p> + Own Id: OTP-6542</p> + </item> + <item> + <p> + Floating point arithmetics in drivers could cause a + runtime system crash and/or unexpected results on runtime + systems with floating point exceptions enabled. Floating + point exceptions are disabled unless explicitly enabled + or if hipe is enabled.</p> + <p> + Own Id: OTP-7237</p> + </item> + <item> + <p> + A bug when many sockets got signalled simultaneously + causing the emulator to panic with the message + "Inconsistent, why isnt io reported?" is now corrected.</p> + <p> + Own Id: OTP-7420</p> + </item> + <item> + <p> + Starting erl with option "-detached" now disconnects + correctly from terminal session on Unix.</p> + <p> + Own Id: OTP-7461</p> + </item> + <item> + <p> + Mended gdb etp-commands for ETS access.</p> + <p> + Own Id: OTP-7538</p> + </item> + <item> + <p> + <c>erlang:decode_packet/3</c> allows white space between + HTTP header tag and colon according to RFC2616.</p> + <p> + Own Id: OTP-7543</p> + </item> + <item> + <p> + An emulator compiled for SCTP now starts even if the + dynamic libraries are not present. The SCTP driver is + then of course not loaded.</p> + <p> + Own Id: OTP-7551</p> + </item> + <item> + <p>To build on Mac OS X, 10.3.0 or later is now required + because of fixes for two problems:</p> + <p>There would be a resource leak when <c>erl_ddl</c> + attempted to unload a driver. This problem has been + corrected by using <c>dlopen()</c> (which works on all + modern Unix-like platforms) instead of the Mac OS X + specific API calls.</p> + <p>Signal handling in the run-time system for HiPE has + been updated to work on later versions of Mac OS X than + 10.2.x. Therefore, <c>--enable-hipe</c> now works on Mac + OS X with Intel CPUs.</p> + <p>Thanks to Geoff Cant for the patches.</p> + <p> + Own Id: OTP-7562</p> + </item> + <item> + <p>Corrected some information about the protocol between + EPMD and Erlang nodes. (Thanks to Michael Regen.)</p> + <p> + Own Id: OTP-7594</p> + </item> + <item> + <p> + When using + <c>erlang:system_monitor(Pid,{long_gc,Time})</c>, and the + GC time exceeded 1 second, it sometimes erroneously + showed up as about 4300 seconds. (This bug was corrected + in R9C, but re-introduced in R12B.) (Thanks to Chris + Newcombe.)</p> + <p> + Own Id: OTP-7622 Aux Id: OTP-4903, seq8379 </p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The driver entry of a dynamically loaded driver is now + copied when loaded which enables some internal + optimizations. Note that drivers that modify the driver + entry during execution will not work anymore. Such a + miss-use of the driver interface is however not + supported.</p> + <p> + Own Id: OTP-6900</p> + </item> + <item> + <p> + The split function is now added to the re library. + Exceptions and errors from both run, replace and split + are made more consistent.</p> + <p> + Own Id: OTP-7514 Aux Id: OTP-7494 </p> + </item> + <item> + <p> + Fixed harmless compiler warnings when building the + emulator and minor build changes in order to avoid + unnecessary rebuilds.</p> + <p> + Own Id: OTP-7530</p> + </item> + <item> + <p> + There is now experimental support for loading of code + from archive files. See the documentation of <c>code</c>, + <c>init</c>, <c>erl_prim_loader </c> and <c>escript</c> + for more info.</p> + <p> + The error handling of <c>escripts</c> has been improved.</p> + <p> + An <c>escript</c> may now set explicit arguments to the + emulator, such as <c>-smp enabled</c>.</p> + <p> + An <c>escript</c> may now contain a precompiled beam + file.</p> + <p> + An <c>escript</c> may now contain an archive file + containing one or more applications (experimental).</p> + <p> + The internal module <c>code_aux</c> has been removed.</p> + <p> + Own Id: OTP-7548 Aux Id: otp-6622 </p> + </item> + <item> + <p> + The reallocation functionality part of the ERTS internal + memory allocators, now consider current block in + combination with surrounding free blocks as an + alternative location for a reallocation.</p> + <p> + Own Id: OTP-7555</p> + </item> + <item> + <p>There could remain false references from a process to + a module that has been called earlier, so that the + process would be killed if the module was reloaded. + (Thanks to Richard Carlsson.)</p> + <p>Also, the fix for this bug also made it possible to + make stack backtraces (as returned from + <c>erlang:get_stacktrace/0</c> and other functions) more + correct in that the immediate caller is always included + in the stack backtrace (it could sometimes be + missing).</p> + <p> + Own Id: OTP-7559</p> + </item> + <item> + <p> + Improved locking in IO-handling for better smp + performance.</p> + <p> + Own Id: OTP-7560</p> + </item> + <item> + <p> + Improved BIF rescheduling functionality.</p> + <p> + Own Id: OTP-7587</p> + </item> + <item> + <p> + Loading a module compiled with Erlang/OTP R9C and calling + <c>module_info/0</c> in the module would crash the + emulator. The emulator now refuses to load any module + compiled with R9C or earlier. (Note: only trivial modules + compiled with R10B or earlier could be loaded anyway.) + (Thanks to Martin Kjellin.)</p> + <p> + Own Id: OTP-7590</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.6.4.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A process calling one of the following BIFs could under + very rare conditions deadlock in the runtime system with + SMP support: <c>check_process_code/2</c>, + <c>garbage_collect/1</c>, <c>process_info/[1,2]</c>, + <c>system_flag/2</c>, and + <c>erlang:suspend_process/[1,2]</c>.</p> + <p> + Own Id: OTP-7582</p> + </item> + <item> + <p> + A couple of statistics variables were not managed in a + thread safe manner in the runtime system with SMP + support.</p> + <p> + Own Id: OTP-7583</p> + </item> + <item> + <p> + An extremely rare race condition when terminating a + process could potentially cause a runtime system crash.</p> + <p> + Own Id: OTP-7584</p> + </item> + <item> + <p> + Under certain conditions and when using run_erl/to_erl, + the terminal Erlang driver (ttsl_drv) could crash the + emulator by doing a division by zero due to incorrect + handling of terminals reporting a zero width. For + terminals reporting zero width, the driver now fallbacks + to a default width of 80 and a default height of 24 + (vt100), as a fallback behaviour. This fixes the crashes + and also makes output on "dumb" terminals much more + readable.</p> + <p> + Own Id: OTP-7592 Aux Id: seq11073 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.6.4.1</title> + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + A new <c>erts_alloc</c> parameter + <c>+M<S>rmbcmt</c> (relative multiblock carrier + move threshold) has been added. It determines when to + force a moving realloc in a multiblock carrier when a + block is shrunk. For more information see the + <c>erts_alloc(3)</c> documentation.</p> + <p> + Own Id: OTP-7540</p> + </item> + <item> + <p>The new option <c>+d</c> can be given to <c>erl</c> to + suppress the crash dump generation if an internal error + is detected. As a result, a more useful core dump is + produced.</p> + <p> + Own Id: OTP-7578 Aux Id: seq11052 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.6.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Double backslashes in format string passed to the erts + internal printf implementation produced erroneous + results. No such format strings were passed to the erts + internal printf implementation, i.e., the bug was + therefore completely harmless. (Thanks to Perry Smith.)</p> + <p> + Own Id: OTP-7408</p> + </item> + <item> + <p> + Large files are now handled on Windows, where the + filesystem supports it.</p> + <p> + Own Id: OTP-7410</p> + </item> + <item> + <p> + Bug fixed for <c>{packet,http}</c> when space follows + http headers.</p> + <p> + Own Id: OTP-7458</p> + </item> + <item> + <p> + The trace option <c>running</c> could cause an emulator + crash if the current function couldn't be determined.</p> + <p> + Own Id: OTP-7484</p> + </item> + <item> + <p> + Using 16#ffffFFFF as a timeout value in receive...after + would often cause a timeout almost at once due to an + 32-bit integer overflow. (Thanks to Serge Aleynikov and + Matthias Lang.)</p> + <p> + Own Id: OTP-7493</p> + </item> + <item> + <p> + For the process that an escript runs in, the + <c>trap_exit</c> process flag is now <c>false</c> instead + of <c>true</c> (as in previous releases). Scripts that + depend on the previous (counter-intuitive) behaviour + might not work. (Thanks to Bengt Kleberg.)</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-7517</p> + </item> + <item> + <p> + A bug in the <c>string:to_integer/1</c> builtin made the + emulator unstable. This is now corrected. (Thanks to Lev + Walkin.)</p> + <p> + Own Id: OTP-7526</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>Performance for ETS intensive applications should now + be better in the SMP emulator. Also, ETS table + identifiers (as returned by <c>ets:new/2</c>) are now + spread out in wider range than before (using 28 bits in a + 32-bit emulator) to make sure that the table identifier + for a deleted table will not be quickly re-used.</p> + <p>NOTE: Table identifiers can now be negative integers. + Programs that (incorrectly) assume that table identifiers + can only be positive integers might stop to work. (The + type of a table identifier is intentionally not + documented, and may change in a future release.)</p> + <p> + Own Id: OTP-7348</p> + </item> + <item> + <p> + New BIF <c>erlang:decode_packet/3</c> that extracts a + protocol packet from a binary. Similar to the socket + option <c>{packet, Type}</c>. Also documented the socket + packet type <c>http</c> and made it official. + <em>NOTE</em>: The tuple format for <c>http</c> packets + sent from an active socket has been changed in an + incompatible way.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-7404</p> + </item> + <item> + <p> + The source code for the documentation for some + applications (erts, kernel, stdlib, and several others) + are now included in the source tar ball. There is + currently no Makefile support for building HTML files + from the source (such support will be included in a + future release).</p> + <p> + Own Id: OTP-7406</p> + </item> + <item> + <p> + A lot of frequently accessed memory counters (erts + internal) have been removed. This since they hurt + performance on the runtime system with SMP support. As a + result <c>erlang:memory/[0,1]</c> will only deliver a + result if all <c>erts_alloc(3)</c> allocators are enabled + (default). The result delivered when all + <c>erts_alloc(3)</c> allocators are enabled are both more + accurate and less accurate than before. More memory than + before are included in the result, but the different + parts that are summed are not gathered atomically. A call + to <c>erlang:memory/[0,1]</c> is much cheaper for the + system than before. This since the information isn't + gathered atomically anymore which was very expensive.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-7468</p> + </item> + <item> + <p> + Pre-allocators used for, for example, timers, and + messages have been rewritten to be scheduler specific. + That is, different schedulers will now allocate from + different pools which reduces lock contention.</p> + <p> + Own Id: OTP-7470</p> + </item> + <item> + <p> + On Mac OS X, file:sync/1 now guarantees that all + filesystem buffers are written to the disk by using the + fcntl() with F_FULLFSYNC option. Previously, file:sync/1 + called fsync(), which only guaranteed that the data had + been transferred to the disk drive. (Thanks to Jan + Lehnardt.)</p> + <p> + Own Id: OTP-7471</p> + </item> + <item> + <p> + Termination of a process that takes a long time can now + be preempted, i.e., the terminating process will be + rescheduled for later continuation of termination so that + other processes can execute. Termination of a process + that owns many and/or large ets tables typically takes a + long time.</p> + <p> + Own Id: OTP-7477</p> + </item> + <item> + <p> + A new trace option <c>exiting</c> has been added. The + <c>exiting</c> trace is similar to the <c>running</c> + trace, but for exiting processes. For more information + see the erlang(3) documentation.</p> + <p> + The <c>erlang:trace/3</c> bif now doesn't block other + scheduler threads if only one tracee is specified in the + call to <c>erlang:trace/3</c>.</p> + <p> + Own Id: OTP-7481</p> + </item> + <item> + <p> + The re module is extended with repetitive matches (global + option) and replacement function.</p> + <p> + Own Id: OTP-7494 Aux Id: OTP-7181 </p> + </item> + <item> + <p> + In the section about binary construction, the reference + manual now mentions what happens when an integer value + does not fit into an integer segment of size N (namely, + that the N least significant bits will be put into into + the binary and that the most significant bits will be + silently discarded). (Thanks to Edwin Fine.)</p> + <p> + Own Id: OTP-7506</p> + </item> + <item> + <p> + Setting the <c>{active,once}</c> for a socket (using + inets:setopts/2) is now specially optimized (because the + <c>{active,once}</c> option is typically used much more + frequently than other options).</p> + <p> + Own Id: OTP-7520</p> + </item> + </list> + </section> + + + <section><title>Known Bugs and Problems</title> + <list> + <item> + <p> + Floating point arithmetics in drivers can cause a runtime + system crash and/or unexpected results on runtime systems + with floating point exceptions enabled. Floating point + exceptions are disabled unless explicitly enabled or if + hipe is enabled.</p> + <p> + Own Id: OTP-7237</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.6.3.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Binary construction with an integer field of size 0 at + the end of the constructed binary (and the size given in + a variable), would cause a write of one byte outside the + memory reserved for the binary, which in turn could cause + an emulator crash.</p> + <p> + Own Id: OTP-7422</p> + </item> + <item> + <p> + A race condition in the dynamic driver implementation + could cause an emulator crash. (Thanks to Paul Fisher)</p> + <p> + Own Id: OTP-7464</p> + </item> + <item> + <p> + Calls to <c>erlang:system_info(allocated_areas)</c> could + cause the runtime system with SMP support to crash.</p> + <p> + Own Id: OTP-7474</p> + </item> + <item> + <p> + The <c>env</c> option to <c>open_port()</c> could cause + the runtime system with SMP support to crash.</p> + <p> + Own Id: OTP-7475</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Operations that needed to block other threads in the + runtime system with SMP support unnecessarily waited for + async threads to block. Most important the + <c>erlang:memory/[0,1]</c> bif, code loading, and the + <c>erlang:trace/3</c> bif.</p> + <p> + Own Id: OTP-7480</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.6.3.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Calls to <c>erlang:memory/[0,1]</c> could cause the + runtime system with SMP support to crash.</p> + <p> + Own Id: OTP-7415</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.6.3.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Doing local call trace on bit syntax matching code that + has been optimized with delayed sub-binary creation could + crash the emulator.</p> + <p> + Own Id: OTP-7399 Aux Id: seq10978 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.6.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Only one to_erl process at a time is allowed to connect + to the same run_erl pipe. Prevents buggy behaviour when + IO from several to_erl's get interleaved.</p> + <p> + Own Id: OTP-5107</p> + </item> + <item> + <p> + IPv6 name resolving has now been fixed to use + getaddrinfo() patch (thoroughly reworked) courtesy of Love + H�rnquist-�strand submitted by Fredrik Thulin. It also + can use gethostname2() patch (also reworked) courtesy of + Mikael Magnusson for debian submitted by Sergei Golovan.</p> + <p> + Own Id: OTP-5382</p> + </item> + <item> + <p> + Improved error handling in run_erl</p> + <p> + Own Id: OTP-7252</p> + </item> + <item> + <p>A permanent fix for the deadlock issue temporarily + fixed by OTP-7260.</p> <taglist><tag>OTP-7260</tag><item> + The runtime system with SMP support could under rare + circumstances deadlock when a distribution channel was + taken down while multiple simultaneous operations were + performed on it. </item></taglist> + <p> + Own Id: OTP-7267 Aux Id: OTP-7260 </p> + </item> + <item> + <p> + ./configure has been improved to find 64-bit OpenSSL + libraries.</p> + <p> + Own Id: OTP-7270</p> + </item> + <item> + <p> + A terminating process could under very rare circumstances + trigger a bug which could crash the runtime system with + SMP support.</p> + <p> + Own Id: OTP-7272</p> + </item> + <item> + <p> + SCTP_ADDR_CONFIRMED events are now handled by gen_sctp.</p> + <p> + Own Id: OTP-7276</p> + </item> + <item> + <p> + binary_to_term/1 would crash the emulator if the binary + data contained an external fun with non-atom module + and/or function. Corrected to generate a badarg + exception.</p> + <p> + Own Id: OTP-7281</p> + </item> + <item> + <p> + On Mac OS 10.5 (Leopard), sending to socket which the + other end closes could cause the emulator to consume 100% + CPU time. (Thanks to Matthias Radestock.)</p> + <p> + Own Id: OTP-7289</p> + </item> + <item> + <p> + The vanilla driver used on Windows could crash the + emulator and sometimes produced corrupt files. The + vanilla driver is the driver that is used when one only + pass a filename as first argument to <c>open_port/2</c>. + <em>NOTE</em>: This use of <c>open_port/2</c> is + <em>obsolete</em>, and the documentation of this use has + previously been removed. The functionality is only + present for backward compatibility reasons and + <em>will</em> eventually be removed.</p> + <p> + Own Id: OTP-7301</p> + </item> + <item> + <p> + Faulty matching in binaries larger than 512Mb on 64bit + machines fixed.(On 32bit, the size limit for binaries is + still 512Mb). Thanks to Edwin Fine and Per Gustafsson for + finding fault and fix.</p> + <p> + Own Id: OTP-7309</p> + </item> + <item> + <p> + crypto:start() on Windows caused emulator to hang on + error popup window if openssl DLL was not found. Windows + error popups now suppressed.</p> + <p> + Own Id: OTP-7325</p> + </item> + <item> + <p> + Configuration option <c>without-termcap</c> can be used to + disable the use of termcap libraries for terminal cursor + control in the shell.</p> + <p> + Own Id: OTP-7338</p> + </item> + <item> + <p> + to_erl reports its terminal window size to run_erl in + order to get output formatted accordingly</p> + <p> + Own Id: OTP-7342</p> + </item> + <item> + <p> + On Solaris, the <c>compressed</c> option for file + operations did not work if the file descriptor happened + to be greater than 255 (a problem with fopen() and + friends in Solaris itself).</p> + <p> + Own Id: OTP-7343 Aux Id: seq10949 </p> + </item> + <item> + <p> + A race condition in the runtime system with SMP support + causing an erroneous removal of a newly created ets table + has been fixed.</p> + <p> + The race occurred when a process removed a table during + termination simultaneously as another process removed the + same table via <c>ets:delete/1</c> and a third process + created a table that accidentaly got the same internal + table index as the table being removed.</p> + <p> + Own Id: OTP-7349</p> + </item> + <item> + <p> + <c>zlib:inflate</c> failed when the size of the inflated + data was an exact multiple of the internal buffer size + (4000 bytes by default).</p> + <p> + Own Id: OTP-7359</p> + </item> + <item> + <p> + If the total number of allowed atoms is exceeded, there + will now be a controlled termination of the emulator with + a crash dump file. The emulator used to simply crash. + (Thanks Howard Yeh and Thomas Lindgren.)</p> + <p> + Own Id: OTP-7372</p> + </item> + <item> + <p> + The break handler in werl on Windows could cause the + emulator to hang or crash, that is now corrected.</p> + <p> + Own Id: OTP-7394 Aux Id: seq10969 </p> + </item> + <item> + <p> + The configure script now tests for an serious + optimization bug in gcc-4.3.0. If the bug is present, the + configure script will abort (if this happens, the only + way to build Erlang/OTP is to change to another version + of gcc). (Thanks to Mikael Pettersson.)</p> + <p> + Own Id: OTP-7397</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + On Unix, the emulator now notices when the width of the + terminal has changed. (Thanks to Matthew Dempsky and + Patrick Mahoney.)</p> + <p> + Own Id: OTP-7290</p> + </item> + <item> + <p> + There is a new function <c>init:stop/1</c> which can be + used to shutdown the system cleanly AND generate a + non-zero exit status or crash dump. (Thanks to Magnus + Froberg.)</p> + <p> + Own Id: OTP-7308</p> + </item> + <item> + <p> + process_info(Pid, garbage_collection) now returns more + information</p> + <p> + Own Id: OTP-7311</p> + </item> + <item> + <p> + The <c>hide</c> option for <c>open_port/2</c> is now + documented. (Thanks to Richard Carlsson.)</p> + <p> + Own Id: OTP-7358</p> + </item> + </list> + </section> + + + <section><title>Known Bugs and Problems</title> + <list> + <item> + <p> + Floating point arithmetics in drivers can cause a runtime + system crash on runtime systems with floating point + exceptions enabled. Floating point exceptions are + disabled unless explicitly enabled or if hipe is enabled.</p> + <p> + Own Id: OTP-7237</p> + </item> + </list> + </section> + +</section> + + +<section><title>Erts 5.6.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The maximum length of an atom of 255 characters is now + strictly enforced. <c>binary_to_term/1</c> will now fail + with a badarg if an encoded term contains an atom longer + than 255 characters. Atoms created by drivers will now be + truncated to 255 characters if necessary. (Thanks to + Matthew Dempsky.)</p> + <p> + Own Id: OTP-7147</p> + </item> + <item> + <p> + A bug in "bignum handling" on some 64bit architectures + could cause rem and div operations on large numbers to + hang indefinitely. Rem operations involving the smallest + negative number representable in 28 bits or 60 bits could + also cause access violation and emulator crash. Both + errors are corrected.</p> + <p> + Own Id: OTP-7177</p> + </item> + <item> + <p> + When doing the initial garbage collection after waking a + hibernated process, a fullsweep garbage collection was + unnecessarily triggered.</p> + <p> + Own Id: OTP-7212</p> + </item> + <item> + <p>The beta testing module <c>gen_sctp</c> now supports + active mode as stated in the documentation. Active mode + is still rather untested, and there are some issues about + what should be the right semantics for + <c>gen_sctp:connect/5</c>. In particular: should it be + blocking or non-blocking or choosable. There is a high + probability it will change semantics in a (near) future + patch.</p> <p>Try it, give comments and send in bug + reports!</p> + <p> + Own Id: OTP-7225</p> + </item> + <item> + <p> + Invalid arguments to <c>ets:update_counter/3</c> were not + handled correctly. A tuple position (<c>Pos</c>) less + than 1 caused the element directly following the key to + be updated (as if no position at all had been specified). + All invalid values for <c>Pos</c> will now fail with + <c>badarg</c>.</p> + <p> + Own Id: OTP-7226</p> + </item> + <item> + <p> + The runtime system with SMP support could under rare + circumstances deadlock when a distribution channel was + taken down while multiple simultaneous operations were + performed on it.</p> + <p> + Own Id: OTP-7260</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + More checksum/hash algorithms from the zlib library are + now available as built in functions (like md5 hashes has + been for a long time).</p> + <p> + Own Id: OTP-7128</p> + </item> + <item> + <p> + Minor improvements in the garbage collector.</p> + <p> + Own Id: OTP-7139 Aux Id: OTP-7132 </p> + </item> + <item> + <p> + The switch "-detached" to the windows werl program now + can create an erlang virtual machine without any main + window and without a temporary console showing.</p> + <p> + Own Id: OTP-7142</p> + </item> + <item> + <p><c>erlang:system_info/1</c> now accepts the + <c>logical_processors</c>, and <c>debug_compiled</c> + arguments. For more info see the, <c>erlang(3)</c> + documentation.</p> <p>The scale factor returned by + <c>test_server:timetrap_scale_factor/0</c> is now also + effected if the emulator uses a larger amount of + scheduler threads than the amount of logical processors + on the system. </p> + <p> + Own Id: OTP-7175</p> + </item> + <item> + <p> + A new BIF ets:update_element/3. To update individual + elements within an ets-tuple, without having to read, + update and write back the entire tuple.</p> + <p> + Own Id: OTP-7200</p> + </item> + <item> + <p> + A process executing the <c>processes/0</c> BIF can now be + preempted by other processes during its execution. This + in order to disturb the rest of the system as little as + possible. The returned result is, of course, still a + consistent snapshot of existing processes at a time + during the call to <c>processes/0</c>.</p> + <p> + The documentation of the <c>processes/0</c> BIF and the + <c>is_process_alive/1</c> BIF have been updated in order + to clarify the difference between an existing process and + a process that is alive.</p> + <p> + Own Id: OTP-7213</p> + </item> + </list> + </section> + +</section> + + +<section><title>Erts 5.6.1.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Not enough parameters were passed when sending an error + report in erl_check_io.c (Thanks to Matthew Dempsky).</p> + <p> + Own Id: OTP-7176</p> + </item> + <item> + <p> + In rare circumstances, complex binary matching code could + cause the emulator to crash or not match when it should. + (Thanks to Rory Byrne.)</p> + <p> + Own Id: OTP-7198</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>The <c>{allocator_sizes, Alloc}</c> and + <c>alloc_util_allocators</c> arguments are now accepted + by <c>erlang:system_info/1</c>. For more information see + the <c>erlang(3)</c> documentation.</p> + <p> + Own Id: OTP-7167</p> + </item> + <item> + <p> + The finishing reallocation of the heap block when + hibernating a process is now always moving the heap block + since it drastically reduces memory fragmentation when + hibernating large amounts of processes.</p> + <p> + Own Id: OTP-7187</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.6.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + The SMP emulator on sparc64 erroneously used the sparc32 + atomic and the sparc32 spinlock implementations which + caused it to crash.</p> + <p> + Own Id: OTP-7006</p> + </item> + <item> + <p> + Call tracing the new guard BIFs <c>byte_size</c>, + <c>bit_size</c>, or <c>tuple_size</c> and the loading a + module that uses one of those functions, could cause the + emulator to terminate.</p> + <p> + Own Id: OTP-7008</p> + </item> + <item> + <p> + configuring --enable-darwin-universal or + --enable-darwin-64bit on MacOSX could result in a non + optimized emulator. Top level configure script now + corrected.</p> + <p> + Own Id: OTP-7014</p> + </item> + <item> + <p> + configuring --with-gd did not produce correct include + flags for percept.</p> + <p> + Own Id: OTP-7015</p> + </item> + <item> + <p> + Environment variables weren't handled in thread safe + manner in the runtime system with SMP support on Windows.</p> + <p> + <c>erl_drv_putenv()</c>, and <c>erl_drv_getenv()</c> has + been introduced for use in drivers. Do <em>not</em> use + putenv(), or getenv() directly in drivers. For more + information see the <c>erl_driver</c> documentation.</p> + <p> + Own Id: OTP-7035</p> + </item> + <item> + <p> + HIPE: Corrected the choice of interface to the send/3 and + setnode/3 BIFs for native-compiled code. Using the + incorrect interface could, in unusual circumstances, lead + to random runtime errors.</p> + <p> + Own Id: OTP-7067</p> + </item> + <item> + <p> + Garbage collections could become extremely slow when + there were many keys in the process dictionary. (Thanks + to Fredrik Svahn.)</p> + <p> + Own Id: OTP-7068</p> + </item> + <item> + <p> + The duplicate documentation directory in the windows + installation is removed.</p> + <p> + Own Id: OTP-7070</p> + </item> + <item> + <p>Documentation bugfixes and clarifications.</p> (Thanks + to Joern ([email protected]), Matthias Lang, and Richard + Carlsson.) + <p> + Own Id: OTP-7079</p> + </item> + <item> + <p> + The runtime system with SMP support <em>not</em> using + the native atomic integer implementation part of OTP + could deadlock when run on a system with more than one + logical processor. That is, only the runtime system with + SMP support on <em>other</em> hardware platforms than + x86, x86_64, sparc32, and powerpc32 were effected by this + bug.</p> + <p> + Own Id: OTP-7080</p> + </item> + <item> + <p> + The break handling code (run when Ctrl-C is hit) could + could potentially deadlock the runtime system with SMP + support.</p> + <p> + Own Id: OTP-7104</p> + </item> + <item> + <p> + The sctp driver has been updated to work against newer + lksctp packages e.g 1.0.7 that uses the API spelling + change adaption -> adaptation. Older lksctp (1.0.6) still + work. The erlang API in gen_sctp.erl and inet_sctp.hrl + now spells 'adaptation' regardless of the underlying C + API.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-7120</p> + </item> + <item> + <p>A bug in <c>erlang:phash2/1</c> on 64-bit platforms + has been fixed. (Thanks to Scott Lystig Fritchie.)</p> + <p> + Own Id: OTP-7127</p> + </item> + <item> + <p> + The emulator could under rare circumstances crash while + garbage collecting.</p> + <p> + Own Id: OTP-7132</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p>The documentation has been updated so as to reflect + the last updates of the Erlang shell as well as the minor + modifications of the control sequence <c>p</c> of the + <c>io_lib</c> module.</p> <p>Superfluous empty lines have + been removed from code examples and from Erlang shell + examples.</p> + <p> + Own Id: OTP-6944 Aux Id: OTP-6554, OTP-6911 </p> + </item> + <item> + <p> + Bit syntax construction with a small integer in a + non-byte aligned field wider than the CPU's word size + could cause garbage bits in the beginning of the field.</p> + <p> + Own Id: OTP-7085</p> + </item> + <item> + <p> + All Windows versions older than Windows 2000 are now + <em>not supported</em> by the Erlang runtime system. This + since there was a need for usage of features introduced + in Windows 2000.</p> + <p> + Own Id: OTP-7086</p> + </item> + <item> + <p>Memory management improvements especially for the + runtime system with SMP support:</p> <list> <item> The + runtime system with SMP support can now use multiple, + thread specific instances of most memory allocators. This + improves performance since it reduces lock contention in + the memory allocators. It may however increase memory + usage for some applications. The runtime system with SMP + support will by default enable this feature on most + allocators. The amount of instances used can be + configured. </item> <item> <c>driver_alloc()</c>, + <c>driver_realloc()</c>, and <c>driver_free()</c> now use + their own erts specific memory allocator instead of the + default <c>malloc()</c> implementation on the system. + </item> <item> The default configuration of some + allocators have been changed to fit applications that use + much memory better. </item> <item> Some new + <c>erts_alloc</c> configuration parameters have been + added. </item> <item> <c>erts_alloc_config</c> has been + modified to be able to create configurations suitable for + multiple instances of allocators. </item> <item> The + returned value from <c>erlang:system_info({allocator, + Alloc})</c> has been changed. This since an allocator may + now run in multiple instances. </item> </list> <p>If you + for some reason want the memory allocators to be + configured as before, you can pass the <c>+Mea r11b</c> + command-line argument to <c>erl</c>.</p> <p>For more + information see the <c>erts_alloc(3)</c>, the + <c>erts_alloc_config(3)</c>, and the <c>erlang(3)</c> + documentation.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-7100</p> + </item> + <item> + <p> + On Unix, denormalized floating point numbers could not be + created using <c>list_to_float/1</c> or + <c>binary_to_term/1</c>. (Thanks to Matthew Dempsky.)</p> + <p> + Own Id: OTP-7122</p> + </item> + <item> + <p> + Native atomic integers and spin-locks are now also + available for the runtime system with SMP support on + sparc64.</p> + <p> + Own Id: OTP-7130</p> + </item> + <item> + <p> + FP exceptions support for sparc64 userspace on Linux has + been added. Note that FP exception support is now turned + off by default, so to actually enable it you need to do + '<c>./configure --enable-fp-exceptions</c>'.</p> + <p> + Own Id: OTP-7131</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.6</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + A bug for raw files when reading 0 bytes returning 'eof' + instead of empty data has been corrected.</p> + <p> + Own Id: OTP-6291 Aux Id: OTP-6967 </p> + </item> + <item> + <p> + All exported functions in gzio.c have now been renamed to + avoid conflict with drivers that are indirectly linked + with an external zlib library.</p> + <p> + Own Id: OTP-6816 Aux Id: OTP-6591 </p> + </item> + <item> + <p> + On the 64-bit Erlang emulator, bit syntax construction + with integers containing more than 60 bits ("big + numbers") into fields with more than 60 bits could + produce incorrect results.</p> + <p> + Own Id: OTP-6833</p> + </item> + <item> + <p> + When the runtime system failed to allocate memory for + binaries, it could dead lock while writing the + <c>erl_crash.dump</c>.</p> + <p> + Own Id: OTP-6848</p> + </item> + <item> + <p> + The runtime system with SMP support could deadlock if a + process called the <c>erlang:suspend_process(Pid)</c> BIF + or the <c>erlang:garbage_collect(Pid)</c> BIF while the + process identified by <c>Pid</c> was currently running + and the process calling the BIFs was terminated during + the call to the BIFs.</p> + <p> + Processes suspending each other via the + <c>erlang:suspend_process/1</c> BIF or garbage collecting + each other via the <c>erlang:garbage_collect/1</c> BIF + could deadlock each other when the runtime system with + SMP support was used.</p> + <p> + Own Id: OTP-6920</p> + </item> + <item> + <p> + <c>dbg</c> could leave traced processes in a suspended + state if the tracer process was killed with exit reason + <c>kill</c>.</p> + <p> + <c>erlang:suspend_process/2</c> has been introduced which + accepts an option list as second argument. For more + information see the <c>erlang(3)</c> documentation.</p> + <p> + Processes suspended via + <c>erlang:suspend_process/[1,2]</c> will now be + automatically resumed if the process that called + <c>erlang:suspend_process/[1,2]</c> terminates.</p> + <p> + Processes could previously be suspended by one process + and resumed by another unless someone was tracing the + suspendee. This is <em>not</em> possible anymore. The + process resuming a process <em>has</em> to be the one + that suspended it.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-6946</p> + </item> + <item> + <p>file:write_file/3, file:write/2 and file:read/2 could + crash (contrary to documentation) for odd enough file + system problems, e.g write to full file system. This bug + has now been corrected.</p> <p>In this process the file + module has been rewritten to produce better error codes. + Posix error codes now originate from the OS file system + calls or are generated only for very similar causes (for + example 'enomem' is generated if a memory allocation + fails, and 'einval' is generated if the file handle in + Erlang is a file handle but currently invalid).</p> + <p>More Erlang-ish error codes are now generated. For + example <c>{error,badarg}</c> is now returned from + <c>file:close/1</c> if the argument is not of a file + handle type. See file(3).</p> <p>The possibility to write + a single byte using <c>file:write/2</c> instead of a list + or binary of one byte, contradictory to the + documentation, has been removed.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-6967 Aux Id: OTP-6597 OTP-6291 </p> + </item> + <item> + <p> + Monitor messages produced by the system monitor + functionality, and garbage collect trace messages could + contain erroneous heap and/or stack sizes when the actual + heaps and/or stacks were huge.</p> + <p> + As of erts version 5.6 the <c>large_heap</c> option to + <c>erlang:system_monitor/[1,2]</c> has been modified. 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 the specified size. Previously the + monitor message was sent if the memory block allocated + for the youngest generation was equal to or larger than + the specified size.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-6974 Aux Id: seq10796 </p> + </item> + <item> + <p> + <c>inet:getopts/2</c> returned random values on Windows + Vista.</p> + <p> + Own Id: OTP-7003</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + The emulator internal process lock implementation has + been rewritten and optimized. A slight risk of starvation + existed in the previous implementation. This risk has + also been eliminated in the new implementation.</p> + <p> + Own Id: OTP-6500</p> + </item> + <item> + <p> + Bitstrings (bit-level) binaries and binary comprehensions + are now part of the language. See the Reference Manual.</p> + <p> + Own Id: OTP-6558</p> + </item> + <item> + <p> + The windows version of erlang now has SMP support. The + SMP emulator is run by default on machines which shows + more than one virtual or physical processor.</p> + <p> + Own Id: OTP-6560 Aux Id: OTP-6925 </p> + </item> + <item> + <p> + The details of the compressed term format has been + documented in erl_ext_dist.txt. (Thanks to Daniel + Goertzen.)</p> + <p> + Own Id: OTP-6755</p> + </item> + <item> + <p> + The runtime system with SMP support is now started by + default if more than one logical processor are detected. + For more information, see the <c>erl(3)</c> + documentation.</p> + <p> + Own Id: OTP-6756</p> + </item> + <item> + <p> + The external format for Erlang terms and the distribution + protocol are now documented in ERTS User's Guide.</p> + <p> + Own Id: OTP-6779</p> + </item> + <item> + <p> + New BIF's erlang:system_profile/1 and + erlang:system_profile/2. These BIF's controls concurrency + profiling options for processes, ports and schedulers.</p> + <p> + Own Id: OTP-6783 Aux Id: OTP-6285 </p> + </item> + <item> + <p> + The <c>ErlDrvTermData</c> term types used by + <c>driver_output_term()</c> and <c>driver_send_term()</c> + have been extended with the term types + <c>ERL_DRV_BUF2BINARY</c>, <c>ERL_DRV_EXT2TERM</c>, and + <c>ERL_DRV_UINT</c>. <c>ERL_DRV_BUF2BINARY</c> is used + for passing and creating a binary, + <c>ERL_DRV_EXT2TERM</c> is used for passing terms encoded + with the external term format, and <c>ERL_DRV_UINT</c> is + used for passing unsigned integers.</p> + <p> + Also the data types <c>ErlDrvUInt</c> and + <c>ErlDrvSInt</c> have been added which makes it more + obvious how arguments to term types are interpreted with + regards to width and signedness.</p> + <p> + The incorrect data types <c>ErlDriverTerm</c>, + <c>ErlDriverBinary</c>, and <c>ErlDriverPort</c> in the + <c>erl_driver(3)</c> documentation have been replaced + with the correct data types <c>ErlDrvTermData</c>, + <c>ErlDrvBinary</c>, and <c>ErlDrvPort</c>.</p> + <p> + For more information see the <c>erl_driver(3)</c> + documentation.</p> + <p> + Own Id: OTP-6823</p> + </item> + <item> + <p> + Miscellaneous improvements of the erts internal thread + library.</p> + <p> + It now support optimized atomic operations and spin-locks + on windows.</p> + <p> + Fall-backs based on mutexes and/or spin-locks for missing + optimized atomic operations, spin-locks, or rwlocks has + been implemented. This makes it possible to compile the + runtime system with SMP support on a lot more platforms.</p> + <p> + Default stack size on OpenBSD has been increased to 256 + kilo-words.</p> + <p> + Own Id: OTP-6831 Aux Id: OTP-6560 </p> + </item> + <item> + <p>Many bit syntax operations, both construction and + matching, are faster. For further information, see the + Efficiency Guide.</p> + <p> + Own Id: OTP-6838</p> + </item> + <item> + <p>Literal lists, tuples, and binaries are no longer + constructed at run-time as they used to be, but are + stored in a per-module constant pool. Literals that are + used more than once are stored only once.</p> + <p>This is not a change to the language, only in the + details of its implementation. Therefore, the + implications of this change is described in the + Efficiency Guide.</p> + <p>Example 1: In the expression <c>element(BitNum-1, + {1,2,4,8,16,32,64,128})</c>, the tuple used to be + constructed every time the expression was executed, which + could be detrimental to performance in two ways if the + expression was executed in a loop: the time to build the + tuple itself and the time spent in garbage collections + because the heap filled up with garbage faster.</p> + <p>Example 2: Literal strings, such as <c>"abc"</c>, used + to be stored in the compiled code compactly as a byte + string and expanded to a list at run-time. Now all + strings will be stored expanded to lists (such as + <c>[$a,$b,$c]</c>) in the constant pool. That means that + the string will be faster to use at run-time, but that it + will require more space even when not used. If space is + an issue, you might want to use binary literals (that is, + <c><<"abc">></c>) instead of string literals for + infrequently used long strings (such as error + messages).</p> + <p> + Own Id: OTP-6850</p> + </item> + <item> + <p>The Erlang driver API has been extended with a + portable POSIX thread like API for multi-threading. The + Erlang driver thread API provides:</p> <list> + <item>Threads</item> <item>Mutexes</item> <item>Condition + variables</item> <item>Read/Write locks</item> + <item>Thread specific data</item> </list> <p>For more + information see the <c>erl_driver(3)</c> + documentation.</p> + <p> + Own Id: OTP-6857</p> + </item> + <item> + <p> + Recursive calls now usually consume less stack than in + R11B. See the Efficiency Guide.</p> + <p> + Own Id: OTP-6862 Aux Id: seq10746 </p> + </item> + <item> + <p> + The deprecated BIFs <c>erlang:old_binary_to_term/1</c> + and <c>erlang:info/1</c> have been removed.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-6876</p> + </item> + <item> + <p> + Calls to driver call-backs triggered by external events + are now scheduled and interleaved with execution of + Erlang processes also on the runtime system without SMP + support.</p> + <p> + Own Id: OTP-6878</p> + </item> + <item> + <p> + Faster arithmetic of integers of more than 27 bits signed + (or 60 bits signed on an 64-bit CPU), and also faster + integer multiplication. (Thanks to Tony Rogvall.)</p> + <p> + Own Id: OTP-6891</p> + </item> + <item> + <p>Significant improvements of the <c>process_info</c> + BIFs:</p> <list> <item> <c>process_info/2</c> can now be + called with a list of items as second argument in order + to atomically retrieve information about multiple items. + </item> <item> <c>process_info/[1,2]</c> has been + optimized in the runtime system with SMP support. The + whole scheduler could previously be blocked for a + significant period of time in <c>process_info/[1,2]</c> + waiting for a lock on the process being inspected. The + Erlang process calling <c>process_info/[1,2]</c> can + still be blocked for a significant period of time waiting + for the lock, but the scheduler will now be able to run + other processes while the process calling + <c>process_info/[1,2]</c> waits for the lock. </item> + <item> <c>process_info/2</c> now accept a few more items + than before. </item> <item> The documentation of + <c>process_info/[1,2]</c> has been improved. </item> + </list> <p>For more information see the <c>erlang(3)</c> + documentation.</p> + <p> + Own Id: OTP-6899</p> + </item> + <item> + <p> + <c>open_port({}, [])</c> could crash the emulator. + (Thanks to Matthew Dempsky.)</p> + <p> + Own Id: OTP-6901</p> + </item> + <item> + <p>Two new guard BIFs have been introduced as a + recommended replacement for <c>size/1</c>. (The + <c>size/1</c> BIF will be removed no earlier than in + R14B.) The BIFs are <c>tuple_size/1</c> to calculate the + size of a tuple and <c>byte_size/1</c> to calculate the + number of bytes needed for the contents of the binary or + bitstring (rounded up to the nearest number of bytes if + necessary).</p> + <p>There is also a new <c>bit_size/1</c> BIF that returns + the exact number of bits that a binary or bitstring + contains.</p> + <p> + Own Id: OTP-6902</p> + </item> + <item> + <p>The <c>ets:fixtable/2</c> function, which has been + deprecated for several releases, has been removed.</p> + <p>The <c>ets:info/1</c> function has been reimplemented + as a BIF, which guarantees that information returned is + consistent.</p> + <p>The <c>ets:info/2</c> function now fails with reason + <c>badarg</c> if the second argument is invalid. + (Dialyzer can be used to find buggy code where the second + argument is misspelled.)</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-6906</p> + </item> + <item> + <p> + As the linux kernel may generate a minor fault when + tracing with CPU timestamps, and there exists no patch to + the Linux kernel that fixes the problem, cpu timestamps + are disabled on Linux for now.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-6922</p> + </item> + <item> + <p>The functions io:columns/0, io:columns/1, io:rows/0 + and io:rows/1 are added to allow the user to get + information about the terminal geometry. The shell takes + some advantage of this when formatting output. For + regular files and other io-devices where height and width + are not applicable, the functions return + {error,enotsup}.</p> + <p>Potential incompatibility: If one has written a custom + io-handler, the handler has to either return an error or + take care of io-requests regarding terminal height and + width. Usually that is no problem as io-handlers, as a + rule of thumb, should give an error reply when receiving + unknown io-requests, instead of crashing.</p> + <p> + *** POTENTIAL INCOMPATIBILITY ***</p> + <p> + Own Id: OTP-6933</p> + </item> + <item> + <p> + <c>driver_caller()</c> can now also be used from the + <c>start</c> callback of a driver.</p> + <p> + Own Id: OTP-6951</p> + </item> + <item> + <p> + The emulator can now be compiled for 64bit intel, as well + as a 32bit universal binary on darwin/MacOSX 10.4 and + 10.5.</p> + <p> + Own Id: OTP-6961</p> + </item> + <item> + <p> + If <c>open_port</c> fails because all available ports are + already in use, it will now throw a <c>system_limit</c> + exception instead of an <c>enfile</c> exception. + (<c>enfile</c> might still be thrown if the operating + system would return ENFILE.)</p> + <p> + Own Id: OTP-6968</p> + </item> + <item> + <p> + The <c>spawn_monitor/1</c> and <c>spawn_monitor/3</c> BIFs + are now auto-imported (i.e. they no longer need an + <c>erlang:</c> prefix).</p> + <p> + Own Id: OTP-6975</p> + </item> + <item> + <p> + On Windows, the werl window now handles resize, so that + the whole window can be utilized. Text selection is also + updated to be line oriented instead of rectangle oriented + as in earlier versions.</p> + <p> + Own Id: OTP-6994 Aux Id: OTP-6933 </p> + </item> + <item> + <p> + Kqueue support (kernel-poll) has been enabled on FreeBSD. + The problem with kqueue not detecting writes on a pipe on + FreeBSD was actually not a kqueue issue, but a writev on + pipes issue. Neither poll(), nor select() detected the + write when the bug hit. NetBSD and DragonFlyBSD probably + have or have had the same bug. This bug should have been + fixed in FreeBSD 6.3 and FreeBSD 7.0 thanks to + Jean-Sebastien Pedron.</p> + <p> + Own Id: OTP-7001</p> + </item> + </list> + </section> + +</section> + + +<section><title>Erts 5.5.5.5</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Hanging writes on temporarily unavailable NFS + filesystems could cause the execution of (not file + related) erlang code to get blocked even though I/O + threads were used. This is now corrected.</p> + <p> + Own Id: OTP-6907 Aux Id: seq10771 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.5.5.4</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Data passed to a driver via <c>erlang:port_call</c> could + be corrupted when the runtime system with SMP support was + used. (Thanks to YAMASHINA Hio.)</p> + <p> + Own Id: OTP-6879</p> + </item> + <item> + <p> + In the SMP emulator, if several processes called + ets:update_counter/3 (even for different tables) when the + counter values exceeded 27 bits, the counter values could + be corrupted or the emulator could crash.</p> + <p> + Own Id: OTP-6880 Aux Id: seq10760 </p> + </item> + </list> + </section> + +</section> + + +<section><title>Erts 5.5.5.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>Creating a named table using <c>ets:new/2</c> or + renaming a named table using <c>ets:rename/2</c> could in + rare circumstances succeed, meaning that there would be + two or more tables with the same name. Now such call will + fail with a <c>badarg</c> exception as it is supposed to + do.</p> + <p><c>ets:delete/1</c> used on a named table now removes + the name immediately so that a new table with the same + name can be created.</p> + <p>Turning on call trace on the internal BIF that + implements <c>ets:delete/1</c> would crash the + emulator.</p> + <p>SMP emulator only: Using <c>ets:rename/2</c> on a + table that <c>ets:safe_fixtable/2</c> has been used on + could cause an emulator crash or undefined behaviour + because of a missing lock.</p> + <p> + Own Id: OTP-6872 Aux Id: seq10756, seq10757 </p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.5.5.2</title> + + <section><title>Known Bugs and Problems</title> + <list> + <item> + <p> + ets:select/3 on ordered_set and with a chunksize a + multiple of 1000 gave all elements instead of just 1000. + Also ets:slot/2 on ordered set could give unexpected + results on SMP emulator. Both problems are corrected.</p> + <p> + Own Id: OTP-6842</p> + </item> + </list> + </section> + +</section> + +<section><title>Erts 5.5.5.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + All exported functions in gzio.c have now been renamed to + avoid conflict with drivers that are indirectly linked + with an external zlib library.</p> + <p> + Own Id: OTP-6816 Aux Id: OTP-6591 </p> + </item> + <item> + <p> + Calling binary_to_term/1 with certain invalid binaries + would crash the emulator.</p> + <p> + Own Id: OTP-6817</p> + </item> + </list> + </section> + + + <section><title>Improvements and New Features</title> + <list> + <item> + <p> + Restored speed of bit-syntax matching of 32 bits + integers.</p> + <p> + Own Id: OTP-6789 Aux Id: seq10688 </p> + </item> + </list> + </section> + +</section> + + <section> + <title>Erts 5.5.5</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The functions in gzio.c have been renamed to avoid + conflict with drivers that indirectly linked with an + external zlib library.</p> + <p>Own Id: OTP-6591</p> + </item> + <item> + <p>The emulator without SMP support dumped core if an + async-thread finished a job after the emulator had begun + writing an <c><![CDATA[erl_crash.dump]]></c>. </p> + <p>Own Id: OTP-6685</p> + </item> + <item> + <p>In bit syntax matching, integer fields with greater + size than 16Mb would fail to match. (Thanks to Bertil + Karlsson and Francesco Pierfederici.)</p> + <p>Matching out a 32-bit integer not aligned on a byte + boundary from a binary could cause an heap overflow (and + subsequent termination of the emulator).</p> + <p>A module that contained bit syntax construction with a + literal field size greater than 16Mb would fail to + load.</p> + <p>Several other similar bugs having to do with huge + field sizes were eliminated.</p> + <p>Attempting to construct a binary longer than 536870911 + bytes will now fail with a <c><![CDATA[system_limit]]></c> exception + (rather than fail in mysterious ways or construct an + binary with incorrect contents). Similarily, attempting + to match a binary longer than 536870911 bytes will now + fail (instead of producing an incorrect result). This + limitation has been documented in the Efficiency Guide. + (The limit is in the 32-bit emulator; use the 64-bit + emulator if you need to handle larger binaries than + 536870911.)</p> + <p>Own Id: OTP-6686</p> + </item> + <item> + <p>Bugs in rem and div of very large numbers are corrected.</p> + <p>Own Id: OTP-6692</p> + </item> + <item> + <p><c><![CDATA[erlang:system_info({allocator, Alloc})]]></c> didn't + allocate enough heap when a bignum was part of the result + which could cause an emulator crash.</p> + <p>Own Id: OTP-6693</p> + </item> + <item> + <p>It was previously not possible to pass + <c><![CDATA[erts_alloc]]></c> the same configuration via the + command-line, as used by default. </p> + <p>A <c><![CDATA[+M*]]></c> command-line argument that configure a + size of some sort can now be passed a value that equals + the size of the address space. The value used, in this + case, will be <c><![CDATA["the size of the address space" - 1]]></c>.</p> + <p>Own Id: OTP-6699</p> + </item> + <item> + <p><c><![CDATA[SysIOVec* driver_peekq(ErlDrvPort port, int *vlen)]]></c> did not update <c><![CDATA[*vlen]]></c> if <c><![CDATA[port]]></c> was + invalid. <c><![CDATA[*vlen]]></c> is now set to <c><![CDATA[-1]]></c> if the + <c><![CDATA[port]]></c> is invalid.</p> + <p>The <c><![CDATA[efile]]></c> driver + expects <c><![CDATA[*vlen]]></c> to be updated also when the + <c><![CDATA[port]]></c> is invalid. This situation occurs seldom, but + when the runtime system has async-threads enabled and + ports are killed it can. When it occurred the runtime + system crashed.</p> + <p>Own Id: OTP-6729</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>For scripts written using <c><![CDATA[escript]]></c>, there is a new + function <c><![CDATA[escript:script_name/0]]></c>, which can be used + to retrieve the pathame of the script. The documentation + has been clarified regarding pre-defined macros such as + ?MODULE and the module name.</p> + <p>Own Id: OTP-6593</p> + </item> + <item> + <p>The section Guards in the chapter The Abstract Format + of the ERTS User's Guide has been updated.</p> + <p>Own Id: OTP-6600</p> + </item> + <item> + <p>Corrected protocol layer flue for socket options + SO_LINGER, SO_SNDBUF and SO_RCVBUF, for SCTP.</p> + <p>Own Id: OTP-6625 Aux Id: OTP-6336 </p> + </item> + <item> + <p>The behaviour of the inet option {active,once} on peer + close is improved and documented.</p> + <p>Own Id: OTP-6681</p> + </item> + <item> + <p>The inet option send_timeout for connection oriented + sockets is added to allow for timeouts in communicating + send requests to the underlying TCP stack.</p> + <p>Own Id: OTP-6684 Aux Id: seq10637 OTP-6681 </p> + </item> + <item> + <p>The command line flag <c><![CDATA[-args_file FileName]]></c>, and + the environment variables <c><![CDATA[ERL_AFLAGS]]></c>, and + <c><![CDATA[ERL_ZFLAGS]]></c> for the <c><![CDATA[erl]]></c> command have been + added. For more information see the <c><![CDATA[erl(1)]]></c> + documentation.</p> + <p>Own Id: OTP-6697</p> + </item> + <item> + <p>The <c><![CDATA[is_constant/1]]></c> type test has been deprecated. + <c><![CDATA[is_constant/1]]></c> is improperly named and almost + entirely undocumented.</p> + <p>Own Id: OTP-6731</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.4.3</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p><c><![CDATA[process_flag(trap_exit, Bad)]]></c> where <c><![CDATA[Bad]]></c> + was a term not equal to <c><![CDATA[true]]></c> or <c><![CDATA[false]]></c>, + didn't fail with <c><![CDATA[badarg]]></c> as it should; instead, the + failure was silently ignored. This bug was introduced in + <c><![CDATA[erts-5.5.2]]></c>.</p> + <p>Own Id: OTP-6627 Aux Id: OTP-6160 </p> + </item> + <item> + <p>The minimum and default stack size for async-threads has + been increased to 16 kilowords. This since the previous + minimum and default stack size of 8 kilowords proved to + be too small (introduced in <c><![CDATA[erts-5.5.4.2]]></c>).</p> + <p>Own Id: OTP-6628 Aux Id: OTP-6580, Seq10633 </p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>process_flag/2 accepts the new flag <c><![CDATA[sensitive]]></c>.</p> + <p>Own Id: OTP-6592 Aux Id: seq10555 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.4.2</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>When a port steals control over a file descriptor from + another port, the stealing port tests if the other port + is alive. This in order to be able to give an accurate + error message. In the runtime system with SMP support, + this test was done without appropriate locks held. This + could in worst case lead to an erroneous error message; + therefore, this bug is to be considered harmless.</p> + <p>Own Id: OTP-6602</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The default stack size for threads in the async-thread + pool has been shrunk to 8 kilowords, i.e., 32 KB 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 <c><![CDATA[driver_async()]]></c> functionality. A suggested + stack size for threads in the async-thread pool can be + configured via the <c><![CDATA[+a]]></c> command line argument of + <c><![CDATA[erl(1)]]></c>.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-6580</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.4.1</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Setting the time on the system while using heart on a + linux machine where the emulator was built with + clock_gettime support (default from Linux 2.6/erts-5.5.4 + and upwards), could make the heart command fire. This was + due to bug in the heart executable which is now + corrected.</p> + <p>Own Id: OTP-6598 Aux Id: seq10614 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.4</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Corrected misspelling of '<c><![CDATA[-pz]]></c>' in the help text + for <c><![CDATA[erlc]]></c>. (Thanks to Ulf Wiger.)</p> + <p>Own Id: OTP-6433</p> + </item> + <item> + <p>The MD5 calculation of a BEAM file done by + <c><![CDATA[code:module_md5/1]]></c>, <c><![CDATA[beam_lib:md5/1]]></c>, and by + the compiler for the default value of the <c><![CDATA[vsn]]></c> + attribute have all been changed so that its result will + be the same on all platforms; modules containing funs + could get different MD5s on different platforms.</p> + <p>Own Id: OTP-6459</p> + </item> + <item> + <p>The emulator could dump core while writing an + <c><![CDATA[erl_crash.dump]]></c> file if there were funs with a + large terms in its environment. Since there is no way to + inspect a fun's environment in the crashdump_viewer + application anyway, a variables in the environment are + now set to [] before dumping the fun. (Thanks to + Jean-Sebastien Pedron.)</p> + <p>Own Id: OTP-6504</p> + </item> + <item> + <p><c><![CDATA[{Port, {exit_status, S}}]]></c> messages from ports + opened with the <c><![CDATA[exit_status]]></c> option could under + rare circumstances be delayed. This bug was present on + Erlang runtime systems without SMP support on all unix + operating systems other than SunOS.</p> + <p>Own Id: OTP-6528</p> + </item> + <item> + <p>A bug in linuxthreads could cause the emulator to dump + core when dlerror() was called before the first call to + dlopen(). As a workaround the emulator always makes a + call to dlopen() on initialization when linuxthreads is + used as thread library.</p> + <p>Own Id: OTP-6530</p> + </item> + <item> + <p>file:sync/1 did not do anything on Windows. Now it calls + the system function for flushing buffers + (FlushFileBuffers()). (Thanks to Matthew Sackman.)</p> + <p>Own Id: OTP-6531</p> + </item> + <item> + <p><c><![CDATA[open_port/2]]></c> could on the runtime system with SMP + support fail with the wrong exit reason when a port + couldn't be created. When this happened the exit reason + was typically <c><![CDATA[eintr]]></c>, or <c><![CDATA[ebusy]]></c> instead of + <c><![CDATA[eagain]]></c>.</p> + <p>Own Id: OTP-6536</p> + </item> + <item> + <p>The file driver (efile_drv) did not flush data written + using the option 'delayed_write' after the set timeout + time, rather at the next file operation. This bug has now + been corrected.</p> + <p>Own Id: OTP-6538</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>An interface towards the SCTP Socket API Extensions + has been implemented.It is an Open Source patch courtesy + of Serge Aleynikov and Leonid Timochouk. The Erlang code + parts has been adapted by the OTP team, changing the + Erlang API somewhat.</p> + <p>The Erlang interface consists of the module + <c><![CDATA[gen_sctp]]></c> and an include file + <c><![CDATA[-include_lib("kernel/include/inet_sctp.hrl").]]></c> for + option record definitions. The <c><![CDATA[gen_sctp]]></c> module is + documented.</p> + <p>The delivered Open Source patch, before the OTP team + rewrites, was written according to + http://tools.ietf.org/html/draft-ietf-tsvwg-sctpsocket-13 + and was claimed to work fine, tested on Linux Fedora Core + 5.0 (kernel 2.6.15-2054 or later) and on Solaris 10 and + 11. The OTP team rewrites used the same standard document + but might have accidentally broken some functionality. If + so it will soon be patched to working state. The tricky + parts in C and the general design has essentially not + changed. During the rewrites the code was hand tested on + SuSE Linux Enterprise Server 10, and briefly on Solaris + 10. Feedbach on code and docs is very much + appreciated.</p> + <p>The SCTP interface is in beta state. It has only been + hand tested and has no automatic test suites in OPT + meaning everything is most certainly not tested. Socket + active mode is broken. IPv6 is not tested. The + documentation has been reworked due to the API changes, + but has not been proofread after this.</p> + <p>Thank you from the OTP team to Serge Aleynikov and + Leonid Timochouk for a valuable contribution. We hope we + have not messed it up too much.</p> + <p>Own Id: OTP-6336</p> + </item> + <item> + <p>A <c><![CDATA[{minor_version,Version}]]></c> option is now recognized + by <c><![CDATA[term_to_binary/2]]></c>. {minor_version,1} will cause + floats to be encoded in an exact and more space-efficient + way compared to the previous encoding.</p> + <p>Own Id: OTP-6434</p> + </item> + <item> + <p>There is a new <c><![CDATA[escript]]></c> program that can be used + for writing scripts in Erlang. Erlang scripts don't need + to be compiled and any arguments can be passed to them + without risk that they are interpreted by the Erlang + system.</p> + <p>Own Id: OTP-6505</p> + </item> + <item> + <p>Setting and getting socket options in a "raw" fashion is + now allowed. Using this feature will inevitably produce + non portable code, but will allow setting ang getting + arbitrary uncommon options on TCP stacks that do have + them.</p> + <p>Own Id: OTP-6519</p> + </item> + <item> + <p>Miscellaneous signal handling improvements on the Erlang + runtime system with SMP support.</p> + <p>The fallback implementation of spin locks and atomic + operations are now implemented using pthread spin locks + when pthread spin locks are found on the system.</p> + <p>The Erlang runtime system with SMP support can now run on + Linux systems that has Linuxthreads instead of NPTL + (Native POSIX Thread Library). Note that the SMP support + hasn't been as thoroughly tested with Linuxthreads as + with NPTL. A runtime system with SMP support will + therefore not be built by default on Linux when NPTL + isn't found. In order to force a build of the runtime + system with SMP support, pass <c><![CDATA[--enable-smp-support]]></c> + to <c><![CDATA[configure]]></c> when building OTP.</p> + <p>Own Id: OTP-6525</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.3.1</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p><c><![CDATA[erlang:system_flag(multi_scheduling, block)]]></c> could + cause the emulator with SMP support to deadlock.</p> + <p>Own Id: OTP-6431 Aux Id: OTP-6403 </p> + </item> + <item> + <p>The runtime system with SMP support failed to call the + driver timeout callback of ports in state closing. This + could cause ports to fail flushing their I/O queues.</p> + <p>Own Id: OTP-6432</p> + </item> + <item> + <p>The <c><![CDATA[{Port, closed}]]></c> message from a closed port + could arrive at the port owner before <c><![CDATA[Port]]></c> had + been removed from the result of <c><![CDATA[erlang:ports/0]]></c> in + the runtime system with SMP support.</p> + <p>Own Id: OTP-6437</p> + </item> + <item> + <p>The async id of async jobs created via + <c><![CDATA[driver_async]]></c> wasn't created in a thread safe + manner in the runtime system with SMP support. This could + in worst case cause <c><![CDATA[driver_async_cancel()]]></c> to + cancel another async job than intended.</p> + <p>Own Id: OTP-6438</p> + </item> + <item> + <p>Under rare circumstances a terminating connection between + two nodes could cause an instantaneous reconnect between + the two nodes to fail on the runtime system with SMP + support.</p> + <p>Own Id: OTP-6447</p> + </item> + <item> + <p>In the documentation of the driver entry field + <c><![CDATA[extended_marker]]></c> of erts version 5.5.3 + (<c><![CDATA[driver_entry(3)]]></c>), the following is stated: "The + following fields are ignored if this field is equal to + <c><![CDATA[0]]></c>". This is a documentation bug and has been + changed to: "If this field is equal to <c><![CDATA[0]]></c>, all the + fields following this field also <em>have</em> to be + <c><![CDATA[0]]></c>, or <c><![CDATA[NULL]]></c> in case it is a pointer field".</p> + <p>The runtime check for detection of old incompatible + drivers made when loading drivers has been improved. The + emulator can, however, not make sure that a driver that + doesn't use the extended driver interface isn't + incompatible. Therefore, when loading a driver that + doesn't use the extended driver interface, there is a + risk that it will be loaded also when the driver is + incompatible. When the driver use the extended driver + interface, the emulator can verify that it isn't of an + incompatible driver version. You are therefore advised to + use the extended driver interface.</p> + <p>For more information see the <c><![CDATA[erl_driver(3)]]></c> and + <c><![CDATA[driver_entry(3)]]></c> documentation.</p> + <p>Own Id: OTP-6452 Aux Id: OTP-6330 </p> + </item> + <item> + <p>When terminating ports on the runtime system with SMP + support, removal of links to processes was done without + locking the link lock on processes. This could cause an + emulator crash.</p> + <p>Own Id: OTP-6475</p> + </item> + <item> + <p>The emulator with SMP support could crash when a port + flushed its I/O queue by calling <c><![CDATA[driver_async()]]></c> + from the timeout driver callback.</p> + <p>Own Id: OTP-6479</p> + </item> + <item> + <p>Large exit reasons could under rare circumstances cause + the runtime system with SMP support to crash.</p> + <p>Own Id: OTP-6521</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Faster system calls for keeping the time accurate are + used on newer Linux kernels, which can result in a + significant speed-up of the emulator on those systems.</p> + <p>Own Id: OTP-6430</p> + </item> + <item> + <p>Added number of async threads and number of scheduler + threads to the system information that can be retrieved + via <c><![CDATA[driver_system_info()]]></c>. For more information see + the <c><![CDATA[erl_driver(3)]]></c> documentation.</p> + <p>Own Id: OTP-6440</p> + </item> + <item> + <p>When <c><![CDATA[SIGUSR1]]></c> is received by the runtime system + with SMP support, the <c><![CDATA[erl_crash.dump]]></c> is now + written by a special thread, instead of as before + directly from the signal handler.</p> + <p>Own Id: OTP-6465</p> + </item> + <item> + <p>term_to_binary/2 with compression is now faster.</p> + <p></p> + <p>term_to_binary/2 now accepts the option + '<c><![CDATA[{compressed,Level}]]></c>' for specifying the + compression level. <c><![CDATA[Level]]></c> must be in the range 0 + (no compression) through 9 (highest compression level). + Default is 6.</p> + <p>Future compatibility bugfix: binary_to_term/1 did not + handle the <c><![CDATA[Uniq]]></c> and <c><![CDATA[Index]]></c> fields + correctly.</p> + <p>Own Id: OTP-6494</p> + </item> + <item> + <p>Removed unnecessary reallocation when initializing + kernel-poll set.</p> + <p>Own Id: OTP-6516</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.3</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Node and fun table entries could under rare circumstances + be deallocated multiple times on the emulator with SMP + support.</p> + <p>Own Id: OTP-6369</p> + </item> + <item> + <p>epoll_wait() can repeat entries for the same file + descriptor in the result array. This could cause the + ready_input, ready_output, or event callbacks of a driver + to unintentionally be called multiple times. We have only + noted repeated entries when an error condition has + occurred on the file descriptor. In this case, the + repeated entries should normally not be a problem for the + driver since it should detect the error and de-select the + file descriptor. Therefore this bug should be considered + harmless. The emulator now coalesce repeated entries into + one.</p> + <p>You are only affected by this bug if you are using + erts-5.5.2.* and the kernel-poll feature on linux.</p> + <p>Own Id: OTP-6376 Aux Id: OTP-6222 </p> + </item> + <item> + <p>If a process that was waiting in gen_tcp:accept/1 was + killed, calling gen_tcp:accept/1 again on the same listen + socket would fail with '<c><![CDATA[{error,einval}]]></c>'.</p> + <p>Own Id: OTP-6381 Aux Id: seq10535 </p> + </item> + <item> + <p>The emulator failed to start on Solaris 10 when + kernel-poll support was enabled and the maximum number of + filedescriptors configured was less than or equal to 256.</p> + <p>Own Id: OTP-6384 Aux Id: OTP-6222 </p> + </item> + <item> + <p>The R10B compiler could generate unsafe + <c><![CDATA[bs_save/bs_restore]]></c> instructions that could cause + memory corruption. (The R11B compiler does not have that + problem.) The erlang emulator will now refuse to load + R10B-compiled modules that contain such unsafe + <c><![CDATA[bs_save/bs_restore]]></c> instructions. In addition, the + beam_validator module in the compiler will also reject + such instructions (in case it is used to validate R10B + code). (Thanks to Matthew Reilly.)</p> + <p>Own Id: OTP-6386</p> + </item> + <item> + <p>Process and port timers could fail to work properly on + the runtime system with SMP support. Many thanks to + Dmitriy Kargapolov and Serge Aleynikov who tracked down + this bug.</p> + <p>Own Id: OTP-6387</p> + </item> + <item> + <p>Bit syntax code compiled by an R10B compiler that matched + out a floating point number would not properly check that + the floating point number was valid; if the float was, + for instance, NaN the emulator could crash.</p> + <p>Own Id: OTP-6395</p> + </item> + <item> + <p>statistics(runtime) on Windows used to return the elapsed + system time for the process, instead of the user time. + Corrected. (Thanks to Robert Virding.)</p> + <p>Own Id: OTP-6407</p> + </item> + <item> + <p>A loadable driver (loaded by erl_ddll) which used + driver_async() would cause the emulator to crash. (Thanks + to Dmitriy Kargapolov.)</p> + <p>Own Id: OTP-6410</p> + </item> + <item> + <p>Under rare circumstances the emulator on unix platforms + could fail to terminate the Erlang port corresponding to + a port program opened with the <c><![CDATA[exit_status]]></c> option.</p> + <p>Own Id: OTP-6411</p> + </item> + <item> + <p>A link removed via <c><![CDATA[unlink/1]]></c> could under rare + circumstances transfer exit signals for a short period of + time after the call to <c><![CDATA[unlink/1]]></c> had returned when + the runtime system with SMP support was used.</p> + <p>Own Id: OTP-6425 Aux Id: OTP-6160 </p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>In the runtime system with SMP support, ports are now + being scheduled on the scheduler threads interleaved with + processes instead of being run in a separate I/O thread.</p> + <p>Own Id: OTP-6262</p> + </item> + <item> + <p>More interfaces are added in erl_ddll, to support + different usage scenarios.</p> + <p>Own Id: OTP-6307 Aux Id: OTP-6234 </p> + </item> + <item> + <p>In the runtime system with SMP support, the global + I/O lock has been replaced with a more fine grained port + locking scheme. Port locking is either done on driver + level, i.e., all ports executing the same driver share a + lock, or on port level, i.e., each port has its own lock. + Currently the inet driver, the efile driver, and the + spawn driver use port level locking and all other + statically linked in drivers use driver level locking. By + default dynamically linked in drivers will use locking on + driver level. For more information on how to enable port + level locking see the <c><![CDATA[erl_driver(3)]]></c> and the + <c><![CDATA[driver_entry(3)]]></c> man pages. </p> + <p>As of erts + version 5.5.3 the driver interface has been extended. The + extended interface introduce version management, the + possibility to pass capability flags to the runtime + system at driver initialization, and some new driver API + functions. For example, the <c><![CDATA[driver_system_info()]]></c> + function which can be used to determine if the driver is + run in a runtime system with SMP support or not. The + extended interface doesn't have to be used, <em>but</em> + dynamically linked in driver <em>have</em> to be + recompiled. For information see the <c><![CDATA[erl_driver(3)]]></c> + and the <c><![CDATA[driver_entry(3)]]></c> man pages. </p> + <p><em>NOTE:</em> Dynamically linked in drivers + <em>have</em> to be recompiled. </p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-6330 Aux Id: OTP-6262 </p> + </item> + <item> + <p>A test and debug feature which modifies the timing of the + runtime system has been added. For more information, see + documentation of the <c><![CDATA[+T<Level>]]></c> command line + argument of <c><![CDATA[erl(1)]]></c>.</p> + <p>Own Id: OTP-6382</p> + </item> + <item> + <p>The version of zlib (http://zlib.net) linked into + run-time system has been updated to version 1.2.3.</p> + <p>Own Id: OTP-6394</p> + </item> + <item> + <p>The <c><![CDATA[erlc]]></c> program now passes on the <c><![CDATA[-smp]]></c> + and <c><![CDATA[-hybrid]]></c> options to the Erlang emulator it + starts. This is mainly useful for compiling native code, + because native code must be compiled with same type of + run-time system as in which it will be run.</p> + <p>If the <c><![CDATA[-s]]></c> option is given, <c><![CDATA[erlc]]></c> now + prints a warning that it is deprecated and that it will + be removed in R12B.</p> + <p>Own Id: OTP-6398</p> + </item> + <item> + <p>The <c><![CDATA[schedulers]]></c> option of + <c><![CDATA[erlang:system_flag/2]]></c> has been removed, i.e., the + number of scheduler threads cannot be changed after + emulator boot time any more.</p> + <p>A <c><![CDATA[multi_scheduling]]></c> option has been added to + <c><![CDATA[erlang:system_flag/2]]></c>. This option can be used for + blocking and unblocking multi-scheduling. For more + information see the <c><![CDATA[erlang(3)]]></c> documentation.</p> + <p>Own Id: OTP-6403</p> + </item> + <item> + <p>A port program that had been started with the + <c><![CDATA[exit_status]]></c> option and closed one of the pipes + used for communication with the emulator caused the + emulator to continuously poll for termination of the port + program. This only became a problem when the emulator + didn't have other things to do and the port program + closed a pipe much earlier than it terminated. When the + emulator had other things to do, such as running Erlang + processes, the emulator polled for termination in between + scheduling of processes.</p> + <p>Now the emulator doesn't poll for termination of the port + program at all; instead, it waits for the child signal + from the terminated port program to arrive and then + schedules the Erlang port for termination.</p> + <p>The termination of any port programs have also been + optimized. Previously the termination of any port program + did always cause a scan of a table of the size equal to + maximum number of file descriptors. If the maximum number + of file descriptors was large, this scan could be quite + expensive. Now the search have been reduced to the set of + ports started with the <c><![CDATA[exit_status]]></c> option.</p> + <p>Note, all of the above only applies to Erlang emulators + on Unix platforms.</p> + <p>Own Id: OTP-6412 Aux Id: seq10194 </p> + </item> + <item> + <p>* BEAM: added support for floating-point exceptions on + FreeBSD (32-bit x86)</p> + <p>* SMP: made locking procedures work even when native + lock operations aren't implemented</p> + <p>* SMP: improved timing accuracy in the timer thread + (if enabled)</p> + <p>Own Id: OTP-6424</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.2.2</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>A bug in the kernel poll implementation could cause the + emulator to omit polling for events on file descriptors. + The bug was only present when using the kernel poll + implementation based on epoll or kqueue. This bug was + introduced in erts-5.5.2.</p> + <p>Own Id: OTP-6344 Aux Id: OTP-6222 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.2.1</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The run_erl program now acquires its pseudo-ttys using + openpty(3), so that it will work on newer Linux + distributions that don't have the traditional pseudo-tty + devices in the file system. On platforms that don't have + openpty(3), run_erl will still search for pseudo-tty + devices in the file system.</p> + <p>The run_erl program will now wait using waitpid(3) to + prevent the program it spawned to become defunct. run_erl + will also terminate after a delay of 5 seconds (to allow + any pending output to be written to the log file) if the + spawned program terminates even if some child of it still + holds stdin and/or stdout open.</p> + <p>Own Id: OTP-6225 Aux Id: seq10500 </p> + </item> + <item> + <p>A bug in ordered_set ETS datatyp caused ets:select (and + match) to return faulty results when the table contained + process id's from another node.</p> + <p>Own Id: OTP-6338</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.2</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>erlc: A typo in the help text for '-pa path' was + corrected.</p> + <p>Own Id: OTP-6218</p> + </item> + <item> + <p>Failure in port command/control driver callbacks could + crash the non-SMP emulator. This bug was introduced in + the 5.5 version of erts.</p> + <p>Own Id: OTP-6224</p> + </item> + <item> + <p>Erroneous "<c><![CDATA[Input driver gone away without deselecting!]]></c>" error reports could sometimes occur + when a driver instance terminated in the ready_output() + callback of the driver. This bug was only present in + emulators that used poll(). Note, that this bug was + harmless, the only effect it had was the erroneous error + report.</p> + <p>Own Id: OTP-6229 Aux Id: OTP-3993, Seq5266, Seq7247, + OTP-4307 </p> + </item> + <item> + <p>The emulator could cause a type assertion failure while + writing an erl_crash.dump, causing the erl_crash.dump to + be terminated and a core dump generated.</p> + <p>Own Id: OTP-6235 Aux Id: seq10444 </p> + </item> + <item> + <p>The registered name of a process is now the last + observable resource removed before links and monitors are + triggered when a process terminates.</p> + <p>Previously ets tables were removed after the registered + name. This could cause problems on the runtime system + with SMP support for code that expected that ets tables + owned by a specific process had been removed if the name + of the process had been removed.</p> + <p>Own Id: OTP-6237</p> + </item> + <item> + <p>Failure to fork() a new (os) process could cause the + emulator to deadlock. This bug affect all emulators with + SMP support, and emulators with async thread support on + SunOS.</p> + <p>Own Id: OTP-6241 Aux Id: OTP-3906 </p> + </item> + <item> + <p>Fprof traces could become truncated for the SMP emulator. + This bug has now been corrected.</p> + <p>Own Id: OTP-6246</p> + </item> + <item> + <p>The undocumented functions inet:getiflist/0,1 + inet:ifget/2,3 and inet:getif/1 were completely broken on + Windows. That has been fixed.</p> + <p>Own Id: OTP-6255</p> + </item> + <item> + <p>Behavior in case of disappeared nodes when using the + dist_auto_connect once got changed in R11B-1. The + timeouts regarding normal distributed operations is now + reverted to the old (pre R11B-1).</p> + <p>Own Id: OTP-6258 Aux Id: OTP-6200, seq10449 </p> + </item> + <item> + <p>The bsl and bsr operators could cause the emulator to + crash if given invalid arguments. (Thanks to datacompboy + and Per Gustafsson.)</p> + <p>Own Id: OTP-6259</p> + </item> + <item> + <p>driver_cancel_timer() could under certain circumstances + fail to cancel the timer on the runtime system with SMP + support.</p> + <p>Own Id: OTP-6261</p> + </item> + <item> + <p>A call to erlang:system_info(info) could deadlock the + runtime system with SMP support.</p> + <p>Own Id: OTP-6268</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Exit signals are now truly asynchronous in the runtime + system with SMP support. This simplifies locking in bifs + a lot, and makes process termination cheaper.</p> + <p>Own Id: OTP-6160</p> + </item> + <item> + <p>When tracing on the runtime system with SMP support it + can be difficult to know when a trace has been delivered + to the tracer. A new built in function + <c><![CDATA[erlang:trace_delivered/1]]></c> has been introduced in + order to make it easier to know when the trace has been + delivered. See the erlang(3) man page for more + information.</p> + <p>Own Id: OTP-6205 Aux Id: OTP-6269 </p> + </item> + <item> + <p>Kernel poll support can now be combined with SMP support. + Currently the following kernel poll versions exist: + <c><![CDATA[/dev/poll]]></c>, <c><![CDATA[epoll]]></c>, and <c><![CDATA[kqueue]]></c>. Linux + <c><![CDATA[kpoll]]></c> has been replaced with <c><![CDATA[epoll]]></c>. Some + time in the future there will also be a kernel poll + version using Solaris event ports.</p> + <p>The "check io" implementation for unix has been + completely rewritten. The current kernel poll + implementation reduce the amount of system calls needed + compared to the old kernel poll implementation.</p> + <p>When <c><![CDATA[epoll]]></c> or <c><![CDATA[kqueue]]></c> is used either + <c><![CDATA[poll]]></c> or <c><![CDATA[select]]></c> is used as fallback. + Previously only <c><![CDATA[poll]]></c> could be used as fallback. + Since <c><![CDATA[select]]></c> now can be used as fallback, kernel + poll support is now also available on newer MacOSX. Note + however, when <c><![CDATA[select]]></c> is used as fallback, the + maximum number of file descriptors is limited to + <c><![CDATA[FD_SETSIZE]]></c>. </p> + <p>Kernel poll support is now enabled by default if + <c><![CDATA[/dev/poll]]></c>, <c><![CDATA[epoll]]></c>, or <c><![CDATA[kqueue]]></c> is found + when building OTP, i.e. you do not have to pass the + <c><![CDATA[--enable-kernel-poll]]></c> argument to <c><![CDATA[configure]]></c>. + As before, kernel poll is disabled by default in the + runtime system. In order to enable it, pass the + <c><![CDATA[+Ktrue]]></c> command line argument to <c><![CDATA[erl]]></c>.</p> + <p>Note: <c><![CDATA[configure]]></c> will refuse to enable kernel poll + support on FreeBSD since <c><![CDATA[kqueue]]></c> have problems with + (at least) pipes on all version of FreeBSD that we have + tested.</p> + <p>Own Id: OTP-6222 Aux Id: seq10380 </p> + </item> + <item> + <p>The <c><![CDATA[erl_ddll]]></c> module and the code in the emulator + have been completely rewritten; several bugs were fixed.</p> + <p>Own Id: OTP-6234</p> + </item> + <item> + <p>The SMP emulator now avoids locking for the following + operations (thus making them as fast as in the UP + emulator): <c><![CDATA[atom_to_list/1]]></c>, atom comparison, atom + hashing, <c><![CDATA[erlang:apply/3]]></c>.</p> + <p>Own Id: OTP-6252</p> + </item> + <item> + <p>There are new BIFs <c><![CDATA[erlang:spawn_monitor/1,3]]></c>, + and the new option <c><![CDATA[monitor]]></c> for + <c><![CDATA[spawn_opt/2,3,4,5]]></c>.</p> + <p>The <c><![CDATA[observer_backend]]></c> module has been updated to + handle the new BIFs.</p> + <p>Own Id: OTP-6281</p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.1.1</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>There is now an option read_packets for UDP sockets that + sets the maximum number of UDP packets that will be read + for each invocation of the socket driver.</p> + <p>Own Id: OTP-6249 Aux Id: seq10452 </p> + </item> + </list> + </section> + </section> + + <section> + <title>Erts 5.5.1</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Complex pattern matching of strings would fail in the 64 + bits emulator because of a bug in the loader. (Thanks to + Igor Goryachev.)</p> + <p>Own Id: OTP-6142</p> + </item> + <item> + <p><c><![CDATA[-134217728 div 134217728]]></c> and <c><![CDATA[-134217728 rem 134217728]]></c> would be calculated incorrectly. + <c><![CDATA[abs(-2147483648)]]></c> could in unlucky circumstances + cause a heap overflow, as could size(Binary) when size of + the binary was larger than 128Mb.</p> + <p>Own Id: OTP-6154</p> + </item> + <item> + <p>erlang:display/1 displayed erroneous values for negative + integers.</p> + <p>Big integers (both positive and negative) were previously + displayed in hexadecimal form while small integers were + displayed in decimal form. All integers are now displayed + in decimal form.</p> + <p>NOTE: erlang:display/1 should only be used for debugging.</p> + <p>Own Id: OTP-6156</p> + </item> + <item> + <p>A call to erlang:trace/3 with erroneous flags caused the + SMP emulator to deadlock instead of exiting the calling + process with badarg.</p> + <p>Own Id: OTP-6175</p> + </item> + <item> + <p>A bug causing the emulator to hang when exiting a process + that is exception traced has been fixed.</p> + <p>Own Id: OTP-6180</p> + </item> + <item> + <p>ets:rename/1 could deadlock, or crash the SMP emulator + when the table wasn't a named table.</p> + <p>ets:next/2, and ets:prev/2 could return erroneous results + on the SMP emulator.</p> + <p>Own Id: OTP-6198 Aux Id: seq10392, seq10415 </p> + </item> + <item> + <p>A memory allocation bug could cause the SMP emulator to + crash when a process had executed a <c><![CDATA[receive after]]></c> + with a larger timeout than 10 minutes.</p> + <p>Own Id: OTP-6199</p> + </item> + <item> + <p>The runtime system with SMP support did not slowly adjust + it's view of time when the system time suddenly changed.</p> + <p>Timeouts could sometimes timeout too early on the runtime + system with SMP support.</p> + <p>Own Id: OTP-6202</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The smp runtime system now automatically detects the + number of logical processors on MacOSX (darwin) and + OpenBSD.</p> + <p>The smp runtime system is now built by default on MacOSX + (darwin) on x86.</p> + <p>Own Id: OTP-6119</p> + </item> + <item> + <p>The <c><![CDATA[-smp]]></c> command line argument now take the + following options: <c><![CDATA[enable]]></c>, <c><![CDATA[auto]]></c>, or + <c><![CDATA[disable]]></c>.</p> + <p>Especially the <c><![CDATA[-smpauto]]></c> argument is useful since + it starts the Erlang runtime system with SMP support if + it is available and more than one logical processor are + detected; otherwise, it starts the Erlang runtime system + without SMP support. For more information see the + <c><![CDATA[erl(1)]]></c> man page.</p> + <p>Own Id: OTP-6126</p> + </item> + <item> + <p>Increased the reduction cost for sending messages in the + SMP emulator so it behaves more like the non-SMP + emulator.</p> + <p>Own Id: OTP-6196</p> + </item> + <item> + <p>A port running a dynamically linked-in driver that exits + due to the driver being unloaded now exits with exit + reason <c><![CDATA[driver_unloaded]]></c>. Previously the port exited + with exit reason <c><![CDATA[-1]]></c>.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-6204</p> + </item> + <item> + <p>Changed name of the <c><![CDATA[erlang:system_info/1]]></c> argument + <c><![CDATA[scheduler]]></c> to <c><![CDATA[scheduler_id]]></c>. This since the + <c><![CDATA[scheduler]]></c> argument so easily could be mixed up + with the <c><![CDATA[schedulers]]></c> argument (both returning + integers).</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-6208</p> + </item> + <item> + <p>The changes below were made by Mikael Pettersson, HiPE.</p> + <p>HiPE runtime system:</p> + <p>Reduce overheads in the HiPE runtime system's BIF glue + code.</p> + <p>Fix bug when exceptions are thrown from BEAM to HiPE.</p> + <p>Support SPARC on Linux.</p> + <p>Support x86 on FreeBSD.</p> + <p>Floating-point exceptions:</p> + <p>Reduce overheads in checking results of floating-point + operations.</p> + <p>Minor bug fix in SSE2 floating-point exception + handling.</p> + <p>Support SSE2 floating-point exceptions on 32-bit x86 + machines.</p> + <p>Make FP exceptions work in the SMP runtime system on + FreeBSD/x86.</p> + <p>Support floating-point exceptions on SPARCs running + Linux.</p> + <p>Runtime system:</p> + <p>Minor scheduler optimisation in the non-SMP runtime + system.</p> + <p>Substantial reduction of I/O thread overheads in the + SMP runtime system if the separate timer thread is used. + (In R11B-1, the separate timer thread is not used.)</p> + <p>Own Id: OTP-6211</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.5</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Previously <c><![CDATA[unlink/1]]></c> and <c><![CDATA[erlang:demonitor/2]]></c> + behaved completely asynchronous. This had one undesirable + effect, though. You could never know when you were + guaranteed <em>not</em> to be affected by a link that you + had unlinked or a monitor that you had demonitored.</p> + <p>The new behavior of <c><![CDATA[unlink/1]]></c> and + <c><![CDATA[erlang:demonitor/2]]></c> can be viewed as two operations + performed atomically. Asynchronously send an unlink + signal or a demonitor signal, and ignore any future + results of the link or monitor.</p> + <p><em>NOTE</em>: This change can cause some obscure code + to fail which previously did not. For example, the + following code might hang:</p> + <code type="none"><![CDATA[ + Mon = erlang:monitor(process, Pid), +\011 %% ... +\011 exit(Pid, bang), + erlang:demonitor(Mon), +\011 receive +\011 {'DOWN', Mon , process, Pid, _} -> ok +\011 %% We were previously guaranteed to get a down message +\011 %% (since we exited the process ourself), so we could +\011 %% in this case leave out: +\011 %% after 0 -> ok +\011 end, + ]]></code> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-5772</p> + </item> + <item> + <p>Two bugs fixed: If the environment variable <c><![CDATA[ERL_FLAGS]]></c> + was set, its contents would be appended to the end of the + command line even if the command line had an <c><![CDATA[-extra]]></c> + options. Changed to place the options from <c><![CDATA[ERL_FLAGS]]></c> + just before <c><![CDATA[-extra]]></c>. Also, the <c><![CDATA[-smp]]></c> and + <c><![CDATA[-hybrid]]></c> flags no longer have any effect if placed + after <c><![CDATA[-extra]]></c>.</p> + <p>Own Id: OTP-6054</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The documentation for writing drivers in the ERTS User's + Guide has been expanded and updated.</p> + <p>Own Id: OTP-5192</p> + </item> + <item> + <p>The <c><![CDATA[andalso]]></c> and <c><![CDATA[orelse]]></c> operators are + now allowed to be used in guards. That also applies to + match specifications.</p> + <p>Own Id: OTP-5894 Aux Id: OTP-5149 </p> + </item> + <item> + <p>There is a new trace match spec function + <c><![CDATA[{exception_trace}]]></c> and a corresponding trace + message <c><![CDATA[exception_from]]></c> that can be used to trace + on any exit from a function, both normal function return + and exception return. See the documentation for + details.</p> + <p>The <c><![CDATA[return_to]]></c> trace message is now also + generated when the execution returns to a function due to + catching an exception.</p> + <p>Own Id: OTP-5956</p> + </item> + <item> + <p>Erlang runtime system with SMP (symmetric multi processing) + support.</p> + <p>The runtime system with SMP support is in this release + focused on stability and there are a number of steps + with optimizations to follow before it will take + full advantage of multi processor systems. + The released system is however truly multi threaded + and you will notice increased performance + for many applications already. + We recommend that you evaluate your application on + the SMP version of the runtime system and wait for some + more optimizations before you use it in a real product. + You will then discover if there are any problems in + your application that needs to be fixed in order for + it to work properly in a multi threaded environment. + More optimized versions of the runtime system + with SMP support will be included in the R11B + maintenance releases.</p> + <p>The SMP enabled runtime system will be started if + the <c><![CDATA[-smp]]></c> command line argument is passed to + the <c><![CDATA[erl]]></c> command. In order to make use of more than + one processor core, multiple scheduler threads are used. By + default, the number of scheduler threads will equal + the number of processor cores. The number of scheduler + threads can be set with the <c><![CDATA[+S]]></c> command line argument. + For more information see the <c><![CDATA[erl(1)]]></c> man page.</p> + <p>A runtime system with SMP support is by default built on + the following platforms if posix threads, and a gcc + compiler of at least version 2.95 is found:</p> + <list type="bulleted"> + <item> + <p>Linux with at least kernel version 2.6 and the Native + POSIX Thread Library on x86, x86_64, and 32-bits + PowerPC.</p> + </item> + <item> + <p>Solaris of at least version 8 on 32-bits SPARC-V9.</p> + </item> + <item> + <p>MacOSX of at least version 10.4 (Darwin 8.0) on + 32-bits PowerPC.</p> + </item> + </list> + <p>The runtime system with SMP support is known <em>not</em> + to build on:</p> + <list type="bulleted"> + <item> + <p>Windows.</p> + </item> + <item> + <p>Linux with kernel versions less than 2.4, or without + the Native POSIX Thread Library.</p> + </item> + <item> + <p>Other hardware platforms than x86, x86_64, 32-bits + SPARC-V9 and 32-bits PowerPC.</p> + </item> + </list> + <p>Windows will be supported in a future release.</p> + <p>The runtime system with SMP support might build on other + operating systems in combination with supported hardware. + In order to force a build of a runtime system with SMP + support, pass the <c><![CDATA[--enable-smp-support]]></c> command line + argument to configure. Note, however, that it is not enough + that it builds. The underlying thread library and operating + system has to provide SMP support as well. If the thread + library does not distribute scheduler threads over multiple + processor cores then the runtime system will only seemingly + provide SMP support. If the runtime system is not built by + default on a specific platform, we have <em>not</em> tested + it on that platform.</p> + <p><em>NOTE</em>: The design of SMP support for drivers is + ongoing. There will probably be incompatible driver + changes (only affecting drivers run on the runtime system + with SMP support) released as patches for R11B.</p> + <p><em>Potential incompatibility</em>: Previously, specific + driver call-backs were always called from the same thread. + This is <em>not</em> true in the runtime system with SMP + support. Calls to call-backs will be made from different + threads, e.g., two consecutive calls to exactly the same + call-back can be made from two different threads. This + will in <em>most</em> cases not be a problem. All calls + to call-backs are synchronized, i.e., only one call-back + will be called at a time.</p> + <p>In the future the default behavior will <em>probably</em> + be the following: Calls to call-backs will, as now, be + made from different threads. Calls to call-backs in the + same driver <em>instance</em> will be synchronized. It + will probably be possible to configure so that all calls + to call-backs in all driver instances of a specific + driver type will be synchronized. It may be possible to + configure so that all calls to call-backs of a driver + instance or a of a specific driver type will be made from + the same thread.</p> + <p>Parallelism in the Erlang code executed is a necessity + for the Erlang runtime system to be able to take + advantage of multi-core or multi-processor hardware. + There need to be at least as many Erlang processes + runnable as processor cores for the Erlang runtime system + to be able to take advantage of all processor cores.</p> + <p>An Erlang runtime system with SMP support with only one + Erlang process runnable all the time will almost always be + slower than the same Erlang runtime system without SMP + support. This is due to thread synchronization overhead.</p> + <p>Known major bottleneck in the Erlang runtime system:</p> + <list type="bulleted"> + <item> + <p>Currently the I/O system uses one "big lock", i.e. only + one thread can do I/O at a time (with the exception of + async threads and threads created by users own linked-in + drivers). This is high on the list of things to + optimize. Note, code that does not do I/O can be executed + at the same time as one thread does I/O.</p> + </item> + </list> + <p>Some pitfalls which might cause Erlang programs that work on + the non-SMP runtime system to fail on the SMP runtime + system:</p> + <list type="bulleted"> + <item> + <p>A newly spawned process will often begin executing + immediately. Code that expects that the parent process + will be able to execute for a while before the child + process begins executing is likely to fail.</p> + </item> + <item> + <p>High priority processes could previously provide + mutual exclusion (bad programming style) by preventing + normal and low priority processes from being run. High + priority processes cannot be used this way to provide + mutual exclusion.</p> + </item> + <item> + <p><c><![CDATA[erlang:yield()]]></c> could be used to provide some + kind of temporary mutual exclusion (also bad programming + style). <c><![CDATA[erlang:yield()]]></c> cannot be used to provide + any kind of mutual exclusion.</p> + </item> + <item> + <p>Obscure pitfall, only if a process being traced also + sends normal messages to the tracer:<br></br> + The order between trace messages and normal + messages is undefined. I.e. the order between normal + messages sent from a tracee to a tracer and the trace + messages generated from the same tracee to the same + tracer is undefined. The internal order of normal + messages and the internal order of trace messages will, + of course, be preserved as before.</p> + </item> + </list> + <p>The kernel poll feature is currently not supported by + the runtime system with SMP support. It will probably be + supported in a future release.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-6006 Aux Id: OTP-6095 </p> + </item> + <item> + <p>Linked-in driver modifications.</p> + <list type="bulleted"> + <item> + <p>Linked-in drivers must be recompiled.</p> + </item> + <item> + <p>The <c><![CDATA[refc]]></c> field in the <c><![CDATA[ErlDrvBinary]]></c> type + has been removed. The reference count can be accessed + via API functions. For more information see + the <c><![CDATA[erl_driver(1)]]></c> man page.</p> + </item> + </list> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-6095 Aux Id: OTP-6006 </p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.13</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Large files (more than 2 GBytes) are now handled on + Solaris 8.</p> + <p>Own Id: OTP-5849 Aux Id: seq10157 </p> + </item> + <item> + <p>A failing bit syntax construction could fail with the + PREVIOUS exception reason that had occurred in the process + (instead of with <c><![CDATA[badarg]]></c>).</p> + <p>Own Id: OTP-5911</p> + </item> + <item> + <p>When building OTP, the Kernel application was built in + both the primary and secondary bootstrap steps, which + would cause problems if OTP including its bootstrap is + checked into a version control system (such as CVS). + (Thanks to Sebastian Strollo.)</p> + <p>Own Id: OTP-5921</p> + </item> + <item> + <p><c><![CDATA[binary_to_term(<<131,109,255,255,255,255)]]></c> and + similar expressions used to crash the emulator instead of + causing a <c><![CDATA[badarg]]></c> exception. (Thanks to Matthias + Lang.)</p> + <p>Own Id: OTP-5933</p> + </item> + <item> + <p><c><![CDATA[erlang:hibernate/3]]></c> could sometimes crash the emulator + when no heap was needed.</p> + <p>Own Id: OTP-5940</p> + </item> + <item> + <p>Execution of match specs could under rare circumstances + cause the emulator to dump core.</p> + <p>Execution of match specs could cause memory leaks in the + hybrid emulator.</p> + <p>Own Id: OTP-5955</p> + </item> + <item> + <p>A bug in <c><![CDATA[erlang:trace_info/2]]></c> when getting info for a + function in a deleted module resulting in an emulator + crash, has been corrected.</p> + <p>Own Id: OTP-5957</p> + </item> + <item> + <p>Different (and old) <c><![CDATA[config.guess]]></c> files in the + ERTS and Erl_Interface applications would cause build + problems on the new Intel-based iMacs. + (Thanks to Sebastion Strollo.)</p> + <p>Own Id: OTP-5967</p> + </item> + <item> + <p>pthread header and library mismatch on Linux systems (at + least some SuSE and Debian) with both NPTL and + Linuxthreads libraries installed.</p> + <p>Own Id: OTP-5981</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The driver_set_timer did not change the previous timeout + if called a second time. Now it works as specified, + changing the timeout.</p> + <p>Own Id: OTP-5942</p> + </item> + <item> + <p>The undocumented <c><![CDATA[{packet,http}]]></c> option (for the + <c><![CDATA[gen_tcp]]></c> module) did not not work correctly when + there were multiple continuation lines. (Thanks to Per + Hedeland.)</p> + <p>Own Id: OTP-5945</p> + </item> + <item> + <p>The setuid_socket_wrap program was corrected to work for + C compilers that treat the <c><![CDATA[char]]></c> type as unsigned. + (Thanks to Magnus Henoch.)</p> + <p>Own Id: OTP-5946</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.12</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Fixed a minor build problem on Windows.</p> + <p>Own Id: OTP-5819 Aux Id: OTP-5382 OTP-5540 OTP-5577 </p> + </item> + <item> + <p>The <c><![CDATA[delay_send]]></c> option for <c><![CDATA[gen_tcp]]></c> was + broken on Windows.</p> + <p>Own Id: OTP-5822</p> + </item> + <item> + <p>If there were user-defined variables in the boot + script, and their values were not provided using the + <c><![CDATA[-boot_var]]></c> option, the emulator would refuse to + start with a confusing error message. Corrected to show a + clear, understandable message.</p> + <p>The <c><![CDATA[prim_file]]></c> module was modified to not depend + on the <c><![CDATA[lists]]></c> module, to make it possible to start + the emulator using a user-defined loader. (Thanks to + Martin Bjorklund.)</p> + <p>Own Id: OTP-5828 Aux Id: seq10151 </p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The HiPE compiler identifies more leaf functions, + giving slightly faster code.</p> + <p>Corrected problems in HiPE's coalescing register + allocating that would cause it to fail when compiling + very large functions (e.g. some of parse modules in the + Megaco application).</p> + <p>Own Id: OTP-5853</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.11</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Timers could sometimes timeout too early. This bug has + now been fixed.</p> + <p>Automatic cancellation of timers created by + <c><![CDATA[erlang:send_after(Time,pid(),Msg)]]></c> and + <c><![CDATA[erlang:start_timer(Time,pid(),Msg)]]></c> has been + introduced. Timers created with the receiver specified by a + pid, will automatically be cancelled when the receiver + exits. For more information see the <c><![CDATA[erlang(3)]]></c> man + page.</p> + <p>In order to be able to maintain a larger amount of timers + without increasing the maintenance cost, the internal + timer wheel and bif timer table have been enlarged.</p> + <p>Also a number of minor bif timer optimizations have been + implemented.</p> + <p>Own Id: OTP-5795 Aux Id: OTP-5090, seq8913, seq10139, + OTP-5782 </p> + </item> + <item> + <p><c><![CDATA[erlang:monitor(process,Pid)]]></c> hanged if <c><![CDATA[Pid]]></c> + referred to a process on a non-existing node with the same + nodename as the nodename of node on which the call was made. + This bug has now been fixed.</p> + <p>Own Id: OTP-5827</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>By setting Unix environment variables, the priority for + the emulator can be lowered when it is writing crash + dumps and the time allowed for finishing writing a crash + dump can be set to a certain number of seconds. See the + documentation for <c><![CDATA[erl]]></c> in the ERTS application. + (Also, a few other previously undocumented environment + variables are now documented.)</p> + <p>Own Id: OTP-5818</p> + </item> + <item> + <p>Documentation improvements:</p> + <p>- documentation for <c><![CDATA[erlang:link/1]]></c> corrected</p> + <p>- command line flag <c><![CDATA[-code_path_cache]]></c> added</p> + <p>- <c><![CDATA[erl]]></c> command line flags clarifications</p> + <p>- <c><![CDATA[net_kernel(3)]]></c> clarifications</p> + <p>Own Id: OTP-5847</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.10</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>-D_GNU_SOURCE is now always passed on the compile command + line on linux. This in order to ensure that all included + system headers see _GNU_SOURCE defined.</p> + <p>_GNU_SOURCE is now also defined on linux in configure + when looking for features.</p> + <p>Some minor (harmless) configure bugs were also fixed.</p> + <p>Own Id: OTP-5749</p> + </item> + <item> + <p>Some compiler warnings and Dialyzer warnings were + eliminated in the Tools application.</p> + <p>When tracing to a port (which <c><![CDATA[fprof]]></c> does), + there could be fake schedule out/schedule in messages + sent for a process that had exited.</p> + <p>Own Id: OTP-5757</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The BIFs <c><![CDATA[iolist_size/1]]></c> and <c><![CDATA[iolist_to_binary/1]]></c> + has been added.</p> + <p>The BIF <c><![CDATA[list_to_existing_atom/1]]></c> has been added.</p> + <p>Minor bug fix: The exception reason could be changed + to <c><![CDATA[error]]></c> inside nested try/catch constructs if the + <c><![CDATA[erlang:raise/3]]></c> BIF was called with an empty + stacktrace. (Calling <c><![CDATA[erlang:raise/3]]></c> with an empty + stacktrace is NOT recommended.)</p> + <p>Minor bugfix: On Windows, <c><![CDATA[file:open/2]]></c> will now + return the documented error reason <c><![CDATA[{error,eisdir}]]></c> + if the filename refers to a directory (it used to return + <c><![CDATA[{error,eacces}]]></c>).</p> + <p>The message in the documentation for + <c><![CDATA[erlang:system_monitor/2]]></c>, description of + <c><![CDATA[busy_dist_port]]></c>, was corrected.</p> + <p>Own Id: OTP-5709 Aux Id: seq10100 </p> + </item> + <item> + <p>The previously undocumented and UNSUPPORTED <c><![CDATA[zlib]]></c> + module has been updated in an incompatible way and many + bugs have been corrected. It is now also documented.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-5715</p> + </item> + <item> + <p>New socket options <c><![CDATA[priority]]></c> and <c><![CDATA[tos]]></c> for + platforms that support them (currently only Linux).</p> + <p>Own Id: OTP-5756</p> + </item> + <item> + <p>Only the emulator is now linked with termcap library in + order to decrease library dependencies for other otp + programs.</p> + <p>Own Id: OTP-5758</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.9.2</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The native resolver has gotten an control API for + extended debugging and soft restart. It is: + <c><![CDATA[inet_gethost_native:control(Control)]]></c><br></br><c><![CDATA[Control = {debug_level,Level} | soft_restart]]></c><br></br><c><![CDATA[Level = integer() in the range 0-4]]></c>.</p> + <p>Own Id: OTP-5751 Aux Id: EABln25013 </p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.9.1</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>On VxWorks, epmd did not handle file descriptors with + higher numbers than 63. Also, if epmd should get a file + descriptor with a number >= FD_SETSIZE, it will close a + the file descriptor and write a message to the log + (instead of mysteriously fail); the Erlang node that + tried to register will fail with a duplicate_name error + (unfortunately, epmd has no way to indicate to the Erlang + node why the register attempt failed).</p> + <p>Own Id: OTP-5716 Aux Id: seq10070 </p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.9</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Timezone data is now initialized better. (was a problem + at least on NetBSD 2.0.2) Thanks to Rich Neswold.</p> + <p>Own Id: OTP-5621</p> + </item> + <item> + <p>The hybrid-heap emulator ('erl -hybrid') is much more + stable. We have corrected all known bugs that caused it + to dump core while running our test suites.</p> + <p>Own Id: OTP-5634</p> + </item> + <item> + <p>Fixed rare memory leaks in <c><![CDATA[erlang:demonitor/1]]></c> when + distributed monitors were removed.</p> + <p>Own Id: OTP-5692</p> + </item> + <item> + <p>Processes were sometimes unnecessarily garbage collected + when terminating. These unnecessary garbage collections + have now been eliminated.</p> + <p>Own Id: OTP-5693</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The <c><![CDATA[c:i/0]]></c> function will now run in a paged mode if + there are more than 100 processes in the system. (Thanks + to Ulf Wiger.)</p> + <p><c><![CDATA[erlang:system_info(process_count)]]></c> has + been optimized and does now return exactly the same value + as <c><![CDATA[length(processes())]]></c>. Previously + <c><![CDATA[erlang:system_info(process_count)]]></c> did not include + exiting processes which are included in + <c><![CDATA[length(processes())]]></c>.</p> + <p>The <c><![CDATA[+P]]></c> flag for <c><![CDATA[erl]]></c>, which sets the maximum + number of processes allowed to exist at the same, no longer + accepts values higher than 134217727. (You will still + probably run out of memory before you'll be able to reach + that limit.)</p> + <p>Own Id: OTP-5645 Aux Id: seq9984 </p> + </item> + <item> + <p>The term-building driver functions + <c><![CDATA[driver_output_term()]]></c> and <c><![CDATA[driver_send_term()]]></c> + have been updated:</p> + <p>The ERL_DRV_FLOAT type has been added.</p> + <p>For the ERL_DRV_BINARY type, the length and offset are + now validated against the length of the driver binary.</p> + <p>The ERL_DRV_PID type is now implemented (it was + documented, but not implemented).</p> + <p>Own Id: OTP-5674</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.8</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p><c><![CDATA[ets:delete/1]]></c> now allows other Erlang process to run + when a large table is being deleted.</p> + <p>Own Id: OTP-5572</p> + </item> + <item> + <p>A bug regarding tcp sockets which results in hanging + <c><![CDATA[gen_tcp:send/2]]></c> has been corrected. To encounter + this bug you needed one process that read from a socket, + one that wrote more date than the reader read out so the + sender got suspended, and then the reader closed the + socket. (Reported and diagnosed by Alexey Shchepin.)</p> + <p>Corrected a bug in the (undocumented and unsupported) + option <c><![CDATA[{packet,http}]]></c> for <c><![CDATA[gen_tcp.]]></c> + (Thanks to Claes Wikstrom and Luke Gorrie.)</p> + <p>Updated the documentation regarding the second argument to + <c><![CDATA[gen_tcp:recv/2]]></c>, the <c><![CDATA[Length]]></c> to receive.</p> + <p>Own Id: OTP-5582 Aux Id: seq9839 </p> + </item> + <item> + <p>Erlang/OTP will now build on Mac OS X 10.4 "Tiger" (the + problem was that 10.4 has a partially implemented poll() + function that can't handle devices). Also, on Mac OS X + 10.3 "Panther", Erlang/OTP will now use select() instead + of poll() (because poll() on Mac OS X 10.3 is implemented + using select()).</p> + <p>Own Id: OTP-5595</p> + </item> + <item> + <p>A bug in the file driver when opening a file in + compressed mode, and the returned allocated pointer from + the compressing library was in very high memory (>= 2GB), + causing e.g. <c><![CDATA[file:read/2]]></c> to return + <c><![CDATA[{error,ebadf}]]></c>, has been corrected.</p> + <p>Own Id: OTP-5618</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The new fun <c><![CDATA[M:F/A]]></c> construct creates a fun that + refers to the latest version of <c><![CDATA[M:F/A.]]></c> This syntax is + meant to replace tuple funs <c><![CDATA[{M,F}]]></c> which have many + problems.</p> + <p>The new type test <c><![CDATA[is_function(Fun,A)]]></c> (which may be + used in guards) test whether <c><![CDATA[Fun]]></c> is a fun that can be + applied with <c><![CDATA[A]]></c> arguments. (Currently, <c><![CDATA[Fun]]></c> + can also be a tuple fun.)</p> + <p>Own Id: OTP-5584</p> + </item> + <item> + <p>In the HiPE application, there's a new experimental + register allocator (optimistic coalescing), and the + linear scan register allocator is now also available on + ppc. Plus lots of cleanups.</p> + <p>Minor hybrid heap corrections.</p> + <p>The maximum size of a heap used to be artificially + limited so that the size of a heap would fit in 28 bits; + that limitation could cause the emulator to terminate in + a garbage collection even if there still was available + memory. Now the largest heap size for a 32 bit CPU is + 1,699,221,830 bytes. (Thanks to Jesper Wilhelmsson.)</p> + <p>Also removed the undocumented <c><![CDATA[+H]]></c> emulator option.</p> + <p>Own Id: OTP-5596</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.7</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p><c><![CDATA[to_erl]]></c> could close unexpectedly on Linux systems. + Also, output from the emulator could be lost. Corrected.</p> + <p>Own Id: OTP-5561</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The <c><![CDATA[cpu_timestamp]]></c> option for <c><![CDATA[erlang:trace/3]]></c> + is now also supported on Linux.</p> + <p>Own Id: OTP-5532 Aux Id: seq9813 </p> + </item> + <item> + <p>The last known <c><![CDATA[werl]]></c> window size/position is now saved + correctly when <c><![CDATA[werl]]></c> is stopped with the window + minimized. A problem with the placement not being saved if + the emulator is halted or stopped from the JCL menu has also + been fixed.</p> + <p>Own Id: OTP-5544 Aux Id: OTP-5522 </p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.6</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Some math libraries do not always throw floating-point + exceptions on errors. In order to be able to use these + libraries, floating-point errors are now more thoroughly + checked.</p> + <p>Misc floating-point fixes for Linux and MacOSX.</p> + <p>Own Id: OTP-5467</p> + </item> + <item> + <p>An internal buffer was sometimes not cleared which caused + garbage to appear in error messages sent to the error + logger.</p> + <p><c><![CDATA[errno]]></c> was sometimes clobbered which caused erroneous + error reports about <c><![CDATA[poll()]]></c> errors.</p> + <p>Only emulators on unix platforms were affected by these + bugs.</p> + <p>Own Id: OTP-5492</p> + </item> + <item> + <p>The ethread library now works on OpenBSD.</p> + <p>Own Id: OTP-5515</p> + </item> + <item> + <p>Corrected a bug in the (undocumented and unsupported) + option <c><![CDATA[{packet,http}]]></c> for <c><![CDATA[gen_tcp]]></c>. + (Thanks to Claes Wikstrom and Luke Gorrie.)</p> + <p>Own Id: OTP-5519</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p><c><![CDATA[binary_to_term/1]]></c> could cause the emulator to crash + when given invalid pids or funs.</p> + <p>Own Id: OTP-5484 Aux Id: seq9801 </p> + </item> + <item> + <p>Some more stability problems were fixed in the + hybrid-heap emulator.</p> + <p>Own Id: OTP-5489</p> + </item> + <item> + <p>After <c><![CDATA[werl]]></c> was closed with the window minimized, it + was not possible to restart <c><![CDATA[werl]]></c> with an open + window. A temporary solution has so far been implemented + that restores the initial window settings every time + <c><![CDATA[werl]]></c> is started.</p> + <p>Own Id: OTP-5522</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.5</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>If a process had node links (created by + <c><![CDATA[monitor_node/2]]></c>), executing + <c><![CDATA[process_info(Pid,memory)]]></c> for that process would + crash the emulator.</p> + <p>Own Id: OTP-5420</p> + </item> + <item> + <p>Minor corrections to the help text printed by <c><![CDATA[erlc -help]]></c>. The documentation for <c><![CDATA[erlc]]></c> was also + slightly updated.</p> + <p>Own Id: OTP-5428</p> + </item> + <item> + <p>32-bit words were used for offsets in the garbage + collector. This caused the emulator to crash on 64-bit + machines when heaps were moved more than 4 GB during + garbage collection.</p> + <p>Own Id: OTP-5430</p> + </item> + <item> + <p><c><![CDATA[is_boolean(42.5)]]></c> failed to load if optimization was + explicitly turned off.</p> + <p>Own Id: OTP-5448</p> + </item> + <item> + <p>If there was a call to <c><![CDATA[Module:foo/X]]></c> from any loaded + module, the returned by <c><![CDATA[M:module_info(exports)]]></c> would + always include <c><![CDATA[{foo,X}]]></c> (even though + <c><![CDATA[Module:foo/X]]></c> if was not defined).</p> + <p>Own Id: OTP-5450 Aux Id: seq9722 </p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The <c><![CDATA[c]]></c> option for the <c><![CDATA[+B]]></c> flag has been + introduced which makes it possible to use Ctrl-C + (Ctrl-Break on Windows) to interrupt the shell process + rather than to invoke the emulator break handler. All new + <c><![CDATA[+B]]></c> options are also supported on Windows + (<c><![CDATA[werl]]></c>) as of now. Furthermore, Ctrl-C on Windows has + now been reserved for copying text (what Ctrl-Ins was used + for previously). Ctrl-Break should be used for break + handling. Lastly, the documentation of the system flags has + been updated.</p> + <p>Own Id: OTP-5388</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.4</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The function <c><![CDATA[erlang:float/1]]></c> can now be used in + match specifications and is recognized by + <c><![CDATA[dbg:fun2ms/1]]></c> and <c><![CDATA[ets:fun2ms/1]]></c>. This + addition is part of the work to "harmonize" match + specification guards with Erlang guards.</p> + <p>Own Id: OTP-5297 Aux Id: OTP-4927 </p> + </item> + <item> + <p>The <c><![CDATA[register/2]]></c> BIF would return <c><![CDATA[true]]></c> even if + the second argument was not a pid for living process. + Corrected to cause an exception.</p> + <p>Own Id: OTP-5324 Aux Id: seq9698 </p> + </item> + <item> + <p>In the 'bag' type of ets tables, elements having the same + key were supposed to be order in insertion order. The + would be wrong if a rehash occurred.</p> + <p>Own Id: OTP-5340 Aux Id: seq9704 </p> + </item> + <item> + <p>Linked in drivers in the Crypto and Asn1 applications + are now compiled with the <c><![CDATA[-D_THREAD_SAFE]]></c> and + <c><![CDATA[-D_REENTRANT]]></c> switches on unix when the emulator has + thread support enabled.</p> + <p>Linked in drivers on MacOSX are not compiled with the + undocumented <c><![CDATA[-lbundle1.o]]></c> switch anymore. Thanks to + Sean Hinde who sent us a patch.</p> + <p>Linked in driver in Crypto, and port programs in SSL, now + compiles on OSF1.</p> + <p>Minor makefile improvements in Runtime_Tools.</p> + <p>Own Id: OTP-5346</p> + </item> + <item> + <p>Fixed a bug in the hybrid heap in distributed send + operations.</p> + <p>Own Id: OTP-5361</p> + </item> + <item> + <p>A BIF <c><![CDATA[erlang:raise/3]]></c> has been added. See the manual + for details. It is intended for internal system programming + only, advanced error handling.</p> + <p>Own Id: OTP-5376 Aux Id: OTP-5257 </p> + </item> + <item> + <p>Mikael Pettersson (HiPE) corrected a few bugs in the + emulator that caused problems when compiled with the + experimental gcc-4.0.0.</p> + <p>Own Id: OTP-5386</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Minor update of the internal documentation of + the <c><![CDATA[epmd]]></c> protocol.</p> + <p>The listen port of <c><![CDATA[epmd]]></c> has now been registered at + IANA: + <url href="http://www.iana.org/assignments/port-numbers">http://www.iana.org/assignments/port-numbers</url>.</p> + <p>Own Id: OTP-5234</p> + </item> + <item> + <p><c><![CDATA[run_erl.c]]></c> now works on Mac OS X and FreeBSD.</p> + <p>Own Id: OTP-5384</p> + </item> + <item> + <p>A few bugs were corrected in the HiPE application.</p> + <p>Own Id: OTP-5385</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.3</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Font and color preferences for <c><![CDATA[werl.exe]]></c> now can be + saved even after the first time you run <c><![CDATA[werl.exe]]></c>. + The window position and size is also saved. Patch from + James Hague who did all the hard work.</p> + <p>Own Id: OTP-5250</p> + </item> + <item> + <p>OTP archive libraries, e.g. the <c><![CDATA[erl_interface]]></c> + library, on MacOSX could not be used without first + rerunning <c><![CDATA[ranlib]]></c> on them. This bug has now been + fixed.</p> + <p>Own Id: OTP-5274</p> + </item> + <item> + <p>Bugs in <c><![CDATA[erlang:hash/2]]></c> and <c><![CDATA[erlang:phash/2]]></c> on + 64-bit platforms have been fixed.</p> + <p>Own Id: OTP-5292</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Corrected a crash in the 64-bits emulator.</p> + <p>Corrected a problem in the hybrid heap emulator.</p> + <p>In the chapter about the abstract format in the ERTS User's + Guide, updated the last section about how the abstract + format is stored in BEAM files.</p> + <p>Own Id: OTP-5262</p> + </item> + <item> + <p>The maximum number of concurrent threads in the internal + ethread thread package has been limited to 2048.</p> + <p>Own Id: OTP-5280</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.2.1</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>If Erlang/OTP was installed in a short directory name, + such as <c><![CDATA[C:\\Program\\erl5.4.2]]></c>, the emulator would not + start.</p> + <p>Own Id: OTP-5254</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.2</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>If one used <c><![CDATA[select/3]]></c> and <c><![CDATA[select/1]]></c> on a + non-fixed ETS table and deleted objects simultaneously, + the emulator could crash. Note that the result of such + simultaneous operations on tables that are not in a fixed + state is still undefined, but the emulator crash is, + needless to say, fixed.</p> + <p>Own Id: OTP-5209 Aux Id: seq9198 </p> + </item> + <item> + <p>Arithmetic with big numbers could crash the emulator.</p> + <p>The HiPE native code compiler and run-time code in the + emulator has been updated. (Note: Native code is still + not supported.)</p> + <p>Eliminated a few bugs that could crash the hybrid emulator + (which is not supported).</p> + <p>Own Id: OTP-5233 Aux Id: seq9587 </p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.4.1</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The ethread library was unnecessarily rebuilt multiple + times during the build process, also a debug version of + the library was build during the install phase. These + unnecessary builds have now been removed. Note, the + content of the installed Erlang/OTP system is not + effected at all by this change.</p> + <p>Own Id: OTP-5203</p> + </item> + <item> + <p>The emulator could fail to clear the memory segment + cache. This could potentially cause memory allocation to + unnecessarily fail when memory usage was close to its + maximum. This bug has now been fixed.</p> + <p>Own Id: OTP-5211</p> + </item> + <item> + <p>std_alloc (std short for standard) was sometimes called + def_alloc (def short for default). std_alloc is now + everywhere referred to as std_alloc.</p> + <p>Own Id: OTP-5216</p> + </item> + <item> + <p>A documentation bug has been corrected in + the <c><![CDATA[erts_alloc(3)]]></c> documentation. It was stated that + some of the memory allocators present were by default + disabled. This is true for Erlang/OTP R9C, but is not true + for Erlang/OTP R10B. In R10B all memory allocators present + are enabled by default.</p> + <p>Own Id: OTP-5217</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The emulator now close all open files and sockets + immediately after receiving an USR1 signal. This causes + the emulator to unregister at <c><![CDATA[epmd]]></c> as early as + possible.</p> + <p>Own Id: OTP-5221 Aux Id: OTP-4985, seq9514 </p> + </item> + <item> + <p>Try/catch support in the emulator slightly updated.</p> + <p>Own Id: OTP-5229</p> + </item> + </list> + </section> + </section> +</chapter> + diff --git a/erts/doc/src/notes_history.xml b/erts/doc/src/notes_history.xml new file mode 100644 index 0000000000..cc3b938c86 --- /dev/null +++ b/erts/doc/src/notes_history.xml @@ -0,0 +1,503 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2006</year><year>2009</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>otp_appnotes</prepared> + <docno>nil</docno> + <date>nil</date> + <rev>nil</rev> + <file>notes_history.xml</file> + </header> + + <section> + <title>ERTS 5.4</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The BIF <c><![CDATA[is_record(Record,RecordTag)]]></c> has been added to + the run-time system. It checks that <c><![CDATA[Record]]></c> is a tuple + whose first element is the atom <c><![CDATA[RecordTag.]]></c> No check + is made of the size of the tuple (because the run-time + system doesn't know anything about records).</p> + <p>Note that normally the compiler translates calls to + <c><![CDATA[is_record/2]]></c> to code that also verify the size of the + tuple, in addition to verifying the first element. The + BIF version will be used <c><![CDATA[is_record/2]]></c> is applied or + if the second argument is not a literal atom (e.g. a + variable or another term type, in which case the BIF will + generate a <c><![CDATA[badarg]]></c> exception).</p> + <p>Own Id: OTP-4812</p> + </item> + <item> + <p>Guards of mach specifications are corrected to resemble + the semantics of guards in real code more closely. The + implementation now corresponds to the documentation in + ERTS User's Guide. The following things are corrected:</p> + <list type="bulleted"> + <item>Guard semantics was wrong when it came to logical + operators and exceptions. + <c><![CDATA[{'or',{'is_integer','$1'},{'or','$1','$1'}}]]></c> + evaluated to <c><![CDATA[true]]></c> with <c><![CDATA['$1']]></c> bound to an + integer.</item> + <item>Unary + and - was not implemented.</item> + <item>Calling operators as Bif's was not supported by + <c><![CDATA[ets/dbg:fun2ms]]></c> (<c><![CDATA[erlang:'or'(A,B)]]></c> etc).</item> + <item>Old typetests (like <c><![CDATA[integer(X)]]></c> instead of + <c><![CDATA[is_integer(X))]]></c> was not supported by + <c><![CDATA[ets/dbg:fun2ms]]></c>.</item> + <item>Semicolon (;) in guards was not supported by + <c><![CDATA[ets/dbg:fun2ms]]></c>.</item> + </list> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-4927</p> + </item> + <item> + <p>A potential initialization failure when using threads and + elib_malloc has been removed.</p> + <p>Own Id: OTP-5125</p> + </item> + <item> + <p>Several problems in the 64-bit emulator has been + corrected. For instance, the emulator could crash while + running the Debugger.</p> + <p>Own Id: OTP-5146</p> + </item> + <item> + <p>The match spec parse transform <c><![CDATA[ms_transform]]></c> no + longer accepts the <c><![CDATA[andalso]]></c> and <c><![CDATA[orelse]]></c> + constructs in guards for consistency with the standard + Erlang language. A future release of Erlang/OTP may allow + <c><![CDATA[andalso]]></c> and <c><![CDATA[orelse]]></c> in guards.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-5149</p> + </item> + <item> + <p>In rare circumstances in a process that has caught + exceptions and uses funs, the process would be killed + when changing code because the code server would think + that the process still held references to the funs.</p> + <p>Own Id: OTP-5153</p> + </item> + <item> + <p><c><![CDATA[erlang:system_monitor/2]]></c> no longer sends any + monitoring messages to the system monitor process from + itself. This behavior is more consistent with other trace + functionality.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-5183</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The documentation stated that <c><![CDATA[ets:safe_fixtable/2]]></c> + could return <c><![CDATA[true]]></c> or <c><![CDATA[false,]]></c> that was wrong, + it always returns <c><![CDATA[true]]></c>.</p> + <p>Own Id: OTP-4830</p> + </item> + <item> + <p>The unary '+' operator has been changed to throw an + <c><![CDATA[badarith]]></c> exception if its argument is not numeric (or + fail in a guard). It used its argument unchanged whatever + the type. Given the new meaning, unary '+' can now be + used to test whether a term is numeric.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-4928</p> + </item> + <item> + <p>Process identifiers and port identifiers have been + made more unique. Previously 18 bits were used as id in + the internal representation of process and port + identifiers. Now 28 bits are used.</p> + <p>The maximum limit on the number of concurrently existing + processes due to the representation of pids has been + increased to 268435456 processes. The same is true for + ports. This limit will at least on a 32-bit architecture be + impossible to reach due to memory shortage.</p> + <p><em>NOTE:</em> By default, the <c><![CDATA[ERTS]]></c>, and the + <c><![CDATA[erl_interface]]></c>, <c><![CDATA[ei]]></c>, and <c><![CDATA[jinterface]]></c> + libraries are now only guaranteed to be compatible with + other Erlang/OTP components from the same release. It is + possible to set each component in compatibility mode of + an earlier release, though. See the documentation for + respective component on how to set it in compatibility + mode.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-4968 Aux Id: OTP-4196 </p> + </item> + <item> + <p>A new internal thread library for the ERTS has been + added.</p> + <p>Own Id: OTP-5048</p> + </item> + <item> + <p>The system's performance could degrade severely if one + process held numerous links or monitors. The issue is + resolved.</p> + <p>Own Id: OTP-5079</p> + </item> + <item> + <p>A new function, <c><![CDATA[string:to_integer/1]]></c>, has been added.</p> + <p>Own Id: OTP-5081 Aux Id: OTP-5136 </p> + </item> + <item> + <p>A new function, <c><![CDATA[string:to_float/1]]></c>, has been added.</p> + <p>Own Id: OTP-5136 Aux Id: OTP-5081 </p> + </item> + <item> + <p>The exception code for calling a fun with wrong number of + arguments has been changed from simply <c><![CDATA[badarity]]></c> to + <c><![CDATA[{badarity,{Fun,Args}}]]></c>.</p> + <p>*** POTENTIAL INCOMPATIBILITY ***</p> + <p>Own Id: OTP-5139</p> + </item> + <item> + <p>The long-awaited <c><![CDATA[try]]></c>...<c><![CDATA[catch]]></c> construction + is included in this release. However, its use in + production code is not yet supported as there are several + known cases of legal code crashing the compiler. We plan + to release a patch to the compiler (including the + documentation) and at that time <c><![CDATA[try]]></c>...<c><![CDATA[catch]]></c> + will be supported.</p> + <p>Own Id: OTP-5150</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.3.6.6</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>A bug that caused an emulator crash when using system + monitor of long GC has been fixed.</p> + <p>Own Id: OTP-5123</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.3.6.5</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p><c><![CDATA[erlang:memory(ets)]]></c> and <c><![CDATA[c:memory(ets)]]></c> + sometimes reported erroneous values. This bug has now been + fixed.</p> + <p>Own Id: OTP-5115 Aux Id: seq9063 </p> + </item> + <item> + <p>There is now a packet size limit option for <c><![CDATA[gen_tcp]]></c> + sockets. See the manual for <c><![CDATA[inet:setopts/2]]></c>.</p> + <p>The ASN.1 BER packet decoding for <c><![CDATA[gen_tcp]]></c> sockets + can now decode indefinite length packets.</p> + <p>Own Id: OTP-5128</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Port index was unnecessarily incremented by port table + size when port table got full. This unnecessary increment + has now been removed.</p> + <p>Own Id: OTP-5119</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.3.6.3</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Resolved a build problem on Mac OS 10.3 ("Panther"). + Because of a conflict with the zlib sources included in + the Erlang run-time system and the zlib library included + in Panther, linking would fail.</p> + <p>Minor optimization on all Unix systems: caching the + system name returned from the uname() system call. + (Thanks to David N. Welton.)</p> + <p>Own Id: OTP-5069</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The ability to set system wide options for TCP sockets is + added through the kernel application variables + <c><![CDATA[inet_default_listen_options]]></c> and + <c><![CDATA[inet_default_connect_options]]></c>, see the <c><![CDATA[inet]]></c> + manual page for details.</p> + <p>Own Id: OTP-5080</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.3.6.2</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>A few portability enhancements for the R9C-1 Open Source + release: The installer for Windows can now be built with + NSIS 2.0 (as well as with the NSIS 2.0b3). The driver + header files updated to allowed drivers to be built which + the MinGW compiler on Windows. Minor portability + enhancement in <c><![CDATA[io_lib:fread]]></c>.</p> + <p>Own Id: OTP-4789</p> + </item> + <item> + <p>Conversion of extremely small floating point numbers in + the external format (distribution) could sometimes fail + leading to unexpected closing of distribution channels, + i.e. generating nodedowns for healthy nodes.</p> + <p>Own Id: OTP-5026 Aux Id: seq8631 EABln12478 </p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.3.6.1</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Conversion of extremely small floating point numbers in + the external format (distribution) could sometimes fail + leading to unexpected closing of distribution channels, + i.e. generating nodedowns for healthy nodes.</p> + <p>Own Id: OTP-5026 Aux Id: seq8631 EABln12478 </p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Remote spawn on a nonreachable node now gives warning + instead of error in the error_log.</p> + <p>Own Id: OTP-5030 Aux Id: seq8663] </p> + </item> + </list> + </section> + + <section> + <title>Known Bugs and Problems</title> + <list type="bulleted"> + <item> + <p>Emulator with elib_malloc enabled could hang when many + I/O threads were in use.</p> + <p>Own Id: OTP-5028 Aux Id: EABln13041, EABln12253 </p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.3.6</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>Distributed monitoring in combination with nodes + restarting did not behave correctly in rare + circumstances.</p> + <p>Own Id: OTP-4914</p> + </item> + <item> + <p>A module containing code similar to <c><![CDATA[receive after 4.1]]></c> + could not be loaded.</p> + <p>Own Id: OTP-4963 Aux Id: seq8344 </p> + </item> + <item> + <p>Problems fixed in <c><![CDATA[file:open/2]]></c>: <c><![CDATA["/dev/null"]]></c> + can now be opened. Opening a FIFO will now return an error + instead of hanging the emulator. The documentation has been + updated to point out that <c><![CDATA[file:open/2]]></c> returns + the error code <c><![CDATA[eisdir]]></c> when the pathname is not a + regular file (the pathname is not necessarily a directory).</p> + <p>Own Id: OTP-4992</p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The Solaris kernel poll feature was changed from a + compile time option to a runtime option. The kernel poll + feature can be enabled, by passing the command-line + argument <c><![CDATA[+K true]]></c> to an emulator (see <c><![CDATA[erl(1)]]></c>) + that have kernel poll support, i.e. an emulator for + Solaris 8. By default the kernel poll feature is disabled.</p> + <p>Own Id: OTP-4979 Aux Id: seq8478 </p> + </item> + <item> + <p>Before the Erlang emulator writes an <c><![CDATA[erl_crash.dump]]></c> + file (for any reason), it will close all open files and + sockets.</p> + <p>Own Id: OTP-4985 Aux Id: EABln10730, EABln11277, + EABln11279 </p> + </item> + <item> + <p>The <c><![CDATA[+c]]></c> switch has been added to disable time + correction in the runtime system, this should be used on + systems where one is certain no dramatic wall clock time + changes will occur and the time correction algorithm is too + costly (namely very fast Linux systems where loads of + <c><![CDATA[erlang:now()]]></c> are executed).</p> + <p>Own Id: OTP-4986</p> + </item> + <item> + <p>The <c><![CDATA[process_flag/2,3]]></c> BIFs now take a flag + <c><![CDATA[min_heap_size]]></c> that allows changing an existing + process's minimum heap size. The actual size will only be + changed when the next garbage collection occurs.</p> + <p>Own Id: OTP-4991 Aux Id: seq8515, OTP-4987 </p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.3.4</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>A possibility to make distribution messages be qued up + during running of erlang code, so that larger packages is + sent over the network is added.</p> + <p>Own Id: OTP-4916</p> + </item> + <item> + <p>When code loading failed it was impossible to know + exactly what caused it, only <c><![CDATA[{undef,[{M,F,A}|...]}]]></c> + would be reported. Now the primitive loader lets the + error logger print an error report if a file operation + fails. All file errors except <c><![CDATA[enoent]]></c> and + <c><![CDATA[enotdir]]></c> are reported this way.</p> + <p>Own Id: OTP-4925 Aux Id: OTP-4952 </p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.3.3</title> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <list type="bulleted"> + <item> + <p>The driver for dynamically linked in drivers has been + fixed to delete loaded drivers when its Erlang server + dies. The Erlang server has also been updated to improve + the start-on-demand behaviour.</p> + <p>Own Id: OTP-4876 Aux Id: OTP-4855 seq8272 </p> + </item> + <item> + <p><c><![CDATA[erlang:register/2]]></c> does no longer generate an ERROR + REPORT to the error logger when the name already is + registered. If the name is already registered the process + function will crash with <c><![CDATA[{'EXIT',Reason}]]></c> and that is + enough. It is up to the caller to decide if it is an + error that the name is already registered.</p> + <p>Own Id: OTP-4892</p> + </item> + <item> + <p>When using <c><![CDATA[erlang:system_monitor(Pid,{long_gc,Time})]]></c>, + and the GC time exceeded 1 second, it sometimes erroneously + showed up as about 4300 seconds. This bug has now been + corrected.</p> + <p>Own Id: OTP-4903 Aux Id: seq8379 </p> + </item> + </list> + </section> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>Starting Erlang with the <c><![CDATA[+Bi]]></c> flag (to ignore ^C), now + also disables the quit ('q') option in the JCL menu.</p> + <p>Own Id: OTP-4897</p> + </item> + </list> + </section> + </section> + + <section> + <title>ERTS 5.3.2</title> + + <section> + <title>Improvements and New Features</title> + <list type="bulleted"> + <item> + <p>The elib_malloc alternative dynamic memory allocator has + been improved to use an address order best fit strategy. + The instrumented emulator has been improved to be able to + catch memory allocations done by external libraries. The + emulator flag <c><![CDATA[+r]]></c> (stands for "relocate") makes + <c><![CDATA[ets]]></c> updates always result in an object relocation, + which significantly lessens the memory fragmentation in + certain systems. The <c><![CDATA[erlang:system_info/1]]></c> bif can + now be called with the argument <c><![CDATA[ets_realloc_moves]]></c> + and will return <c><![CDATA[true]]></c> if the <c><![CDATA[+r]]></c> emulator flag + is in effect, <c><![CDATA[false]]></c> otherwise.</p> + <p>Own Id: OTP-4838 Aux Id: seq8156 </p> + </item> + </list> + </section> + </section> +</chapter> + diff --git a/erts/doc/src/part.xml b/erts/doc/src/part.xml new file mode 100644 index 0000000000..e27b722721 --- /dev/null +++ b/erts/doc/src/part.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>1996</year><year>2009</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 User's Guide</title> + <prepared>Catrin Granbom</prepared> + <docno></docno> + <date>1997-05-15</date> + <rev>4.5.2</rev> + <file>part.xml</file> + </header> + <description> + <p>The Erlang Runtime System Application <em>ERTS</em>.</p> + </description> + <xi:include href="match_spec.xml"/> + <xi:include href="crash_dump.xml"/> + <xi:include href="alt_dist.xml"/> + <xi:include href="absform.xml"/> + <xi:include href="tty.xml"/> + <xi:include href="driver.xml"/> + <xi:include href="inet_cfg.xml"/> + <xi:include href="erl_ext_dist.xml"/> + <xi:include href="erl_dist_protocol.xml"/> +</part> + diff --git a/erts/doc/src/part_notes.xml b/erts/doc/src/part_notes.xml new file mode 100644 index 0000000000..4f183999e6 --- /dev/null +++ b/erts/doc/src/part_notes.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>2004</year><year>2009</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 new file mode 100644 index 0000000000..1b9bcca773 --- /dev/null +++ b/erts/doc/src/part_notes_history.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE part SYSTEM "part.dtd"> + +<part xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>2006</year><year>2009</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 new file mode 100644 index 0000000000..2042cf28bd --- /dev/null +++ b/erts/doc/src/ref_man.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE application SYSTEM "application.dtd"> + +<application xmlns:xi="http://www.w3.org/2001/XInclude"> + <header> + <copyright> + <year>1996</year><year>2009</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 Reference Manual</title> + <prepared>Lars Thorsén</prepared> + <docno></docno> + <date>1997-05-15</date> + <rev>4.5.2</rev> + <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"/> + <xi:include href="init.xml"/> + <xi:include href="zlib.xml"/> + <xi:include href="epmd.xml"/> + <xi:include href="erl.xml"/> + <xi:include href="erlc.xml"/> + <xi:include href="werl.xml"/> + <xi:include href="escript.xml"/> + <xi:include href="erlsrv.xml"/> + <xi:include href="start_erl.xml"/> + <xi:include href="erl_set_memory_block.xml"/> + <xi:include href="run_erl.xml"/> + <xi:include href="start.xml"/> + <xi:include href="erl_driver.xml"/> + <xi:include href="driver_entry.xml"/> + <xi:include href="erts_alloc.xml"/> + <xi:include href="erl_nif.xml"/> +</application> + diff --git a/erts/doc/src/run_erl.xml b/erts/doc/src/run_erl.xml new file mode 100644 index 0000000000..7bf7f559c5 --- /dev/null +++ b/erts/doc/src/run_erl.xml @@ -0,0 +1,155 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE comref SYSTEM "comref.dtd"> + +<comref> + <header> + <copyright> + <year>1999</year><year>2009</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>run_erl</title> + <prepared>Kent Boortz</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>99-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> + <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> + </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> + <desc> + <p>The <c><![CDATA[run_erl]]></c> program arguments are:</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>. 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> + </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> + <code type="none"><![CDATA[ + ===== ALIVE <date-time-string> + ]]></code> + <p>while the other timestamps look like this:</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> + </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> + <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> + </taglist> + </section> + + <section> + <title>SEE ALSO</title> + <p>start(1), start_erl(1)</p> + </section> +</comref> + diff --git a/erts/doc/src/start.xml b/erts/doc/src/start.xml new file mode 100644 index 0000000000..5dc33deb2a --- /dev/null +++ b/erts/doc/src/start.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE comref SYSTEM "comref.dtd"> + +<comref> + <header> + <copyright> + <year>1999</year><year>2009</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>start</title> + <prepared>Kent Boortz</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>99-12-15</date> + <rev></rev> + <file>start.xml</file> + </header> + <com>start</com> + <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> + </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> + <desc> + <p>In the example there is one argument</p> + <taglist> + <tag>data_file</tag> + <item>Optional, specifies what <c><![CDATA[start_erl.data]]></c> file + to use.</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 + where to find the release files.</p> + </desc> + </func> + </funcs> + + <section> + <title>SEE ALSO</title> + <p>run_erl(1), start_erl(1)</p> + </section> +</comref> + diff --git a/erts/doc/src/start_erl.xml b/erts/doc/src/start_erl.xml new file mode 100644 index 0000000000..21cc901f52 --- /dev/null +++ b/erts/doc/src/start_erl.xml @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE comref SYSTEM "comref.dtd"> + +<comref> + <header> + <copyright> + <year>1998</year><year>2009</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>start_erl</title> + <prepared>Patrik Nyblom</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>98-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> + <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 + 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 + <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> + </description> + <funcs> + <func> + <name>start_erl [<erl options>] ++ [<start_erl options>]</name> + <fsummary>Start the Erlang emulator with the correct release data</fsummary> + <desc> + <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. Tells start_erl where the root of the + release tree is placed in the file-system + (like <Erlang root>\\releases). The + <c><![CDATA[start_erl.data]]></c> file is expected to be placed in + this directory (if not otherwise specified).</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> + </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> + </section> + + <section> + <title>SEE ALSO</title> + <p>erlsrv(1), release_handler(3)</p> + </section> +</comref> + diff --git a/erts/doc/src/tty.xml b/erts/doc/src/tty.xml new file mode 100644 index 0000000000..23694e5965 --- /dev/null +++ b/erts/doc/src/tty.xml @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>1996</year><year>2009</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>tty - A command line interface</title> + <prepared>ETX/B/SFP C. Granbom</prepared> + <responsible></responsible> + <docno></docno> + <approved>EPK/TE (K. Boortz)</approved> + <checked></checked> + <date>1996-11-01</date> + <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> + <list type="bulleted"> + <item> + <p><em>normal mode</em>, in which lines of text 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> + </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>\011The 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>. + </p> + <table> + <row> + <cell align="left" valign="middle"><em>Key Sequence</em></cell> + <cell align="left" valign="middle"><em>Function</em></cell> + </row> + <row> + <cell align="left" valign="middle">C-a</cell> + <cell align="left" valign="middle">Beginning of line</cell> + </row> + <row> + <cell align="left" valign="middle">C-b</cell> + <cell align="left" valign="middle">Backward character</cell> + </row> + <row> + <cell align="left" valign="middle">M-b</cell> + <cell align="left" valign="middle">Backward word</cell> + </row> + <row> + <cell align="left" valign="middle">C-d</cell> + <cell align="left" valign="middle">Delete character</cell> + </row> + <row> + <cell align="left" valign="middle">M-d</cell> + <cell align="left" valign="middle">Delete word</cell> + </row> + <row> + <cell align="left" valign="middle">C-e</cell> + <cell align="left" valign="middle">End of line</cell> + </row> + <row> + <cell align="left" valign="middle">C-f</cell> + <cell align="left" valign="middle">Forward character</cell> + </row> + <row> + <cell align="left" valign="middle">M-f</cell> + <cell align="left" valign="middle">Forward word</cell> + </row> + <row> + <cell align="left" valign="middle">C-g</cell> + <cell align="left" valign="middle">Enter shell break mode</cell> + </row> + <row> + <cell align="left" valign="middle">C-k</cell> + <cell align="left" valign="middle">Kill line</cell> + </row> + <row> + <cell align="left" valign="middle">C-l</cell> + <cell align="left" valign="middle">Redraw line</cell> + </row> + <row> + <cell align="left" valign="middle">C-n</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> + </row> + <row> + <cell align="left" valign="middle">C-t</cell> + <cell align="left" valign="middle">Transpose characters</cell> + </row> + <row> + <cell align="left" valign="middle">C-y</cell> + <cell align="left" valign="middle">Insert previously killed text</cell> + </row> + <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> + <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> + </list> + </section> +</chapter> + diff --git a/erts/doc/src/werl.xml b/erts/doc/src/werl.xml new file mode 100644 index 0000000000..1494d91da8 --- /dev/null +++ b/erts/doc/src/werl.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE comref SYSTEM "comref.dtd"> + +<comref> + <header> + <copyright> + <year>1998</year><year>2009</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>werl</title> + <prepared>Björn Gustavsson</prepared> + <responsible>Bjarne Däcker</responsible> + <docno>1</docno> + <approved>Bjarne Däcker</approved> + <checked></checked> + <date>98-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><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 + except <c><![CDATA[-oldshell]]></c> work as they do for + the <seealso marker="erl">erl</seealso> command.</p> + + <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> + + <p>The <c>werl</c> window is in many ways modelled 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> + + <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> + + <p>Pasted text is always inserted at the current prompt position + and will be 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 + command.</p> + + <p>Closing the <c>werl</c> window will stop the Erlang emulator.</p> + + </description> +</comref> + diff --git a/erts/doc/src/zlib.xml b/erts/doc/src/zlib.xml new file mode 100644 index 0000000000..9f39ac657a --- /dev/null +++ b/erts/doc/src/zlib.xml @@ -0,0 +1,606 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE erlref SYSTEM "erlref.dtd"> + +<erlref> + <header> + <copyright> + <year>2005</year><year>2009</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>zlib</title> + <prepared></prepared> + <docno></docno> + <date></date> + <rev></rev> + <file>zlib.xml</file> + </header> + <module>zlib</module> + <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> + <pre> +Z = zlib:open(), +ok = zlib:deflateInit(Z,default), + +Compress = fun(end_of_data, _Cont) -> []; + (Data, Cont) -> + [zlib:deflate(Z, Data)|Cont(Read(),Cont)] + end, +Compressed = Compress(Read(),Compress), +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> + <taglist> + <tag><c>badarg</c></tag> + <item> + <p>Bad argument</p> + </item> + <tag><c>data_error</c></tag> + <item> + <p>The data contains errors</p> + </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> + <tag><c>{need_dictionary,Adler32}</c></tag> + <item> + <p>See <c>inflate/2</c></p> + </item> + </taglist> + </description> + + <section> + <title>DATA TYPES</title> + <code type="none"> +iodata = iolist() | binary() + +iolist = [char() | binary() | iolist()] + a binary is allowed as the tail of the list + +zstream = a zlib stream, see open/0</code> + </section> + <funcs> + <func> + <name>open() -> Z </name> + <fsummary>Open a stream and return a stream reference</fsummary> + <type> + <v>Z = zstream()</v> + </type> + <desc> + <p>Open a zlib stream.</p> + </desc> + </func> + <func> + <name>close(Z) -> ok</name> + <fsummary>Close a stream</fsummary> + <type> + <v>Z = zstream()</v> + </type> + <desc> + <p>Closes the stream referenced by <c>Z</c>.</p> + </desc> + </func> + <func> + <name>deflateInit(Z) -> ok</name> + <fsummary>Initialize a session for compression</fsummary> + <type> + <v>Z = zstream()</v> + </type> + <desc> + <p>Same as <c>zlib:deflateInit(Z, default)</c>.</p> + </desc> + </func> + <func> + <name>deflateInit(Z, Level) -> ok</name> + <fsummary>Initialize a session for compression</fsummary> + <type> + <v>Z = zstream()</v> + <v>Level = none | default | best_speed | best_compression | 0..9</v> + </type> + <desc> + <p>Initialize a zlib stream for compression.</p> + <p><c>Level</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> + </desc> + </func> + <func> + <name>deflateInit(Z, Level, Method, WindowBits, MemLevel, Strategy) -> ok</name> + <fsummary>Initialize a session for compression</fsummary> + <type> + <v>Z = zstream()</v> + <v>Level = none | default | best_speed | best_compression | 0..9</v> + <v>Method = deflated</v> + <v>WindowBits = 9..15|-9..-15</v> + <v>MemLevel = 1..9</v> + <v>Strategy = default|filtered|huffman_only</v> + </type> + <desc> + <p>Initiates a zlib stream for compression.</p> + <p>The <c>Level</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>Method</c> parameter decides which compression method to use, + currently the only supported method is <c>deflated</c>.</p> + <p>The <c>WindowBits</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>WindowBits</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>MemLevel</c> parameter specifies how much memory + should be allocated for the internal compression + state. <c>MemLevel</c>=1 uses minimum memory but is slow and + reduces compression ratio; <c>MemLevel</c>=9 uses maximum + memory for optimal speed. The default value is 8.</p> + <p>The <c>Strategy</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), or <c>huffman_only</c> to force Huffman + encoding only (no string match). 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>. The <c>Strategy</c> + parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set + appropriately.</p> + </desc> + </func> + <func> + <name>deflate(Z, Data) -> Compressed</name> + <fsummary>Compress data</fsummary> + <type> + <v>Z = zstream()</v> + <v>Data = iodata()</v> + <v>Compressed = iolist()</v> + </type> + <desc> + <p>Same as <c>deflate(Z, Data, none)</c>.</p> + </desc> + </func> + <func> + <name>deflate(Z, Data, Flush) -> </name> + <fsummary>Compress data</fsummary> + <type> + <v>Z = zstream()</v> + <v>Data = iodata()</v> + <v>Flush = none | sync | full | finish</v> + <v>Compressed = iolist()</v> + </type> + <desc> + <p><c>deflate/3</c> compresses as much data as possible, and + stops when the input buffer becomes empty. It may introduce + some output latency (reading input without producing any + output) except when forced to flush.</p> + <p>If the parameter <c>Flush</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>Flush</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>Flush</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>Flush</c> can be set to <c>finish</c> immediately after + <c>deflateInit</c> if all compression is to be done in one step.</p> + <pre> + +zlib:deflateInit(Z), +B1 = zlib:deflate(Z,Data), +B2 = zlib:deflate(Z,<< >>,finish), +zlib:deflateEnd(Z), +list_to_binary([B1,B2])</pre> + </desc> + </func> + <func> + <name>deflateSetDictionary(Z, Dictionary) -> Adler32</name> + <fsummary>Initialize the compression dictionary</fsummary> + <type> + <v>Z = zstream()</v> + <v>Dictionary = binary()</v> + <v>Adler32 = integer()</v> + </type> + <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> + </desc> + </func> + <func> + <name>deflateReset(Z) -> ok</name> + <fsummary>Reset the deflate session</fsummary> + <type> + <v>Z = zstream()</v> + </type> + <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> + </desc> + </func> + <func> + <name>deflateParams(Z, Level, Strategy) -> ok </name> + <fsummary>Dynamicly update deflate parameters</fsummary> + <type> + <v>Z = zstream()</v> + <v>Level = none | default | best_speed | best_compression | 0..9</v> + <v>Strategy = default|filtered|huffman_only</v> + </type> + <desc> + <p>Dynamically update the compression level and compression + strategy. The interpretation of <c>Level</c> and + <c>Strategy</c> is as in <c>deflateInit/6</c>. 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 deflateParams, 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> + </desc> + </func> + <func> + <name>deflateEnd(Z) -> ok</name> + <fsummary>End deflate session</fsummary> + <type> + <v>Z = zstream()</v> + </type> + <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> + </desc> + </func> + <func> + <name>inflateInit(Z) -> ok </name> + <fsummary>Initialize a session for decompression</fsummary> + <type> + <v>Z = zstream()</v> + </type> + <desc> + <p>Initialize a zlib stream for decompression.</p> + </desc> + </func> + <func> + <name>inflateInit(Z, WindowBits) -> ok </name> + <fsummary>Initialize a session for decompression</fsummary> + <type> + <v>Z = zstream()</v> + <v>WindowBits = 9..15|-9..-15</v> + </type> + <desc> + <p>Initialize decompression session on zlib stream.</p> + <p>The <c>WindowBits</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>WindowBits</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> + </desc> + </func> + <func> + <name>inflate(Z, Data) -> DeCompressed </name> + <fsummary>Decompress data</fsummary> + <type> + <v>Z = zstream()</v> + <v>Data = iodata()</v> + <v>DeCompressed = iolist()</v> + </type> + <desc> + <p><c>inflate/2</c> decompresses as much data as possible. + It may some 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> + </desc> + </func> + <func> + <name>inflateSetDictionary(Z, Dictionary) -> ok</name> + <fsummary>Initialize the decompression dictionary</fsummary> + <type> + <v>Z = zstream()</v> + <v>Dictionary = binary()</v> + </type> + <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 +\011 {'EXIT',{{need_dictionary,DictID},_}} -> + \011 zlib:inflateSetDictionary(Z, Dict), +\011 Uncompressed = zlib:inflate(Z, []); +\011 Uncompressed -> +\011 Uncompressed + end.</pre> + </desc> + </func> + <func> + <name>inflateReset(Z) -> ok</name> + <fsummary>>Reset the inflate session</fsummary> + <type> + <v>Z = zstream()</v> + </type> + <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> + </desc> + </func> + <func> + <name>inflateEnd(Z) -> ok</name> + <fsummary>End inflate session</fsummary> + <type> + <v>Z = zstream()</v> + </type> + <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> + </desc> + </func> + <func> + <name>setBufSize(Z, Size) -> ok</name> + <fsummary>Set buffer size</fsummary> + <type> + <v>Z = zstream()</v> + <v>Size = integer()</v> + </type> + <desc> + <p>Sets the intermediate buffer size.</p> + </desc> + </func> + <func> + <name>getBufSize(Z) -> Size</name> + <fsummary>Get buffer size</fsummary> + <type> + <v>Z = zstream()</v> + <v>Size = integer()</v> + </type> + <desc> + <p>Get the size of intermediate buffer.</p> + </desc> + </func> + <func> + <name>crc32(Z) -> CRC</name> + <fsummary>Get current CRC</fsummary> + <type> + <v>Z = zstream()</v> + <v>CRC = integer()</v> + </type> + <desc> + <p>Get the current calculated CRC checksum.</p> + </desc> + </func> + <func> + <name>crc32(Z, Binary) -> CRC</name> + <fsummary>Calculate CRC</fsummary> + <type> + <v>Z = zstream()</v> + <v>Binary = binary()</v> + <v>CRC = integer()</v> + </type> + <desc> + <p>Calculate the CRC checksum for <c>Binary</c>.</p> + </desc> + </func> + <func> + <name>crc32(Z, PrevCRC, Binary) -> CRC </name> + <fsummary>Calculate CRC</fsummary> + <type> + <v>Z = zstream()</v> + <v>PrevCRC = integer()</v> + <v>Binary = binary()</v> + <v>CRC = integer()</v> + </type> + <desc> + <p>Update a running CRC checksum for <c>Binary</c>. + If <c>Binary</c> is the empty binary, this function returns + the required initial value for the crc.</p> + <pre> +Crc = lists:foldl(fun(Bin,Crc0) -> +\011 zlib:crc32(Z, Crc0, Bin), +\011 end, zlib:crc32(Z,<< >>), Bins)</pre> + </desc> + </func> + <func> + <name>crc32_combine(Z, CRC1, CRC2, Size2) -> CRC </name> + <fsummary>Combine two CRC's</fsummary> + <type> + <v>Z = zstream()</v> + <v>CRC = integer()</v> + <v>CRC1 = integer()</v> + <v>CRC2 = integer()</v> + <v>Size2 = integer()</v> + </type> + <desc> + <p>Combine two CRC checksums into one. For two binaries, + <c>Bin1</c> and <c>Bin2</c> with sizes of <c>Size1</c> and + <c>Size2</c>, with CRC checksums <c>CRC1</c> and + <c>CRC2</c>. <c>crc32_combine/4</c> returns the <c>CRC</c> + checksum of <c><<Bin1/binary,Bin2/binary>></c>, requiring + only <c>CRC1</c>, <c>CRC2</c>, and <c>Size2</c>. + </p> + </desc> + </func> + <func> + <name>adler32(Z, Binary) -> Checksum</name> + <fsummary>Calculate the adler checksum</fsummary> + <type> + <v>Z = zstream()</v> + <v>Binary = binary()</v> + <v>Checksum = integer()</v> + </type> + <desc> + <p>Calculate the Adler-32 checksum for <c>Binary</c>.</p> + </desc> + </func> + <func> + <name>adler32(Z, PrevAdler, Binary) -> Checksum</name> + <fsummary>Calculate the adler checksum</fsummary> + <type> + <v>Z = zstream()</v> + <v>PrevAdler = integer()</v> + <v>Binary = binary()</v> + <v>Checksum = integer()</v> + </type> + <desc> + <p>Update a running Adler-32 checksum for <c>Binary</c>. + If <c>Binary</c> is the empty binary, this function returns + the required initial value for the checksum.</p> + <pre> +Crc = lists:foldl(fun(Bin,Crc0) -> +\011 zlib:adler32(Z, Crc0, Bin), +\011 end, zlib:adler32(Z,<< >>), Bins)</pre> + </desc> + </func> + <func> + <name>adler32_combine(Z, Adler1, Adler2, Size2) -> Adler </name> + <fsummary>Combine two Adler-32 checksums</fsummary> + <type> + <v>Z = zstream()</v> + <v>Adler = integer()</v> + <v>Adler1 = integer()</v> + <v>Adler2 = integer()</v> + <v>Size2 = integer()</v> + </type> + <desc> + <p>Combine two Adler-32 checksums into one. For two binaries, + <c>Bin1</c> and <c>Bin2</c> with sizes of <c>Size1</c> and + <c>Size2</c>, with Adler-32 checksums <c>Adler1</c> and + <c>Adler2</c>. <c>adler32_combine/4</c> returns the <c>Adler</c> + checksum of <c><<Bin1/binary,Bin2/binary>></c>, requiring + only <c>Adler1</c>, <c>Adler2</c>, and <c>Size2</c>. + </p> + </desc> + </func> + <func> + <name>compress(Binary) -> Compressed </name> + <fsummary>Compress a binary with standard zlib functionality</fsummary> + <type> + <v>Binary = Compressed = binary()</v> + </type> + <desc> + <p>Compress a binary (with zlib headers and checksum).</p> + </desc> + </func> + <func> + <name>uncompress(Binary) -> Decompressed</name> + <fsummary>Uncompress a binary with standard zlib functionality</fsummary> + <type> + <v>Binary = Decompressed = binary()</v> + </type> + <desc> + <p>Uncompress a binary (with zlib headers and checksum).</p> + </desc> + </func> + <func> + <name>zip(Binary) -> Compressed</name> + <fsummary>Compress a binary without the zlib headers</fsummary> + <type> + <v>Binary = Compressed = binary()</v> + </type> + <desc> + <p>Compress a binary (without zlib headers and checksum).</p> + </desc> + </func> + <func> + <name>unzip(Binary) -> Decompressed</name> + <fsummary>Uncompress a binary without the zlib headers</fsummary> + <type> + <v>Binary = Decompressed = binary()</v> + </type> + <desc> + <p>Uncompress a binary (without zlib headers and checksum).</p> + </desc> + </func> + <func> + <name>gzip(Data) -> Compressed</name> + <fsummary>Compress a binary with gz header</fsummary> + <type> + <v>Binary = Compressed = binary()</v> + </type> + <desc> + <p>Compress a binary (with gz headers and checksum).</p> + </desc> + </func> + <func> + <name>gunzip(Bin) -> Decompressed</name> + <fsummary>Uncompress a binary with gz header</fsummary> + <type> + <v>Binary = Decompressed = binary()</v> + </type> + <desc> + <p>Uncompress a binary (with gz headers and checksum).</p> + </desc> + </func> + </funcs> +</erlref> + |